Skip to content

Commit

Permalink
Pass max_allowed_packet through the ruby library
Browse files Browse the repository at this point in the history
Co-authored-by: Kamil Gwóźdź <kamil-gwozdz@github.com>
  • Loading branch information
matthewd and kamil-gwozdz committed Jun 7, 2023
1 parent 00c099a commit e62ba20
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 11 deletions.
12 changes: 11 additions & 1 deletion contrib/ruby/ext/trilogy-ruby/cext.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ static ID id_socket, id_host, id_port, id_username, id_password, id_found_rows,
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_multi_statement, id_multi_result,
id_from_code, id_from_errno, id_connection_options;
id_from_code, id_from_errno, id_connection_options, id_max_allowed_packet;

struct trilogy_ctx {
trilogy_conn_t conn;
Expand Down Expand Up @@ -139,6 +139,10 @@ static void handle_trilogy_error(struct trilogy_ctx *ctx, int rc, const char *ms
rb_raise(Trilogy_BaseConnectionError, "%" PRIsVALUE ": TRILOGY_DNS_ERROR", rbmsg);
}

case TRILOGY_MAX_PACKET_EXCEEDED: {
rb_raise(Trilogy_QueryError, "%" PRIsVALUE ": TRILOGY_MAX_PACKET_EXCEEDED", rbmsg);
}

default:
rb_raise(Trilogy_QueryError, "%" PRIsVALUE ": %s", rbmsg, trilogy_error(rc));
}
Expand Down Expand Up @@ -415,6 +419,11 @@ static VALUE rb_trilogy_initialize(VALUE self, VALUE encoding, VALUE charset, VA
connopt.keepalive_interval = NUM2USHORT(val);
}

if ((val = rb_hash_lookup(opts, ID2SYM(id_max_allowed_packet))) != Qnil) {
Check_Type(val, T_FIXNUM);
connopt.max_allowed_packet = NUM2SIZET(val);
}

if ((val = rb_hash_lookup(opts, ID2SYM(id_host))) != Qnil) {
Check_Type(val, T_STRING);

Expand Down Expand Up @@ -1114,6 +1123,7 @@ RUBY_FUNC_EXPORTED void Init_cext()
id_connect_timeout = rb_intern("connect_timeout");
id_read_timeout = rb_intern("read_timeout");
id_write_timeout = rb_intern("write_timeout");
id_max_allowed_packet = rb_intern("max_allowed_packet");
id_keepalive_enabled = rb_intern("keepalive_enabled");
id_keepalive_idle = rb_intern("keepalive_idle");
id_keepalive_count = rb_intern("keepalive_count");
Expand Down
108 changes: 98 additions & 10 deletions contrib/ruby/test/client_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -745,28 +745,116 @@ def test_connect_by_multiple_names
Trilogy.new(host: "localhost")
end

PADDED_QUERY_TEMPLATE = "SELECT LENGTH('%s')"
PROTOCOL_OVERHEAD = 2 # One byte for the 0x03 (COM_QUERY); one because the packet is actually required to be shorter than the "max"
PADDED_QUERY_OVERHEAD =
PADDED_QUERY_TEMPLATE.size - "%s".size + PROTOCOL_OVERHEAD

def query_for_target_packet_size(size)
PADDED_QUERY_TEMPLATE % ("x" * (size - PADDED_QUERY_OVERHEAD))
end

def set_max_allowed_packet(size)
client = new_tcp_client
client.query "SET GLOBAL max_allowed_packet = #{size}"
ensure
ensure_closed client
end

def test_packet_size
def test_packet_size_lower_than_trilogy_max_packet_len
set_max_allowed_packet(4 * 1024 * 1024) # TRILOGY_MAX_PACKET_LEN is 16MB

client = new_tcp_client(max_allowed_packet: 4 * 1024 * 1024)

assert client.query query_for_target_packet_size(1 * 1024 * 1024)

assert client.query query_for_target_packet_size(2 * 1024 * 1024)

assert client.query query_for_target_packet_size(4 * 1024 * 1024)

exception = assert_raises Trilogy::QueryError do
client.query query_for_target_packet_size(4 * 1024 * 1024 + 1)
end

assert_equal exception.message, "trilogy_query_send: TRILOGY_MAX_PACKET_EXCEEDED"
ensure
ensure_closed client
end

def test_packet_size_greater_than_trilogy_max_packet_len
set_max_allowed_packet(32 * 1024 * 1024) # TRILOGY_MAX_PACKET_LEN is 16MB

client = new_tcp_client(max_allowed_packet: 32 * 1024 * 1024)

assert client.query query_for_target_packet_size(16 * 1024 * 1024)

assert client.query query_for_target_packet_size(32 * 1024 * 1024)

exception = assert_raises Trilogy::QueryError do
client.query query_for_target_packet_size(32 * 1024 * 1024 + 1)
end

assert_equal exception.message, "trilogy_query_send: TRILOGY_MAX_PACKET_EXCEEDED"
ensure
ensure_closed client
end

def test_configured_max_packet_below_server
set_max_allowed_packet(32 * 1024 * 1024)

client = new_tcp_client
client = new_tcp_client(max_allowed_packet: 24 * 1024 * 1024)

create_test_table(client)
client.query "TRUNCATE trilogy_test"
assert client.query query_for_target_packet_size(16 * 1024 * 1024)

result = client.query "INSERT INTO trilogy_test (blob_test) VALUES ('#{"x" * (15 * 1024 * 1024)}')"
assert result
assert_equal 1, client.last_insert_id
assert client.query query_for_target_packet_size(24 * 1024 * 1024)

result = client.query "INSERT INTO trilogy_test (blob_test) VALUES ('#{"x" * (31 * 1024 * 1024)}')"
assert result
assert_equal 2, client.last_insert_id
exception = assert_raises Trilogy::QueryError do
client.query query_for_target_packet_size(24 * 1024 * 1024 + 1)
end

assert_equal exception.message, "trilogy_query_send: TRILOGY_MAX_PACKET_EXCEEDED"
ensure
ensure_closed client
end

def test_configured_max_packet_above_server
set_max_allowed_packet(24 * 1024 * 1024)

client = new_tcp_client(max_allowed_packet: 32 * 1024 * 1024)

assert client.query query_for_target_packet_size(16 * 1024 * 1024)

assert client.query query_for_target_packet_size(24 * 1024 * 1024)

exception = assert_raises Trilogy::QueryError do
client.query query_for_target_packet_size(32 * 1024 * 1024 + 1)
end

assert_equal exception.message, "trilogy_query_send: TRILOGY_MAX_PACKET_EXCEEDED"

exception = assert_raises Trilogy::QueryError do
client.query query_for_target_packet_size(24 * 1024 * 1024 + 1)
end

refute_match exception.message, /TRILOGY_MAX_PACKET_EXCEEDED/
ensure
ensure_closed client
end

def test_absolute_maximum_packet_size
skip unless ENV["CI"]

set_max_allowed_packet(1024 * 1024 * 1024) # 1GB is the highest maximum allowed

client = new_tcp_client(max_allowed_packet: 1024 * 1024 * 1024)

assert client.query query_for_target_packet_size(1024 * 1024 * 1024)

exception = assert_raises Trilogy::QueryError do
client.query query_for_target_packet_size(1024 * 1024 * 1024 + 1)
end

assert_equal exception.message, "trilogy_query_send: TRILOGY_MAX_PACKET_EXCEEDED"
ensure
ensure_closed client
end
Expand Down

0 comments on commit e62ba20

Please sign in to comment.