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.
@@ -0,0 +1,170 @@
1
+ #ifndef _DO_COMMON_H_
2
+ #define _DO_COMMON_H_
3
+
4
+ #include <ruby.h>
5
+
6
+ #ifdef _WIN32
7
+ #define cCommand_execute cCommand_execute_sync
8
+ typedef signed __int64 do_int64;
9
+ #else
10
+ #define cCommand_execute cCommand_execute_async
11
+ typedef signed long long int do_int64;
12
+ #endif
13
+
14
+ #ifdef HAVE_RUBY_ENCODING_H
15
+ #include <ruby/encoding.h>
16
+
17
+ #define DO_STR_NEW2(str, encoding, internal_encoding) \
18
+ ({ \
19
+ VALUE _string = rb_str_new2((const char *)str); \
20
+ if(encoding != -1) { \
21
+ rb_enc_associate_index(_string, encoding); \
22
+ } \
23
+ if(internal_encoding) { \
24
+ _string = rb_str_export_to_enc(_string, internal_encoding); \
25
+ } \
26
+ _string; \
27
+ })
28
+
29
+ #define DO_STR_NEW(str, len, encoding, internal_encoding) \
30
+ ({ \
31
+ VALUE _string = rb_str_new((const char *)str, (long)len); \
32
+ if(encoding != -1) { \
33
+ rb_enc_associate_index(_string, encoding); \
34
+ } \
35
+ if(internal_encoding) { \
36
+ _string = rb_str_export_to_enc(_string, internal_encoding); \
37
+ } \
38
+ _string; \
39
+ })
40
+
41
+ # else
42
+
43
+ #define DO_STR_NEW2(str, encoding, internal_encoding) \
44
+ rb_str_new2((const char *)str)
45
+
46
+ #define DO_STR_NEW(str, len, encoding, internal_encoding) \
47
+ rb_str_new((const char *)str, (long)len)
48
+ #endif
49
+
50
+ // Needed for defining error.h
51
+ struct errcodes {
52
+ int error_no;
53
+ const char *error_name;
54
+ const char *exception;
55
+ };
56
+
57
+ #define ERRCODE(name,message) {name, #name, message}
58
+
59
+ // To store rb_intern values
60
+ extern ID ID_NEW;
61
+ extern ID ID_NEW_DATE;
62
+ extern ID ID_CONST_GET;
63
+ extern ID ID_RATIONAL;
64
+ extern ID ID_ESCAPE;
65
+ extern ID ID_STRFTIME;
66
+ extern ID ID_LOG;
67
+
68
+ // Reference to Extlib module
69
+ extern VALUE mExtlib;
70
+ extern VALUE rb_cByteArray;
71
+
72
+ // References to DataObjects base classes
73
+ extern VALUE mDO;
74
+ extern VALUE mEncoding;
75
+ extern VALUE cDO_Quoting;
76
+ extern VALUE cDO_Connection;
77
+ extern VALUE cDO_Command;
78
+ extern VALUE cDO_Result;
79
+ extern VALUE cDO_Reader;
80
+ extern VALUE cDO_Logger;
81
+ extern VALUE cDO_Logger_Message;
82
+ extern VALUE cDO_Extension;
83
+ extern VALUE eConnectionError;
84
+ extern VALUE eDataError;
85
+
86
+ // References to Ruby classes that we'll need
87
+ extern VALUE rb_cDate;
88
+ extern VALUE rb_cDateTime;
89
+ extern VALUE rb_cBigDecimal;
90
+
91
+ extern void data_objects_debug(VALUE connection, VALUE string, struct timeval *start);
92
+ extern char *get_uri_option(VALUE query_hash, const char *key);
93
+ extern void assert_file_exists(char *file, const char *message);
94
+ extern VALUE build_query_from_args(VALUE klass, int count, VALUE *args);
95
+
96
+ extern void reduce(do_int64 *numerator, do_int64 *denominator);
97
+ extern int jd_from_date(int year, int month, int day);
98
+ extern VALUE seconds_to_offset(long seconds_offset);
99
+ extern VALUE timezone_to_offset(int hour_offset, int minute_offset);
100
+
101
+ extern VALUE parse_date(const char *date);
102
+ extern VALUE parse_time(const char *date);
103
+ extern VALUE parse_date_time(const char *date);
104
+
105
+ extern VALUE cConnection_character_set(VALUE self);
106
+ extern VALUE cConnection_is_using_socket(VALUE self);
107
+ extern VALUE cConnection_ssl_cipher(VALUE self);
108
+ extern VALUE cConnection_quote_time(VALUE self, VALUE value);
109
+ extern VALUE cConnection_quote_date_time(VALUE self, VALUE value);
110
+ extern VALUE cConnection_quote_date(VALUE self, VALUE value);
111
+
112
+ extern VALUE cCommand_set_types(int argc, VALUE *argv, VALUE self);
113
+
114
+ extern VALUE cReader_values(VALUE self);
115
+ extern VALUE cReader_fields(VALUE self);
116
+ extern VALUE cReader_field_count(VALUE self);
117
+
118
+ extern void common_init(void);
119
+
120
+ static inline VALUE do_const_get(VALUE scope, const char *constant) {
121
+ return rb_funcall(scope, ID_CONST_GET, 1, rb_str_new2(constant));
122
+ }
123
+
124
+ static inline VALUE do_str_new(const void *string, long length, int encoding, void *internal_encoding) {
125
+ VALUE new_string = rb_str_new(string, length);
126
+
127
+ #ifdef HAVE_RUBY_ENCODING_H
128
+ if(encoding != -1) {
129
+ rb_enc_associate_index(new_string, encoding);
130
+ }
131
+
132
+ if(internal_encoding) {
133
+ new_string = rb_str_export_to_enc(new_string, internal_encoding);
134
+ }
135
+ #endif
136
+
137
+ return new_string;
138
+ }
139
+
140
+ static inline VALUE do_str_new2(const void *string, int encoding, void *internal_encoding) {
141
+ VALUE new_string = rb_str_new2(string);
142
+
143
+ #ifdef HAVE_RUBY_ENCODING_H
144
+ if(encoding != -1) {
145
+ rb_enc_associate_index(new_string, encoding);
146
+ }
147
+
148
+ if(internal_encoding) {
149
+ new_string = rb_str_export_to_enc(new_string, internal_encoding);
150
+ }
151
+ #endif
152
+
153
+ return new_string;
154
+ }
155
+
156
+ static inline void do_define_errors(VALUE scope, const struct errcodes *errors) {
157
+ const struct errcodes *e;
158
+
159
+ for (e = errors; e->error_name; e++) {
160
+ rb_const_set(scope, rb_intern(e->error_name), INT2NUM(e->error_no));
161
+ }
162
+ }
163
+
164
+ extern void do_raise_error(VALUE self, const struct errcodes *errors, int errnum, const char *message, VALUE query, VALUE state);
165
+
166
+ extern VALUE do_typecast(const char *value, long length, const VALUE type, int encoding);
167
+
168
+ #define RSTRING_NOT_MODIFIED
169
+
170
+ #endif
@@ -1,343 +1,96 @@
1
1
  #include "do_sqlite3.h"
