# HG changeset patch # User František Kučera # Date 1544660935 -3600 # Node ID 9ec1290b4a9d5ef392dbec44c243420800ef0a76 # Parent f06781a5071b59570836876299d681b77042178a first working cut version diff -r f06781a5071b -r 9ec1290b4a9d src/CutHandler.h --- a/src/CutHandler.h Wed Dec 12 23:45:46 2018 +0100 +++ b/src/CutHandler.h Thu Dec 13 01:28:55 2018 +0100 @@ -49,13 +49,11 @@ shared_ptr relationalWriter; wregex relationNameRegEx; - wregex attributeNameRegEx; - wregex searchRegEx; + vector attributeNameRegExes; - vector currentSearchableAttributes; + vector currentAttributeMapping; vector currentRecord; integer_t currentAttributeIndex = 0; - boolean_t includeCurrentRecord = false; boolean_t filterCurrentRelation = false; public: @@ -63,51 +61,52 @@ GrepHandler(ostream& output, const vector& arguments) { relationalWriter.reset(writer::Factory::create(output)); - if (arguments.size() == 3) { + if (arguments.size() >= 2) { relationNameRegEx = wregex(arguments[0]); - attributeNameRegEx = wregex(arguments[1]); - searchRegEx = wregex(arguments[2]); + for (int i = 1; i < arguments.size(); i++) attributeNameRegExes.push_back(wregex(arguments[i])); } else { - throw cli::RelpipeCLIException(L"Usage: relpipe-tr-cut ", cli::CLI::EXIT_CODE_UNKNOWN_COMMAND); + throw cli::RelpipeCLIException(L"Usage: relpipe-tr-cut [ ...]", cli::CLI::EXIT_CODE_UNKNOWN_COMMAND); } } void startRelation(string_t name, vector attributes) override { // TODO: move to a reusable method (or use same metadata on both reader and writer side?) - vector writerMetadata; + vector allWriterMetadata; for (AttributeMetadata readerMetadata : attributes) { - writerMetadata.push_back({readerMetadata.getAttributeName(), relationalWriter->toTypeId(readerMetadata.getTypeName())}); + allWriterMetadata.push_back({readerMetadata.getAttributeName(), relationalWriter->toTypeId(readerMetadata.getTypeName())}); } + vector writerMetadata; - currentRecord.resize(attributes.size()); - currentSearchableAttributes.resize(attributes.size(), false); filterCurrentRelation = regex_match(name, relationNameRegEx); if (filterCurrentRelation) { - for (int i = 0; i < currentSearchableAttributes.size(); i++) { - currentSearchableAttributes[i] = regex_match(attributes[i].getAttributeName(), attributeNameRegEx); + currentAttributeMapping.clear(); + for (wregex attributeNameRegEx : attributeNameRegExes) { + for (int i = 0; i < allWriterMetadata.size(); i++) { + if (regex_match(allWriterMetadata[i].attributeName, attributeNameRegEx)) currentAttributeMapping.push_back(i); + } } + + if (currentAttributeMapping.empty()) throw cli::RelpipeCLIException(L"No attribute matches. Relation must have at least one attribute.", cli::CLI::EXIT_CODE_BAD_SYNTAX); // TODO: review exit code + for (integer_t i : currentAttributeMapping) writerMetadata.push_back(allWriterMetadata[i]); + } else { + writerMetadata = allWriterMetadata; } + currentRecord.resize(allWriterMetadata.size()); relationalWriter->startRelation(name, writerMetadata, true); } void attribute(const string_t& value) override { if (filterCurrentRelation) { currentRecord[currentAttributeIndex] = value; - - if (currentSearchableAttributes[currentAttributeIndex]) { - includeCurrentRecord |= regex_search(value, searchRegEx); - } - currentAttributeIndex++; - if (currentAttributeIndex > 0 && currentAttributeIndex % currentSearchableAttributes.size() == 0) { - if (includeCurrentRecord) for (string_t v : currentRecord) relationalWriter->writeAttribute(v); - includeCurrentRecord = false; + if (currentAttributeIndex > 0 && currentAttributeIndex % currentRecord.size() == 0) { + for (integer_t i : currentAttributeMapping) relationalWriter->writeAttribute(currentRecord[i]); } - currentAttributeIndex = currentAttributeIndex % currentSearchableAttributes.size(); + currentAttributeIndex = currentAttributeIndex % currentRecord.size(); } else { relationalWriter->writeAttribute(value); }