do_sqlite3 0.10.3 → 0.10.4.rc1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2007 - 2010 Yehuda Katz, Dirkjan Bussink
1
+ Copyright (c) 2007 - 2011 Yehuda Katz, Dirkjan Bussink
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -18,10 +18,6 @@ An example of usage:
18
18
  @reader = @connection.create_command('SELECT * FROM users').execute_reader
19
19
  @reader.next!
20
20
 
21
- In the future, the `Connection` constructor will be able to be passed either a
22
- DataObjects-style URL or JDBC style URL, when using do\_sqlite3 on JRuby.
23
- However, this feature is not currently working reliably and is a known issue.
24
-
25
21
  ## Requirements
26
22
 
27
23
  This driver is provided for the following platforms:
@@ -74,7 +70,7 @@ For more information, see the SQLite3 driver wiki page:
74
70
  ## Developers
75
71
 
76
72
  Follow the above installation instructions. Additionally, you'll need:
77
- * `bacon` gem for running specs.
73
+ * `rspec` gem for running specs.
78
74
  * `YARD` gem for generating documentation.
79
75
 
80
76
  See the DataObjects wiki for more comprehensive information on installing and
@@ -91,10 +87,7 @@ To run specs without compiling extensions first:
91
87
 
92
88
  To run individual specs:
93
89
 
94
- rake spec TEST=spec/connection_spec.rb
95
-
96
- (Note that the `rake` task uses a `TEST` parameter, not `SPEC`. This is because
97
- the `Rake::TestTask` is used for executing the Bacon specs).
90
+ rake spec SPEC=spec/connection_spec.rb
98
91
 
99
92
  ## License
100
93
 
data/Rakefile CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'pathname'
2
- require 'rubygems'
2
+ require 'bundler'
3
+ Bundler::GemHelper.install_tasks
4
+
3
5
  require 'rake'
4
6
  require 'rake/clean'
5
7
 
@@ -11,53 +13,18 @@ JRUBY = RUBY_PLATFORM =~ /java/
11
13
  IRONRUBY = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ironruby'
12
14
  WINDOWS = Gem.win_platform? || (JRUBY && ENV_JAVA['os.name'] =~ /windows/i)
13
15
  SUDO = WINDOWS ? '' : ('sudo' unless ENV['SUDOLESS'])
14
- BINARY_VERSION = '3070400'
16
+ BINARY_VERSION = '3070600'
15
17
 
