sbf-do_sqlite3 0.10.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/ChangeLog.markdown +119 -0
  3. data/LICENSE +20 -0
  4. data/README.markdown +94 -0
  5. data/Rakefile +21 -0
  6. data/ext/do_sqlite3/compat.h +55 -0
  7. data/ext/do_sqlite3/do_common.c +510 -0
  8. data/ext/do_sqlite3/do_common.h +132 -0
  9. data/ext/do_sqlite3/do_sqlite3.c +448 -0
  10. data/ext/do_sqlite3/do_sqlite3.h +22 -0
  11. data/ext/do_sqlite3/do_sqlite3_extension.c +87 -0
  12. data/ext/do_sqlite3/error.h +85 -0
  13. data/ext/do_sqlite3/extconf.rb +26 -0
  14. data/lib/do_sqlite3/transaction.rb +21 -0
  15. data/lib/do_sqlite3/version.rb +5 -0
  16. data/lib/do_sqlite3.rb +13 -0
  17. data/spec/command_spec.rb +6 -0
  18. data/spec/connection_spec.rb +26 -0
  19. data/spec/encoding_spec.rb +7 -0
  20. data/spec/error/sql_error_spec.rb +7 -0
  21. data/spec/reader_spec.rb +6 -0
  22. data/spec/result_spec.rb +17 -0
  23. data/spec/spec_helper.rb +138 -0
  24. data/spec/typecast/array_spec.rb +6 -0
  25. data/spec/typecast/bigdecimal_spec.rb +9 -0
  26. data/spec/typecast/boolean_spec.rb +9 -0
  27. data/spec/typecast/byte_array_spec.rb +6 -0
  28. data/spec/typecast/class_spec.rb +6 -0
  29. data/spec/typecast/date_spec.rb +9 -0
  30. data/spec/typecast/datetime_spec.rb +9 -0
  31. data/spec/typecast/float_spec.rb +10 -0
  32. data/spec/typecast/integer_spec.rb +6 -0
  33. data/spec/typecast/nil_spec.rb +18 -0
  34. data/spec/typecast/other_spec.rb +6 -0
  35. data/spec/typecast/range_spec.rb +6 -0
  36. data/spec/typecast/string_spec.rb +6 -0
  37. data/spec/typecast/time_spec.rb +7 -0
  38. data/tasks/compile.rake +23 -0
  39. data/tasks/release.rake +14 -0
  40. data/tasks/retrieve.rake +16 -0
  41. data/tasks/spec.rake +10 -0
  42. metadata +100 -0
