Skip to content

Commit 8d557b0

Browse files
kubosodabrew
authored andcommitted
Support connect attributes and set the script name to program_name attribute if it is not specified. (brianmario#760)
1 parent 811a57a commit 8d557b0

File tree

5 files changed

+51
-3
lines changed

5 files changed

+51
-3
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ Mysql2::Client.new(
203203
:read_timeout = seconds,
204204
:write_timeout = seconds,
205205
:connect_timeout = seconds,
206+
:connect_attrs = {:program_name => $PROGRAM_NAME, ...},
206207
:reconnect = true/false,
207208
:local_infile = true/false,
208209
:secure_auth = true/false,

ext/mysql2/client.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,20 @@ static VALUE rb_mysql_get_ssl_cipher(VALUE self)
400400
return rb_str;
401401
}
402402

403-
static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE port, VALUE database, VALUE socket, VALUE flags) {
403+
#ifdef HAVE_CONST_MYSQL_OPT_CONNECT_ATTR_ADD
404+
static int opt_connect_attr_add_i(VALUE key, VALUE value, VALUE arg)
405+
{
406+
mysql_client_wrapper *wrapper = (mysql_client_wrapper *)arg;
407+
rb_encoding *enc = rb_to_encoding(wrapper->encoding);
408+
key = rb_str_export_to_enc(key, enc);
409+
value = rb_str_export_to_enc(value, enc);
410+
411+
mysql_options4(wrapper->client, MYSQL_OPT_CONNECT_ATTR_ADD, StringValueCStr(key), StringValueCStr(value));
412+
return ST_CONTINUE;
413+
}
414+
#endif
415+
416+
static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE port, VALUE database, VALUE socket, VALUE flags, VALUE conn_attrs) {
404417
struct nogvl_connect_args args;
405418
time_t start_time, end_time, elapsed_time, connect_timeout;
406419
VALUE rv;
@@ -415,6 +428,11 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po
415428
args.mysql = wrapper->client;
416429
args.client_flag = NUM2ULONG(flags);
417430

431+
#ifdef HAVE_CONST_MYSQL_OPT_CONNECT_ATTR_ADD
432+
mysql_options(wrapper->client, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
433+
rb_hash_foreach(conn_attrs, opt_connect_attr_add_i, (VALUE)wrapper);
434+
#endif
435+
418436
if (wrapper->connect_timeout)
419437
time(&start_time);
420438
rv = (VALUE) rb_thread_call_without_gvl(nogvl_connect, &args, RUBY_UBF_IO, 0);
@@ -1403,7 +1421,7 @@ void init_mysql2_client() {
14031421
rb_define_private_method(cMysql2Client, "ssl_mode=", rb_set_ssl_mode_option, 1);
14041422
rb_define_private_method(cMysql2Client, "enable_cleartext_plugin=", set_enable_cleartext_plugin, 1);
14051423
rb_define_private_method(cMysql2Client, "initialize_ext", initialize_ext, 0);
1406-
rb_define_private_method(cMysql2Client, "connect", rb_connect, 7);
1424+
rb_define_private_method(cMysql2Client, "connect", rb_connect, 8);
14071425
rb_define_private_method(cMysql2Client, "_query", rb_query, 2);
14081426

14091427
sym_id = ID2SYM(rb_intern("id"));

ext/mysql2/extconf.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ def add_ssl_defines(header)
111111
have_struct_member('MYSQL', 'net.vio', mysql_h)
112112
have_struct_member('MYSQL', 'net.pvio', mysql_h)
113113
have_const('MYSQL_ENABLE_CLEARTEXT_PLUGIN', mysql_h)
114+
have_const('MYSQL_OPT_CONNECT_ATTR_ADD', mysql_h) # for mysql_options4
114115

115116
# This is our wishlist. We use whichever flags work on the host.
116117
# -Wall and -Wextra are included by default.

lib/mysql2/client.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ def initialize(opts = {})
6464
# SSL verify is a connection flag rather than a mysql_ssl_set option
6565
flags |= SSL_VERIFY_SERVER_CERT if opts[:sslverify]
6666

67+
# Set default program_name in performance_schema.session_connect_attrs
68+
# and performance_schema.session_account_connect_attrs
69+
conn_attrs = opts[:connect_attrs] || {}
70+
conn_attrs[:program_name] = $PROGRAM_NAME unless conn_attrs.key?(:program_name)
71+
6772
if [:user, :pass, :hostname, :dbname, :db, :sock].any? { |k| @query_options.key?(k) }
6873
warn "============= WARNING FROM mysql2 ============="
6974
warn "The options :user, :pass, :hostname, :dbname, :db, and :sock are deprecated and will be removed at some point in the future."
@@ -85,8 +90,11 @@ def initialize(opts = {})
8590
port = port.to_i unless port.nil?
8691
database = database.to_s unless database.nil?
8792
socket = socket.to_s unless socket.nil?
93+
conn_attrs = conn_attrs.each_with_object({}) do |(key, value), hash|
94+
hash[key.to_s] = value.to_s
95+
end
8896

89-
connect user, pass, host, port, database, socket, flags
97+
connect user, pass, host, port, database, socket, flags, conn_attrs
9098
end
9199

92100
def parse_ssl_mode(mode)

spec/mysql2/client_spec.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,26 @@ def run_gc
433433
expect(client.read_timeout).to be_nil
434434
end
435435

436+
it "should set default program_name in connect_attrs" do
437+
client = new_client
438+
if Mysql2::Client.info[:version] < '5.6' or client.info[:version] < '5.6'
439+
pending('Both client and server versions must be MySQL 5.6 or later.')
440+
end
441+
result = client.query("SELECT attr_value FROM performance_schema.session_account_connect_attrs WHERE processlist_id = connection_id() AND attr_name = 'program_name'")
442+
expect(result.first['attr_value']).to eq($0)
443+
end
444+
445+
it "should set custom connect_attrs" do
446+
client = new_client(:connect_attrs => {:program_name => 'my_program_name', :foo => 'fooval', :bar => 'barval'})
447+
if Mysql2::Client.info[:version] < '5.6' or client.info[:version] < '5.6'
448+
pending('Both client and server versions must be MySQL 5.6 or later.')
449+
end
450+
results = Hash[client.query("SELECT * FROM performance_schema.session_account_connect_attrs WHERE processlist_id = connection_id()").map { |x| x.values_at('ATTR_NAME', 'ATTR_VALUE') }]
451+
expect(results['program_name']).to eq('my_program_name')
452+
expect(results['foo']).to eq('fooval')
453+
expect(results['bar']).to eq('barval')
454+
end
455+
436456
context "#query" do
437457
it "should let you query again if iterating is finished when streaming" do
438458
@client.query("SELECT 1 UNION SELECT 2", :stream => true, :cache_rows => false).each.to_a

0 commit comments

Comments
 (0)