From 8e65255248d4ab6a427ccff168c8ac36ba7c7bf7 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Fri, 3 Jan 2025 19:58:12 -0600 Subject: [PATCH] Delete and cleanup in QueryManger; test coverage improvements --- .../jdbc/BaseC3P0ConnectionCustomizer.java | 22 +- .../module/rdbms/jdbc/QueryManager.java | 593 +----------------- .../strategy/BaseRDBMSActionStrategy.java | 2 +- .../C3P0PooledConnectionProviderTest.java | 31 + .../module/rdbms/jdbc/QueryManagerTest.java | 23 - .../MySQLFullTextIndexFieldStrategyTest.java | 76 +++ 6 files changed, 127 insertions(+), 620 deletions(-) create mode 100644 qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/strategy/MySQLFullTextIndexFieldStrategyTest.java diff --git a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/BaseC3P0ConnectionCustomizer.java b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/BaseC3P0ConnectionCustomizer.java index 2e0549d3..87d26536 100644 --- a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/BaseC3P0ConnectionCustomizer.java +++ b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/BaseC3P0ConnectionCustomizer.java @@ -27,6 +27,7 @@ import java.sql.Statement; import java.util.HashMap; import java.util.List; import java.util.Map; +import com.kingsrook.qqq.backend.core.logging.QLogger; import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.mchange.v2.c3p0.ConnectionCustomizer; @@ -38,6 +39,8 @@ import com.mchange.v2.c3p0.ConnectionCustomizer; *******************************************************************************/ public class BaseC3P0ConnectionCustomizer implements ConnectionCustomizer { + private static final QLogger LOG = QLogger.getLogger(BaseC3P0ConnectionCustomizer.class); + private static Map> queriesForNewConnections = new HashMap<>(); @@ -48,15 +51,23 @@ public class BaseC3P0ConnectionCustomizer implements ConnectionCustomizer @Override public void onAcquire(Connection connection, String dataSourceIdentityToken) throws Exception { - List queries = queriesForNewConnections.get(dataSourceIdentityToken); - if(CollectionUtils.nullSafeHasContents(queries)) + try { - for(String sql : queries) + List queries = queriesForNewConnections.get(dataSourceIdentityToken); + if(CollectionUtils.nullSafeHasContents(queries)) { - Statement statement = connection.createStatement(); - statement.execute(sql); + for(String sql : queries) + { + Statement statement = connection.createStatement(); + statement.execute(sql); + } } } + catch(Exception e) + { + LOG.warn("Exception on a query-for-new-connection", e); + throw (e); + } } @@ -99,6 +110,7 @@ public class BaseC3P0ConnectionCustomizer implements ConnectionCustomizer } + /*************************************************************************** * ***************************************************************************/ diff --git a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManager.java b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManager.java index ceed311a..72069193 100644 --- a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManager.java +++ b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManager.java @@ -22,7 +22,6 @@ package com.kingsrook.qqq.backend.module.rdbms.jdbc; -import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Connection; @@ -31,7 +30,6 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; -import java.sql.Statement; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; @@ -43,7 +41,6 @@ import java.time.OffsetDateTime; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; -import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; @@ -53,16 +50,14 @@ import java.util.List; import java.util.Map; import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.logging.QLogger; -import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType; import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.PossibleValueEnum; -import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.StringUtils; -import org.apache.commons.lang.NotImplementedException; import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair; /******************************************************************************* - ** + ** Note that much of this class is/was ported (well, copied) to BaseRDBMSActionStrategy + ** around 2025-01, during the addition of SQLite backend module. *******************************************************************************/ public class QueryManager { @@ -169,49 +164,6 @@ public class QueryManager - /******************************************************************************* - ** - *******************************************************************************/ - public static void executeStatementForeachResult(Connection connection, String sql, ResultSetProcessor processor, Object... params) throws SQLException - { - throw (new NotImplementedException()); - /* - PreparedStatement statement = null; - ResultSet resultSet = null; - - try - { - if(params.length == 1 && params[0] instanceof Collection) - { - params = ((Collection) params[0]).toArray(); - } - - statement = prepareStatementAndBindParams(connection, sql, params); - statement.execute(); - resultSet = statement.getResultSet(); - - while(resultSet.next()) - { - processor.processResultSet(resultSet); - } - } - finally - { - if(statement != null) - { - statement.close(); - } - - if(resultSet != null) - { - resultSet.close(); - } - } - */ - } - - - /******************************************************************************* ** *******************************************************************************/ @@ -269,57 +221,6 @@ public class QueryManager - /******************************************************************************* - ** - *******************************************************************************/ - public static Map executeStatementForSingleRow(Connection connection, String sql, Object... params) throws SQLException - { - throw (new NotImplementedException()); - /* - PreparedStatement statement = prepareStatementAndBindParams(connection, sql, params); - statement.execute(); - ResultSet resultSet = statement.getResultSet(); - if(resultSet.next()) - { - Map rs = new LinkedHashMap<>(); - - ResultSetMetaData metaData = resultSet.getMetaData(); - for(int i = 1; i <= metaData.getColumnCount(); i++) - { - rs.put(metaData.getColumnName(i), getObject(resultSet, i)); - } - - return (rs); - } - else - { - return (null); - } - */ - } - - - - /******************************************************************************* - ** - *******************************************************************************/ - public static SimpleEntity executeStatementForSimpleEntity(Connection connection, String sql, Object... params) throws SQLException - { - PreparedStatement statement = prepareStatementAndBindParams(connection, sql, params); - statement.execute(); - ResultSet resultSet = statement.getResultSet(); - if(resultSet.next()) - { - return (buildSimpleEntity(resultSet)); - } - else - { - return (null); - } - } - - - /******************************************************************************* ** *******************************************************************************/ @@ -347,48 +248,6 @@ public class QueryManager - /******************************************************************************* - ** - *******************************************************************************/ - public static List executeStatementForSimpleEntityList(Connection connection, String sql, Object... params) throws SQLException - { - throw (new NotImplementedException()); - /* - List rs = new ArrayList<>(); - - PreparedStatement statement = prepareStatementAndBindParams(connection, sql, params); - statement.execute(); - ResultSet resultSet = statement.getResultSet(); - while(resultSet.next()) - { - SimpleEntity row = buildSimpleEntity(resultSet); - - rs.add(row); - } - - return (rs); - */ - } - - - - /******************************************************************************* - ** - *******************************************************************************/ - public static SimpleEntity buildSimpleEntity(ResultSet resultSet) throws SQLException - { - SimpleEntity row = new SimpleEntity(); - - ResultSetMetaData metaData = resultSet.getMetaData(); - for(int i = 1; i <= metaData.getColumnCount(); i++) - { - row.put(metaData.getColumnName(i), getObject(resultSet, i)); - } - return row; - } - - - /******************************************************************************* ** *******************************************************************************/ @@ -429,38 +288,6 @@ public class QueryManager - /******************************************************************************* - ** - *******************************************************************************/ - public static void executeUpdateVoid(Connection connection, String sql, Object... params) throws SQLException - { - throw (new NotImplementedException()); - /* - try(PreparedStatement statement = prepareStatementAndBindParams(connection, sql, params)) - { - statement.executeUpdate(); - } - */ - } - - - - /******************************************************************************* - ** - *******************************************************************************/ - public static void executeUpdateVoid(Connection connection, String sql, List params) throws SQLException - { - throw (new NotImplementedException()); - /* - try(PreparedStatement statement = prepareStatementAndBindParams(connection, sql, params)) - { - statement.executeUpdate(); - } - */ - } - - - /******************************************************************************* ** *******************************************************************************/ @@ -481,189 +308,6 @@ public class QueryManager - /******************************************************************************* - ** - *******************************************************************************/ - public static Integer executeUpdateForRowCount(Connection connection, String sql, List params) throws SQLException - { - throw (new NotImplementedException()); - /* - try(PreparedStatement statement = prepareStatementAndBindParams(connection, sql, params)) - { - statement.executeUpdate(); - return (statement.getUpdateCount()); - } - */ - } - - - - /******************************************************************************* - ** - *******************************************************************************/ - public static Integer executeInsertForGeneratedId(Connection connection, String sql, Object... params) throws SQLException - { - throw (new NotImplementedException()); - /* - try(PreparedStatement statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) - { - bindParams(params, statement); - statement.executeUpdate(); - ResultSet generatedKeys = statement.getGeneratedKeys(); - if(generatedKeys.next()) - { - return (getInteger(generatedKeys, 1)); - } - else - { - return (null); - } - } - */ - } - - - - /******************************************************************************* - ** todo - needs (specific) unit test - *******************************************************************************/ - public static List executeInsertForGeneratedIds(Connection connection, String sql, List params, QFieldType idType) throws SQLException - { - try(PreparedStatement statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) - { - bindParams(params.toArray(), statement); - incrementStatistic(STAT_QUERIES_RAN); - statement.executeUpdate(); - - ///////////////////////////////////////////////////////////// - // We default to idType of INTEGER if it was not passed in // - ///////////////////////////////////////////////////////////// - if(idType == null) - { - idType = QFieldType.INTEGER; - } - - ResultSet generatedKeys = statement.getGeneratedKeys(); - List rs = new ArrayList<>(); - while(generatedKeys.next()) - { - switch(idType) - { - case INTEGER: - { - rs.add(getInteger(generatedKeys, 1)); - break; - } - case LONG: - { - rs.add(getLong(generatedKeys, 1)); - break; - } - default: - { - LOG.warn("Unknown id data type, attempting to getInteger.", logPair("sql", sql)); - rs.add(getInteger(generatedKeys, 1)); - break; - } - } - } - return (rs); - } - catch(SQLException e) - { - LOG.warn("SQLException", e, logPair("sql", sql)); - throw (e); - } - } - - - - /******************************************************************************* - ** - *******************************************************************************/ - public static void executeInsertForList(Connection connection, List entityList) throws SQLException - { - throw (new NotImplementedException()); - /* - List> pages = CollectionUtils.getPages(entityList, PAGE_SIZE); - for(List page : pages) - { - ArrayList columns = new ArrayList<>(page.get(0).keySet()); - String sql = "INSERT INTO " + page.get(0).getTableName() + "(" + StringUtils.join(",", columns) + ") VALUES (" + columns.stream().map(s -> "?").collect(Collectors.joining(",")) + ")"; - - PreparedStatement insertPS = connection.prepareStatement(sql); - for(SimpleEntity entity : page) - { - Object[] params = new Object[columns.size()]; - for(int i = 0; i < columns.size(); i++) - { - params[i] = entity.get(columns.get(i)); - } - - bindParams(insertPS, params); - insertPS.addBatch(); - } - insertPS.executeBatch(); - } - - for(List page : pages) - { - page.clear(); - } - pages.clear(); - */ - } - - - - /******************************************************************************* - ** - *******************************************************************************/ - public static Integer executeInsert(Connection connection, SimpleEntity entity) throws SQLException - { - throw (new NotImplementedException()); - /* - ArrayList columns = new ArrayList<>(entity.keySet()); - String sql = "INSERT INTO " + entity.getTableName() + "(" + StringUtils.join(",", columns) + ") VALUES (" + columns.stream().map(s -> "?").collect(Collectors.joining(",")) + ")"; - - Object[] params = new Object[columns.size()]; - for(int i = 0; i < columns.size(); i++) - { - params[i] = entity.get(columns.get(i)); - } - - return (executeInsertForGeneratedId(connection, sql, params)); - */ - } - - - - /******************************************************************************* - ** - *******************************************************************************/ - public static void executeBatchUpdate(Connection connection, String updateSQL, List> values) throws SQLException - { - for(List> page : CollectionUtils.getPages(values, PAGE_SIZE)) - { - PreparedStatement updatePS = connection.prepareStatement(updateSQL); - for(List row : page) - { - Object[] params = new Object[row.size()]; - for(int i = 0; i < row.size(); i++) - { - params[i] = row.get(i); - } - - bindParams(updatePS, params); - updatePS.addBatch(); - } - incrementStatistic(STAT_BATCHES_RAN); - updatePS.executeBatch(); - } - } - - - /******************************************************************************* ** *******************************************************************************/ @@ -734,15 +378,8 @@ public class QueryManager /******************************************************************************* * index is 1-based!! *******************************************************************************/ - @SuppressWarnings("unchecked") public static int bindParamObject(PreparedStatement statement, int index, Object value) throws SQLException { - /* if(value instanceof TypeValuePair) - { - bindParamTypeValuePair(statement, index, (TypeValuePair) value); - return (1); - } - else*/ if(value instanceof Integer i) { bindParam(statement, index, i); @@ -856,68 +493,6 @@ public class QueryManager } } - /******************************************************************************* - ** - *******************************************************************************/ - /* - public static TypeValuePair param(Class c, T v) - { - return (new TypeValuePair<>(c, v)); - } - */ - - /******************************************************************************* - ** - *******************************************************************************/ - /* - private static void bindParamTypeValuePair(PreparedStatement statement, int index, TypeValuePair value) throws SQLException - { - Object v = value.getValue(); - Class t = value.getType(); - - if(t.equals(Integer.class)) - { - bindParam(statement, index, (Integer) v); - } - else if(t.equals(String.class)) - { - bindParam(statement, index, (String) v); - } - else if(t.equals(Boolean.class)) - { - bindParam(statement, index, (Boolean) v); - } - else if(t.equals(Timestamp.class)) - { - bindParam(statement, index, (Timestamp) v); - } - else if(t.equals(Date.class)) - { - bindParam(statement, index, (Date) v); - } - else if(t.equals(Calendar.class)) - { - bindParam(statement, index, (Calendar) v); - } - else if(t.equals(LocalDate.class)) - { - bindParam(statement, index, (LocalDate) v); - } - else if(t.equals(LocalDateTime.class)) - { - bindParam(statement, index, (LocalDateTime) v); - } - else if(t.equals(BigDecimal.class)) - { - bindParam(statement, index, (BigDecimal) v); - } - else - { - throw (new SQLException("Unexpected value type [" + t.getSimpleName() + "] in bindParamTypeValuePair.")); - } - } - */ - /******************************************************************************* @@ -1675,170 +1250,6 @@ public class QueryManager - /******************************************************************************* - ** Find an id from a "large" table that was created X days ago (assumes the date - ** field in the table isn't indexed, but id is - so do a binary search on id, - ** selecting the date of the min & max & mid id, then sub-dividing until the goal - ** days-ago is found). - ** - *******************************************************************************/ - public static Integer findIdForDaysAgo(Connection connection, String tableName, String dateFieldName, int goalDaysAgo) throws SQLException - { - throw (new NotImplementedException()); - /* - return (findIdForTimeUnitAgo(connection, tableName, dateFieldName, goalDaysAgo, ChronoUnit.DAYS)); - */ - } - - - - /******************************************************************************* - ** - *******************************************************************************/ - public static Integer findIdForTimestamp(Connection connection, String tableName, String dateFieldName, LocalDateTime timestamp) throws SQLException - { - throw (new NotImplementedException()); - /* - long between = ChronoUnit.SECONDS.between(timestamp, LocalDateTime.now()); - return (findIdForTimeUnitAgo(connection, tableName, dateFieldName, (int) between, ChronoUnit.SECONDS)); - */ - } - - - - /******************************************************************************* - ** - *******************************************************************************/ - public static Integer findIdForTimeUnitAgo(Connection connection, String tableName, String dateFieldName, int goalUnitsAgo, ChronoUnit unit) throws SQLException - { - throw (new NotImplementedException()); - /* - Integer maxId = executeStatementForSingleValue(connection, Integer.class, "SELECT MAX(id) FROM " + tableName); - Integer minId = executeStatementForSingleValue(connection, Integer.class, "SELECT MIN(id) FROM " + tableName); - - if(maxId == null || minId == null) - { - // Logger.logDebug("For [" + tableName + "], returning null id for X time-units ago, because either a min or max wasn't found."); - return (null); - } - - Integer idForGoal = findIdForTimeUnitAgo(connection, tableName, dateFieldName, goalUnitsAgo, minId, maxId, unit); - long foundUnitsAgo = getTimeUnitAgo(connection, tableName, dateFieldName, idForGoal, unit); - - // Logger.logDebug("For [" + tableName + "], using min id [" + idForGoal + "], which is from [" + foundUnitsAgo + "] Units[" + unit + "] ago."); - - return (idForGoal); - */ - } - - - - /******************************************************************************* - ** - *******************************************************************************/ - private static Integer findIdForTimeUnitAgo(Connection connection, String tableName, String dateFieldName, int goalUnitsAgo, Integer minId, Integer maxId, ChronoUnit unit) throws SQLException - { - throw (new NotImplementedException()); - /* - Integer midId = minId + ((maxId - minId) / 2); - if(midId.equals(minId) || midId.equals(maxId)) - { - return (midId); - } - - long foundUnitsAgo = getTimeUnitAgo(connection, tableName, dateFieldName, midId, unit); - if(foundUnitsAgo == goalUnitsAgo) - { - return (midId); - } - else if(foundUnitsAgo > goalUnitsAgo) - { - return (findIdForTimeUnitAgo(connection, tableName, dateFieldName, goalUnitsAgo, midId, maxId, unit)); - } - else - { - return (findIdForTimeUnitAgo(connection, tableName, dateFieldName, goalUnitsAgo, minId, midId, unit)); - } - */ - } - - - - /******************************************************************************* - ** - *******************************************************************************/ - private static long getTimeUnitAgo(Connection connection, String tableName, String dateFieldName, Integer id, ChronoUnit unit) throws SQLException - { - throw (new NotImplementedException()); - /* - LocalDateTime now = LocalDateTime.now(); - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // note, we used to just do where id=? here - but if that row is ever missing, we have a bad time - so - do id >= ? order by id, and just the first row. // - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - LocalDateTime date = executeStatementForSingleValue(connection, LocalDateTime.class, "SELECT " + dateFieldName + " FROM " + tableName + " WHERE id >= ? ORDER BY id LIMIT 1", id); - // System.out.println(date); - - // if(date == null) - { - // return now. - } - // else - { - long diff = unit.between(date, now); - // System.out.println("Unit[" + unit + "]'s ago: " + diff); - return diff; - } - */ - } - - /******************************************************************************* - ** - *******************************************************************************/ - // public static class TypeValuePair - // { - // private Class type; - // private T value; - - // /******************************************************************************* - // ** - // *******************************************************************************/ - // @SuppressWarnings("unchecked") - // public TypeValuePair(T value) - // { - // this.value = value; - // this.type = (Class) value.getClass(); - // } - - // /******************************************************************************* - // ** - // *******************************************************************************/ - // public TypeValuePair(Class type, T value) - // { - // this.type = type; - // this.value = value; - // } - - // /******************************************************************************* - // ** - // *******************************************************************************/ - // public T getValue() - // { - // return (value); - // } - - // /******************************************************************************* - // ** - // *******************************************************************************/ - // public Class getType() - // { - // return (type); - // } - - // } - - - /******************************************************************************* ** Setter for collectStatistics ** diff --git a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/strategy/BaseRDBMSActionStrategy.java b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/strategy/BaseRDBMSActionStrategy.java index 08309cd3..5bde3252 100644 --- a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/strategy/BaseRDBMSActionStrategy.java +++ b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/strategy/BaseRDBMSActionStrategy.java @@ -61,7 +61,7 @@ import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair; /******************************************************************************* - ** + ** Note that much of this class came from the old (old) QueryManager class. *******************************************************************************/ public class BaseRDBMSActionStrategy implements RDBMSActionStrategyInterface { diff --git a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/C3P0PooledConnectionProviderTest.java b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/C3P0PooledConnectionProviderTest.java index c588a06a..8657eb68 100644 --- a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/C3P0PooledConnectionProviderTest.java +++ b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/C3P0PooledConnectionProviderTest.java @@ -24,12 +24,17 @@ package com.kingsrook.qqq.backend.module.rdbms.jdbc; import java.util.ArrayList; import java.util.List; +import java.util.UUID; import java.util.concurrent.TimeUnit; import com.kingsrook.qqq.backend.core.actions.QBackendTransaction; import com.kingsrook.qqq.backend.core.actions.tables.QueryAction; import com.kingsrook.qqq.backend.core.context.QContext; import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput; +import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator; +import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria; +import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter; import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput; +import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; import com.kingsrook.qqq.backend.core.model.session.QSession; @@ -217,6 +222,32 @@ class C3P0PooledConnectionProviderTest extends BaseTest + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testQueriesForNewConnections() throws Exception + { + String uuid = UUID.randomUUID().toString(); + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // change the default database backend to use the class under test here - the C3PL connection pool provider // + // and add a new-connection query to it to insert a record with a UUID, that we can then query for. // + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// + QInstance qInstance = TestUtils.defineInstance(); + RDBMSBackendMetaData backend = (RDBMSBackendMetaData) qInstance.getBackend(TestUtils.DEFAULT_BACKEND_NAME); + backend.setQueriesForNewConnections(List.of("insert into person (first_name, last_name, email) values ('D', 'K', '" + uuid + "')")); + backend.setConnectionProvider(new QCodeReference(C3P0PooledConnectionProvider.class)); + QContext.init(qInstance, new QSession()); + + ////////////////////////////////////////////////////////////////////////////////////////////// + // we actually get multiple, because c3p0 default config opens multiple connections at once // + ////////////////////////////////////////////////////////////////////////////////////////////// + List records = QueryAction.execute(TestUtils.TABLE_NAME_PERSON, new QQueryFilter(new QFilterCriteria("email", QCriteriaOperator.EQUALS, uuid))); + assertThat(records.size()).isGreaterThanOrEqualTo(1); + } + + /******************************************************************************* ** *******************************************************************************/ diff --git a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManagerTest.java b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManagerTest.java index 396a8c77..222734fa 100644 --- a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManagerTest.java +++ b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManagerTest.java @@ -422,29 +422,6 @@ class QueryManagerTest extends BaseTest - /******************************************************************************* - ** - *******************************************************************************/ - @Test - void testQueryForSimpleEntity() throws SQLException - { - try(Connection connection = getConnection()) - { - QueryManager.executeUpdate(connection, """ - INSERT INTO test_table - ( int_col, datetime_col, char_col, date_col, time_col ) - VALUES - ( 47, '2022-08-10 19:22:08', 'Q', '2022-08-10', '19:22:08') - """); - SimpleEntity simpleEntity = QueryManager.executeStatementForSimpleEntity(connection, "SELECT * FROM test_table"); - assertNotNull(simpleEntity); - assertEquals(47, simpleEntity.get("INT_COL")); - assertEquals("Q", simpleEntity.get("CHAR_COL")); - } - } - - - /******************************************************************************* ** *******************************************************************************/ diff --git a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/strategy/MySQLFullTextIndexFieldStrategyTest.java b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/strategy/MySQLFullTextIndexFieldStrategyTest.java new file mode 100644 index 00000000..25c16621 --- /dev/null +++ b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/strategy/MySQLFullTextIndexFieldStrategyTest.java @@ -0,0 +1,76 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2025. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.backend.module.rdbms.strategy; + + +import java.util.List; +import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator; +import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria; +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.module.rdbms.BaseTest; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + + +/******************************************************************************* + ** Unit test for MySQLFullTextIndexFieldStrategy + *******************************************************************************/ +class MySQLFullTextIndexFieldStrategyTest extends BaseTest +{ + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void test() + { + /////////////////////////////////////////////////// + // test an operator that uses the fulltext index // + /////////////////////////////////////////////////// + QFieldMetaData field = new QFieldMetaData("myText", QFieldType.TEXT); + QFilterCriteria criterion = new QFilterCriteria(field.getName(), QCriteriaOperator.LIKE, "hello"); + StringBuilder clause = new StringBuilder(); + Integer expectedNoOfParams = new MySQLFullTextIndexFieldStrategy().appendCriterionToWhereClause(criterion, clause, "my_text", List.of("hello"), field); + assertEquals(1, expectedNoOfParams); + assertEquals(" MATCH (my_text) AGAINST (?) ", clause.toString()); + + //////////////////////////////////////////// + // test a negated fulltext index operator // + //////////////////////////////////////////// + criterion.setOperator(QCriteriaOperator.NOT_CONTAINS); + clause.delete(0, clause.length()); + expectedNoOfParams = new MySQLFullTextIndexFieldStrategy().appendCriterionToWhereClause(criterion, clause, "my_text", List.of("hello"), field); + assertEquals(1, expectedNoOfParams); + assertEquals(" NOT MATCH (my_text) AGAINST (?) ", clause.toString()); + + //////////////////////////////////////////// + // an operator that should defer to super // + //////////////////////////////////////////// + criterion.setOperator(QCriteriaOperator.IS_BLANK); + clause.delete(0, clause.length()); + expectedNoOfParams = new MySQLFullTextIndexFieldStrategy().appendCriterionToWhereClause(criterion, clause, "my_text", List.of("hello"), field); + assertEquals(0, expectedNoOfParams); + assertEquals("my_text IS NULL OR my_text = ''", clause.toString()); + } + +} \ No newline at end of file