mysql2 0.2.24 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/.gitignore +12 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/CHANGELOG.md +148 -0
  5. data/Gemfile +3 -0
  6. data/README.rdoc +257 -0
  7. data/Rakefile +5 -0
  8. data/benchmark/active_record.rb +51 -0
  9. data/benchmark/active_record_threaded.rb +42 -0
  10. data/benchmark/allocations.rb +33 -0
  11. data/benchmark/escape.rb +36 -0
  12. data/benchmark/query_with_mysql_casting.rb +80 -0
  13. data/benchmark/query_without_mysql_casting.rb +47 -0
  14. data/benchmark/sequel.rb +37 -0
  15. data/benchmark/setup_db.rb +119 -0
  16. data/benchmark/threaded.rb +44 -0
  17. data/ext/mysql2/client.c +272 -849
  18. data/ext/mysql2/client.h +12 -27
  19. data/ext/mysql2/extconf.rb +14 -72
  20. data/ext/mysql2/mysql2_ext.h +4 -7
  21. data/ext/mysql2/result.c +123 -319
  22. data/ext/mysql2/result.h +1 -4
  23. data/lib/active_record/connection_adapters/em_mysql2_adapter.rb +64 -0
  24. data/lib/active_record/fiber_patches.rb +104 -0
  25. data/lib/mysql2.rb +5 -20
  26. data/lib/mysql2/client.rb +200 -50
  27. data/lib/mysql2/em.rb +3 -13
  28. data/lib/mysql2/em_fiber.rb +31 -0
  29. data/lib/mysql2/error.rb +6 -71
  30. data/lib/mysql2/version.rb +2 -2
  31. data/mysql2.gemspec +32 -0
  32. data/spec/em/em_fiber_spec.rb +22 -0
  33. data/spec/em/em_spec.rb +9 -74
  34. data/spec/mysql2/client_spec.rb +126 -593
  35. data/spec/mysql2/error_spec.rb +44 -58
  36. data/spec/mysql2/result_spec.rb +85 -257
  37. data/spec/spec_helper.rb +3 -24
  38. data/tasks/benchmarks.rake +20 -0
  39. data/tasks/compile.rake +71 -0
  40. data/tasks/rspec.rake +16 -0
  41. data/tasks/vendor_mysql.rake +40 -0
  42. metadata +179 -92
  43. checksums.yaml +0 -7
  44. data/README.md +0 -524
  45. data/ext/mysql2/infile.c +0 -122
  46. data/ext/mysql2/infile.h +0 -1
  47. data/ext/mysql2/mysql_enc_name_to_ruby.h +0 -168
  48. data/ext/mysql2/mysql_enc_to_ruby.h +0 -246
  49. data/ext/mysql2/wait_for_single_fd.h +0 -36
  50. data/lib/active_record/connection_adapters/mysql2_adapter.rb +0 -635
  51. data/lib/arel/engines/sql/compilers/mysql2_compiler.rb +0 -11
  52. data/lib/mysql2/console.rb +0 -5
  53. data/spec/configuration.yml.example +0 -17
  54. data/spec/my.cnf.example +0 -9
  55. data/spec/test_data +0 -1
  56. data/support/mysql_enc_to_ruby.rb +0 -82
  57. data/support/ruby_enc_to_mysql.rb +0 -61
data/ext/mysql2/client.h CHANGED
@@ -1,30 +1,24 @@
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
4
  /*
13
- * partial emulation of the 2.0 rb_thread_call_without_gvl under 1.8,
5
+ * partial emulation of the 1.9 rb_thread_blocking_region under 1.8,
14
6
  * this is enough for dealing with blocking I/O functions in the
15
7
  * presence of threads.
16
8
  */
9
+ #ifndef HAVE_RB_THREAD_BLOCKING_REGION
17
10
 
18
11
  #include <rubysig.h>
19
12
  #define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
20
13
  typedef void rb_unblock_function_t(void *);