2
2
  #include "error.h"
3
- // To store rb_intern values
4
-
5
- static ID ID_NEW;
6
- static ID ID_NEW_DATE;
7
- static ID ID_CONST_GET;
8
- static ID ID_RATIONAL;
9
- static ID ID_ESCAPE;
10
- static ID ID_LOG;
11
-
12
- static VALUE mExtlib;
13
-
14
- static VALUE mDO;
15
- static VALUE cDO_Quoting;
16
- static VALUE cDO_Connection;
17
- static VALUE cDO_Command;
18
- static VALUE cDO_Result;
19
- static VALUE cDO_Reader;
20
- static VALUE cDO_Logger;
21
- static VALUE cDO_Logger_Message;
22
-
23
- static VALUE rb_cDate;
24
- static VALUE rb_cDateTime;
25
- static VALUE rb_cBigDecimal;
26
- static VALUE rb_cByteArray;
27
-
28
- static VALUE mSqlite3;
29
- static VALUE cConnection;
30
- static VALUE cCommand;
31
- static VALUE cResult;
32
- static VALUE cReader;
33
- static VALUE eConnectionError;
34
- static VALUE eDataError;
35
-
36
- static VALUE OPEN_FLAG_READONLY;
37
- static VALUE OPEN_FLAG_READWRITE;
38
- static VALUE OPEN_FLAG_CREATE;
39
- static VALUE OPEN_FLAG_NO_MUTEX;
40
- static VALUE OPEN_FLAG_FULL_MUTEX;
41
-
42
- // Find the greatest common denominator and reduce the provided numerator and denominator.
43
- // This replaces calles to Rational.reduce! which does the same thing, but really slowly.
44
- static void reduce( do_int64 *numerator, do_int64 *denominator ) {
45
- do_int64 a, b, c = 0;
46
- a = *numerator;
47
- b = *denominator;
48
- while ( a != 0 ) {
49
- c = a; a = b % a; b = c;
50
- }
51
- *numerator = *numerator / b;
52
- *denominator = *denominator / b;
53
- }
54
-
55
- // Generate the date integer which Date.civil_to_jd returns
56
- static int jd_from_date(int year, int month, int day) {
57
- int a, b;
58
- if ( month <= 2 ) {
59
- year -= 1;
60
- month += 12;
61
- }
62
- a = year / 100;
63
- b = 2 - a + (a / 4);
64
- return (int) (floor(365.25 * (year + 4716)) + floor(30.6001 * (month + 1)) + day + b - 1524);
65
- }
66
-
67
- static void data_objects_debug(VALUE connection, VALUE string, struct timeval* start) {
68
- struct timeval stop;
69
- VALUE message;
70
3
 
71
- gettimeofday(&stop, NULL);
72
- do_int64 duration = (stop.tv_sec - start->tv_sec) * 1000000 + stop.tv_usec - start->tv_usec;
4
+ #include "do_common.h"
73
5
 
74
- message = rb_funcall(cDO_Logger_Message, ID_NEW, 3, string, rb_time_new(start->tv_sec, start->tv_usec), INT2NUM(duration));
6
+ VALUE mSqlite3;
7
+ VALUE cConnection;
8
+ VALUE cCommand;
9
+ VALUE cResult;
10
+ VALUE cReader;
75
11
 
76
- rb_funcall(connection, ID_LOG, 1, message);
77
- }
12
+ VALUE OPEN_FLAG_READONLY;
13
+ VALUE OPEN_FLAG_READWRITE;
14
+ VALUE OPEN_FLAG_CREATE;
15
+ VALUE OPEN_FLAG_NO_MUTEX;
16
+ VALUE OPEN_FLAG_FULL_MUTEX;
78
17
 
