mysql2 0.3.18 → 0.3.19

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 791bc0352c6464ca1765498b0babcedfad3c284e
4
- data.tar.gz: 08b44b761494ec18a0c9903fcb67bfe61718b77b
3
+ metadata.gz: 927d6afad1ca42286f65ccdabaab7221b0d40ba5
4
+ data.tar.gz: 01941e7450c35c68243880b1c09646c398a64362
5
5
  SHA512:
6
- metadata.gz: 5554897f395a4fcd71e26612ef895da5d3e1d528ef29604380974950f7216783bf7636197d04228c39b471a51863f75c56e9140e05bb79410e1582c64842d0dc
7
- data.tar.gz: afad060a7a899d69b75ca2c44aa69a07c743984fc6897cce825c6d9ec3269bbb3733671243afe7fb33a615e61e4aa8c7b9e7863fa18289578ab29abc8409e2e8
6
+ metadata.gz: 03f2cba3cf55e78b04d1afc30405e7cfdabf473d253688dfb470b4fa685549421a9c3db148535e2b6dce3f6929c9ae9ac84aff452cbeaadff12c76f562bbd8a9
7
+ data.tar.gz: c5425db807f77acd11cf7eca9ea3108d08993d87385ecc028a90e5c9f6032e9069a4c279e066181f3d9e2565a1acddade6545318647ee6977d4211ee7d4f568a
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Brian Lopez
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -16,7 +16,7 @@
16
16
 
17
17
  VALUE cMysql2Client;
18
18
  extern VALUE mMysql2, cMysql2Error;
19
- static VALUE sym_id, sym_version, sym_async, sym_symbolize_keys, sym_as, sym_array, sym_stream;
19
+ static VALUE sym_id, sym_version, sym_header_version, sym_async, sym_symbolize_keys, sym_as, sym_array, sym_stream;
20
20
  static ID intern_merge, intern_merge_bang, intern_error_number_eql, intern_sql_state_eql;
21
21
 
22
22
  #ifndef HAVE_RB_HASH_DUP
