--- 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<string_t>& 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";
}
}
--- 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<DefinitionRecipe> 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() {
}
--- 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<string_t>& arguments) : relationalWriter(relationalWriter), configuration(configuration) {
@@ -195,6 +206,7 @@
void startRelation(string_t name, vector<AttributeMetadata> 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();
+ }
}
};