diff --git a/modules/database/SCsub b/modules/database/SCsub index fa0fa50ef..a17258d1d 100644 --- a/modules/database/SCsub +++ b/modules/database/SCsub @@ -16,6 +16,7 @@ sources = [ "query_builder.cpp", "query_result.cpp", "table_builder.cpp", + "prepared_statement.cpp", ] if ARGUMENTS.get('custom_modules_shared', 'no') == 'yes': diff --git a/modules/database/config.py b/modules/database/config.py index 304781503..eea3832be 100644 --- a/modules/database/config.py +++ b/modules/database/config.py @@ -18,6 +18,7 @@ def get_doc_classes(): "QueryBuilder", "QueryResult", "TableBuilder", + "PreparedStatement", ] def get_doc_path(): diff --git a/modules/database/database_connection.cpp b/modules/database/database_connection.cpp index e61c50411..d81cc6283 100644 --- a/modules/database/database_connection.cpp +++ b/modules/database/database_connection.cpp @@ -32,6 +32,7 @@ #include "database_connection.h" #include "database.h" +#include "prepared_statement.h" #include "query_builder.h" #include "query_result.h" #include "table_builder.h" @@ -47,11 +48,15 @@ void DatabaseConnection::query_run(const String &query) { } Ref DatabaseConnection::get_query_builder() { - return Ref(new QueryBuilder()); + return Ref(); } Ref DatabaseConnection::get_table_builder() { - return Ref(new TableBuilder()); + return Ref(); +} + +Ref DatabaseConnection::create_prepared_statement() { + return Ref(); } String DatabaseConnection::escape(const String &str) { @@ -99,6 +104,7 @@ void DatabaseConnection::_bind_methods() { ClassDB::bind_method(D_METHOD("get_query_builder"), &DatabaseConnection::get_query_builder); ClassDB::bind_method(D_METHOD("get_table_builder"), &DatabaseConnection::get_table_builder); + ClassDB::bind_method(D_METHOD("create_prepared_statement"), &DatabaseConnection::create_prepared_statement); ClassDB::bind_method(D_METHOD("escape", "str"), &DatabaseConnection::escape); diff --git a/modules/database/database_connection.h b/modules/database/database_connection.h index 8445dbdf6..835575f52 100644 --- a/modules/database/database_connection.h +++ b/modules/database/database_connection.h @@ -40,6 +40,7 @@ class QueryBuilder; class TableBuilder; class QueryResult; class Database; +class PreparedStatement; class DatabaseConnection : public Reference { GDCLASS(DatabaseConnection, Reference); @@ -51,6 +52,7 @@ public: virtual Ref get_query_builder(); virtual Ref get_table_builder(); + virtual Ref create_prepared_statement(); virtual String escape(const String &str); virtual void escape_to(const String &str, String *to); diff --git a/modules/database/prepared_statement.cpp b/modules/database/prepared_statement.cpp new file mode 100644 index 000000000..d89a96fdf --- /dev/null +++ b/modules/database/prepared_statement.cpp @@ -0,0 +1,117 @@ +/*************************************************************************/ +/* 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 "prepared_statement.h" + +#include "database_connection.h" + +String PreparedStatement::get_sql() { + return _sql; +} +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() { + ClassDB::bind_method(D_METHOD("get_sql"), &PreparedStatement::get_sql); + ClassDB::bind_method(D_METHOD("set_sql"), &PreparedStatement::set_sql); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "sql"), "set_sql", "get_sql"); + + ClassDB::bind_method(D_METHOD("get_expanded_sql"), &PreparedStatement::get_expanded_sql); + ClassDB::bind_method(D_METHOD("get_normalized_sql"), &PreparedStatement::get_normalized_sql); + + // Binding + + ClassDB::bind_method(D_METHOD("bind_blob", "index", "value"), &PreparedStatement::bind_blob); + ClassDB::bind_method(D_METHOD("bind_float", "index", "value"), &PreparedStatement::bind_float); + ClassDB::bind_method(D_METHOD("bind_double", "index", "value"), &PreparedStatement::bind_double); + ClassDB::bind_method(D_METHOD("bind_int", "index", "value"), &PreparedStatement::bind_int); + ClassDB::bind_method(D_METHOD("bind_int64", "index", "value"), &PreparedStatement::bind_int64); + ClassDB::bind_method(D_METHOD("bind_null", "index"), &PreparedStatement::bind_null); + ClassDB::bind_method(D_METHOD("bind_text", "index", "value"), &PreparedStatement::bind_text); + ClassDB::bind_method(D_METHOD("bind_zeroblob", "index", "num"), &PreparedStatement::bind_zeroblob); + ClassDB::bind_method(D_METHOD("bind_value", "index", "value"), &PreparedStatement::bind_value); + + ClassDB::bind_method(D_METHOD("bind_parameter_index", "name"), &PreparedStatement::bind_parameter_index); + ClassDB::bind_method(D_METHOD("bind_parameter_name", "index"), &PreparedStatement::bind_parameter_name); + + ClassDB::bind_method(D_METHOD("bind_parameter_count"), &PreparedStatement::bind_parameter_count); + + ClassDB::bind_method(D_METHOD("clear_bindings"), &PreparedStatement::clear_bindings); + + // Querying + + ClassDB::bind_method(D_METHOD("column_name", "index"), &PreparedStatement::column_name); + ClassDB::bind_method(D_METHOD("column_decltype", "index"), &PreparedStatement::column_decltype); + ClassDB::bind_method(D_METHOD("column_type", "index"), &PreparedStatement::column_type); + + ClassDB::bind_method(D_METHOD("column_database_name", "index"), &PreparedStatement::column_database_name); + ClassDB::bind_method(D_METHOD("column_table_name", "index"), &PreparedStatement::column_table_name); + ClassDB::bind_method(D_METHOD("column_origin_name", "index"), &PreparedStatement::column_origin_name); + + ClassDB::bind_method(D_METHOD("column_blob", "index"), &PreparedStatement::column_blob); + ClassDB::bind_method(D_METHOD("column_float", "index"), &PreparedStatement::column_float); + ClassDB::bind_method(D_METHOD("column_double", "index"), &PreparedStatement::column_double); + 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); + + // Control + + ClassDB::bind_method(D_METHOD("prepare"), &PreparedStatement::prepare); + ClassDB::bind_method(D_METHOD("step"), &PreparedStatement::step); + ClassDB::bind_method(D_METHOD("data_count"), &PreparedStatement::data_count); + 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); +} diff --git a/modules/database/prepared_statement.h b/modules/database/prepared_statement.h new file mode 100644 index 000000000..a612b7ba5 --- /dev/null +++ b/modules/database/prepared_statement.h @@ -0,0 +1,111 @@ +#ifndef PREPARED_STATEMENT_H +#define 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 "core/object/reference.h" + +class DatabaseConnection; + +class PreparedStatement : public Reference { + GDCLASS(PreparedStatement, Reference); + +public: + String get_sql(); + void set_sql(const String &p_sql); + + virtual String get_expanded_sql() = 0; + virtual String get_normalized_sql() = 0; + + // Binding + virtual Error bind_blob(const int p_index, const Vector &p_value) = 0; + virtual Error bind_float(const int p_index, const float p_value) = 0; + virtual Error bind_double(const int p_index, const double p_value) = 0; + virtual Error bind_int(const int p_index, const int p_value) = 0; + virtual Error bind_int64(const int p_index, const int64_t p_value) = 0; + virtual Error bind_null(const int p_index) = 0; + virtual Error bind_text(const int p_index, const String &p_value) = 0; + virtual Error bind_zeroblob(const int p_index, const int p_num) = 0; + virtual Error bind_value(const int p_index, const Variant &p_value) = 0; + + virtual int bind_parameter_index(const String &p_name) = 0; + virtual String bind_parameter_name(const int p_index) = 0; + + virtual int bind_parameter_count() = 0; + + virtual Error clear_bindings() = 0; + + // 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_database_name(const int p_index) = 0; + virtual String column_table_name(const int p_index) = 0; + virtual String column_origin_name(const int p_index) = 0; + + virtual Vector column_blob(const int p_index) = 0; + virtual float column_float(const int p_index) = 0; + virtual double column_double(const int p_index) = 0; + 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; + + // Control + virtual Error prepare() = 0; + virtual Error step() = 0; + virtual int data_count() = 0; + virtual Error reset() = 0; + virtual Error finalize(); + + virtual bool is_busy() = 0; + + Ref get_connection() const; + + PreparedStatement(); + virtual ~PreparedStatement(); + +protected: + static void _bind_methods(); + + String _sql; + + Ref _connection; +}; + +#endif diff --git a/modules/database/query_builder.cpp b/modules/database/query_builder.cpp index d1cebd79d..ee516f5fa 100644 --- a/modules/database/query_builder.cpp +++ b/modules/database/query_builder.cpp @@ -32,6 +32,7 @@ #include "query_builder.h" #include "query_result.h" +#include "prepared_statement.h" String QueryBuilder::get_result() { return query_result; @@ -290,19 +291,6 @@ String QueryBuilder::escape(const String ¶ms) { return params; } -QueryBuilder *QueryBuilder::prepare() { - return this; -} -QueryBuilder *QueryBuilder::set_params(const int index, const String &value) { - return this; -} -QueryBuilder *QueryBuilder::set_parami(const int index, const int value) { - return this; -} -QueryBuilder *QueryBuilder::set_paramf(const int index, const float value) { - return this; -} - QueryBuilder *QueryBuilder::end_command() { return this; } @@ -320,6 +308,10 @@ Ref QueryBuilder::run() { void QueryBuilder::run_query() { } +Ref QueryBuilder::create_prepared_statement() { + return Ref(); +} + void QueryBuilder::print() { //printf("%s\n", query_result.get_data()); ERR_PRINT(query_result); @@ -411,17 +403,14 @@ void QueryBuilder::_bind_methods() { ClassDB::bind_method(D_METHOD("escape", "param"), &QueryBuilder::escape); - ClassDB::bind_method(D_METHOD("prepare"), &QueryBuilder::_prepare_bind); - ClassDB::bind_method(D_METHOD("set_params", "index", "value"), &QueryBuilder::_set_params_bind); - ClassDB::bind_method(D_METHOD("set_parami", "index", "value"), &QueryBuilder::_set_parami_bind); - ClassDB::bind_method(D_METHOD("set_paramf", "index", "value"), &QueryBuilder::_set_paramf_bind); - ClassDB::bind_method(D_METHOD("end_command"), &QueryBuilder::_end_command_bind); ClassDB::bind_method(D_METHOD("reset"), &QueryBuilder::_reset_bind); ClassDB::bind_method(D_METHOD("run"), &QueryBuilder::run); ClassDB::bind_method(D_METHOD("run_query"), &QueryBuilder::run_query); + + ClassDB::bind_method(D_METHOD("create_prepared_statement"), &QueryBuilder::create_prepared_statement); } Ref QueryBuilder::_cvalues_bind() { @@ -614,19 +603,6 @@ Ref QueryBuilder::_select_last_insert_id_bind() { return Ref(select_last_insert_id()); } -Ref QueryBuilder::_prepare_bind() { - return Ref(prepare()); -} -Ref QueryBuilder::_set_params_bind(const int index, const String &value) { - return Ref(set_params(index, value)); -} -Ref QueryBuilder::_set_parami_bind(const int index, const int value) { - return Ref(set_parami(index, value)); -} -Ref QueryBuilder::_set_paramf_bind(const int index, const float value) { - return Ref(set_paramf(index, value)); -} - Ref QueryBuilder::_end_command_bind() { return Ref(end_command()); } diff --git a/modules/database/query_builder.h b/modules/database/query_builder.h index 50a41d0c1..5c1e17b38 100644 --- a/modules/database/query_builder.h +++ b/modules/database/query_builder.h @@ -37,6 +37,7 @@ #include "core/object/reference.h" class QueryResult; +class PreparedStatement; //methods that start with an e escape their params. @@ -135,11 +136,6 @@ public: virtual String escape(const String ¶ms); - virtual QueryBuilder *prepare(); - virtual QueryBuilder *set_params(const int index, const String &value); - virtual QueryBuilder *set_parami(const int index, const int value); - virtual QueryBuilder *set_paramf(const int index, const float value); - virtual QueryBuilder *end_command(); virtual QueryBuilder *reset(); @@ -147,6 +143,8 @@ public: virtual Ref run(); virtual void run_query(); + virtual Ref create_prepared_statement(); + void print(); QueryBuilder(); diff --git a/modules/database/query_result.cpp b/modules/database/query_result.cpp index 2fa4e3fd7..a56d366cb 100644 --- a/modules/database/query_result.cpp +++ b/modules/database/query_result.cpp @@ -31,8 +31,6 @@ #include "query_result.h" -#include - bool QueryResult::next_row() { return false; } diff --git a/modules/database/register_types.cpp b/modules/database/register_types.cpp index 9d8c4ccb0..1c785ff54 100644 --- a/modules/database/register_types.cpp +++ b/modules/database/register_types.cpp @@ -39,6 +39,7 @@ #include "query_builder.h" #include "query_result.h" #include "table_builder.h" +#include "prepared_statement.h" #include "core/config/engine.h" @@ -59,6 +60,7 @@ void register_database_types(ModuleRegistrationLevel p_level) { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_virtual_class(); } }