mysql2 0.2.24 → 0.3.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.
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);