diff --git a/modules/database/prepared_statement.cpp b/modules/database/prepared_statement.cpp index d89a96fdf..e61f754a8 100644 --- a/modules/database/prepared_statement.cpp +++ b/modules/database/prepared_statement.cpp @@ -40,19 +40,10 @@ void PreparedStatement::set_sql(const String &p_sql) { _sql = p_sql; } -Error PreparedStatement::finalize() { - return FAILED; -} - -Ref PreparedStatement::get_connection() const { - return _connection; -} - PreparedStatement::PreparedStatement() { } PreparedStatement::~PreparedStatement() { - finalize(); } void PreparedStatement::_bind_methods() { @@ -98,7 +89,6 @@ void PreparedStatement::_bind_methods() { ClassDB::bind_method(D_METHOD("column_int", "index"), &PreparedStatement::column_int); ClassDB::bind_method(D_METHOD("column_int64", "index"), &PreparedStatement::column_int64); ClassDB::bind_method(D_METHOD("column_text", "index"), &PreparedStatement::column_text); - ClassDB::bind_method(D_METHOD("column_bytes", "index"), &PreparedStatement::column_bytes); ClassDB::bind_method(D_METHOD("column_value", "index"), &PreparedStatement::column_value); ClassDB::bind_method(D_METHOD("column_count"), &PreparedStatement::column_count); @@ -111,7 +101,18 @@ void PreparedStatement::_bind_methods() { ClassDB::bind_method(D_METHOD("reset"), &PreparedStatement::reset); ClassDB::bind_method(D_METHOD("finalize"), &PreparedStatement::finalize); - ClassDB::bind_method(D_METHOD("is_busy"), &PreparedStatement::is_busy); - ClassDB::bind_method(D_METHOD("get_connection"), &PreparedStatement::get_connection); + + BIND_ENUM_CONSTANT(TYPE_NULL); + BIND_ENUM_CONSTANT(TYPE_BLOB); + BIND_ENUM_CONSTANT(TYPE_FLOAT); + BIND_ENUM_CONSTANT(TYPE_DOUBLE); + BIND_ENUM_CONSTANT(TYPE_INT); + BIND_ENUM_CONSTANT(TYPE_INT64); + BIND_ENUM_CONSTANT(TYPE_TEXT); + BIND_ENUM_CONSTANT(TYPE_VARCHAR); + BIND_ENUM_CONSTANT(TYPE_VALUE); + BIND_ENUM_CONSTANT(TYPE_BYTES); + BIND_ENUM_CONSTANT(TYPE_TYPE); + BIND_ENUM_CONSTANT(TYPE_UNKNOWN); } diff --git a/modules/database/prepared_statement.h b/modules/database/prepared_statement.h index a612b7ba5..681f21bbf 100644 --- a/modules/database/prepared_statement.h +++ b/modules/database/prepared_statement.h @@ -42,6 +42,21 @@ class PreparedStatement : public Reference { GDCLASS(PreparedStatement, Reference); public: + enum Type { + TYPE_NULL, + TYPE_BLOB, + TYPE_FLOAT, + TYPE_DOUBLE, + TYPE_INT, + TYPE_INT64, + TYPE_TEXT, + TYPE_VARCHAR, + TYPE_VALUE, + TYPE_BYTES, + TYPE_TYPE, + TYPE_UNKNOWN, + }; + String get_sql(); void set_sql(const String &p_sql); @@ -68,8 +83,8 @@ public: // Querying virtual String column_name(const int p_index) = 0; - virtual Error column_decltype(const int p_index) = 0; - virtual Error column_type(const int p_index) = 0; + virtual String column_decltype(const int p_index) = 0; + virtual Type column_type(const int p_index) = 0; virtual String column_database_name(const int p_index) = 0; virtual String column_table_name(const int p_index) = 0; @@ -81,7 +96,6 @@ public: virtual int64_t column_int(const int p_index) = 0; virtual int column_int64(const int p_index) = 0; virtual String column_text(const int p_index) = 0; - virtual Vector column_bytes(const int p_index) = 0; virtual Variant column_value(const int p_index) = 0; virtual int column_count() = 0; @@ -91,11 +105,9 @@ public: virtual Error step() = 0; virtual int data_count() = 0; virtual Error reset() = 0; - virtual Error finalize(); + virtual Error finalize() = 0; - virtual bool is_busy() = 0; - - Ref get_connection() const; + virtual Ref get_connection() const = 0; PreparedStatement(); virtual ~PreparedStatement(); @@ -104,8 +116,8 @@ protected: static void _bind_methods(); String _sql; - - Ref _connection; }; +VARIANT_ENUM_CAST(PreparedStatement::Type); + #endif diff --git a/modules/database_sqlite/SCsub b/modules/database_sqlite/SCsub index c18c3a241..8e6bbaf30 100644 --- a/modules/database_sqlite/SCsub +++ b/modules/database_sqlite/SCsub @@ -29,6 +29,7 @@ sources = [ "sqlite3_query_builder.cpp", "sqlite3_query_result.cpp", "sqlite3_table_builder.cpp", + "sqlite3_prepared_statement.cpp", ] if ARGUMENTS.get('custom_modules_shared', 'no') == 'yes': diff --git a/modules/database_sqlite/sqlite3_connection.cpp b/modules/database_sqlite/sqlite3_connection.cpp index f4775260c..c243ea4fc 100644 --- a/modules/database_sqlite/sqlite3_connection.cpp +++ b/modules/database_sqlite/sqlite3_connection.cpp @@ -2,6 +2,7 @@ #include "core/string/print_string.h" #include "core/string/ustring.h" +#include "sqlite3_prepared_statement.h" #include "sqlite3_query_builder.h" #include "sqlite3_query_result.h" #include "sqlite3_table_builder.h" @@ -26,6 +27,14 @@ Ref SQLite3DatabaseConnection::get_table_builder() { return b; } +Ref SQLite3DatabaseConnection::create_prepared_statement() { + Ref b; + b.instance(); + b->_connection.reference_ptr(this); + + return b; +} + Error SQLite3DatabaseConnection::database_connect(const String &connection_str) { int ret = sqlite3_config(SQLITE_CONFIG_SERIALIZED); diff --git a/modules/database_sqlite/sqlite3_connection.h b/modules/database_sqlite/sqlite3_connection.h index c00a4274d..dd5904d90 100644 --- a/modules/database_sqlite/sqlite3_connection.h +++ b/modules/database_sqlite/sqlite3_connection.h @@ -13,12 +13,15 @@ struct sqlite3; class SQLite3DatabaseConnection : public DatabaseConnection { public: + friend class SQLite3PreparedStatement; + Error database_connect(const String &connection_str); Ref query(const String &query); void query_run(const String &query); Ref get_query_builder(); Ref get_table_builder(); + Ref create_prepared_statement(); String escape(const String &str); void escape_to(const String &str, String *to); diff --git a/modules/database_sqlite/sqlite3_prepared_statement.cpp b/modules/database_sqlite/sqlite3_prepared_statement.cpp new file mode 100644 index 000000000..3c77ecfea --- /dev/null +++ b/modules/database_sqlite/sqlite3_prepared_statement.cpp @@ -0,0 +1,514 @@ +/*************************************************************************/ +/* query_result.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* PANDEMONIUM ENGINE */ +/* https://github.com/Relintai/pandemonium_engine */ +/*************************************************************************/ +/* Copyright (c) 2022-present Péter Magyar. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "sqlite3_prepared_statement.h" + +#include "sqlite3_connection.h" + +String SQLite3PreparedStatement::get_expanded_sql() { + if (!_prepared_statement) { + return String(); + } + + char *res = sqlite3_expanded_sql(_prepared_statement); + String r = String::utf8(res); + sqlite3_free(res); + + return r; +} +String SQLite3PreparedStatement::get_normalized_sql() { +#ifdef SQLITE_ENABLE_NORMALIZE + if (!_prepared_statement) { + return String(); + } + + char *res = sqlite3_normalized_sql(_prepared_statement); + String r = String::utf8(res); + sqlite3_free(res); + + return r; +#else + return String(); +#endif +} + +// Binding +Error SQLite3PreparedStatement::bind_blob(const int p_index, const Vector &p_value) { + if (!_prepared_statement) { + return ERR_UNCONFIGURED; + } + + int res = sqlite3_bind_blob(_prepared_statement, p_index, p_value.ptr(), p_value.size(), SQLITE_TRANSIENT); + + if (res != SQLITE_OK) { + return FAILED; + } + + return OK; +} +Error SQLite3PreparedStatement::bind_float(const int p_index, const float p_value) { + return bind_double(p_index, p_value); +} +Error SQLite3PreparedStatement::bind_double(const int p_index, const double p_value) { + if (!_prepared_statement) { + return ERR_UNCONFIGURED; + } + + int res = sqlite3_bind_double(_prepared_statement, p_index, p_value); + + if (res != SQLITE_OK) { + return FAILED; + } + + return OK; +} +Error SQLite3PreparedStatement::bind_int(const int p_index, const int p_value) { + if (!_prepared_statement) { + return ERR_UNCONFIGURED; + } + + int res = sqlite3_bind_int(_prepared_statement, p_index, p_value); + + if (res != SQLITE_OK) { + return FAILED; + } + + return OK; +} +Error SQLite3PreparedStatement::bind_int64(const int p_index, const int64_t p_value) { + if (!_prepared_statement) { + return ERR_UNCONFIGURED; + } + + int res = sqlite3_bind_int64(_prepared_statement, p_index, p_value); + + if (res != SQLITE_OK) { + return FAILED; + } + + return OK; +} +Error SQLite3PreparedStatement::bind_null(const int p_index) { + if (!_prepared_statement) { + return ERR_UNCONFIGURED; + } + + int res = sqlite3_bind_null(_prepared_statement, p_index); + + if (res != SQLITE_OK) { + return FAILED; + } + + return OK; +} +Error SQLite3PreparedStatement::bind_text(const int p_index, const String &p_value) { + if (!_prepared_statement) { + return ERR_UNCONFIGURED; + } + + CharString cs = p_value.utf8(); + + int res = sqlite3_bind_text(_prepared_statement, p_index, cs.get_data(), cs.size(), SQLITE_TRANSIENT); + + if (res != SQLITE_OK) { + return FAILED; + } + + return OK; +} +Error SQLite3PreparedStatement::bind_zeroblob(const int p_index, const int p_num) { + if (!_prepared_statement) { + return ERR_UNCONFIGURED; + } + + int res = sqlite3_bind_zeroblob(_prepared_statement, p_index, p_num); + + if (res != SQLITE_OK) { + return FAILED; + } + + return OK; +} +Error SQLite3PreparedStatement::bind_value(const int p_index, const Variant &p_value) { + switch (p_value.get_type()) { + case Variant::NIL: + return bind_null(p_index); + + case Variant::BOOL: + case Variant::INT: + return bind_int(p_index, p_value); + + case Variant::REAL: + return bind_double(p_index, p_value); + + case Variant::STRING: + case Variant::RECT2: // 5 + case Variant::RECT2I: + case Variant::VECTOR2: + case Variant::VECTOR2I: + case Variant::VECTOR3: + case Variant::VECTOR3I: // 10 + case Variant::VECTOR4: + case Variant::VECTOR4I: + case Variant::PLANE: + case Variant::QUATERNION: + case Variant::AABB: // 15 + case Variant::BASIS: + case Variant::TRANSFORM: + case Variant::TRANSFORM2D: + case Variant::PROJECTION: + case Variant::COLOR: + case Variant::NODE_PATH: + case Variant::RID: + case Variant::OBJECT: + case Variant::STRING_NAME: + case Variant::DICTIONARY: + case Variant::ARRAY: + case Variant::POOL_INT_ARRAY: + case Variant::POOL_REAL_ARRAY: + case Variant::POOL_STRING_ARRAY: + case Variant::POOL_VECTOR2_ARRAY: + case Variant::POOL_VECTOR2I_ARRAY: + case Variant::POOL_VECTOR3_ARRAY: + case Variant::POOL_VECTOR3I_ARRAY: + case Variant::POOL_VECTOR4_ARRAY: + case Variant::POOL_VECTOR4I_ARRAY: + case Variant::POOL_COLOR_ARRAY: + case Variant::VARIANT_MAX: + return bind_text(p_index, p_value); + + case Variant::POOL_BYTE_ARRAY: + return bind_blob(p_index, p_value); + + default: + break; + } + + return ERR_UNAVAILABLE; +} + +int SQLite3PreparedStatement::bind_parameter_index(const String &p_name) { + if (!_prepared_statement) { + return -1; + } + + CharString cs = p_name.utf8(); + + return sqlite3_bind_parameter_index(_prepared_statement, cs.get_data()); +} +String SQLite3PreparedStatement::bind_parameter_name(const int p_index) { + if (!_prepared_statement) { + return String(); + } + + // don't free it + const char *pname = sqlite3_bind_parameter_name(_prepared_statement, p_index); + + return String::utf8(pname); +} + +int SQLite3PreparedStatement::bind_parameter_count() { + if (!_prepared_statement) { + return ERR_UNCONFIGURED; + } + + return sqlite3_bind_parameter_count(_prepared_statement); +} + +Error SQLite3PreparedStatement::clear_bindings() { + if (!_prepared_statement) { + return ERR_UNCONFIGURED; + } + + int res = sqlite3_clear_bindings(_prepared_statement); + + if (res != SQLITE_OK) { + return FAILED; + } + + return OK; +} + +// Querying +String SQLite3PreparedStatement::column_name(const int p_index) { + if (!_prepared_statement) { + return String(); + } + + // don't free it + const char *cname = sqlite3_column_name(_prepared_statement, p_index); + + return String::utf8(cname); +} +String SQLite3PreparedStatement::column_decltype(const int p_index) { + if (!_prepared_statement) { + return String(); + } + + // don't free it + const char *cname = sqlite3_column_decltype(_prepared_statement, p_index); + + return String::utf8(cname); +} +PreparedStatement::Type SQLite3PreparedStatement::column_type(const int p_index) { + if (!_prepared_statement) { + return TYPE_UNKNOWN; + } + + int type = sqlite3_column_type(_prepared_statement, p_index); + + switch (type) { + case SQLITE_BLOB: + return TYPE_BLOB; + case SQLITE_FLOAT: + return TYPE_DOUBLE; + case SQLITE_INTEGER: + return TYPE_INT; + case SQLITE_TEXT: + return TYPE_TEXT; + case SQLITE_NULL: + return TYPE_NULL; + default: + break; + } + + return TYPE_UNKNOWN; +} + +String SQLite3PreparedStatement::column_database_name(const int p_index) { +#ifdef SQLITE_ENABLE_COLUMN_METADATA + if (!_prepared_statement) { + return String(); + } + + // don't free it + const char *name = sqlite3_column_database_name(_prepared_statement, p_index); + + return String::utf8(name); +#else + return String(); +#endif +} +String SQLite3PreparedStatement::column_table_name(const int p_index) { +#ifdef SQLITE_ENABLE_COLUMN_METADATA + if (!_prepared_statement) { + return String(); + } + + // don't free it + const char *name = sqlite3_column_table_name(_prepared_statement, p_index); + + return String::utf8(name); +#else + return String(); +#endif +} +String SQLite3PreparedStatement::column_origin_name(const int p_index) { +#ifdef SQLITE_ENABLE_COLUMN_METADATA + if (!_prepared_statement) { + return String(); + } + + // don't free it + const char *name = sqlite3_column_origin_name(_prepared_statement, p_index); + + return String::utf8(name); +#else + return String(); +#endif +} + +Vector SQLite3PreparedStatement::column_blob(const int p_index) { + if (!_prepared_statement) { + return Vector(); + } + + const uint8_t *val = (const uint8_t *)sqlite3_column_blob(_prepared_statement, p_index); + + if (!val) { + return Vector(); + } + + int size = sqlite3_column_bytes(_prepared_statement, p_index); + + Vector r; + r.resize(size); + + memcpy(r.ptrw(), val, size); + + return r; +} +float SQLite3PreparedStatement::column_float(const int p_index) { + return static_cast(column_double(p_index)); +} +double SQLite3PreparedStatement::column_double(const int p_index) { + if (!_prepared_statement) { + return 0; + } + + return sqlite3_column_double(_prepared_statement, p_index); +} +int64_t SQLite3PreparedStatement::column_int(const int p_index) { + if (!_prepared_statement) { + return 0; + } + + return sqlite3_column_int(_prepared_statement, p_index); +} +int SQLite3PreparedStatement::column_int64(const int p_index) { + if (!_prepared_statement) { + return 0; + } + + return sqlite3_column_int64(_prepared_statement, p_index); +} +String SQLite3PreparedStatement::column_text(const int p_index) { + if (!_prepared_statement) { + return String(); + } + + const char *val = (const char *)sqlite3_column_text(_prepared_statement, p_index); + + if (!val) { + return String(); + } + + return String::utf8(val); +} + +Variant SQLite3PreparedStatement::column_value(const int p_index) { + if (!_prepared_statement) { + return Variant(); + } + + switch (column_type(p_index)) { + case TYPE_BLOB: + return Variant(column_blob(p_index)); + case TYPE_DOUBLE: + return Variant(column_double(p_index)); + break; + case TYPE_INT: + return Variant(column_int(p_index)); + break; + case TYPE_TEXT: + return Variant(column_text(p_index)); + break; + case TYPE_NULL: + default: + break; + } + + return Variant(); +} + +int SQLite3PreparedStatement::column_count() { + if (!_prepared_statement) { + return 0; + } + + return sqlite3_column_count(_prepared_statement); +} + +// Control +Error SQLite3PreparedStatement::prepare() { + ERR_FAIL_COND_V(!_connection.is_valid(), FAILED); + + CharString cs = _sql.utf8(); + + int res = sqlite3_prepare_v2(_connection->conn, cs.get_data(), cs.size(), &_prepared_statement, NULL); + + if (res != SQLITE_OK) { + return FAILED; + } + + return OK; +} +Error SQLite3PreparedStatement::step() { + if (!_prepared_statement) { + return ERR_UNCONFIGURED; + } + + int res = sqlite3_step(_prepared_statement); + + if (res != SQLITE_OK) { + return FAILED; + } + + return OK; +} +int SQLite3PreparedStatement::data_count() { + if (!_prepared_statement) { + return 0; + } + + return sqlite3_data_count(_prepared_statement); +} +Error SQLite3PreparedStatement::reset() { + if (!_prepared_statement) { + return ERR_UNCONFIGURED; + } + + int res = sqlite3_reset(_prepared_statement); + + if (res != SQLITE_OK) { + return FAILED; + } + + return OK; +} +Error SQLite3PreparedStatement::finalize() { + if (!_prepared_statement) { + return OK; + } + + sqlite3_finalize(_prepared_statement); + + _prepared_statement = NULL; + + return OK; +} + +Ref SQLite3PreparedStatement::get_connection() const { + return _connection; +} + +SQLite3PreparedStatement::SQLite3PreparedStatement() { + _prepared_statement = NULL; +} + +SQLite3PreparedStatement::~SQLite3PreparedStatement() { + finalize(); + + _prepared_statement = NULL; +} + +void SQLite3PreparedStatement::_bind_methods() { +} diff --git a/modules/database_sqlite/sqlite3_prepared_statement.h b/modules/database_sqlite/sqlite3_prepared_statement.h new file mode 100644 index 000000000..7fc179e29 --- /dev/null +++ b/modules/database_sqlite/sqlite3_prepared_statement.h @@ -0,0 +1,107 @@ +#ifndef SQLITE3_PREPARED_STATEMENT_H +#define SQLITE3_PREPARED_STATEMENT_H + +/*************************************************************************/ +/* query_result.h */ +/*************************************************************************/ +/* This file is part of: */ +/* PANDEMONIUM ENGINE */ +/* https://github.com/Relintai/pandemonium_engine */ +/*************************************************************************/ +/* Copyright (c) 2022-present Péter Magyar. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "core/string/ustring.h" + +#include "modules/database/prepared_statement.h" + +#include "./sqlite/sqlite3.h" + +class SQLite3DatabaseConnection; + +class SQLite3PreparedStatement : public PreparedStatement { + GDCLASS(SQLite3PreparedStatement, PreparedStatement); + +public: + virtual String get_expanded_sql(); + virtual String get_normalized_sql(); + + // Binding + virtual Error bind_blob(const int p_index, const Vector &p_value); + virtual Error bind_float(const int p_index, const float p_value); + virtual Error bind_double(const int p_index, const double p_value); + virtual Error bind_int(const int p_index, const int p_value); + virtual Error bind_int64(const int p_index, const int64_t p_value); + virtual Error bind_null(const int p_index); + virtual Error bind_text(const int p_index, const String &p_value); + virtual Error bind_zeroblob(const int p_index, const int p_num); + virtual Error bind_value(const int p_index, const Variant &p_value); + + virtual int bind_parameter_index(const String &p_name); + virtual String bind_parameter_name(const int p_index); + + virtual int bind_parameter_count(); + + virtual Error clear_bindings(); + + // Querying + virtual String column_name(const int p_index); + virtual String column_decltype(const int p_index); + virtual Type column_type(const int p_index); + + virtual String column_database_name(const int p_index); + virtual String column_table_name(const int p_index); + virtual String column_origin_name(const int p_index); + + virtual Vector column_blob(const int p_index); + virtual float column_float(const int p_index); + virtual double column_double(const int p_index); + virtual int64_t column_int(const int p_index); + virtual int column_int64(const int p_index); + virtual String column_text(const int p_index); + virtual Variant column_value(const int p_index); + + virtual int column_count(); + + // Control + virtual Error prepare(); + virtual Error step(); + virtual int data_count(); + virtual Error reset(); + virtual Error finalize(); + + virtual Ref get_connection() const; + + SQLite3PreparedStatement(); + virtual ~SQLite3PreparedStatement(); + + Ref _connection; + +protected: + static void _bind_methods(); + + sqlite3_stmt *_prepared_statement; +}; + +#endif diff --git a/modules/database_sqlite/sqlite3_query_builder.cpp b/modules/database_sqlite/sqlite3_query_builder.cpp index 0eed0155e..c33032d86 100644 --- a/modules/database_sqlite/sqlite3_query_builder.cpp +++ b/modules/database_sqlite/sqlite3_query_builder.cpp @@ -3,6 +3,7 @@ #include "sqlite3_connection.h" #include "sqlite3_database.h" #include "sqlite3_query_result.h" +#include "sqlite3_prepared_statement.h" QueryBuilder *SQLite3QueryBuilder::select() { query_result += "SELECT "; @@ -213,7 +214,7 @@ QueryBuilder *SQLite3QueryBuilder::sets() { } QueryBuilder *SQLite3QueryBuilder::cset() { ERR_FAIL_COND_V(query_result.length() <= 2, this); - + query_result[query_result.length() - 2] = ' '; return this; @@ -345,20 +346,6 @@ String SQLite3QueryBuilder::escape(const String ¶ms) { return _connection->escape(params); } -QueryBuilder *SQLite3QueryBuilder::prepare() { - return this; -} - -QueryBuilder *SQLite3QueryBuilder::set_param(const int index, const String &value) { - return this; -} -QueryBuilder *SQLite3QueryBuilder::set_param(const int index, const int value) { - return this; -} -QueryBuilder *SQLite3QueryBuilder::set_param(const int index, const float value) { - return this; -} - QueryBuilder *SQLite3QueryBuilder::end_command() { query_result += ";"; @@ -385,6 +372,12 @@ void SQLite3QueryBuilder::run_query() { _connection->query_run(query_result); } +Ref SQLite3QueryBuilder::create_prepared_statement() { + ERR_FAIL_COND_V(!_connection.is_valid(), Ref()); + + return _connection->create_prepared_statement(); +} + QueryBuilder *SQLite3QueryBuilder::select_last_insert_id() { return this; } diff --git a/modules/database_sqlite/sqlite3_query_builder.h b/modules/database_sqlite/sqlite3_query_builder.h index b2e66373c..86f04bff7 100644 --- a/modules/database_sqlite/sqlite3_query_builder.h +++ b/modules/database_sqlite/sqlite3_query_builder.h @@ -77,16 +77,13 @@ public: String escape(const String ¶ms); - QueryBuilder *prepare(); - QueryBuilder *set_param(const int index, const String &value); - QueryBuilder *set_param(const int index, const int value); - QueryBuilder *set_param(const int index, const float value); - QueryBuilder *end_command(); Ref run(); void run_query(); + Ref create_prepared_statement(); + SQLite3QueryBuilder(); ~SQLite3QueryBuilder();