src/SqlHandler.h
author František Kučera <franta-hg@frantovo.cz>
Sun, 28 Aug 2022 18:03:13 +0200
branchv_0
changeset 59 a1775ba6d056
parent 58 a4907b207f0c
permissions -rw-r--r--
optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes) examples, shortcuts: relpipe-tr-unionall() { relpipe-tr-sql --copy '.+' --on-duplicate-relation insert; } # does UNION ALL for all tables with same name (including already existing ones – when non-empty database is used) relpipe-tr-unionall() { relpipe-tr-serialize | relpipe-tr-deserialize; } # does UNION ALL only for tables with same name immediately following each other (interleaved duplicates will stay unaffected)
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     1
/**
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     2
 * Relational pipes
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     3
 * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     4
 *
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     5
 * This program is free software: you can redistribute it and/or modify
c205f5d06418 project skeleton
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
10
7da7173d84b0 fix license version: GNU GPLv3
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
     7
 * the Free Software Foundation, version 3.
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     8
 *
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     9
 * This program is distributed in the hope that it will be useful,
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    12
 * GNU General Public License for more details.
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    13
 *
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    14
 * You should have received a copy of the GNU General Public License
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    16
 */
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    17
#pragma once
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    18
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    19
#include <memory>
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    20
#include <string>
6
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
    21
#include <sstream>
14
eacacf060755 add --dump option: allow pass through of relation specified by a regular expression
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    22
#include <regex>
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    23
#include <vector>
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    24
#include <locale>
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    25
#include <codecvt>
5
cbc7817a3346 add option to create DB in a file and to keep that file
František Kučera <franta-hg@frantovo.cz>
parents: 4
diff changeset
    26
#include <unistd.h>
8
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
    27
#include <cassert>
12
0b38339b871b improve --keep-file option: default is auto = file will be kept, if it was present before the transformation
František Kučera <franta-hg@frantovo.cz>
parents: 11
diff changeset
    28
#include <sys/stat.h>
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    29
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    30
#include <relpipe/reader/typedefs.h>
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    31
#include <relpipe/reader/TypeId.h>
8
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
    32
#include <relpipe/reader/handlers/RelationalReaderValueHandler.h>
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    33
#include <relpipe/reader/handlers/AttributeMetadata.h>
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    34
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    35
#include <relpipe/writer/Factory.h>
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    36
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    37
#include "Configuration.h"
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    38
#include "SqlException.h"
33
86ceb97db7de SqlInputScanner for parsing SQL script and separating particular statements; does not depend on sqlite3_complete()
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
    39
#include "SqlInputScanner.h"
26
49919a60c747 move PreparedStatement class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    40
#include "PreparedStatement.h"
27
9441a517fa1f move Connection class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents: 26
diff changeset
    41
