From 0c10acb1223c37fbbd8105653697633fefec0d63 Mon Sep 17 00:00:00 2001 From: Tim Chamberlain Date: Fri, 8 Jul 2022 15:32:32 -0500 Subject: [PATCH] QQQ-21: added 'count' action --- pom.xml | 4 +- .../qqq/frontend/picocli/QCommandBuilder.java | 1 + .../picocli/QPicoCliImplementation.java | 73 ++++++++++++++----- .../picocli/QPicoCliImplementationTest.java | 22 ++++++ 4 files changed, 79 insertions(+), 21 deletions(-) diff --git a/pom.xml b/pom.xml index 8a87a81c..77305cc8 100644 --- a/pom.xml +++ b/pom.xml @@ -53,12 +53,12 @@ com.kingsrook.qqq qqq-backend-core - 0.1.0-20220708.155822-4 + 0.1.0-20220708.195335-5 com.kingsrook.qqq qqq-backend-module-rdbms - 0.0.0 + 0.1.0-20220708.202041-3 test diff --git a/src/main/java/com/kingsrook/qqq/frontend/picocli/QCommandBuilder.java b/src/main/java/com/kingsrook/qqq/frontend/picocli/QCommandBuilder.java index 9d2525df..d2fbed7b 100644 --- a/src/main/java/com/kingsrook/qqq/frontend/picocli/QCommandBuilder.java +++ b/src/main/java/com/kingsrook/qqq/frontend/picocli/QCommandBuilder.java @@ -90,6 +90,7 @@ public class QCommandBuilder // add table-specific sub-commands for the table // /////////////////////////////////////////////////// tableCommand.addSubcommand("meta-data", defineMetaDataCommand(table)); + tableCommand.addSubcommand("count", defineQueryCommand(table)); tableCommand.addSubcommand("query", defineQueryCommand(table)); tableCommand.addSubcommand("insert", defineInsertCommand(table)); tableCommand.addSubcommand("update", defineUpdateCommand(table)); diff --git a/src/main/java/com/kingsrook/qqq/frontend/picocli/QPicoCliImplementation.java b/src/main/java/com/kingsrook/qqq/frontend/picocli/QPicoCliImplementation.java index 11c415ea..56cd335a 100644 --- a/src/main/java/com/kingsrook/qqq/frontend/picocli/QPicoCliImplementation.java +++ b/src/main/java/com/kingsrook/qqq/frontend/picocli/QPicoCliImplementation.java @@ -32,6 +32,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import com.kingsrook.qqq.backend.core.actions.CountAction; import com.kingsrook.qqq.backend.core.actions.DeleteAction; import com.kingsrook.qqq.backend.core.actions.InsertAction; import com.kingsrook.qqq.backend.core.actions.MetaDataAction; @@ -45,6 +46,8 @@ import com.kingsrook.qqq.backend.core.adapters.JsonToQRecordAdapter; import com.kingsrook.qqq.backend.core.adapters.QInstanceAdapter; import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.exceptions.QModuleDispatchException; +import com.kingsrook.qqq.backend.core.model.actions.count.CountRequest; +import com.kingsrook.qqq.backend.core.model.actions.count.CountResult; import com.kingsrook.qqq.backend.core.model.actions.delete.DeleteRequest; import com.kingsrook.qqq.backend.core.model.actions.delete.DeleteResult; import com.kingsrook.qqq.backend.core.model.actions.insert.InsertRequest; @@ -94,7 +97,7 @@ public class QPicoCliImplementation public static final int DEFAULT_LIMIT = 20; private static QInstance qInstance; - private static QSession session; + private static QSession session; @@ -109,14 +112,14 @@ public class QPicoCliImplementation // parse args to look up metaData and prime instance if(args.length > 0 && args[0].startsWith("--qInstanceJsonFile=")) { - String filePath = args[0].replaceFirst("--.*=", ""); + String filePath = args[0].replaceFirst("--.*=", ""); String qInstanceJson = FileUtils.readFileToString(new File(filePath)); qInstance = new QInstanceAdapter().jsonToQInstanceIncludingBackends(qInstanceJson); String[] subArgs = Arrays.copyOfRange(args, 1, args.length); QPicoCliImplementation qPicoCliImplementation = new QPicoCliImplementation(qInstance); - int exitCode = qPicoCliImplementation.runCli("qapi", subArgs); + int exitCode = qPicoCliImplementation.runCli("qapi", subArgs); System.exit(exitCode); } else @@ -229,7 +232,7 @@ public class QPicoCliImplementation private static void setupSession(String[] args) throws QModuleDispatchException { QAuthenticationModuleDispatcher qAuthenticationModuleDispatcher = new QAuthenticationModuleDispatcher(); - QAuthenticationModuleInterface authenticationModule = qAuthenticationModuleDispatcher.getQModule(qInstance.getAuthentication()); + QAuthenticationModuleInterface authenticationModule = qAuthenticationModuleDispatcher.getQModule(qInstance.getAuthentication()); // todo - does this need some per-provider logic actually? mmm... Map authenticationContext = new HashMap<>(); @@ -251,7 +254,7 @@ public class QPicoCliImplementation else { ParseResult subParseResult = parseResult.subcommand(); - String subCommandName = subParseResult.commandSpec().name(); + String subCommandName = subParseResult.commandSpec().name(); CommandLine subCommandLine = commandLine.getSubcommands().get(subCommandName); switch(subCommandName) { @@ -282,13 +285,17 @@ public class QPicoCliImplementation if(tableParseResult.hasSubcommand()) { ParseResult subParseResult = tableParseResult.subcommand(); - String subCommandName = subParseResult.commandSpec().name(); + String subCommandName = subParseResult.commandSpec().name(); switch(subCommandName) { case "meta-data": { return runTableMetaData(commandLine, tableName, subParseResult); } + case "count": + { + return runTableCount(commandLine, tableName, subParseResult); + } case "query": { return runTableQuery(commandLine, tableName, subParseResult); @@ -345,7 +352,7 @@ public class QPicoCliImplementation /////////////////////////////////////////// // move on to running the actual process // /////////////////////////////////////////// - String subCommandName = subParseResult.subcommand().commandSpec().name(); + String subCommandName = subParseResult.subcommand().commandSpec().name(); CommandLine subCommandLine = commandLine.getSubcommands().get(subCommandName); return runActualProcess(subCommandLine, subParseResult.subcommand()); } @@ -358,9 +365,9 @@ public class QPicoCliImplementation *******************************************************************************/ private int runActualProcess(CommandLine subCommandLine, ParseResult processParseResult) { - String processName = processParseResult.commandSpec().name(); - QProcessMetaData process = qInstance.getProcess(processName); - RunProcessRequest request = new RunProcessRequest(qInstance); + String processName = processParseResult.commandSpec().name(); + QProcessMetaData process = qInstance.getProcess(processName); + RunProcessRequest request = new RunProcessRequest(qInstance); request.setSession(session); request.setProcessName(processName); @@ -418,6 +425,24 @@ public class QPicoCliImplementation + /******************************************************************************* + ** + *******************************************************************************/ + private int runTableCount(CommandLine commandLine, String tableName, ParseResult subParseResult) throws QException + { + CountRequest countRequest = new CountRequest(qInstance); + countRequest.setSession(session); + countRequest.setTableName(tableName); + countRequest.setFilter(generateQueryFilter(subParseResult)); + + CountAction countAction = new CountAction(); + CountResult countResult = countAction.execute(countRequest); + commandLine.getOut().println(JsonUtils.toPrettyJson(countResult)); + return commandLine.getCommandSpec().exitCodeOnSuccess(); + } + + + /******************************************************************************* ** *******************************************************************************/ @@ -428,15 +453,28 @@ public class QPicoCliImplementation queryRequest.setTableName(tableName); queryRequest.setSkip(subParseResult.matchedOptionValue("skip", null)); queryRequest.setLimit(subParseResult.matchedOptionValue("limit", DEFAULT_LIMIT)); + queryRequest.setFilter(generateQueryFilter(subParseResult)); + QueryAction queryAction = new QueryAction(); + QueryResult queryResult = queryAction.execute(queryRequest); + commandLine.getOut().println(JsonUtils.toPrettyJson(queryResult)); + return commandLine.getCommandSpec().exitCodeOnSuccess(); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + private QQueryFilter generateQueryFilter(ParseResult subParseResult) + { QQueryFilter filter = new QQueryFilter(); - queryRequest.setFilter(filter); String[] criteria = subParseResult.matchedOptionValue("criteria", new String[] {}); for(String criterion : criteria) { // todo - parse! - String[] parts = criterion.split(" "); + String[] parts = criterion.split(" "); QFilterCriteria qQueryCriteria = new QFilterCriteria(); qQueryCriteria.setFieldName(parts[0]); qQueryCriteria.setOperator(QCriteriaOperator.valueOf(parts[1])); @@ -444,10 +482,7 @@ public class QPicoCliImplementation filter.addCriteria(qQueryCriteria); } - QueryAction queryAction = new QueryAction(); - QueryResult queryResult = queryAction.execute(queryRequest); - commandLine.getOut().println(JsonUtils.toPrettyJson(queryResult)); - return commandLine.getCommandSpec().exitCodeOnSuccess(); + return filter; } @@ -497,7 +532,7 @@ public class QPicoCliImplementation try { String path = subParseResult.matchedOptionValue("--csvFile", ""); - String csv = FileUtils.readFileToString(new File(path)); + String csv = FileUtils.readFileToString(new File(path)); recordList = new CsvToQRecordAdapter().buildRecordsFromCsv(csv, table, mapping); } catch(IOException e) @@ -554,7 +589,7 @@ public class QPicoCliImplementation boolean anyFields = false; - String primaryKeyOption = subParseResult.matchedOptionValue("--primaryKey", ""); + String primaryKeyOption = subParseResult.matchedOptionValue("--primaryKey", ""); Serializable[] primaryKeyValues = primaryKeyOption.split(","); for(Serializable primaryKeyValue : primaryKeyValues) { @@ -603,7 +638,7 @@ public class QPicoCliImplementation ///////////////////////////////////////////// // get the pKeys that the user specified // ///////////////////////////////////////////// - String primaryKeyOption = subParseResult.matchedOptionValue("--primaryKey", ""); + String primaryKeyOption = subParseResult.matchedOptionValue("--primaryKey", ""); Serializable[] primaryKeyValues = primaryKeyOption.split(","); deleteRequest.setPrimaryKeys(Arrays.asList(primaryKeyValues)); diff --git a/src/test/java/com/kingsrook/qqq/frontend/picocli/QPicoCliImplementationTest.java b/src/test/java/com/kingsrook/qqq/frontend/picocli/QPicoCliImplementationTest.java index 588a9b5b..90ea165f 100644 --- a/src/test/java/com/kingsrook/qqq/frontend/picocli/QPicoCliImplementationTest.java +++ b/src/test/java/com/kingsrook/qqq/frontend/picocli/QPicoCliImplementationTest.java @@ -214,6 +214,28 @@ class QPicoCliImplementationTest + /******************************************************************************* + ** test running a count on a table + ** + *******************************************************************************/ + @Test + public void test_tableCount() + { + TestOutput testOutput = testCli("person", "count", "--criteria", "id NOT_EQUALS 3"); + JSONObject countResult = JsonUtils.toJSONObject(testOutput.getOutput()); + assertNotNull(countResult); + int count = countResult.getInt("count"); + assertEquals(4, count); + + testOutput = testCli("person", "count", "--criteria", "id EQUALS 3"); + countResult = JsonUtils.toJSONObject(testOutput.getOutput()); + assertNotNull(countResult); + count = countResult.getInt("count"); + assertEquals(1, count); + } + + + /******************************************************************************* ** test running a query on a table **