@@ -287,7 +287,7 @@ static VALUE rb_mysql_client_escape(RB_MYSQL_UNUSED VALUE klass, VALUE str) {
287
287
  oldLen = RSTRING_LEN(str);
288
288
  newStr = xmalloc(oldLen*2+1);
289
289
 
290
- newLen = mysql_escape_string((char *)newStr, StringValuePtr(str), oldLen);
290
+ newLen = mysql_escape_string((char *)newStr, RSTRING_PTR(str), oldLen);
291
291
  if (newLen == oldLen) {
292
292
  /* no need to return a new ruby string if nothing changed */
293
293
  xfree(newStr);
@@ -337,13 +337,13 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po
337
337
  VALUE rv;
338
338
  GET_CLIENT(self);
339
339
 
340
- args.host = NIL_P(host) ? NULL : StringValuePtr(host);
341
- args.unix_socket = NIL_P(socket) ? NULL : StringValuePtr(socket);
342
- args.port = NIL_P(port) ? 0 : NUM2INT(port);
343
- args.user = NIL_P(user) ? NULL : StringValuePtr(user);
344
- args.passwd = NIL_P(pass) ? NULL : StringValuePtr(pass);
345
- args.db = NIL_P(database) ? NULL : StringValuePtr(database);
346
- args.mysql = wrapper->client;
340
+ args.host = NIL_P(host) ? NULL : StringValueCStr(host);
341
+ args.unix_socket = NIL_P(socket) ? NULL : StringValueCStr(socket);
342
+ args.port = NIL_P(port) ? 0 : NUM2INT(port);
343
+ args.user = NIL_P(user) ? NULL : StringValueCStr(user);
344
+ args.passwd = NIL_P(pass) ? NULL : StringValueCStr(pass);
345
+ args.db = NIL_P(database) ? NULL : StringValueCStr(database);
346
+ args.mysql = wrapper->client;
347
347
  args.client_flag = NUM2ULONG(flags);
348
348
 
349
349
  if (wrapper->connect_timeout)
@@ -669,7 +669,7 @@ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
669
669
  /* ensure the string is in the encoding the connection is expecting */
670
670
  args.sql = rb_str_export_to_enc(args.sql, conn_enc);
671
671
  #endif
672
- args.sql_ptr = StringValuePtr(args.sql);
672
+ args.sql_ptr = RSTRING_PTR(args.sql);
673
673
  args.sql_len = RSTRING_LEN(args.sql);
674
674
 
675
675
  /* see if this connection is still waiting on a result from a previous query */
@@ -736,9 +736,14 @@ static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) {
736
736
  oldLen = RSTRING_LEN(str);
737
737
  newStr = xmalloc(oldLen*2+1);
738
738
 
739
- newLen = mysql_real_escape_string(wrapper->client, (char *)newStr, StringValuePtr(str), oldLen);
739
+ newLen = mysql_real_escape_string(wrapper->client, (char *)newStr, RSTRING_PTR(str), oldLen);
740
740
  if (newLen == oldLen) {
741
741
  /* no need to return a new ruby string if nothing changed */
742
+ #ifdef HAVE_RUBY_ENCODING_H
743
+ if (default_internal_enc) {
744
+ str = rb_str_export_to_enc(str, default_internal_enc);
745
+ }
746
+ #endif
742
747
  xfree(newStr);
743
748
  return str;
744
749
  } else {
@@ -800,17 +805,17 @@ static VALUE _mysql_client_options(VALUE self, int opt, VALUE value) {
800
805
  break;
801
806
 
802
807
  case MYSQL_READ_DEFAULT_FILE:
803
- charval = (const char *)StringValuePtr(value);
808
+ charval = (const char *)StringValueCStr(value);
804
809
  retval = charval;
805
810
  break;
806
811
 
807
812
  case MYSQL_READ_DEFAULT_GROUP:
808
- charval = (const char *)StringValuePtr(value);
813
+ charval = (const char *)StringValueCStr(value);
809
814
  retval = charval;
810
815
  break;
811
816
 
812
817
  case MYSQL_INIT_COMMAND:
813
- charval = (const char *)StringValuePtr(value);
818
+ charval = (const char *)StringValueCStr(value);
814
819
  retval = charval;
815
820
  break;
816
821
 
@@ -843,30 +848,23 @@ static VALUE _mysql_client_options(VALUE self, int opt, VALUE value) {
843
848
  *
844
849
  * Returns a string that represents the client library version.
845
850
  */
846
- static VALUE rb_mysql_client_info(VALUE self) {
847
- VALUE version, client_info;
848
- #ifdef HAVE_RUBY_ENCODING_H
849
- rb_encoding *default_internal_enc;
850
- rb_encoding *conn_enc;
851
- GET_CLIENT(self);
852
- #endif
853
- version = rb_hash_new();
851
+ static VALUE rb_mysql_client_info(RB_MYSQL_UNUSED VALUE klass) {
852
+ VALUE version_info, version, header_version;
853
+ version_info = rb_hash_new();
854
854
 
855
- #ifdef HAVE_RUBY_ENCODING_H
856
- default_internal_enc = rb_default_internal_encoding();
857
- conn_enc = rb_to_encoding(wrapper->encoding);
858
- #endif
855
+ version = rb_str_new2(mysql_get_client_info());
856
+ header_version = rb_str_new2(MYSQL_LINK_VERSION);
859
857
 
860
- rb_hash_aset(version, sym_id, LONG2NUM(mysql_get_client_version()));
861
- client_info = rb_str_new2(mysql_get_client_info());
862
858
  #ifdef HAVE_RUBY_ENCODING_H
863
- rb_enc_associate(client_info, conn_enc);
864
- if (default_internal_enc) {
865
- client_info = rb_str_export_to_enc(client_info, default_internal_enc);
866
- }
859
+ rb_enc_associate(version, rb_usascii_encoding());
860
+ rb_enc_associate(header_version, rb_usascii_encoding());
867
861
  #endif
868
- rb_hash_aset(version, sym_version, client_info);
869
- return version;
862
+
863
+ rb_hash_aset(version_info, sym_id, LONG2NUM(mysql_get_client_version()));
864
+ rb_hash_aset(version_info, sym_version, version);
865
+ rb_hash_aset(version_info, sym_header_version, header_version);
866
+
867
+ return version_info;
870
868
  }
871
869
 
872
870
  /* call-seq:
@@ -907,14 +905,10 @@ static VALUE rb_mysql_client_server_info(VALUE self) {
907
905
  * Return the file descriptor number for this client.
908
906
  */
909
907
  static VALUE rb_mysql_client_socket(VALUE self) {
910
- GET_CLIENT(self);
911
908
  #ifndef _WIN32
912
- {
913
- int fd_set_fd;
914
- REQUIRE_CONNECTED(wrapper);
915
- fd_set_fd = wrapper->client->net.fd;
916
- return INT2NUM(fd_set_fd);
917
- }
909
+ GET_CLIENT(self);
910
+ REQUIRE_CONNECTED(wrapper);
911
+ return INT2NUM(wrapper->client->net.fd);
918
912
  #else
919
913
  rb_raise(cMysql2Error, "Raw access to the mysql file descriptor isn't supported on Windows");
920
914
  #endif
@@ -987,7 +981,7 @@ static VALUE rb_mysql_client_select_db(VALUE self, VALUE db)
987
981
  REQUIRE_CONNECTED(wrapper);
988
982
 
989
983
  args.mysql = wrapper->client;
990
- args.db = StringValuePtr(db);
984
+ args.db = StringValueCStr(db);
991
985
 
992
986
  if (rb_thread_call_without_gvl(nogvl_select_db, &args, RUBY_UBF_IO, 0) == Qfalse)
993
987
  rb_raise_mysql2_error(wrapper);
@@ -1183,11 +1177,11 @@ static VALUE set_ssl_options(VALUE self, VALUE key, VALUE cert, VALUE ca, VALUE
1183
1177
  GET_CLIENT(self);
1184
1178
 
1185
1179
  mysql_ssl_set(wrapper->client,
1186
- NIL_P(key) ? NULL : StringValuePtr(key),
1187
- NIL_P(cert) ? NULL : StringValuePtr(cert),
1188
- NIL_P(ca) ? NULL : StringValuePtr(ca),
1189
- NIL_P(capath) ? NULL : StringValuePtr(capath),
1190
- NIL_P(cipher) ? NULL : StringValuePtr(cipher));
1180
+ NIL_P(key) ? NULL : StringValueCStr(key),
1181
+ NIL_P(cert) ? NULL : StringValueCStr(cert),
1182
+ NIL_P(ca) ? NULL : StringValueCStr(ca),
1183
+ NIL_P(capath) ? NULL : StringValueCStr(capath),
1184
+ NIL_P(cipher) ? NULL : StringValueCStr(cipher));
1191
1185
 
1192
1186
  return self;
1193
1187
  }
@@ -1254,12 +1248,12 @@ void init_mysql2_client() {
1254
1248
  rb_define_alloc_func(cMysql2Client, allocate);
1255
1249
 
1256
1250
  rb_define_singleton_method(cMysql2Client, "escape", rb_mysql_client_escape, 1);
1251
+ rb_define_singleton_method(cMysql2Client, "info", rb_mysql_client_info, 0);
1257
1252
 
1258
1253
  rb_define_method(cMysql2Client, "close", rb_mysql_client_close, 0);
1259
1254
  rb_define_method(cMysql2Client, "query", rb_mysql_client_query, -1);
1260
1255
  rb_define_method(cMysql2Client, "abandon_results!", rb_mysql_client_abandon_results, 0);
1261
1256
  rb_define_method(cMysql2Client, "escape", rb_mysql_client_real_escape, 1);
1262
- rb_define_method(cMysql2Client, "info", rb_mysql_client_info, 0);
1263
1257
  rb_define_method(cMysql2Client, "server_info", rb_mysql_client_server_info, 0);
1264
1258
  rb_define_method(cMysql2Client, "socket", rb_mysql_client_socket, 0);
1265
1259
  rb_define_method(cMysql2Client, "async_result", rb_mysql_client_async_result, 0);
@@ -1293,6 +1287,7 @@ void init_mysql2_client() {
1293
1287
 
1294
1288
  sym_id = ID2SYM(rb_intern("id"));
1295
1289
  sym_version = ID2SYM(rb_intern("version"));
1290
+ sym_header_version = ID2SYM(rb_intern("header_version"));
1296
1291
  sym_async = ID2SYM(rb_intern("async"));
1297
1292
  sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
1298
1293
  sym_as = ID2SYM(rb_intern("as"));
@@ -2,7 +2,14 @@
2
2
  require 'mkmf'
3
3
 
4
4
  def asplode lib
5
- abort "-----\n#{lib} is missing. please check your installation of mysql and try again.\n-----"
5
+ if RUBY_PLATFORM =~ /mingw|mswin/
6
+ abort "-----\n#{lib} is missing. please check your installation of mysql and try again.\n-----"
7
+ elsif RUBY_PLATFORM =~ /darwin/
8
+ abort "-----\n#{lib} is missing. Try 'brew install mysql', check your installation of mysql and try again.\n-----"
9
+ else
10
+ abort "-----\n#{lib} is missing. Try 'apt-get install libmysqlclient-dev' or
11
+ 'yum install mysql-devel', check your installation of mysql and try again.\n-----"
12
+ end
6
13
  end
7
14
 
8
15
  # 2.0-only
@@ -29,7 +36,7 @@ dirs = ENV['PATH'].split(File::PATH_SEPARATOR) + %w[
29
36
  /usr/local/lib/mysql5*
30
37
  ].map{|dir| "#{dir}/bin" }
31
38
 
32
- GLOB = "{#{dirs.join(',')}}/{mysql_config,mysql_config5}"
39
+ GLOB = "{#{dirs.join(',')}}/{mysql_config,mysql_config5,mariadb_config}"
33
40
 
34
41
  # If the user has provided a --with-mysql-dir argument, we must respect it or fail.
35
42
  inc, lib = dir_config('mysql')
@@ -67,10 +74,14 @@ elsif mc = (with_config('mysql-config') || Dir[GLOB].first)
67
74
  else
68
75
  inc, lib = dir_config('mysql', '/usr/local')
69
76
  libs = ['m', 'z', 'socket', 'nsl', 'mygcc']
77
+ found = false
70
78
  while not find_library('mysqlclient', 'mysql_query', lib, "#{lib}/mysql") do
71
79
  exit 1 if libs.empty?
72
- have_library(libs.shift)
80
+ found ||= have_library(libs.shift)
73
81
  end
82
+
83
+ asplode("mysql client") unless found
84
+
74
85
  rpath_dir = lib
75
86
  end
76
87
 
@@ -50,6 +50,10 @@ static rb_encoding *binaryEncoding;
50
50
  #define MYSQL2_MIN_TIME 62171150401ULL
51
51
  #endif
52
52
 
53
+ #define GET_RESULT(obj) \
54
+ mysql2_result_wrapper *wrapper; \
55
+ Data_Get_Struct(self, mysql2_result_wrapper, wrapper);
56
+
53
57
  static VALUE cMysql2Result;
54
58
  static VALUE cBigDecimal, cDate, cDateTime;
55
59
  static VALUE opt_decimal_zero, opt_float_zero, opt_time_year, opt_time_month, opt_utc_offset;
@@ -103,9 +107,8 @@ static void *nogvl_fetch_row(void *ptr) {
103
107
  }
104
108
 
105
109
  static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, short int symbolize_keys) {
106
- mysql2_result_wrapper * wrapper;
107
110
  VALUE rb_field;
108
- GetMysql2Result(self, wrapper);
111
+ GET_RESULT(self);
109
112
 
110
113
  if (wrapper->fields == Qnil) {
111
114
  wrapper->numberOfFields = mysql_num_fields(wrapper->result);
@@ -193,7 +196,6 @@ static unsigned int msec_char_to_uint(char *msec_char, size_t len)
193
196
 
194
197
  static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezone, int symbolizeKeys, int asArray, int castBool, int cast, MYSQL_FIELD * fields) {
195
198
  VALUE rowVal;
196
- mysql2_result_wrapper * wrapper;
197
199
  MYSQL_ROW row;
198
200
  unsigned int i = 0;
199
201
  unsigned long * fieldLengths;
@@ -202,7 +204,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
202
204
  rb_encoding *default_internal_enc;
203
205
  rb_encoding *conn_enc;
204
206
  #endif
205
- GetMysql2Result(self, wrapper);
207
+ GET_RESULT(self);
206
208
 
207
209
  #ifdef HAVE_RUBY_ENCODING_H
208
210
  default_internal_enc = rb_default_internal_encoding();
@@ -413,12 +415,11 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
413
415
  }
414
416
 
415
417
  static VALUE rb_mysql_result_fetch_fields(VALUE self) {
416
- mysql2_result_wrapper * wrapper;
417
418
  unsigned int i = 0;
418
419
  short int symbolizeKeys = 0;
419
420
  VALUE defaults;
420
421
 
421
- GetMysql2Result(self, wrapper);
422
+ GET_RESULT(self);
422
423
 
423
424
  defaults = rb_iv_get(self, "@query_options");
424
425
  Check_Type(defaults, T_HASH);
@@ -443,13 +444,12 @@ static VALUE rb_mysql_result_fetch_fields(VALUE self) {
443
444
  static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
444
445
  VALUE defaults, opts, block;
445
446
  ID db_timezone, app_timezone, dbTz, appTz;
446
- mysql2_result_wrapper * wrapper;
447
447
  unsigned long i;
448
448
  const char * errstr;
449
- int symbolizeKeys = 0, asArray = 0, castBool = 0, cacheRows = 1, cast = 1, streaming = 0;
449
+ int symbolizeKeys, asArray, castBool, cacheRows, cast;
450
450
  MYSQL_FIELD * fields = NULL;
451
451
 
452
- GetMysql2Result(self, wrapper);
452
+ GET_RESULT(self);
453
453
 
454
454
  defaults = rb_iv_get(self, "@query_options");
455
455
  Check_Type(defaults, T_HASH);
@@ -459,32 +459,14 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
459
459
  opts = defaults;
460
460
  }
461
461
 
462
- if (rb_hash_aref(opts, sym_symbolize_keys) == Qtrue) {
463
- symbolizeKeys = 1;
464
- }
465
-
466
- if (rb_hash_aref(opts, sym_as) == sym_array) {
467
- asArray = 1;
468
- }
469
-
470
- if (rb_hash_aref(opts, sym_cast_booleans) == Qtrue) {
471
- castBool = 1;
472
- }
473
-
474
- if (rb_hash_aref(opts, sym_cache_rows) == Qfalse) {
475
- cacheRows = 0;
476
- }
477
-
478
- if (rb_hash_aref(opts, sym_cast) == Qfalse) {
479
- cast = 0;
480
- }
481
-
482
- if (rb_hash_aref(opts, sym_stream) == Qtrue) {
483
- streaming = 1;
484
- }
462
+ symbolizeKeys = RTEST(rb_hash_aref(opts, sym_symbolize_keys));
463
+ asArray = rb_hash_aref(opts, sym_as) == sym_array;
464
+ castBool = RTEST(rb_hash_aref(opts, sym_cast_booleans));
465
+ cacheRows = RTEST(rb_hash_aref(opts, sym_cache_rows));
466
+ cast = RTEST(rb_hash_aref(opts, sym_cast));
485
467
 
486
- if (streaming && cacheRows) {
487
- rb_warn("cacheRows is ignored if streaming is true");
468
+ if (wrapper->is_streaming && cacheRows) {
469
+ rb_warn(":cache_rows is ignored if :stream is true");
488
470
  }
489
471
 
490
472
  dbTz = rb_hash_aref(opts, sym_database_timezone);
@@ -508,23 +490,12 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
508
490
  app_timezone = Qnil;
509
491
  }
510
492
 
511
- if (wrapper->lastRowProcessed == 0) {
512
- if (streaming) {
513
- /* We can't get number of rows if we're streaming, */
514
- /* until we've finished fetching all rows */
515
- wrapper->numberOfRows = 0;
493
+ if (wrapper->is_streaming) {
494
+ /* When streaming, we will only yield rows, not return them. */
495
+ if (wrapper->rows == Qnil) {
516
496
  wrapper->rows = rb_ary_new();
517
- } else {
518
- wrapper->numberOfRows = mysql_num_rows(wrapper->result);
519
- if (wrapper->numberOfRows == 0) {
520
- wrapper->rows = rb_ary_new();
521
- return wrapper->rows;
522
- }
523
- wrapper->rows = rb_ary_new2(wrapper->numberOfRows);
524
497
  }
525
- }
526
498
 
527
- if (streaming) {
528
499
  if (!wrapper->streamingComplete) {
529
500
  VALUE row;
530
501
 
@@ -532,16 +503,15 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
532
503
 
533
504
  do {
534
505
  row = rb_mysql_result_fetch_row(self, db_timezone, app_timezone, symbolizeKeys, asArray, castBool, cast, fields);
535
-
536
- if (block != Qnil && row != Qnil) {
537
- rb_yield(row);
538
- wrapper->lastRowProcessed++;
506
+ if (row != Qnil) {
507
+ wrapper->numberOfRows++;
508
+ if (block != Qnil) {
509
+ rb_yield(row);
510
+ }
539
511
  }
540
512
  } while(row != Qnil);
541
513
 
542
514
  rb_mysql_result_free_result(wrapper);
543
-
544
- wrapper->numberOfRows = wrapper->lastRowProcessed;
545
515
  wrapper->streamingComplete = 1;
546
516
 
547
517
  // Check for errors, the connection might have gone out from under us
@@ -554,6 +524,15 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
554
524
  rb_raise(cMysql2Error, "You have already fetched all the rows for this query and streaming is true. (to reiterate you must requery).");
555
525
  }
556
526
  } else {
527
+ if (wrapper->lastRowProcessed == 0) {
528
+ wrapper->numberOfRows = mysql_num_rows(wrapper->result);
529
+ if (wrapper->numberOfRows == 0) {
530
+ wrapper->rows = rb_ary_new();
531
+ return wrapper->rows;
532
+ }
533
+ wrapper->rows = rb_ary_new2(wrapper->numberOfRows);
534
+ }
535
+
557
536
  if (cacheRows && wrapper->lastRowProcessed == wrapper->numberOfRows) {
558
537
  /* we've already read the entire dataset from the C result into our */
559
538
  /* internal array. Lets hand that over to the user since it's ready to go */
@@ -598,17 +577,19 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
598
577
  }
599
578
 
600
579
  static VALUE rb_mysql_result_count(VALUE self) {
601
- mysql2_result_wrapper *wrapper;
580
+ GET_RESULT(self);
581
+
582
+ if (wrapper->is_streaming) {
583
+ /* This is an unsigned long per result.h */
584
+ return ULONG2NUM(wrapper->numberOfRows);
585
+ }
602
586
 
603
- GetMysql2Result(self, wrapper);
604
587
  if (wrapper->resultFreed) {
605
- if (wrapper->streamingComplete){
606
- return LONG2NUM(wrapper->numberOfRows);
607
- } else {
608
- return LONG2NUM(RARRAY_LEN(wrapper->rows));
609
- }
588
+ /* Ruby arrays have platform signed long length */
589
+ return LONG2NUM(RARRAY_LEN(wrapper->rows));
610
590
  } else {
611
- return INT2FIX(mysql_num_rows(wrapper->result));
591
+ /* MySQL returns an unsigned 64-bit long here */
592
+ return ULL2NUM(mysql_num_rows(wrapper->result));
612
593
  }
613
594
  }
614
595
 
@@ -616,6 +597,7 @@ static VALUE rb_mysql_result_count(VALUE self) {
616
597
  VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_RES *r) {
617
598
  VALUE obj;
618
599
  mysql2_result_wrapper * wrapper;
600
+
619
601
  obj = Data_Make_Struct(cMysql2Result, mysql2_result_wrapper, rb_mysql_result_mark, rb_mysql_result_free, wrapper);
620
602
  wrapper->numberOfFields = 0;
621
603
  wrapper->numberOfRows = 0;
@@ -634,6 +616,10 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
634
616
 
635
617
  rb_iv_set(obj, "@query_options", options);
636
618
 
619
+ /* Options that cannot be changed in results.each(...) { |row| }
620
+ * should be processed here. */
621
+ wrapper->is_streaming = (rb_hash_aref(options, sym_stream) == Qtrue ? 1 : 0);
622
+
637
623
  return obj;
638
624
  }
639
625
 
@@ -12,12 +12,11 @@ typedef struct {
12
12
  unsigned int numberOfFields;
13
13
  unsigned long numberOfRows;
14
14
  unsigned long lastRowProcessed;
15
+ char is_streaming;
15
16
  char streamingComplete;
16
17
  char resultFreed;
17
18
  MYSQL_RES *result;
18
19
  mysql_client_wrapper *client_wrapper;
19
20
  } mysql2_result_wrapper;
20
21
 
21
- #define GetMysql2Result(obj, sval) (sval = (mysql2_result_wrapper*)DATA_PTR(obj));
22
-
23
22
  #endif
@@ -82,6 +82,10 @@ module Mysql2
82
82
  info_hash
83
83
  end
84
84
 
85
+ def info
86
+ self.class.info
87
+ end
88
+
85
89
  private
86
90
  def self.local_offset
87
91
  ::Time.local(2010).utc_offset.to_r / 86400
@@ -30,7 +30,7 @@ module Mysql2
30
30
  # variable.
31
31
  #
32
32
  # See http://dev.mysql.com/doc/refman/5.5/en/charset-errors.html for
33
- # more contetx.
33
+ # more context.
34
34
  #
35
35
  # Before MySQL 5.5 error message template strings are in whatever encoding
36
36
  # is associated with the error message language.
@@ -1,3 +1,3 @@
1
1
  module Mysql2
2
- VERSION = "0.3.18"
2
+ VERSION = "0.3.19"
3
3
  end
@@ -66,12 +66,13 @@ describe Mysql2::Client do
66
66
  end
67
67
  end
68
68
  client = klient.new
69
- (client.connect_args.last[6] & (Mysql2::Client::REMEMBER_OPTIONS |
70
- Mysql2::Client::LONG_PASSWORD |
71
- Mysql2::Client::LONG_FLAG |
72
- Mysql2::Client::TRANSACTIONS |
73
- Mysql2::Client::PROTOCOL_41 |
74
- Mysql2::Client::SECURE_CONNECTION)).should be_true
69
+ client_flags = Mysql2::Client::REMEMBER_OPTIONS |
70
+ Mysql2::Client::LONG_PASSWORD |
71
+ Mysql2::Client::LONG_FLAG |
72
+ Mysql2::Client::TRANSACTIONS |
73
+ Mysql2::Client::PROTOCOL_41 |
74
+ Mysql2::Client::SECURE_CONNECTION
75
+ client.connect_args.last[6].should eql(client_flags)
75
76
  end
76
77
 
77
78
  it "should execute init command" do
@@ -614,6 +615,21 @@ describe Mysql2::Client do
614
615
 
615
616
  @multi_client.more_results?.should be_false
616
617
  end
618
+
619
+ it "#more_results? should work with stored procedures" do
620
+ @multi_client.query("DROP PROCEDURE IF EXISTS test_proc")
621
+ @multi_client.query("CREATE PROCEDURE test_proc() BEGIN SELECT 1 AS 'set_1'; SELECT 2 AS 'set_2'; END")
622
+ @multi_client.query("CALL test_proc()").first.should eql({ 'set_1' => 1 })
623
+ @multi_client.more_results?.should be_true
624
+
625
+ @multi_client.next_result
626
+ @multi_client.store_result.first.should eql({ 'set_2' => 2 })
627
+
628
+ @multi_client.next_result
629
+ @multi_client.store_result.should be_nil # this is the result from CALL itself
630
+
631
+ @multi_client.more_results?.should be_false
632
+ end
617
633
  end
618
634
  end
619
635
 
@@ -700,6 +716,19 @@ describe Mysql2::Client do
700
716
  @client.escape ""
701
717
  }.should raise_error(Mysql2::Error)
702
718
  end
719
+
720
+ context 'when mysql encoding is not utf8' do
721
+ before { pending('Encoding is undefined') unless defined?(Encoding) }
722
+
723
+ let(:client) { Mysql2::Client.new(DatabaseCredentials['root'].merge(:encoding => "ujis")) }
724
+
725
+ it 'should return a internal encoding string if Encoding.default_internal is set' do
726
+ with_internal_encoding Encoding::UTF_8 do
727
+ client.escape("\u{30C6}\u{30B9}\u{30C8}").should eql("\u{30C6}\u{30B9}\u{30C8}")
728
+ client.escape("\u{30C6}'\u{30B9}\"\u{30C8}").should eql("\u{30C6}\\'\u{30B9}\\\"\u{30C8}")
729
+ end
730
+ end
731
+ end
703
732
  end
704
733
 
705
734
  it "should respond to #info" do
@@ -715,26 +744,21 @@ describe Mysql2::Client do
715
744
  info[:version].class.should eql(String)
716
745
  end
717
746
 
718
- if defined? Encoding
719
- context "strings returned by #info" do
720
- it "should default to the connection's encoding if Encoding.default_internal is nil" do
721
- with_internal_encoding nil do
722
- @client.info[:version].encoding.should eql(Encoding.find('utf-8'))
747
+ context "strings returned by #info" do
748
+ before { pending('Encoding is undefined') unless defined?(Encoding) }
723
749
 
724
- client2 = Mysql2::Client.new(DatabaseCredentials['root'].merge(:encoding => 'ascii'))
725
- client2.info[:version].encoding.should eql(Encoding.find('us-ascii'))
726
- end
727
- end
750
+ it "should be tagged as ascii" do
751
+ @client.info[:version].encoding.should eql(Encoding::US_ASCII)
752
+ @client.info[:header_version].encoding.should eql(Encoding::US_ASCII)
753
+ end
754
+ end
728
755
 
729
- it "should use Encoding.default_internal" do
730
- with_internal_encoding 'utf-8' do
731
- @client.info[:version].encoding.should eql(Encoding.default_internal)
732
- end
756
+ context "strings returned by .info" do
757
+ before { pending('Encoding is undefined') unless defined?(Encoding) }
733
758
 
734
- with_internal_encoding 'us-ascii' do
735
- @client.info[:version].encoding.should eql(Encoding.default_internal)
736
- end
737
- end
759
+ it "should be tagged as ascii" do
760
+ Mysql2::Client.info[:version].encoding.should eql(Encoding::US_ASCII)
761
+ Mysql2::Client.info[:header_version].encoding.should eql(Encoding::US_ASCII)
738
762
  end
739
763
  end
740
764
 
@@ -6,6 +6,14 @@ describe Mysql2::Result do
6
6
  @result = @client.query "SELECT 1"
7
7
  end
8
8
 
9
+ it "should raise a TypeError exception when it doesn't wrap a result set" do
10
+ r = Mysql2::Result.new
11
+ expect { r.count }.to raise_error(TypeError)
12
+ expect { r.fields }.to raise_error(TypeError)
13
+ expect { r.size }.to raise_error(TypeError)
14
+ expect { r.each }.to raise_error(TypeError)
15
+ end
16
+
9
17
  it "should have included Enumerable" do
10
18
  Mysql2::Result.ancestors.include?(Enumerable).should be_true
11
19
  end
@@ -107,18 +115,19 @@ describe Mysql2::Result do
107
115
 
108
116
  context "streaming" do
109
117
  it "should maintain a count while streaming" do
110
- result = @client.query('SELECT 1')
111
-
112
- result.count.should eql(1)
118
+ result = @client.query('SELECT 1', :stream => true, :cache_rows => false)
119
+ result.count.should eql(0)
113
120
  result.each.to_a
114
121
  result.count.should eql(1)
115
122
  end
116
123
 
117
- it "should set the actual count of rows after streaming" do
118
- result = @client.query("SELECT * FROM mysql2_test", :stream => true, :cache_rows => false)
124
+ it "should retain the count when mixing first and each" do
125
+ result = @client.query("SELECT 1 UNION SELECT 2", :stream => true, :cache_rows => false)
119
126
  result.count.should eql(0)
120
- result.each {|r| }
127
+ result.first
121
128
  result.count.should eql(1)
129
+ result.each.to_a
130
+ result.count.should eql(2)
122
131
  end
123
132
 
124
133
  it "should not yield nil at the end of streaming" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mysql2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.18
4
+ version: 0.3.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Lopez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-17 00:00:00.000000000 Z
11
+ date: 2015-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -59,6 +59,7 @@ extensions:
59
59
  - ext/mysql2/extconf.rb
60
60
  extra_rdoc_files: []
61
61
  files:
62
+ - LICENSE
62
63
  - README.md
63
64
  - ext/mysql2/client.c
64
65
  - ext/mysql2/client.h