From db1269824ce9fbe6da190f518a366aae1d7fcba5 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Fri, 3 Jan 2025 16:49:50 -0600 Subject: [PATCH] Refactor to use RDBMSActionStrategy --- .../rdbms/actions/AbstractRDBMSAction.java | 262 ++++-------------- .../rdbms/actions/RDBMSAggregateAction.java | 4 +- .../rdbms/actions/RDBMSCountAction.java | 4 +- .../rdbms/actions/RDBMSDeleteAction.java | 9 +- .../rdbms/actions/RDBMSInsertAction.java | 13 +- .../rdbms/actions/RDBMSQueryAction.java | 4 +- .../rdbms/actions/RDBMSUpdateAction.java | 8 +- .../rdbms/actions/RDBMSDeleteActionTest.java | 37 ++- .../rdbms/actions/RDBMSInsertActionTest.java | 11 +- .../rdbms/actions/RDBMSUpdateActionTest.java | 23 +- 10 files changed, 108 insertions(+), 267 deletions(-) diff --git a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/AbstractRDBMSAction.java b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/AbstractRDBMSAction.java index 68ecce54..e5511ed8 100644 --- a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/AbstractRDBMSAction.java +++ b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/AbstractRDBMSAction.java @@ -39,8 +39,6 @@ import java.util.ListIterator; import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; -import com.kingsrook.qqq.backend.core.actions.ActionHelper; import com.kingsrook.qqq.backend.core.actions.values.QValueFormatter; import com.kingsrook.qqq.backend.core.context.QContext; import com.kingsrook.qqq.backend.core.exceptions.QException; @@ -63,6 +61,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput; import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin; import com.kingsrook.qqq.backend.core.model.actions.tables.query.expressions.AbstractFilterExpression; import com.kingsrook.qqq.backend.core.model.data.QRecord; +import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.metadata.fields.DisplayFormat; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData; @@ -80,9 +79,10 @@ import com.kingsrook.qqq.backend.core.utils.StringUtils; import com.kingsrook.qqq.backend.core.utils.ValueUtils; import com.kingsrook.qqq.backend.core.utils.memoization.Memoization; import com.kingsrook.qqq.backend.module.rdbms.jdbc.ConnectionManager; -import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager; import com.kingsrook.qqq.backend.module.rdbms.model.metadata.RDBMSBackendMetaData; +import com.kingsrook.qqq.backend.module.rdbms.model.metadata.RDBMSFieldMetaData; import com.kingsrook.qqq.backend.module.rdbms.model.metadata.RDBMSTableBackendDetails; +import com.kingsrook.qqq.backend.module.rdbms.strategy.RDBMSActionStrategyInterface; import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair; @@ -101,6 +101,9 @@ public abstract class AbstractRDBMSAction private static Memoization doesSelectClauseRequireDistinctMemoization = new Memoization() .withTimeout(Duration.ofDays(365)); + private RDBMSBackendMetaData backendMetaData; + private RDBMSActionStrategyInterface actionStrategy; + /******************************************************************************* @@ -313,9 +316,9 @@ public abstract class AbstractRDBMSAction } joinClauseList.add(escapeIdentifier(baseTableOrAlias) - + "." + escapeIdentifier(getColumnName(leftTable.getField(joinOn.getLeftField()))) - + " = " + escapeIdentifier(joinTableOrAlias) - + "." + escapeIdentifier(getColumnName((rightTable.getField(joinOn.getRightField()))))); + + "." + escapeIdentifier(getColumnName(leftTable.getField(joinOn.getLeftField()))) + + " = " + escapeIdentifier(joinTableOrAlias) + + "." + escapeIdentifier(getColumnName((rightTable.getField(joinOn.getRightField()))))); } if(CollectionUtils.nullSafeHasContents(queryJoin.getSecurityCriteria())) @@ -479,172 +482,25 @@ public abstract class AbstractRDBMSAction JoinsContext.FieldAndTableNameOrAlias fieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(criterion.getFieldName()); - List values = criterion.getValues() == null ? new ArrayList<>() : new ArrayList<>(criterion.getValues()); - QFieldMetaData field = fieldAndTableNameOrAlias.field(); - String column = escapeIdentifier(fieldAndTableNameOrAlias.tableNameOrAlias()) + "." + escapeIdentifier(getColumnName(field)); - String clause = column; - Integer expectedNoOfParams = null; - switch(criterion.getOperator()) - { - case EQUALS -> - { - clause += " = ?"; - expectedNoOfParams = 1; - } - case NOT_EQUALS -> - { - clause += " != ?"; - expectedNoOfParams = 1; - } - case NOT_EQUALS_OR_IS_NULL -> - { - clause += " != ? OR " + column + " IS NULL "; - expectedNoOfParams = 1; - } - case IN -> - { - if(values.isEmpty()) - { - /////////////////////////////////////////////////////// - // if there are no values, then we want a false here // - /////////////////////////////////////////////////////// - clause = " 0 = 1 "; - } - else - { - clause += " IN (" + values.stream().map(x -> "?").collect(Collectors.joining(",")) + ")"; - } - } - case IS_NULL_OR_IN -> - { - clause += " IS NULL "; + List values = criterion.getValues() == null ? new ArrayList<>() : new ArrayList<>(criterion.getValues()); + QFieldMetaData field = fieldAndTableNameOrAlias.field(); + String column = escapeIdentifier(fieldAndTableNameOrAlias.tableNameOrAlias()) + "." + escapeIdentifier(getColumnName(field)); + StringBuilder clause = new StringBuilder(); - if(!values.isEmpty()) - { - clause += " OR " + column + " IN (" + values.stream().map(x -> "?").collect(Collectors.joining(",")) + ")"; - } - } - case NOT_IN -> + RDBMSActionStrategyInterface actionStrategy = getActionStrategy(); + + RDBMSFieldMetaData rdbmsFieldMetaData = RDBMSFieldMetaData.of(field); + if(rdbmsFieldMetaData != null) + { + RDBMSActionStrategyInterface fieldActionStrategy = rdbmsFieldMetaData.getActionStrategy(); + if(fieldActionStrategy != null) { - if(values.isEmpty()) - { - ////////////////////////////////////////////////////// - // if there are no values, then we want a true here // - ////////////////////////////////////////////////////// - clause = " 1 = 1 "; - } - else - { - clause += " NOT IN (" + values.stream().map(x -> "?").collect(Collectors.joining(",")) + ")"; - } + actionStrategy = fieldActionStrategy; } - case LIKE -> - { - clause += " LIKE ?"; - expectedNoOfParams = 1; - } - case NOT_LIKE -> - { - clause += " NOT LIKE ?"; - expectedNoOfParams = 1; - } - case STARTS_WITH -> - { - clause += " LIKE ?"; - ActionHelper.editFirstValue(values, (s -> s + "%")); - expectedNoOfParams = 1; - } - case ENDS_WITH -> - { - clause += " LIKE ?"; - ActionHelper.editFirstValue(values, (s -> "%" + s)); - expectedNoOfParams = 1; - } - case CONTAINS -> - { - clause += " LIKE ?"; - ActionHelper.editFirstValue(values, (s -> "%" + s + "%")); - expectedNoOfParams = 1; - } - case NOT_STARTS_WITH -> - { - clause += " NOT LIKE ?"; - ActionHelper.editFirstValue(values, (s -> s + "%")); - expectedNoOfParams = 1; - } - case NOT_ENDS_WITH -> - { - clause += " NOT LIKE ?"; - ActionHelper.editFirstValue(values, (s -> "%" + s)); - expectedNoOfParams = 1; - } - case NOT_CONTAINS -> - { - clause += " NOT LIKE ?"; - ActionHelper.editFirstValue(values, (s -> "%" + s + "%")); - expectedNoOfParams = 1; - } - case LESS_THAN -> - { - clause += " < ?"; - expectedNoOfParams = 1; - } - case LESS_THAN_OR_EQUALS -> - { - clause += " <= ?"; - expectedNoOfParams = 1; - } - case GREATER_THAN -> - { - clause += " > ?"; - expectedNoOfParams = 1; - } - case GREATER_THAN_OR_EQUALS -> - { - clause += " >= ?"; - expectedNoOfParams = 1; - } - case IS_BLANK -> - { - clause += " IS NULL"; - if(field.getType().isStringLike()) - { - clause += " OR " + column + " = ''"; - } - expectedNoOfParams = 0; - } - case IS_NOT_BLANK -> - { - clause += " IS NOT NULL"; - if(field.getType().isStringLike()) - { - clause += " AND " + column + " != ''"; - } - expectedNoOfParams = 0; - } - case BETWEEN -> - { - clause += " BETWEEN ? AND ?"; - expectedNoOfParams = 2; - } - case NOT_BETWEEN -> - { - clause += " NOT BETWEEN ? AND ?"; - expectedNoOfParams = 2; - } - case TRUE -> - { - clause = " 1 = 1 "; - expectedNoOfParams = 0; - } - case FALSE -> - { - clause = " 0 = 1 "; - expectedNoOfParams = 0; - } - default -> throw new IllegalStateException("Unexpected operator: " + criterion.getOperator()); } + Integer expectedNoOfParams = actionStrategy.appendCriterionToWhereClause(criterion, clause, column, values, field); + if(expectedNoOfParams != null) { if(expectedNoOfParams.equals(1) && StringUtils.hasContent(criterion.getOtherFieldName())) @@ -652,7 +508,7 @@ public abstract class AbstractRDBMSAction JoinsContext.FieldAndTableNameOrAlias otherFieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(criterion.getOtherFieldName()); String otherColumn = escapeIdentifier(otherFieldAndTableNameOrAlias.tableNameOrAlias()) + "." + escapeIdentifier(getColumnName(otherFieldAndTableNameOrAlias.field())); - clause = clause.replace("?", otherColumn); + clause = new StringBuilder(clause.toString().replace("?", otherColumn)); ///////////////////////////////////////////////////////////////////// // make sure we don't add any values in this case, just in case... // @@ -797,53 +653,7 @@ public abstract class AbstractRDBMSAction *******************************************************************************/ protected Serializable getFieldValueFromResultSet(QFieldType type, ResultSet resultSet, int i) throws SQLException { - switch(type) - { - case STRING: - case TEXT: - case HTML: - case PASSWORD: - { - return (QueryManager.getString(resultSet, i)); - } - case INTEGER: - { - return (QueryManager.getInteger(resultSet, i)); - } - case LONG: - { - return (QueryManager.getLong(resultSet, i)); - } - case DECIMAL: - { - return (QueryManager.getBigDecimal(resultSet, i)); - } - case DATE: - { - // todo - queryManager.getLocalDate? - return (QueryManager.getDate(resultSet, i)); - } - case TIME: - { - return (QueryManager.getLocalTime(resultSet, i)); - } - case DATE_TIME: - { - return (QueryManager.getInstant(resultSet, i)); - } - case BOOLEAN: - { - return (QueryManager.getBoolean(resultSet, i)); - } - case BLOB: - { - return (QueryManager.getByteArray(resultSet, i)); - } - default: - { - throw new IllegalStateException("Unexpected field type: " + type); - } - } + return (actionStrategy.getFieldValueFromResultSet(type, resultSet, i)); } @@ -1151,4 +961,26 @@ public abstract class AbstractRDBMSAction return (filter.clone()); } } + + + + /******************************************************************************* + ** Setter for backendMetaData + ** + *******************************************************************************/ + protected void setBackendMetaData(QBackendMetaData backendMetaData) + { + this.backendMetaData = (RDBMSBackendMetaData) backendMetaData; + this.actionStrategy = this.backendMetaData.getActionStrategy(); + } + + + + /*************************************************************************** + * + ***************************************************************************/ + protected RDBMSActionStrategyInterface getActionStrategy() + { + return (this.actionStrategy); + } } diff --git a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSAggregateAction.java b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSAggregateAction.java index 5c2f8710..e4d69585 100644 --- a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSAggregateAction.java +++ b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSAggregateAction.java @@ -48,7 +48,6 @@ import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.StringUtils; -import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager; /******************************************************************************* @@ -70,6 +69,7 @@ public class RDBMSAggregateAction extends AbstractRDBMSAction implements Aggrega try { QTableMetaData table = aggregateInput.getTable(); + setBackendMetaData(aggregateInput.getBackend()); QQueryFilter filter = clonedOrNewFilter(aggregateInput.getFilter()); JoinsContext joinsContext = new JoinsContext(QContext.getQInstance(), table.getName(), aggregateInput.getQueryJoins(), filter); @@ -126,7 +126,7 @@ public class RDBMSAggregateAction extends AbstractRDBMSAction implements Aggrega queryStat.setStartTimestamp(Instant.now()); } - QueryManager.executeStatement(statement, sql, ((ResultSet resultSet) -> + getActionStrategy().executeStatement(statement, sql, ((ResultSet resultSet) -> { ///////////////////////////////////////////////////////////////////////// // once we've started getting results, go ahead and cancel the timeout // diff --git a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSCountAction.java b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSCountAction.java index 121c2c9b..2aac8fb2 100644 --- a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSCountAction.java +++ b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSCountAction.java @@ -40,7 +40,6 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountOutput; import com.kingsrook.qqq.backend.core.model.actions.tables.query.JoinsContext; import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; -import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager; import org.apache.commons.lang.BooleanUtils; @@ -63,6 +62,7 @@ public class RDBMSCountAction extends AbstractRDBMSAction implements CountInterf try { QTableMetaData table = countInput.getTable(); + setBackendMetaData(countInput.getBackend()); QQueryFilter filter = clonedOrNewFilter(countInput.getFilter()); JoinsContext joinsContext = new JoinsContext(QContext.getQInstance(), countInput.getTableName(), countInput.getQueryJoins(), filter); @@ -106,7 +106,7 @@ public class RDBMSCountAction extends AbstractRDBMSAction implements CountInterf queryStat.setStartTimestamp(Instant.now()); } - QueryManager.executeStatement(statement, sql, ((ResultSet resultSet) -> + getActionStrategy().executeStatement(statement, sql, ((ResultSet resultSet) -> { ///////////////////////////////////////////////////////////////////////// // once we've started getting results, go ahead and cancel the timeout // diff --git a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteAction.java b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteAction.java index 9869435d..b59e9588 100644 --- a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteAction.java +++ b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteAction.java @@ -39,7 +39,6 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter; import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.statusmessages.SystemErrorStatusMessage; -import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager; /******************************************************************************* @@ -67,6 +66,8 @@ public class RDBMSDeleteAction extends AbstractRDBMSAction implements DeleteInte *******************************************************************************/ public DeleteOutput execute(DeleteInput deleteInput) throws QException { + setBackendMetaData(deleteInput.getBackend()); + DeleteOutput deleteOutput = new DeleteOutput(); deleteOutput.setRecordsWithErrors(new ArrayList<>()); @@ -196,7 +197,7 @@ public class RDBMSDeleteAction extends AbstractRDBMSAction implements DeleteInte try { - int rowCount = QueryManager.executeUpdateForRowCount(connection, sql, primaryKey); + int rowCount = getActionStrategy().executeUpdateForRowCount(connection, sql, primaryKey); deleteOutput.addToDeletedRecordCount(rowCount); ///////////////////////////////////////////////////////////////////////////////////////////////////// @@ -249,7 +250,7 @@ public class RDBMSDeleteAction extends AbstractRDBMSAction implements DeleteInte // todo sql customization - can edit sql and/or param list - Integer rowCount = QueryManager.executeUpdateForRowCount(connection, sql, primaryKeys); + Integer rowCount = getActionStrategy().executeUpdateForRowCount(connection, sql, primaryKeys); deleteOutput.addToDeletedRecordCount(rowCount); } catch(Exception e) @@ -287,7 +288,7 @@ public class RDBMSDeleteAction extends AbstractRDBMSAction implements DeleteInte try { - int rowCount = QueryManager.executeUpdateForRowCount(connection, sql, params); + int rowCount = getActionStrategy().executeUpdateForRowCount(connection, sql, params); deleteOutput.setDeletedRecordCount(rowCount); } catch(Exception e) diff --git a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSInsertAction.java b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSInsertAction.java index 42ac344c..d6b89246 100644 --- a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSInsertAction.java +++ b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSInsertAction.java @@ -37,7 +37,6 @@ import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.utils.CollectionUtils; -import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager; /******************************************************************************* @@ -56,6 +55,7 @@ public class RDBMSInsertAction extends AbstractRDBMSAction implements InsertInte { InsertOutput rs = new InsertOutput(); QTableMetaData table = insertInput.getTable(); + setBackendMetaData(insertInput.getBackend()); Connection connection = null; boolean needToCloseConnection = false; @@ -90,7 +90,7 @@ public class RDBMSInsertAction extends AbstractRDBMSAction implements InsertInte needToCloseConnection = true; } - for(List page : CollectionUtils.getPages(insertInput.getRecords(), QueryManager.PAGE_SIZE)) + for(List page : CollectionUtils.getPages(insertInput.getRecords(), getActionStrategy().getPageSize(insertInput))) { String tableName = escapeIdentifier(getTableName(table)); sql = new StringBuilder("INSERT INTO ").append(tableName).append("(").append(columns).append(") VALUES"); @@ -146,7 +146,7 @@ public class RDBMSInsertAction extends AbstractRDBMSAction implements InsertInte // todo sql customization - can edit sql and/or param list // todo - non-serial-id style tables // todo - other generated values, e.g., createDate... maybe need to re-select? - List idList = QueryManager.executeInsertForGeneratedIds(connection, sql.toString(), params, table.getField(table.getPrimaryKeyField()).getType()); + List idList = getActionStrategy().executeInsertForGeneratedIds(connection, sql.toString(), params, table.getField(table.getPrimaryKeyField())); int index = 0; for(QRecord record : page) { @@ -155,8 +155,11 @@ public class RDBMSInsertAction extends AbstractRDBMSAction implements InsertInte if(CollectionUtils.nullSafeIsEmpty(record.getErrors())) { - Serializable id = idList.get(index++); - outputRecord.setValue(table.getPrimaryKeyField(), id); + if(idList.size() > index) + { + Serializable id = idList.get(index++); + outputRecord.setValue(table.getPrimaryKeyField(), id); + } } } diff --git a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSQueryAction.java b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSQueryAction.java index 8ead329e..5c98b8c4 100644 --- a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSQueryAction.java +++ b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSQueryAction.java @@ -57,7 +57,6 @@ import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.Pair; -import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager; import com.kingsrook.qqq.backend.module.rdbms.model.metadata.RDBMSBackendMetaData; import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair; @@ -94,6 +93,7 @@ public class RDBMSQueryAction extends AbstractRDBMSAction implements QueryInterf { QTableMetaData table = queryInput.getTable(); String tableName = queryInput.getTableName(); + setBackendMetaData(queryInput.getBackend()); List params = new ArrayList<>(); Selection selection = makeSelection(queryInput); @@ -140,7 +140,7 @@ public class RDBMSQueryAction extends AbstractRDBMSAction implements QueryInterf ////////////////////////////////////////////// QueryOutput queryOutput = new QueryOutput(queryInput); - QueryManager.executeStatement(statement, sql, ((ResultSet resultSet) -> + getActionStrategy().executeStatement(statement, sql, ((ResultSet resultSet) -> { ///////////////////////////////////////////////////////////////////////// // once we've started getting results, go ahead and cancel the timeout // diff --git a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSUpdateAction.java b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSUpdateAction.java index 627b9c60..1894d911 100644 --- a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSUpdateAction.java +++ b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSUpdateAction.java @@ -41,7 +41,6 @@ import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.ListingHash; import com.kingsrook.qqq.backend.core.utils.StringUtils; -import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager; /******************************************************************************* @@ -66,6 +65,7 @@ public class RDBMSUpdateAction extends AbstractRDBMSAction implements UpdateInte public UpdateOutput execute(UpdateInput updateInput) throws QException { QTableMetaData table = updateInput.getTable(); + setBackendMetaData(updateInput.getBackend()); UpdateActionRecordSplitHelper updateActionRecordSplitHelper = new UpdateActionRecordSplitHelper(); updateActionRecordSplitHelper.init(updateInput); @@ -181,7 +181,7 @@ public class RDBMSUpdateAction extends AbstractRDBMSAction implements UpdateInte //////////////////////////////////////////////////////////////////////////////// try { - QueryManager.executeBatchUpdate(connection, sql, values); + getActionStrategy().executeBatchUpdate(connection, sql, values); incrementStatus(updateInput, recordList.size()); } finally @@ -214,7 +214,7 @@ public class RDBMSUpdateAction extends AbstractRDBMSAction implements UpdateInte *******************************************************************************/ private void updateRecordsWithMatchingValuesAndFields(UpdateInput updateInput, Connection connection, QTableMetaData table, List recordList, List fieldsBeingUpdated) throws SQLException { - for(List page : CollectionUtils.getPages(recordList, QueryManager.PAGE_SIZE)) + for(List page : CollectionUtils.getPages(recordList, getActionStrategy().getPageSize(updateInput))) { ////////////////////////////// // skip records with errors // @@ -256,7 +256,7 @@ public class RDBMSUpdateAction extends AbstractRDBMSAction implements UpdateInte ///////////////////////////////////// try { - QueryManager.executeUpdate(connection, sql, params); + getActionStrategy().executeUpdate(connection, sql, params); incrementStatus(updateInput, page.size()); } finally diff --git a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteActionTest.java b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteActionTest.java index 61e72681..27b17dcd 100644 --- a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteActionTest.java +++ b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteActionTest.java @@ -34,8 +34,8 @@ import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.module.rdbms.TestUtils; -import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager; import com.kingsrook.qqq.backend.module.rdbms.model.metadata.RDBMSTableBackendDetails; +import com.kingsrook.qqq.backend.module.rdbms.strategy.BaseRDBMSActionStrategy; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -128,6 +128,11 @@ public class RDBMSDeleteActionTest extends RDBMSActionTest deleteInput.setPrimaryKeys(List.of(1, -1)); DeleteOutput deleteResult = new RDBMSDeleteAction().execute(deleteInput); assertEquals(1, deleteResult.getDeletedRecordCount(), "Should delete one row"); + + ///////////////////////////////////////////////////////////////////////////////////// + // note - that if we went to the top-level DeleteAction, then it would have pre- // + // checked that the ids existed, and it WOULD give us an error for the -1 row here // + ///////////////////////////////////////////////////////////////////////////////////// assertEquals(0, deleteResult.getRecordsWithErrors().size(), "should have no errors (the one not found is just noop)"); } @@ -162,17 +167,15 @@ public class RDBMSDeleteActionTest extends RDBMSActionTest ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// deleteInput.setPrimaryKeys(List.of(1, 2, 3, 4, 5)); - QueryManager.setCollectStatistics(true); - QueryManager.resetStatistics(); - + BaseRDBMSActionStrategy actionStrategy = getBaseRDBMSActionStrategyAndActivateCollectingStatistics(); DeleteOutput deleteResult = new RDBMSDeleteAction().execute(deleteInput); //////////////////////////////////////////////////////////////////////////////////////// // assert that 6 queries ran - the initial delete (which failed), then 5 more deletes // //////////////////////////////////////////////////////////////////////////////////////// - QueryManager.setCollectStatistics(false); - Map queryStats = QueryManager.getStatistics(); - assertEquals(6, queryStats.get(QueryManager.STAT_QUERIES_RAN), "Number of queries ran"); + actionStrategy.setCollectStatistics(false); + Map queryStats = actionStrategy.getStatistics(); + assertEquals(6, queryStats.get(BaseRDBMSActionStrategy.STAT_QUERIES_RAN), "Number of queries ran"); assertEquals(2, deleteResult.getRecordsWithErrors().size(), "Should get back the 2 records with errors"); assertTrue(deleteResult.getRecordsWithErrors().stream().noneMatch(r -> r.getErrors().isEmpty()), "All we got back should have errors"); @@ -212,17 +215,15 @@ public class RDBMSDeleteActionTest extends RDBMSActionTest //////////////////////////////////////////////////////////////////////// deleteInput.setQueryFilter(new QQueryFilter(new QFilterCriteria("id", QCriteriaOperator.IN, List.of(2, 4, 5)))); - QueryManager.setCollectStatistics(true); - QueryManager.resetStatistics(); - + BaseRDBMSActionStrategy actionStrategy = getBaseRDBMSActionStrategyAndActivateCollectingStatistics(); DeleteOutput deleteResult = new RDBMSDeleteAction().execute(deleteInput); ////////////////////////////////// // assert that just 1 query ran // ////////////////////////////////// - QueryManager.setCollectStatistics(false); - Map queryStats = QueryManager.getStatistics(); - assertEquals(1, queryStats.get(QueryManager.STAT_QUERIES_RAN), "Number of queries ran"); + actionStrategy.setCollectStatistics(false); + Map queryStats = actionStrategy.getStatistics(); + assertEquals(1, queryStats.get(BaseRDBMSActionStrategy.STAT_QUERIES_RAN), "Number of queries ran"); assertEquals(3, deleteResult.getDeletedRecordCount(), "Should get back that 3 were deleted"); runTestSql("SELECT id FROM child_table", (rs -> @@ -259,9 +260,7 @@ public class RDBMSDeleteActionTest extends RDBMSActionTest ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// deleteInput.setQueryFilter(new QQueryFilter(new QFilterCriteria("id", QCriteriaOperator.IN, List.of(1, 2, 3, 4, 5)))); - QueryManager.setCollectStatistics(true); - QueryManager.resetStatistics(); - + BaseRDBMSActionStrategy actionStrategy = getBaseRDBMSActionStrategyAndActivateCollectingStatistics(); DeleteOutput deleteResult = new RDBMSDeleteAction().execute(deleteInput); /////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -270,9 +269,9 @@ public class RDBMSDeleteActionTest extends RDBMSActionTest // todo - maybe we shouldn't do that 2nd "try to delete 'em all by id"... why would it ever work, // // but the original filter query didn't (other than malformed SQL)? // /////////////////////////////////////////////////////////////////////////////////////////////////////// - QueryManager.setCollectStatistics(false); - Map queryStats = QueryManager.getStatistics(); - assertEquals(8, queryStats.get(QueryManager.STAT_QUERIES_RAN), "Number of queries ran"); + actionStrategy.setCollectStatistics(false); + Map queryStats = actionStrategy.getStatistics(); + assertEquals(8, queryStats.get(BaseRDBMSActionStrategy.STAT_QUERIES_RAN), "Number of queries ran"); assertEquals(2, deleteResult.getRecordsWithErrors().size(), "Should get back the 2 records with errors"); assertTrue(deleteResult.getRecordsWithErrors().stream().noneMatch(r -> r.getErrors().isEmpty()), "All we got back should have errors"); diff --git a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSInsertActionTest.java b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSInsertActionTest.java index c7689286..0daa1381 100644 --- a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSInsertActionTest.java +++ b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSInsertActionTest.java @@ -24,6 +24,7 @@ package com.kingsrook.qqq.backend.module.rdbms.actions; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Objects; import com.kingsrook.qqq.backend.core.actions.tables.InsertAction; import com.kingsrook.qqq.backend.core.context.QContext; @@ -32,7 +33,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput; import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertOutput; import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.module.rdbms.TestUtils; -import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager; +import com.kingsrook.qqq.backend.module.rdbms.strategy.BaseRDBMSActionStrategy; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -53,6 +54,8 @@ public class RDBMSInsertActionTest extends RDBMSActionTest public void beforeEach() throws Exception { super.primeTestDatabase(); + + getBaseRDBMSActionStrategyAndActivateCollectingStatistics(); } @@ -113,7 +116,7 @@ public class RDBMSInsertActionTest extends RDBMSActionTest @Test public void testInsertMany() throws Exception { - QueryManager.setPageSize(2); + getBaseRDBMSActionStrategy().setPageSize(2); InsertInput insertInput = initInsertRequest(); QRecord record1 = new QRecord().withTableName("person") @@ -137,6 +140,10 @@ public class RDBMSInsertActionTest extends RDBMSActionTest assertEquals(6, insertOutput.getRecords().get(0).getValue("id"), "Should have next id in the row"); assertEquals(7, insertOutput.getRecords().get(1).getValue("id"), "Should have next id in the row"); assertEquals(8, insertOutput.getRecords().get(2).getValue("id"), "Should have next id in the row"); + + Map statistics = getBaseRDBMSActionStrategy().getStatistics(); + assertEquals(2, statistics.get(BaseRDBMSActionStrategy.STAT_QUERIES_RAN)); + assertAnInsertedPersonRecord("Jean-Luc", "Picard", 6); assertAnInsertedPersonRecord("William", "Riker", 7); assertAnInsertedPersonRecord("Beverly", "Crusher", 8); diff --git a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSUpdateActionTest.java b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSUpdateActionTest.java index 64f4c950..6eb9357f 100644 --- a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSUpdateActionTest.java +++ b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSUpdateActionTest.java @@ -36,7 +36,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateOutput; import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.utils.StringUtils; import com.kingsrook.qqq.backend.module.rdbms.TestUtils; -import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager; +import com.kingsrook.qqq.backend.module.rdbms.strategy.BaseRDBMSActionStrategy; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -61,8 +61,7 @@ public class RDBMSUpdateActionTest extends RDBMSActionTest { super.primeTestDatabase(); - QueryManager.setCollectStatistics(true); - QueryManager.resetStatistics(); + getBaseRDBMSActionStrategyAndActivateCollectingStatistics(); } @@ -112,8 +111,8 @@ public class RDBMSUpdateActionTest extends RDBMSActionTest updateInput.setRecords(List.of(record)); UpdateOutput updateResult = new UpdateAction().execute(updateInput); - Map statistics = QueryManager.getStatistics(); - assertEquals(2, statistics.get(QueryManager.STAT_QUERIES_RAN)); + Map statistics = getBaseRDBMSActionStrategy().getStatistics(); + assertEquals(2, statistics.get(BaseRDBMSActionStrategy.STAT_QUERIES_RAN)); assertEquals(1, updateResult.getRecords().size(), "Should return 1 row"); assertEquals(2, updateResult.getRecords().get(0).getValue("id"), "Should have id=2 in the row"); @@ -169,9 +168,9 @@ public class RDBMSUpdateActionTest extends RDBMSActionTest UpdateOutput updateResult = new UpdateAction().execute(updateInput); // this test runs one batch and one regular query - Map statistics = QueryManager.getStatistics(); - assertEquals(1, statistics.get(QueryManager.STAT_BATCHES_RAN)); - assertEquals(2, statistics.get(QueryManager.STAT_QUERIES_RAN)); + Map statistics = getBaseRDBMSActionStrategy().getStatistics(); + assertEquals(1, statistics.get(BaseRDBMSActionStrategy.STAT_BATCHES_RAN)); + assertEquals(2, statistics.get(BaseRDBMSActionStrategy.STAT_QUERIES_RAN)); assertEquals(3, updateResult.getRecords().size(), "Should return 3 rows"); assertEquals(1, updateResult.getRecords().get(0).getValue("id"), "Should have expected ids in the row"); @@ -241,8 +240,8 @@ public class RDBMSUpdateActionTest extends RDBMSActionTest updateInput.setRecords(List.of(record1, record2)); UpdateOutput updateResult = new UpdateAction().execute(updateInput); - Map statistics = QueryManager.getStatistics(); - assertEquals(1, statistics.get(QueryManager.STAT_BATCHES_RAN)); + Map statistics = getBaseRDBMSActionStrategy().getStatistics(); + assertEquals(1, statistics.get(BaseRDBMSActionStrategy.STAT_BATCHES_RAN)); assertEquals(2, updateResult.getRecords().size(), "Should return 2 rows"); assertEquals(1, updateResult.getRecords().get(0).getValue("id"), "Should have expected ids in the row"); @@ -296,8 +295,8 @@ public class RDBMSUpdateActionTest extends RDBMSActionTest updateInput.setRecords(records); UpdateOutput updateResult = new UpdateAction().execute(updateInput); - Map statistics = QueryManager.getStatistics(); - assertEquals(2, statistics.get(QueryManager.STAT_QUERIES_RAN)); + Map statistics = getBaseRDBMSActionStrategy().getStatistics(); + assertEquals(2, statistics.get(BaseRDBMSActionStrategy.STAT_QUERIES_RAN)); assertEquals(5, updateResult.getRecords().size(), "Should return 5 rows"); // todo - add errors to QRecord? assertTrue(updateResult.getRecords().stream().noneMatch(qrs -> CollectionUtils.nullSafeHasContents(qrs.getErrors())), "There should be no errors");