src/ResultSet.cpp
author František Kučera <franta-hg@frantovo.cz>
Tue, 02 Jun 2020 23:31:55 +0200
branchv_0
changeset 44 ec9694f3b343
parent 43 7f396cdb9628
child 48 c83119110c7b
permissions -rw-r--r--
faulty SQLGetDiagRec() call, unicode error, temporary workaround
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     1
/**
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     2
 * Relational pipes
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     3
 * Copyright © 2020 František Kučera (Frantovo.cz, GlobalCode.info)
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     4
 *
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     5
 * This program is free software: you can redistribute it and/or modify
91cb012d779a use ODBC, avoid direct dependency on SQLite
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
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     7
 * the Free Software Foundation, version 3.
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     8
 *
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     9
 * This program is distributed in the hope that it will be useful,
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    12
 * GNU General Public License for more details.
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    13
 *
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    14
 * You should have received a copy of the GNU General Public License
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    16
 */
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    17
43
7f396cdb9628 getTablePrivileges() finds columns by names instead of numbers
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
    18
#include <sstream>
7f396cdb9628 getTablePrivileges() finds columns by names instead of numbers
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
    19
#include <algorithm>
7f396cdb9628 getTablePrivileges() finds columns by names instead of numbers
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
    20
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    21
#include <sql.h>
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    22
#include <sqlext.h>
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    23
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    24
#include "ResultSet.h"
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    25
#include "OdbcCommon.h"
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    26
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    27
namespace relpipe {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    28
namespace tr {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    29
namespace sql {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    30
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    31
ResultSet::ResultSet(void* statement) : statement(statement) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    32
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    33
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    34
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    35
ResultSet::~ResultSet() {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    36
	// freeHandle() is called in ~PreparedStatement()
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    37
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    38
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    39
bool ResultSet::next() {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    40
	SQLRETURN result = SQLFetch(statement);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    41
	if (OdbcCommon::isSuccessful(result)) return true;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    42
	else if (result == SQL_NO_DATA) return false;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    43
	else throw SqlException(L"Unable to fetch next record", result, SQL_HANDLE_STMT, statement);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    44
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    45
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    46
relpipe::writer::boolean_t ResultSet::getBoolean(unsigned short columnNumber, bool* isNull) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    47
	throw SqlException(L"not yet implemented: getBoolean()");
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    48
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    49
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    50
relpipe::writer::integer_t ResultSet::getInteger(unsigned short columnNumber, bool* isNull) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    51
	throw SqlException(L"not yet implemented: getInteger()");
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    52
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    53
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    54
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    55
relpipe::writer::string_t ResultSet::getString(unsigned short columnNumber, bool* isNull) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    56
	SQLCHAR uselessBuffer; // just to get stringLength – ODBC does not eat nullptr
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    57
	SQLLEN stringLength = -1;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    58
	SQLRETURN result = SQLGetData(statement, columnNumber, SQL_C_CHAR, &uselessBuffer, 0, &stringLength);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    59
	if (isNull) *isNull = stringLength == SQL_NULL_DATA;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    60
	if (stringLength == SQL_NULL_DATA) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    61
		return L"";
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    62
	} else if (stringLength >= 0) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    63
		std::string value;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    64
		value.reserve(stringLength);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    65
		result = SQLGetData(statement, columnNumber, SQL_C_CHAR, (SQLCHAR*) value.c_str(), value.capacity() + 1, &stringLength); // trailing null byte = + 1
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    66
		if (OdbcCommon::isSuccessful(result)) return convertor.from_bytes(value.c_str());
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    67
	}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    68
	throw SqlException(L"Unable to get string value", result, SQL_HANDLE_STMT, statement);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    69
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    70
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    71
ResultSet::MetaData* ResultSet::getMetaData() {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    72
	SQLRETURN result;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    73
	SQLSMALLINT columnCount;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    74
	std::vector<ResultSet::MetaData::ColumnDescriptor> columnDescriptors;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    75
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    76
	result = SQLNumResultCols(statement, &columnCount);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    77
	if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to get column count", result, SQL_HANDLE_STMT, statement);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    78
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    79
	for (SQLSMALLINT columnNumber = 1; columnNumber <= columnCount; columnNumber++) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    80
		ResultSet::MetaData::ColumnDescriptor columnDescriptor;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    81
		std::string nameBuffer; // TODO: use rather vector<char> instead of string.c_str()?
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    82
		nameBuffer.reserve(100); // TODO: max column name length?
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    83
		SQLSMALLINT nameLength;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    84
		SQLSMALLINT dataType;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    85
		SQLULEN columnSize;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    86
		SQLSMALLINT decimalDigits;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    87
		SQLSMALLINT nullable;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    88
		result = SQLDescribeCol(statement, columnNumber, (SQLCHAR*) nameBuffer.c_str(), nameBuffer.capacity(), &nameLength, &dataType, &columnSize, &decimalDigits, &nullable);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    89
		if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable describe column", result, SQL_HANDLE_STMT, statement);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    90
		columnDescriptor.name = convertor.from_bytes(nameBuffer.c_str());
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    91
		//columnDescriptor.type = … // FIXME: support also other types than string
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    92
		columnDescriptors.emplace_back(columnDescriptor);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    93
	}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    94
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    95
	return new MetaData(columnCount, columnDescriptors);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    96
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    97
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    98
ResultSet::MetaData::MetaData(unsigned short columnCount, std::vector<ColumnDescriptor> columnDescriptors) : columnCount(columnCount), columnDescriptors(columnDescriptors) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    99
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   100
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   101
ResultSet::MetaData::~MetaData() {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   102
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   103
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   104
unsigned short ResultSet::MetaData::getColumnCount() {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   105
	return columnCount;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   106
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   107
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   108
ResultSet::MetaData::ColumnDescriptor ResultSet::MetaData::describeColumn(unsigned short columnNumber) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   109
	if (columnNumber >= 1 && columnNumber <= columnCount) return columnDescriptors[columnNumber - 1];
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   110
	else throw SqlException(L"Unable to describe column " + std::to_wstring(columnNumber) + L", out of bounds, column count is " + std::to_wstring(columnCount));
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   111
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   112
43
7f396cdb9628 getTablePrivileges() finds columns by names instead of numbers
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   113
SQLUSMALLINT ResultSet::MetaData::getColumnNumber(relpipe::writer::string_t columnName) {
7f396cdb9628 getTablePrivileges() finds columns by names instead of numbers
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   114
	// TODO: also case insensitive mode
7f396cdb9628 getTablePrivileges() finds columns by names instead of numbers
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   115
	for (SQLUSMALLINT i = 0; i < columnDescriptors.size(); i++) {
7f396cdb9628 getTablePrivileges() finds columns by names instead of numbers
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   116
		if (columnDescriptors[i].name == columnName) return i + 1;
7f396cdb9628 getTablePrivileges() finds columns by names instead of numbers
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   117
	}
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   118
43
7f396cdb9628 getTablePrivileges() finds columns by names instead of numbers
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   119
	std::wstringstream errorMessage;
7f396cdb9628 getTablePrivileges() finds columns by names instead of numbers
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   120
	errorMessage << L"Unable to find column with name „" << columnName.c_str() << L"“ Availalable columns are: ";
7f396cdb9628 getTablePrivileges() finds columns by names instead of numbers
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   121
	for (MetaData::ColumnDescriptor cd : columnDescriptors) errorMessage << L"„" << cd.name.c_str() << L"“ ";
7f396cdb9628 getTablePrivileges() finds columns by names instead of numbers
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   122
	throw SqlException(errorMessage.str());
7f396cdb9628 getTablePrivileges() finds columns by names instead of numbers
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   123
}
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   124
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   125
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   126
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   127
}