79
- static void raise_error(VALUE self, sqlite3 *result, VALUE query) {
80
- VALUE exception;
18
+ void raise_error(VALUE self, sqlite3 *result, VALUE query) {
19
+ int errnum = sqlite3_errcode(result);
81
20
  const char *message = sqlite3_errmsg(result);
82
- const char *exception_type = "SQLError";
83
- int sqlite3_errno = sqlite3_errcode(result);
84
-
85
- struct errcodes *errs;
86
-
87
- for (errs = errors; errs->error_name; errs++) {
88
- if(errs->error_no == sqlite3_errno) {
89
- exception_type = errs->exception;
90
- break;
91
- }
92
- }
93
-
94
-
95
- VALUE uri = rb_funcall(rb_iv_get(self, "@connection"), rb_intern("to_s"), 0);
96
-
97
- exception = rb_funcall(CONST_GET(mDO, exception_type), ID_NEW, 5,
98
- rb_str_new2(message),
99
- INT2NUM(sqlite3_errno),
100
- rb_str_new2(""),
101
- query,
102
- uri);
103
- rb_exc_raise(exception);
104
- }
105
-
106
- static VALUE parse_date(char *date) {
107
- int year, month, day;
108
- int jd, ajd;
109
- VALUE rational;
110
-
111
- sscanf(date, "%4d-%2d-%2d", &year, &month, &day);
112
-
113
- jd = jd_from_date(year, month, day);
114
-
115
- // Math from Date.jd_to_ajd
116
- ajd = jd * 2 - 1;
117
- rational = rb_funcall(rb_mKernel, ID_RATIONAL, 2, INT2NUM(ajd), INT2NUM(2));
118
- return rb_funcall(rb_cDate, ID_NEW_DATE, 3, rational, INT2NUM(0), INT2NUM(2299161));
119
- }
120
-
121
- // Creates a Rational for use as a Timezone offset to be passed to DateTime.new!
122
- static VALUE seconds_to_offset(do_int64 num) {
123
- do_int64 den = 86400;
124
- reduce(&num, &den);
125
- return rb_funcall(rb_mKernel, ID_RATIONAL, 2, rb_ll2inum(num), rb_ll2inum(den));
126
- }
127
-
128
- static VALUE timezone_to_offset(int hour_offset, int minute_offset) {
129
- do_int64 seconds = 0;
130
-
131
- seconds += hour_offset * 3600;
132
- seconds += minute_offset * 60;
21
+ VALUE sql_state = rb_str_new2("");
133
22
 
134
- return seconds_to_offset(seconds);
23
+ do_raise_error(self, errors, errnum, message, query, sql_state);
135
24
  }
136
25
 
137
- static VALUE parse_date_time(char *date) {
138
- VALUE ajd, offset;
139
-
140
- int year, month, day, hour, min, sec, usec, hour_offset, minute_offset;
141
- int jd;
142
- do_int64 num, den;
143
-
144
- long int gmt_offset;
145
- int dst_adjustment;
146
-
147
- time_t rawtime;
148
- struct tm timeinfo;
149
-
150
- int tokens_read, max_tokens;
26
+ VALUE typecast(sqlite3_stmt *stmt, int i, VALUE type, int encoding) {
27
+ int original_type = sqlite3_column_type(stmt, i);
28
+ int length = sqlite3_column_bytes(stmt, i);
151
29
 
152
- if ( strcmp(date, "") == 0 ) {
30
+ if (original_type == SQLITE_NULL) {
153
31
  return Qnil;
154
32
  }
155
33
 
156
- if (0 != strchr(date, '.')) {
157
- // This is a datetime with sub-second precision
158
- tokens_read = sscanf(date, "%4d-%2d-%2d%*c%2d:%2d:%2d.%d%3d:%2d", &year, &month, &day, &hour, &min, &sec, &usec, &hour_offset, &minute_offset);
159
- max_tokens = 9;
160
- } else {
161
- // This is a datetime second precision
162
- tokens_read = sscanf(date, "%4d-%2d-%2d%*c%2d:%2d:%2d%3d:%2d", &year, &month, &day, &hour, &min, &sec, &hour_offset, &minute_offset);
163
- max_tokens = 8;
164
- }
165
-
166
- if (max_tokens == tokens_read) {
167
- // We read the Date, Time, and Timezone info
168
- minute_offset *= hour_offset < 0 ? -1 : 1;
169
- } else if ((max_tokens - 1) == tokens_read) {
170
- // We read the Date and Time, but no Minute Offset
171
- minute_offset = 0;
172
- } else if (tokens_read == 3 || tokens_read >= (max_tokens - 3)) {
173
- if (tokens_read == 3) {
174
- hour = 0;
175
- min = 0;
176
- hour_offset = 0;
177
- minute_offset = 0;
178
- sec = 0;
179
- }
180
- // We read the Date and Time, default to the current locale's offset
181
-
182
- tzset();
183
-
184
- // Get localtime
185
- time(&rawtime);
186
- #ifdef HAVE_LOCALTIME_R
187
- localtime_r(&rawtime, &timeinfo);
188
- #else
189
- timeinfo = *localtime(&rawtime);
190
- #endif
191
-
192
- timeinfo.tm_sec = sec;
193
- timeinfo.tm_min = min;
194
- timeinfo.tm_hour = hour;
195
- timeinfo.tm_mday = day;
196
- timeinfo.tm_mon = month;
197
- timeinfo.tm_year = year - 1900;
198
- timeinfo.tm_isdst = -1;
199
-
200
- // Update tm_isdst
201
- mktime(&timeinfo);
202
-
203
- if (timeinfo.tm_isdst) {
204
- dst_adjustment = 3600;
205
- } else {
206
- dst_adjustment = 0;
207
- }
208
-
209
- // Reset to GM Time
210
- #ifdef HAVE_GMTIME_R
211
- gmtime_r(&rawtime, &timeinfo);
212
- #else
213
- timeinfo = *gmtime(&rawtime);
214
- #endif
215
-
216
- gmt_offset = rawtime - mktime(&timeinfo);
217
-
218
- if (dst_adjustment) {
219
- gmt_offset += dst_adjustment;
220
- }
221
-
222
- hour_offset = ((int)gmt_offset / 3600);
223
- minute_offset = ((int)gmt_offset % 3600 / 60);
224
-
225
- } else {
226
- // Something went terribly wrong
227
- rb_raise(eDataError, "Couldn't parse date: %s", date);
228
- }
229
-
230
- jd = jd_from_date(year, month, day);
231
-
232
- // Generate ajd with fractional days for the time
233
- // Extracted from Date#jd_to_ajd, Date#day_fraction_to_time, and Rational#+ and #-
234
- num = (hour * 1440) + (min * 24);
235
-
236
- // Modify the numerator so when we apply the timezone everything works out
237
- num -= (hour_offset * 1440) + (minute_offset * 24);
238
-
239
- den = (24 * 1440);
240
- reduce(&num, &den);
241
-
242
- num = (num * 86400) + (sec * den);
243
- den = den * 86400;
244
- reduce(&num, &den);
245
-
246
- num = (jd * den) + num;
247
-
248
- num = num * 2;
249
- num = num - den;
250
- den = den * 2;
251
-
252
- reduce(&num, &den);
253
-
254
- ajd = rb_funcall(rb_mKernel, ID_RATIONAL, 2, rb_ull2inum(num), rb_ull2inum(den));
255
- offset = timezone_to_offset(hour_offset, minute_offset);
256
-
257
- return rb_funcall(rb_cDateTime, ID_NEW_DATE, 3, ajd, offset, INT2NUM(2299161));
258
- }
259
-
260
- static VALUE parse_time(char *date) {
261
-
262
- int year, month, day, hour, min, sec, usec, tokens, hour_offset, minute_offset;
263
-
264
- if (0 != strchr(date, '.')) {
265
- // This is a datetime with sub-second precision
266
- tokens = sscanf(date, "%4d-%2d-%2d%*c%2d:%2d:%2d.%d%3d:%2d", &year, &month, &day, &hour, &min, &sec, &usec, &hour_offset, &minute_offset);
267
- } else {
268
- // This is a datetime second precision
269
- tokens = sscanf(date, "%4d-%2d-%2d%*c%2d:%2d:%2d%3d:%2d", &year, &month, &day, &hour, &min, &sec, &hour_offset, &minute_offset);
270
- usec = 0;
271
- if(tokens == 3) {
272
- hour = 0;
273
- min = 0;
274
- sec = 0;
275
- hour_offset = 0;
276
- minute_offset = 0;
277
- }
278
- }
279
-
280
- return rb_funcall(rb_cTime, rb_intern("local"), 7, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec), INT2NUM(usec));
281
- }
282
-
283
- static VALUE typecast(sqlite3_stmt *stmt, int i, VALUE type, int encoding) {
284
- VALUE ruby_value = Qnil;
285
- int original_type = sqlite3_column_type(stmt, i);
286
- int length = sqlite3_column_bytes(stmt, i);
287
- if ( original_type == SQLITE_NULL ) {
288
- return ruby_value;
289
- }
290
-
291
34
  #ifdef HAVE_RUBY_ENCODING_H
292
- rb_encoding * internal_encoding = rb_default_internal_encoding();
35
+ rb_encoding *internal_encoding = rb_default_internal_encoding();
293
36
  #else
294
- void * internal_encoding = NULL;
37
+ void *internal_encoding = NULL;
295
38
  #endif
296
39
 
297
- if(type == Qnil) {
298
- switch(original_type) {
299
- case SQLITE_INTEGER: {
40
+ if (type == Qnil) {
41
+ switch (original_type) {
42
+ case SQLITE_INTEGER:
300
43
  type = rb_cInteger;
301
44
  break;
302
- }
303
- case SQLITE_FLOAT: {
45
+
46
+ case SQLITE_FLOAT:
304
47
  type = rb_cFloat;
305
48
  break;
306
- }
307
- case SQLITE_BLOB: {
49
+
50
+ case SQLITE_BLOB:
308
51
  type = rb_cByteArray;
309
52
  break;
310
- }
311
- default: {
53
+
54
+ default:
312
55
  type = rb_cString;
313
56
  break;
314
- }
315
57
  }
316
58
  }
317
59
 
318
60
  if (type == rb_cInteger) {
319
61
  return LL2NUM(sqlite3_column_int64(stmt, i));
320
- } else if (type == rb_cString) {
62
+ }
63
+ else if (type == rb_cString) {
321
64
  return DO_STR_NEW((char*)sqlite3_column_text(stmt, i), length, encoding, internal_encoding);
322
- } else if (type == rb_cFloat) {
65
+ }
66
+ else if (type == rb_cFloat) {
323
67
  return rb_float_new(sqlite3_column_double(stmt, i));
324
- } else if (type == rb_cBigDecimal) {
68
+ }
69
+ else if (type == rb_cBigDecimal) {
325
70
  return rb_funcall(rb_cBigDecimal, ID_NEW, 1, rb_str_new((char*)sqlite3_column_text(stmt, i), length));
326
- } else if (type == rb_cDate) {
71
+ }
72
+ else if (type == rb_cDate) {
327
73
  return parse_date((char*)sqlite3_column_text(stmt, i));
328
- } else if (type == rb_cDateTime) {
74
+ }
75
+ else if (type == rb_cDateTime) {
329
76
  return parse_date_time((char*)sqlite3_column_text(stmt, i));
330
- } else if (type == rb_cTime) {
77
+ }
78
+ else if (type == rb_cTime) {
331
79
  return parse_time((char*)sqlite3_column_text(stmt, i));
332
- } else if (type == rb_cTrueClass) {
80
+ }
81
+ else if (type == rb_cTrueClass) {
333
82
  return strcmp((char*)sqlite3_column_text(stmt, i), "t") == 0 ? Qtrue : Qfalse;
334
- } else if (type == rb_cByteArray) {
83
+ }
84
+ else if (type == rb_cByteArray) {
335
85
  return rb_funcall(rb_cByteArray, ID_NEW, 1, rb_str_new((char*)sqlite3_column_blob(stmt, i), length));
336
- } else if (type == rb_cClass) {
86
+ }
87
+ else if (type == rb_cClass) {
337
88
  return rb_funcall(mDO, rb_intern("full_const_get"), 1, rb_str_new((char*)sqlite3_column_text(stmt, i), length));
338
- } else if (type == rb_cNilClass) {
89
+ }
90
+ else if (type == rb_cNilClass) {
339
91
  return Qnil;
340
- } else {
92
+ }
93
+ else {
341
94
  return DO_STR_NEW((char*)sqlite3_column_text(stmt, i), length, encoding, internal_encoding);
342
95
  }
343
96
  }
@@ -346,9 +99,8 @@ static VALUE typecast(sqlite3_stmt *stmt, int i, VALUE type, int encoding) {
346
99
 
347
100
  #define FLAG_PRESENT(query_values, flag) !NIL_P(rb_hash_aref(query_values, flag))
348
101
 
349
- static int flags_from_uri(VALUE uri) {
102
+ int flags_from_uri(VALUE uri) {
350
103
  VALUE query_values = rb_funcall(uri, rb_intern("query"), 0);
351
-
352
104
  int flags = 0;
353
105
 
354
106
  if (!NIL_P(query_values) && TYPE(query_values) == T_HASH) {
@@ -356,22 +108,27 @@ static int flags_from_uri(VALUE uri) {
356
108
  #ifdef SQLITE_OPEN_READONLY
357
109
  if (FLAG_PRESENT(query_values, OPEN_FLAG_READONLY)) {
358
110
  flags |= SQLITE_OPEN_READONLY;
359
- } else {
111
+ }
112
+ else {
360
113
  flags |= SQLITE_OPEN_READWRITE;
361
114
  }
362
115
  #endif
116
+
363
117
  #ifdef SQLITE_OPEN_NOMUTEX
364
118
  if (FLAG_PRESENT(query_values, OPEN_FLAG_NO_MUTEX)) {
365
119
  flags |= SQLITE_OPEN_NOMUTEX;
366
120
  }
367
121
  #endif
122
+
368
123
  #ifdef SQLITE_OPEN_FULLMUTEX
369
124
  if (FLAG_PRESENT(query_values, OPEN_FLAG_FULL_MUTEX)) {
370
125
  flags |= SQLITE_OPEN_FULLMUTEX;
371
126
  }
372
127
  #endif
128
+
373
129
  flags |= SQLITE_OPEN_CREATE;
374
- } else {
130
+ }
131
+ else {
375
132
  flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
376
133
  }
377
134
 
@@ -382,12 +139,10 @@ static int flags_from_uri(VALUE uri) {
382
139
 
383
140
  /****** Public API ******/
384
141
 
385
- static VALUE cConnection_initialize(VALUE self, VALUE uri) {
142
+ VALUE cConnection_initialize(VALUE self, VALUE uri) {
143
+ VALUE path = rb_funcall(uri, rb_intern("path"), 0);
144
+ sqlite3 *db = NULL;
386
145
  int ret;
387
- VALUE path;
388
- sqlite3 *db;
389
-
390
- path = rb_funcall(uri, rb_intern("path"), 0);
391
146
 
392
147
  #ifdef HAVE_SQLITE3_OPEN_V2
393
148
  ret = sqlite3_open_v2(StringValuePtr(path), &db, flags_from_uri(uri), 0);
@@ -395,7 +150,7 @@ static VALUE cConnection_initialize(VALUE self, VALUE uri) {
395
150
  ret = sqlite3_open(StringValuePtr(path), &db);
396
151
  #endif
397
152
 
398
- if ( ret != SQLITE_OK ) {
153
+ if (ret != SQLITE_OK) {
399
154
  raise_error(self, db, Qnil);
400
155
  }
401
156
 
@@ -410,72 +165,40 @@ static VALUE cConnection_initialize(VALUE self, VALUE uri) {
410
165
  return Qtrue;
411
166
  }
412
167
 
413
- static VALUE cConnection_dispose(VALUE self) {
168
+ VALUE cConnection_dispose(VALUE self) {
414
169
  VALUE connection_container = rb_iv_get(self, "@connection");
415
170
 
416
- sqlite3 *db;
417
-
418
- if (Qnil == connection_container)
171
+ if (connection_container == Qnil) {
419
172
  return Qfalse;
173
+ }
420
174
 
421
- db = DATA_PTR(connection_container);
175
+ sqlite3 *db = DATA_PTR(connection_container);
422
176
 
423
- if (NULL == db)
177
+ if (!db) {
424
178
  return Qfalse;
179
+ }
425
180
 
426
181
  sqlite3_close(db);
427
182
  rb_iv_set(self, "@connection", Qnil);
428
-
429
183
  return Qtrue;
430
-
431
- }
432
-
433
- static VALUE cCommand_set_types(int argc, VALUE *argv, VALUE self) {
434
- VALUE type_strings = rb_ary_new();
435
- VALUE array = rb_ary_new();
436
-
437
- int i, j;
438
-
439
- for ( i = 0; i < argc; i++) {
440
- rb_ary_push(array, argv[i]);
441
- }
442
-
443
- for (i = 0; i < RARRAY_LEN(array); i++) {
444
- VALUE entry = rb_ary_entry(array, i);
445
- if(TYPE(entry) == T_CLASS) {
446
- rb_ary_push(type_strings, entry);
447
- } else if (TYPE(entry) == T_ARRAY) {
448
- for (j = 0; j < RARRAY_LEN(entry); j++) {
449
- VALUE sub_entry = rb_ary_entry(entry, j);
450
- if(TYPE(sub_entry) == T_CLASS) {
451
- rb_ary_push(type_strings, sub_entry);
452
- } else {
453
- rb_raise(rb_eArgError, "Invalid type given");
454
- }
455
- }
456
- } else {
457
- rb_raise(rb_eArgError, "Invalid type given");
458
- }
459
- }
460
-
461
- rb_iv_set(self, "@field_types", type_strings);
462
-
463
- return array;
464
184
  }
465
185
 
466
- static VALUE cConnection_quote_boolean(VALUE self, VALUE value) {
186
+ VALUE cConnection_quote_boolean(VALUE self, VALUE value) {
467
187
  return rb_str_new2(value == Qtrue ? "'t'" : "'f'");
468
188
  }
469
189
 
470
- static VALUE cConnection_quote_string(VALUE self, VALUE string) {
190
+ VALUE cConnection_quote_string(VALUE self, VALUE string) {
471
191
  const char *source = rb_str_ptr_readonly(string);
472
- char *escaped_with_quotes;
473
- VALUE result;
474
192
 
475
193
  // Wrap the escaped string in single-quotes, this is DO's convention
476
- escaped_with_quotes = sqlite3_mprintf("%Q", source);
194
+ char *escaped_with_quotes = sqlite3_mprintf("%Q", source);
195
+
196
+ if(!escaped_with_quotes) {
197
+ rb_memerror();
198
+ }
199
+
200
+ VALUE result = rb_str_new2(escaped_with_quotes);
477
201
 
478
- result = rb_str_new2(escaped_with_quotes);
479
202
  #ifdef HAVE_RUBY_ENCODING_H
480
203
  rb_enc_associate_index(result, FIX2INT(rb_iv_get(self, "@encoding_id")));
481
204
  #endif
@@ -483,209 +206,176 @@ static VALUE cConnection_quote_string(VALUE self, VALUE string) {
483
206
  return result;
484
207
  }
485
208
 
486
- static VALUE cConnection_quote_byte_array(VALUE self, VALUE string) {
209
+ VALUE cConnection_quote_byte_array(VALUE self, VALUE string) {
487
210
  VALUE source = StringValue(string);
488
211
  VALUE array = rb_funcall(source, rb_intern("unpack"), 1, rb_str_new2("H*"));
212
+
489
213
  rb_ary_unshift(array, rb_str_new2("X'"));
490
214
  rb_ary_push(array, rb_str_new2("'"));
491
215
  return rb_ary_join(array, Qnil);
492
216
  }
493
217
 
494
- static VALUE cConnection_character_set(VALUE self) {
495
- return rb_iv_get(self, "@encoding");
496
- }
497
-
498
- static VALUE cConnection_enable_load_extension(VALUE self, VALUE value) {
499
- VALUE connection;
500
- int status;
501
- sqlite3 *db;
218
+ VALUE cConnection_enable_load_extension(VALUE self, VALUE value) {
219
+ VALUE connection = rb_iv_get(self, "@connection");
502
220
 
503
- connection = rb_iv_get(self, "@connection");
504
-
505
- if (Qnil == connection)
221
+ if (connection == Qnil) {
506
222
  return Qfalse;
223
+ }
507
224
 
508
- db = DATA_PTR(connection);
225
+ sqlite3 *db = DATA_PTR(connection);
509
226
 
510
- if (NULL == db)
227
+ if (!db) {
511
228
  return Qfalse;
229
+ }
512
230
 
513
- status = sqlite3_enable_load_extension(db, value == Qtrue ? 1 : 0);
514
- if ( status != SQLITE_OK ) {
231
+ int status = sqlite3_enable_load_extension(db, value == Qtrue ? 1 : 0);
232
+
233
+ if (status != SQLITE_OK) {
515
234
  rb_raise(eConnectionError, "Error enabling load extension.");
516
235
  }
517
236
  return Qtrue;
518
237
  }
519
238
 
520
- static VALUE cConnection_load_extension(VALUE self, VALUE string) {
521
- VALUE connection;
522
- sqlite3 *db;
523
- const char *extension_name = rb_str_ptr_readonly(string);
524
- char* errmsg;
525
- int status;
239
+ VALUE cConnection_load_extension(VALUE self, VALUE string) {
240
+ VALUE connection = rb_iv_get(self, "@connection");
526
241
 
527
- connection = rb_iv_get(self, "@connection");
528
-
529
- if (Qnil == connection)
242
+ if (connection == Qnil) {
530
243
  return Qfalse;
244
+ }
531
245
 
532
- db = DATA_PTR(connection);
246
+ sqlite3 *db = DATA_PTR(connection);
533
247
 
534
- if (NULL == db)
248
+ if (!db) {
535
249
  return Qfalse;
250
+ }
251
+
252
+ const char *extension_name = rb_str_ptr_readonly(string);
253
+ char *errmsg = NULL;
254
+ int status = sqlite3_load_extension(db, extension_name, 0, &errmsg);
536
255
 
537
- status = sqlite3_load_extension(db, extension_name, 0, &errmsg);
538
- if ( status != SQLITE_OK ) {
256
+ if (status != SQLITE_OK) {
539
257
  rb_raise(eConnectionError, "%s", errmsg);
540
258
  }
541
259
  return Qtrue;
542
260
  }
543
261
 
544
- static VALUE build_query_from_args(VALUE klass, int count, VALUE *args) {
545
- VALUE query = rb_iv_get(klass, "@text");
546
- int i;
547
- VALUE array = rb_ary_new();
548
- for ( i = 0; i < count; i++) {
549
- rb_ary_push(array, (VALUE)args[i]);
550
- }
551
- query = rb_funcall(klass, ID_ESCAPE, 1, array);
552
- return query;
553
- }
554
-
555
- static VALUE cCommand_execute_non_query(int argc, VALUE *argv, VALUE self) {
556
- sqlite3 *db;
557
- char *error_message;
558
- int status;
559
- int affected_rows;
560
- do_int64 insert_id;
561
- VALUE connection, sqlite3_connection;
562
- VALUE query;
563
- struct timeval start;
564
-
565
- query = build_query_from_args(self, argc, argv);
262
+ VALUE cCommand_execute_non_query(int argc, VALUE *argv, VALUE self) {
263
+ VALUE query = build_query_from_args(self, argc, argv);
264
+ VALUE connection = rb_iv_get(self, "@connection");
265
+ VALUE sqlite3_connection = rb_iv_get(connection, "@connection");
566
266
 
567
- connection = rb_iv_get(self, "@connection");
568
- sqlite3_connection = rb_iv_get(connection, "@connection");
569
- if (Qnil == sqlite3_connection) {
267
+ if (sqlite3_connection == Qnil) {
570
268
  rb_raise(eConnectionError, "This connection has already been closed.");
571
269
  }
572
270
 
271
+ sqlite3 *db = NULL;
272
+
573
273
  Data_Get_Struct(sqlite3_connection, sqlite3, db);
574
274
 
275
+ struct timeval start;
276
+ char *error_message;
277
+ int status;
278
+
575
279
  gettimeofday(&start, NULL);
576
280
  status = sqlite3_exec(db, rb_str_ptr_readonly(query), 0, 0, &error_message);
577
281
 
578
- if ( status != SQLITE_OK ) {
282
+ if (status != SQLITE_OK) {
579
283
  raise_error(self, db, query);
580
284
  }
285
+
581
286
  data_objects_debug(connection, query, &start);
582
287
 
583
- affected_rows = sqlite3_changes(db);
584
- insert_id = sqlite3_last_insert_rowid(db);
288
+ int affected_rows = sqlite3_changes(db);
289
+ do_int64 insert_id = sqlite3_last_insert_rowid(db);
585
290
 
586
291
  return rb_funcall(cResult, ID_NEW, 3, self, INT2NUM(affected_rows), INT2NUM(insert_id));
587
292
  }
588
293
 
589
- static VALUE cCommand_execute_reader(int argc, VALUE *argv, VALUE self) {
590
- sqlite3 *db;
591
- sqlite3_stmt *sqlite3_reader;
592
- int status;
593
- int field_count;
594
- int i;
595
- VALUE reader;
596
- VALUE connection, sqlite3_connection;
597
- VALUE query;
598
- VALUE field_names, field_types;
599
- struct timeval start;
294
+ VALUE cCommand_execute_reader(int argc, VALUE *argv, VALUE self) {
295
+ VALUE query = build_query_from_args(self, argc, argv);
296
+ VALUE connection = rb_iv_get(self, "@connection");
297
+ VALUE sqlite3_connection = rb_iv_get(connection, "@connection");
600
298
 
601
- connection = rb_iv_get(self, "@connection");
602
- sqlite3_connection = rb_iv_get(connection, "@connection");
603
- if (Qnil == sqlite3_connection) {
299
+ if (sqlite3_connection == Qnil) {
604
300
  rb_raise(eConnectionError, "This connection has already been closed.");
605
301
  }
606
302
 
303
+ sqlite3 *db = NULL;
304
+
607
305
  Data_Get_Struct(sqlite3_connection, sqlite3, db);
608
306
 
609
- query = build_query_from_args(self, argc, argv);
307
+ sqlite3_stmt *sqlite3_reader;
308
+ struct timeval start;
309
+ int status;
610
310
 
611
311
  gettimeofday(&start, NULL);
612
312
  status = sqlite3_prepare_v2(db, rb_str_ptr_readonly(query), -1, &sqlite3_reader, 0);
613
313
  data_objects_debug(connection, query, &start);
614
314
 
615
- if ( status != SQLITE_OK ) {
315
+ if (status != SQLITE_OK) {
616
316
  raise_error(self, db, query);
617
317
  }
618
318
 
619
- field_count = sqlite3_column_count(sqlite3_reader);
620
- reader = rb_funcall(cReader, ID_NEW, 0);
319
+ int field_count = sqlite3_column_count(sqlite3_reader);
320
+ VALUE reader = rb_funcall(cReader, ID_NEW, 0);
621
321
 
622
322
  rb_iv_set(reader, "@reader", Data_Wrap_Struct(rb_cObject, 0, 0, sqlite3_reader));
623
323
  rb_iv_set(reader, "@field_count", INT2NUM(field_count));
624
324
  rb_iv_set(reader, "@connection", connection);
625
325
 
626
- field_names = rb_ary_new();
627
- field_types = rb_iv_get(self, "@field_types");
326
+ VALUE field_types = rb_iv_get(self, "@field_types");
628
327
 
629
- if ( field_types == Qnil || 0 == RARRAY_LEN(field_types) ) {
328
+ if (field_types == Qnil || RARRAY_LEN(field_types) == 0) {
630
329
  field_types = rb_ary_new();
631
- } else if (RARRAY_LEN(field_types) != field_count) {
330
+ }
331
+ else if (RARRAY_LEN(field_types) != field_count) {
632
332
  // Whoops... wrong number of types passed to set_types. Close the reader and raise
633
333
  // and error
634
334
  rb_funcall(reader, rb_intern("close"), 0);
635
335
  rb_raise(rb_eArgError, "Field-count mismatch. Expected %ld fields, but the query yielded %d", RARRAY_LEN(field_types), field_count);
636
336
  }
637
337
 
638
- for ( i = 0; i < field_count; i++ ) {
338
+ VALUE field_names = rb_ary_new();
339
+ int i;
340
+
341
+ for (i = 0; i < field_count; i++) {
639
342
  rb_ary_push(field_names, rb_str_new2((char *)sqlite3_column_name(sqlite3_reader, i)));
640
343
  }
641
344
 
642
345
  rb_iv_set(reader, "@fields", field_names);
643
346
  rb_iv_set(reader, "@field_types", field_types);
644
-
645
347
  return reader;
646
348
  }
647
349
 
648
- static VALUE cReader_close(VALUE self) {
350
+ VALUE cReader_close(VALUE self) {
649
351
  VALUE reader_obj = rb_iv_get(self, "@reader");
650
352
 
651
- if ( reader_obj != Qnil ) {
652
- sqlite3_stmt *reader;
353
+ if (reader_obj != Qnil) {
354
+ sqlite3_stmt *reader = NULL;
355
+
653
356
  Data_Get_Struct(reader_obj, sqlite3_stmt, reader);
654
357
  sqlite3_finalize(reader);
655
358
  rb_iv_set(self, "@reader", Qnil);
656
359
  return Qtrue;
657
360
  }
658
- else {
659
- return Qfalse;
660
- }
661
- }
662
361
 
663
- static VALUE cReader_next(VALUE self) {
664
- sqlite3_stmt *reader;
665
- int field_count;
666
- int result;
667
- int i;
668
- size_t ft_length;
669
- VALUE arr = rb_ary_new();
670
- VALUE field_types;
671
- VALUE field_type;
672
- VALUE value;
362
+ return Qfalse;
363
+ }
673
364
 
674
- if(rb_iv_get(self, "@done") == Qtrue) {
365
+ VALUE cReader_next(VALUE self) {
366
+ if (rb_iv_get(self, "@done") == Qtrue) {
675
367
  return Qfalse;
676
368
  }
677
369
 
678
- Data_Get_Struct(rb_iv_get(self, "@reader"), sqlite3_stmt, reader);
679
- field_count = NUM2INT(rb_iv_get(self, "@field_count"));
370
+ sqlite3_stmt *reader = NULL;
371
+ int result;
680
372
 
681
- field_types = rb_iv_get(self, "@field_types");
682
- ft_length = RARRAY_LEN(field_types);
373
+ Data_Get_Struct(rb_iv_get(self, "@reader"), sqlite3_stmt, reader);
683
374
 
684
375
  result = sqlite3_step(reader);
685
-
686
376
  rb_iv_set(self, "@state", INT2NUM(result));
687
377
 
688
- if ( result != SQLITE_ROW ) {
378
+ if (result != SQLITE_ROW) {
689
379
  rb_iv_set(self, "@values", Qnil);
690
380
  rb_iv_set(self, "@done", Qtrue);
691
381
  return Qfalse;
@@ -694,86 +384,46 @@ static VALUE cReader_next(VALUE self) {
694
384
  int enc = -1;
695
385
  #ifdef HAVE_RUBY_ENCODING_H
696
386
  VALUE encoding_id = rb_iv_get(rb_iv_get(self, "@connection"), "@encoding_id");
387
+
697
388
  if (encoding_id != Qnil) {
698
389
  enc = FIX2INT(encoding_id);
699
390
  }
700
391
  #endif
701
392
 
393
+ VALUE field_types = rb_iv_get(self, "@field_types");
394
+ int field_count = NUM2INT(rb_iv_get(self, "@field_count"));
395
+ VALUE arr = rb_ary_new();
396
+ VALUE field_type;
397
+ VALUE value;
398
+ int i;
702
399
 
703
- for ( i = 0; i < field_count; i++ ) {
400
+ for (i = 0; i < field_count; i++) {
704
401
  field_type = rb_ary_entry(field_types, i);
705
402
  value = typecast(reader, i, field_type, enc);
706
403
  rb_ary_push(arr, value);
707
404
  }
708
405
 
709
406
  rb_iv_set(self, "@values", arr);
710
-
711
407
  return Qtrue;
712
408
  }
713
409
 
714
- static VALUE cReader_values(VALUE self) {
410
+ VALUE cReader_values_sqlite(VALUE self) {
715
411
  VALUE state = rb_iv_get(self, "@state");
716
- if ( state == Qnil || NUM2INT(state) != SQLITE_ROW ) {
412
+
413
+ if (state == Qnil || NUM2INT(state) != SQLITE_ROW) {
717
414
  rb_raise(eDataError, "Reader is not initialized");
718
415
  return Qnil;
719
416
  }
720
- else {
721
- return rb_iv_get(self, "@values");
722
- }
723
- }
724
-
725
- static VALUE cReader_fields(VALUE self) {
726
- return rb_iv_get(self, "@fields");
727
- }
728
417
 
729
- static VALUE cReader_field_count(VALUE self) {
730
- return rb_iv_get(self, "@field_count");
418
+ return rb_iv_get(self, "@values");
731
419
  }
732
420
 
733
421
  void Init_do_sqlite3() {
734
- rb_require("bigdecimal");
735
- rb_require("date");
736
- rb_require("rational");
737
- rb_require("data_objects");
738
-
739
- ID_CONST_GET = rb_intern("const_get");
740
-
741
- // Get references classes needed for Date/Time parsing
742
- rb_cDate = CONST_GET(rb_mKernel, "Date");
743
- rb_cDateTime = CONST_GET(rb_mKernel, "DateTime");
744
- rb_cBigDecimal = CONST_GET(rb_mKernel, "BigDecimal");
422
+ common_init();
745
423
 
746
- #ifdef RUBY_LESS_THAN_186
747
- ID_NEW_DATE = rb_intern("new0");
748
- #else
749
- ID_NEW_DATE = rb_intern("new!");
750
- #endif
751
- ID_RATIONAL = rb_intern("Rational");
752
- ID_NEW = rb_intern("new");
753
- ID_ESCAPE = rb_intern("escape_sql");
754
- ID_LOG = rb_intern("log");
755
-
756
- // Get references to the Extlib module
757
- mExtlib = CONST_GET(rb_mKernel, "Extlib");
758
- rb_cByteArray = CONST_GET(mExtlib, "ByteArray");
759
-
760
- // Get references to the DataObjects module and its classes
761
- mDO = CONST_GET(rb_mKernel, "DataObjects");
762
- cDO_Quoting = CONST_GET(mDO, "Quoting");
763
- cDO_Connection = CONST_GET(mDO, "Connection");
764
- cDO_Command = CONST_GET(mDO, "Command");
765
- cDO_Result = CONST_GET(mDO, "Result");
766
- cDO_Reader = CONST_GET(mDO, "Reader");
767
- cDO_Logger = CONST_GET(mDO, "Logger");
768
- cDO_Logger_Message = CONST_GET(cDO_Logger, "Message");
769
-
770
- // Initialize the DataObjects::Sqlite3 module, and define its classes
771
424
  mSqlite3 = rb_define_module_under(mDO, "Sqlite3");
772
425
 
773
- eConnectionError = CONST_GET(mDO, "ConnectionError");
774
- eDataError = CONST_GET(mDO, "DataError");
775
-
776
- cConnection = DRIVER_CLASS("Connection", cDO_Connection);
426
+ cConnection = rb_define_class_under(mSqlite3, "Connection", cDO_Connection);
777
427
  rb_define_method(cConnection, "initialize", cConnection_initialize, 1);
778
428
  rb_define_method(cConnection, "dispose", cConnection_dispose, 0);
779
429
  rb_define_method(cConnection, "quote_boolean", cConnection_quote_boolean, 1);
@@ -783,41 +433,23 @@ void Init_do_sqlite3() {
783
433
  rb_define_method(cConnection, "enable_load_extension", cConnection_enable_load_extension, 1);
784
434
  rb_define_method(cConnection, "load_extension", cConnection_load_extension, 1);
785
435
 
786
- cCommand = DRIVER_CLASS("Command", cDO_Command);
436
+ cCommand = rb_define_class_under(mSqlite3, "Command", cDO_Command);
787
437
  rb_define_method(cCommand, "set_types", cCommand_set_types, -1);
788
438
  rb_define_method(cCommand, "execute_non_query", cCommand_execute_non_query, -1);
789
439
  rb_define_method(cCommand, "execute_reader", cCommand_execute_reader, -1);
790
440
 
791
- cResult = DRIVER_CLASS("Result", cDO_Result);
441
+ cResult = rb_define_class_under(mSqlite3, "Result", cDO_Result);
792
442
 
793
- cReader = DRIVER_CLASS("Reader", cDO_Reader);
443
+ cReader = rb_define_class_under(mSqlite3, "Reader", cDO_Reader);
794
444
  rb_define_method(cReader, "close", cReader_close, 0);
795
445
  rb_define_method(cReader, "next!", cReader_next, 0);
796
- rb_define_method(cReader, "values", cReader_values, 0);
446
+ rb_define_method(cReader, "values", cReader_values_sqlite, 0); // TODO: DRY?
797
447
  rb_define_method(cReader, "fields", cReader_fields, 0);
798
448
  rb_define_method(cReader, "field_count", cReader_field_count, 0);
799
449
 
800
- rb_global_variable(&ID_NEW_DATE);
801
- rb_global_variable(&ID_RATIONAL);
802
- rb_global_variable(&ID_CONST_GET);
803
- rb_global_variable(&ID_ESCAPE);
804
- rb_global_variable(&ID_LOG);
805
- rb_global_variable(&ID_NEW);
806
-
807
- rb_global_variable(&rb_cDate);
808
- rb_global_variable(&rb_cDateTime);
809
- rb_global_variable(&rb_cBigDecimal);
810
- rb_global_variable(&rb_cByteArray);
811
-
812
- rb_global_variable(&mDO);
813
- rb_global_variable(&cDO_Logger_Message);
814
-
815
450
  rb_global_variable(&cResult);
816
451
  rb_global_variable(&cReader);
817
452
 
818
- rb_global_variable(&eConnectionError);
819
- rb_global_variable(&eDataError);
820
-
821
453
  OPEN_FLAG_READONLY = rb_str_new2("read_only");
822
454
  rb_global_variable(&OPEN_FLAG_READONLY);
823
455
  OPEN_FLAG_READWRITE = rb_str_new2("read_write");
@@ -830,4 +462,6 @@ void Init_do_sqlite3() {
830
462
  rb_global_variable(&OPEN_FLAG_FULL_MUTEX);
831
463
 
832
464
  Init_do_sqlite3_extension();
465
+
466
+ do_define_errors(mSqlite3, errors);
833
467
  }