src/SqlHandler.h
author František Kučera <franta-hg@frantovo.cz>
Thu, 04 Jun 2020 13:24:17 +0200
branchv_0
changeset 48 c83119110c7b
parent 47 428c278af4be
child 58 a4907b207f0c
permissions -rw-r--r--
support also boolean and integer data types, do not treat everything as mere strings
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)) {
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
    73
				*sql << scanner.getAndReset().c_str();
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
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   163
	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
   164
		output << L'"';
6
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   165
		for (auto & ch : identifier) {
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   166
			if (ch == L'"') output << L"\"\"";
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   167
			else output << ch;
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   168
		}
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
	}
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   171
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
   172
	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
   173
		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
   174
		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
   175
		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
   176
		// 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
   177
		// 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
   178
	}
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
   179
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   180
public:
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   181
34
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   182
	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
   183
		connection.reset(getConnection());
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   184
		//connection->setAutoCommit(false);
1
eb7134dfdcc5 link to the sqlite3 library
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   185
	}
eb7134dfdcc5 link to the sqlite3 library
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   186
eb7134dfdcc5 link to the sqlite3 library
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   187
	virtual ~SqlHandler() {
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   188
	}
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   189
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   190
	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
   191
		currentReaderMetadata = attributes;
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   192
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   193
		// CREATE TABLE:
6
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   194
		std::wstringstream sql;
7
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   195
		// TODO: if already exist just append new columns
6
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   196
		sql << L"CREATE TABLE ";
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   197
		writeIdentifier(sql, name);
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   198
		sql << L" (\n";
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   199
		for (int i = 0; i < attributes.size(); i++) {
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   200
			sql << L"\t";
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   201
			writeIdentifier(sql, attributes[i].getAttributeName());
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   202
			sql << L" " << toSQLType(attributes[i].getTypeId());
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   203
			if (i < attributes.size() - 1) sql << L",\n";
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   204
		}
32b4293307f4 create table for each relation
František Kučera <franta-hg@frantovo.cz>
parents: 5
diff changeset
   205
		sql << L"\n)";
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   206
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   207
		std::unique_ptr<PreparedStatement> createTable(connection->prepareStatement(sql.str()));
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   208
		createTable->executeUpdate();
7
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   209
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   210
		// prepare INSERT:
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   211
		sql = wstringstream();
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   212
		sql << L"INSERT INTO ";
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   213
		writeIdentifier(sql, name);
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   214
		sql << L" VALUES (";
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   215
		for (int i = 0; i < attributes.size(); i++) {
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   216
			sql << L"?";
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   217
			if (i < attributes.size() - 1) sql << L",";
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   218
		}
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   219
		sql << L")";
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   220
		currentInsert.reset(connection->prepareStatement(sql.str()));
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   221
	}
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   222
8
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   223
	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
   224
		relpipe::reader::TypeId type = currentReaderMetadata[currentAttributeIndex].getTypeId();
7
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   225
		currentAttributeIndex++;
8
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   226
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   227
		switch (type) {
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   228
			case relpipe::reader::TypeId::BOOLEAN:
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   229
			{
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   230
				assert(typeInfo == typeid (boolean_t));
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   231
				auto* typedValue = static_cast<const boolean_t*> (value);
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   232
				currentInsert->setBoolean(currentAttributeIndex, *typedValue);
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   233
				break;
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   234
			}
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   235
			case relpipe::reader::TypeId::INTEGER:
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   236
			{
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   237
				assert(typeInfo == typeid (integer_t));
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   238
				auto* typedValue = static_cast<const integer_t*> (value);
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   239
				currentInsert->setInteger(currentAttributeIndex, *typedValue);
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   240
				break;
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   241
			}
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   242
			case relpipe::reader::TypeId::STRING:
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   243
			{
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   244
				assert(typeInfo == typeid (string_t));
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   245
				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
   246
				currentInsert->setString(currentAttributeIndex, *typedValue);
8
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   247
				break;
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   248
			}
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   249
			default:
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   250
				throw SqlException(L"Unsupported type in attribute()");
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   251
		}
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
   252
8
3e076cc76c89 data types
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   253
		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
   254
			currentInsert->executeUpdate();
7
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   255
			currentInsert->reset();
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   256
			currentAttributeIndex = 0;
9119b29d1e7c insert records
František Kučera <franta-hg@frantovo.cz>
parents: 6
diff changeset
   257
		}
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   258
	}
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   259
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   260
	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
   261
		// 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
   262
		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
   263
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
   264
		// 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
   265
		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
   266
15
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   267
		// 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
   268
		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
   269
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
   270
		// 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
   271
		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
   272
25
ec793cb3e686 rename DB methods to match standard API
František Kučera <franta-hg@frantovo.cz>
parents: 24
diff changeset
   273
		connection->commit();
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   274
	}
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   275
34
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   276
	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
   277
		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
   278
			{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
   279
			{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
   280
		}, true);
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   281
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   282
		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
   283
			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
   284
			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
   285
		}
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   286
	}
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   287
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   288
};
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   289
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   290
}
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   291
}
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   292
}