21
- static void *
22
- rb_thread_call_without_gvl(
23
- void *(*func)(void *), void *data1,
14
+ typedef VALUE rb_blocking_function_t(void *);
15
+ static VALUE
16
+ rb_thread_blocking_region(
17
+ rb_blocking_function_t *func, void *data1,
24
18
  RB_MYSQL_UNUSED rb_unblock_function_t *ubf,
25
19
  RB_MYSQL_UNUSED void *data2)
26
20
  {
27
- void *rv;
21
+ VALUE rv;
28
22
 
29
23
  TRAP_BEG;
30
24
  rv = func(data1);
@@ -34,23 +28,14 @@ rb_thread_call_without_gvl(
34
28
  }
35
29
 
36
30
  #endif /* ! HAVE_RB_THREAD_BLOCKING_REGION */
37
- #endif /* ! HAVE_RB_THREAD_CALL_WITHOUT_GVL */
31
+
32
+ void init_mysql2_client();
38
33
 
39
34
  typedef struct {
40
35
  VALUE encoding;
41
- VALUE active_thread; /* rb_thread_current() or Qnil */
42
- long server_version;
43
- int reconnect_enabled;
44
- unsigned int connect_timeout;
45
- int active;
46
- int connected;
47
- int initialized;
48
- int refcount;
49
- int freed;
36
+ char active;
37
+ char closed;
50
38
  MYSQL *client;
51
39
  } mysql_client_wrapper;
52
40
 
53
- void init_mysql2_client();
54
- void decr_mysql2_client(mysql_client_wrapper *wrapper);
55
-
56
- #endif
41
+ #endif
@@ -5,14 +5,8 @@ def asplode lib
5
5
  abort "-----\n#{lib} is missing. please check your installation of mysql and try again.\n-----"
6
6
  end
7
7
 
8
- # 2.0-only
9
- have_header('ruby/thread.h') && have_func('rb_thread_call_without_gvl', 'ruby/thread.h')
10
-
11
8
  # 1.9-only
12
9
  have_func('rb_thread_blocking_region')
13
- have_func('rb_wait_for_single_fd')
14
- have_func('rb_hash_dup')
15
- have_func('rb_intern3')
16
10
 
17
11
  # borrowed from mysqlplus
18
12
  # http://github.com/oldmoe/mysqlplus/blob/master/ext/extconf.rb
@@ -22,7 +16,6 @@ dirs = ENV['PATH'].split(File::PATH_SEPARATOR) + %w[
22
16
  /opt/local/mysql
23
17
  /opt/local/lib/mysql5
24
18
  /usr
25
- /usr/mysql
26
19
  /usr/local
27
20
  /usr/local/mysql
28
21
  /usr/local/mysql-*
@@ -31,39 +24,20 @@ dirs = ENV['PATH'].split(File::PATH_SEPARATOR) + %w[
31
24
 
32
25
  GLOB = "{#{dirs.join(',')}}/{mysql_config,mysql_config5}"
33
26
 
34
- # If the user has provided a --with-mysql-dir argument, we must respect it or fail.
35
- inc, lib = dir_config('mysql')
36
- if inc && lib
37
- # Ruby versions not incorporating the mkmf fix at
38
- # https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/39717
39
- # do not properly search for lib directories, and must be corrected
40
- unless lib && lib[-3, 3] == 'lib'
41
- @libdir_basename = 'lib'
42
- inc, lib = dir_config('mysql')
43
- end
44
- abort "-----\nCannot find include dir(s) #{inc}\n-----" unless inc && inc.split(File::PATH_SEPARATOR).any?{|dir| File.directory?(dir)}
45
- abort "-----\nCannot find library dir(s) #{lib}\n-----" unless lib && lib.split(File::PATH_SEPARATOR).any?{|dir| File.directory?(dir)}
46
- warn "-----\nUsing --with-mysql-dir=#{File.dirname inc}\n-----"
47
- rpath_dir = lib
48
- elsif mc = (with_config('mysql-config') || Dir[GLOB].first)
49
- # If the user has provided a --with-mysql-config argument, we must respect it or fail.
50
- # If the user gave --with-mysql-config with no argument means we should try to find it.
27
+ if RUBY_PLATFORM =~ /mswin|mingw/
28
+ inc, lib = dir_config('mysql')
29
+ exit 1 unless have_library("libmysql")
30
+ elsif mc = (with_config('mysql-config') || Dir[GLOB].first) then
51
31
  mc = Dir[GLOB].first if mc == true
52
- abort "-----\nCannot find mysql_config at #{mc}\n-----" unless mc && File.exists?(mc)
53
- abort "-----\nCannot execute mysql_config at #{mc}\n-----" unless File.executable?(mc)
54
- warn "-----\nUsing mysql_config at #{mc}\n-----"
55
- ver = `#{mc} --version`.chomp.to_f
56
- includes = `#{mc} --include`.chomp
32
+ cflags = `#{mc} --cflags`.chomp
57
33
  exit 1 if $? != 0
58
34
  libs = `#{mc} --libs_r`.chomp
59
- # MySQL 5.5 and above already have re-entrant code in libmysqlclient (no _r).
60
- if ver >= 5.5 || libs.empty?
35
+ if libs.empty?
61
36
  libs = `#{mc} --libs`.chomp
62
37
  end
63
38
  exit 1 if $? != 0
64
- $INCFLAGS += ' ' + includes
39
+ $CPPFLAGS += ' ' + cflags
65
40
  $libs = libs + " " + $libs
66
- rpath_dir = libs
67
41
  else
68
42
  inc, lib = dir_config('mysql', '/usr/local')
69
43
  libs = ['m', 'z', 'socket', 'nsl', 'mygcc']
@@ -71,16 +45,11 @@ else
71
45
  exit 1 if libs.empty?
72
46
  have_library(libs.shift)
73
47
  end
74
- rpath_dir = lib
75
- end
76
-
77
- if RUBY_PLATFORM =~ /mswin|mingw/
78
- exit 1 unless have_library('libmysql')
79
48
  end
80
49
 
81
- if have_header('mysql.h')
50
+ if have_header('mysql.h') then
82
51
  prefix = nil
83
- elsif have_header('mysql/mysql.h')
52
+ elsif have_header('mysql/mysql.h') then
84
53
  prefix = 'mysql'
85
54
  else
86
55
  asplode 'mysql.h'
@@ -91,40 +60,13 @@ end
91
60
  asplode h unless have_header h
92
61
  end
93
62
 
94
- # These gcc style flags are also supported by clang and xcode compilers,
95
- # so we'll use a does-it-work test instead of an is-it-gcc test.
96
- gcc_flags = ' -Wall -funroll-loops'
97
- if try_link('int main() {return 0;}', gcc_flags)
98
- $CFLAGS << gcc_flags
63
+ unless RUBY_PLATFORM =~ /mswin/ or RUBY_PLATFORM =~ /sparc/
64
+ $CFLAGS << ' -Wall -funroll-loops'
99
65
  end
66
+ # $CFLAGS << ' -O0 -ggdb3 -Wextra'
100
67
 
101
- case explicit_rpath = with_config('mysql-rpath')
102
- when true
103
- abort "-----\nOption --with-mysql-rpath must have an argument\n-----"
104
- when false
105
- warn "-----\nOption --with-mysql-rpath has been disabled at your request\n-----"
106
- when String
107
- # The user gave us a value so use it
108
- rpath_flags = " -Wl,-rpath,#{explicit_rpath}"
109
- warn "-----\nSetting mysql rpath to #{explicit_rpath}\n-----"
110
- $LDFLAGS << rpath_flags
111
- else
112
- if libdir = rpath_dir[%r{(-L)?(/[^ ]+)}, 2]
113
- rpath_flags = " -Wl,-rpath,#{libdir}"
114
- if RbConfig::CONFIG["RPATHFLAG"].to_s.empty? && try_link('int main() {return 0;}', rpath_flags)
115
- # Usually Ruby sets RPATHFLAG the right way for each system, but not on OS X.
116
- warn "-----\nSetting rpath to #{libdir}\n-----"
117
- $LDFLAGS << rpath_flags
118
- else
119
- if RbConfig::CONFIG["RPATHFLAG"].to_s.empty?
120
- # If we got here because try_link failed, warn the user
121
- warn "-----\nDon't know how to set rpath on your system, if MySQL libraries are not in path mysql2 may not load\n-----"
122
- end
123
- # Make sure that LIBPATH gets set if we didn't explicitly set the rpath.
124
- warn "-----\nSetting libpath to #{libdir}\n-----"
125
- $LIBPATH << libdir unless $LIBPATH.include?(libdir)
126
- end
127
- end
68
+ if hard_mysql_path = $libs[%r{-L(/[^ ]+)}, 1]
69
+ $LDFLAGS << " -Wl,-rpath,#{hard_mysql_path}"
128
70
  end
129
71
 
130
72
  create_makefile('mysql2/mysql2')
@@ -1,11 +1,12 @@
1
1
  #ifndef MYSQL2_EXT
2
2
  #define MYSQL2_EXT
3
3
 
4
- /* tell rbx not to use it's caching compat layer
5
- by doing this we're making a promise to RBX that
6
- we'll never modify the pointers we get back from RSTRING_PTR */
4
+ // tell rbx not to use it's caching compat layer
5
+ // by doing this we're making a promize to RBX that
6
+ // we'll never modify the pointers we get back from RSTRING_PTR
7
7
  #define RSTRING_NOT_MODIFIED
8
8
  #include <ruby.h>
9
+ #include <fcntl.h>
9
10
 
10
11
  #ifndef HAVE_UINT
11
12
  #define HAVE_UINT
@@ -28,9 +29,6 @@ typedef unsigned int uint;
28
29
  #ifdef HAVE_RUBY_ENCODING_H
29
30
  #include <ruby/encoding.h>
30
31
  #endif
31
- #ifdef HAVE_RUBY_THREAD_H
32
- #include <ruby/thread.h>
33
- #endif
34
32
 
35
33
  #if defined(__GNUC__) && (__GNUC__ >= 3)
36
34
  #define RB_MYSQL_UNUSED __attribute__ ((unused))
@@ -40,6 +38,5 @@ typedef unsigned int uint;
40
38
 
41
39
  #include <client.h>
42
40
  #include <result.h>
43
- #include <infile.h>
44
41
 
45
42
  #endif
data/ext/mysql2/result.c CHANGED
@@ -1,62 +1,28 @@
1
1
  #include <mysql2_ext.h>
2
2
 
3
- #include <stdint.h>
4
-
5
- #include "mysql_enc_to_ruby.h"
6
-
7
3
  #ifdef HAVE_RUBY_ENCODING_H
8
4
  static rb_encoding *binaryEncoding;
9
5
  #endif
10
6
 
11
- #if (SIZEOF_INT < SIZEOF_LONG) || defined(HAVE_RUBY_ENCODING_H)
12
- /* on 64bit platforms we can handle dates way outside 2038-01-19T03:14:07
13
- *
14
- * (9999*31557600) + (12*2592000) + (31*86400) + (11*3600) + (59*60) + 59
15
- */
16
- #define MYSQL2_MAX_TIME 315578267999ULL
17
- #else
18
- /**
19
- * On 32bit platforms the maximum date the Time class can handle is 2038-01-19T03:14:07
20
- * 2038 years + 1 month + 19 days + 3 hours + 14 minutes + 7 seconds = 64318634047 seconds
21
- *
22
- * (2038*31557600) + (1*2592000) + (19*86400) + (3*3600) + (14*60) + 7
23
- */
24
- #define MYSQL2_MAX_TIME 64318634047ULL
25
- #endif
7
+ #define MYSQL2_MAX_YEAR 2058
26
8
 
27
- #if defined(HAVE_RUBY_ENCODING_H)
28
- /* 0000-1-1 00:00:00 UTC
29
- *
30
- * (0*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 0
31
- */
32
- #define MYSQL2_MIN_TIME 2678400ULL
33
- #elif SIZEOF_INT < SIZEOF_LONG /* 64bit Ruby 1.8 */
34
- /* 0139-1-1 00:00:00 UTC
35
- *
36
- * (139*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 0
37
- */
38
- #define MYSQL2_MIN_TIME 4389184800ULL
39
- #elif defined(NEGATIVE_TIME_T)
40
- /* 1901-12-13 20:45:52 UTC : The oldest time in 32-bit signed time_t.
41
- *
42
- * (1901*31557600) + (12*2592000) + (13*86400) + (20*3600) + (45*60) + 52
43
- */
44
- #define MYSQL2_MIN_TIME 60023299552ULL
9
+ #ifdef NEGATIVE_TIME_T
10
+ /* 1901-12-13 20:45:52 UTC : The oldest time in 32-bit signed time_t. */
11
+ #define MYSQL2_MIN_YEAR 1902
45
12
  #else
46
- /* 1970-01-01 00:00:01 UTC : The Unix epoch - the oldest time in portable time_t.
47
- *
48
- * (1970*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 1
49
- */
50
- #define MYSQL2_MIN_TIME 62171150401ULL
13
+ /* 1970-01-01 00:00:00 UTC : The Unix epoch - the oldest time in portable time_t. */
14
+ #define MYSQL2_MIN_YEAR 1970
51
15
  #endif
52
16
 
53
17
  static VALUE cMysql2Result;
54
18
  static VALUE cBigDecimal, cDate, cDateTime;
55
19
  static VALUE opt_decimal_zero, opt_float_zero, opt_time_year, opt_time_month, opt_utc_offset;
56
20
  extern VALUE mMysql2, cMysql2Client, cMysql2Error;
57
- static ID intern_new, intern_utc, intern_local, intern_localtime, intern_local_offset, intern_civil, intern_new_offset;
21
+ static VALUE intern_encoding_from_charset;
22
+ static ID intern_new, intern_utc, intern_local, intern_encoding_from_charset_code,
23
+ intern_localtime, intern_local_offset, intern_civil, intern_new_offset;
58
24
  static VALUE sym_symbolize_keys, sym_as, sym_array, sym_database_timezone, sym_application_timezone,
59
- sym_local, sym_utc, sym_cast_booleans, sym_cache_rows, sym_cast, sym_stream, sym_name;
25
+ sym_local, sym_utc, sym_cast_booleans, sym_cache_rows;
60
26
  static ID intern_merge;
61
27
 
62
28
  static void rb_mysql_result_mark(void * wrapper) {
@@ -65,29 +31,22 @@ static void rb_mysql_result_mark(void * wrapper) {
65
31
  rb_gc_mark(w->fields);
66
32
  rb_gc_mark(w->rows);
67
33
  rb_gc_mark(w->encoding);
68
- rb_gc_mark(w->client);
69
34
  }
70
35
  }
71
36
 
72
37
  /* this may be called manually or during GC */
73
38
  static void rb_mysql_result_free_result(mysql2_result_wrapper * wrapper) {
74
39
  if (wrapper && wrapper->resultFreed != 1) {
75
- /* FIXME: this may call flush_use_result, which can hit the socket */
76
40
  mysql_free_result(wrapper->result);
77
41
  wrapper->resultFreed = 1;
78
42
  }
79
43
  }
80
44
 
81
45
  /* this is called during GC */
82
- static void rb_mysql_result_free(void *ptr) {
83
- mysql2_result_wrapper * wrapper = ptr;
84
- rb_mysql_result_free_result(wrapper);
85
-
86
- // If the GC gets to client first it will be nil
87
- if (wrapper->client != Qnil) {
88
- decr_mysql2_client(wrapper->client_wrapper);
89
- }
90
-
46
+ static void rb_mysql_result_free(void * wrapper) {
47
+ mysql2_result_wrapper * w = wrapper;
48
+ /* FIXME: this may call flush_use_result, which can hit the socket */
49
+ rb_mysql_result_free_result(w);
91
50
  xfree(wrapper);
92
51
  }
93
52
 
@@ -96,10 +55,10 @@ static void rb_mysql_result_free(void *ptr) {
96
55
  * reliable way for us to tell this so we'll always release the GVL
97
56
  * to be safe
98
57
  */
99
- static void *nogvl_fetch_row(void *ptr) {
58
+ static VALUE nogvl_fetch_row(void *ptr) {
100
59
  MYSQL_RES *result = ptr;
101
60
 
102
- return mysql_fetch_row(result);
61
+ return (VALUE)mysql_fetch_row(result);
103
62
  }
104
63
 
105
64
  static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, short int symbolize_keys) {
@@ -122,14 +81,10 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, short int
122
81
 
123
82
  field = mysql_fetch_field_direct(wrapper->result, idx);
124
83
  if (symbolize_keys) {
125
- #ifdef HAVE_RB_INTERN3
126
- rb_field = rb_intern3(field->name, field->name_length, rb_utf8_encoding());
127
- rb_field = ID2SYM(rb_field);
128
- #else
129
- VALUE colStr;
130
- colStr = rb_str_new(field->name, field->name_length);
131
- rb_field = ID2SYM(rb_to_id(colStr));
132
- #endif
84
+ char buf[field->name_length+1];
85
+ memcpy(buf, field->name, field->name_length);
86
+ buf[field->name_length] = 0;
87
+ rb_field = ID2SYM(rb_intern(buf));
133
88
  } else {
134
89
  rb_field = rb_str_new(field->name, field->name_length);
135
90
  #ifdef HAVE_RUBY_ENCODING_H
@@ -145,56 +100,11 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, short int
145
100
  return rb_field;
146
101
  }
147
102
 
148
- #ifdef HAVE_RUBY_ENCODING_H
149
- static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_encoding *default_internal_enc, rb_encoding *conn_enc) {
150
- /* if binary flag is set, respect it's wishes */
151
- if (field.flags & BINARY_FLAG && field.charsetnr == 63) {
152
- rb_enc_associate(val, binaryEncoding);
153
- } else if (!field.charsetnr) {
154
- /* MySQL 4.x may not provide an encoding, binary will get the bytes through */
155
- rb_enc_associate(val, binaryEncoding);
156
- } else {
157
- /* lookup the encoding configured on this field */
158
- const char *enc_name;
159
- int enc_index;
160
-
161
- enc_name = mysql2_mysql_enc_to_rb[field.charsetnr-1];
162
- if (enc_name != NULL) {
163
- /* use the field encoding we were able to match */
164
- enc_index = rb_enc_find_index(enc_name);
165
- rb_enc_set_index(val, enc_index);
166
- } else {
167
- /* otherwise fall-back to the connection's encoding */
168
- rb_enc_associate(val, conn_enc);
169
- }
170
-
171
- if (default_internal_enc) {
172
- val = rb_str_export_to_enc(val, default_internal_enc);
173
- }
174
- }
175
- return val;
176
- }
177
- #endif
178
-
179
- /* Interpret microseconds digits left-aligned in fixed-width field.
180
- * e.g. 10.123 seconds means 10 seconds and 123000 microseconds,
181
- * because the microseconds are to the right of the decimal point.
182
- */
183
- static unsigned int msec_char_to_uint(char *msec_char, size_t len)
184
- {
185
- int i;
186
- for (i = 0; i < (len - 1); i++) {
187
- if (msec_char[i] == '\0') {
188
- msec_char[i] = '0';
189
- }
190
- }
191
- return (unsigned int)strtoul(msec_char, NULL, 10);
192
- }
193
-
194
- 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) {
103
+ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezone, int symbolizeKeys, int asArray, int castBool) {
195
104
  VALUE rowVal;
196
105
  mysql2_result_wrapper * wrapper;
197
106
  MYSQL_ROW row;
107
+ MYSQL_FIELD * fields = NULL;
198
108
  unsigned int i = 0;
199
109
  unsigned long * fieldLengths;
200
110
  void * ptr;
@@ -210,7 +120,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
210
120
  #endif
211
121
 
212
122
  ptr = wrapper->result;
213
- row = (MYSQL_ROW)rb_thread_call_without_gvl(nogvl_fetch_row, ptr, RUBY_UBF_IO, 0);
123
+ row = (MYSQL_ROW)rb_thread_blocking_region(nogvl_fetch_row, ptr, RUBY_UBF_IO, 0);
214
124
  if (row == NULL) {
215
125
  return Qnil;
216
126
  }
@@ -220,6 +130,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
220
130
  } else {
221
131
  rowVal = rb_hash_new();
222
132
  }
133
+ fields = mysql_fetch_fields(wrapper->result);
223
134
  fieldLengths = mysql_fetch_lengths(wrapper->result);
224
135
  if (wrapper->fields == Qnil) {
225
136
  wrapper->numberOfFields = mysql_num_fields(wrapper->result);
@@ -230,53 +141,35 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
230
141
  VALUE field = rb_mysql_result_fetch_field(self, i, symbolizeKeys);
231
142
  if (row[i]) {
232
143
  VALUE val = Qnil;
233
- enum enum_field_types type = fields[i].type;
234
-
235
- if(!cast) {
236
- if (type == MYSQL_TYPE_NULL) {
237
- val = Qnil;
238
- } else {
239
- val = rb_str_new(row[i], fieldLengths[i]);
240
- #ifdef HAVE_RUBY_ENCODING_H
241
- val = mysql2_set_field_string_encoding(val, fields[i], default_internal_enc, conn_enc);
242
- #endif
243
- }
244
- } else {
245
- switch(type) {
246
- case MYSQL_TYPE_NULL: /* NULL-type field */
144
+ switch(fields[i].type) {
145
+ case MYSQL_TYPE_NULL: // NULL-type field
247
146
  val = Qnil;
248
147
  break;
249
- case MYSQL_TYPE_BIT: /* BIT field (MySQL 5.0.3 and up) */
250
- if (castBool && fields[i].length == 1) {
251
- val = *row[i] == 1 ? Qtrue : Qfalse;
252
- }else{
253
- val = rb_str_new(row[i], fieldLengths[i]);
254
- }
148
+ case MYSQL_TYPE_BIT: // BIT field (MySQL 5.0.3 and up)
149
+ val = rb_str_new(row[i], fieldLengths[i]);
255
150
  break;
256
- case MYSQL_TYPE_TINY: /* TINYINT field */
151
+ case MYSQL_TYPE_TINY: // TINYINT field
257
152
  if (castBool && fields[i].length == 1) {
258
- val = *row[i] != '0' ? Qtrue : Qfalse;
153
+ val = *row[i] == '1' ? Qtrue : Qfalse;
259
154
  break;
260
155
  }
261
- case MYSQL_TYPE_SHORT: /* SMALLINT field */
262
- case MYSQL_TYPE_LONG: /* INTEGER field */
263
- case MYSQL_TYPE_INT24: /* MEDIUMINT field */
264
- case MYSQL_TYPE_LONGLONG: /* BIGINT field */
265
- case MYSQL_TYPE_YEAR: /* YEAR field */
156
+ case MYSQL_TYPE_SHORT: // SMALLINT field
157
+ case MYSQL_TYPE_LONG: // INTEGER field
158
+ case MYSQL_TYPE_INT24: // MEDIUMINT field
159
+ case MYSQL_TYPE_LONGLONG: // BIGINT field
160
+ case MYSQL_TYPE_YEAR: // YEAR field
266
161
  val = rb_cstr2inum(row[i], 10);
267
162
  break;
268
- case MYSQL_TYPE_DECIMAL: /* DECIMAL or NUMERIC field */
269
- case MYSQL_TYPE_NEWDECIMAL: /* Precision math DECIMAL or NUMERIC field (MySQL 5.0.3 and up) */
270
- if (fields[i].decimals == 0) {
271
- val = rb_cstr2inum(row[i], 10);
272
- } else if (strtod(row[i], NULL) == 0.000000){
163
+ case MYSQL_TYPE_DECIMAL: // DECIMAL or NUMERIC field
164
+ case MYSQL_TYPE_NEWDECIMAL: // Precision math DECIMAL or NUMERIC field (MySQL 5.0.3 and up)
165
+ if (strtod(row[i], NULL) == 0.000000){
273
166
  val = rb_funcall(cBigDecimal, intern_new, 1, opt_decimal_zero);
274
167
  }else{
275
168
  val = rb_funcall(cBigDecimal, intern_new, 1, rb_str_new(row[i], fieldLengths[i]));
276
169
  }
277
170
  break;
278
- case MYSQL_TYPE_FLOAT: /* FLOAT field */
279
- case MYSQL_TYPE_DOUBLE: { /* DOUBLE or REAL field */
171
+ case MYSQL_TYPE_FLOAT: // FLOAT field
172
+ case MYSQL_TYPE_DOUBLE: { // DOUBLE or REAL field
280
173
  double column_to_double;
281
174
  column_to_double = strtod(row[i], NULL);
282
175
  if (column_to_double == 0.000000){
@@ -286,69 +179,50 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
286
179
  }
287
180
  break;
288
181
  }
289
- case MYSQL_TYPE_TIME: { /* TIME field */
290
- int tokens;
291
- unsigned int hour=0, min=0, sec=0, msec=0;
292
- char msec_char[7] = {'0','0','0','0','0','0','\0'};
293
-
294
- tokens = sscanf(row[i], "%2u:%2u:%2u.%6s", &hour, &min, &sec, msec_char);
295
- if (tokens < 3) {
296
- val = Qnil;
297
- break;
298
- }
299
- msec = msec_char_to_uint(msec_char, sizeof(msec_char));
300
- val = rb_funcall(rb_cTime, db_timezone, 6, opt_time_year, opt_time_month, opt_time_month, UINT2NUM(hour), UINT2NUM(min), UINT2NUM(sec), UINT2NUM(msec));
182
+ case MYSQL_TYPE_TIME: { // TIME field
183
+ int hour, min, sec, tokens;
184
+ tokens = sscanf(row[i], "%2d:%2d:%2d", &hour, &min, &sec);
185
+ val = rb_funcall(rb_cTime, db_timezone, 6, opt_time_year, opt_time_month, opt_time_month, INT2NUM(hour), INT2NUM(min), INT2NUM(sec));
301
186
  if (!NIL_P(app_timezone)) {
302
187
  if (app_timezone == intern_local) {
303
188
  val = rb_funcall(val, intern_localtime, 0);
304
- } else { /* utc */
189
+ } else { // utc
305
190
  val = rb_funcall(val, intern_utc, 0);
306
191
  }
307
192
  }
308
193
  break;
309
194
  }
310
- case MYSQL_TYPE_TIMESTAMP: /* TIMESTAMP field */
311
- case MYSQL_TYPE_DATETIME: { /* DATETIME field */
312
- int tokens;
313
- unsigned int year=0, month=0, day=0, hour=0, min=0, sec=0, msec=0;
314
- char msec_char[7] = {'0','0','0','0','0','0','\0'};
315
- uint64_t seconds;
316
-
317
- tokens = sscanf(row[i], "%4u-%2u-%2u %2u:%2u:%2u.%6s", &year, &month, &day, &hour, &min, &sec, msec_char);
318
- if (tokens < 6) { /* msec might be empty */
319
- val = Qnil;
320
- break;
321
- }
322
- seconds = (year*31557600ULL) + (month*2592000ULL) + (day*86400ULL) + (hour*3600ULL) + (min*60ULL) + sec;
323
-
324
- if (seconds == 0) {
195
+ case MYSQL_TYPE_TIMESTAMP: // TIMESTAMP field
196
+ case MYSQL_TYPE_DATETIME: { // DATETIME field
197
+ int year, month, day, hour, min, sec, tokens;
198
+ tokens = sscanf(row[i], "%4d-%2d-%2d %2d:%2d:%2d", &year, &month, &day, &hour, &min, &sec);
199
+ if (year+month+day+hour+min+sec == 0) {
325
200
  val = Qnil;
326
201
  } else {
327
202
  if (month < 1 || day < 1) {
328
- rb_raise(cMysql2Error, "Invalid date in field '%.*s': %s", fields[i].name_length, fields[i].name, row[i]);
203
+ rb_raise(cMysql2Error, "Invalid date: %s", row[i]);
329
204
  val = Qnil;
330
205
  } else {
331
- if (seconds < MYSQL2_MIN_TIME || seconds > MYSQL2_MAX_TIME) { /* use DateTime for larger date range, does not support microseconds */
206
+ if (year < MYSQL2_MIN_YEAR || year+month+day > MYSQL2_MAX_YEAR) { // use DateTime instead
332
207
  VALUE offset = INT2NUM(0);
333
208
  if (db_timezone == intern_local) {
334
209
  offset = rb_funcall(cMysql2Client, intern_local_offset, 0);
335
210
  }
336
- val = rb_funcall(cDateTime, intern_civil, 7, UINT2NUM(year), UINT2NUM(month), UINT2NUM(day), UINT2NUM(hour), UINT2NUM(min), UINT2NUM(sec), offset);
211
+ val = rb_funcall(cDateTime, intern_civil, 7, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec), offset);
337
212
  if (!NIL_P(app_timezone)) {
338
213
  if (app_timezone == intern_local) {
339
214
  offset = rb_funcall(cMysql2Client, intern_local_offset, 0);
340
215
  val = rb_funcall(val, intern_new_offset, 1, offset);
341
- } else { /* utc */
216
+ } else { // utc
342
217
  val = rb_funcall(val, intern_new_offset, 1, opt_utc_offset);
343
218
  }
344
219
  }
345
220
  } else {
346
- msec = msec_char_to_uint(msec_char, sizeof(msec_char));
347
- val = rb_funcall(rb_cTime, db_timezone, 7, UINT2NUM(year), UINT2NUM(month), UINT2NUM(day), UINT2NUM(hour), UINT2NUM(min), UINT2NUM(sec), UINT2NUM(msec));
221
+ val = rb_funcall(rb_cTime, db_timezone, 6, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec));
348
222
  if (!NIL_P(app_timezone)) {
349
223
  if (app_timezone == intern_local) {
350
224
  val = rb_funcall(val, intern_localtime, 0);
351
- } else { /* utc */
225
+ } else { // utc
352
226
  val = rb_funcall(val, intern_utc, 0);
353
227
  }
354
228
  }
@@ -357,23 +231,18 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
357
231
  }
358
232
  break;
359
233
  }
360
- case MYSQL_TYPE_DATE: /* DATE field */
361
- case MYSQL_TYPE_NEWDATE: { /* Newer const used > 5.0 */
362
- int tokens;
363
- unsigned int year=0, month=0, day=0;
364
- tokens = sscanf(row[i], "%4u-%2u-%2u", &year, &month, &day);
365
- if (tokens < 3) {
366
- val = Qnil;
367
- break;
368
- }
234
+ case MYSQL_TYPE_DATE: // DATE field
235
+ case MYSQL_TYPE_NEWDATE: { // Newer const used > 5.0
236
+ int year, month, day, tokens;
237
+ tokens = sscanf(row[i], "%4d-%2d-%2d", &year, &month, &day);
369
238
  if (year+month+day == 0) {
370
239
  val = Qnil;
371
240
  } else {
372
241
  if (month < 1 || day < 1) {
373
- rb_raise(cMysql2Error, "Invalid date in field '%.*s': %s", fields[i].name_length, fields[i].name, row[i]);
242
+ rb_raise(cMysql2Error, "Invalid date: %s", row[i]);
374
243
  val = Qnil;
375
244
  } else {
376
- val = rb_funcall(cDate, intern_new, 3, UINT2NUM(year), UINT2NUM(month), UINT2NUM(day));
245
+ val = rb_funcall(cDate, intern_new, 3, INT2NUM(year), INT2NUM(month), INT2NUM(day));
377
246
  }
378
247
  }
379
248
  break;
@@ -384,17 +253,33 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
384
253
  case MYSQL_TYPE_BLOB:
385
254
  case MYSQL_TYPE_VAR_STRING:
386
255
  case MYSQL_TYPE_VARCHAR:
387
- case MYSQL_TYPE_STRING: /* CHAR or BINARY field */
388
- case MYSQL_TYPE_SET: /* SET field */
389
- case MYSQL_TYPE_ENUM: /* ENUM field */
390
- case MYSQL_TYPE_GEOMETRY: /* Spatial fielda */
256
+ case MYSQL_TYPE_STRING: // CHAR or BINARY field
257
+ case MYSQL_TYPE_SET: // SET field
258
+ case MYSQL_TYPE_ENUM: // ENUM field
259
+ case MYSQL_TYPE_GEOMETRY: // Spatial fielda
391
260
  default:
392
261
  val = rb_str_new(row[i], fieldLengths[i]);
393
262
  #ifdef HAVE_RUBY_ENCODING_H
394
- val = mysql2_set_field_string_encoding(val, fields[i], default_internal_enc, conn_enc);
263
+ // if binary flag is set, respect it's wishes
264
+ if (fields[i].flags & BINARY_FLAG && fields[i].charsetnr == 63) {
265
+ rb_enc_associate(val, binaryEncoding);
266
+ } else {
267
+ // lookup the encoding configured on this field
268
+ VALUE new_encoding = rb_funcall(cMysql2Client, intern_encoding_from_charset_code, 1, INT2NUM(fields[i].charsetnr));
269
+ if (new_encoding != Qnil) {
270
+ // use the field encoding we were able to match
271
+ rb_encoding *enc = rb_to_encoding(new_encoding);
272
+ rb_enc_associate(val, enc);
273
+ } else {
274
+ // otherwise fall-back to the connection's encoding
275
+ rb_enc_associate(val, conn_enc);
276
+ }
277
+ if (default_internal_enc) {
278
+ val = rb_str_export_to_enc(val, default_internal_enc);
279
+ }
280
+ }
395
281
  #endif
396
282
  break;
397
- }
398
283
  }
399
284
  if (asArray) {
400
285
  rb_ary_push(rowVal, val);
@@ -421,7 +306,6 @@ static VALUE rb_mysql_result_fetch_fields(VALUE self) {
421
306
  GetMysql2Result(self, wrapper);
422
307
 
423
308
  defaults = rb_iv_get(self, "@query_options");
424
- Check_Type(defaults, T_HASH);
425
309
  if (rb_hash_aref(defaults, sym_symbolize_keys) == Qtrue) {
426
310
  symbolizeKeys = 1;
427
311
  }
@@ -445,14 +329,11 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
445
329
  ID db_timezone, app_timezone, dbTz, appTz;
446
330
  mysql2_result_wrapper * wrapper;
447
331
  unsigned long i;
448
- const char * errstr;
449
- int symbolizeKeys = 0, asArray = 0, castBool = 0, cacheRows = 1, cast = 1, streaming = 0;
450
- MYSQL_FIELD * fields = NULL;
332
+ int symbolizeKeys = 0, asArray = 0, castBool = 0, cacheRows = 1;
451
333
 
452
334
  GetMysql2Result(self, wrapper);
453
335
 
454
336
  defaults = rb_iv_get(self, "@query_options");
455
- Check_Type(defaults, T_HASH);
456
337
  if (rb_scan_args(argc, argv, "01&", &opts, &block) == 1) {
457
338
  opts = rb_funcall(defaults, intern_merge, 1, opts);
458
339
  } else {
@@ -475,18 +356,6 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
475
356
  cacheRows = 0;
476
357
  }
477
358
 
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
- }
485
-
486
- if(streaming && cacheRows) {
487
- rb_warn("cacheRows is ignored if streaming is true");
488
- }
489
-
490
359
  dbTz = rb_hash_aref(opts, sym_database_timezone);
491
360
  if (dbTz == sym_local) {
492
361
  db_timezone = intern_local;
@@ -509,111 +378,56 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
509
378
  }
510
379
 
511
380
  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;
381
+ wrapper->numberOfRows = mysql_num_rows(wrapper->result);
382
+ if (wrapper->numberOfRows == 0) {
516
383
  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);
384
+ return wrapper->rows;
524
385
  }
386
+ wrapper->rows = rb_ary_new2(wrapper->numberOfRows);
525
387
  }
526
388
 
527
- if (streaming) {
528
- if (!wrapper->streamingComplete) {
529
- VALUE row;
530
-
531
- fields = mysql_fetch_fields(wrapper->result);
532
-
533
- do {
534
- 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++;
539
- }
540
- } while(row != Qnil);
541
-
542
- rb_mysql_result_free_result(wrapper);
543
-
544
- wrapper->numberOfRows = wrapper->lastRowProcessed;
545
- wrapper->streamingComplete = 1;
546
-
547
- // Check for errors, the connection might have gone out from under us
548
- // mysql_error returns an empty string if there is no error
549
- errstr = mysql_error(wrapper->client_wrapper->client);
550
- if (errstr[0]) {
551
- rb_raise(cMysql2Error, "%s", errstr);
552
- }
553
- } else {
554
- rb_raise(cMysql2Error, "You have already fetched all the rows for this query and streaming is true. (to reiterate you must requery).");
389
+ if (cacheRows && wrapper->lastRowProcessed == wrapper->numberOfRows) {
390
+ // we've already read the entire dataset from the C result into our
391
+ // internal array. Lets hand that over to the user since it's ready to go
392
+ for (i = 0; i < wrapper->numberOfRows; i++) {
393
+ rb_yield(rb_ary_entry(wrapper->rows, i));
555
394
  }
556
395
  } else {
557
- if (cacheRows && wrapper->lastRowProcessed == wrapper->numberOfRows) {
558
- /* we've already read the entire dataset from the C result into our */
559
- /* internal array. Lets hand that over to the user since it's ready to go */
560
- for (i = 0; i < wrapper->numberOfRows; i++) {
561
- rb_yield(rb_ary_entry(wrapper->rows, i));
562
- }
563
- } else {
564
- unsigned long rowsProcessed = 0;
565
- rowsProcessed = RARRAY_LEN(wrapper->rows);
566
- fields = mysql_fetch_fields(wrapper->result);
567
-
568
- for (i = 0; i < wrapper->numberOfRows; i++) {
569
- VALUE row;
570
- if (cacheRows && i < rowsProcessed) {
571
- row = rb_ary_entry(wrapper->rows, i);
572
- } else {
573
- row = rb_mysql_result_fetch_row(self, db_timezone, app_timezone, symbolizeKeys, asArray, castBool, cast, fields);
574
- if (cacheRows) {
575
- rb_ary_store(wrapper->rows, i, row);
576
- }
577
- wrapper->lastRowProcessed++;
578
- }
579
-
580
- if (row == Qnil) {
581
- /* we don't need the mysql C dataset around anymore, peace it */
582
- rb_mysql_result_free_result(wrapper);
583
- return Qnil;
584
- }
585
-
586
- if (block != Qnil) {
587
- rb_yield(row);
396
+ unsigned long rowsProcessed = 0;
397
+ rowsProcessed = RARRAY_LEN(wrapper->rows);
398
+ for (i = 0; i < wrapper->numberOfRows; i++) {
399
+ VALUE row;
400
+ if (cacheRows && i < rowsProcessed) {
401
+ row = rb_ary_entry(wrapper->rows, i);
402
+ } else {
403
+ row = rb_mysql_result_fetch_row(self, db_timezone, app_timezone, symbolizeKeys, asArray, castBool);
404
+ if (cacheRows) {
405
+ rb_ary_store(wrapper->rows, i, row);
588
406
  }
407
+ wrapper->lastRowProcessed++;
589
408
  }
590
- if (wrapper->lastRowProcessed == wrapper->numberOfRows) {
591
- /* we don't need the mysql C dataset around anymore, peace it */
409
+
410
+ if (row == Qnil) {
411
+ // we don't need the mysql C dataset around anymore, peace it
592
412
  rb_mysql_result_free_result(wrapper);
413
+ return Qnil;
593
414
  }
415
+
416
+ if (block != Qnil) {
417
+ rb_yield(row);
418
+ }
419
+ }
420
+ if (wrapper->lastRowProcessed == wrapper->numberOfRows) {
421
+ // we don't need the mysql C dataset around anymore, peace it
422
+ rb_mysql_result_free_result(wrapper);
594
423
  }
595
424
  }
596
425
 
597
426
  return wrapper->rows;
598
427
  }
599
428
 
600
- static VALUE rb_mysql_result_count(VALUE self) {
601
- mysql2_result_wrapper *wrapper;
602
-
603
- GetMysql2Result(self, wrapper);
604
- if(wrapper->resultFreed) {
605
- if (wrapper->streamingComplete){
606
- return LONG2NUM(wrapper->numberOfRows);
607
- } else {
608
- return LONG2NUM(RARRAY_LEN(wrapper->rows));
609
- }
610
- } else {
611
- return INT2FIX(mysql_num_rows(wrapper->result));
612
- }
613
- }
614
-
615
429
  /* Mysql2::Result */
616
- VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_RES *r) {
430
+ VALUE rb_mysql_result_to_obj(MYSQL_RES * r) {
617
431
  VALUE obj;
618
432
  mysql2_result_wrapper * wrapper;
619
433
  obj = Data_Make_Struct(cMysql2Result, mysql2_result_wrapper, rb_mysql_result_mark, rb_mysql_result_free, wrapper);
@@ -624,16 +438,8 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
624
438
  wrapper->result = r;
625
439
  wrapper->fields = Qnil;
626
440
  wrapper->rows = Qnil;
627
- wrapper->encoding = encoding;
628
- wrapper->streamingComplete = 0;
629
- wrapper->client = client;
630
- wrapper->client_wrapper = DATA_PTR(client);
631
- wrapper->client_wrapper->refcount++;
632
-
441
+ wrapper->encoding = Qnil;
633
442
  rb_obj_call_init(obj, 0, NULL);
634
-
635
- rb_iv_set(obj, "@query_options", options);
636
-
637
443
  return obj;
638
444
  }
639
445
 
@@ -645,8 +451,9 @@ void init_mysql2_result() {
645
451
  cMysql2Result = rb_define_class_under(mMysql2, "Result", rb_cObject);
646
452
  rb_define_method(cMysql2Result, "each", rb_mysql_result_each, -1);
647
453
  rb_define_method(cMysql2Result, "fields", rb_mysql_result_fetch_fields, 0);
648
- rb_define_method(cMysql2Result, "count", rb_mysql_result_count, 0);
649
- rb_define_alias(cMysql2Result, "size", "count");
454
+
455
+ intern_encoding_from_charset = rb_intern("encoding_from_charset");
456
+ intern_encoding_from_charset_code = rb_intern("encoding_from_charset_code");
650
457
 
651
458
  intern_new = rb_intern("new");
652
459
  intern_utc = rb_intern("utc");
@@ -666,12 +473,9 @@ void init_mysql2_result() {
666
473
  sym_database_timezone = ID2SYM(rb_intern("database_timezone"));
667
474
  sym_application_timezone = ID2SYM(rb_intern("application_timezone"));
668
475
  sym_cache_rows = ID2SYM(rb_intern("cache_rows"));
669
- sym_cast = ID2SYM(rb_intern("cast"));
670
- sym_stream = ID2SYM(rb_intern("stream"));
671
- sym_name = ID2SYM(rb_intern("name"));
672
476
 
673
477
  opt_decimal_zero = rb_str_new2("0.0");
674
- rb_global_variable(&opt_decimal_zero); /*never GC */
478
+ rb_global_variable(&opt_decimal_zero); //never GC
675
479
  opt_float_zero = rb_float_new((double)0);
676
480
  rb_global_variable(&opt_float_zero);
677
481
  opt_time_year = INT2NUM(2000);