Skip to content

Instantly share code, notes, and snippets.

@martyychang
Last active October 5, 2020 14:22
Show Gist options
  • Save martyychang/2b1666caaba05bd4cf2fd0a9731942bf to your computer and use it in GitHub Desktop.
Save martyychang/2b1666caaba05bd4cf2fd0a9731942bf to your computer and use it in GitHub Desktop.
Generate Salesforce SELECT * query, Postgres CREATE TABLE statement and database-conf.xml content for a given object.
public class SobjectQueryGenerator {
private List<Schema.DescribeFieldResult> fieldDescList;
private Schema.DescribeSObjectResult sobjectDesc;
public SobjectQueryGenerator(Schema.DescribeSObjectResult sobjectDesc, Boolean includeCalculated) {
this.sobjectDesc = sobjectDesc;
this.fieldDescList = new List<Schema.DescribeFieldResult>();
for (Schema.SObjectField eachField : this.sobjectDesc.fields.getMap().values()) {
Schema.DescribeFieldResult eachDfr = eachField.getDescribe();
if (includeCalculated || eachDfr.isCalculated() == false) {
this.fieldDescList.add(eachDfr);
}
}
}
public String getDatabaseConfSqlString() {
List<String> fieldNames = new List<String>();
List<String> fieldParams = new List<String>();
Set<Schema.SoapType> castedTypes = new Set<Schema.SoapType> {
Schema.SoapType.BOOLEAN,
Schema.SoapType.DOUBLE,
Schema.SoapType.INTEGER
};
for (Schema.DescribeFieldResult eachDfr : this.fieldDescList) {
String fieldName = this.getLowerCaseFieldName(eachDfr);
fieldNames.add(fieldName);
fieldParams.add(
!castedTypes.contains(eachDfr.getSoapType()) ? '@' + fieldName + '@' :
'CAST(@' + fieldName + '@ AS ' + this.getPostgresFieldType(eachDfr) + ')'
);
}
return String.join(new List<String> {
'INSERT INTO __schema__.' + this.sobjectDesc.getName().toLowerCase() + ' (',
String.join(fieldNames, ',\n'),
') VALUES (',
String.join(fieldParams, ',\n'),
')'
}, '\n');
}
public String getDatabaseConfSqlParams() {
// Aggregate field names
List<String> fieldDefinitions = new List<String>();
for (Schema.DescribeFieldResult eachDfr : this.fieldDescList) {
fieldDefinitions.add(this.getDatabaseConfSqlParamEntry(eachDfr));
}
return String.join(new List<String> {
'<map>',
String.join(fieldDefinitions, '\n'),
'</map>'
}, '\n');
}
public String getDatabaseConfSqlParamEntry(Schema.DescribeFieldResult fieldDesc) {
// Default the field name
String fieldName = this.getLowerCaseFieldName(fieldDesc);
// Figure out the type
Schema.SoapType fieldSoapType = fieldDesc.getSoapType();
String fieldType =
fieldSoapType == Schema.SoapType.BOOLEAN ? 'java.lang.Boolean' :
fieldSoapType == Schema.SoapType.DATE ? 'java.sql.Date' :
fieldSoapType == Schema.SoapType.DATETIME ? 'java.sql.Timestamp' :
fieldSoapType == Schema.SoapType.DOUBLE ? 'java.lang.Double' :
fieldSoapType == Schema.SoapType.INTEGER ? 'java.lang.Integer' :
fieldSoapType == Schema.SoapType.TIME ? 'java.sql.Time' :
'java.lang.String'; // default
// Return the definition
return '<entry key="' + fieldName + '" value="' + fieldType + '"/>';
}
public String getLowerCaseFieldName(Schema.DescribeFieldResult fieldDesc) {
String fieldName = fieldDesc.getName().toLowerCase();
return fieldName.equals('id') ? 'sfid' : fieldName;
}
public String getSoqlQuery() {
List<String> fieldNames = new List<String>();
for (Schema.DescribeFieldResult eachDfr : this.fieldDescList) {
fieldNames.add(eachDfr.getName());
}
return String.join(new List<String> {
'SELECT',
String.join(fieldNames, ',\n'),
'FROM ' + this.sobjectDesc.getName()
}, '\n');
}
public String getPostgresCreateTableQuery() {
List<String> fieldDefs = new List<String> { 'id serial' };
for (Schema.DescribeFieldResult eachDfr : this.fieldDescList) {
fieldDefs.add(this.getPostgresFieldDefinition(eachDfr));
}
// Return query
return String.join(new List<String> {
'CREATE TABLE __schema__.' + this.sobjectDesc.getName().toLowerCase() + ' (',
String.join(fieldDefs, ',\n'),
');'
}, '\n');
}
public String getPostgresFieldDefinition(Schema.DescribeFieldResult fieldDesc) {
return this.getLowerCaseFieldName(fieldDesc) + ' ' + this.getPostgresFieldType(fieldDesc);
}
public String getPostgresFieldType(Schema.DescribeFieldResult dfr) {
return this.getPostgresFieldType(dfr.getSoapType(), dfr.getLength());
}
public String getPostgresFieldType(Schema.SoapType fieldType, Integer length) {
return
fieldType == Schema.SoapType.BOOLEAN ? 'boolean' :
fieldType == Schema.SoapType.DATE ? 'date' :
fieldType == Schema.SoapType.DATETIME ? 'timestamp without time zone' :
fieldType == Schema.SoapType.DOUBLE ? 'double precision' :
fieldType == Schema.SoapType.ID ? 'character varying(18)' :
fieldType == Schema.SoapType.INTEGER ? 'integer' :
fieldType == Schema.SoapType.STRING ? 'character varying(' + length + ')' :
fieldType == Schema.SoapType.TIME ? 'time without time zone' :
'text'; // default, variable any length
}
public Messaging.SingleEmailMessage getSingleEmailMessage() {
Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
email.setSubject(this.sobjectDesc.getName() + ' ...-conf.xml');
email.setSaveAsActivity(false);
email.setPlainTextBody(String.join(new List<String> {
'Salesforce SOQL SELECT', '=====', this.getSoqlQuery(), '',
'Postgres CREATE TABLE', '=====', this.getPostgresCreateTableQuery(), '',
'database-conf.xml sqlString', '=====', this.getDatabaseConfSqlString(), '',
'database-conf.xml sqlParams', '=====', this.getDatabaseConfSqlParams()
}, '\n'));
return email;
}
}
SobjectQueryGenerator generator = new SobjectQueryGenerator(Schema.SObjectType.Task, false);
Messaging.SingleEmailMessage email = generator.getSingleEmailMessage();
email.setTargetObjectId(UserInfo.getUserId());
Messaging.sendEmail(new List<Messaging.Email> { email });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment