Class: Mysql2::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/mysql2/client.rb,
ext/mysql2/client.c

Direct Known Subclasses

EM::Client, Fibered::Client

Constant Summary collapse

CHARSET_MAP =
{
  "armscii8" => nil,
  "ascii"    => Encoding::US_ASCII,
  "big5"     => Encoding::Big5,
  "binary"   => Encoding::ASCII_8BIT,
  "cp1250"   => Encoding::Windows_1250,
  "cp1251"   => Encoding::Windows_1251,
  "cp1256"   => Encoding::Windows_1256,
  "cp1257"   => Encoding::Windows_1257,
  "cp850"    => Encoding::CP850,
  "cp852"    => Encoding::CP852,
  "cp866"    => Encoding::IBM866,
  "cp932"    => Encoding::Windows_31J,
  "dec8"     => nil,
  "eucjpms"  => Encoding::EucJP_ms,
  "euckr"    => Encoding::EUC_KR,
  "gb2312"   => Encoding::EUC_CN,
  "gbk"      => Encoding::GBK,
  "geostd8"  => nil,
  "greek"    => Encoding::ISO_8859_7,
  "hebrew"   => Encoding::ISO_8859_8,
  "hp8"      => nil,
  "keybcs2"  => nil,
  "koi8r"    => Encoding::KOI8_R,
  "koi8u"    => Encoding::KOI8_U,
  "latin1"   => Encoding::ISO_8859_1,
  "latin2"   => Encoding::ISO_8859_2,
  "latin5"   => Encoding::ISO_8859_9,
  "latin7"   => Encoding::ISO_8859_13,
  "macce"    => Encoding::MacCentEuro,
  "macroman" => Encoding::MacRoman,
  "sjis"     => Encoding::SHIFT_JIS,
  "swe7"     => nil,
  "tis620"   => Encoding::TIS_620,
  "ucs2"     => Encoding::UTF_16BE,
  "ujis"     => Encoding::EucJP_ms,
  "utf8"     => Encoding::UTF_8,
}
MYSQL_CHARSET_MAP =
{
  1 => {:name => "big5",      :collation => "big5_chinese_ci"},
  2 => {:name => "latin2",    :collation => "latin2_czech_cs"},
  3 => {:name => "dec8",      :collation => "dec8_swedish_ci"},
  4 => {:name => "cp850",     :collation => "cp850_general_ci"},
  5 => {:name => "latin1",    :collation => "latin1_german1_ci"},
  6 => {:name => "hp8",       :collation => "hp8_english_ci"},
  7 => {:name => "koi8r",     :collation => "koi8r_general_ci"},
  8 => {:name => "latin1",    :collation => "latin1_swedish_ci"},
  9 => {:name => "latin2",    :collation => "latin2_general_ci"},
  10 => {:name => "swe7",     :collation => "swe7_swedish_ci"},
  11 => {:name => "ascii",    :collation => "ascii_general_ci"},
  12 => {:name => "ujis",     :collation => "ujis_japanese_ci"},
  13 => {:name => "sjis",     :collation => "sjis_japanese_ci"},
  14 => {:name => "cp1251",   :collation => "cp1251_bulgarian_ci"},
  15 => {:name => "latin1",   :collation => "latin1_danish_ci"},
  16 => {:name => "hebrew",   :collation => "hebrew_general_ci"},
  17 => {:name => "filename", :collation => "filename"},
  18 => {:name => "tis620",   :collation => "tis620_thai_ci"},
  19 => {:name => "euckr",    :collation => "euckr_korean_ci"},
  20 => {:name => "latin7",   :collation => "latin7_estonian_cs"},
  21 => {:name => "latin2",   :collation => "latin2_hungarian_ci"},
  22 => {:name => "koi8u",    :collation => "koi8u_general_ci"},
  23 => {:name => "cp1251",   :collation => "cp1251_ukrainian_ci"},
  24 => {:name => "gb2312",   :collation => "gb2312_chinese_ci"},
  25 => {:name => "greek",    :collation => "greek_general_ci"},
  26 => {:name => "cp1250",   :collation => "cp1250_general_ci"},
  27 => {:name => "latin2",   :collation => "latin2_croatian_ci"},
  28 => {:name => "gbk",      :collation => "gbk_chinese_ci"},
  29 => {:name => "cp1257",   :collation => "cp1257_lithuanian_ci"},
  30 => {:name => "latin5",   :collation => "latin5_turkish_ci"},
  31 => {:name => "latin1",   :collation => "latin1_german2_ci"},
  32 => {:name => "armscii8", :collation => "armscii8_general_ci"},
  33 => {:name => "utf8",     :collation => "utf8_general_ci"},
  34 => {:name => "cp1250",   :collation => "cp1250_czech_cs"},
  35 => {:name => "ucs2",     :collation => "ucs2_general_ci"},
  36 => {:name => "cp866",    :collation => "cp866_general_ci"},
  37 => {:name => "keybcs2",  :collation => "keybcs2_general_ci"},
  38 => {:name => "macce",    :collation => "macce_general_ci"},
  39 => {:name => "macroman", :collation => "macroman_general_ci"},
  40 => {:name => "cp852",    :collation => "cp852_general_ci"},
  41 => {:name => "latin7",   :collation => "latin7_general_ci"},
  42 => {:name => "latin7",   :collation => "latin7_general_cs"},
  43 => {:name => "macce",    :collation => "macce_bin"},
  44 => {:name => "cp1250",   :collation => "cp1250_croatian_ci"},
  47 => {:name => "latin1",   :collation => "latin1_bin"},
  48 => {:name => "latin1",   :collation => "latin1_general_ci"},
  49 => {:name => "latin1",   :collation => "latin1_general_cs"},
  50 => {:name => "cp1251",   :collation => "cp1251_bin"},
  51 => {:name => "cp1251",   :collation => "cp1251_general_ci"},
  52 => {:name => "cp1251",   :collation => "cp1251_general_cs"},
  53 => {:name => "macroman", :collation => "macroman_bin"},
  57 => {:name => "cp1256",   :collation => "cp1256_general_ci"},
  58 => {:name => "cp1257",   :collation => "cp1257_bin"},
  59 => {:name => "cp1257",   :collation => "cp1257_general_ci"},
  63 => {:name => "binary",   :collation => "binary"},
  64 => {:name => "armscii8", :collation => "armscii8_bin"},
  65 => {:name => "ascii",    :collation => "ascii_bin"},
  66 => {:name => "cp1250",   :collation => "cp1250_bin"},
  67 => {:name => "cp1256",   :collation => "cp1256_bin"},
  68 => {:name => "cp866",    :collation => "cp866_bin"},
  69 => {:name => "dec8",     :collation => "dec8_bin"},
  70 => {:name => "greek",    :collation => "greek_bin"},
  71 => {:name => "hebrew",   :collation => "hebrew_bin"},
  72 => {:name => "hp8",      :collation => "hp8_bin"},
  73 => {:name => "keybcs2",  :collation => "keybcs2_bin"},
  74 => {:name => "koi8r",    :collation => "koi8r_bin"},
  75 => {:name => "koi8u",    :collation => "koi8u_bin"},
  77 => {:name => "latin2",   :collation => "latin2_bin"},
  78 => {:name => "latin5",   :collation => "latin5_bin"},
  79 => {:name => "latin7",   :collation => "latin7_bin"},
  80 => {:name => "cp850",    :collation => "cp850_bin"},
  81 => {:name => "cp852",    :collation => "cp852_bin"},
  82 => {:name => "swe7",     :collation => "swe7_bin"},
  83 => {:name => "utf8",     :collation => "utf8_bin"},
  84 => {:name => "big5",     :collation => "big5_bin"},
  85 => {:name => "euckr",    :collation => "euckr_bin"},
  86 => {:name => "gb2312",   :collation => "gb2312_bin"},
  87 => {:name => "gbk",      :collation => "gbk_bin"},
  88 => {:name => "sjis",     :collation => "sjis_bin"},
  89 => {:name => "tis620",   :collation => "tis620_bin"},
  90 => {:name => "ucs2",     :collation => "ucs2_bin"},
  91 => {:name => "ujis",     :collation => "ujis_bin"},
  92 => {:name => "geostd8",  :collation => "geostd8_general_ci"},
  93 => {:name => "geostd8",  :collation => "geostd8_bin"},
  94 => {:name => "latin1",   :collation => "latin1_spanish_ci"},
  95 => {:name => "cp932",    :collation => "cp932_japanese_ci"},
  96 => {:name => "cp932",    :collation => "cp932_bin"},
  97 => {:name => "eucjpms",  :collation => "eucjpms_japanese_ci"},
  98 => {:name => "eucjpms",  :collation => "eucjpms_bin"},
  99 => {:name => "cp1250",   :collation => "cp1250_polish_ci"},
  128 => {:name => "ucs2",    :collation => "ucs2_unicode_ci"},
  129 => {:name => "ucs2",    :collation => "ucs2_icelandic_ci"},
  130 => {:name => "ucs2",    :collation => "ucs2_latvian_ci"},
  131 => {:name => "ucs2",    :collation => "ucs2_romanian_ci"},
  132 => {:name => "ucs2",    :collation => "ucs2_slovenian_ci"},
  133 => {:name => "ucs2",    :collation => "ucs2_polish_ci"},
  134 => {:name => "ucs2",    :collation => "ucs2_estonian_ci"},
  135 => {:name => "ucs2",    :collation => "ucs2_spanish_ci"},
  136 => {:name => "ucs2",    :collation => "ucs2_swedish_ci"},
  137 => {:name => "ucs2",    :collation => "ucs2_turkish_ci"},
  138 => {:name => "ucs2",    :collation => "ucs2_czech_ci"},
  139 => {:name => "ucs2",    :collation => "ucs2_danish_ci"},
  140 => {:name => "ucs2",    :collation => "ucs2_lithuanian_ci"},
  141 => {:name => "ucs2",    :collation => "ucs2_slovak_ci"},
  142 => {:name => "ucs2",    :collation => "ucs2_spanish2_ci"},
  143 => {:name => "ucs2",    :collation => "ucs2_roman_ci"},
  144 => {:name => "ucs2",    :collation => "ucs2_persian_ci"},
  145 => {:name => "ucs2",    :collation => "ucs2_esperanto_ci"},
  146 => {:name => "ucs2",    :collation => "ucs2_hungarian_ci"},
  192 => {:name => "utf8",    :collation => "utf8_unicode_ci"},
  193 => {:name => "utf8",    :collation => "utf8_icelandic_ci"},
  194 => {:name => "utf8",    :collation => "utf8_latvian_ci"},
  195 => {:name => "utf8",    :collation => "utf8_romanian_ci"},
  196 => {:name => "utf8",    :collation => "utf8_slovenian_ci"},
  197 => {:name => "utf8",    :collation => "utf8_polish_ci"},
  198 => {:name => "utf8",    :collation => "utf8_estonian_ci"},
  199 => {:name => "utf8",    :collation => "utf8_spanish_ci"},
  200 => {:name => "utf8",    :collation => "utf8_swedish_ci"},
  201 => {:name => "utf8",    :collation => "utf8_turkish_ci"},
  202 => {:name => "utf8",    :collation => "utf8_czech_ci"},
  203 => {:name => "utf8",    :collation => "utf8_danish_ci"},
  204 => {:name => "utf8",    :collation => "utf8_lithuanian_ci"},
  205 => {:name => "utf8",    :collation => "utf8_slovak_ci"},
  206 => {:name => "utf8",    :collation => "utf8_spanish2_ci"},
  207 => {:name => "utf8",    :collation => "utf8_roman_ci"},
  208 => {:name => "utf8",    :collation => "utf8_persian_ci"},
  209 => {:name => "utf8",    :collation => "utf8_esperanto_ci"},
  210 => {:name => "utf8",    :collation => "utf8_hungarian_ci"},
  254 => {:name => "utf8",    :collation => "utf8_general_cs"}
}
@@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 it's internal row cache for results
  :connect_flags => REMEMBER_OPTIONS | LONG_PASSWORD | LONG_FLAG | TRANSACTIONS | PROTOCOL_41 | SECURE_CONNECTION
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Client

Returns a new instance of Client.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/mysql2/client.rb', line 15

def initialize(opts = {})
  @query_options = @@default_query_options.dup

  init_connection

  [:reconnect, :connect_timeout].each do |key|
    next unless opts.key?(key)
    send(:"#{key}=", opts[key])
  end
  # force the encoding to utf8
  self.charset_name = opts[:encoding] || 'utf8'

  @read_timeout = opts[:read_timeout]
  if @read_timeout and @read_timeout < 0
    raise Mysql2::Error, "read_timeout must be a positive integer, you passed #{@read_timeout}"
  end

  ssl_set(*opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslciper))

  user     = opts[:username]
  pass     = opts[:password]
  host     = opts[:host] || 'localhost'
  port     = opts[:port] || 3306
  database = opts[:database]
  socket   = opts[:socket]
  flags    = opts[:flags] ? opts[:flags] | @query_options[:connect_flags] : @query_options[:connect_flags]

  connect user, pass, host, port, database, socket, flags
end

Instance Attribute Details

#query_optionsObject (readonly)

Returns the value of attribute query_options.



3
4
5
# File 'lib/mysql2/client.rb', line 3

def query_options
  @query_options
end

Class Method Details

.default_query_optionsObject



45
46
47
# File 'lib/mysql2/client.rb', line 45

def self.default_query_options
  @@default_query_options
end

.encoding_from_charset(charset) ⇒ Object



222
223
224
# File 'lib/mysql2/client.rb', line 222

def self.encoding_from_charset(charset)
  CHARSET_MAP[charset.to_s.downcase]
end

.encoding_from_charset_code(code) ⇒ Object



226
227
228
229
230
231
232
# File 'lib/mysql2/client.rb', line 226

def self.encoding_from_charset_code(code)
  if mapping = MYSQL_CHARSET_MAP[code]
    encoding_from_charset(mapping[:name])
  else
    nil
  end
end

Instance Method Details

#affected_rowsObject



488
489
490
491
492
493
494
495
496
497
498
# File 'ext/mysql2/client.c', line 488

static VALUE rb_mysql_client_affected_rows(VALUE self) {
  my_ulonglong retVal;
  GET_CLIENT(self);

  REQUIRE_OPEN_DB(wrapper);
  retVal = mysql_affected_rows(wrapper->client);
  if (retVal == (my_ulonglong)-1) {
    rb_raise_mysql2_error(wrapper->client);
  }
  return ULL2NUM(retVal);
}

#async_resultObject



231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'ext/mysql2/client.c', line 231

static VALUE rb_mysql_client_async_result(VALUE self) {
  MYSQL_RES * result;
  VALUE resultObj;
#ifdef HAVE_RUBY_ENCODING_H
  mysql2_result_wrapper * result_wrapper;
#endif
  GET_CLIENT(self);

  REQUIRE_OPEN_DB(wrapper);
  if (rb_thread_blocking_region(nogvl_read_query_result, wrapper->client, RUBY_UBF_IO, 0) == Qfalse) {
    // an error occurred, mark this connection inactive
    MARK_CONN_INACTIVE(self);
    return rb_raise_mysql2_error(wrapper->client);
  }

  result = (MYSQL_RES *)rb_thread_blocking_region(nogvl_store_result, wrapper->client, RUBY_UBF_IO, 0);

  // we have our result, mark this connection inactive
  MARK_CONN_INACTIVE(self);

  if (result == NULL) {
    if (mysql_field_count(wrapper->client) != 0) {
      rb_raise_mysql2_error(wrapper->client);
    }
    return Qnil;
  }

  resultObj = rb_mysql_result_to_obj(result);
  // pass-through query options for result construction later
  rb_iv_set(resultObj, "@query_options", rb_funcall(rb_iv_get(self, "@query_options"), rb_intern("dup"), 0));

#ifdef HAVE_RUBY_ENCODING_H
  GetMysql2Result(resultObj, result_wrapper);
  result_wrapper->encoding = wrapper->encoding;
#endif
  return resultObj;
}

#closeObject

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.



187
188
189
190
191
192
193
194
195
# File 'ext/mysql2/client.c', line 187

static VALUE rb_mysql_client_close(VALUE self) {
  GET_CLIENT(self);

  if (!wrapper->closed) {
    rb_thread_blocking_region(nogvl_close, wrapper, RUBY_UBF_IO, 0);
  }

  return Qnil;
}

#escape(str) ⇒ Object



386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
# File 'ext/mysql2/client.c', line 386

static VALUE rb_mysql_client_escape(VALUE self, VALUE str) {
  VALUE newStr;
  unsigned long newLen, oldLen;
#ifdef HAVE_RUBY_ENCODING_H
  rb_encoding *default_internal_enc;
  rb_encoding *conn_enc;
#endif
  GET_CLIENT(self);

  REQUIRE_OPEN_DB(wrapper);
  Check_Type(str, T_STRING);
#ifdef HAVE_RUBY_ENCODING_H
  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);
#endif

  oldLen = RSTRING_LEN(str);
  newStr = rb_str_new(0, oldLen*2+1);

  newLen = mysql_real_escape_string(wrapper->client, RSTRING_PTR(newStr), StringValuePtr(str), oldLen);
  if (newLen == oldLen) {
    // no need to return a new ruby string if nothing changed
    return str;
  } else {
    rb_str_resize(newStr, newLen);
#ifdef HAVE_RUBY_ENCODING_H
    rb_enc_associate(newStr, conn_enc);
    if (default_internal_enc) {
      newStr = rb_str_export_to_enc(newStr, default_internal_enc);
    }
#endif
    return newStr;
  }
}

#infoObject



423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
# File 'ext/mysql2/client.c', line 423

static VALUE rb_mysql_client_info(VALUE self) {
  VALUE version, client_info;
#ifdef HAVE_RUBY_ENCODING_H
  rb_encoding *default_internal_enc;
  rb_encoding *conn_enc;
#endif
  GET_CLIENT(self);
  version = rb_hash_new();

#ifdef HAVE_RUBY_ENCODING_H
  default_internal_enc = rb_default_internal_encoding();
  conn_enc = rb_to_encoding(wrapper->encoding);
#endif

  rb_hash_aset(version, sym_id, LONG2NUM(mysql_get_client_version()));
  client_info = rb_str_new2(mysql_get_client_info());
#ifdef HAVE_RUBY_ENCODING_H
  rb_enc_associate(client_info, conn_enc);
  if (default_internal_enc) {
    client_info = rb_str_export_to_enc(client_info, default_internal_enc);
  }
#endif
  rb_hash_aset(version, sym_version, client_info);
  return version;
}

#last_idObject



482
483
484
485
486
# File 'ext/mysql2/client.c', line 482

static VALUE rb_mysql_client_last_id(VALUE self) {
  GET_CLIENT(self);
  REQUIRE_OPEN_DB(wrapper);
  return ULL2NUM(mysql_insert_id(wrapper->client));
}

#pingObject



509
510
511
512
513
514
515
516
517
518
519
# File 'ext/mysql2/client.c', line 509

static VALUE rb_mysql_client_ping(VALUE self) {
  unsigned long retVal;
  GET_CLIENT(self);

  retVal = mysql_ping(wrapper->client);
  if (retVal == 0) {
    return Qtrue;
  } else {
    return Qfalse;
  }
}

#query(*args) ⇒ Object



269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
# File 'ext/mysql2/client.c', line 269

static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
  struct nogvl_send_query_args args;
  fd_set fdset;
  int fd, retval;
  int async = 0;
  VALUE opts, defaults, read_timeout;
#ifdef HAVE_RUBY_ENCODING_H
  rb_encoding *conn_enc;
#endif
  struct timeval tv;
  struct timeval* tvp;
  long int sec;
  VALUE result;
  GET_CLIENT(self);

  REQUIRE_OPEN_DB(wrapper);
  args.mysql = wrapper->client;

  // see if this connection is still waiting on a result from a previous query
  if (wrapper->active == 0) {
    // mark this connection active
    wrapper->active = 1;
  } else {
    rb_raise(cMysql2Error, "This connection is still waiting for a result, try again once you have the result");
  }

  defaults = rb_iv_get(self, "@query_options");
  if (rb_scan_args(argc, argv, "11", &args.sql, &opts) == 2) {
    opts = rb_funcall(defaults, intern_merge, 1, opts);
    rb_iv_set(self, "@query_options", opts);

    if (rb_hash_aref(opts, sym_async) == Qtrue) {
      async = 1;
    }
  } else {
    opts = defaults;
  }

  Check_Type(args.sql, T_STRING);