#include "Connection.h"
34
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    42
#include "DriverManager.h"
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    43
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    44
namespace relpipe {
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    45
namespace tr {
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    46
namespace sql {
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    47
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    48
using namespace std;
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    49
using namespace relpipe;
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    50
using namespace relpipe::reader;
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    51
using namespace relpipe::reader::handlers;
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    52
8
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
    53
class SqlHandler : public RelationalReaderValueHandler {
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    54
private:
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    55
	Configuration configuration;
12
0b38339b871b improve --keep-file option: default is auto = file will be kept, if it was present before the transformation
František Kučera <franta-hg@frantovo.cz>
parents: 11
diff changeset
    56
	boolean_t fileAlreadyExisted = false;
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    57
	writer::RelationalWriter* relationalWriter;
34
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    58
	DriverManager* driverManager;
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    59
	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings
7
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
    60
	vector<AttributeMetadata> currentReaderMetadata;
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
    61
	integer_t currentAttributeIndex = 0;
3
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    62
	std::unique_ptr<Connection> connection;
7
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
    63
	std::unique_ptr<PreparedStatement> currentInsert;
3
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    64
15
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    65
	bool readNextSqlStatement(std::wistream* input, std::wstringstream* sql) {
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    66
		sql->str(L"");
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    67
		sql->clear();
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    68
33
86ceb97db7de SqlInputScanner for parsing SQL script and separating particular statements; does not depend on sqlite3_complete()
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
    69
		SqlInputScanner scanner;
86ceb97db7de SqlInputScanner for parsing SQL script and separating particular statements; does not depend on sqlite3_complete()
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
    70
15
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    71
		for (wchar_t ch; *input >> ch;) {
33
86ceb97db7de SqlInputScanner for parsing SQL script and separating particular statements; does not depend on sqlite3_complete()
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
    72
			if (scanner.append(ch)) {
58
a4907b207f0c remove superfluous c_str()
František Kučera <franta-hg@frantovo.cz>
parents: 48
diff changeset
    73
				*sql << scanner.getAndReset();
33
86ceb97db7de SqlInputScanner for parsing SQL script and separating particular statements; does not depend on sqlite3_complete()
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
    74
				return true;
86ceb97db7de SqlInputScanner for parsing SQL script and separating particular statements; does not depend on sqlite3_complete()
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
    75
			}
15
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    76
		}
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    77
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
    78
		// TODO: support comments at the end of the script (after last ;)
33
86ceb97db7de SqlInputScanner for parsing SQL script and separating particular statements; does not depend on sqlite3_complete()
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
    79
		string_t remainingSql = scanner.getAndReset();
15
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    80
		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"“");
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    81
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    82
		return false;
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    83
	}
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    84
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    85
	void processSqlInput(std::wistream* input) {
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    86
		if (input == nullptr) return;
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    87
		*input >> std::ws >> std::noskipws;
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    88
		for (std::wstringstream sql; readNextSqlStatement(input, &sql);) {
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
    89
			std::unique_ptr<PreparedStatement> prepared(connection->prepareStatement(sql.str()));
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
    90
			prepared->executeUpdate();
15
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    91
		}
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    92
	}
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    93
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
    94
	relpipe::writer::TypeId findType(string_t columnName, const Statement& statement, relpipe::writer::TypeId typeFromResultSet) {
24
884ece10575d add --type-cast to allow explicit specification of type for given output attributes
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    95
		for (TypeCast typeCast : statement.typeCasts) if (typeCast.name == columnName) return relationalWriter->toTypeId(typeCast.type);
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
    96
		return typeFromResultSet;
24
884ece10575d add --type-cast to allow explicit specification of type for given output attributes
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    97
	}
884ece10575d add --type-cast to allow explicit specification of type for given output attributes
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    98
3
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    99
	void processStatement(const Statement& statement) {
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   100
		std::shared_ptr<PreparedStatement> prepared(connection->prepareStatement(statement.sql));
3
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   101
		int parameterCount = statement.parameters.size();
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   102
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   103
		for (int i = 0; i < parameterCount; i++) {
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   104
			prepared->setString(i + 1, statement.parameters[i].value);
3
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   105
		}
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   106
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   107
		std::shared_ptr<ResultSet> resultSet(prepared->executeQuery());
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   108
		std::shared_ptr<ResultSet::MetaData> metaData(resultSet->getMetaData());
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   109
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   110
		auto columnCount = metaData->getColumnCount();
4
925b15fb5c63 generate relational outputs
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   111
		std::vector<relpipe::writer::AttributeMetadata> metadata;
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   112
		for (int columnNumber = 1; columnNumber <= columnCount; columnNumber++) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   113
			auto columnDescriptor = metaData->describeColumn(columnNumber);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   114
			metadata.push_back({columnDescriptor.name, findType(columnDescriptor.name, statement, columnDescriptor.type)});
24
884ece10575d add --type-cast to allow explicit specification of type for given output attributes
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
   115
		}
4
925b15fb5c63 generate relational outputs
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   116
		relationalWriter->startRelation(statement.relation, metadata, true);
3
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   117
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   118
		while (resultSet->next()) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   119
			for (int columnNumber = 1; columnNumber <= columnCount; columnNumber++) {
48
c83119110c7b support also boolean and integer data types, do not treat everything as mere strings
František Kučera <franta-hg@frantovo.cz>
parents: 47
diff changeset
   120
				// TODO: null values (when supported in the format)
c83119110c7b support also boolean and integer data types, do not treat everything as mere strings
František Kučera <franta-hg@frantovo.cz>
parents: 47
diff changeset
   121
				if (metadata[columnNumber - 1].typeId == relpipe::writer::TypeId::BOOLEAN) {
c83119110c7b support also boolean and integer data types, do not treat everything as mere strings
František Kučera <franta-hg@frantovo.cz>
parents: 47
diff changeset
   122
					auto booleanValue = resultSet->getBoolean(columnNumber);
c83119110c7b support also boolean and integer data types, do not treat everything as mere strings
František Kučera <franta-hg@frantovo.cz>
parents: 47
diff changeset
   123
					relationalWriter->writeAttribute(&booleanValue, typeid (booleanValue));
c83119110c7b support also boolean and integer data types, do not treat everything as mere strings
František Kučera <franta-hg@frantovo.cz>
parents: 47
diff changeset
   124
				} else if (metadata[columnNumber - 1].typeId == relpipe::writer::TypeId::INTEGER) {
c83119110c7b support also boolean and integer data types, do not treat everything as mere strings
František Kučera <franta-hg@frantovo.cz>
parents: 47
diff changeset
   125
					auto integerValue = resultSet->getInteger(columnNumber);
c83119110c7b support also boolean and integer data types, do not treat everything as mere strings
František Kučera <franta-hg@frantovo.cz>
parents: 47
diff changeset
   126
					relationalWriter->writeAttribute(&integerValue, typeid (integerValue));
c83119110c7b support also boolean and integer data types, do not treat everything as mere strings
František Kučera <franta-hg@frantovo.cz>
parents: 47
diff changeset
   127
				} else {
c83119110c7b support also boolean and integer data types, do not treat everything as mere strings
František Kučera <franta-hg@frantovo.cz>
parents: 47
diff changeset
   128
					relationalWriter->writeAttribute(resultSet->getString(columnNumber));
c83119110c7b support also boolean and integer data types, do not treat everything as mere strings
František Kučera <franta-hg@frantovo.cz>
parents: 47
diff changeset
   129
				}
3
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   130
			}
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   131
		}
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   132
	}
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   133
16
3c51a2c32c86 rename --dump to --copy + add option --copy-renamed + allow multiple copy/copy-renamed commands
František Kučera <franta-hg@frantovo.cz>
parents: 15
diff changeset
   134
	void copyRelations(const CopyRelations& copy) {
3c51a2c32c86 rename --dump to --copy + add option --copy-renamed + allow multiple copy/copy-renamed commands
František Kučera <franta-hg@frantovo.cz>
parents: 15
diff changeset
   135
		std::wregex pattern(copy.pattern);
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   136
		relpipe::writer::string_t userName = connection->getUserName();
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   137
		for (Connection::TablePrivilege tableMetaData : connection->getTablePrivileges()) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   138
			if (regex_match(tableMetaData.name, pattern) && tableMetaData.privilege == L"SELECT" && tableMetaData.grantee == userName) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   139
				// TODO: May we have multiple SELECT permissions for same table? Copy it only once.
14
eacacf060755 add --dump option: allow pass through of relation specified by a regular expression
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   140
				std::wstringstream select;
eacacf060755 add --dump option: allow pass through of relation specified by a regular expression
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   141
				select << L"SELECT * FROM ";
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   142
				if (tableMetaData.schema.size()) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   143
					// TODO: use qualified table name also for regex matching and for relation name
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   144
					writeIdentifier(select, tableMetaData.schema);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   145
					select << L".";
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   146
				}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   147
				writeIdentifier(select, tableMetaData.name);
14
eacacf060755 add --dump option: allow pass through of relation specified by a regular expression
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   148
eacacf060755 add --dump option: allow pass through of relation specified by a regular expression
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   149
				Statement statement;
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   150
				statement.relation = copy.replace ? regex_replace(tableMetaData.name, pattern, copy.replacement) : tableMetaData.name;
14
eacacf060755 add --dump option: allow pass through of relation specified by a regular expression
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   151
				statement.sql = select.str();
eacacf060755 add --dump option: allow pass through of relation specified by a regular expression
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   152
				processStatement(statement);
eacacf060755 add --dump option: allow pass through of relation specified by a regular expression
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   153
			}
