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 +4 -4
- data/LICENSE +21 -0
- data/ext/mysql2/client.c +43 -48
- data/ext/mysql2/extconf.rb +14 -3
- data/ext/mysql2/result.c +48 -62
- data/ext/mysql2/result.h +1 -2
- data/lib/mysql2/client.rb +4 -0
- data/lib/mysql2/error.rb +1 -1
- data/lib/mysql2/version.rb +1 -1
- data/spec/mysql2/client_spec.rb +47 -23
- data/spec/mysql2/result_spec.rb +15 -6
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 927d6afad1ca42286f65ccdabaab7221b0d40ba5
|
4
|
+
data.tar.gz: 01941e7450c35c68243880b1c09646c398a64362
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
data/ext/mysql2/client.c
CHANGED
@@ -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,
|
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
|
341
|
-
args.unix_socket = NIL_P(socket)
|
342
|
-
args.port
|
343
|
-
args.user
|
344
|
-
args.passwd
|
345
|
-
args.db
|
346
|
-
args.mysql
|
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 =
|
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,
|
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 *)
|
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 *)
|
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 *)
|
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
|
847
|
-
VALUE version,
|
848
|
-
|
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
|
-
|
856
|
-
|
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(
|
864
|
-
|
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
|
-
|
869
|
-
|
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
|
-
|
914
|
-
|
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 =
|
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)
|
1187
|
-
NIL_P(cert)
|
1188
|
-
NIL_P(ca)
|
1189
|
-
NIL_P(capath) ? NULL :
|
1190
|
-
NIL_P(cipher) ? NULL :
|
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"));
|
data/ext/mysql2/extconf.rb
CHANGED
@@ -2,7 +2,14 @@
|
|
2
2
|
require 'mkmf'
|
3
3
|
|
4
4
|
def asplode lib
|
5
|
-
|
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
|
|
data/ext/mysql2/result.c
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
449
|
+
int symbolizeKeys, asArray, castBool, cacheRows, cast;
|
450
450
|
MYSQL_FIELD * fields = NULL;
|
451
451
|
|
452
|
-
|
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
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
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 (
|
487
|
-
rb_warn("
|
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->
|
512
|
-
|
513
|
-
|
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
|
-
|
537
|
-
|
538
|
-
|
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
|
-
|
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
|
-
|
606
|
-
|
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
|
-
|
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
|
|
data/ext/mysql2/result.h
CHANGED
@@ -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
|
data/lib/mysql2/client.rb
CHANGED
data/lib/mysql2/error.rb
CHANGED
@@ -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
|
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.
|
data/lib/mysql2/version.rb
CHANGED
data/spec/mysql2/client_spec.rb
CHANGED
@@ -66,12 +66,13 @@ describe Mysql2::Client do
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
client = klient.new
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
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
|
-
|
719
|
-
|
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
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
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
|
-
|
730
|
-
|
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
|
-
|
735
|
-
|
736
|
-
|
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
|
|
data/spec/mysql2/result_spec.rb
CHANGED
@@ -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
|
118
|
-
result = @client.query("SELECT
|
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.
|
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.
|
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-
|
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
|