# HG changeset patch # User František Kučera # Date 1549497354 -3600 # Node ID 2dcc22b7a42487c83f72dfdf1815593150cb3ba2 # Parent 051e580227833cf7b1f319a574663fdd1994076c add --has-more-records and allow adding more records dynamically in Guile diff -r 051e58022783 -r 2dcc22b7a424 src/CLIParser.h --- a/src/CLIParser.h Tue Feb 05 20:40:32 2019 +0100 +++ b/src/CLIParser.h Thu Feb 07 00:55:54 2019 +0100 @@ -66,6 +66,7 @@ static const string_t OPTION_WHERE; static const string_t OPTION_DROP; static const string_t OPTION_DEFINE; + static const string_t OPTION_HAS_MORE_RECORDS; Configuration parse(const std::vector& arguments) { Configuration c; @@ -79,6 +80,7 @@ else if (option == OPTION_AFTER_RECORDS) currentRelation.guileAfterRecords = readNext(arguments, i); else if (option == OPTION_FOR_EACH) currentRelation.guileForEach = readNext(arguments, i); else if (option == OPTION_WHERE) currentRelation.guileWhere = readNext(arguments, i); + else if (option == OPTION_HAS_MORE_RECORDS) currentRelation.guileHasMoreRecords = 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; @@ -121,6 +123,7 @@ const string_t CLIParser::OPTION_WHERE = L"--where"; const string_t CLIParser::OPTION_DROP = L"--drop"; const string_t CLIParser::OPTION_DEFINE = L"--define"; +const string_t CLIParser::OPTION_HAS_MORE_RECORDS = L"--has-more-records"; } } diff -r 051e58022783 -r 2dcc22b7a424 src/Configuration.h --- a/src/Configuration.h Tue Feb 05 20:40:32 2019 +0100 +++ b/src/Configuration.h Thu Feb 07 00:55:54 2019 +0100 @@ -49,6 +49,7 @@ relpipe::writer::string_t guileAfterRecords; relpipe::writer::string_t guileForEach; relpipe::writer::string_t guileWhere; + relpipe::writer::string_t guileHasMoreRecords; /** * If true, Guile code will be executed, but no output will be generated. @@ -90,6 +91,8 @@ std::vector definitions; // TODO: --create t2 3 a integer b boolean '…guile…' – allow creating new relations? Or allow calling startRelation() and attribute() from Guile? + // TODO: --has-more-relations '…guile…' – called after all relations … ? + // TODO: --dynamic-output-attributes '…guile…' – used instead or together with --output-attribute virtual ~Configuration() { } diff -r 051e58022783 -r 2dcc22b7a424 src/GuileHandler.h --- a/src/GuileHandler.h Tue Feb 05 20:40:32 2019 +0100 +++ b/src/GuileHandler.h Thu Feb 07 00:55:54 2019 +0100 @@ -187,6 +187,17 @@ } } + /** + * Read from the Guile variables and write to relational output stream. + */ + void writeCurrentRecord() { + for (auto attribute : currentWriterMetadata) writeGuileValueToAttribute(attribute); + } + + void writeMoreRecords() { + while (scm_to_bool(evalGuileCode(currentRelationConfiguration->guileHasMoreRecords, SCM_BOOL_F))) writeCurrentRecord(); + } + public: GuileHandler(writer::RelationalWriter* relationalWriter, Configuration& configuration, const vector& arguments) : relationalWriter(relationalWriter), configuration(configuration) { @@ -195,6 +206,7 @@ void startRelation(string_t name, vector attributes) override { if (currentRelationConfiguration) { evalGuileCode(currentRelationConfiguration->guileAfterRecords); + writeMoreRecords(); for (DefinitionRecipe definition : currentRelationConfiguration->definitions) undefineGuileVariable(definition.name); } for (auto attribute : currentReaderMetadata) undefineGuileVariable(attribute.getAttributeName()); @@ -240,8 +252,9 @@ if (currentAttributeIndex > 0 && currentAttributeIndex % currentReaderMetadata.size() == 0) { evalGuileCode(currentRelationConfiguration->guileForEach); includeCurrentRecord = scm_to_bool(evalGuileCode(currentRelationConfiguration->guileWhere, SCM_BOOL_T)); - if (includeCurrentRecord && !currentRelationConfiguration->drop) for (auto attribute : currentWriterMetadata) writeGuileValueToAttribute(attribute); + if (includeCurrentRecord && !currentRelationConfiguration->drop) writeCurrentRecord(); includeCurrentRecord = false; + writeMoreRecords(); } currentAttributeIndex = currentAttributeIndex % currentReaderMetadata.size(); @@ -251,7 +264,10 @@ } void endOfPipe() { - if (currentRelationConfiguration) evalGuileCode(currentRelationConfiguration->guileAfterRecords); + if (currentRelationConfiguration) { + evalGuileCode(currentRelationConfiguration->guileAfterRecords); + writeMoreRecords(); + } } };