#ifdef HAVE_RUBY_ENCODING_H
  conn_enc = rb_to_encoding(wrapper->encoding);
  // ensure the string is in the encoding the connection is expecting
  args.sql = rb_str_export_to_enc(args.sql, conn_enc);
#endif

  if (rb_thread_blocking_region(nogvl_send_query, &args, RUBY_UBF_IO, 0) == Qfalse) {
    // an error occurred, we're not active anymore
    MARK_CONN_INACTIVE(self);
    return rb_raise_mysql2_error(wrapper->client);
  }

  read_timeout = rb_iv_get(self, "@read_timeout");

  tvp = NULL;
  if (!NIL_P(read_timeout)) {
    Check_Type(read_timeout, T_FIXNUM);
    tvp = &tv;
    sec = FIX2INT(read_timeout);
    // TODO: support partial seconds?
    // also, this check is here for sanity, we also check up in Ruby
    if (sec >= 0) {
      tvp->tv_sec = sec;
    } else {
      rb_raise(cMysql2Error, "read_timeout must be a positive integer, you passed %ld", sec);
    }
    tvp->tv_usec = 0;
  }

  if (!async) {
    // the below code is largely from do_mysql
    // http://github.com/datamapper/do
    fd = wrapper->client->net.fd;
    for(;;) {
      int fd_set_fd = fd;

#ifdef _WIN32
      WSAPROTOCOL_INFO wsa_pi;
      // dupicate the SOCKET from libmysql
      int r = WSADuplicateSocket(fd, GetCurrentProcessId(), &wsa_pi);
      SOCKET s = WSASocket(wsa_pi.iAddressFamily, wsa_pi.iSocketType, wsa_pi.iProtocol, &wsa_pi, 0, 0);
      // create the CRT fd so ruby can get back to the SOCKET
      fd_set_fd = _open_osfhandle(s, O_RDWR|O_BINARY);
#endif

      FD_ZERO(&fdset);
      FD_SET(fd_set_fd, &fdset);

      retval = rb_thread_select(fd_set_fd + 1, &fdset, NULL, NULL, tvp);

#ifdef _WIN32
      // cleanup the CRT fd
      _close(fd_set_fd);
      // cleanup the duplicated SOCKET
      closesocket(s);
#endif

      if (retval == 0) {
        rb_raise(cMysql2Error, "Timeout waiting for a response from the last query. (waited %d seconds)", FIX2INT(read_timeout));
      }

      if (retval < 0) {
        rb_sys_fail(0);
      }

      if (retval > 0) {
        break;
      }
    }

    result = rb_mysql_client_async_result(self);

    return result;
  } else {
    return Qnil;
  }
}

#server_infoObject



449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
# File 'ext/mysql2/client.c', line 449

static VALUE rb_mysql_client_server_info(VALUE self) {
  VALUE version, server_info;
#ifdef HAVE_RUBY_ENCODING_H
  rb_encoding *default_internal_enc;
  rb_encoding *conn_enc;
#endif
  GET_CLIENT(self);

  REQUIRE_OPEN_DB(wrapper);
#ifdef HAVE_RUBY_ENCODING_H
  default_internal_enc = rb_default_internal_encoding();
  conn_enc = rb_to_encoding(wrapper->encoding);
#endif

  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));
#ifdef HAVE_RUBY_ENCODING_H
  rb_enc_associate(server_info, conn_enc);
  if (default_internal_enc) {
    server_info = rb_str_export_to_enc(server_info, default_internal_enc);
  }
#endif
  rb_hash_aset(version, sym_version, server_info);
  return version;
}

#socketObject



476
477
478
479
480
# File 'ext/mysql2/client.c', line 476

static VALUE rb_mysql_client_socket(VALUE self) {
  GET_CLIENT(self);
  REQUIRE_OPEN_DB(wrapper);
  return INT2NUM(wrapper->client->net.fd);
}

#thread_idObject



500
501
502
503
504
505
506
507
# File 'ext/mysql2/client.c', line 500

static VALUE rb_mysql_client_thread_id(VALUE self) {
  unsigned long retVal;
  GET_CLIENT(self);

  REQUIRE_OPEN_DB(wrapper);
  retVal = mysql_thread_id(wrapper->client);
  return ULL2NUM(retVal);
}