eacacf060755 add --dump option: allow pass through of relation specified by a regular expression
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   154
		}
eacacf060755 add --dump option: allow pass through of relation specified by a regular expression
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   155
	}
eacacf060755 add --dump option: allow pass through of relation specified by a regular expression
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   156
6
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   157
	relpipe::writer::string_t toSQLType(relpipe::reader::TypeId typeId) {
48
c83119110c7b support also boolean and integer data types, do not treat everything as mere strings
František Kučera <franta-hg@frantovo.cz>
parents: 47
diff changeset
   158
		if (typeId == relpipe::reader::TypeId::BOOLEAN) return L"integer"; // TODO: bit type might fit better, but needs more testing (support in various DBMS and their drivers)
c83119110c7b support also boolean and integer data types, do not treat everything as mere strings
František Kučera <franta-hg@frantovo.cz>
parents: 47
diff changeset
   159
		else if (typeId == relpipe::reader::TypeId::INTEGER) return L"bigint";
6
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   160
		else return L"text";
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   161
	}
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   162
59
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   163
	bool isInsertable(const relpipe::writer::string_t& tableName) {
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   164
		for (Connection::TablePrivilege tp : connection->getTablePrivileges()) if (tp.name == tableName && tp.privilege == L"INSERT") return true;
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   165
		return false;
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   166
	}
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   167
6
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   168
	void writeIdentifier(std::wstringstream& output, relpipe::writer::string_t identifier) {
11
ccf19c7e7adf finish writeIdentifier() method
František Kučera <franta-hg@frantovo.cz>
parents: 10
diff changeset
   169
		output << L'"';
6
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   170
		for (auto & ch : identifier) {
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   171
			if (ch == L'"') output << L"\"\"";
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   172
			else output << ch;
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   173
		}
11
ccf19c7e7adf finish writeIdentifier() method
František Kučera <franta-hg@frantovo.cz>
parents: 10
diff changeset
   174
		output << L'"';
6
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   175
	}
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   176
59
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   177
	void createTable(const string_t& name, const std::vector<AttributeMetadata>& attributes) {
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   178
		std::wstringstream sql;
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   179
		sql << L"CREATE TABLE ";
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   180
		writeIdentifier(sql, name);
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   181
		sql << L" (\n";
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   182
		for (int i = 0; i < attributes.size(); i++) {
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   183
			sql << L"\t";
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   184
			writeIdentifier(sql, attributes[i].getAttributeName());
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   185
			sql << L" " << toSQLType(attributes[i].getTypeId());
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   186
			if (i < attributes.size() - 1) sql << L",\n";
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   187
		}
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   188
		sql << L"\n)";
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   189
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   190
		std::unique_ptr<PreparedStatement> createTable(connection->prepareStatement(sql.str()));
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   191
		createTable->executeUpdate();
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   192
	}
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   193
37
3de41719d7eb add options --data-source-name and --data-source-url for custom datasource; drop options --file and --file-keep
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   194
	Connection* getConnection() {
3de41719d7eb add options --data-source-name and --data-source-url for custom datasource; drop options --file and --file-keep
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   195
		if (configuration.dataSourceName.size()) return driverManager->getConnectionByDSN(configuration.dataSourceName);
47
428c278af4be rename option --data-source-url to --data-source-string
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   196
		else if (configuration.dataSourceString.size()) return driverManager->getConnectionByString(configuration.dataSourceString);
428c278af4be rename option --data-source-url to --data-source-string
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   197
		else return driverManager->getConnectionByString(L"Driver=SQLite3;Database=:memory:");
37
3de41719d7eb add options --data-source-name and --data-source-url for custom datasource; drop options --file and --file-keep
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   198
		// SQLite is default/fallback oprion
3de41719d7eb add options --data-source-name and --data-source-url for custom datasource; drop options --file and --file-keep
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   199
		// TODO: use environmental variable to allow setting a different default
3de41719d7eb add options --data-source-name and --data-source-url for custom datasource; drop options --file and --file-keep
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   200
	}
