--- 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<DefinitionRecipe> definitions;
/**
@@ -67,6 +68,11 @@
public:
vector<RelationConfiguration> 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() {
}
};
--- 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<AttributeMetadata> 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
}
}