src/PreparedStatement.cpp
author František Kučera <franta-hg@frantovo.cz>
Mon, 26 Oct 2020 00:00:35 +0100
branchv_0
changeset 53 cc6ffeba0fe5
parent 48 c83119110c7b
permissions -rw-r--r--
fix: support bigger numbers, SQL_BIGINT there was an overflow and some values resulted into negative ones. TODO: there is still a problem with big negative numbers – this needs to be addressed in relpipe-lib-writer/relpipe-lib-reader
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
28
498d5d3406c3 remove unused includes
František Kučera <franta-hg@frantovo.cz>
parents: 26
diff changeset
    18
#include <cstring>
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    19
#include <iostream>
28
498d5d3406c3 remove unused includes
František Kučera <franta-hg@frantovo.cz>
parents: 26
diff changeset
    20
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    21
#include <sql.h>
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
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: 28
diff changeset
    23
26
49919a60c747 move PreparedStatement class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    24
#include "PreparedStatement.h"
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    25
#include "ResultSet.h"
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    26
#include "OdbcCommon.h"
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    27
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    28
namespace relpipe {
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    29
namespace tr {
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    30
namespace sql {
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    31
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    32
PreparedStatement::PreparedStatement(void* stmt) : statement(stmt) {
26
49919a60c747 move PreparedStatement class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    33
}
3
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    34
26
49919a60c747 move PreparedStatement class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    35
PreparedStatement::~PreparedStatement() {
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    36
	OdbcCommon::freeHandle(SQL_HANDLE_STMT, statement);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    37
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    38
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    39
ResultSet* PreparedStatement::executeQuery() {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    40
	SQLRETURN result = SQLExecute(statement);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    41
	if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to execute (query) prepared statement", result, SQL_HANDLE_STMT, statement);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    42
	return new ResultSet(statement);
26
49919a60c747 move PreparedStatement class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    43
}
3
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    44
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    45
long PreparedStatement::executeUpdate() {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    46
	SQLRETURN result;
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    47
	SQLLEN count = 0; // returned e.g. on empty statement: ""
3
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    48
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    49
	result = SQLExecute(statement);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    50
	// PostgreSQL returns SUCCESS but SQLite returns SQL_NO_DATA_FOUND:
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    51
	if (OdbcCommon::isNotSuccessful(result) && result != SQL_NO_DATA_FOUND) throw SqlException(L"Unable to execute (update) prepared statement", result, SQL_HANDLE_STMT, statement);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    52
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    53
	result = SQLRowCount(statement, &count);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    54
	if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to get updated record count", result, SQL_HANDLE_STMT, statement);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    55
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    56
	return count;
26
49919a60c747 move PreparedStatement class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    57
}
3
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    58
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    59
void PreparedStatement::setBoolean(int parameterNumber, relpipe::reader::boolean_t value) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    60
	booleanParameters.emplace_back(value);
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: 36
diff changeset
    61
	SQLRETURN result = SQLBindParameter(statement, parameterNumber, SQL_PARAM_INPUT, SQL_C_BIT, SQL_INTEGER, 0, 0, &booleanParameters.back(), 0, nullptr);
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    62
	if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to set boolean parameter in prepared statement", result, SQL_HANDLE_STMT, statement);
26
49919a60c747 move PreparedStatement class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    63
}
25
ec793cb3e686 rename DB methods to match standard API
František Kučera <franta-hg@frantovo.cz>
parents: 24
diff changeset
    64
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    65
void PreparedStatement::setInteger(int parameterNumber, relpipe::reader::integer_t value) {
53
cc6ffeba0fe5 fix: support bigger numbers, SQL_BIGINT
František Kučera <franta-hg@frantovo.cz>
parents: 48
diff changeset
    66
	integerParameters.emplace_back(std::to_string(value));
cc6ffeba0fe5 fix: support bigger numbers, SQL_BIGINT
František Kučera <franta-hg@frantovo.cz>
parents: 48
diff changeset
    67
	SQLRETURN result = SQLBindParameter(statement, parameterNumber, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_BIGINT, 0, 0, (void *) integerParameters.back().c_str(), 0, nullptr);
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    68
	if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to set integer parameter in prepared statement", result, SQL_HANDLE_STMT, statement);
26
49919a60c747 move PreparedStatement class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    69
}
3
0b932e05aa9f sqlite wrapper objects + execute query
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    70
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    71
void PreparedStatement::setString(int parameterNumber, relpipe::reader::string_t value) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    72
	std::string valueBytes = convertor.to_bytes(value);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    73
	stringParameters.emplace_back(std::make_pair(valueBytes, valueBytes.size()));
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    74
	SQLRETURN result = SQLBindParameter(statement, parameterNumber, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 0, 0, (void *) stringParameters.back().first.c_str(), 0, &stringParameters.back().second);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    75
	if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to set string parameter in prepared statement", result, SQL_HANDLE_STMT, statement);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    76
}
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    77
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    78
void PreparedStatement::setNull(int parameterNumber) {
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    79
	throw SqlException(L"Use ODBC: setNull()");
26
49919a60c747 move PreparedStatement class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    80
}
15
0ecde5272f8e process SQL input in the relpipe-in-sql mode
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    81
26
49919a60c747 move PreparedStatement class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    82
void PreparedStatement::reset() {
36
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    83
	// TODO: do also SQL_UNBIND if column binding is used
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    84
	SQLRETURN result = SQLFreeStmt(statement, SQL_RESET_PARAMS);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    85
	if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to reset prepared statement", result, SQL_HANDLE_STMT, statement);
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    86
	booleanParameters.clear();
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    87
	integerParameters.clear();
91cb012d779a use ODBC, avoid direct dependency on SQLite
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
    88
	stringParameters.clear();
26
49919a60c747 move PreparedStatement class to separate .h and .cpp files
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    89
}
0
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    90
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    91
}
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    92
}
c205f5d06418 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    93
}