I am using the force.com SOAP API (Partner WSDL) to query one of our Salesforce orgs and retrieve a list of all objects and all fields of each object.
This seemed pretty simple as I could quite easily retrieve a DescribeGlobalResult object which contained a collection of 'sObjects', I could then call DescribeSObject for each object to retrieve its object representation (an sObject object). Each sObject object contained a collection of Fields, perfect! :D... NO!
Oddly some of the fields contained in the field collections do not appear to exist in the targeted SalesForce org. I guess maybe these fields have been deleted or something(?). Problem I am having is distinguishing which fields actually exist and which ones do not. The Field object does not have a 'Queryable' or 'isDeleted' property. I tried selecting only fields where there byte size was 0 - but then realised what byte size was referring to :(
If it helps to know why I am trying to do this... I am attempting to build SOQL select all queries, since SOQL does not support * I have to find each field name for each object before building the query. I have done a fair bit of googling and trawling through SF's 'documentation' ... but I have found very little useful info and lot's of pompous PR telling me how great the platform is (descends into frustrated rant).
NOTE - Can we please focus on the question of... How to determine if a field exists/has been deleted/can be queried? If this is not possible or I should not be recieving these ghost fields then please say. I am aware of the flaws in the spec and the alternate approaches... I'll save those for a programmers.stackexchange.com/ question :)
CODE -
// Please hold off on flaming for the slow, clumsy, non-defensive code - this is just an example
public void ShowSEMYCode()
{
SFAPI.SFConnection sfConn = new Salesforce.API.SFConnection();
// The above would log me in and convert any exceptions into hateful messages
// Get global description object which contains a collection of sObjects
SForce.DescribeGlobalResult globalResult = sfConn.describeGlobal();
// For each sObject in the collection...
foreach (SForce.DescribeGlobalSObjectResult globalSObj in globalResult.sobjects)
{
// retrieve a DescribeSObjectResult object using SObject name
SForce.DescribeSObjectResult sObj = sfConn.describeSObject(globalSObj.name);
List<string> fieldNames = new List<string>();
// For each field ijn sObject.Fields collection....
foreach (SForce.Field field in sObj.fields)
{
// Add its name to my list
fieldNames.Add(field.name); // I checked - the name proerty seems to be the only property guaranteed to display the API name rather than some friendly name/label.
}
// Here i would simply call a method to convert my collection of column names into a SOQL string
// (eg: SELECT ColName1, colName2, colNam3__C FROM sObjectName) simples
}
}
DescribeSObjectResult class
public DescribeSObjectResult describeSObject(string sObjectType)
{
object[] results = this.Invoke("describeSObject", new object[] {sObjectType});
return ((DescribeSObjectResult)(results[0]));
}
Thanks in advance.
Jamie
Examples
Object:- Account
- Id
- IsDeleted
- MasterRecordId
- Name
- Type
- RecordTypeId
- ParentId
- BillingStreet
- BillingCity
- BillingState
- BillingPostalCode
- BillingCountry
- BillingLatitude
- BillingLongitude
- ShippingStreet
- ShippingCity
- ShippingState
- ShippingPostalCode
- ShippingCountry
- ShippingLatitude <- Phantom Field!
- ShippingLongitude
- Phone
- Fax
- Website
...
...
Object:- Idea
- Id
- IsDeleted
- Title
- CurrencyIsoCode
- RecordTypeId
- CreatedDate
- CreatedById
- LastModifiedDate
- LastModifiedById
- SystemModstamp
- LastViewedDate <- Ghost Field
- LastReferencedDate
- CommunityId
Object:- ApexPage
- Id
- NamespacePrefix
- Name
- ApiVersion
- MasterLabel
- Description
- ControllerType
- ControllerKey
- IsAvailableInTouch
- IsConfirmationTokenRequired <- Duff
- Markup
- CreatedDate
- CreatedById