3de41719d7eb add options --data-source-name and --data-source-url for custom datasource; drop options --file and --file-keep
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   201
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   202
public:
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   203
34
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   204
	SqlHandler(writer::RelationalWriter* relationalWriter, DriverManager* driverManager, Configuration& configuration) : relationalWriter(relationalWriter), driverManager(driverManager), configuration(configuration) {
37
3de41719d7eb add options --data-source-name and --data-source-url for custom datasource; drop options --file and --file-keep
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   205
		connection.reset(getConnection());
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   206
		//connection->setAutoCommit(false);
1
eb7134dfdcc5 link to the sqlite3 library
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   207
	}
eb7134dfdcc5 link to the sqlite3 library
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   208
eb7134dfdcc5 link to the sqlite3 library
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   209
	virtual ~SqlHandler() {
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   210
	}
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   211
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   212
	void startRelation(string_t name, vector<AttributeMetadata> attributes) override {
7
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   213
		currentReaderMetadata = attributes;
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   214
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   215
		// CREATE TABLE:
59
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   216
		if (configuration.onDuplicateRelation == OnDuplicateRelation::Fail) {
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   217
			createTable(name, attributes); // duplicate will cause exception
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   218
		} else if (configuration.onDuplicateRelation == OnDuplicateRelation::Insert) {
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   219
			if (isInsertable(name)); // nothing needs to be created; we will just append new records to the existing table
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   220
			else createTable(name, attributes);
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   221
		} else {
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   222
			throw SqlException(L"Unsupported OnDuplicateRelation mode: " + std::to_wstring((int) configuration.onDuplicateRelation));
6
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   223
		}
7
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   224
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   225
		// prepare INSERT:
59
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   226
		std::wstringstream sql;
7
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   227
		sql << L"INSERT INTO ";
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   228
		writeIdentifier(sql, name);
59
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   229
		sql << L" (";
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   230
		for (int i = 0; i < attributes.size(); i++) {
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   231
			writeIdentifier(sql, attributes[i].getAttributeName());
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   232
			if (i < attributes.size() - 1) sql << L",";
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   233
		}
a1775ba6d056 optional UNION ALL: CLI option '--on-duplicate-relation' with values 'fail' and 'insert' (later more modes)
František Kučera <franta-hg@frantovo.cz>
parents: 58
diff changeset
   234
		sql << L") VALUES (";
7
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   235
		for (int i = 0; i < attributes.size(); i++) {
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   236
			sql << L"?";
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   237
			if (i < attributes.size() - 1) sql << L",";
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   238
		}
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   239
		sql << L")";
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   240
		currentInsert.reset(connection->prepareStatement(sql.str()));
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   241
	}
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   242
8
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   243
	void attribute(const void* value, const std::type_info& typeInfo) override {
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   244
		relpipe::reader::TypeId type = currentReaderMetadata[currentAttributeIndex].getTypeId();
7
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   245
		currentAttributeIndex++;
8
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   246
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   247
		switch (type) {
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   248
			case relpipe::reader::TypeId::BOOLEAN:
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   249
			{
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   250
				assert(typeInfo == typeid (boolean_t));
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   251
				auto* typedValue = static_cast<const boolean_t*> (value);
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   252
				currentInsert->setBoolean(currentAttributeIndex, *typedValue);
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   253
				break;
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   254
			}
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   255
			case relpipe::reader::TypeId::INTEGER:
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   256
			{
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   257
				assert(typeInfo == typeid (integer_t));
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   258
				auto* typedValue = static_cast<const integer_t*> (value);
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   259
				currentInsert->setInteger(currentAttributeIndex, *typedValue);
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   260
				break;
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   261
			}
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   262
			case relpipe::reader::TypeId::STRING:
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   263
			{
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   264
				assert(typeInfo == typeid (string_t));
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   265
				auto* typedValue = static_cast<const string_t*> (value);
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   266
				currentInsert->setString(currentAttributeIndex, *typedValue);
8
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   267
				break;
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   268
			}
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   269
			default:
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   270
				throw SqlException(L"Unsupported type in attribute()");
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   271
		}
12
0b38339b871b improve --keep-file option: default is auto = file will be kept, if it was present before the transformation
František Kučera <franta-hg@frantovo.cz>
parents: 11
diff changeset
   272
8
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   273
		if (currentAttributeIndex % currentReaderMetadata.size() == 0) {
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   274
			currentInsert->executeUpdate();
7
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   275
			currentInsert->reset();
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   276
			currentAttributeIndex = 0;
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   277
		}
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   278
	}
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   279
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   280
	void endOfPipe() {
15
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   281
		// process optional SQL input
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   282
		processSqlInput(configuration.sqlBeforeRelational);
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   283
12
0b38339b871b improve --keep-file option: default is auto = file will be kept, if it was present before the transformation
František Kučera <franta-hg@frantovo.cz>
parents: 11
diff changeset
   284
		// run the transformation – process all statements:
3
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   285
		for (const Statement& statement : configuration.statements) processStatement(statement);
6
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   286
15
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   287
		// process optional SQL input
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   288
		processSqlInput(configuration.sqlAfterRelational);
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   289
14
eacacf060755 add --dump option: allow pass through of relation specified by a regular expression
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   290
		// pass-through some relations:
16
3c51a2c32c86 rename --dump to --copy + add option --copy-renamed + allow multiple copy/copy-renamed commands
František Kučera <franta-hg@frantovo.cz>
parents: 15
diff changeset
   291
		for (const CopyRelations& copy : configuration.copyRelations) copyRelations(copy);
23
d3bfbce022aa support signed integers, negative numbers; binary format change: encode numbers as SLEB128
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   292
25
ec793cb3e686 rename DB methods to match standard API
František Kučera <franta-hg@frantovo.cz>
parents: 24
diff changeset
   293
		connection->commit();
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   294
	}
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   295
34
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   296
	static void listDataSources(writer::RelationalWriter* relationalWriter, DriverManager* driverManager) {
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   297
		relationalWriter->startRelation(L"data_source",{
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   298
			{L"name", writer::TypeId::STRING},
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   299
			{L"description", writer::TypeId::STRING}
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   300
		}, true);
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   301
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   302
		for (DriverManager::DataSource ds : driverManager->getDataSources()) {
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   303
			relationalWriter->writeAttribute(ds.name);
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   304
			relationalWriter->writeAttribute(ds.description);
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   305
		}
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   306
	}
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   307
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   308
};
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   309
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   310
}
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   311
}
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   312
}