Skip to content

Commit

Permalink
Merge pull request #963 from ashitsalesforce/master
Browse files Browse the repository at this point in the history
support for polymorphic relations with more than 5 obj types
  • Loading branch information
ashitsalesforce authored Feb 6, 2024
2 parents 9a37256 + 5ff1cb3 commit c08925b
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ public abstract class DAOLoadVisitor extends AbstractVisitor implements DAORowVi
protected final List<DynaBean> dynaArray;
private HashMap<Integer, Boolean> rowConversionFailureMap;

protected final BasicDynaClass dynaClass;
protected final DynaProperty[] dynaProps;
protected BasicDynaClass dynaClass = null;
protected DynaProperty[] dynaProps = null;

private final int batchSize;
protected List<Row> daoRowList = new ArrayList<Row>();
Expand All @@ -95,9 +95,6 @@ protected DAOLoadVisitor(Controller controller, ILoaderProgress monitor, DataWri

SforceDynaBean.registerConverters(getConfig());

dynaProps = SforceDynaBean.createDynaProps(controller.getFieldTypes(), controller);
dynaClass = SforceDynaBean.getDynaBeanInstance(dynaProps);

this.batchSize = getConfig().getLoadBatchSize();
rowConversionFailureMap = new HashMap<Integer, Boolean>();
String newRichTextRegex = getConfig().getString(Config.RICH_TEXT_FIELD_REGEX);
Expand Down Expand Up @@ -131,6 +128,16 @@ public boolean visit(Row row) throws OperationException, DataAccessObjectExcepti
}
// the result are sforce fields mapped to data
Row sforceDataRow = getMapper().mapData(row);

