author | František Kučera <franta-hg@frantovo.cz> |
Tue, 02 Jun 2020 18:40:20 +0200 | |
branch | v_0 |
changeset 42 | 7f668a5a435b |
parent 39 | b4af13653313 |
child 43 | 7f396cdb9628 |
permissions | -rw-r--r-- |
0 | 1 |
/** |
2 |
* Relational pipes |
|
3 |
* Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info) |
|
4 |
* |
|
5 |
* This program is free software: you can redistribute it and/or modify |
|
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 | 8 |
* |
9 |
* This program is distributed in the hope that it will be useful, |
|
10 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 |
* GNU General Public License for more details. |
|
13 |
* |
|
14 |
* You should have received a copy of the GNU General Public License |
|
15 |
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 |
*/ |
|
17 |
||
36
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
18 |
#include <memory> |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
19 |
#include <iostream> |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
20 |
|
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
21 |
#include <sql.h> |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
22 |
#include <sqlext.h> |
29
b0ef1e1dc9c8
keep sqlite3.h dependency in Connection.cpp and PreparedStatement.cpp only
František Kučera <franta-hg@frantovo.cz>
parents:
27
diff
changeset
|
23 |
|
27
9441a517fa1f
move Connection class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents:
26
diff
changeset
|
24 |
#include "Connection.h" |
36
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
25 |
#include "OdbcCommon.h" |
0 | 26 |
|
27 |
namespace relpipe { |
|
28 |
namespace tr { |
|
29 |
namespace sql { |
|
30 |
||
36
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
31 |
Connection::Connection(void* db) : connection(db) { |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
32 |
// TODO: transaction control |
27
9441a517fa1f
move Connection class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents:
26
diff
changeset
|
33 |
} |
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
|
34 |
|
27
9441a517fa1f
move Connection class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents:
26
diff
changeset
|
35 |
Connection::~Connection() { |
36
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
36 |
SQLRETURN result = SQLDisconnect(connection); |
38
a871779a4e3c
improved exception handling
František Kučera <franta-hg@frantovo.cz>
parents:
37
diff
changeset
|
37 |
// TODO: log warning if disconnection failed? |
36
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
38 |
OdbcCommon::freeHandle(SQL_HANDLE_DBC, connection); |
27
9441a517fa1f
move Connection class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents:
26
diff
changeset
|
39 |
} |
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
|
40 |
|
36
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
41 |
PreparedStatement* Connection::prepareStatement(relpipe::reader::string_t sql) { |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
42 |
SQLHSTMT statement = OdbcCommon::allocateHandle(SQL_HANDLE_STMT, connection); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
43 |
SQLRETURN result = SQLPrepare(statement, (SQLCHAR*) convertor.to_bytes(sql).c_str(), SQL_NTS); |
39
b4af13653313
improved exception handling: diagnostics of prepare statement error
František Kučera <franta-hg@frantovo.cz>
parents:
38
diff
changeset
|
44 |
if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to prepare statement", result, SQL_HANDLE_STMT, statement, true); |
36
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
45 |
return new PreparedStatement(statement); |
27
9441a517fa1f
move Connection class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents:
26
diff
changeset
|
46 |
} |
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
|
47 |
|
27
9441a517fa1f
move Connection class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents:
26
diff
changeset
|
48 |
bool Connection::getAutoCommit() { |
36
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
49 |
// TODO: transaction control |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
50 |
return false; |
27
9441a517fa1f
move Connection class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents:
26
diff
changeset
|
51 |
} |
7 | 52 |
|
27
9441a517fa1f
move Connection class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents:
26
diff
changeset
|
53 |
void Connection::setAutoCommit(bool autoCommit) { |
36
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
54 |
// TODO: transaction control |
27
9441a517fa1f
move Connection class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents:
26
diff
changeset
|
55 |
} |
8 | 56 |
|
27
9441a517fa1f
move Connection class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents:
26
diff
changeset
|
57 |
void Connection::commit() { |
36
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
58 |
SQLRETURN result = SQLEndTran(SQL_HANDLE_DBC, connection, SQL_COMMIT); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
59 |
if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to COMMIT: " + std::to_wstring(result)); |
27
9441a517fa1f
move Connection class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents:
26
diff
changeset
|
60 |
} |
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
|
61 |
|
27
9441a517fa1f
move Connection class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents:
26
diff
changeset
|
62 |
void Connection::rollback() { |
36
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
63 |
SQLRETURN result = SQLEndTran(SQL_HANDLE_DBC, connection, SQL_ROLLBACK); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
64 |
if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to ROLLBACK: " + std::to_wstring(result)); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
65 |
} |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
66 |
|
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
67 |
std::vector<Connection::TableMetaData> Connection::getTables() { |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
68 |
std::vector<TableMetaData> tables; |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
69 |
SQLHSTMT statementHandle = OdbcCommon::allocateHandle(SQL_HANDLE_STMT, connection); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
70 |
SQLRETURN result = SQLTables(statementHandle, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
71 |
if (OdbcCommon::isNotSuccessful(result)) { |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
72 |
OdbcCommon::freeHandle(SQL_HANDLE_STMT, statementHandle); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
73 |
throw SqlException(L"Unable get tables (prepare)", result, SQL_HANDLE_DBC, connection); // TODO: SQL_HANDLE_STMT? |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
74 |
} |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
75 |
ResultSet resultSet(statementHandle); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
76 |
while (resultSet.next()) { |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
77 |
TableMetaData tm; |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
78 |
tm.catalog = resultSet.getString(1); // FIXME: column name: table_cat |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
79 |
tm.schema = resultSet.getString(2); // FIXME: column name: table_schem |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
80 |
tm.name = resultSet.getString(3); // FIXME: column name: table_name |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
81 |
tm.type = resultSet.getString(4); // FIXME: column name: table_type |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
82 |
tables.emplace_back(tm); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
83 |
} |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
84 |
|
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
85 |
return tables; |
27
9441a517fa1f
move Connection class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents:
26
diff
changeset
|
86 |
} |
0 | 87 |
|
36
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
88 |
std::vector<Connection::TablePrivilege> Connection::getTablePrivileges() { |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
89 |
std::vector<TablePrivilege> tables; |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
90 |
SQLHSTMT statementHandle = OdbcCommon::allocateHandle(SQL_HANDLE_STMT, connection); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
91 |
SQLRETURN result = SQLTablePrivileges(statementHandle, nullptr, 0, nullptr, 0, nullptr, 0); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
92 |
if (OdbcCommon::isNotSuccessful(result)) { |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
93 |
OdbcCommon::freeHandle(SQL_HANDLE_STMT, statementHandle); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
94 |
throw SqlException(L"Unable get tables (prepare)", result, SQL_HANDLE_DBC, connection); // TODO: SQL_HANDLE_STMT? |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
95 |
} |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
96 |
ResultSet resultSet(statementHandle); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
97 |
while (resultSet.next()) { |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
98 |
TablePrivilege tp; |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
99 |
tp.catalog = resultSet.getString(1); // FIXME: column name: table_cat |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
100 |
tp.schema = resultSet.getString(2); // FIXME: column name: table_schem |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
101 |
tp.name = resultSet.getString(3); // FIXME: column name: table_name |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
102 |
tp.grantor = resultSet.getString(4); // FIXME: column name: grantor |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
103 |
tp.grantee = resultSet.getString(5); // FIXME: column name: grantee |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
104 |
tp.privilege = resultSet.getString(6); // FIXME: column name: privilege |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
105 |
tp.isGrantable = resultSet.getString(7) == L"YES"; // FIXME: column name: is_grantable |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
106 |
tables.emplace_back(tp); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
107 |
} |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
108 |
|
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
109 |
return tables; |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
110 |
} |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
111 |
|
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
112 |
relpipe::reader::string_t Connection::getUserName() { |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
113 |
std::vector<char> buffer(100); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
114 |
SQLSMALLINT stringLength; |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
115 |
SQLRETURN result = SQLGetInfo(connection, SQL_USER_NAME, buffer.data(), buffer.size(), &stringLength); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
116 |
if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to get user name: " + std::to_wstring(result)); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
117 |
if (stringLength >= buffer.size()) throw SqlException(L"Unable to get user name: too long" + std::to_wstring(stringLength)); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
118 |
return convertor.from_bytes(buffer.data(), buffer.data() + stringLength); |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
119 |
} |
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
120 |
|
91cb012d779a
use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
32
diff
changeset
|
121 |
|
0 | 122 |
} |
123 |
} |
|
124 |
} |