--- a/src/GuileHandler.h Tue May 07 01:03:21 2019 +0200
+++ b/src/GuileHandler.h Sun May 26 19:46:47 2019 +0200
@@ -20,6 +20,7 @@
#include <memory>
#include <string>
#include <vector>
+#include <map>
#include <iostream>
#include <sstream>
#include <locale>
@@ -39,6 +40,7 @@
#include <relpipe/cli/RelpipeCLIException.h>
#include "Configuration.h"
+#include "GuileException.h"
namespace relpipe {
namespace tr {
@@ -59,6 +61,7 @@
RelationConfiguration* currentRelationConfiguration = nullptr;
vector<AttributeMetadata> currentReaderMetadata;
vector<writer::AttributeMetadata> currentWriterMetadata;
+ std::map<string_t, string_t> currenVariablesMapping;
integer_t currentAttributeIndex = 0;
boolean_t includeCurrentRecord = false;
@@ -70,13 +73,51 @@
});
}
+ void generateVariableMappings() {
+ currenVariablesMapping.clear();
+ for (AttributeMetadata m : currentReaderMetadata) currenVariablesMapping[m.getAttributeName()] = L"";
+ for (writer::AttributeMetadata m : currentWriterMetadata) currenVariablesMapping[m.attributeName] = L"";
+
+ for (std::pair<string_t, string_t> m : currenVariablesMapping) {
+ currenVariablesMapping[m.first] = escapeAwkVariableName(m.first);
+ }
+ }
+
/**
* @param attributeName name from relational pipe
* @return variable name in Guile
*/
string_t a2v(const string_t& attributeName) {
- // TODO: escape spaces and special characters
- return L"$" + attributeName;
+ if (currenVariablesMapping.find(attributeName) != currenVariablesMapping.end()) return currenVariablesMapping[attributeName];
+ else throw GuileException(L"Unable to find value in currenVariablesMapping");
+ }
+
+ template <typename K, typename V> bool containsValue(std::map<K, V> map, V value) { // TODO: common function (Guile, AWK)
+ for (std::pair<K, V> p : map) if (p.second == value) return true;
+ return false;
+ }
+
+ string_t escapeAwkVariableName(const string_t& attributeName, bool addPrefix = true) {
+ std::wregex badCharacters(L"\\s");
+ string_t name = std::regex_replace(attributeName, badCharacters, L"-");
+
+ if (addPrefix) name = L"$" + name; // $ = standard attribute-variable prefix
+
+ if (containsValue(currenVariablesMapping, name)) return escapeAwkVariableName(L"$" + name, false); // $ = different prefix added to distinguish two attributes with ambiguous names
+ else return name;
+
+ }
+
+ void debugVariableMapping(const string_t& relationName) {
+ relationalWriter->startRelation(relationName + L".variableMapping",{
+ {L"attribute", writer::TypeId::STRING},
+ {L"variable", writer::TypeId::STRING},
+ }, true);
+
+ for (std::pair<string_t, string_t> m : currenVariablesMapping) {
+ relationalWriter->writeAttribute(m.first);
+ relationalWriter->writeAttribute(m.second);
+ }
}
SCM toGuileSymbol(const string_t& name) {
@@ -233,6 +274,10 @@
add(currentReaderMetadata, currentWriterMetadata);
}
+ generateVariableMappings();
+
+ if (currentRelationConfiguration->debugVariableMapping) debugVariableMapping(name);
+
if (!currentRelationConfiguration || !currentRelationConfiguration->drop) relationalWriter->startRelation(name, currentWriterMetadata, true);
if (currentRelationConfiguration) {