# HG changeset patch # User František Kučera # Date 1572104737 -7200 # Node ID 0ecde5272f8e70cb7f53566b5dd3378beb07804a # Parent eacacf06075568c430e9507e7e72c08b8c40bb36 process SQL input in the relpipe-in-sql mode diff -r eacacf060755 -r 0ecde5272f8e nbproject/configurations.xml --- a/nbproject/configurations.xml Fri Oct 25 12:33:00 2019 +0200 +++ b/nbproject/configurations.xml Sat Oct 26 17:45:37 2019 +0200 @@ -93,8 +93,6 @@ true - - diff -r eacacf060755 -r 0ecde5272f8e src/Configuration.h --- a/src/Configuration.h Fri Oct 25 12:33:00 2019 +0200 +++ b/src/Configuration.h Sat Oct 26 17:45:37 2019 +0200 @@ -75,7 +75,17 @@ KeepFile keepFile = KeepFile::Automatic; std::vector statements; + + /** + * SQL script to be executed before the relational input. + */ + std::wistream* sqlBeforeRelational = nullptr; + /** + * SQL script to be executed after the relational input. + */ + std::wistream* sqlAfterRelational = nullptr; + std::wstring dumpRelations; virtual ~Configuration() { diff -r eacacf060755 -r 0ecde5272f8e src/SqlHandler.h --- a/src/SqlHandler.h Fri Oct 25 12:33:00 2019 +0200 +++ b/src/SqlHandler.h Sat Oct 26 17:45:37 2019 +0200 @@ -150,6 +150,30 @@ std::unique_ptr connection; std::unique_ptr currentInsert; + bool readNextSqlStatement(std::wistream* input, std::wstringstream* sql) { + sql->str(L""); + sql->clear(); + + for (wchar_t ch; *input >> ch;) { + *sql << ch; + if (ch == L';' && sqlite3_complete(convertor.to_bytes(sql->str()).c_str())) return true; + } + + string_t remainingSql = sql->str(); + for (wchar_t ch : remainingSql) if (ch != L' ' && ch != L'\n' && ch != L'\r' && ch != L'\t') throw SqlException(L"Unexpected EOF, missing „;“ after: „" + remainingSql + L"“"); + + return false; + } + + void processSqlInput(std::wistream* input) { + if (input == nullptr) return; + *input >> std::ws >> std::noskipws; + for (std::wstringstream sql; readNextSqlStatement(input, &sql);) { + std::unique_ptr prepared(connection->prepareStatement(convertor.to_bytes(sql.str()).c_str())); + while (prepared->next()); + } + } + void processStatement(const Statement& statement) { std::unique_ptr prepared(connection->prepareStatement(convertor.to_bytes(statement.sql).c_str())); int columnCount = prepared->getColumnCount(); @@ -300,9 +324,15 @@ } void endOfPipe() { + // process optional SQL input + processSqlInput(configuration.sqlBeforeRelational); + // run the transformation – process all statements: for (const Statement& statement : configuration.statements) processStatement(statement); + // process optional SQL input + processSqlInput(configuration.sqlAfterRelational); + // pass-through some relations: if (configuration.dumpRelations.size()) dumpRelations(); diff -r eacacf060755 -r 0ecde5272f8e src/relpipe-tr-sql.cpp --- a/src/relpipe-tr-sql.cpp Fri Oct 25 12:33:00 2019 +0200 +++ b/src/relpipe-tr-sql.cpp Sat Oct 26 17:45:37 2019 +0200 @@ -55,6 +55,8 @@ if (std::regex_match(cli.programName(), std::wregex(L"^(.*/)?relpipe-in-sql$"))) { // relpipe-in-sql: std::shared_ptr writer(writer::Factory::create(std::cout)); + configuration.sqlBeforeRelational = isatty(fileno(stdin)) ? nullptr : &std::wcin; + configuration.sqlAfterRelational = nullptr; SqlHandler handler(writer.get(), configuration); handler.endOfPipe(); } else {