CE-535 All more points of overridability, and make keys in existing record map a pair of {fieldName,value}

This commit is contained in:
2023-07-14 14:08:27 -05:00
parent 6ec838c48b
commit 3d2708da23

View File

@ -26,6 +26,7 @@ import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -232,7 +233,7 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
// query to see if we already have those records in the destination (to determine insert/update) // // query to see if we already have those records in the destination (to determine insert/update) //
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
Map<Serializable, QRecord> existingRecordsByForeignKey = getExistingRecordsByForeignKey(runBackendStepInput, destinationTableForeignKeyField, destinationTableName, sourceKeyList); Map<Pair<String, Serializable>, QRecord> existingRecordsByForeignKey = getExistingRecordsByForeignKey(runBackendStepInput, destinationTableForeignKeyField, destinationTableName, sourceKeyList);
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// foreach source record, build the record we'll insert/update // // foreach source record, build the record we'll insert/update //
@ -267,13 +268,10 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
continue; continue;
} }
///////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
// look for the existing record - note - we may need to type-convert here, the sourceKey value // // look for the existing record, to determine insert/update //
// from the source table to the destinationKey. e.g., if source table had an integer, and the // //////////////////////////////////////////////////////////////
// destination has a string. // QRecord existingRecord = getExistingRecord(existingRecordsByForeignKey, destinationForeignKeyField, sourceKeyValue);
/////////////////////////////////////////////////////////////////////////////////////////////////
Serializable sourceKeyValueInTargetFieldType = ValueUtils.getValueAsFieldType(destinationForeignKeyField.getType(), sourceKeyValue);
QRecord existingRecord = existingRecordsByForeignKey.get(sourceKeyValueInTargetFieldType);
QRecord recordToStore; QRecord recordToStore;
if(existingRecord != null && config.performUpdates) if(existingRecord != null && config.performUpdates)
@ -333,11 +331,34 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
/******************************************************************************* /*******************************************************************************
** **
*******************************************************************************/ *******************************************************************************/
protected Map<Serializable, QRecord> getExistingRecordsByForeignKey(RunBackendStepInput runBackendStepInput, String destinationTableForeignKeyField, String destinationTableName, List<Serializable> sourceKeyList) throws QException protected QRecord getExistingRecord(Map<Pair<String, Serializable>, QRecord> existingRecordsByForeignKey, QFieldMetaData destinationForeignKeyField, Serializable sourceKeyValue)
{ {
Map<Serializable, QRecord> existingRecordsByForeignKey = Collections.emptyMap(); //////////////////////////////////////////////////////////////////////////////////////////////////
if(!sourceKeyList.isEmpty()) // note - we may need to type-convert here, the sourceKey value from the source table to //
// the destinationKey. e.g., if source table had an integer, and the destination has a string. //
//////////////////////////////////////////////////////////////////////////////////////////////////
Serializable sourceKeyValueInTargetFieldType = ValueUtils.getValueAsFieldType(destinationForeignKeyField.getType(), sourceKeyValue);
return (existingRecordsByForeignKey.get(Pair.of(destinationForeignKeyField.getName(), sourceKeyValueInTargetFieldType)));
}
/*******************************************************************************
** Run the existingRecordQueryFilter - to look in the destinationTable for
** any records that may need an update (rather than an insert).
**
** Generally returns a Map, keyed by a Pair of the destinationTableForeignKeyField
** and the value in that field. But, for more complex use-cases, one can override
** the buildExistingRecordsMap method, to make different keys (e.g., if there are
** two possible destinationTableForeignKeyFields).
*******************************************************************************/
protected Map<Pair<String, Serializable>, QRecord> getExistingRecordsByForeignKey(RunBackendStepInput runBackendStepInput, String destinationTableForeignKeyField, String destinationTableName, List<Serializable> sourceKeyList) throws QException
{ {
if(sourceKeyList.isEmpty())
{
return (Collections.emptyMap());
}
QueryInput queryInput = new QueryInput(); QueryInput queryInput = new QueryInput();
queryInput.setTableName(destinationTableName); queryInput.setTableName(destinationTableName);
getTransaction().ifPresent(queryInput::setTransaction); getTransaction().ifPresent(queryInput::setTransaction);
@ -352,7 +373,24 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
} }
QueryOutput queryOutput = new QueryAction().execute(queryInput); QueryOutput queryOutput = new QueryAction().execute(queryInput);
existingRecordsByForeignKey = CollectionUtils.recordsToMap(queryOutput.getRecords(), destinationTableForeignKeyField); return (buildExistingRecordsMap(destinationTableForeignKeyField, queryOutput.getRecords()));
}
/*******************************************************************************
** Overridable point where you can, for example, keys in the existingRecordsMap
** with different fieldNames from the destinationTable.
**
** Note, if you're overriding this method, you'll likely also want & need to
** override getExistingRecord.
*******************************************************************************/
protected Map<Pair<String, Serializable>, QRecord> buildExistingRecordsMap(String destinationTableForeignKeyField, List<QRecord> existingRecordList)
{
Map<Pair<String, Serializable>, QRecord> existingRecordsByForeignKey = new HashMap<>();
for(QRecord record : existingRecordList)
{
existingRecordsByForeignKey.put(Pair.of(destinationTableForeignKeyField, record.getValue(destinationTableForeignKeyField)), record);
} }
return (existingRecordsByForeignKey); return (existingRecordsByForeignKey);
} }