Last active
August 21, 2023 05:17
-
-
Save the-last-byte/50011f11e2582c315b2b99a803a340a0 to your computer and use it in GitHub Desktop.
Script that prints a CSV of the Salesforce Schema to the console. This output can be imported into LucidChart (using the MySQL option) to create an ERD from your current schema.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Should only name, required, and lookup fields be exported. Set this to true | |
* if a (probably much smaller) result showing primarily objects and relationships | |
* is desired. | |
*/ | |
final Boolean keyFieldsOnly = false; | |
/** | |
* Optional. List of SObject API names to return. If this is empty, all SObjects | |
* will be returned. | |
*/ | |
final Set<String> objectApiNamesToInclude = new Set<String> { | |
//Optional - Add SObject API names here to filter which objects to export | |
}; | |
final String dbms = 'mysql'; | |
final String TABLE_SCHEMA = 'Schema'; | |
final Map<String, SObjectType> globalDescribe = Schema.getGlobalDescribe(); | |
final Set<String> keySetToUse = objectApiNamesToInclude?.isEmpty() == false | |
? objectApiNamesToInclude | |
: globalDescribe.keySet(); | |
final List<String> rows = new List<String> { | |
//Header row | |
'dbms,' + | |
'TABLE_SCHEMA,' + | |
'TABLE_NAME,' + | |
'COLUMN_NAME,' + | |
'ORDINAL_POSITION,' + | |
'DATA_TYPE,' + | |
'CHARACTER_MAXIMUM_LENGTH,' + | |
'CONSTRAINT_TYPE,' + | |
'REFERENCED_TABLE_SCHEMA,' + | |
'REFERENCED_TABLE_NAME,' + | |
'REFERENCED_COLUMN_NAME' | |
}; | |
for(String key : keySetToUse) { | |
final SObjectType objectType = globalDescribe.get(key); | |
Assert.isNotNull(key, 'Unable to find SObjectType: ' + key); | |
final DescribeSObjectResult describe = objectType.getDescribe(); | |
Integer ordinalPosition = 1; | |
for(SObjectField field : describe.fields.getMap().values()) { | |
final DescribeFieldResult fieldDescribe = field.getDescribe(); | |
if(keyFieldsOnly && fieldDescribe.getName() != 'Id' && fieldDescribe.getReferenceTo().isEmpty() && fieldDescribe.isNameField() == false && fieldDescribe.isUnique() == false) { | |
continue; | |
} | |
String constraintType = null; | |
String referencedSchema = null; | |
String referencedObject = null; | |
String referencedField = null; | |
if(fieldDescribe.getName() == 'Id') { | |
constraintType = 'PRIMARY KEY'; | |
} else if(!fieldDescribe.getReferenceTo().isEmpty()) { | |
constraintType = 'FOREIGN KEY'; | |
referencedObject = fieldDescribe.getReferenceTo()[0].getDescribe().getName(); | |
referencedField = 'Id';//fieldDescribe.getRelationshipName(); | |
referencedSchema = TABLE_SCHEMA; | |
} | |
final List<String> rowFields = new List<String> { | |
dbms, | |
TABLE_SCHEMA, | |
describe.getName(), | |
fieldDescribe.getName(), | |
String.valueOf(ordinalPosition++), | |
resolveDataType(fieldDescribe), | |
fieldDescribe.getLength() == 0 | |
? '' | |
: String.valueOf(fieldDescribe.getLength()), | |
constraintType, | |
referencedSchema, | |
referencedObject, | |
referencedField | |
}; | |
rows.add(String.join(rowFields, ', ')); | |
} | |
} | |
//Print the CSV to the console | |
System.debug('\n\n' + String.join(rows, '\n')); | |
public static String resolveDataType(DescribeFieldResult describe) { | |
switch on describe.getType() { | |
when ADDRESS { | |
return 'address'; | |
} | |
when ANYTYPE { | |
return 'any'; | |
} | |
when BASE64 { | |
return 'base64'; | |
} | |
when BOOLEAN { | |
return 'checkbox'; | |
} | |
when COMBOBOX { | |
return 'picklist'; | |
} | |
when COMPLEXVALUE { | |
return 'other'; | |
} | |
when CURRENCY { | |
return 'currency'; | |
} | |
when DATACATEGORYGROUPREFERENCE { | |
return 'other'; | |
} | |
when DATE { | |
return 'date'; | |
} | |
when DATETIME { | |
return 'datetime'; | |
} | |
when DOUBLE { | |
return 'double'; | |
} | |
when EMAIL { | |
return 'email'; | |
} | |
when ENCRYPTEDSTRING { | |
return 'encrypted'; | |
} | |
when ID { | |
return 'Id'; | |
} | |
when INTEGER { | |
return 'integer'; | |
} | |
when JSON { | |
return 'json'; | |
} | |
when LOCATION { | |
return 'coordinates'; | |
} | |
when LONG { | |
return 'long'; | |
} | |
when MULTIPICKLIST { | |
return 'multi-picklist'; | |
} | |
when PERCENT { | |
return 'percent'; | |
} | |
when PHONE { | |
return 'phone'; | |
} | |
when PICKLIST { | |
return 'picklist'; | |
} | |
when REFERENCE { | |
final List<SObjectType> referenceTo = describe.getReferenceTo(); | |
if(referenceTo.isEmpty()) { | |
return 'Lookup'; | |
} | |
return 'Lookup(' + referenceTo[0].getDescribe().getName() + ')'; | |
} | |
when SOBJECT { | |
return 'sobject'; | |
} | |
when STRING { | |
return 'string'; | |
} | |
when TEXTAREA { | |
return 'textarea'; | |
} | |
when TIME { | |
return 'time'; | |
} | |
when URL { | |
return 'url'; | |
} | |
when else { | |
return 'text'; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment