do_sqlite3 0.10.3-x86-mingw32 → 0.10.4.rc1-x86-mingw32
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.
- data/LICENSE +1 -1
- data/README.markdown +2 -9
- data/Rakefile +12 -45
- data/ext/do_sqlite3/do_common.c +526 -0
- data/ext/do_sqlite3/do_common.h +170 -0
- data/ext/do_sqlite3/do_sqlite3.c +171 -537
- data/ext/do_sqlite3/do_sqlite3.h +3 -49
- data/ext/do_sqlite3/do_sqlite3_extension.c +28 -29
- data/ext/do_sqlite3/error.h +30 -56
- data/lib/do_sqlite3.rb +8 -3
- data/lib/do_sqlite3/1.8/do_sqlite3.so +0 -0
- data/lib/do_sqlite3/1.9/do_sqlite3.so +0 -0
- data/lib/do_sqlite3/version.rb +1 -1
- data/spec/command_spec.rb +2 -2
- data/spec/connection_spec.rb +9 -9
- data/spec/encoding_spec.rb +3 -3
- data/spec/error/sql_error_spec.rb +2 -2
- data/spec/reader_spec.rb +2 -2
- data/spec/result_spec.rb +4 -4
- data/spec/spec_helper.rb +14 -11
- data/spec/typecast/array_spec.rb +2 -2
- data/spec/typecast/bigdecimal_spec.rb +2 -2
- data/spec/typecast/boolean_spec.rb +2 -2
- data/spec/typecast/byte_array_spec.rb +2 -2
- data/spec/typecast/class_spec.rb +2 -2
- data/spec/typecast/date_spec.rb +2 -2
- data/spec/typecast/datetime_spec.rb +2 -2
- data/spec/typecast/float_spec.rb +3 -3
- data/spec/typecast/integer_spec.rb +2 -2
- data/spec/typecast/nil_spec.rb +5 -5
- data/spec/typecast/other_spec.rb +2 -2
- data/spec/typecast/range_spec.rb +2 -2
- data/spec/typecast/string_spec.rb +2 -2
- data/spec/typecast/time_spec.rb +2 -2
- data/tasks/compile.rake +28 -29
- data/tasks/spec.rake +8 -19
- metadata +50 -47
| @@ -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
         | 
    
        data/ext/do_sqlite3/do_sqlite3.c
    CHANGED
    
    | @@ -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 | 
            -
             | 
| 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 | 
            -
             | 
| 6 | 
            +
            VALUE mSqlite3;
         | 
| 7 | 
            +
            VALUE cConnection;
         | 
| 8 | 
            +
            VALUE cCommand;
         | 
| 9 | 
            +
            VALUE cResult;
         | 
| 10 | 
            +
            VALUE cReader;
         | 
| 75 11 |  | 
| 76 | 
            -
             | 
| 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 | 
            -
             | 
| 80 | 
            -
               | 
| 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 | 
            -
               | 
| 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 | 
            -
               | 
| 23 | 
            +
              do_raise_error(self, errors, errnum, message, query, sql_state);
         | 
| 135 24 | 
             
            }
         | 
| 136 25 |  | 
| 137 | 
            -
             | 
| 138 | 
            -
               | 
| 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 (  | 
| 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 * | 
| 35 | 
            +
              rb_encoding *internal_encoding = rb_default_internal_encoding();
         | 
| 293 36 | 
             
            #else
         | 
| 294 | 
            -
              void * | 
| 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 | 
            -
              } | 
| 62 | 
            +
              }
         | 
| 63 | 
            +
              else if (type == rb_cString) {
         | 
| 321 64 | 
             
                return DO_STR_NEW((char*)sqlite3_column_text(stmt, i), length, encoding, internal_encoding);
         | 
| 322 | 
            -
              } | 
| 65 | 
            +
              }
         | 
| 66 | 
            +
              else if (type == rb_cFloat) {
         | 
| 323 67 | 
             
                return rb_float_new(sqlite3_column_double(stmt, i));
         | 
| 324 | 
            -
              } | 
| 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 | 
            -
              } | 
| 71 | 
            +
              }
         | 
| 72 | 
            +
              else if (type == rb_cDate) {
         | 
| 327 73 | 
             
                return parse_date((char*)sqlite3_column_text(stmt, i));
         | 
| 328 | 
            -
              } | 
| 74 | 
            +
              }
         | 
| 75 | 
            +
              else if (type == rb_cDateTime) {
         | 
| 329 76 | 
             
                return parse_date_time((char*)sqlite3_column_text(stmt, i));
         | 
| 330 | 
            -
              } | 
| 77 | 
            +
              }
         | 
| 78 | 
            +
              else if (type == rb_cTime) {
         | 
| 331 79 | 
             
                return parse_time((char*)sqlite3_column_text(stmt, i));
         | 
| 332 | 
            -
              } | 
| 80 | 
            +
              }
         | 
| 81 | 
            +
              else if (type == rb_cTrueClass) {
         | 
| 333 82 | 
             
                return strcmp((char*)sqlite3_column_text(stmt, i), "t") == 0 ? Qtrue : Qfalse;
         | 
| 334 | 
            -
              } | 
| 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 | 
            -
              } | 
| 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 | 
            -
              } | 
| 89 | 
            +
              }
         | 
| 90 | 
            +
              else if (type == rb_cNilClass) {
         | 
| 339 91 | 
             
                return Qnil;
         | 
| 340 | 
            -
              } | 
| 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 | 
            -
             | 
| 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 | 
            -
                } | 
| 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 | 
            -
              } | 
| 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 | 
            -
             | 
| 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 ( | 
| 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 | 
            -
             | 
| 168 | 
            +
            VALUE cConnection_dispose(VALUE self) {
         | 
| 414 169 | 
             
              VALUE connection_container = rb_iv_get(self, "@connection");
         | 
| 415 170 |  | 
| 416 | 
            -
               | 
| 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 ( | 
| 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 | 
            -
             | 
| 186 | 
            +
            VALUE cConnection_quote_boolean(VALUE self, VALUE value) {
         | 
| 467 187 | 
             
              return rb_str_new2(value == Qtrue ? "'t'" : "'f'");
         | 
| 468 188 | 
             
            }
         | 
| 469 189 |  | 
| 470 | 
            -
             | 
| 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 | 
            -
             | 
| 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 | 
            -
             | 
| 495 | 
            -
               | 
| 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  | 
| 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 ( | 
| 227 | 
            +
              if (!db) {
         | 
| 511 228 | 
             
                return Qfalse;
         | 
| 229 | 
            +
              }
         | 
| 512 230 |  | 
| 513 | 
            -
              status = sqlite3_enable_load_extension(db, value == Qtrue ? 1 : 0);
         | 
| 514 | 
            -
             | 
| 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 | 
            -
             | 
| 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  | 
| 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 ( | 
| 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 | 
            -
               | 
| 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 | 
            -
             | 
| 545 | 
            -
              VALUE query =  | 
| 546 | 
            -
               | 
| 547 | 
            -
              VALUE  | 
| 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 | 
            -
               | 
| 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 ( | 
| 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 | 
            -
             | 
| 590 | 
            -
               | 
| 591 | 
            -
               | 
| 592 | 
            -
               | 
| 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 | 
            -
               | 
| 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 | 
            -
               | 
| 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 ( | 
| 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 | 
            -
               | 
| 627 | 
            -
              field_types = rb_iv_get(self, "@field_types");
         | 
| 326 | 
            +
              VALUE field_types = rb_iv_get(self, "@field_types");
         | 
| 628 327 |  | 
| 629 | 
            -
              if ( | 
| 328 | 
            +
              if (field_types == Qnil || RARRAY_LEN(field_types) == 0) {
         | 
| 630 329 | 
             
                field_types = rb_ary_new();
         | 
| 631 | 
            -
              } | 
| 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 | 
            -
               | 
| 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 | 
            -
             | 
| 350 | 
            +
            VALUE cReader_close(VALUE self) {
         | 
| 649 351 | 
             
              VALUE reader_obj = rb_iv_get(self, "@reader");
         | 
| 650 352 |  | 
| 651 | 
            -
              if ( | 
| 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 | 
            -
             | 
| 664 | 
            -
             | 
| 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 | 
            -
             | 
| 365 | 
            +
            VALUE cReader_next(VALUE self) {
         | 
| 366 | 
            +
              if (rb_iv_get(self, "@done") == Qtrue) {
         | 
| 675 367 | 
             
                return Qfalse;
         | 
| 676 368 | 
             
              }
         | 
| 677 369 |  | 
| 678 | 
            -
               | 
| 679 | 
            -
               | 
| 370 | 
            +
              sqlite3_stmt *reader = NULL;
         | 
| 371 | 
            +
              int result;
         | 
| 680 372 |  | 
| 681 | 
            -
               | 
| 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 ( | 
| 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 ( | 
| 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 | 
            -
             | 
| 410 | 
            +
            VALUE cReader_values_sqlite(VALUE self) {
         | 
| 715 411 | 
             
              VALUE state = rb_iv_get(self, "@state");
         | 
| 716 | 
            -
             | 
| 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 | 
            -
             | 
| 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 | 
            -
               | 
| 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 | 
            -
               | 
| 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 =  | 
| 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 =  | 
| 441 | 
            +
              cResult = rb_define_class_under(mSqlite3, "Result", cDO_Result);
         | 
| 792 442 |  | 
| 793 | 
            -
              cReader =  | 
| 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",  | 
| 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 | 
             
            }
         |