# HG changeset patch # User František Kučera # Date 1564422552 -7200 # Node ID 362f2689cb87708b7cce28aa333a0e07ecf4cce9 # Parent eb7134dfdcc5d75ea27748b27ae24898c68a92fa configuration and CLI parser diff -r eb7134dfdcc5 -r 362f2689cb87 src/CLIParser.h --- a/src/CLIParser.h Sat Jul 27 23:51:14 2019 +0200 +++ b/src/CLIParser.h Mon Jul 29 19:49:12 2019 +0200 @@ -29,10 +29,6 @@ namespace tr { namespace sql { -/** - * This tr-sql CLI options are inspired by tr-guile options. - * These configurations are independent and might diverge, but when possible, they should share same option names and same logic for common parts. - */ class CLIParser { private: @@ -43,66 +39,36 @@ else throw relpipe::cli::RelpipeCLIException(L"Missing CLI argument" + (i > 0 ? (L" after " + arguments[i - 1]) : L""), relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); } - void addRelation(Configuration& c, RelationConfiguration& currentRelation) { - if (currentRelation.relation.size()) { - c.relationConfigurations.push_back(currentRelation); - currentRelation = RelationConfiguration(); + void addQuery(Configuration& c, Statement& currentQuery) { + if (currentQuery.sql.size()) { + c.statements.push_back(currentQuery); + currentQuery = Statement(); } } - relpipe::writer::TypeId parseTypeId(const string_t& value) { - using t = relpipe::writer::TypeId; - if (value == L"string") return t::STRING; - else if (value == L"integer") return t::INTEGER; - else if (value == L"boolean") return t::BOOLEAN; - else throw relpipe::cli::RelpipeCLIException(L"Unable to parse TypeId: " + value, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); - } - public: static const string_t OPTION_RELATION; - static const string_t OPTION_OUTPUT_ATTRIBUTE; - static const string_t OPTION_INPUT_ATTRIBUTES_APPEND; - static const string_t OPTION_INPUT_ATTRIBUTES_PREPEND; - static const string_t OPTION_DEBUG_VARIABLE_MAPPING; - static const string_t OPTION_BEFORE_RECORDS; - static const string_t OPTION_AFTER_RECORDS; - static const string_t OPTION_FOR_EACH; - static const string_t OPTION_DROP; - static const string_t OPTION_DEFINE; + static const string_t OPTION_PARAMETER; Configuration parse(const std::vector& arguments) { Configuration c; - RelationConfiguration currentRelation; + Statement currentQuery; for (int i = 0; i < arguments.size();) { string_t option = readNext(arguments, i); - if (option == OPTION_BEFORE_RECORDS) currentRelation.sqlBeforeRecords = readNext(arguments, i); - else if (option == OPTION_AFTER_RECORDS) currentRelation.sqlAfterRecords = readNext(arguments, i); - else if (option == OPTION_FOR_EACH) currentRelation.sqlForEach = readNext(arguments, i); - else if (option == OPTION_DROP) currentRelation.drop = true; - else if (option == OPTION_INPUT_ATTRIBUTES_APPEND) currentRelation.inputAttributesAppend = true; - else if (option == OPTION_INPUT_ATTRIBUTES_PREPEND) currentRelation.inputAttributesPrepend = true; - else if (option == OPTION_DEBUG_VARIABLE_MAPPING) currentRelation.debugVariableMapping = true; - else if (option == OPTION_RELATION) { - addRelation(c, currentRelation); // previous relation - currentRelation.relation = readNext(arguments, i); - } else if (option == OPTION_OUTPUT_ATTRIBUTE) { - relpipe::writer::AttributeMetadata attribute; - attribute.attributeName = readNext(arguments, i); - attribute.typeId = parseTypeId(readNext(arguments, i)); - currentRelation.writerMetadata.push_back(attribute); - } else if (option == OPTION_DEFINE) { - DefinitionRecipe definition; - definition.name = readNext(arguments, i); - definition.type = readNext(arguments, i); - definition.value = readNext(arguments, i); - if (currentRelation.relation.size()) currentRelation.definitions.push_back(definition); - else c.definitions.push_back(definition); + if (option == OPTION_RELATION) { + addQuery(c, currentQuery); // previous relation + currentQuery.relation = readNext(arguments, i); + currentQuery.sql = readNext(arguments, i); + } else if (option == OPTION_PARAMETER) { + Parameter parameter; + parameter.value = readNext(arguments, i); + currentQuery.parameters.push_back(parameter); } else throw relpipe::cli::RelpipeCLIException(L"Unsupported CLI option: " + option, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); } - addRelation(c, currentRelation); // last relation + addQuery(c, currentQuery); // last relation return c; } @@ -111,16 +77,13 @@ } }; + +// relpipe-tr-sql --relation "tabulka" "SELECT * FROM fstab WHERE id = ?" --parameter "123" +// TODO: --file db.sqlite --keep-file +// TODO: --type string/integer/boolean (default is string) + const string_t CLIParser::OPTION_RELATION = L"--relation"; -const string_t CLIParser::OPTION_OUTPUT_ATTRIBUTE = L"--output-attribute"; -const string_t CLIParser::OPTION_INPUT_ATTRIBUTES_APPEND = L"--input-attributes-append"; -const string_t CLIParser::OPTION_INPUT_ATTRIBUTES_PREPEND = L"--input-attributes-prepend"; -const string_t CLIParser::OPTION_DEBUG_VARIABLE_MAPPING = L"--debug-variable-mapping"; -const string_t CLIParser::OPTION_BEFORE_RECORDS = L"--before-records"; -const string_t CLIParser::OPTION_AFTER_RECORDS = L"--after-records"; -const string_t CLIParser::OPTION_FOR_EACH = L"--for-each"; -const string_t CLIParser::OPTION_DROP = L"--drop"; -const string_t CLIParser::OPTION_DEFINE = L"--define"; +const string_t CLIParser::OPTION_PARAMETER = L"--parameter"; } } diff -r eb7134dfdcc5 -r 362f2689cb87 src/Configuration.h --- a/src/Configuration.h Sat Jul 27 23:51:14 2019 +0200 +++ b/src/Configuration.h Mon Jul 29 19:49:12 2019 +0200 @@ -24,72 +24,36 @@ namespace tr { namespace sql { -class DefinitionRecipe { +class Parameter { public: - virtual ~DefinitionRecipe() { - } - - relpipe::writer::string_t name; - relpipe::writer::string_t type; relpipe::writer::string_t value; + // TODO: relpipe::writer::TypeId type; }; -class RelationConfiguration { +class Statement { public: - virtual ~RelationConfiguration() { + virtual ~Statement() { } - relpipe::writer::string_t relation; - relpipe::writer::string_t sqlBeforeRecords; - relpipe::writer::string_t sqlAfterRecords; - relpipe::writer::string_t sqlForEach; - /** - * If true, additional relation will be generated: mapping between relpipe attribute names and SQL variable names - */ - bool debugVariableMapping = false; - - /** - * If true, SQL code will be executed, but no output will be generated. - */ - bool drop = false; - - /** - * Variable definitions for this relation. - * Can be used as a safe way for passing parameters from the outside environment. - * See also Configuration::definitions (can be overridden by relation's definitions) + * output relation name; + * if empty, the SQL code (DML, DDL) will be executed, but no relational output will be generated */ - std::vector definitions; - - /** - * If empty, output relation will have same metadata as the input relation. - */ - std::vector writerMetadata; - + relpipe::writer::string_t relation; /** - * Whether original attributes should be appended to those specified using --output-attribute + * SQL code, usually some SELECT; + * might be also DML or DDL */ - bool inputAttributesAppend = false; - - /** - * Whether original attributes should be prepended to those specified using --output-attribute - */ - bool inputAttributesPrepend = false; + relpipe::writer::string_t sql; + std::vector parameters; }; class Configuration { public: - std::vector relationConfigurations; - - /** - * Global definitions for all relations. - * Can be used as a safe way for passing parameters from the outside environment. - * See also RelationConfiguration::definitions - */ - std::vector definitions; + std::vector statements; virtual ~Configuration() { } @@ -97,4 +61,4 @@ } } -} \ No newline at end of file +}