From a60296a46d680c11c193f26e60e1dd51c90d87b9 Mon Sep 17 00:00:00 2001 From: Carl Brasic Date: Sat, 9 Apr 2022 21:02:23 -0500 Subject: [PATCH] Copy the in_transaction flag into Trilogy::Result This flag (SERVER_STATUS_IN_TRANS, position 0x0001) is part of the server_status bitfield sent with every OK_Packet which is already stored on the connection. But this particular data is not always safe to read from the connection since in some cases one or more queries may have been executed since the result was generated. So to increase safety let's also store it on the Result itself. --- contrib/ruby/ext/trilogy-ruby/cext.c | 13 ++++++++++--- contrib/ruby/test/client_test.rb | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/contrib/ruby/ext/trilogy-ruby/cext.c b/contrib/ruby/ext/trilogy-ruby/cext.c index f9c0f44d..293c6e25 100644 --- a/contrib/ruby/ext/trilogy-ruby/cext.c +++ b/contrib/ruby/ext/trilogy-ruby/cext.c @@ -21,9 +21,9 @@ static VALUE Trilogy_DatabaseError, Trilogy_Result; static ID id_socket, id_host, id_port, id_username, id_password, id_found_rows, id_connect_timeout, id_read_timeout, id_write_timeout, id_keepalive_enabled, id_keepalive_idle, id_keepalive_interval, id_keepalive_count, - id_ivar_affected_rows, id_ivar_fields, id_ivar_last_insert_id, id_ivar_rows, id_ivar_query_time, id_password, - id_database, id_ssl_ca, id_ssl_capath, id_ssl_cert, id_ssl_cipher, id_ssl_crl, id_ssl_crlpath, id_ssl_key, - id_ssl_mode, id_tls_ciphersuites, id_tls_min_version, id_tls_max_version; + id_ivar_affected_rows, id_ivar_fields, id_ivar_last_insert_id, id_ivar_query_time, id_ivar_rows, + id_ivar_in_transaction, id_password, id_database, id_ssl_ca, id_ssl_capath, id_ssl_cert, id_ssl_cipher, + id_ssl_crl, id_ssl_crlpath, id_ssl_key, id_ssl_mode, id_tls_ciphersuites, id_tls_min_version, id_tls_max_version; struct trilogy_ctx { trilogy_conn_t conn; @@ -610,6 +610,9 @@ static VALUE execute_read_query(VALUE vargs) rb_ivar_set(result, id_ivar_query_time, DBL2NUM(query_time)); + rb_ivar_set(result, id_ivar_in_transaction, + (ctx->conn.server_status & TRILOGY_SERVER_STATUS_IN_TRANS) ? Qtrue : Qfalse); + if (rc == TRILOGY_OK) { rb_ivar_set(result, id_ivar_last_insert_id, ULL2NUM(ctx->conn.last_insert_id)); @@ -944,6 +947,9 @@ void Init_cext() rb_define_attr(Trilogy_Result, "last_insert_id", 1, 0); rb_define_attr(Trilogy_Result, "rows", 1, 0); rb_define_attr(Trilogy_Result, "query_time", 1, 0); + rb_define_attr(Trilogy_Result, "in_transaction", 1, 0); + + rb_define_alias(Trilogy_Result, "in_transaction?", "in_transaction"); id_socket = rb_intern("socket"); id_host = rb_intern("host"); @@ -976,6 +982,7 @@ void Init_cext() id_ivar_last_insert_id = rb_intern("@last_insert_id"); id_ivar_rows = rb_intern("@rows"); id_ivar_query_time = rb_intern("@query_time"); + id_ivar_in_transaction = rb_intern("@in_transaction"); rb_trilogy_cast_init(); diff --git a/contrib/ruby/test/client_test.rb b/contrib/ruby/test/client_test.rb index a6bfb14e..d825c4bc 100644 --- a/contrib/ruby/test/client_test.rb +++ b/contrib/ruby/test/client_test.rb @@ -132,6 +132,7 @@ def test_trilogy_query_result_object assert_equal [{ "a" => 1, "b" => 2 }], result.each_hash.to_a assert_equal [[1, 2]], result.to_a assert_kind_of Float, result.query_time + refute_predicate result, :in_transaction? assert_in_delta 0.1, result.query_time, 0.1 ensure ensure_closed client @@ -215,6 +216,24 @@ def test_trilogy_affected_rows_in_found_rows_mode ensure_closed client end + def test_trilogy_in_transaction_flag_on_result + client = new_tcp_client + create_test_table(client) + + refute_predicate client.query("SELECT 1"), :in_transaction? + refute_predicate client.query("INSERT INTO trilogy_test (varchar_test, int_test) VALUES ('a', 1)"), :in_transaction? + + assert_predicate client.query("BEGIN"), :in_transaction? + assert_predicate client.query("INSERT INTO trilogy_test (varchar_test, int_test) VALUES ('b', 2)"), :in_transaction? + + refute_predicate client.query("COMMIT"), :in_transaction? + + assert_predicate client.query("BEGIN"), :in_transaction? + refute_predicate client.query("ROLLBACK"), :in_transaction? + ensure + ensure_closed client + end + def test_trilogy_warning_count client = new_tcp_client create_test_table(client)