src/DriverManager.cpp
author František Kučera <franta-hg@frantovo.cz>
Thu, 04 Jun 2020 00:46:00 +0200
branchv_0
changeset 47 428c278af4be
parent 42 7f668a5a435b
permissions -rw-r--r--
rename option --data-source-url to --data-source-string In some implementations like JDBC, the connection string is URL, but in ODBC the string is not formally URL, so it is better to use more general term „data source string“ instead of URL. - data source name (DSN) = name of a pre-configured database connection that should be looked-up in configuration and used - data source string (connection string) = arbitrary string containing (in certain encoding which might and might not be URL) all needed parameters (e.g. server name + port + user name + password) Name and string might sometimes be also combined: in ODBC we can e.g. connect to a string: DSN=relpipe;someParameter=foo;someOther=bar which will lookup configuration for the „relpipe“ data source and will combine it with given parameters.
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;
42
7f668a5a435b getDataSources() can be called multiple-times, use SQL_FETCH_FIRST and SQL_FETCH_NEXT
František Kučera <franta-hg@frantovo.cz>
parents: 41
diff changeset
    50
	for (int i = 0; true; i++) {
7f668a5a435b getDataSources() can be called multiple-times, use SQL_FETCH_FIRST and SQL_FETCH_NEXT
František Kučera <franta-hg@frantovo.cz>
parents: 41
diff changeset
    51
		SQLRETURN result = SQLDataSources(environment, i == 0 ? SQL_FETCH_FIRST : SQL_FETCH_NEXT,
7f668a5a435b getDataSources() can be called multiple-times, use SQL_FETCH_FIRST and SQL_FETCH_NEXT
František Kučera <franta-hg@frantovo.cz>
parents: 41
diff changeset
    52
				name, sizeof (name), &nameLength,
7f668a5a435b getDataSources() can be called multiple-times, use SQL_FETCH_FIRST and SQL_FETCH_NEXT
František Kučera <franta-hg@frantovo.cz>
parents: 41
diff changeset
    53
				description, sizeof (description), &descriptionLength);
7f668a5a435b getDataSources() can be called multiple-times, use SQL_FETCH_FIRST and SQL_FETCH_NEXT
František Kučera <franta-hg@frantovo.cz>
parents: 41
diff changeset
    54
		// TODO: description field actually contains the driver name – see comments in unixODBC file: DriverManager/SQLDataSources.c
34
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    55
		// 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
    56
		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
    57
		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
    58
		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
    59
	}
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    60
	return list;
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    61
}
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    62
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    63
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
    64
	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
    65
	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
    66
	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
    67
	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
    68
	SQLRETURN result = SQLConnect(connection,
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    69
			(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
    70
			(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
    71
			(SQLCHAR*) passwordBytes.c_str(), SQL_NTS);
47
428c278af4be rename option --data-source-url to --data-source-string
František Kučera <franta-hg@frantovo.cz>
parents: 42
diff changeset
    72
	if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to connect through 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
    73
	return new Connection(connection);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    74
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    75
47
428c278af4be rename option --data-source-url to --data-source-string
František Kučera <franta-hg@frantovo.cz>
parents: 42
diff changeset
    76
Connection* DriverManager::getConnectionByString(relpipe::reader::string_t connectionString) {
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
    77
	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
    78
	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
    79
	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
    80
	SQLSMALLINT completeConnectionStringLength = -1;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    81
	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
    82
			(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
    83
			(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
    84
			SQL_DRIVER_NOPROMPT);
47
428c278af4be rename option --data-source-url to --data-source-string
František Kučera <franta-hg@frantovo.cz>
parents: 42
diff changeset
    85
	if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to connect through string: " + 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
    86
	return new Connection(connection);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    87
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    88
34
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    89
}
24c05e69d68f add ODBC library and --list-data-sources mode (DSN)
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    90
}
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
    91
}