Class: Mysql2::Client
Relationships & Source Files | |
Extension / Inclusion / Inheritance Descendants | |
Subclasses:
|
|
Inherits: | Object |
Defined in: | lib/mysql2/client.rb, ext/mysql2/client.c |
Class Method Summary
- .default_query_options
-
.escape(string)
Escape
string
so that it may be used in a SQL statement. -
.info
Returns a string that represents the client library version.
- .new(opts = {}) ⇒ Client constructor
- .local_offset private
Instance Attribute Summary
-
#automatic_close=(false)
rw
Set this to
false
to leave the connection open after it is garbage collected. - #automatic_close? ⇒ Boolean rw
- #closed? ⇒ Boolean readonly
-
#more_results? ⇒ Boolean
readonly
Returns true or false if there are more results to process.
- #query_options readonly
- #read_timeout rw
-
#reconnect=(true)
writeonly
Enable or disable the automatic reconnect behavior of libmysql.
- #charset_name=(value) writeonly private
- #connect_timeout=(value) writeonly private
- #default_auth=(value) writeonly private
- #default_file=(value) writeonly private
- #default_group=(value) writeonly private
- #enable_cleartext_plugin=(value) writeonly private
- #get_server_public_key=(value) writeonly private
- #init_command=(value) writeonly private
- #local_infile=(value) writeonly private
- #read_timeout=(value) rw private
- #secure_auth=(value) writeonly private
- #ssl_mode=(setting) writeonly private
- #write_timeout=(value) writeonly private
Instance Method Summary
-
#abandon_results!
When using MULTI_STATEMENTS support, calling this will throw away any unprocessed results as fast as it can in order to put the connection back into a state where queries can be issued again.
-
#affected_rows
returns the number of rows changed, deleted, or inserted by the last statement if it was an UPDATE, DELETE, or INSERT.
-
#async_result
Returns the result for the last async issued query.
-
#close ⇒ nil
Immediately disconnect from the server; normally the garbage collector will disconnect automatically when a connection is no longer needed.
-
#encoding
Returns the encoding set on the client.
-
#escape(string)
Escape
string
so that it may be used in a SQL statement. -
#find_default_ca_path
Find any default system CA paths to handle system roots by default if stricter validation is requested and no path is provide.
- #info
-
#last_id
Returns the value generated for an AUTO_INCREMENT column by the previous INSERT or UPDATE statement.
-
#next_result
Fetch the next result set from the server.
-
#parse_connect_attrs(conn_attrs)
Set default program_name in performance_schema.session_connect_attrs and performance_schema.session_account_connect_attrs.
- #parse_flags_array(flags, initial = 0)
- #parse_ssl_mode(mode)
-
#ping
Checks whether the connection to the server is working.
-
#prepare(#) ⇒ Mysql2::Statement
Create a new prepared statement.
- #query(sql, options = {})
- #query_info
- #query_info_string
-
#select_db(name)
Causes the database specified by
name
to become the default (current) database on the connection specified by mysql. -
#server_info
Returns a string that represents the server version number.
-
#session_track
Returns information about changes to the session state on the server.
-
#set_server_option(value)
Enables or disables an option for the connection.
- #socket
- #ssl_cipher
-
#store_result
Return the next result object from a query which yielded multiple result sets.
-
#thread_id
Returns the thread ID of the current connection.
- #warning_count
-
#query(sql, options = {})
private
Query the database with
sql
, with optionaloptions
. - #connect(user, pass, host, port, database, socket, flags, conn_attrs) private
- #initialize_ext private
- #ssl_set(key, cert, ca, capath, cipher) private
Constructor Details
.new(opts = {}) ⇒ Client
# File 'lib/mysql2/client.rb', line 21
def initialize(opts = {}) raise Mysql2::Error, "Options parameter must be a Hash" unless opts.is_a? Hash opts = Mysql2::Util.key_hash_as_symbols(opts) @read_timeout = nil @query_options = self.class. .dup @query_options.merge! opts initialize_ext # Set default connect_timeout to avoid unlimited retries from signal interruption opts[:connect_timeout] = 120 unless opts.key?(:connect_timeout) # TODO: stricter validation rather than silent massaging %i[reconnect connect_timeout local_infile read_timeout write_timeout default_file default_group secure_auth init_command automatic_close enable_cleartext_plugin default_auth get_server_public_key].each do |key| next unless opts.key?(key) case key when :reconnect, :local_infile, :secure_auth, :automatic_close, :enable_cleartext_plugin, :get_server_public_key send(:"#{key}=", !!opts[key]) # rubocop:disable Style/DoubleNegation when :connect_timeout, :read_timeout, :write_timeout send(:"#{key}=", Integer(opts[key])) unless opts[key].nil? else send(:"#{key}=", opts[key]) end end # force the encoding to utf8 self.charset_name = opts[:encoding] || 'utf8' mode = parse_ssl_mode(opts[:ssl_mode]) if opts[:ssl_mode] if (mode == SSL_MODE_VERIFY_CA || mode == SSL_MODE_VERIFY_IDENTITY) && !opts[:sslca] opts[:sslca] = find_default_ca_path end = opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslcipher) ssl_set(* ) if .any? || opts.key?(:sslverify) self.ssl_mode = mode if mode flags = case opts[:flags] when Array parse_flags_array(opts[:flags], @query_options[:connect_flags]) when String parse_flags_array(opts[:flags].split(' '), @query_options[:connect_flags]) when Integer @query_options[:connect_flags] | opts[:flags] else @query_options[:connect_flags] end # SSL verify is a connection flag rather than a mysql_ssl_set option flags |= SSL_VERIFY_SERVER_CERT if opts[:sslverify] if %i[user pass hostname dbname db sock].any? { |k| @query_options.key?(k) } warn "============= WARNING FROM mysql2 =============" warn "The options :user, :pass, :hostname, :dbname, :db, and :sock are deprecated and will be removed at some point in the future." warn "Instead, please use :username, :password, :host, :port, :database, :socket, :flags for the options." warn "============= END WARNING FROM mysql2 =========" end user = opts[:username] || opts[:user] pass = opts[:password] || opts[:pass] host = opts[:host] || opts[:hostname] port = opts[:port] database = opts[:database] || opts[:dbname] || opts[:db] socket = opts[:socket] || opts[:sock] # Correct the data types before passing these values down to the C level user = user.to_s unless user.nil? pass = pass.to_s unless pass.nil? host = host.to_s unless host.nil? port = port.to_i unless port.nil? database = database.to_s unless database.nil? socket = socket.to_s unless socket.nil? conn_attrs = parse_connect_attrs(opts[:connect_attrs]) connect user, pass, host, port, database, socket, flags, conn_attrs end
Class Method Details
.default_query_options
[ GitHub ]# File 'lib/mysql2/client.rb', line 5
def self. @default_query_options ||= { as: :hash, # the type of object you want each row back as; also supports :array (an array of values) async: false, # don't wait for a result after sending the query, you'll have to monitor the socket yourself then eventually call Mysql2::Client#async_result cast_booleans: false, # cast tinyint(1) fields as true/false in ruby symbolize_keys: false, # return field names as symbols instead of strings database_timezone: :local, # timezone Mysql2 will assume datetime objects are stored in application_timezone: nil, # timezone Mysql2 will convert to before handing the object back to the caller cache_rows: true, # tells Mysql2 to use its internal row cache for results connect_flags: REMEMBER_OPTIONS | LONG_PASSWORD | LONG_FLAG | TRANSACTIONS | PROTOCOL_41 | SECURE_CONNECTION | CONNECT_ATTRS, cast: true, default_file: nil, default_group: nil, } end
.escape(string)
Escape string
so that it may be used in a SQL statement. Note that this escape method is not connection encoding aware. If you need encoding support use #escape instead.
# File 'ext/mysql2/client.c', line 426
static VALUE rb_mysql_client_escape(RB_MYSQL_UNUSED VALUE klass, VALUE str) { unsigned char *newStr; VALUE rb_str; unsigned long newLen, oldLen; Check_Type(str, T_STRING); oldLen = RSTRING_LEN(str); newStr = xmalloc(oldLen*2+1); newLen = mysql_escape_string((char *)newStr, RSTRING_PTR(str), oldLen); if (newLen == oldLen) { /* no need to return a new ruby string if nothing changed */ xfree(newStr); return str; } else { rb_str = rb_str_new((const char*)newStr, newLen); rb_enc_copy(rb_str, str); xfree(newStr); return rb_str; } }
.info
Returns a string that represents the client library version.
# File 'ext/mysql2/client.c', line 1049
static VALUE rb_mysql_client_info(RB_MYSQL_UNUSED VALUE klass) { VALUE version_info, version, header_version; version_info = rb_hash_new(); version = rb_str_new2(mysql_get_client_info()); header_version = rb_str_new2(MYSQL_LINK_VERSION); rb_enc_associate(version, rb_usascii_encoding()); rb_enc_associate(header_version, rb_usascii_encoding()); rb_hash_aset(version_info, sym_id, LONG2NUM(mysql_get_client_version())); rb_hash_aset(version_info, sym_version, version); rb_hash_aset(version_info, sym_header_version, header_version); return version_info; }
.local_offset (private)
[ GitHub ]# File 'lib/mysql2/client.rb', line 171
def local_offset ::Time.local(2010).utc_offset.to_r / 86400 end
Instance Attribute Details
#automatic_close=(false) (rw)
Set this to false
to leave the connection open after it is garbage collected. To avoid “Aborted connection” errors on the server, explicitly call #close when the connection is no longer needed.
# File 'ext/mysql2/client.c', line 1351
static VALUE set_automatic_close(VALUE self, VALUE value) { GET_CLIENT(self); if (RTEST(value)) { wrapper->automatic_close = 1; } else { #ifndef _WIN32 wrapper->automatic_close = 0; #else rb_warn("Connections are always closed by garbage collector on Windows"); #endif } return value; }
#automatic_close? ⇒ Boolean
(rw)
# File 'ext/mysql2/client.c', line 1337
static VALUE get_automatic_close(VALUE self) { GET_CLIENT(self); return wrapper->automatic_close ? Qtrue : Qfalse; }
#charset_name=(value) (writeonly, private)
[ GitHub ]# File 'ext/mysql2/client.c', line 1414
static VALUE set_charset_name(VALUE self, VALUE value) { char *charset_name; const struct mysql2_mysql_enc_name_to_rb_map *mysql2rb; rb_encoding *enc; VALUE rb_enc; GET_CLIENT(self); Check_Type(value, T_STRING); charset_name = RSTRING_PTR(value); mysql2rb = mysql2_mysql_enc_name_to_rb(charset_name, (unsigned int)RSTRING_LEN(value)); if (mysql2rb == NULL || mysql2rb->rb_name == NULL) { VALUE inspect = rb_inspect(value); rb_raise(cMysql2Error, "Unsupported charset: '%s'", RSTRING_PTR(inspect)); } else { enc = rb_enc_find(mysql2rb->rb_name); rb_enc = rb_enc_from_encoding(enc); wrapper->encoding = rb_enc; } if (mysql_options(wrapper->client, MYSQL_SET_CHARSET_NAME, charset_name)) { /* TODO: warning - unable to set charset */ rb_warn("%s\n", mysql_error(wrapper->client)); } return value; }
#closed? ⇒ Boolean
(readonly)
# File 'ext/mysql2/client.c', line 583
static VALUE rb_mysql_client_closed(VALUE self) { GET_CLIENT(self); return CONNECTED(wrapper) ? Qfalse : Qtrue; }
#connect_timeout=(value) (writeonly, private)
[ GitHub ]# File 'ext/mysql2/client.c', line 1380
static VALUE set_connect_timeout(VALUE self, VALUE value) { long int sec; Check_Type(value, T_FIXNUM); sec = FIX2INT(value); if (sec < 0) { rb_raise(cMysql2Error, "connect_timeout must be a positive integer, you passed %ld", sec); } return _mysql_client_options(self, MYSQL_OPT_CONNECT_TIMEOUT, value); }
#default_auth=(value) (writeonly, private)
[ GitHub ]# File 'ext/mysql2/client.c', line 1503
static VALUE set_default_auth(VALUE self, VALUE value) { #ifdef HAVE_MYSQL_DEFAULT_AUTH return _mysql_client_options(self, MYSQL_DEFAULT_AUTH, value); #else rb_raise(cMysql2Error, "pluggable authentication is not available, you may need a newer MySQL client library"); #endif }
#default_file=(value) (writeonly, private)
[ GitHub ]# File 'ext/mysql2/client.c', line 1483
static VALUE set_read_default_file(VALUE self, VALUE value) { return _mysql_client_options(self, MYSQL_READ_DEFAULT_FILE, value); }
#default_group=(value) (writeonly, private)
[ GitHub ]# File 'ext/mysql2/client.c', line 1487
static VALUE set_read_default_group(VALUE self, VALUE value) { return _mysql_client_options(self, MYSQL_READ_DEFAULT_GROUP, value); }
#enable_cleartext_plugin=(value) (writeonly, private)
[ GitHub ]# File 'ext/mysql2/client.c', line 1511
static VALUE set_enable_cleartext_plugin(VALUE self, VALUE value) { #ifdef HAVE_CONST_MYSQL_ENABLE_CLEARTEXT_PLUGIN return _mysql_client_options(self, MYSQL_ENABLE_CLEARTEXT_PLUGIN, value); #else rb_raise(cMysql2Error, "enable-cleartext-plugin is not available, you may need a newer MySQL client library"); #endif }
#get_server_public_key=(value) (writeonly, private)
[ GitHub ]# File 'ext/mysql2/client.c', line 1495
static VALUE set_get_server_public_key(VALUE self, VALUE value) { #ifdef HAVE_CONST_MYSQL_OPT_GET_SERVER_PUBLIC_KEY return _mysql_client_options(self, MYSQL_OPT_GET_SERVER_PUBLIC_KEY, value); #else rb_raise(cMysql2Error, "get-server-public-key is not available, you may need a newer MySQL client library"); #endif }
#init_command=(value) (writeonly, private)
[ GitHub ]# File 'ext/mysql2/client.c', line 1491
static VALUE set_init_command(VALUE self, VALUE value) { return _mysql_client_options(self, MYSQL_INIT_COMMAND, value); }
#local_infile=(value) (writeonly, private)
[ GitHub ]# File 'ext/mysql2/client.c', line 1376
static VALUE set_local_infile(VALUE self, VALUE value) { return _mysql_client_options(self, MYSQL_OPT_LOCAL_INFILE, value); }
#more_results? ⇒ Boolean
(readonly)
Returns true or false if there are more results to process.
# File 'ext/mysql2/client.c', line 1260
static VALUE rb_mysql_client_more_results(VALUE self) { GET_CLIENT(self); if (mysql_more_results(wrapper->client) == 0) return Qfalse; else return Qtrue; }
#query_options (readonly)
[ GitHub ]# File 'lib/mysql2/client.rb', line 3
attr_reader :, :read_timeout
#read_timeout (rw)
[ GitHub ]# File 'lib/mysql2/client.rb', line 3
attr_reader :, :read_timeout
#read_timeout=(value) (rw, private)
[ GitHub ]# File 'ext/mysql2/client.c', line 1390
static VALUE set_read_timeout(VALUE self, VALUE value) { long int sec; Check_Type(value, T_FIXNUM); sec = FIX2INT(value); if (sec < 0) { rb_raise(cMysql2Error, "read_timeout must be a positive integer, you passed %ld", sec); } /* Set the instance variable here even though _mysql_client_options might not succeed, because the timeout is used in other ways elsewhere */ rb_ivar_set(self, intern_read_timeout, value); return _mysql_client_options(self, MYSQL_OPT_READ_TIMEOUT, value); }
#reconnect=(true) (writeonly)
Enable or disable the automatic reconnect behavior of libmysql. Read dev.mysql.com/doc/refman/5.5/en/auto-reconnect.html for more information.
# File 'ext/mysql2/client.c', line 1372
static VALUE set_reconnect(VALUE self, VALUE value) { return _mysql_client_options(self, MYSQL_OPT_RECONNECT, value); }
#secure_auth=(value) (writeonly, private)
[ GitHub ]# File 'ext/mysql2/client.c', line 1474
static VALUE set_secure_auth(VALUE self, VALUE value) { /* This option was deprecated in MySQL 5.x and removed in MySQL 8.0 */ #ifdef MYSQL_SECURE_AUTH return _mysql_client_options(self, MYSQL_SECURE_AUTH, value); #else return Qfalse; #endif }
#ssl_mode=(setting) (writeonly, private)
[ GitHub ]# File 'ext/mysql2/client.c', line 121
static VALUE rb_set_ssl_mode_option(VALUE self, VALUE setting) { unsigned long version = mysql_get_client_version(); const char *version_str = mysql_get_client_info(); /* Warn about versions that are known to be incomplete; these are pretty * ancient, we want people to upgrade if they need SSL/TLS to work * * MySQL 5.x before 5.6.30 -- ssl_mode introduced but not fully working until 5.6.36) * MySQL 5.7 before 5.7.3 -- ssl_mode introduced but not fully working until 5.7.11) */ if ((version >= 50000 && version < 50630) || (version >= 50700 && version < 50703)) { rb_warn("Your mysql client library version %s does not support setting ssl_mode; full support comes with 5.6.36+, 5.7.11+, 8.0+", version_str); return Qnil; } /* For these versions, map from the options we're exposing to Ruby to the constant available: * ssl_mode: :verify_identity to MYSQL_OPT_SSL_VERIFY_SERVER_CERT = 1 * ssl_mode: :required to MYSQL_OPT_SSL_ENFORCE = 1 * ssl_mode: :disabled to MYSQL_OPT_SSL_ENFORCE = 0 */ #if defined(HAVE_CONST_MYSQL_OPT_SSL_VERIFY_SERVER_CERT) || defined(HAVE_CONST_MYSQL_OPT_SSL_ENFORCE) GET_CLIENT(self); int val = NUM2INT(setting); /* Expected code path for MariaDB 10.x and MariaDB Connector/C 3.x * Workaround code path for MySQL 5.7.3 - 5.7.10 and MySQL Connector/C 6.1.3 - 6.1.x */ if (version >= 100000 // MariaDB (all versions numbered 10.x) || (version >= 30000 && version < 40000) // MariaDB Connector/C (all versions numbered 3.x) || (version >= 50703 && version < 50711) // Workaround for MySQL 5.7.3 - 5.7.10 || (version >= 60103 && version < 60200)) { // Workaround for MySQL Connector/C 6.1.3 - 6.1.x #ifdef HAVE_CONST_MYSQL_OPT_SSL_VERIFY_SERVER_CERT if (val == SSL_MODE_VERIFY_IDENTITY) { my_bool b = 1; int result = mysql_options(wrapper->client, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &b); return INT2NUM(result); } #endif #ifdef HAVE_CONST_MYSQL_OPT_SSL_ENFORCE if (val == SSL_MODE_DISABLED || val == SSL_MODE_REQUIRED) { my_bool b = (val == SSL_MODE_REQUIRED); int result = mysql_options(wrapper->client, MYSQL_OPT_SSL_ENFORCE, &b); return INT2NUM(result); } #endif rb_warn("Your mysql client library version %s does not support ssl_mode %d", version_str, val); return Qnil; } else { rb_warn("Your mysql client library version %s does not support ssl_mode as expected", version_str); return Qnil; } #endif /* For other versions -- known to be MySQL 5.6.36+, 5.7.11+, 8.0+ * pass the value of the argument to MYSQL_OPT_SSL_MODE -- note the code * mapping from atoms / constants is in the MySQL::Client Ruby class */ #ifdef FULL_SSL_MODE_SUPPORT GET_CLIENT(self); int val = NUM2INT(setting); if (val != SSL_MODE_DISABLED && val != SSL_MODE_PREFERRED && val != SSL_MODE_REQUIRED && val != SSL_MODE_VERIFY_CA && val != SSL_MODE_VERIFY_IDENTITY) { rb_raise(cMysql2Error, "ssl_mode= takes DISABLED, PREFERRED, REQUIRED, VERIFY_CA, VERIFY_IDENTITY, you passed: %d", val ); } int result = mysql_options(wrapper->client, MYSQL_OPT_SSL_MODE, &val); return INT2NUM(result); #endif // Warn if we get this far #ifdef NO_SSL_MODE_SUPPORT rb_warn("Your mysql client library does not support setting ssl_mode"); return Qnil; #endif }
#write_timeout=(value) (writeonly, private)
[ GitHub ]# File 'ext/mysql2/client.c', line 1404
static VALUE set_write_timeout(VALUE self, VALUE value) { long int sec; Check_Type(value, T_FIXNUM); sec = FIX2INT(value); if (sec < 0) { rb_raise(cMysql2Error, "write_timeout must be a positive integer, you passed %ld", sec); } return _mysql_client_options(self, MYSQL_OPT_WRITE_TIMEOUT, value); }
Instance Method Details
#query(sql, options = {}) (private)
Query the database with sql
, with optional options
. For the possible options, see default_query_options on the Client
class.
# File 'ext/mysql2/client.c', line 849
static VALUE rb_mysql_query(VALUE self, VALUE sql, VALUE current) { #ifndef _WIN32 struct async_query_args async_args; #endif struct nogvl_send_query_args args; GET_CLIENT(self); REQUIRE_CONNECTED(wrapper); args.mysql = wrapper->client; (void)RB_GC_GUARD(current); Check_Type(current, T_HASH); rb_ivar_set(self, intern_current_query_options, current); Check_Type(sql, T_STRING); /* ensure the string is in the encoding the connection is expecting */ args.sql = rb_str_export_to_enc(sql, rb_to_encoding(wrapper->encoding)); args.sql_ptr = RSTRING_PTR(args.sql); args.sql_len = RSTRING_LEN(args.sql); args.wrapper = wrapper; rb_mysql_client_set_active_fiber(self); #ifndef _WIN32 rb_rescue2(do_send_query, (VALUE)&args, disconnect_and_raise, self, rb_eException, (VALUE)0); (void)RB_GC_GUARD(sql); if (rb_hash_aref(current, sym_async) == Qtrue) { return Qnil; } else { async_args.fd = wrapper->client->net.fd; async_args.self = self; rb_rescue2(do_query, (VALUE)&async_args, disconnect_and_raise, self, rb_eException, (VALUE)0); return rb_ensure(rb_mysql_client_async_result, self, disconnect_and_mark_inactive, self); } #else do_send_query((VALUE)&args); (void)RB_GC_GUARD(sql); /* this will just block until the result is ready */ return rb_ensure(rb_mysql_client_async_result, self, disconnect_and_mark_inactive, self); #endif }
#abandon_results!
When using MULTI_STATEMENTS support, calling this will throw away any unprocessed results as fast as it can in order to put the connection back into a state where queries can be issued again.
# File 'ext/mysql2/client.c', line 821
static VALUE rb_mysql_client_abandon_results(VALUE self) { MYSQL_RES *result; int ret; GET_CLIENT(self); while (mysql_more_results(wrapper->client) == 1) { ret = mysql_next_result(wrapper->client); if (ret > 0) { rb_raise_mysql2_error(wrapper); } result = (MYSQL_RES *)rb_thread_call_without_gvl(nogvl_store_result, wrapper, RUBY_UBF_IO, 0); if (result != NULL) { mysql_free_result(result); } } return Qnil; }
#affected_rows
returns the number of rows changed, deleted, or inserted by the last statement if it was an UPDATE, DELETE, or INSERT.
# File 'ext/mysql2/client.c', line 1157
static VALUE rb_mysql_client_affected_rows(VALUE self) { my_ulonglong retVal; GET_CLIENT(self); REQUIRE_CONNECTED(wrapper); retVal = mysql_affected_rows(wrapper->client); if (retVal == (my_ulonglong)-1) { rb_raise_mysql2_error(wrapper); } return ULL2NUM(retVal); }
#async_result
Returns the result for the last async issued query.
# File 'ext/mysql2/client.c', line 656
static VALUE rb_mysql_client_async_result(VALUE self) { MYSQL_RES * result; VALUE resultObj; VALUE current, is_streaming; GET_CLIENT(self); /* if we're not waiting on a result, do nothing */ if (NIL_P(wrapper->active_fiber)) return Qnil; REQUIRE_CONNECTED(wrapper); if ((VALUE)rb_thread_call_without_gvl(nogvl_read_query_result, wrapper->client, RUBY_UBF_IO, 0) == Qfalse) { /* an error occurred, mark this connection inactive */ wrapper->active_fiber = Qnil; rb_raise_mysql2_error(wrapper); } is_streaming = rb_hash_aref(rb_ivar_get(self, intern_current_query_options), sym_stream); if (is_streaming == Qtrue) { result = (MYSQL_RES *)rb_thread_call_without_gvl(nogvl_use_result, wrapper, RUBY_UBF_IO, 0); } else { result = (MYSQL_RES *)rb_thread_call_without_gvl(nogvl_store_result, wrapper, RUBY_UBF_IO, 0); } if (result == NULL) { if (mysql_errno(wrapper->client) != 0) { wrapper->active_fiber = Qnil; rb_raise_mysql2_error(wrapper); } /* no data and no error, so query was not a SELECT */ return Qnil; } // Duplicate the options hash and put the copy in the Result object current = rb_hash_dup(rb_ivar_get(self, intern_current_query_options)); (void)RB_GC_GUARD(current); Check_Type(current, T_HASH); resultObj = rb_mysql_result_to_obj(self, wrapper->encoding, current, result, Qnil); rb_mysql_set_server_query_flags(wrapper->client, resultObj); return resultObj; }
#close ⇒ nil
Immediately disconnect from the server; normally the garbage collector will disconnect automatically when a connection is no longer needed. Explicitly closing this will free up server resources sooner than waiting for the garbage collector.
# File 'ext/mysql2/client.c', line 568
static VALUE rb_mysql_client_close(VALUE self) { GET_CLIENT(self); if (wrapper->client) { rb_thread_call_without_gvl(nogvl_close, wrapper, RUBY_UBF_IO, 0); } return Qnil; }
#connect(user, pass, host, port, database, socket, flags, conn_attrs) (private)
[ GitHub ]# File 'ext/mysql2/client.c', line 506
static VALUE rb_mysql_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE port, VALUE database, VALUE socket, VALUE flags, VALUE conn_attrs) { struct nogvl_connect_args args; time_t start_time, end_time, elapsed_time, connect_timeout; VALUE rv; GET_CLIENT(self); args.host = NIL_P(host) ? NULL : StringValueCStr(host); args.unix_socket = NIL_P(socket) ? NULL : StringValueCStr(socket); args.port = NIL_P(port) ? 0 : NUM2INT(port); args.user = NIL_P(user) ? NULL : StringValueCStr(user); args.passwd = NIL_P(pass) ? NULL : StringValueCStr(pass); args.db = NIL_P(database) ? NULL : StringValueCStr(database); args.mysql = wrapper->client; args.client_flag = NUM2ULONG(flags); #ifdef CLIENT_CONNECT_ATTRS mysql_options(wrapper->client, MYSQL_OPT_CONNECT_ATTR_RESET, 0); rb_hash_foreach(conn_attrs, opt_connect_attr_add_i, (VALUE)wrapper); #endif if (wrapper->connect_timeout) time(&start_time); rv = (VALUE) rb_thread_call_without_gvl(nogvl_connect, &args, RUBY_UBF_IO, 0); if (rv == Qfalse) { while (rv == Qfalse && errno == EINTR) { if (wrapper->connect_timeout) { time(&end_time); /* avoid long connect timeout from system time changes */ if (end_time < start_time) start_time = end_time; elapsed_time = end_time - start_time; /* avoid an early timeout due to time truncating milliseconds off the start time */ if (elapsed_time > 0) elapsed_time--; if (elapsed_time >= (time_t)wrapper->connect_timeout) break; connect_timeout = wrapper->connect_timeout - elapsed_time; mysql_options(wrapper->client, MYSQL_OPT_CONNECT_TIMEOUT, &connect_timeout); } errno = 0; rv = (VALUE) rb_thread_call_without_gvl(nogvl_connect, &args, RUBY_UBF_IO, 0); } /* restore the connect timeout for reconnecting */ if (wrapper->connect_timeout) mysql_options(wrapper->client, MYSQL_OPT_CONNECT_TIMEOUT, &wrapper->connect_timeout); if (rv == Qfalse) rb_raise_mysql2_error(wrapper); } wrapper->closed = 0; wrapper->server_version = mysql_get_server_version(wrapper->client); return self; }
#encoding
Returns the encoding set on the client.
# File 'ext/mysql2/client.c', line 1327
static VALUE rb_mysql_client_encoding(VALUE self) { GET_CLIENT(self); return wrapper->encoding; }
#escape(string)
Escape string
so that it may be used in a SQL statement.
# File 'ext/mysql2/client.c', line 900
static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) { unsigned char *newStr; VALUE rb_str; unsigned long newLen, oldLen; rb_encoding *default_internal_enc; rb_encoding *conn_enc; GET_CLIENT(self); REQUIRE_CONNECTED(wrapper); Check_Type(str, T_STRING); default_internal_enc = rb_default_internal_encoding(); conn_enc = rb_to_encoding(wrapper->encoding); /* ensure the string is in the encoding the connection is expecting */ str = rb_str_export_to_enc(str, conn_enc); oldLen = RSTRING_LEN(str); newStr = xmalloc(oldLen*2+1); newLen = mysql_real_escape_string(wrapper->client, (char *)newStr, RSTRING_PTR(str), oldLen); if (newLen == oldLen) { /* no need to return a new ruby string if nothing changed */ if (default_internal_enc) { str = rb_str_export_to_enc(str, default_internal_enc); } xfree(newStr); return str; } else { rb_str = rb_str_new((const char*)newStr, newLen); rb_enc_associate(rb_str, conn_enc); if (default_internal_enc) { rb_str = rb_str_export_to_enc(rb_str, default_internal_enc); } xfree(newStr); return rb_str; } }
#find_default_ca_path
Find any default system CA paths to handle system roots by default if stricter validation is requested and no path is provide.
# File 'lib/mysql2/client.rb', line 128
def find_default_ca_path [ "/etc/ssl/certs/ca-certificates.crt", "/etc/pki/tls/certs/ca-bundle.crt", "/etc/ssl/ca-bundle.pem", "/etc/ssl/cert.pem", ].find { |f| File.exist?(f) } end
#info
[ GitHub ]# File 'lib/mysql2/client.rb', line 164
def info self.class.info end
#initialize_ext (private)
[ GitHub ]# File 'ext/mysql2/client.c', line 1519
static VALUE initialize_ext(VALUE self) { GET_CLIENT(self); if ((VALUE)rb_thread_call_without_gvl(nogvl_init, wrapper, RUBY_UBF_IO, 0) == Qfalse) { /* TODO: warning - not enough memory? */ rb_raise_mysql2_error(wrapper); } wrapper->initialized = 1; return self; }
#last_id
Returns the value generated for an AUTO_INCREMENT column by the previous INSERT or UPDATE statement.
# File 'ext/mysql2/client.c', line 1115
static VALUE rb_mysql_client_last_id(VALUE self) { GET_CLIENT(self); REQUIRE_CONNECTED(wrapper); return ULL2NUM(mysql_insert_id(wrapper->client)); }
#next_result
Fetch the next result set from the server. Returns nothing.
# File 'ext/mysql2/client.c', line 1275
static VALUE rb_mysql_client_next_result(VALUE self) { int ret; GET_CLIENT(self); ret = mysql_next_result(wrapper->client); if (ret > 0) { rb_raise_mysql2_error(wrapper); return Qfalse; } else if (ret == 0) { return Qtrue; } else { return Qfalse; } }
#parse_connect_attrs(conn_attrs)
Set default program_name in performance_schema.session_connect_attrs and performance_schema.session_account_connect_attrs
# File 'lib/mysql2/client.rb', line 139
def parse_connect_attrs(conn_attrs) return {} if Mysql2::Client::CONNECT_ATTRS.zero? conn_attrs ||= {} conn_attrs[:program_name] ||= $PROGRAM_NAME conn_attrs.each_with_object({}) do |(key, value), hash| hash[key.to_s] = value.to_s end end
#parse_flags_array(flags, initial = 0)
[ GitHub ]# File 'lib/mysql2/client.rb', line 111
def parse_flags_array(flags, initial = 0) flags.reduce(initial) do |memo, f| fneg = f.start_with?('-') ? f[1..-1] : nil if fneg && fneg =~ /^\w+$/ && Mysql2::Client.const_defined?(fneg) memo & ~ Mysql2::Client.const_get(fneg) elsif f && f =~ /^\w+$/ && Mysql2::Client.const_defined?(f) memo | Mysql2::Client.const_get(f) else warn "Unknown MySQL connection flag: '#{f}'" memo end end end
#parse_ssl_mode(mode)
[ GitHub ]# File 'lib/mysql2/client.rb', line 100
def parse_ssl_mode(mode) m = mode.to_s.upcase if m.start_with?('SSL_MODE_') return Mysql2::Client.const_get(m) if Mysql2::Client.const_defined?(m) else x = 'SSL_MODE_' + m return Mysql2::Client.const_get(x) if Mysql2::Client.const_defined?(x) end warn "Unknown MySQL ssl_mode flag: #{mode}" end
#ping
Checks whether the connection to the server is working. If the connection has gone down and auto-reconnect is enabled an attempt to reconnect is made. If the connection is down and auto-reconnect is disabled, ping returns an error.
# File 'ext/mysql2/client.c', line 1228
static VALUE rb_mysql_client_ping(VALUE self) { GET_CLIENT(self); if (!CONNECTED(wrapper)) { return Qfalse; } else { return (VALUE)rb_thread_call_without_gvl(nogvl_ping, wrapper->client, RUBY_UBF_IO, 0); } }
#prepare(#) ⇒ Mysql2::Statement
Create a new prepared statement.
# File 'ext/mysql2/client.c', line 1535
static VALUE rb_mysql_client_prepare_statement(VALUE self, VALUE sql) { GET_CLIENT(self); REQUIRE_CONNECTED(wrapper); return rb_mysql_stmt_new(self, sql); }
#query(sql, options = {})
[ GitHub ]# File 'lib/mysql2/client.rb', line 149
def query(sql, = {}) Thread.handle_interrupt(::Mysql2::Util::TIMEOUT_ERROR_NEVER) do _query(sql, @query_options.merge( )) end end
#query_info
[ GitHub ]# File 'lib/mysql2/client.rb', line 155
def query_info info = query_info_string return {} unless info info_hash = {} info.split.each_slice(2) { |s| info_hash[s[0].downcase.delete(':').to_sym] = s[1].to_i } info_hash end
#query_info_string
[ GitHub ]# File 'ext/mysql2/client.c', line 458
static VALUE rb_mysql_info(VALUE self) { const char *info; VALUE rb_str; GET_CLIENT(self); info = mysql_info(wrapper->client); if (info == NULL) { return Qnil; } rb_str = rb_str_new2(info); rb_enc_associate(rb_str, rb_utf8_encoding()); return rb_str; }
#select_db(name)
Causes the database specified by name
to become the default (current) database on the connection specified by mysql.
# File 'ext/mysql2/client.c', line 1198
static VALUE rb_mysql_client_select_db(VALUE self, VALUE db) { struct nogvl_select_db_args args; GET_CLIENT(self); REQUIRE_CONNECTED(wrapper); args.mysql = wrapper->client; args.db = StringValueCStr(db); if (rb_thread_call_without_gvl(nogvl_select_db, &args, RUBY_UBF_IO, 0) == Qfalse) rb_raise_mysql2_error(wrapper); return db; }
#server_info
Returns a string that represents the server version number
# File 'ext/mysql2/client.c', line 1071
static VALUE rb_mysql_client_server_info(VALUE self) { VALUE version, server_info; rb_encoding *default_internal_enc; rb_encoding *conn_enc; GET_CLIENT(self); REQUIRE_CONNECTED(wrapper); default_internal_enc = rb_default_internal_encoding(); conn_enc = rb_to_encoding(wrapper->encoding); version = rb_hash_new(); rb_hash_aset(version, sym_id, LONG2FIX(mysql_get_server_version(wrapper->client))); server_info = rb_str_new2(mysql_get_server_info(wrapper->client)); rb_enc_associate(server_info, conn_enc); if (default_internal_enc) { server_info = rb_str_export_to_enc(server_info, default_internal_enc); } rb_hash_aset(version, sym_version, server_info); return version; }
#session_track
Returns information about changes to the session state on the server.
# File 'ext/mysql2/client.c', line 1126
static VALUE rb_mysql_client_session_track(VALUE self, VALUE type) { #ifdef CLIENT_SESSION_TRACK const char *data; size_t length; my_ulonglong retVal; GET_CLIENT(self); REQUIRE_CONNECTED(wrapper); retVal = mysql_session_track_get_first(wrapper->client, NUM2INT(type), &data, &length); if (retVal != 0) { return Qnil; } VALUE rbAry = rb_ary_new(); VALUE rbFirst = rb_str_new(data, length); rb_ary_push(rbAry, rbFirst); while(mysql_session_track_get_next(wrapper->client, NUM2INT(type), &data, &length) == 0) { VALUE rbNext = rb_str_new(data, length); rb_ary_push(rbAry, rbNext); } return rbAry; #else return Qnil; #endif }
#set_server_option(value)
Enables or disables an option for the connection. Read dev.mysql.com/doc/refman/5.7/en/mysql-set-server-option.html for more information.
# File 'ext/mysql2/client.c', line 1245
static VALUE rb_mysql_client_set_server_option(VALUE self, VALUE value) { GET_CLIENT(self); if (mysql_set_server_option(wrapper->client, NUM2INT(value)) == 0) { return Qtrue; } else { return Qfalse; } }
#socket
[ GitHub ]# File 'ext/mysql2/client.c', line 1104
static VALUE rb_mysql_client_socket(RB_MYSQL_UNUSED VALUE self) { rb_raise(cMysql2Error, "Raw access to the mysql file descriptor isn't supported on Windows"); }
#ssl_cipher
[ GitHub ]# File 'ext/mysql2/client.c', line 475
static VALUE rb_mysql_get_ssl_cipher(VALUE self) { const char *cipher; VALUE rb_str; GET_CLIENT(self); cipher = mysql_get_ssl_cipher(wrapper->client); if (cipher == NULL) { return Qnil; } rb_str = rb_str_new2(cipher); rb_enc_associate(rb_str, rb_utf8_encoding()); return rb_str; }
#ssl_set(key, cert, ca, capath, cipher) (private)
[ GitHub ]# File 'ext/mysql2/client.c', line 1442
static VALUE set_ssl_options(VALUE self, VALUE key, VALUE cert, VALUE ca, VALUE capath, VALUE cipher) { GET_CLIENT(self); #ifdef HAVE_MYSQL_SSL_SET mysql_ssl_set(wrapper->client, NIL_P(key) ? NULL : StringValueCStr(key), NIL_P(cert) ? NULL : StringValueCStr(cert), NIL_P(ca) ? NULL : StringValueCStr(ca), NIL_P(capath) ? NULL : StringValueCStr(capath), NIL_P(cipher) ? NULL : StringValueCStr(cipher)); #else /* mysql 8.3 does not provide mysql_ssl_set */ if (!NIL_P(key)) { mysql_options(wrapper->client, MYSQL_OPT_SSL_KEY, StringValueCStr(key)); } if (!NIL_P(cert)) { mysql_options(wrapper->client, MYSQL_OPT_SSL_CERT, StringValueCStr(cert)); } if (!NIL_P(ca)) { mysql_options(wrapper->client, MYSQL_OPT_SSL_CA, StringValueCStr(ca)); } if (!NIL_P(capath)) { mysql_options(wrapper->client, MYSQL_OPT_SSL_CAPATH, StringValueCStr(capath)); } if (!NIL_P(cipher)) { mysql_options(wrapper->client, MYSQL_OPT_SSL_CIPHER, StringValueCStr(cipher)); } #endif return self; }
#store_result
Return the next result object from a query which yielded multiple result sets.
# File 'ext/mysql2/client.c', line 1296
static VALUE rb_mysql_client_store_result(VALUE self) { MYSQL_RES * result; VALUE resultObj; VALUE current; GET_CLIENT(self); result = (MYSQL_RES *)rb_thread_call_without_gvl(nogvl_store_result, wrapper, RUBY_UBF_IO, 0); if (result == NULL) { if (mysql_errno(wrapper->client) != 0) { rb_raise_mysql2_error(wrapper); } /* no data and no error, so query was not a SELECT */ return Qnil; } // Duplicate the options hash and put the copy in the Result object current = rb_hash_dup(rb_ivar_get(self, intern_current_query_options)); (void)RB_GC_GUARD(current); Check_Type(current, T_HASH); resultObj = rb_mysql_result_to_obj(self, wrapper->encoding, current, result, Qnil); return resultObj; }
#thread_id
Returns the thread ID of the current connection.
# File 'ext/mysql2/client.c', line 1174
static VALUE rb_mysql_client_thread_id(VALUE self) { unsigned long retVal; GET_CLIENT(self); REQUIRE_CONNECTED(wrapper); retVal = mysql_thread_id(wrapper->client); return ULL2NUM(retVal); }
#warning_count
[ GitHub ]# File 'ext/mysql2/client.c', line 449
static VALUE rb_mysql_client_warning_count(VALUE self) { unsigned int warning_count; GET_CLIENT(self); warning_count = mysql_warning_count(wrapper->client); return UINT2NUM(warning_count); }