// Make sure to initialize dynaClass only after mapping a row.
// This is to make sure that all polymorphic field mappings specified
// in the mapping file are mapped to parent object.
if (dynaProps == null) {
dynaProps = SforceDynaBean.createDynaProps(controller.getFieldTypes(), controller);
}
if (dynaClass == null) {
dynaClass = SforceDynaBean.getDynaBeanInstance(dynaProps);
}
try {
convertBulkAPINulls(sforceDataRow);
DynaBean dynaBean = SforceDynaBean.convertToDynaBean(dynaClass, sforceDataRow);
Expand Down
23 changes: 21 additions & 2 deletions src/main/java/com/salesforce/dataloader/client/PartnerClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import com.salesforce.dataloader.config.Config;
import com.salesforce.dataloader.config.Messages;
import com.salesforce.dataloader.controller.Controller;
import com.salesforce.dataloader.dyna.RelationshipField;
import com.salesforce.dataloader.dyna.SforceDynaBean;
import com.salesforce.dataloader.exception.ParameterLoadException;
import com.salesforce.dataloader.exception.PasswordExpiredException;
Expand Down Expand Up @@ -938,7 +939,6 @@ private boolean checkConnectionException(ConnectionException ex, String operatio
private final Map<String, Field> fieldsByName = new HashMap<String, Field>();

public Field getField(String sObjectFieldName) {
sObjectFieldName = sObjectFieldName.toLowerCase();
Field field = this.fieldsByName.get(sObjectFieldName);
if (field == null) {
field = lookupField(sObjectFieldName);
Expand All @@ -948,10 +948,29 @@ public Field getField(String sObjectFieldName) {
}

private Field lookupField(String sObjectFieldName) {
boolean isRelationshipField = RelationshipField.isRelationshipFieldMapping(sObjectFieldName);
RelationshipField relField = new RelationshipField(sObjectFieldName, true);
// look for field on target object
for (Field f : getFieldTypes().getFields()) {
if (sObjectFieldName.equals(f.getName().toLowerCase()) || sObjectFieldName.equals(f.getLabel().toLowerCase()))
if (sObjectFieldName.equalsIgnoreCase(f.getName()) || sObjectFieldName.equalsIgnoreCase(f.getLabel())) {
return f;
}
if (isRelationshipField
&& relField != null
&& relField.getRelationshipName().equalsIgnoreCase(f.getRelationshipName())) {
Field parentField = this.referenceEntitiesDescribesMap.getParentField(sObjectFieldName);
if (parentField != null) {
return parentField;
}
// need to add the relationship mapping to referenceEntitiesDescribesMap
try {
processParentObjectForLookupReferences(relField.getParentObjectName(), f, 0, 1);
} catch (ConnectionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return this.referenceEntitiesDescribesMap.getParentField(sObjectFieldName);
}
}
return this.referenceEntitiesDescribesMap.getParentField(sObjectFieldName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,8 @@ static public DynaProperty[] createDynaProps(DescribeSObjectResult describer, Co
// NOTE: currently only fields with one reference are supported on the server
FieldType fieldType = field.getType();
String relationshipName = field.getRelationshipName();
if (fieldType == FieldType.reference && field.getReferenceTo().length <= DescribeRefObject.MAX_PARENT_OBJECTS_IN_REFERENCING_FIELD &&
if (fieldType == FieldType.reference &&
relationshipName != null && relationshipName.length() > 0) {

for (String parentName : field.getReferenceTo()) {
RelationshipField relField = new RelationshipField(parentName, relationshipName);
DescribeRefObject parent = controller.getReferenceDescribes().getParentSObject(relField.toFormattedRelationshipString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,17 @@
import com.salesforce.dataloader.action.progress.ILoaderProgress;
import com.salesforce.dataloader.config.Config;
import com.salesforce.dataloader.controller.Controller;
import com.salesforce.dataloader.dyna.RelationshipField;
import com.salesforce.dataloader.exception.DataAccessObjectException;
import com.salesforce.dataloader.exception.ProcessInitializationException;
import com.salesforce.dataloader.exception.UnsupportedOperationException;
import com.salesforce.dataloader.model.Row;
import com.sforce.soap.partner.QueryResult;
import com.sforce.soap.partner.SaveResult;
import com.sforce.soap.partner.sobject.SObject;
import com.sforce.ws.ConnectionException;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
Expand Down Expand Up @@ -98,6 +101,31 @@ public void testCreateAttachment() throws ProcessInitializationException, DataAc
runProcess(argMap, 1);
}
}

@Test
public void testPolymorphicRelationshipInAttachment() throws ProcessInitializationException, DataAccessObjectException, ConnectionException {
// convert the template using the parent account id
Map<String, String> configMap = getTestConfig(OperationInfo.insert, false);

// this feature does not work when bulk api is enabled but the zip content type is not
final boolean bulkApi = isBulkAPIEnabled(configMap);
final boolean zipContent = isSettingEnabled(configMap, Config.BULK_API_ZIP_CONTENT);
if (bulkApi && !zipContent) {
return;
}
AccountGenerator acctGen = new AccountGenerator();
SObject[] parentAccts = new SObject[1];
parentAccts[0] = acctGen.getObject(0, false);

// value of Oracle_id__c = 1-000000
SaveResult[] results = getBinding().create(parentAccts);
parentAccts[0].addField("id", results[0]);

configMap.put(Config.ENTITY, "Attachment");
RelationshipField parentRel = new RelationshipField("Account", "Parent");
parentRel.setParentFieldName(DEFAULT_ACCOUNT_EXT_ID_FIELD);
runProcess(configMap, 1);
}

/**
* Verify that multiple binary files can be correctly zipped up and inserted into a record.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Name,Body,Parent:Account-Oracle_Id__c
TestAttachment_01.txt,"target/test-classes/testfiles/data/attachment.txt","1-000000"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# extract account mapping values for query from salesforce (left) and update to csv file (right)
# salesforceFieldName=csvFieldName
Name=Name
Body=Body
Parent\:Account-Oracle_Id__c=Parent\:Account-Oracle_Id__c

0 comments on commit c08925b

Please sign in to comment.