3

Is it possible to get a list of key prefixes for all Metadata types in Salesforce org. Not the standard objects or custom objects, but Metadata types e.g. AccountSettings, ApexPage, CustomObject etc (listed here: https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_types_list.htm). Thank you!

1 Answer 1

2

You can't generally get the key prefixes of some objects (those that are not describe-able), but I've devised a workaround that actually (mosty) does just this. Here's the code:

Page

<apex:page controller="describe">
    <style>
        #output {
            display: table;
        }
        #output div {
            display: table-row;
        }
        #output div span {
            display: table-cell;
            padding: 2px;
        }
    </style>
    <script>
    var temp, parent;
    function processResults(data) {
        var index = 0, row, key, value;
        if(data) {
            while(index < data.validKeys.length) {
                row = document.createElement("div");
                key = document.createElement("span");
                value = document.createElement("span");
                key.appendChild(document.createTextNode(data.validKeys[index].key));
                value.appendChild(document.createTextNode(data.validKeys[index].value));
                row.appendChild(key);
                row.appendChild(value);
                temp.appendChild(row);
                index++;
            }
        } else {
            data = { nextValue: 0 };
        }
        if(data.nextValue!=null) {
            {!$RemoteAction.describe.getList}(data.nextValue, processResults);
        }
        if(data.nextValue==null) {
            data.nextValue = 262144;
            parent.appendChild(temp);
        }
        document.getElementById("progress").value = data.nextValue;
        row = document.getElementById("valuepercent");
        if(row.firstChild) row.removeChild(row.firstChild);
        key = parseInt(data.nextValue)/262144;
        key = Math.floor(key*10000)/100;
        row.appendChild(document.createTextNode(key+'%'));
    }
    window.addEventListener("load", function() { temp = document.getElementById("output"); parent = temp.parentNode; temp.parentNode.removeChild(temp); processResults(null); }, true);

    </script>
    <progress value="0" max="262143" id="progress"/>
    <span id="valuepercent"></span>
    <div id="output">

    </div>

</apex:page>

Controller

global class describe {
    global class KeyValuePair {
        global String key, value;
        global KeyValuePair(String k, String v) {
            key = k;
            value = v;
        }
    }
    global class Result {
        global Integer nextValue;
        global KeyValuePair[] validKeys;

        global Result() {
            validKeys = new KeyValuePair[0];
        }
    }

    @RemoteAction global static Result getList(Integer firstIndex) {
        Result result = new Result();
        String[] base62 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
        base62.remove(0);
        Integer a = (firstIndex & 258048) >> 12, b = (firstIndex & 4032) >> 6, c = (firstIndex & 63);
        while(Limits.getCpuTime()<1000) {
            try {
                String key = base62[a]+base62[b]+base62[c];
                Id value = Id.valueOf(key+'000000000000');
                result.validKeys.add(new KeyValuePair(key, String.valueOf(value.getSObjectType())));
            } catch(Exception e) { }
            c++;
            if(c>62) {
                b++;
                c = 0;
            }
            if(b>62) {
                a++;
                b = 0;
            }
            if(a>62) {
                result.nextValue = null;
                break;
            }
            result.nextValue = (a<<12)+(b<<6)+c;
        }
        return result;
    }
}

This code basically brute-forces every key prefix by way of Id.getSObjectType() to describe every single object in the system. It provides a very basic table that allows you to find any type of object that has a stable key prefix. It even includes some tables that I'm pretty sure we shouldn't be able to know about but have nevertheless been exposed to us.


Note: AccountSettings is a specific example of something that apparently doesn't have any key prefix at all. These are probably stored in some specific table that is a meta-table (contains a large number of settings that are all lumped into one). I would guess that the Organization table probably contains this information, but there's no documentation of how this data is organized. Other tables, like CustomObject, are actually aliased to a different type; for example, CustomObject is internally called CustomEntityDefinition.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .