Refactor to use RDBMSActionStrategy

This commit is contained in:
2025-01-03 16:49:50 -06:00
parent dc6d37aad3
commit db1269824c
10 changed files with 108 additions and 267 deletions

View File

@ -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<String, Boolean> doesSelectClauseRequireDistinctMemoization = new Memoization<String, Boolean>()
.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<Serializable> 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<Serializable> 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);
}
}

View File

@ -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 //

View File

@ -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 //

View File

@ -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)

View File

@ -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<QRecord> page : CollectionUtils.getPages(insertInput.getRecords(), QueryManager.PAGE_SIZE))
for(List<QRecord> 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<Serializable> idList = QueryManager.executeInsertForGeneratedIds(connection, sql.toString(), params, table.getField(table.getPrimaryKeyField()).getType());
List<Serializable> 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);
}
}
}

View File

@ -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<Serializable> 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 //

View File

@ -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<QRecord> recordList, List<String> fieldsBeingUpdated) throws SQLException
{
for(List<QRecord> page : CollectionUtils.getPages(recordList, QueryManager.PAGE_SIZE))
for(List<QRecord> 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

View File

@ -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<String, Integer> queryStats = QueryManager.getStatistics();
assertEquals(6, queryStats.get(QueryManager.STAT_QUERIES_RAN), "Number of queries ran");
actionStrategy.setCollectStatistics(false);
Map<String, Integer> 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<String, Integer> queryStats = QueryManager.getStatistics();
assertEquals(1, queryStats.get(QueryManager.STAT_QUERIES_RAN), "Number of queries ran");
actionStrategy.setCollectStatistics(false);
Map<String, Integer> 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<String, Integer> queryStats = QueryManager.getStatistics();
assertEquals(8, queryStats.get(QueryManager.STAT_QUERIES_RAN), "Number of queries ran");
actionStrategy.setCollectStatistics(false);
Map<String, Integer> 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");

View File

@ -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<String, Integer> statistics = getBaseRDBMSActionStrategy().getStatistics();
assertEquals(2, statistics.get(BaseRDBMSActionStrategy.STAT_QUERIES_RAN));
assertAnInsertedPersonRecord("Jean-Luc", "Picard", 6);
assertAnInsertedPersonRecord("William", "Riker", 7);
assertAnInsertedPersonRecord("Beverly", "Crusher", 8);

View File

@ -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<String, Integer> statistics = QueryManager.getStatistics();
assertEquals(2, statistics.get(QueryManager.STAT_QUERIES_RAN));
Map<String, Integer> 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<String, Integer> statistics = QueryManager.getStatistics();
assertEquals(1, statistics.get(QueryManager.STAT_BATCHES_RAN));
assertEquals(2, statistics.get(QueryManager.STAT_QUERIES_RAN));
Map<String, Integer> 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<String, Integer> statistics = QueryManager.getStatistics();
assertEquals(1, statistics.get(QueryManager.STAT_BATCHES_RAN));
Map<String, Integer> 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<String, Integer> statistics = QueryManager.getStatistics();
assertEquals(2, statistics.get(QueryManager.STAT_QUERIES_RAN));
Map<String, Integer> 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");