mysql2 0.4.4 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
}
|