src/DriverManager.cpp
author František Kučera <franta-hg@frantovo.cz>
Mon, 01 Jun 2020 17:23:27 +0200
branchv_0
changeset 41 4b2d46989f44
parent 40 0d67e271abb7
child 42 7f668a5a435b
permissions -rw-r--r--
improved exception handling: diagnostics of URL connection error
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
34
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     1
/**
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     2
 * Relational pipes
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     3
 * Copyright © 2020 František Kučera (Frantovo.cz, GlobalCode.info)
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     4
 *
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     5
 * This program is free software: you can redistribute it and/or modify
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
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
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     7
 * the Free Software Foundation, version 3.
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     8
 *
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     9
 * This program is distributed in the hope that it will be useful,
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    12
 * GNU General Public License for more details.
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    13
 *
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    14
 * You should have received a copy of the GNU General Public License
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    16
 */
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    17
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    18
#include <cstring>
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    19
#include <iostream>
34
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    20
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    21
#include <sql.h>
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    22
#include <sqlext.h>
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    23
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    24
#include "SqlException.h"
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    25
#include "DriverManager.h"
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    26
#include "OdbcCommon.h"
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    27
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    28
namespace relpipe {
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    29
namespace tr {
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    30
namespace sql {
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    31
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    32
DriverManager::DriverManager() {
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
    33
	environment = OdbcCommon::allocateHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE);
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
    34
	SQLRETURN result = SQLSetEnvAttr(environment, SQL_ATTR_ODBC_VERSION, (void*) SQL_OV_ODBC3, 0);
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
    35
	if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to set ODBC version", result, SQL_HANDLE_ENV, environment);
34
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    36
}
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    37
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    38
DriverManager::~DriverManager() {
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
    39
	OdbcCommon::freeHandle(SQL_HANDLE_ENV, environment);
34
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    40
}
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    41
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    42
std::vector<DriverManager::DataSource> DriverManager::getDataSources() {
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    43
	std::vector<DriverManager::DataSource> list;
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    44
	SQLCHAR name[SQL_MAX_DSN_LENGTH + 1];
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    45
	SQLCHAR description[255];
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    46
	memset(name, 0, sizeof (name));
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    47
	memset(description, 0, sizeof (description));
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    48
	SQLSMALLINT nameLength;
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    49
	SQLSMALLINT descriptionLength;
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    50
	while (true) {
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
    51
		SQLRETURN result = SQLDataSources(environment, SQL_FETCH_NEXT, name, sizeof (name), &nameLength, description, sizeof (description), &descriptionLength);
34
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    52
		// TODO: check nameLength and descriptionLength whether values were truncated?
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    53
		if (OdbcCommon::isSuccessful(result)) list.push_back({convertor.from_bytes((char*) name), convertor.from_bytes((char*) description)});
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    54
		else if (result == SQL_NO_DATA_FOUND) break;
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
    55
		else throw SqlException(L"Unable to list data sources: " + std::to_wstring(result), result, SQL_HANDLE_ENV, environment);
34
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    56
	}
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    57
	return list;
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    58
}
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    59
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    60
Connection* DriverManager::getConnectionByDSN(relpipe::reader::string_t dataSourceName, relpipe::reader::string_t userName, relpipe::reader::string_t password) {
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
    61
	SQLHDBC connection = OdbcCommon::allocateHandle(SQL_HANDLE_DBC, environment);
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    62
	std::string dataSourceNameBytes = convertor.to_bytes(dataSourceName);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    63
	std::string userNameBytes = convertor.to_bytes(userName);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    64
	std::string passwordBytes = convertor.to_bytes(password);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    65
	SQLRETURN result = SQLConnect(connection,
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    66
			(SQLCHAR*) dataSourceNameBytes.c_str(), SQL_NTS,
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    67
			(SQLCHAR*) userNameBytes.c_str(), SQL_NTS,
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
    68
			(SQLCHAR*) passwordBytes.c_str(), SQL_NTS);
40
0d67e271abb7 improved exception handling: diagnostics of DSN connection error
František Kučera <franta-hg@frantovo.cz>
parents: 38
diff changeset
    69
	if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to connect to DSN: " + dataSourceName, result, SQL_HANDLE_DBC, connection, true);
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    70
	return new Connection(connection);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    71
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    72
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
    73
Connection* DriverManager::getConnectionByURL(relpipe::reader::string_t connectionString) {
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
    74
	SQLHDBC connection = OdbcCommon::allocateHandle(SQL_HANDLE_DBC, environment);
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    75
	char completeConnectionString[SQL_MAX_OPTION_STRING_LENGTH];
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    76
	memset(completeConnectionString, 0, sizeof (completeConnectionString));
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    77
	SQLSMALLINT completeConnectionStringLength = -1;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    78
	SQLRETURN result = SQLDriverConnect(connection, nullptr,
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    79
			(SQLCHAR*) convertor.to_bytes(connectionString).c_str(), SQL_NTS,
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    80
			(SQLCHAR*) completeConnectionString, sizeof (completeConnectionString), &completeConnectionStringLength,
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    81
			SQL_DRIVER_NOPROMPT);
41
4b2d46989f44 improved exception handling: diagnostics of URL connection error
František Kučera <franta-hg@frantovo.cz>
parents: 40
diff changeset
    82
	if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to connect to URL: " + connectionString, result, SQL_HANDLE_DBC, connection, true);
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    83
	return new Connection(connection);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    84
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    85
34
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    86
}
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    87
}
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    88
}