Guile can now process multiple relations in the stream v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sun, 03 Feb 2019 19:02:50 +0100
branchv_0
changeset 8 1e6206284c6c
parent 7 61fc569b77e6
child 9 65f9d6b94f5c
Guile can now process multiple relations in the stream
src/GuileHandler.h
--- a/src/GuileHandler.h	Sun Feb 03 12:35:17 2019 +0100
+++ b/src/GuileHandler.h	Sun Feb 03 19:02:50 2019 +0100
@@ -56,15 +56,12 @@
 	Configuration configuration;
 	writer::RelationalWriter* relationalWriter;
 
-	wregex relationNameRegEx;
-
+	RelationConfiguration* currentRelationConfiguration = nullptr;
 	vector<AttributeMetadata> currentReaderMetadata;
 	vector<writer::AttributeMetadata> currentWriterMetadata;
 	vector<string_t> currentRecord;
 	integer_t currentAttributeIndex = 0;
 	boolean_t includeCurrentRecord = false;
-	boolean_t filterCurrentRelation = false;
-	string_t guileCodeWhereCondition;
 
 	/**
 	 * @param attributeName name from relational pipe
@@ -147,15 +144,6 @@
 public:
 
 	GuileHandler(writer::RelationalWriter* relationalWriter, Configuration& configuration, const vector<string_t>& arguments) : relationalWriter(relationalWriter), configuration(configuration) {
-
-		// FIXME: remove and work directly with configuration in startRelation() and attribute()
-		// i.e. support multiple relationConfigurations
-		if (configuration.relationConfigurations.size() == 1) {
-			relationNameRegEx = wregex(configuration.relationConfigurations[0].relation);
-			guileCodeWhereCondition = configuration.relationConfigurations[0].guileWhere;
-		} else {
-			throw cli::RelpipeCLIException(L"FIXME: only single relationConfiguration is currently supported", cli::CLI::EXIT_CODE_UNKNOWN_COMMAND);
-		}
 	}
 
 	void startRelation(string_t name, vector<AttributeMetadata> attributes) override {
@@ -163,27 +151,32 @@
 		currentReaderMetadata = attributes;
 		// TODO: move to a reusable method (or use same metadata on both reader and writer side?)
 		// TODO: allow structural changes during transformation
-		// TODO: clear Guile variables for attributes from previous relation
 		currentWriterMetadata.clear();
 		for (AttributeMetadata readerMetadata : attributes) {
 			currentWriterMetadata.push_back({readerMetadata.getAttributeName(), relationalWriter->toTypeId(readerMetadata.getTypeName())});
 		}
 
 		currentRecord.resize(attributes.size());
-		filterCurrentRelation = regex_match(name, relationNameRegEx);
+
+		for (int i = 0; i < configuration.relationConfigurations.size(); i++) {
+			if (regex_match(name, wregex(configuration.relationConfigurations[i].relation))) {
+				currentRelationConfiguration = &configuration.relationConfigurations[i];
+				break; // it there are multiple matches, only the first configuration is used
+			}
+		}
 
 		relationalWriter->startRelation(name, currentWriterMetadata, true);
 	}
 
 	void attribute(const void* value, const std::type_info& type) override {
-		if (filterCurrentRelation) {
+		if (currentRelationConfiguration) {
 			defineGuileVariable(a2v(currentReaderMetadata[currentAttributeIndex].getAttributeName()), value, type, currentReaderMetadata[currentAttributeIndex].getTypeId());
 
 			currentAttributeIndex++;
 
 			// TODO: > 0 ?:
 			if (currentAttributeIndex > 0 && currentAttributeIndex % currentReaderMetadata.size() == 0) {
-				includeCurrentRecord = scm_to_bool(evalGuileCode(guileCodeWhereCondition));
+				includeCurrentRecord = scm_to_bool(evalGuileCode(currentRelationConfiguration->guileWhere));
 				if (includeCurrentRecord) for (auto attribute : currentWriterMetadata) writeGuileValueToAttribute(attribute);
 				includeCurrentRecord = false;
 			}