3#include <vtkInformation.h>
5#include <vtkDelimitedTextReader.h>
6#include <vtkFieldData.h>
7#include <vtkInformationVector.h>
8#include <vtkObjectFactory.h>
9#include <vtkSmartPointer.h>
17#include <boost/algorithm/string.hpp>
18#include <boost/algorithm/string/replace.hpp>
23 this->SetNumberOfInputPorts(1);
24 this->SetNumberOfOutputPorts(1);
30 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(),
"vtkTable");
31 info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1);
39 info->Set(vtkDataObject::DATA_TYPE_NAME(),
"vtkTable");
46 vtkInformationVector **inputVector,
47 vtkInformationVector *outputVector) {
51 auto outTable = vtkTable::GetData(outputVector);
55 auto nTables = inputVector[0]->GetNumberOfInformationObjects();
57 this->
printErr(
"No input vtkTable found");
61 std::vector<vtkTable *> inTables(nTables);
62 for(
int i = 0; i < nTables; ++i) {
63 inTables[i] = vtkTable::GetData(inputVector[0], i);
66 auto firstTable = inTables[0];
68 std::vector<std::string> sqlTableDefinitions;
69 std::vector<std::string> sqlInsertStatements;
73 for(
int i = 0; i < nTables; i++) {
74 auto inTable = inTables[i];
76 size_t nc = inTable->GetNumberOfColumns();
77 size_t nr = inTable->GetNumberOfRows();
78 std::vector<bool> isNumeric(nc);
80 std::vector<size_t> includeColumns(nc);
81 std::iota(includeColumns.begin(), includeColumns.end(), 0);
84 if(this->ExcludeColumnsWithRegexp) {
85 const auto oldSize{includeColumns.size()};
87 std::remove_if(includeColumns.begin(), includeColumns.end(),
88 [inTable,
this](
const size_t a) {
89 const auto name{inTable->GetColumnName(a)};
90 return std::regex_match(
91 name, std::regex(this->RegexpString));
93 includeColumns.end());
94 if(includeColumns.size() < oldSize) {
96 + std::to_string(oldSize - includeColumns.size())
97 +
" columns with regexp `" + this->RegexpString +
"'");
103 const auto oldSize{includeColumns.size()};
104 includeColumns.erase(
105 std::remove_if(includeColumns.begin(), includeColumns.end(),
106 [inTable](
const size_t a) {
107 const auto col{inTable->GetColumn(a)};
108 return col->GetNumberOfComponents() != 1;
110 includeColumns.end());
111 if(includeColumns.size() < oldSize) {
113 + std::to_string(oldSize - includeColumns.size())
114 +
" non-scalar columns");
120 const auto oldSize{includeColumns.size()};
121 includeColumns.erase(
122 std::remove_if(includeColumns.begin(), includeColumns.end(),
123 [inTable](
const size_t a) {
124 const std::string colName{inTable->GetColumnName(a)};
125 return colName.find(
' ') != std::string::npos;
127 includeColumns.end());
128 if(includeColumns.size() < oldSize) {
130 + std::to_string(oldSize - includeColumns.size())
131 +
" columns with a space in their name");
135 if(includeColumns.empty()) {
136 this->printWrn(
"No columns to process!");
142 std::string sqlTableDefinition
143 =
"CREATE TABLE InputTable" + std::to_string(i) +
" (";
145 for(
const auto j : includeColumns) {
146 auto c = inTable->GetColumn(j);
147 isNumeric[j] = c->IsNumeric();
148 sqlTableDefinition += (firstCol ?
"" :
",") + std::string(c->GetName())
149 +
" " + (isNumeric[j] ?
"REAL" :
"TEXT");
154 sqlTableDefinition +=
")";
155 sqlTableDefinitions.emplace_back(sqlTableDefinition);
161 std::string sqlInsertStatement
162 =
"INSERT INTO InputTable" + std::to_string(i) +
" VALUES ";
163 for(
size_t j = 0; j < 500 && q < nr; j++) {
165 sqlInsertStatement +=
",";
167 sqlInsertStatement +=
"(";
169 for(
const auto k : includeColumns) {
170 sqlInsertStatement += (firstCol ?
"" :
",");
175 const auto var = inTable->GetValue(q, k);
176 if(
var.IsChar() ||
var.IsSignedChar()) {
179 sqlInsertStatement += std::to_string(
var.ToInt());
180 }
else if(std::isnan(
var.ToDouble())) {
181 sqlInsertStatement +=
"'NaN'";
183 sqlInsertStatement +=
var.ToString();
187 +=
"'" + inTable->GetValue(q, k).ToString() +
"'";
190 sqlInsertStatement +=
")";
193 sqlInsertStatements.emplace_back(sqlInsertStatement);
197 this->
printMsg(
"Converting input VTK tables to SQL tables", 1,
198 conversionTimer.getElapsedTime());
203 std::string finalQueryString;
205 std::string errorMsg;
207 firstTable->GetFieldData(), finalQueryString,
209 this->printErr(errorMsg);
216 std::stringstream csvResult;
221 = this->execute(sqlTableDefinitions, sqlInsertStatements, finalQueryString,
222 csvResult, csvNColumns, csvNRows);
227 if(csvNRows < 1 || status != 1) {
229 for(
int i = 0; i < csvNColumns; i++)
230 csvResult <<
",NULL";
239 reader->SetReadFromInputString(
true);
240 reader->SetInputString(csvResult.str().data());
241 reader->DetectNumericColumnsOn();
242 reader->SetHaveHeaders(
true);
243 reader->SetFieldDelimiterCharacters(
",");
246 outTable->ShallowCopy(reader->GetOutput());
248 auto outFD = outTable->GetFieldData();
249 for(
const auto inTable : inTables) {
252 auto inFD = inTable->GetFieldData();
254 size_t n = inFD->GetNumberOfArrays();
255 for(
size_t i = 0; i < n; i++) {
256 auto iArray = inFD->GetAbstractArray(i);
257 if(!outFD->GetAbstractArray(iArray->GetName())) {
258 outFD->AddArray(iArray);
263 this->
printMsg(
"Converting SQL result to VTK table", 1,
269 this->
printMsg(
"Complete (#rows: " + std::to_string(csvNRows) +
")", 1,
270 timer.getElapsedTime());
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
TTK VTK-filter that uses a SQL statement to select a subset of a vtkTable.
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
~ttkCinemaQuery() override
int FillOutputPortInformation(int port, vtkInformation *info) override
int FillInputPortInformation(int port, vtkInformation *info) override
static int replaceVariables(const std::string &iString, vtkFieldData *fieldData, std::string &oString, std::string &errorMsg)
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
int printMsg(const std::string &msg, const debug::Priority &priority=debug::Priority::INFO, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cout) const
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
T var(const T *v, const int &dimension=3)
vtkStandardNewMacro(ttkCinemaQuery)
printMsg(debug::output::GREEN+" "+debug::output::ENDCOLOR+debug::output::GREEN+"▒"+debug::output::ENDCOLOR+debug::output::GREEN+"▒▒▒▒▒▒▒▒▒▒▒▒▒░"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)