16
18
  CLEAN.include(%w[ {tmp,pkg}/ **/*.{o,so,bundle,jar,log,a,gem,dSYM,obj,pdb,exp,DS_Store,rbc,db} ext/do_sqlite3/Makefile ext-java/target ])
17
19
 
18
- begin
19
- gem 'jeweler', '~> 1.4'
20
- require 'jeweler'
21
-
22
- Jeweler::Tasks.new do |gem|
23
- gem.name = 'do_sqlite3'
24
- gem.version = DataObjects::Sqlite3::VERSION
25
- gem.summary = 'DataObjects Sqlite3 Driver'
26
- gem.description = 'Implements the DataObjects API for Sqlite3'
27
- gem.platform = Gem::Platform::RUBY
28
- gem.files = FileList['lib/**/*.rb', 'spec/**/*.rb', 'tasks/**/*.rake',
29
- 'ext/**/*.{rb,c,h}', 'LICENSE', 'Rakefile',
30
- '*.{markdown,rdoc,txt,yml}']
31
- gem.extra_rdoc_files = FileList['README*', 'ChangeLog*', 'LICENSE']
32
- gem.test_files = FileList['spec/**/*.rb']
33
-
34
- # rake-compiler should generate gemspecs for other platforms (e.g. 'java')
35
- # and modify dependencies and extensions appropriately
36
- gem.extensions << 'ext/do_sqlite3/extconf.rb'
37
-
38
- gem.add_dependency 'data_objects', DataObjects::Sqlite3::VERSION
39
-
40
- gem.add_development_dependency 'bacon', '~>1.1'
41
- gem.add_development_dependency 'rake-compiler', '= 0.7.0'
42
-
43
- gem.has_rdoc = false
44
- gem.rubyforge_project = 'dorb'
45
- gem.authors = [ 'Dirkjan Bussink' ]
46
- gem.email = 'd.bussink@gmail.com'
47
- end
48
20
 
49
- if JRUBY
50
- Rake::Task['build'].clear_actions if Rake::Task.task_defined?('build')
51
- Rake::Task['install'].clear_actions if Rake::Task.task_defined?('install')
52
- task :build => [ :java, :gem ]
53
- task :install do
54
- sh "#{Config::CONFIG['RUBY_INSTALL_NAME']} -S gem install pkg/do_sqlite3-#{DataObjects::Sqlite3::VERSION}-java.gem"
55
- end
21
+ if JRUBY
22
+ Rake::Task['build'].clear_actions if Rake::Task.task_defined?('build')
23
+ Rake::Task['install'].clear_actions if Rake::Task.task_defined?('install')
24
+ task :build => [ :java, :gem ]
25
+ task :install do
26
+ sh "#{Config::CONFIG['RUBY_INSTALL_NAME']} -S gem install pkg/do_sqlite3-#{DataObjects::Sqlite3::VERSION}-java.gem"
56
27
  end
57
-
58
- Jeweler::GemcutterTasks.new
59
-
60
- FileList['tasks/**/*.rake'].each { |task| import task }
61
- rescue LoadError
62
- puts 'Jeweler (or a dependency) not available. Install it with: gem install jeweler'
63
28
  end
29
+
30
+ FileList['tasks/**/*.rake'].each { |task| import task }
@@ -0,0 +1,526 @@
1
+ #include <ruby.h>
2
+ #include <string.h>
3
+ #include <math.h>
4
+ #include <ctype.h>
5
+ #include <time.h>
6
+
7
+ #include "do_common.h"
8
+
9
+ /*
10
+ * Common variables ("globals")
11
+ */
12
+
13
+ // To store rb_intern values
14
+ ID ID_NEW;
15
+ ID ID_NEW_DATE;
16
+ ID ID_CONST_GET;
17
+ ID ID_RATIONAL;
18
+ ID ID_ESCAPE;
19
+ ID ID_STRFTIME;
20
+ ID ID_LOG;
21
+
22
+ // Reference to Extlib module
23
+ VALUE mExtlib;
24
+ VALUE rb_cByteArray;
25
+
26
+ // References to DataObjects base classes
27
+ VALUE mDO;
28
+ VALUE cDO_Quoting;
29
+ VALUE cDO_Connection;
30
+ VALUE cDO_Command;
31
+ VALUE cDO_Result;
32
+ VALUE cDO_Reader;
33
+ VALUE cDO_Logger;
34
+ VALUE cDO_Logger_Message;
35
+ VALUE cDO_Extension;
36
+ VALUE eConnectionError;
37
+ VALUE eDataError;
38
+
39
+ // References to Ruby classes that we'll need
40
+ VALUE rb_cDate;
41
+ VALUE rb_cDateTime;
42
+ VALUE rb_cBigDecimal;
43
+
44
+ /*
45
+ * Common Functions
46
+ */
47
+
48
+ void data_objects_debug(VALUE connection, VALUE string, struct timeval *start) {
49
+ struct timeval stop;
50
+ VALUE message;
51
+
52
+ gettimeofday(&stop, NULL);
53
+ do_int64 duration = (stop.tv_sec - start->tv_sec) * 1000000 + stop.tv_usec - start->tv_usec;
54
+
55
+ message = rb_funcall(cDO_Logger_Message, ID_NEW, 3, string, rb_time_new(start->tv_sec, start->tv_usec), INT2NUM(duration));
56
+
57
+ rb_funcall(connection, ID_LOG, 1, message);
58
+ }
59
+
60
+ void do_raise_error(VALUE self, const struct errcodes *errors, int errnum, const char *message, VALUE query, VALUE state) {
61
+ const char *exception_type = "SQLError";
62
+ const struct errcodes *e;
63
+
64
+ for (e = errors; e->error_name; e++) {
65
+ if (e->error_no == errnum) {
66
+ // return the exception type for the matching error
67
+ exception_type = e->exception;
68
+ break;
69
+ }
70
+ }
71
+
72
+ VALUE uri = rb_funcall(rb_iv_get(self, "@connection"), rb_intern("to_s"), 0);
73
+
74
+ VALUE exception = rb_funcall(
75
+ do_const_get(mDO, exception_type),
76
+ ID_NEW,
77
+ 5,
78
+ rb_str_new2(message),
79
+ INT2NUM(errnum),
80
+ state,
81
+ query,
82
+ uri
83
+ );
84
+
85
+ rb_exc_raise(exception);
86
+ }
87
+
88
+ char *get_uri_option(VALUE query_hash, const char *key) {
89
+ VALUE query_value;
90
+ char *value = NULL;
91
+
92
+ if (!rb_obj_is_kind_of(query_hash, rb_cHash)) {
93
+ return NULL;
94
+ }
95
+
96
+ query_value = rb_hash_aref(query_hash, rb_str_new2(key));
97
+
98
+ if (Qnil != query_value) {
99
+ value = StringValuePtr(query_value);
100
+ }
101
+
102
+ return value;
103
+ }
104
+
105
+ void assert_file_exists(char *file, const char *message) {
106
+ if (file) {
107
+ if (rb_funcall(rb_cFile, rb_intern("exist?"), 1, rb_str_new2(file)) == Qfalse) {
108
+ rb_raise(rb_eArgError, "%s", message);
109
+ }
110
+ }
111
+ }
112
+
113
+ VALUE build_query_from_args(VALUE klass, int count, VALUE *args) {
114
+ VALUE array = rb_ary_new();
115
+ int i;
116
+
117
+ for (i = 0; i < count; i++) {
118
+ rb_ary_push(array, args[i]);
119
+ }
120
+
121
+ return rb_funcall(klass, ID_ESCAPE, 1, array);
122
+ }
123
+
124
+ // Find the greatest common denominator and reduce the provided numerator and denominator.
125
+ // This replaces calles to Rational.reduce! which does the same thing, but really slowly.
126
+ void reduce(do_int64 *numerator, do_int64 *denominator) {
127
+ do_int64 a = *numerator, b = *denominator, c;
128
+
129
+ while (a != 0) {
130
+ c = a;
131
+ a = b % a;
132
+ b = c;
133
+ }
134
+
135
+ *numerator /= b;
136
+ *denominator /= b;
137
+ }
138
+
139
+ // Generate the date integer which Date.civil_to_jd returns
140
+ int jd_from_date(int year, int month, int day) {
141
+ int a, b;
142
+
143
+ if (month <= 2) {
144
+ year -= 1;
145
+ month += 12;
146
+ }
147
+
148
+ a = year / 100;
149
+ b = 2 - a + (a / 4);
150
+
151
+ return (int)(floor(365.25 * (year + 4716)) + floor(30.6001 * (month + 1)) + day + b - 1524);
152
+ }
153
+
154
+ VALUE seconds_to_offset(long seconds_offset) {
155
+ do_int64 num = seconds_offset;
156
+ do_int64 den = 86400;
157
+
158
+ reduce(&num, &den);
159
+ return rb_funcall(rb_mKernel, ID_RATIONAL, 2, rb_ll2inum(num), rb_ll2inum(den));
160
+ }
161
+
162
+ VALUE timezone_to_offset(int hour_offset, int minute_offset) {
163
+ do_int64 seconds = 0;
164
+
165
+ seconds += hour_offset * 3600;
166
+ seconds += minute_offset * 60;
167
+
168
+ return seconds_to_offset(seconds);
169
+ }
170
+
171
+ VALUE parse_date(const char *date) {
172
+ static char const *const _fmt_date = "%4d-%2d-%2d";
173
+ int year = 0, month = 0, day = 0;
174
+ int jd, ajd;
175
+ VALUE rational;
176
+
177
+ switch (sscanf(date, _fmt_date, &year, &month, &day)) {
178
+ case 0:
179
+ case EOF:
180
+ return Qnil;
181
+ }
182
+
183
+ jd = jd_from_date(year, month, day);
184
+ ajd = (jd * 2) - 1; // Math from Date.jd_to_ajd
185
+ rational = rb_funcall(rb_mKernel, ID_RATIONAL, 2, INT2NUM(ajd), INT2NUM(2));
186
+
187
+ return rb_funcall(rb_cDate, ID_NEW_DATE, 3, rational, INT2NUM(0), INT2NUM(2299161));
188
+ }
189
+
190
+ VALUE parse_time(const char *date) {
191
+ static char const* const _fmt_datetime = "%4d-%2d-%2d %2d:%2d:%2d%7lf";
192
+ int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0, usec = 0;
193
+ double subsec = 0;
194
+
195
+ switch (sscanf(date, _fmt_datetime, &year, &month, &day, &hour, &min, &sec, &subsec)) {
196
+ case 0:
197
+ case EOF:
198
+ return Qnil;
199
+ }
200
+
201
+ usec = (int) (subsec * 1000000);
202
+
203
+ /* Mysql TIMESTAMPS can default to 0 */
204
+ if ((year + month + day + hour + min + sec + usec) == 0) {
205
+ return Qnil;
206
+ }
207
+
208
+ return rb_funcall(rb_cTime, rb_intern("local"), 7, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec), INT2NUM(usec));
209
+ }
210
+
211
+ VALUE parse_date_time(const char *date) {
212
+ static char const* const _fmt_datetime_tz_normal = "%4d-%2d-%2d %2d:%2d:%2d%3d:%2d";
213
+ static char const* const _fmt_datetime_tz_subsec = "%4d-%2d-%2d %2d:%2d:%2d.%*d%3d:%2d";
214
+ int tokens_read;
215
+ const char *fmt_datetime;
216
+
217
+ VALUE ajd, offset;
218
+
219
+ int year, month, day, hour, min, sec, hour_offset, minute_offset, jd;
220
+ do_int64 num, den;
221
+
222
+ struct tm timeinfo;
223
+ time_t target_time;
224
+ time_t gmt_offset;
225
+ int dst_adjustment;
226
+
227
+ if (*date == '\0') {
228
+ return Qnil;
229
+ }
230
+
231
+ /*
232
+ * We handle the following cases:
233
+ * - Date (default to midnight) [3 tokens, missing 5]
234
+ * - DateTime [6 tokens, missing 2]
235
+ * - DateTime with hour, possibly minute TZ offset [7-8 tokens]
236
+ */
237
+ fmt_datetime = strchr(date, '.') ? _fmt_datetime_tz_subsec : _fmt_datetime_tz_normal;
238
+ tokens_read = sscanf(date, fmt_datetime, &year, &month, &day, &hour, &min, &sec, &hour_offset, &minute_offset);
239
+
240
+ switch (tokens_read) {
241
+ case 8:
242
+ minute_offset *= hour_offset < 0 ? -1 : 1;
243
+ break;
244
+
245
+ case 7: /* Only got TZ hour offset, so assume 0 for minute */
246
+ minute_offset = 0;
247
+ break;
248
+
249
+ case 3: /* Only got Date */
250
+ hour = 0;
251
+ min = 0;
252
+ sec = 0;
253
+ /* Fall through */
254
+
255
+ case 6: /* Only got DateTime */
256
+ /*
257
+ * Interpret the DateTime from the local system TZ. If target date would
258
+ * end up in DST, assume adjustment of a 1 hour shift.
259
+ *
260
+ * FIXME: The DST adjustment calculation won't be accurate for timezones
261
+ * that observe fractional-hour shifts. But that's a real minority for
262
+ * now..
263
+ */
264
+ timeinfo.tm_year = year - 1900;
265
+ timeinfo.tm_mon = month - 1; // 0 - 11
266
+ timeinfo.tm_mday = day;
267
+ timeinfo.tm_hour = hour;
268
+ timeinfo.tm_min = min;
269
+ timeinfo.tm_sec = sec;
270
+ timeinfo.tm_isdst = -1;
271
+
272
+ target_time = mktime(&timeinfo);
273
+ dst_adjustment = timeinfo.tm_isdst ? 3600 : 0;
274
+
275
+ /*
276
+ * Now figure out seconds from UTC. For that we need a UTC/GMT-adjusted
277
+ * time_t, which we get from mktime(gmtime(current_time)).
278
+ *
279
+ * NOTE: Some modern libc's have tm_gmtoff in struct tm, but we can't count
280
+ * on that.
281
+ */
282
+ #ifdef HAVE_GMTIME_R
283
+ gmtime_r(&target_time, &timeinfo);
284
+ #else
285
+ timeinfo = *gmtime(&target_time);
286
+ #endif
287
+
288
+ gmt_offset = target_time - mktime(&timeinfo) + dst_adjustment;
289
+ hour_offset = ((int)gmt_offset / 3600);
290
+ minute_offset = ((int)gmt_offset % 3600 / 60);
291
+ break;
292
+
293
+ default: /* Any other combo of missing tokens and we can't do anything */
294
+ rb_raise(eDataError, "Couldn't parse date: %s", date);
295
+ }
296
+
297
+ jd = jd_from_date(year, month, day);
298
+
299
+ /*
300
+ * Generate ajd with fractional days for the time.
301
+ * Extracted from Date#jd_to_ajd, Date#day_fraction_to_time, and Rational#+ and #-.
302
+ *
303
+ * TODO: These are 64bit numbers; is reduce() really necessary?
304
+ */
305
+
306
+ num = (hour * 1440) + (min * 24);
307
+ num -= (hour_offset * 1440) + (minute_offset * 24);
308
+ den = (24 * 1440);
309
+ reduce(&num, &den);
310
+
311
+ num = (num * 86400) + (sec * den);
312
+ den = den * 86400;
313
+ reduce(&num, &den);
314
+
315
+ num += jd * den;
316
+
317
+ num = (num * 2) - den;
318
+ den *= 2;
319
+ reduce(&num, &den);
320
+
321
+ ajd = rb_funcall(rb_mKernel, ID_RATIONAL, 2, rb_ull2inum(num), rb_ull2inum(den));
322
+ offset = timezone_to_offset(hour_offset, minute_offset);
323
+
324
+ return rb_funcall(rb_cDateTime, ID_NEW_DATE, 3, ajd, offset, INT2NUM(2299161));
325
+ }
326
+
327
+ VALUE cConnection_character_set(VALUE self) {
328
+ return rb_iv_get(self, "@encoding");
329
+ }
330
+
331
+ VALUE cConnection_is_using_socket(VALUE self) {
332
+ return rb_iv_get(self, "@using_socket");
333
+ }
334
+
335
+ VALUE cConnection_ssl_cipher(VALUE self) {
336
+ return rb_iv_get(self, "@ssl_cipher");
337
+ }
338
+
339
+ VALUE cConnection_quote_time(VALUE self, VALUE value) {
340
+ return rb_funcall(value, ID_STRFTIME, 1, rb_str_new2("'%Y-%m-%d %H:%M:%S'"));
341
+ }
342
+
343
+ VALUE cConnection_quote_date_time(VALUE self, VALUE value) {
344
+ // TODO: Support non-local dates. we need to call #new_offset on the date to be
345
+ // quoted and pass in the current locale's date offset (self.new_offset((hours * 3600).to_r / 86400)
346
+ return rb_funcall(value, ID_STRFTIME, 1, rb_str_new2("'%Y-%m-%d %H:%M:%S'"));
347
+ }
348
+
349
+ VALUE cConnection_quote_date(VALUE self, VALUE value) {
350
+ return rb_funcall(value, ID_STRFTIME, 1, rb_str_new2("'%Y-%m-%d'"));
351
+ }
352
+
353
+ /*
354
+ * Accepts an array of Ruby types (Fixnum, Float, String, etc...) and turns them
355
+ * into Ruby-strings so we can easily typecast later
356
+ */
357
+ VALUE cCommand_set_types(int argc, VALUE *argv, VALUE self) {
358
+ VALUE type_strings = rb_ary_new();
359
+ VALUE array = rb_ary_new();
360
+
361
+ int i, j;
362
+
363
+ for (i = 0; i < argc; i++) {
364
+ rb_ary_push(array, argv[i]);
365
+ }
366
+
367
+ VALUE entry, sub_entry;
368
+
369
+ for (i = 0; i < RARRAY_LEN(array); i++) {
370
+ entry = rb_ary_entry(array, i);
371
+
372
+ if (TYPE(entry) == T_CLASS) {
373
+ rb_ary_push(type_strings, entry);
374
+ }
375
+ else if (TYPE(entry) == T_ARRAY) {
376
+ for (j = 0; j < RARRAY_LEN(entry); j++) {
377
+ sub_entry = rb_ary_entry(entry, j);
378
+
379
+ if (TYPE(sub_entry) == T_CLASS) {
380
+ rb_ary_push(type_strings, sub_entry);
381
+ }
382
+ else {
383
+ rb_raise(rb_eArgError, "Invalid type given");
384
+ }
385
+ }
386
+ }
387
+ else {
388
+ rb_raise(rb_eArgError, "Invalid type given");
389
+ }
390
+ }
391
+
392
+ rb_iv_set(self, "@field_types", type_strings);
393
+ return array;
394
+ }
395
+
396
+ VALUE cReader_values(VALUE self) {
397
+ VALUE state = rb_iv_get(self, "@opened");
398
+ VALUE values = rb_iv_get(self, "@values");
399
+
400
+ if (state == Qnil || state == Qfalse || values == Qnil) {
401
+ rb_raise(eDataError, "Reader is not initialized");
402
+ }
403
+
404
+ return rb_iv_get(self, "@values");
405
+ }
406
+
407
+ VALUE cReader_fields(VALUE self) {
408
+ return rb_iv_get(self, "@fields");
409
+ }
410
+
411
+ VALUE cReader_field_count(VALUE self) {
412
+ return rb_iv_get(self, "@field_count");
413
+ }
414
+
415
+ void common_init(void) {
416
+ rb_require("bigdecimal");
417
+ rb_require("rational");
418
+ rb_require("date");
419
+ rb_require("data_objects");
420
+
421
+ // Needed by do_const_get
422
+ ID_CONST_GET = rb_intern("const_get");
423
+
424
+ // Get references classes needed for Date/Time parsing
425
+ rb_cDate = do_const_get(rb_mKernel, "Date");
426
+ rb_cDateTime = do_const_get(rb_mKernel, "DateTime");
427
+ rb_cBigDecimal = do_const_get(rb_mKernel, "BigDecimal");
428
+
429
+ ID_NEW = rb_intern("new");
430
+ #ifdef RUBY_LESS_THAN_186
431
+ ID_NEW_DATE = rb_intern("new0");
432
+ #else
433
+ ID_NEW_DATE = rb_intern("new!");
434
+ #endif
435
+ ID_CONST_GET = rb_intern("const_get");
436
+ ID_RATIONAL = rb_intern("Rational");
437
+ ID_ESCAPE = rb_intern("escape_sql");
438
+ ID_STRFTIME = rb_intern("strftime");
439
+ ID_LOG = rb_intern("log");
440
+
441
+ // Get references to the Extlib module
442
+ mExtlib = do_const_get(rb_mKernel, "Extlib");
443
+ rb_cByteArray = do_const_get(mExtlib, "ByteArray");
444
+
445
+ // Get references to the DataObjects module and its classes
446
+ mDO = do_const_get(rb_mKernel, "DataObjects");
447
+ cDO_Quoting = do_const_get(mDO, "Quoting");
448
+ cDO_Connection = do_const_get(mDO, "Connection");
449
+ cDO_Command = do_const_get(mDO, "Command");
450
+ cDO_Result = do_const_get(mDO, "Result");
451
+ cDO_Reader = do_const_get(mDO, "Reader");
452
+ cDO_Logger = do_const_get(mDO, "Logger");
453
+ cDO_Logger_Message = do_const_get(cDO_Logger, "Message");
454
+ cDO_Extension = do_const_get(mDO, "Extension");
455
+
456
+ eConnectionError = do_const_get(mDO, "ConnectionError");
457
+ eDataError = do_const_get(mDO, "DataError");
458
+
459
+ rb_global_variable(&ID_NEW_DATE);
460
+ rb_global_variable(&ID_RATIONAL);
461
+ rb_global_variable(&ID_CONST_GET);
462
+ rb_global_variable(&ID_ESCAPE);
463
+ rb_global_variable(&ID_LOG);
464
+ rb_global_variable(&ID_NEW);
465
+
466
+ rb_global_variable(&rb_cDate);
467
+ rb_global_variable(&rb_cDateTime);
468
+ rb_global_variable(&rb_cBigDecimal);
469
+ rb_global_variable(&rb_cByteArray);
470
+
471
+ rb_global_variable(&mDO);
472
+ rb_global_variable(&cDO_Logger_Message);
473
+
474
+ rb_global_variable(&eConnectionError);
475
+ rb_global_variable(&eDataError);
476
+
477
+ tzset();
478
+ }
479
+
480
+ /*
481
+ * Common typecasting logic that can be used or overriden by Adapters.
482
+ */
483
+ extern VALUE do_typecast(const char *value, long length, const VALUE type, int encoding) {
484
+ #ifdef HAVE_RUBY_ENCODING_H
485
+ rb_encoding *internal_encoding = rb_default_internal_encoding();
486
+ #else
487
+ void *internal_encoding = NULL;
488
+ #endif
489
+
490
+ if (type == rb_cInteger) {
491
+ return rb_cstr2inum(value, 10);
492
+ }
493
+ else if (type == rb_cString) {
494
+ return do_str_new(value, length, encoding, internal_encoding);
495
+ }
496
+ else if (type == rb_cFloat) {
497
+ return rb_float_new(rb_cstr_to_dbl(value, Qfalse));
498
+ }
499
+ else if (type == rb_cBigDecimal) {
500
+ return rb_funcall(rb_cBigDecimal, ID_NEW, 1, rb_str_new(value, length));
501
+ }
502
+ else if (type == rb_cDate) {
503
+ return parse_date(value);
504
+ }
505
+ else if (type == rb_cDateTime) {
506
+ return parse_date_time(value);
507
+ }
508
+ else if (type == rb_cTime) {
509
+ return parse_time(value);
510
+ }
511
+ else if (type == rb_cTrueClass) {
512
+ return (!value || strcmp("0", value) == 0) ? Qfalse : Qtrue;
513
+ }
514
+ else if (type == rb_cByteArray) {
515
+ return rb_funcall(rb_cByteArray, ID_NEW, 1, rb_str_new(value, length));
516
+ }
517
+ else if (type == rb_cClass) {
518
+ return rb_funcall(mDO, rb_intern("full_const_get"), 1, rb_str_new(value, length));
519
+ }
520
+ else if (type == rb_cNilClass) {
521
+ return Qnil;
522
+ }
523
+ else {
524
+ return DO_STR_NEW(value, length, encoding, internal_encoding);
525
+ }
526
+ }