author | František Kučera <franta-hg@frantovo.cz> |
Fri, 14 Dec 2018 00:14:58 +0100 | |
branch | v_0 |
changeset 12 | ee69be2212fa |
parent 11 | 5e0b317f4100 |
child 13 | df354b680b89 |
permissions | -rw-r--r-- |
3
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
1 |
/** |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
2 |
* Relational pipes |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
3 |
* Copyright © 2018 František Kučera (Frantovo.cz, GlobalCode.info) |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
4 |
* |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
5 |
* This program is free software: you can redistribute it and/or modify |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
6 |
* it under the terms of the GNU General Public License as published by |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
7 |
* the Free Software Foundation, either version 3 of the License, or |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
8 |
* (at your option) any later version. |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
9 |
* |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
10 |
* This program is distributed in the hope that it will be useful, |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
13 |
* GNU General Public License for more details. |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
14 |
* |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
15 |
* You should have received a copy of the GNU General Public License |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
16 |
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
17 |
*/ |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
18 |
#pragma once |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
19 |
|
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
20 |
#include <memory> |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
21 |
#include <string> |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
22 |
#include <vector> |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
23 |
#include <iostream> |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
24 |
#include <sstream> |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
25 |
#include <locale> |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
26 |
#include <codecvt> |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
27 |
#include <regex> |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
28 |
|
10 | 29 |
#include <Python.h> |
30 |
||
3
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
31 |
#include <relpipe/reader/typedefs.h> |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
32 |
#include <relpipe/reader/TypeId.h> |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
33 |
#include <relpipe/reader/handlers/RelationalReaderStringHandler.h> |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
34 |
#include <relpipe/reader/handlers/AttributeMetadata.h> |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
35 |
|
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
36 |
#include <relpipe/writer/Factory.h> |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
37 |
|
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
38 |
#include <relpipe/cli/RelpipeCLIException.h> |
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
39 |
|
3
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
40 |
namespace relpipe { |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
41 |
namespace tr { |
7 | 42 |
namespace grep { |
3
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
43 |
|
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
44 |
using namespace std; |
3
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
45 |
using namespace relpipe; |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
46 |
using namespace relpipe::reader; |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
47 |
using namespace relpipe::reader::handlers; |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
48 |
|
7 | 49 |
class GrepHandler : public RelationalReaderStringHadler { |
3
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
50 |
private: |
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
51 |
shared_ptr<writer::RelationalWriter> relationalWriter; |
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
52 |
|
11
5e0b317f4100
execute arbitrary python code,
František Kučera <franta-hg@frantovo.cz>
parents:
10
diff
changeset
|
53 |
wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings. |
10 | 54 |
wchar_t* pythonProgramName; |
55 |
||
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
56 |
wregex relationNameRegEx; |
11
5e0b317f4100
execute arbitrary python code,
František Kučera <franta-hg@frantovo.cz>
parents:
10
diff
changeset
|
57 |
string_t pythonCode; |
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
58 |
|
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
59 |
vector<string_t> currentRecord; |
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
60 |
integer_t currentAttributeIndex = 0; |
11
5e0b317f4100
execute arbitrary python code,
František Kučera <franta-hg@frantovo.cz>
parents:
10
diff
changeset
|
61 |
boolean_t includeCurrentRecord = true; |
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
62 |
boolean_t filterCurrentRelation = false; |
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
63 |
|
3
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
64 |
public: |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
65 |
|
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
66 |
GrepHandler(ostream& output, const vector<string_t>& arguments) { |
7 | 67 |
relationalWriter.reset(writer::Factory::create(output)); |
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
68 |
|
10 | 69 |
pythonProgramName = Py_DecodeLocale("relpipe-tr-python", NULL); |
70 |
Py_SetProgramName(pythonProgramName); |
|
71 |
Py_Initialize(); |
|
12
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
72 |
|
11
5e0b317f4100
execute arbitrary python code,
František Kučera <franta-hg@frantovo.cz>
parents:
10
diff
changeset
|
73 |
if (arguments.size() == 2) { |
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
74 |
relationNameRegEx = wregex(arguments[0]); |
11
5e0b317f4100
execute arbitrary python code,
František Kučera <franta-hg@frantovo.cz>
parents:
10
diff
changeset
|
75 |
pythonCode = arguments[1]; |
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
76 |
} else { |
10 | 77 |
PyMem_RawFree(pythonProgramName); |
11
5e0b317f4100
execute arbitrary python code,
František Kučera <franta-hg@frantovo.cz>
parents:
10
diff
changeset
|
78 |
throw cli::RelpipeCLIException(L"Usage: relpipe-tr-python <relationNameRegExp> <pythonCode>", cli::CLI::EXIT_CODE_UNKNOWN_COMMAND); |
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
79 |
} |
3
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
80 |
} |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
81 |
|
10 | 82 |
virtual ~GrepHandler() { |
83 |
Py_FinalizeEx(); |
|
84 |
PyMem_RawFree(pythonProgramName); |
|
85 |
} |
|
86 |
||
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
87 |
void startRelation(string_t name, vector<AttributeMetadata> attributes) override { |
3
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
88 |
// TODO: move to a reusable method (or use same metadata on both reader and writer side?) |
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
89 |
vector<writer::AttributeMetadata> writerMetadata; |
3
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
90 |
for (AttributeMetadata readerMetadata : attributes) { |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
91 |
writerMetadata.push_back({readerMetadata.getAttributeName(), relationalWriter->toTypeId(readerMetadata.getTypeName())}); |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
92 |
} |
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
93 |
|
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
94 |
|
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
95 |
currentRecord.resize(attributes.size()); |
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
96 |
filterCurrentRelation = regex_match(name, relationNameRegEx); |
3
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
97 |
relationalWriter->startRelation(name, writerMetadata, true); |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
98 |
} |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
99 |
|
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
100 |
void attribute(const string_t& value) override { |
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
101 |
if (filterCurrentRelation) { |
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
102 |
currentRecord[currentAttributeIndex] = value; |
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
103 |
currentAttributeIndex++; |
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
104 |
|
11
5e0b317f4100
execute arbitrary python code,
František Kučera <franta-hg@frantovo.cz>
parents:
10
diff
changeset
|
105 |
if (currentAttributeIndex > 0 && currentAttributeIndex % currentRecord.size() == 0) { |
12
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
106 |
|
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
107 |
PyObject* pyModule; |
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
108 |
PyObject* pyDict; |
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
109 |
PyObject* pyWhere; |
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
110 |
|
11
5e0b317f4100
execute arbitrary python code,
František Kučera <franta-hg@frantovo.cz>
parents:
10
diff
changeset
|
111 |
PyRun_SimpleString(convertor.to_bytes(pythonCode).c_str()); |
12
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
112 |
|
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
113 |
// FIXME: check Python error and throw exception |
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
114 |
// if (PyErr_Occurred()) throw cli::RelpipeCLIException(L"Python code failed.", cli::CLI::EXIT_CODE_UNEXPECTED_ERROR); // TODO: review exit code |
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
115 |
// if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); } |
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
116 |
|
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
117 |
pyModule = PyImport_AddModule((char*) "__main__"); // FIXME: variable and Py_DecodeLocale ? |
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
118 |
pyDict = PyModule_GetDict(pyModule); |
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
119 |
pyWhere = PyDict_GetItemString(pyDict, "WHERE"); |
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
120 |
|
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
121 |
if (pyWhere) includeCurrentRecord = PyLong_AsLong(pyWhere); |
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
122 |
|
ee69be2212fa
relational restriction possible through Python: WHERE = False
František Kučera <franta-hg@frantovo.cz>
parents:
11
diff
changeset
|
123 |
|
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
124 |
if (includeCurrentRecord) for (string_t v : currentRecord) relationalWriter->writeAttribute(v); |
11
5e0b317f4100
execute arbitrary python code,
František Kučera <franta-hg@frantovo.cz>
parents:
10
diff
changeset
|
125 |
includeCurrentRecord = true; |
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
126 |
} |
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
127 |
|
11
5e0b317f4100
execute arbitrary python code,
František Kučera <franta-hg@frantovo.cz>
parents:
10
diff
changeset
|
128 |
currentAttributeIndex = currentAttributeIndex % currentRecord.size(); |
8
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
129 |
} else { |
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
130 |
relationalWriter->writeAttribute(value); |
f66c759d1111
first working grep version
František Kučera <franta-hg@frantovo.cz>
parents:
7
diff
changeset
|
131 |
} |
3
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
132 |
} |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
133 |
|
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
134 |
void endOfPipe() { |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
135 |
|
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
136 |
} |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
137 |
|
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
138 |
}; |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
139 |
|
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
140 |
} |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
141 |
} |
8731263d44f1
PassthroughHandler (string-based version)
František Kučera <franta-hg@frantovo.cz>
parents:
diff
changeset
|
142 |
} |