--- 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<writer::RelationalWriter> relationalWriter;
wregex relationNameRegEx;
- wregex attributeNameRegEx;
- wregex searchRegEx;
+ vector<wregex> attributeNameRegExes;
- vector<boolean_t> currentSearchableAttributes;
+ vector<integer_t> currentAttributeMapping;
vector<string_t> currentRecord;
integer_t currentAttributeIndex = 0;
- boolean_t includeCurrentRecord = false;
boolean_t filterCurrentRelation = false;
public:
@@ -63,51 +61,52 @@
GrepHandler(ostream& output, const vector<string_t>& 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 <relationNameRegExp> <attributeNameRegExp> <searchRegExp>", cli::CLI::EXIT_CODE_UNKNOWN_COMMAND);
+ throw cli::RelpipeCLIException(L"Usage: relpipe-tr-cut <relationNameRegExp> <attributeNameRegExp> [<otherAttributeNameRegExp> ...]", cli::CLI::EXIT_CODE_UNKNOWN_COMMAND);
}
}
void startRelation(string_t name, vector<AttributeMetadata> attributes) override {
// TODO: move to a reusable method (or use same metadata on both reader and writer side?)
- vector<writer::AttributeMetadata> writerMetadata;
+ vector<writer::AttributeMetadata> allWriterMetadata;
for (AttributeMetadata readerMetadata : attributes) {
- writerMetadata.push_back({readerMetadata.getAttributeName(), relationalWriter->toTypeId(readerMetadata.getTypeName())});
+ allWriterMetadata.push_back({readerMetadata.getAttributeName(), relationalWriter->toTypeId(readerMetadata.getTypeName())});
}
+ vector<writer::AttributeMetadata> 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);
}