mysql2 0.4.4 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +90 -52
- data/examples/eventmachine.rb +0 -2
- data/examples/threaded.rb +2 -4
- data/ext/mysql2/client.c +260 -76
- data/ext/mysql2/client.h +2 -47
- data/ext/mysql2/extconf.rb +44 -18
- data/ext/mysql2/mysql2_ext.c +2 -1
- data/ext/mysql2/mysql2_ext.h +8 -8
- data/ext/mysql2/result.c +23 -74
- data/ext/mysql2/statement.c +139 -63
- data/ext/mysql2/statement.h +0 -2
- data/ext/mysql2/wait_for_single_fd.h +2 -1
- data/lib/mysql2/client.rb +50 -31
- data/lib/mysql2/em.rb +2 -4
- data/lib/mysql2/error.rb +49 -20
- data/lib/mysql2/result.rb +2 -0
- data/lib/mysql2/statement.rb +3 -9
- data/lib/mysql2/version.rb +1 -1
- data/lib/mysql2.rb +14 -15
- data/spec/configuration.yml.example +0 -6
- data/spec/em/em_spec.rb +6 -6
- data/spec/mysql2/client_spec.rb +318 -237
- data/spec/mysql2/error_spec.rb +4 -10
- data/spec/mysql2/result_spec.rb +124 -158
- data/spec/mysql2/statement_spec.rb +185 -180
- data/spec/spec_helper.rb +79 -61
- data/spec/ssl/gen_certs.sh +1 -1
- data/support/5072E1F5.asc +432 -0
- data/support/mysql_enc_to_ruby.rb +2 -2
- data/support/ruby_enc_to_mysql.rb +5 -5
- metadata +16 -14
data/ext/mysql2/client.h
CHANGED
@@ -1,41 +1,6 @@
|
|
1
1
|
#ifndef MYSQL2_CLIENT_H
|
2
2
|
#define MYSQL2_CLIENT_H
|
3
3
|
|
4
|
-
#ifndef HAVE_RB_THREAD_CALL_WITHOUT_GVL
|
5
|
-
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
|
6
|
-
|
7
|
-
/* emulate rb_thread_call_without_gvl with rb_thread_blocking_region */
|
8
|
-
#define rb_thread_call_without_gvl(func, data1, ubf, data2) \
|
9
|
-
rb_thread_blocking_region((rb_blocking_function_t *)func, data1, ubf, data2)
|
10
|
-
|
11
|
-
#else /* ! HAVE_RB_THREAD_BLOCKING_REGION */
|
12
|
-
/*
|
13
|
-
* partial emulation of the 2.0 rb_thread_call_without_gvl under 1.8,
|
14
|
-
* this is enough for dealing with blocking I/O functions in the
|
15
|
-
* presence of threads.
|
16
|
-
*/
|
17
|
-
|
18
|
-
#include <rubysig.h>
|
19
|
-
#define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
|
20
|
-
typedef void rb_unblock_function_t(void *);
|
21
|
-
static void *
|
22
|
-
rb_thread_call_without_gvl(
|
23
|
-
void *(*func)(void *), void *data1,
|
24
|
-
RB_MYSQL_UNUSED rb_unblock_function_t *ubf,
|
25
|
-
RB_MYSQL_UNUSED void *data2)
|
26
|
-
{
|
27
|
-
void *rv;
|
28
|
-
|
29
|
-
TRAP_BEG;
|
30
|
-
rv = func(data1);
|
31
|
-
TRAP_END;
|
32
|
-
|
33
|
-
return rv;
|
34
|
-
}
|
35
|
-
|
36
|
-
#endif /* ! HAVE_RB_THREAD_BLOCKING_REGION */
|
37
|
-
#endif /* ! HAVE_RB_THREAD_CALL_WITHOUT_GVL */
|
38
|
-
|
39
4
|
typedef struct {
|
40
5
|
VALUE encoding;
|
41
6
|
VALUE active_thread; /* rb_thread_current() or Qnil */
|
@@ -44,20 +9,14 @@ typedef struct {
|
|
44
9
|
unsigned int connect_timeout;
|
45
10
|
int active;
|
46
11
|
int automatic_close;
|
47
|
-
int connected;
|
48
12
|
int initialized;
|
49
13
|
int refcount;
|
50
|
-
int
|
14
|
+
int closed;
|
51
15
|
MYSQL *client;
|
52
16
|
} mysql_client_wrapper;
|
53
17
|
|
54
|
-
#define REQUIRE_CONNECTED(wrapper) \
|
55
|
-
REQUIRE_INITIALIZED(wrapper) \
|
56
|
-
if (!wrapper->connected && !wrapper->reconnect_enabled) { \
|
57
|
-
rb_raise(cMysql2Error, "closed MySQL connection"); \
|
58
|
-
}
|
59
|
-
|
60
18
|
void rb_mysql_client_set_active_thread(VALUE self);
|
19
|
+
void rb_mysql_set_server_query_flags(MYSQL *client, VALUE result);
|
61
20
|
|
62
21
|
#define GET_CLIENT(self) \
|
63
22
|
mysql_client_wrapper *wrapper; \
|
@@ -67,7 +26,3 @@ void init_mysql2_client(void);
|
|
67
26
|
void decr_mysql2_client(mysql_client_wrapper *wrapper);
|
68
27
|
|
69
28
|
#endif
|
70
|
-
|
71
|
-
#ifndef HAVE_RB_HASH_DUP
|
72
|
-
VALUE rb_hash_dup(VALUE other);
|
73
|
-
#endif
|
data/ext/mysql2/extconf.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: UTF-8
|
2
1
|
require 'mkmf'
|
3
2
|
require 'English'
|
4
3
|
|
@@ -12,18 +11,26 @@ def asplode(lib)
|
|
12
11
|
end
|
13
12
|
end
|
14
13
|
|
15
|
-
|
16
|
-
|
14
|
+
def add_ssl_defines(header)
|
15
|
+
all_modes_found = %w[SSL_MODE_DISABLED SSL_MODE_PREFERRED SSL_MODE_REQUIRED SSL_MODE_VERIFY_CA SSL_MODE_VERIFY_IDENTITY].inject(true) do |m, ssl_mode|
|
16
|
+
m && have_const(ssl_mode, header)
|
17
|
+
end
|
18
|
+
$CFLAGS << ' -DFULL_SSL_MODE_SUPPORT' if all_modes_found
|
19
|
+
# if we only have ssl toggle (--ssl,--disable-ssl) from 5.7.3 to 5.7.10
|
20
|
+
has_no_support = all_modes_found ? false : !have_const('MYSQL_OPT_SSL_ENFORCE', header)
|
21
|
+
$CFLAGS << ' -DNO_SSL_MODE_SUPPORT' if has_no_support
|
22
|
+
end
|
17
23
|
|
18
|
-
# 1
|
19
|
-
have_func('
|
24
|
+
# 2.1+
|
25
|
+
have_func('rb_absint_size')
|
26
|
+
have_func('rb_absint_singlebit_p')
|
27
|
+
|
28
|
+
# Missing in RBX (https://github.com/rubinius/rubinius/issues/3771)
|
20
29
|
have_func('rb_wait_for_single_fd')
|
21
|
-
have_func('rb_hash_dup')
|
22
|
-
have_func('rb_intern3')
|
23
30
|
|
24
31
|
# borrowed from mysqlplus
|
25
32
|
# http://github.com/oldmoe/mysqlplus/blob/master/ext/extconf.rb
|
26
|
-
dirs = ENV.fetch('PATH').split(File::PATH_SEPARATOR) + %w
|
33
|
+
dirs = ENV.fetch('PATH').split(File::PATH_SEPARATOR) + %w[
|
27
34
|
/opt
|
28
35
|
/opt/local
|
29
36
|
/opt/local/mysql
|
@@ -35,17 +42,19 @@ dirs = ENV.fetch('PATH').split(File::PATH_SEPARATOR) + %w(
|
|
35
42
|
/usr/local/mysql-*
|
36
43
|
/usr/local/lib/mysql5*
|
37
44
|
/usr/local/opt/mysql5*
|
38
|
-
|
45
|
+
].map { |dir| dir << '/bin' }
|
46
|
+
|
47
|
+
# For those without HOMEBREW_ROOT in PATH
|
48
|
+
dirs << "#{ENV['HOMEBREW_ROOT']}/bin" if ENV['HOMEBREW_ROOT']
|
39
49
|
|
40
|
-
GLOB = "{#{dirs.join(',')}}/{mysql_config,mysql_config5,mariadb_config}"
|
50
|
+
GLOB = "{#{dirs.join(',')}}/{mysql_config,mysql_config5,mariadb_config}".freeze
|
41
51
|
|
42
52
|
# If the user has provided a --with-mysql-dir argument, we must respect it or fail.
|
43
53
|
inc, lib = dir_config('mysql')
|
44
54
|
if inc && lib
|
45
|
-
#
|
46
|
-
#
|
55
|
+
# Ruby versions below 2.0 on Unix and below 2.1 on Windows
|
56
|
+
# do not properly search for lib directories, and must be corrected:
|
47
57
|
# https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/39717
|
48
|
-
# do not properly search for lib directories, and must be corrected
|
49
58
|
unless lib && lib[-3, 3] == 'lib'
|
50
59
|
@libdir_basename = 'lib'
|
51
60
|
inc, lib = dir_config('mysql')
|
@@ -74,7 +83,7 @@ elsif (mc = (with_config('mysql-config') || Dir[GLOB].first))
|
|
74
83
|
else
|
75
84
|
_, usr_local_lib = dir_config('mysql', '/usr/local')
|
76
85
|
|
77
|
-
asplode("mysql client") unless find_library('mysqlclient',
|
86
|
+
asplode("mysql client") unless find_library('mysqlclient', nil, usr_local_lib, "#{usr_local_lib}/mysql")
|
78
87
|
|
79
88
|
rpath_dir = usr_local_lib
|
80
89
|
end
|
@@ -87,11 +96,28 @@ else
|
|
87
96
|
asplode 'mysql.h'
|
88
97
|
end
|
89
98
|
|
90
|
-
%w
|
91
|
-
header = [prefix, h].compact.join
|
99
|
+
%w[errmsg.h].each do |h|
|
100
|
+
header = [prefix, h].compact.join('/')
|
92
101
|
asplode h unless have_header header
|
93
102
|
end
|
94
103
|
|
104
|
+
mysql_h = [prefix, 'mysql.h'].compact.join('/')
|
105
|
+
add_ssl_defines(mysql_h)
|
106
|
+
have_struct_member('MYSQL', 'net.vio', mysql_h)
|
107
|
+
have_struct_member('MYSQL', 'net.pvio', mysql_h)
|
108
|
+
|
109
|
+
# These constants are actually enums, so they cannot be detected by #ifdef in C code.
|
110
|
+
have_const('MYSQL_ENABLE_CLEARTEXT_PLUGIN', mysql_h)
|
111
|
+
have_const('SERVER_QUERY_NO_GOOD_INDEX_USED', mysql_h)
|
112
|
+
have_const('SERVER_QUERY_NO_INDEX_USED', mysql_h)
|
113
|
+
have_const('SERVER_QUERY_WAS_SLOW', mysql_h)
|
114
|
+
have_const('MYSQL_OPTION_MULTI_STATEMENTS_ON', mysql_h)
|
115
|
+
have_const('MYSQL_OPTION_MULTI_STATEMENTS_OFF', mysql_h)
|
116
|
+
|
117
|
+
# my_bool is replaced by C99 bool in MySQL 8.0, but we want
|
118
|
+
# to retain compatibility with the typedef in earlier MySQLs.
|
119
|
+
have_type('my_bool', mysql_h)
|
120
|
+
|
95
121
|
# This is our wishlist. We use whichever flags work on the host.
|
96
122
|
# -Wall and -Wextra are included by default.
|
97
123
|
wishlist = [
|
@@ -126,7 +152,7 @@ sanitizers = with_config('sanitize')
|
|
126
152
|
case sanitizers
|
127
153
|
when true
|
128
154
|
# Try them all, turn on whatever we can
|
129
|
-
enabled_sanitizers = %w
|
155
|
+
enabled_sanitizers = %w[address cfi integer memory thread undefined].select do |s|
|
130
156
|
try_link('int main() {return 0;}', "-Werror -fsanitize=#{s}")
|
131
157
|
end
|
132
158
|
abort "-----\nCould not enable any sanitizers!\n-----" if enabled_sanitizers.empty?
|
@@ -154,7 +180,7 @@ unless enabled_sanitizers.empty?
|
|
154
180
|
$CFLAGS << ' -g -fno-omit-frame-pointer'
|
155
181
|
end
|
156
182
|
|
157
|
-
if RUBY_PLATFORM =~ /mswin|mingw/
|
183
|
+
if RUBY_PLATFORM =~ /mswin|mingw/ && !defined?(RubyInstaller)
|
158
184
|
# Build libmysql.a interface link library
|
159
185
|
require 'rake'
|
160
186
|
|
data/ext/mysql2/mysql2_ext.c
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
#include <mysql2_ext.h>
|
2
2
|
|
3
|
-
VALUE mMysql2, cMysql2Error;
|
3
|
+
VALUE mMysql2, cMysql2Error, cMysql2TimeoutError;
|
4
4
|
|
5
5
|
/* Ruby Extension initializer */
|
6
6
|
void Init_mysql2() {
|
7
7
|
mMysql2 = rb_define_module("Mysql2");
|
8
8
|
cMysql2Error = rb_const_get(mMysql2, rb_intern("Error"));
|
9
|
+
cMysql2TimeoutError = rb_const_get(cMysql2Error, rb_intern("TimeoutError"));
|
9
10
|
|
10
11
|
init_mysql2_client();
|
11
12
|
init_mysql2_result();
|
data/ext/mysql2/mysql2_ext.h
CHANGED
@@ -11,22 +11,14 @@ void Init_mysql2(void);
|
|
11
11
|
|
12
12
|
#ifdef HAVE_MYSQL_H
|
13
13
|
#include <mysql.h>
|
14
|
-
#include <mysql_com.h>
|
15
14
|
#include <errmsg.h>
|
16
|
-
#include <mysqld_error.h>
|
17
15
|
#else
|
18
16
|
#include <mysql/mysql.h>
|
19
|
-
#include <mysql/mysql_com.h>
|
20
17
|
#include <mysql/errmsg.h>
|
21
|
-
#include <mysql/mysqld_error.h>
|
22
18
|
#endif
|
23
19
|
|
24
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
25
20
|
#include <ruby/encoding.h>
|
26
|
-
#endif
|
27
|
-
#ifdef HAVE_RUBY_THREAD_H
|
28
21
|
#include <ruby/thread.h>
|
29
|
-
#endif
|
30
22
|
|
31
23
|
#if defined(__GNUC__) && (__GNUC__ >= 3)
|
32
24
|
#define RB_MYSQL_NORETURN __attribute__ ((noreturn))
|
@@ -36,6 +28,14 @@ void Init_mysql2(void);
|
|
36
28
|
#define RB_MYSQL_UNUSED
|
37
29
|
#endif
|
38
30
|
|
31
|
+
/* MySQL 8.0 replaces my_bool with C99 bool. Earlier versions of MySQL had
|
32
|
+
* a typedef to char. Gem users reported failures on big endian systems when
|
33
|
+
* using C99 bool types with older MySQLs due to mismatched behavior. */
|
34
|
+
#ifndef HAVE_TYPE_MY_BOOL
|
35
|
+
#include <stdbool.h>
|
36
|
+
typedef bool my_bool;
|
37
|
+
#endif
|
38
|
+
|
39
39
|
#include <client.h>
|
40
40
|
#include <statement.h>
|
41
41
|
#include <result.h>
|
data/ext/mysql2/result.c
CHANGED
@@ -2,51 +2,19 @@
|
|
2
2
|
|
3
3
|
#include "mysql_enc_to_ruby.h"
|
4
4
|
|
5
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
6
5
|
static rb_encoding *binaryEncoding;
|
7
|
-
#endif
|
8
6
|
|
9
|
-
#if (SIZEOF_INT < SIZEOF_LONG) || defined(HAVE_RUBY_ENCODING_H)
|
10
7
|
/* on 64bit platforms we can handle dates way outside 2038-01-19T03:14:07
|
11
8
|
*
|
12
9
|
* (9999*31557600) + (12*2592000) + (31*86400) + (11*3600) + (59*60) + 59
|
13
10
|
*/
|
14
11
|
#define MYSQL2_MAX_TIME 315578267999ULL
|
15
|
-
#else
|
16
|
-
/**
|
17
|
-
* On 32bit platforms the maximum date the Time class can handle is 2038-01-19T03:14:07
|
18
|
-
* 2038 years + 1 month + 19 days + 3 hours + 14 minutes + 7 seconds = 64318634047 seconds
|
19
|
-
*
|
20
|
-
* (2038*31557600) + (1*2592000) + (19*86400) + (3*3600) + (14*60) + 7
|
21
|
-
*/
|
22
|
-
#define MYSQL2_MAX_TIME 64318634047ULL
|
23
|
-
#endif
|
24
12
|
|
25
|
-
#if defined(HAVE_RUBY_ENCODING_H)
|
26
13
|
/* 0000-1-1 00:00:00 UTC
|
27
14
|
*
|
28
15
|
* (0*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 0
|
29
16
|
*/
|
30
17
|
#define MYSQL2_MIN_TIME 2678400ULL
|
31
|
-
#elif SIZEOF_INT < SIZEOF_LONG /* 64bit Ruby 1.8 */
|
32
|
-
/* 0139-1-1 00:00:00 UTC
|
33
|
-
*
|
34
|
-
* (139*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 0
|
35
|
-
*/
|
36
|
-
#define MYSQL2_MIN_TIME 4389184800ULL
|
37
|
-
#elif defined(NEGATIVE_TIME_T)
|
38
|
-
/* 1901-12-13 20:45:52 UTC : The oldest time in 32-bit signed time_t.
|
39
|
-
*
|
40
|
-
* (1901*31557600) + (12*2592000) + (13*86400) + (20*3600) + (45*60) + 52
|
41
|
-
*/
|
42
|
-
#define MYSQL2_MIN_TIME 60023299552ULL
|
43
|
-
#else
|
44
|
-
/* 1970-01-01 00:00:01 UTC : The Unix epoch - the oldest time in portable time_t.
|
45
|
-
*
|
46
|
-
* (1970*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 1
|
47
|
-
*/
|
48
|
-
#define MYSQL2_MIN_TIME 62171150401ULL
|
49
|
-
#endif
|
50
18
|
|
51
19
|
#define GET_RESULT(self) \
|
52
20
|
mysql2_result_wrapper *wrapper; \
|
@@ -64,14 +32,14 @@ typedef struct {
|
|
64
32
|
VALUE block_given;
|
65
33
|
} result_each_args;
|
66
34
|
|
67
|
-
VALUE cBigDecimal, cDateTime, cDate;
|
68
|
-
static VALUE cMysql2Result;
|
69
|
-
static VALUE opt_decimal_zero, opt_float_zero, opt_time_year, opt_time_month, opt_utc_offset;
|
70
35
|
extern VALUE mMysql2, cMysql2Client, cMysql2Error;
|
71
|
-
static
|
72
|
-
static VALUE
|
73
|
-
|
74
|
-
|
36
|
+
static VALUE cMysql2Result, cDateTime, cDate;
|
37
|
+
static VALUE opt_decimal_zero, opt_float_zero, opt_time_year, opt_time_month, opt_utc_offset;
|
38
|
+
static ID intern_new, intern_utc, intern_local, intern_localtime, intern_local_offset,
|
39
|
+
intern_civil, intern_new_offset, intern_merge, intern_BigDecimal;
|
40
|
+
static VALUE sym_symbolize_keys, sym_as, sym_array, sym_database_timezone,
|
41
|
+
sym_application_timezone, sym_local, sym_utc, sym_cast_booleans,
|
42
|
+
sym_cache_rows, sym_cast, sym_stream, sym_name;
|
75
43
|
|
76
44
|
/* Mark any VALUEs that are only referenced in C, so the GC won't get them. */
|
77
45
|
static void rb_mysql_result_mark(void * wrapper) {
|
@@ -179,29 +147,19 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, int symbo
|
|
179
147
|
rb_field = rb_ary_entry(wrapper->fields, idx);
|
180
148
|
if (rb_field == Qnil) {
|
181
149
|
MYSQL_FIELD *field = NULL;
|
182
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
183
150
|
rb_encoding *default_internal_enc = rb_default_internal_encoding();
|
184
151
|
rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
|
185
|
-
#endif
|
186
152
|
|
187
153
|
field = mysql_fetch_field_direct(wrapper->result, idx);
|
188
154
|
if (symbolize_keys) {
|
189
|
-
#ifdef HAVE_RB_INTERN3
|
190
155
|
rb_field = rb_intern3(field->name, field->name_length, rb_utf8_encoding());
|
191
156
|
rb_field = ID2SYM(rb_field);
|
192
|
-
#else
|
193
|
-
VALUE colStr;
|
194
|
-
colStr = rb_str_new(field->name, field->name_length);
|
195
|
-
rb_field = ID2SYM(rb_to_id(colStr));
|
196
|
-
#endif
|
197
157
|
} else {
|
198
158
|
rb_field = rb_str_new(field->name, field->name_length);
|
199
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
200
159
|
rb_enc_associate(rb_field, conn_enc);
|
201
160
|
if (default_internal_enc) {
|
202
161
|
rb_field = rb_str_export_to_enc(rb_field, default_internal_enc);
|
203
162
|
}
|
204
|
-
#endif
|
205
163
|
}
|
206
164
|
rb_ary_store(wrapper->fields, idx, rb_field);
|
207
165
|
}
|
@@ -209,7 +167,6 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, int symbo
|
|
209
167
|
return rb_field;
|
210
168
|
}
|
211
169
|
|
212
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
213
170
|
static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_encoding *default_internal_enc, rb_encoding *conn_enc) {
|
214
171
|
/* if binary flag is set, respect its wishes */
|
215
172
|
if (field.flags & BINARY_FLAG && field.charsetnr == 63) {
|
@@ -238,7 +195,6 @@ static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_e
|
|
238
195
|
}
|
239
196
|
return val;
|
240
197
|
}
|
241
|
-
#endif
|
242
198
|
|
243
199
|
/* Interpret microseconds digits left-aligned in fixed-width field.
|
244
200
|
* e.g. 10.123 seconds means 10 seconds and 123000 microseconds,
|
@@ -278,12 +234,12 @@ static void rb_mysql_result_alloc_result_buffers(VALUE self, MYSQL_FIELD *fields
|
|
278
234
|
wrapper->result_buffers[i].buffer_length = sizeof(signed char);
|
279
235
|
break;
|
280
236
|
case MYSQL_TYPE_SHORT: // short int
|
237
|
+
case MYSQL_TYPE_YEAR: // short int
|
281
238
|
wrapper->result_buffers[i].buffer = xcalloc(1, sizeof(short int));
|
282
239
|
wrapper->result_buffers[i].buffer_length = sizeof(short int);
|
283
240
|
break;
|
284
241
|
case MYSQL_TYPE_INT24: // int
|
285
242
|
case MYSQL_TYPE_LONG: // int
|
286
|
-
case MYSQL_TYPE_YEAR: // int
|
287
243
|
wrapper->result_buffers[i].buffer = xcalloc(1, sizeof(int));
|
288
244
|
wrapper->result_buffers[i].buffer_length = sizeof(int);
|
289
245
|
break;
|
@@ -335,16 +291,12 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
|
|
335
291
|
VALUE rowVal;
|
336
292
|
unsigned int i = 0;
|
337
293
|
|
338
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
339
294
|
rb_encoding *default_internal_enc;
|
340
295
|
rb_encoding *conn_enc;
|
341
|
-
#endif
|
342
296
|
GET_RESULT(self);
|
343
297
|
|
344
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
345
298
|
default_internal_enc = rb_default_internal_encoding();
|
346
299
|
conn_enc = rb_to_encoding(wrapper->encoding);
|
347
|
-
#endif
|
348
300
|
|
349
301
|
if (wrapper->fields == Qnil) {
|
350
302
|
wrapper->numberOfFields = mysql_num_fields(wrapper->result);
|
@@ -405,7 +357,15 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
|
|
405
357
|
val = INT2NUM(*((signed char*)result_buffer->buffer));
|
406
358
|
}
|
407
359
|
break;
|
360
|
+
case MYSQL_TYPE_BIT: /* BIT field (MySQL 5.0.3 and up) */
|
361
|
+
if (args->castBool && fields[i].length == 1) {
|
362
|
+
val = (*((unsigned char*)result_buffer->buffer) != 0) ? Qtrue : Qfalse;
|
363
|
+
}else{
|
364
|
+
val = rb_str_new(result_buffer->buffer, *(result_buffer->length));
|
365
|
+
}
|
366
|
+
break;
|
408
367
|
case MYSQL_TYPE_SHORT: // short int
|
368
|
+
case MYSQL_TYPE_YEAR: // short int
|
409
369
|
if (result_buffer->is_unsigned) {
|
410
370
|
val = UINT2NUM(*((unsigned short int*)result_buffer->buffer));
|
411
371
|
} else {
|
@@ -414,7 +374,6 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
|
|
414
374
|
break;
|
415
375
|
case MYSQL_TYPE_INT24: // int
|
416
376
|
case MYSQL_TYPE_LONG: // int
|
417
|
-
case MYSQL_TYPE_YEAR: // int
|
418
377
|
if (result_buffer->is_unsigned) {
|
419
378
|
val = UINT2NUM(*((unsigned int*)result_buffer->buffer));
|
420
379
|
} else {
|
@@ -485,7 +444,7 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
|
|
485
444
|
}
|
486
445
|
case MYSQL_TYPE_DECIMAL: // char[]
|
487
446
|
case MYSQL_TYPE_NEWDECIMAL: // char[]
|
488
|
-
val = rb_funcall(
|
447
|
+
val = rb_funcall(rb_mKernel, intern_BigDecimal, 1, rb_str_new(result_buffer->buffer, *(result_buffer->length)));
|
489
448
|
break;
|
490
449
|
case MYSQL_TYPE_STRING: // char[]
|
491
450
|
case MYSQL_TYPE_VAR_STRING: // char[]
|
@@ -494,15 +453,12 @@ static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, co
|
|
494
453
|
case MYSQL_TYPE_BLOB: // char[]
|
495
454
|
case MYSQL_TYPE_MEDIUM_BLOB: // char[]
|
496
455
|
case MYSQL_TYPE_LONG_BLOB: // char[]
|
497
|
-
case MYSQL_TYPE_BIT: // char[]
|
498
456
|
case MYSQL_TYPE_SET: // char[]
|
499
457
|
case MYSQL_TYPE_ENUM: // char[]
|
500
458
|
case MYSQL_TYPE_GEOMETRY: // char[]
|
501
459
|
default:
|
502
460
|
val = rb_str_new(result_buffer->buffer, *(result_buffer->length));
|
503
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
504
461
|
val = mysql2_set_field_string_encoding(val, fields[i], default_internal_enc, conn_enc);
|
505
|
-
#endif
|
506
462
|
break;
|
507
463
|
}
|
508
464
|
}
|
@@ -524,16 +480,12 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, MYSQL_FIELD * fields, const r
|
|
524
480
|
unsigned int i = 0;
|
525
481
|
unsigned long * fieldLengths;
|
526
482
|
void * ptr;
|
527
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
528
483
|
rb_encoding *default_internal_enc;
|
529
484
|
rb_encoding *conn_enc;
|
530
|
-
#endif
|
531
485
|
GET_RESULT(self);
|
532
486
|
|
533
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
534
487
|
default_internal_enc = rb_default_internal_encoding();
|
535
488
|
conn_enc = rb_to_encoding(wrapper->encoding);
|
536
|
-
#endif
|
537
489
|
|
538
490
|
ptr = wrapper->result;
|
539
491
|
row = (MYSQL_ROW)rb_thread_call_without_gvl(nogvl_fetch_row, ptr, RUBY_UBF_IO, 0);
|
@@ -563,9 +515,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, MYSQL_FIELD * fields, const r
|
|
563
515
|
val = Qnil;
|
564
516
|
} else {
|
565
517
|
val = rb_str_new(row[i], fieldLengths[i]);
|
566
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
567
518
|
val = mysql2_set_field_string_encoding(val, fields[i], default_internal_enc, conn_enc);
|
568
|
-
#endif
|
569
519
|
}
|
570
520
|
} else {
|
571
521
|
switch(type) {
|
@@ -596,9 +546,9 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, MYSQL_FIELD * fields, const r
|
|
596
546
|
if (fields[i].decimals == 0) {
|
597
547
|
val = rb_cstr2inum(row[i], 10);
|
598
548
|
} else if (strtod(row[i], NULL) == 0.000000){
|
599
|
-
val = rb_funcall(
|
549
|
+
val = rb_funcall(rb_mKernel, intern_BigDecimal, 1, opt_decimal_zero);
|
600
550
|
}else{
|
601
|
-
val = rb_funcall(
|
551
|
+
val = rb_funcall(rb_mKernel, intern_BigDecimal, 1, rb_str_new(row[i], fieldLengths[i]));
|
602
552
|
}
|
603
553
|
break;
|
604
554
|
case MYSQL_TYPE_FLOAT: /* FLOAT field */
|
@@ -716,9 +666,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, MYSQL_FIELD * fields, const r
|
|
716
666
|
case MYSQL_TYPE_GEOMETRY: /* Spatial fielda */
|
717
667
|
default:
|
718
668
|
val = rb_str_new(row[i], fieldLengths[i]);
|
719
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
720
669
|
val = mysql2_set_field_string_encoding(val, fields[i], default_internal_enc, conn_enc);
|
721
|
-
#endif
|
722
670
|
break;
|
723
671
|
}
|
724
672
|
}
|
@@ -920,6 +868,9 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
|
920
868
|
wrapper->numberOfRows = wrapper->stmt_wrapper ? mysql_stmt_num_rows(wrapper->stmt_wrapper->stmt) : mysql_num_rows(wrapper->result);
|
921
869
|
wrapper->rows = rb_ary_new2(wrapper->numberOfRows);
|
922
870
|
} else if (wrapper->rows && !cacheRows) {
|
871
|
+
if (wrapper->resultFreed) {
|
872
|
+
rb_raise(cMysql2Error, "Result set has already been freed");
|
873
|
+
}
|
923
874
|
mysql_data_seek(wrapper->result, 0);
|
924
875
|
wrapper->lastRowProcessed = 0;
|
925
876
|
wrapper->rows = rb_ary_new2(wrapper->numberOfRows);
|
@@ -1008,7 +959,6 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
|
|
1008
959
|
}
|
1009
960
|
|
1010
961
|
void init_mysql2_result() {
|
1011
|
-
cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
|
1012
962
|
cDate = rb_const_get(rb_cObject, rb_intern("Date"));
|
1013
963
|
cDateTime = rb_const_get(rb_cObject, rb_intern("DateTime"));
|
1014
964
|
|
@@ -1027,6 +977,7 @@ void init_mysql2_result() {
|
|
1027
977
|
intern_local_offset = rb_intern("local_offset");
|
1028
978
|
intern_civil = rb_intern("civil");
|
1029
979
|
intern_new_offset = rb_intern("new_offset");
|
980
|
+
intern_BigDecimal = rb_intern("BigDecimal");
|
1030
981
|
|
1031
982
|
sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
|
1032
983
|
sym_as = ID2SYM(rb_intern("as"));
|
@@ -1049,7 +1000,5 @@ void init_mysql2_result() {
|
|
1049
1000
|
opt_time_month = INT2NUM(1);
|
1050
1001
|
opt_utc_offset = INT2NUM(0);
|
1051
1002
|
|
1052
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
1053
1003
|
binaryEncoding = rb_enc_find("binary");
|
1054
|
-
#endif
|
1055
1004
|
}
|