@@ -0,0 +1,510 @@
1
+ #include <ruby.h>
2
+ #include <string.h>
3
+ #include <math.h>
4
+ #include <ctype.h>
5
+ #include <time.h>
6
+ #ifndef _WIN32
7
+ #include <sys/time.h>
8
+ #endif
9
+
10
+ #include "do_common.h"
11
+
12
+ /*
13
+ * Common variables ("globals")
14
+ */
15
+
16
+ // To store rb_intern values
17
+ ID DO_ID_NEW;
18
+ ID DO_ID_NEW_DATE;
19
+ ID DO_ID_CONST_GET;
20
+ ID DO_ID_RATIONAL;
21
+ ID DO_ID_ESCAPE;
22
+ ID DO_ID_STRFTIME;
23
+ ID DO_ID_LOG;
24
+
25
+ // Reference to Extlib module
26
+ VALUE mExtlib;
27
+ VALUE rb_cByteArray;
28
+
29
+ // References to DataObjects base classes
30
+ VALUE mDO;
31
+ VALUE cDO_Quoting;
32
+ VALUE cDO_Connection;
33
+ VALUE cDO_Command;
34
+ VALUE cDO_Result;
35
+ VALUE cDO_Reader;
36
+ VALUE cDO_Logger;
37
+ VALUE cDO_Logger_Message;
38
+ VALUE cDO_Extension;
39
+ VALUE eDO_ConnectionError;
40
+ VALUE eDO_DataError;
41
+
42
+ // References to Ruby classes that we'll need
43
+ VALUE rb_cDate;
44
+ VALUE rb_cDateTime;
45
+ VALUE rb_cBigDecimal;
46
+
47
+ /*
48
+ * Common Functions
49
+ */
50
+
51
+
52
+ VALUE data_objects_const_get(VALUE scope, const char *constant) {
53
+ return rb_funcall(scope, DO_ID_CONST_GET, 1, rb_str_new2(constant));
54
+ }
55
+
56
+ void data_objects_debug(VALUE connection, VALUE string, struct timeval *start) {
57
+ struct timeval stop;
58
+ VALUE message;
59
+ do_int64 duration;
60
+
61
+ gettimeofday(&stop, NULL);
62
+ duration = (stop.tv_sec - start->tv_sec) * 1000000 + stop.tv_usec - start->tv_usec;
63
+
64
+ message = rb_funcall(cDO_Logger_Message, DO_ID_NEW, 3, string, rb_time_new(start->tv_sec, start->tv_usec), INT2NUM(duration));
65
+
66
+ rb_funcall(connection, DO_ID_LOG, 1, message);
67
+ }
68
+
69
+ _Noreturn void data_objects_raise_error(VALUE self, const struct errcodes *errors, int errnum, VALUE message, VALUE query, VALUE state) {
70
+ const char *exception_type = "SQLError";
71
+ const struct errcodes *e;
72
+ VALUE uri, exception;
73
+
74
+ for (e = errors; e->error_name; e++) {
75
+ if (e->error_no == errnum) {
76
+ // return the exception type for the matching error
77
+ exception_type = e->exception;
78
+ break;
79
+ }
80
+ }
81
+
82
+ uri = rb_funcall(rb_iv_get(self, "@connection"), rb_intern("to_s"), 0);
83
+
84
+ exception = rb_funcall(
85
+ data_objects_const_get(mDO, exception_type),
86
+ DO_ID_NEW,
87
+ 5,
88
+ message,
89
+ INT2NUM(errnum),
90
+ state,
91
+ query,
92
+ uri
93
+ );
94
+
95
+ rb_exc_raise(exception);
96
+ }
97
+
98
+ char *data_objects_get_uri_option(VALUE query_hash, const char *key) {
99
+ VALUE query_value;
100
+ char *value = NULL;
101
+
102
+ if (!rb_obj_is_kind_of(query_hash, rb_cHash)) {
103
+ return NULL;
104
+ }
105
+
106
+ query_value = rb_hash_aref(query_hash, rb_str_new2(key));
107
+
108
+ if (Qnil != query_value) {
109
+ value = StringValuePtr(query_value);
110
+ }
111
+
112
+ return value;
113
+ }
114
+
115
+ void data_objects_assert_file_exists(char *file, const char *message) {
116
+ if (file) {
117
+ if (rb_funcall(rb_cFile, rb_intern("exist?"), 1, rb_str_new2(file)) == Qfalse) {
118
+ rb_raise(rb_eArgError, "%s", message);
119
+ }
120
+ }
121
+ }
122
+
123
+ VALUE data_objects_build_query_from_args(VALUE klass, int count, VALUE *args) {
124
+ int i;
125
+ VALUE array = rb_ary_new();
126
+
127
+ for (i = 0; i < count; i++) {
128
+ rb_ary_push(array, args[i]);
129
+ }
130
+
131
+ return rb_funcall(klass, DO_ID_ESCAPE, 1, array);
132
+ }
133
+
134
+ // Find the greatest common denominator and reduce the provided numerator and denominator.
135
+ // This replaces calles to Rational.reduce! which does the same thing, but really slowly.
136
+ void data_objects_reduce(do_int64 *numerator, do_int64 *denominator) {
137
+ do_int64 a = *numerator, b = *denominator, c;
138
+
139
+ while (a != 0) {
140
+ c = a;
141
+ a = b % a;
142
+ b = c;
143
+ }
144
+
145
+ *numerator /= b;
146
+ *denominator /= b;
147
+ }
148
+
149
+ // Generate the date integer which Date.civil_to_jd returns
150
+ int data_objects_jd_from_date(int year, int month, int day) {
151
+ int a, b;
152
+
153
+ if (month <= 2) {
154
+ year -= 1;
155
+ month += 12;
156
+ }
157
+
158
+ a = year / 100;
159
+ b = 2 - a + (a / 4);
160
+
161
+ return (int)(floor(365.25 * (year + 4716)) + floor(30.6001 * (month + 1)) + day + b - 1524);
162
+ }
163
+
164
+ VALUE data_objects_seconds_to_offset(long seconds_offset) {
165
+ do_int64 num = seconds_offset;
166
+ do_int64 den = 86400;
167
+
168
+ data_objects_reduce(&num, &den);
169
+ return rb_funcall(rb_mKernel, DO_ID_RATIONAL, 2, rb_ll2inum(num), rb_ll2inum(den));
170
+ }
171
+
172
+ VALUE data_objects_timezone_to_offset(int hour_offset, int minute_offset) {
173
+ do_int64 seconds = 0;
174
+
175
+ seconds += hour_offset * 3600;
176
+ seconds += minute_offset * 60;
177
+
178
+ return data_objects_seconds_to_offset(seconds);
179
+ }
180
+
181
+ VALUE data_objects_parse_date(const char *date) {
182
+ static char const *const _fmt_date = "%4d-%2d-%2d";
183
+ int year = 0, month = 0, day = 0;
184
+
185
+ switch (sscanf(date, _fmt_date, &year, &month, &day)) {
186
+ case 0:
187
+ case EOF:
188
+ return Qnil;
189
+ }
190
+
191
+ if(!year && !month && !day) {
192
+ return Qnil;
193
+ }
194
+
195
+ return rb_funcall(rb_cDate, DO_ID_NEW, 3, INT2NUM(year), INT2NUM(month), INT2NUM(day));
196
+ }
197
+
198
+ VALUE data_objects_parse_time(const char *date) {
199
+ static char const* const _fmt_datetime = "%4d-%2d-%2d%*c%2d:%2d:%2d%7lf";
200
+ int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0, usec = 0;
201
+ double subsec = 0;
202
+
203
+ switch (sscanf(date, _fmt_datetime, &year, &month, &day, &hour, &min, &sec, &subsec)) {
204
+ case 0:
205
+ case EOF:
206
+ return Qnil;
207
+ }
208
+
209
+ usec = (int) (subsec * 1000000);
210
+
211
+ /* Mysql TIMESTAMPS can default to 0 */
212
+ if ((year + month + day + hour + min + sec + usec) == 0) {
213
+ return Qnil;
214
+ }
215
+
216
+ return rb_funcall(rb_cTime, rb_intern("local"), 7, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec), INT2NUM(usec));
217
+ }
218
+
219
+ VALUE data_objects_parse_date_time(const char *date) {
220
+ static char const* const _fmt_datetime_tz_normal = "%4d-%2d-%2d%*c%2d:%2d:%2d%3d:%2d";
221
+ static char const* const _fmt_datetime_tz_subsec = "%4d-%2d-%2d%*c%2d:%2d:%2d.%*d%3d:%2d";
222
+ int tokens_read;
223
+ const char *fmt_datetime;
224
+
225
+ VALUE offset;
226
+
227
+ int year, month, day, hour, min, sec, hour_offset, minute_offset;
228
+
229
+ struct tm timeinfo;
230
+ time_t target_time;
231
+ time_t gmt_offset;
232
+ int dst_adjustment;
233
+
234
+ if (*date == '\0') {
235
+ return Qnil;
236
+ }
237
+
238
+ /*
239
+ * We handle the following cases:
240
+ * - Date (default to midnight) [3 tokens, missing 5]
241
+ * - DateTime [6 tokens, missing 2]
242
+ * - DateTime with hour, possibly minute TZ offset [7-8 tokens]
243
+ */
244
+ fmt_datetime = strchr(date, '.') ? _fmt_datetime_tz_subsec : _fmt_datetime_tz_normal;
245
+ tokens_read = sscanf(date, fmt_datetime, &year, &month, &day, &hour, &min, &sec, &hour_offset, &minute_offset);
246
+
247
+ if(!year && !month && !day && !hour && !min && !sec) {
248
+ return Qnil;
249
+ }
250
+
251
+ switch (tokens_read) {
252
+ case 8:
253
+ minute_offset *= hour_offset < 0 ? -1 : 1;
254
+ break;
255
+
256
+ case 7: /* Only got TZ hour offset, so assume 0 for minute */
257
+ minute_offset = 0;
258
+ break;
259
+
260
+ case 3: /* Only got Date */
261
+ hour = 0;
262
+ min = 0;
263
+ sec = 0;
264
+ /* Fall through */
265
+
266
+ case 6: /* Only got DateTime */
267
+ /*
268
+ * Interpret the DateTime from the local system TZ. If target date would
269
+ * end up in DST, assume adjustment of a 1 hour shift.
270
+ *
271
+ * FIXME: The DST adjustment calculation won't be accurate for timezones
272
+ * that observe fractional-hour shifts. But that's a real minority for
273
+ * now..
274
+ */
275
+ timeinfo.tm_year = year - 1900;
276
+ timeinfo.tm_mon = month - 1; // 0 - 11
277
+ timeinfo.tm_mday = day;
278
+ timeinfo.tm_hour = hour;
279
+ timeinfo.tm_min = min;
280
+ timeinfo.tm_sec = sec;
281
+ timeinfo.tm_isdst = -1;
282
+
283
+ target_time = mktime(&timeinfo);
284
+ dst_adjustment = timeinfo.tm_isdst ? 3600 : 0;
285
+
286
+ /*
287
+ * Now figure out seconds from UTC. For that we need a UTC/GMT-adjusted
288
+ * time_t, which we get from mktime(gmtime(current_time)).
289
+ *
290
+ * NOTE: Some modern libc's have tm_gmtoff in struct tm, but we can't count
291
+ * on that.
292
+ */
293
+ #ifdef HAVE_GMTIME_R
294
+ gmtime_r(&target_time, &timeinfo);
295
+ #else
296
+ timeinfo = *gmtime(&target_time);
297
+ #endif
298
+
299
+ gmt_offset = target_time - mktime(&timeinfo) + dst_adjustment;
300
+ hour_offset = ((int)gmt_offset / 3600);
301
+ minute_offset = ((int)gmt_offset % 3600 / 60);
302
+ break;
303
+
304
+ default: /* Any other combo of missing tokens and we can't do anything */
305
+ rb_raise(eDO_DataError, "Couldn't parse date: %s", date);
306
+ }
307
+
308
+ offset = data_objects_timezone_to_offset(hour_offset, minute_offset);
309
+ return rb_funcall(rb_cDateTime, DO_ID_NEW, 7, INT2NUM(year), INT2NUM(month), INT2NUM(day),
310
+ INT2NUM(hour), INT2NUM(min), INT2NUM(sec), offset);
311
+ }
312
+
313
+ VALUE data_objects_cConnection_character_set(VALUE self) {
314
+ return rb_iv_get(self, "@encoding");
315
+ }
316
+
317
+ VALUE data_objects_cConnection_is_using_socket(VALUE self) {
318
+ return rb_iv_get(self, "@using_socket");
319
+ }
320
+
321
+ VALUE data_objects_cConnection_ssl_cipher(VALUE self) {
322
+ return rb_iv_get(self, "@ssl_cipher");
323
+ }
324
+
325
+ VALUE data_objects_cConnection_quote_time(VALUE self, VALUE value) {
326
+ return rb_funcall(value, DO_ID_STRFTIME, 1, rb_str_new2("'%Y-%m-%d %H:%M:%S'"));
327
+ }
328
+
329
+ VALUE data_objects_cConnection_quote_date_time(VALUE self, VALUE value) {
330
+ // TODO: Support non-local dates. we need to call #new_offset on the date to be
331
+ // quoted and pass in the current locale's date offset (self.new_offset((hours * 3600).to_r / 86400)
332
+ return rb_funcall(value, DO_ID_STRFTIME, 1, rb_str_new2("'%Y-%m-%d %H:%M:%S'"));
333
+ }
334
+
335
+ VALUE data_objects_cConnection_quote_date(VALUE self, VALUE value) {
336
+ return rb_funcall(value, DO_ID_STRFTIME, 1, rb_str_new2("'%Y-%m-%d'"));
337
+ }
338
+
339
+ /*
340
+ * Accepts an array of Ruby types (Fixnum, Float, String, etc...) and turns them
341
+ * into Ruby-strings so we can easily typecast later
342
+ */
343
+ VALUE data_objects_cCommand_set_types(int argc, VALUE *argv, VALUE self) {
344
+ VALUE entry, sub_entry;
345
+ int i, j;
346
+ VALUE type_strings = rb_ary_new();
347
+ VALUE array = rb_ary_new();
348
+
349
+ for (i = 0; i < argc; i++) {
350
+ rb_ary_push(array, argv[i]);
351
+ }
352
+
353
+ for (i = 0; i < RARRAY_LEN(array); i++) {
354
+ entry = rb_ary_entry(array, i);
355
+
356
+ if (TYPE(entry) == T_CLASS) {
357
+ rb_ary_push(type_strings, entry);
358
+ }
359
+ else if (TYPE(entry) == T_ARRAY) {
360
+ for (j = 0; j < RARRAY_LEN(entry); j++) {
361
+ sub_entry = rb_ary_entry(entry, j);
362
+
363
+ if (TYPE(sub_entry) == T_CLASS) {
364
+ rb_ary_push(type_strings, sub_entry);
365
+ }
366
+ else {
367
+ rb_raise(rb_eArgError, "Invalid type given");
368
+ }
369
+ }
370
+ }
371
+ else {
372
+ rb_raise(rb_eArgError, "Invalid type given");
373
+ }
374
+ }
375
+
376
+ rb_iv_set(self, "@field_types", type_strings);
377
+ return array;
378
+ }
379
+
380
+ VALUE data_objects_cReader_values(VALUE self) {
381
+ VALUE state = rb_iv_get(self, "@opened");
382
+ VALUE values = rb_iv_get(self, "@values");
383
+
384
+ if (state == Qnil || state == Qfalse || values == Qnil) {
385
+ rb_raise(eDO_DataError, "Reader is not initialized");
386
+ }
387
+
388
+ return rb_iv_get(self, "@values");
389
+ }
390
+
391
+ VALUE data_objects_cReader_fields(VALUE self) {
392
+ return rb_iv_get(self, "@fields");
393
+ }
394
+
395
+ VALUE data_objects_cReader_field_count(VALUE self) {
396
+ return rb_iv_get(self, "@field_count");
397
+ }
398
+
399
+ void data_objects_common_init(void) {
400
+ rb_require("bigdecimal");
401
+ rb_require("rational");
402
+ rb_require("date");
403
+ rb_require("data_objects");
404
+
405
+ // Needed by data_objects_const_get
406
+ DO_ID_CONST_GET = rb_intern("const_get");
407
+
408
+ // Get references classes needed for Date/Time parsing
409
+ rb_cDate = data_objects_const_get(rb_mKernel, "Date");
410
+ rb_cDateTime = data_objects_const_get(rb_mKernel, "DateTime");
411
+ rb_cBigDecimal = data_objects_const_get(rb_mKernel, "BigDecimal");
412
+
413
+ DO_ID_NEW = rb_intern("new");
414
+ #ifdef RUBY_LESS_THAN_186
415
+ DO_ID_NEW_DATE = rb_intern("new0");
416
+ #else
417
+ DO_ID_NEW_DATE = rb_intern("new!");
418
+ #endif
419
+ DO_ID_CONST_GET = rb_intern("const_get");
420
+ DO_ID_RATIONAL = rb_intern("Rational");
421
+ DO_ID_ESCAPE = rb_intern("escape_sql");
422
+ DO_ID_STRFTIME = rb_intern("strftime");
423
+ DO_ID_LOG = rb_intern("log");
424
+
425
+ // Get references to the Extlib module
426
+ mExtlib = data_objects_const_get(rb_mKernel, "Extlib");
427
+ rb_cByteArray = data_objects_const_get(mExtlib, "ByteArray");
428
+
429
+ // Get references to the DataObjects module and its classes
430
+ mDO = data_objects_const_get(rb_mKernel, "DataObjects");
431
+ cDO_Quoting = data_objects_const_get(mDO, "Quoting");
432
+ cDO_Connection = data_objects_const_get(mDO, "Connection");
433
+ cDO_Command = data_objects_const_get(mDO, "Command");
434
+ cDO_Result = data_objects_const_get(mDO, "Result");
435
+ cDO_Reader = data_objects_const_get(mDO, "Reader");
436
+ cDO_Logger = data_objects_const_get(mDO, "Logger");
437
+ cDO_Logger_Message = data_objects_const_get(cDO_Logger, "Message");
438
+ cDO_Extension = data_objects_const_get(mDO, "Extension");
439
+
440
+ eDO_ConnectionError = data_objects_const_get(mDO, "ConnectionError");
441
+ eDO_DataError = data_objects_const_get(mDO, "DataError");
442
+
443
+ rb_global_variable(&DO_ID_NEW_DATE);
444
+ rb_global_variable(&DO_ID_RATIONAL);
445
+ rb_global_variable(&DO_ID_CONST_GET);
446
+ rb_global_variable(&DO_ID_ESCAPE);
447
+ rb_global_variable(&DO_ID_LOG);
448
+ rb_global_variable(&DO_ID_NEW);
449
+
450
+ rb_global_variable(&rb_cDate);
451
+ rb_global_variable(&rb_cDateTime);
452
+ rb_global_variable(&rb_cBigDecimal);
453
+ rb_global_variable(&rb_cByteArray);
454
+
455
+ rb_global_variable(&mDO);
456
+ rb_global_variable(&cDO_Logger_Message);
457
+
458
+ rb_global_variable(&eDO_ConnectionError);
459
+ rb_global_variable(&eDO_DataError);
460
+
461
+ tzset();
462
+ }
463
+
464
+ /*
465
+ * Common typecasting logic that can be used or overriden by Adapters.
466
+ */
467
+ extern VALUE data_objects_typecast(const char *value, long length, const VALUE type, int encoding) {
468
+ #ifdef HAVE_RUBY_ENCODING_H
469
+ rb_encoding *internal_encoding = rb_default_internal_encoding();
470
+ #else
471
+ void *internal_encoding = NULL;
472
+ #endif
473
+
474
+ if (type == rb_cInteger) {
475
+ return rb_cstr2inum(value, 10);
476
+ }
477
+ else if (type == rb_cString) {
478
+ return DATA_OBJECTS_STR_NEW(value, length, encoding, internal_encoding);
479
+ }
480
+ else if (type == rb_cFloat) {
481
+ return rb_float_new(rb_cstr_to_dbl(value, Qfalse));
482
+ }
483
+ else if (type == rb_cBigDecimal) {
484
+ return rb_funcall(rb_cObject, rb_intern("BigDecimal"), 1, rb_str_new(value, length));
485
+ }
486
+ else if (type == rb_cDate) {
487
+ return data_objects_parse_date(value);
488
+ }
489
+ else if (type == rb_cDateTime) {
490
+ return data_objects_parse_date_time(value);
491
+ }
492
+ else if (type == rb_cTime) {
493
+ return data_objects_parse_time(value);
494
+ }
495
+ else if (type == rb_cTrueClass) {
496
+ return (!value || strcmp("0", value) == 0) ? Qfalse : Qtrue;
497
+ }
498
+ else if (type == rb_cByteArray) {
499
+ return rb_funcall(rb_cByteArray, DO_ID_NEW, 1, rb_str_new(value, length));
500
+ }
501
+ else if (type == rb_cClass) {
502
+ return rb_funcall(mDO, rb_intern("full_const_get"), 1, rb_str_new(value, length));
503
+ }
504
+ else if (type == rb_cNilClass) {
505
+ return Qnil;
506
+ }
507
+ else {
508
+ return DATA_OBJECTS_STR_NEW(value, length, encoding, internal_encoding);
509
+ }
510
+ }
@@ -0,0 +1,132 @@
1
+ #ifndef _DO_COMMON_H_
2
+ #define _DO_COMMON_H_
3
+
4
+ #include <ruby.h>
5
+
6
+ // Needed for defining error.h
7
+ struct errcodes {
8
+ int error_no;
9
+ const char *error_name;
10
+ const char *exception;
11
+ };
12
+
13
+ #define ERRCODE(name,message) {name, #name, message}
14
+
15
+ #ifdef _WIN32
16
+ typedef signed __int64 do_int64;
17
+ #else
18
+ typedef signed long long int do_int64;
19
+ #endif
20
+
21
+ #ifdef HAVE_RUBY_ENCODING_H
22
+ #include <ruby/encoding.h>
23
+ #define DATA_OBJECTS_STR_NEW2(str, encoding, internal_encoding) \
24
+ ({ \
25
+ VALUE _string = rb_str_new2((const char *)str); \
26
+ if(encoding != -1) { \
27
+ rb_enc_associate_index(_string, encoding); \
28
+ } \
29
+ if(internal_encoding) { \
30
+ _string = rb_str_export_to_enc(_string, internal_encoding); \
31
+ } \
32
+ _string; \
33
+ })
34
+
35
+ #define DATA_OBJECTS_STR_NEW(str, len, encoding, internal_encoding) \
36
+ ({ \
37
+ VALUE _string = rb_str_new((const char *)str, (long)len); \
38
+ if(encoding != -1) { \
39
+ rb_enc_associate_index(_string, encoding); \
40
+ } \
41
+ if(internal_encoding) { \
42
+ _string = rb_str_export_to_enc(_string, internal_encoding); \
43
+ } \
44
+ _string; \
45
+ })
46
+
47
+ #else
48
+
49
+ #define DATA_OBJECTS_STR_NEW2(str, encoding, internal_encoding) \
50
+ rb_str_new2((const char *)str)
51
+
52
+ #define DATA_OBJECTS_STR_NEW(str, len, encoding, internal_encoding) \
53
+ rb_str_new((const char *)str, (long)len)
54
+ #endif
55
+
56
+ // To store rb_intern values
57
+ extern ID DO_ID_NEW;
58
+ extern ID DO_ID_NEW_DATE;
59
+ extern ID DO_ID_CONST_GET;
60
+ extern ID DO_ID_RATIONAL;
61
+ extern ID DO_ID_ESCAPE;
62
+ extern ID DO_ID_STRFTIME;
63
+ extern ID DO_ID_LOG;
64
+
65
+ // Reference to Extlib module
66
+ extern VALUE mExtlib;
67
+ extern VALUE rb_cByteArray;
68
+
69
+ // References to DataObjects base classes
70
+ extern VALUE mDO;
71
+ extern VALUE cDO_Quoting;
72
+ extern VALUE cDO_Connection;
73
+ extern VALUE cDO_Command;
74
+ extern VALUE cDO_Result;
75
+ extern VALUE cDO_Reader;
76
+ extern VALUE cDO_Logger;
77
+ extern VALUE cDO_Logger_Message;
78
+ extern VALUE cDO_Extension;
79
+ extern VALUE eDO_ConnectionError;
80
+ extern VALUE eDO_DataError;
81
+
82
+ // References to Ruby classes that we'll need
83
+ extern VALUE rb_cDate;
84
+ extern VALUE rb_cDateTime;
85
+ extern VALUE rb_cBigDecimal;
86
+
87
+ extern void data_objects_debug(VALUE connection, VALUE string, struct timeval *start);
88
+ extern char *data_objects_get_uri_option(VALUE query_hash, const char *key);
89
+ extern void data_objects_assert_file_exists(char *file, const char *message);
90
+ extern VALUE data_objects_build_query_from_args(VALUE klass, int count, VALUE *args);
91
+
92
+ extern void data_objects_reduce(do_int64 *numerator, do_int64 *denominator);
93
+ extern int data_objects_jd_from_date(int year, int month, int day);
94
+ extern VALUE data_objects_seconds_to_offset(long seconds_offset);
95
+ extern VALUE data_objects_timezone_to_offset(int hour_offset, int minute_offset);
96
+
97
+ extern VALUE data_objects_parse_date(const char *date);
98
+ extern VALUE data_objects_parse_time(const char *date);
99
+ extern VALUE data_objects_parse_date_time(const char *date);
100
+
101
+ extern VALUE data_objects_cConnection_character_set(VALUE self);
102
+ extern VALUE data_objects_cConnection_is_using_socket(VALUE self);
103
+ extern VALUE data_objects_cConnection_ssl_cipher(VALUE self);
104
+ extern VALUE data_objects_cConnection_quote_time(VALUE self, VALUE value);
105
+ extern VALUE data_objects_cConnection_quote_date_time(VALUE self, VALUE value);
106
+ extern VALUE data_objects_cConnection_quote_date(VALUE self, VALUE value);
107
+
108
+ extern VALUE data_objects_cCommand_set_types(int argc, VALUE *argv, VALUE self);
109
+
110
+ extern VALUE data_objects_cReader_values(VALUE self);
111
+ extern VALUE data_objects_cReader_fields(VALUE self);
112
+ extern VALUE data_objects_cReader_field_count(VALUE self);
113
+
114
+ extern void data_objects_common_init(void);
115
+
116
+ extern VALUE data_objects_const_get(VALUE scope, const char *constant);
117
+
118
+ static inline void data_objects_define_errors(VALUE scope, const struct errcodes *errors) {
119
+ const struct errcodes *e;
120
+
121
+ for (e = errors; e->error_name; e++) {
122
+ rb_const_set(scope, rb_intern(e->error_name), INT2NUM(e->error_no));
123
+ }
124
+ }
125
+
126
+ extern void data_objects_raise_error(VALUE self, const struct errcodes *errors, int errnum, VALUE message, VALUE query, VALUE state);
127
+
128
+ extern VALUE data_objects_typecast(const char *value, long length, const VALUE type, int encoding);
129
+
130
+ #define RSTRING_NOT_MODIFIED
131
+
132
+ #endif