# HG changeset patch # User František Kučera # Date 1549227190 -3600 # Node ID 9603e64324bc4a2bd9780d9e7b0237f75365c0bf # Parent f7f9a2553128cb6a2d5a289d004b978d163d536b add --define for passing parameters from the outside environment diff -r f7f9a2553128 -r 9603e64324bc src/Configuration.h --- a/src/Configuration.h Sun Feb 03 19:52:37 2019 +0100 +++ b/src/Configuration.h Sun Feb 03 21:53:10 2019 +0100 @@ -54,7 +54,8 @@ */ bool drop = false; /** - * + * Variable definitions for this relation. + * Can be used as a safe way for passing parameters from the outside environment. */ std::vector definitions; /** @@ -67,6 +68,11 @@ public: vector relationConfigurations; + // TODO: --define – global definitions (for all relations)? + // TODO: --relation … --drop – will execute --for-each, but no output will be generated for this relation + // TODO: --relation … --output-attribute 'name' 'type' – output relation will have different attributes than the input relation + // TODO: --create t2 3 a integer b boolean '…guile…' – allow creating new relations? Or allow calling startRelation() and attribute() from Guile? + virtual ~Configuration() { } }; diff -r f7f9a2553128 -r 9603e64324bc src/GuileHandler.h --- a/src/GuileHandler.h Sun Feb 03 19:52:37 2019 +0100 +++ b/src/GuileHandler.h Sun Feb 03 21:53:10 2019 +0100 @@ -114,6 +114,39 @@ scm_define(toGuileSymbol(name), toGuileValue(value, typeInfo, type)); } + /** + * TODO: use a common method + */ + bool parseBoolean(const string_t& value) { + if (value == L"true") return true; + else if (value == L"false") return false; + else throw relpipe::cli::RelpipeCLIException(L"Unable to parse boolean value: " + value + L" (expecting true or false)", relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); + } + + void defineGuileVariable(const DefinitionRecipe& definition) { + switch (relationalWriter->toTypeId(definition.type)) { + case writer::TypeId::BOOLEAN: + { + boolean_t value = parseBoolean(definition.value); + defineGuileVariable(definition.name, &value, typeid (value), TypeId::BOOLEAN); + break; + } + case writer::TypeId::INTEGER: + { + integer_t value = stoul(definition.value); + defineGuileVariable(definition.name, &value, typeid (value), TypeId::INTEGER); + break; + } + case writer::TypeId::STRING: + { + defineGuileVariable(definition.name, &definition.value, typeid (definition.value), TypeId::STRING); + break; + } + default: + throw cli::RelpipeCLIException(L"Unsupported type in defineGuileVariable(): " + definition.type, cli::CLI::EXIT_CODE_UNEXPECTED_ERROR); + } + } + void undefineGuileVariable(const string_t& name) { scm_define(toGuileSymbol(name), scm_make_undefined_variable()); // undefined != (define n) // TODO: or use: scm_variable_unset_x() ? @@ -152,7 +185,10 @@ } void startRelation(string_t name, vector attributes) override { - if (currentRelationConfiguration) evalGuileCode(currentRelationConfiguration->guileAfterRecords); + if (currentRelationConfiguration) { + evalGuileCode(currentRelationConfiguration->guileAfterRecords); + for (DefinitionRecipe definition : currentRelationConfiguration->definitions) undefineGuileVariable(definition.name); + } for (auto attribute : currentReaderMetadata) undefineGuileVariable(attribute.getAttributeName()); currentReaderMetadata = attributes; // TODO: move to a reusable method (or use same metadata on both reader and writer side?) @@ -166,6 +202,7 @@ for (int i = 0; i < configuration.relationConfigurations.size(); i++) { if (regex_match(name, wregex(configuration.relationConfigurations[i].relation))) { currentRelationConfiguration = &configuration.relationConfigurations[i]; + for (DefinitionRecipe definition : currentRelationConfiguration->definitions) defineGuileVariable(definition); break; // it there are multiple matches, only the first configuration is used } }