trilogy 2.1.2 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/README.md +7 -1
 - data/ext/trilogy-ruby/cast.c +11 -6
 - data/ext/trilogy-ruby/cext.c +167 -78
 - data/ext/trilogy-ruby/inc/trilogy/protocol.h +1 -3
 - data/ext/trilogy-ruby/trilogy-ruby.h +2 -1
 - data/lib/trilogy/version.rb +1 -1
 - data/lib/trilogy.rb +119 -21
 - metadata +3 -3
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 693efafac411af8e0859eee682d4432a501f17d90c3735faabad4cac4ab07537
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 646bc59fce2e3b26058bf867f448496e5d5caf1344ca0832d706bd3e2db99a2f
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 311d5640cdd3da6e3ba331c8222698ff18a10b06886d277712fb8da453924d862f4c9269163a5f748b73dcbc19087993ae2b3cbdc6fccbbd97a91c0c88f83bed
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 77442107a8527f806c2f602d95c000d81c2e7b7a09f6efc8a77a5dcbb091eb4c6890948a1352a72a8fa2f7ef6fe1d74cb0eda84b0d385049514a8dd0236d597d
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -34,6 +34,12 @@ if client.ping 
     | 
|
| 
       34 
34 
     | 
    
         
             
              result.each_hash do |user|
         
     | 
| 
       35 
35 
     | 
    
         
             
                p user
         
     | 
| 
       36 
36 
     | 
    
         
             
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              # Multi-statement
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              results = []
         
     | 
| 
      
 41 
     | 
    
         
            +
              results << client.query("SELECT name FROM users WHERE id = 1; SELECT name FROM users WHERE id = 2")
         
     | 
| 
      
 42 
     | 
    
         
            +
              results << client.next_result while client.more_results_exist?
         
     | 
| 
       37 
43 
     | 
    
         
             
            end
         
     | 
| 
       38 
44 
     | 
    
         
             
            ```
         
     | 
| 
       39 
45 
     | 
    
         | 
| 
         @@ -59,7 +65,7 @@ The official Ruby bindings are inside of the canonical trilogy repository itself 
     | 
|
| 
       59 
65 
     | 
    
         
             
            The trilogy API was heavily inspired by the mysql2 gem but has a few notable
         
     | 
| 
       60 
66 
     | 
    
         
             
            differences:
         
     | 
| 
       61 
67 
     | 
    
         | 
| 
       62 
     | 
    
         
            -
            * The ` 
     | 
| 
      
 68 
     | 
    
         
            +
            * The `query_flags` don't inherit from the connection options hash.
         
     | 
| 
       63 
69 
     | 
    
         
             
              This means that options like turning on/of casting will need to be set before
         
     | 
| 
       64 
70 
     | 
    
         
             
              a query and not passed in at connect time.
         
     | 
| 
       65 
71 
     | 
    
         
             
            * For performance reasons there is no `application_timezone` query option. If
         
     | 
    
        data/ext/trilogy-ruby/cast.c
    CHANGED
    
    | 
         @@ -7,7 +7,7 @@ 
     | 
|
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
            #define CAST_STACK_SIZE 64
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
     | 
    
         
            -
            static ID id_BigDecimal, id_new, id_local, id_localtime, id_utc;
         
     | 
| 
      
 10 
     | 
    
         
            +
            static ID id_BigDecimal, id_Integer, id_new, id_local, id_localtime, id_utc;
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
            static const char *ruby_encoding_name_map[] = {
         
     | 
| 
       13 
13 
     | 
    
         
             
                [TRILOGY_ENCODING_ARMSCII8] = NULL,
         
     | 
| 
         @@ -71,7 +71,7 @@ static void cstr_from_value(char *buf, const trilogy_value_t *value, const char 
     | 
|
| 
       71 
71 
     | 
    
         
             
            {
         
     | 
| 
       72 
72 
     | 
    
         | 
| 
       73 
73 
     | 
    
         
             
                if (value->data_len > CAST_STACK_SIZE - 1) {
         
     | 
| 
       74 
     | 
    
         
            -
                    rb_raise( 
     | 
| 
      
 74 
     | 
    
         
            +
                    rb_raise(Trilogy_CastError, errmsg, (int)value->data_len, (char *)value->data);
         
     | 
| 
       75 
75 
     | 
    
         
             
                }
         
     | 
| 
       76 
76 
     | 
    
         | 
| 
       77 
77 
     | 
    
         
             
                memcpy(buf, value->data, value->data_len);
         
     | 
| 
         @@ -145,7 +145,11 @@ rb_trilogy_cast_value(const trilogy_value_t *value, const struct column_info *co 
     | 
|
| 
       145 
145 
     | 
    
         
             
                        // TODO - optimize so we don't have to allocate a ruby string for
         
     | 
| 
       146 
146 
     | 
    
         
             
                        // decimal columns
         
     | 
| 
       147 
147 
     | 
    
         
             
                        VALUE str = rb_str_new(value->data, value->data_len);
         
     | 
| 
       148 
     | 
    
         
            -
                         
     | 
| 
      
 148 
     | 
    
         
            +
                        if (column->decimals == 0) {
         
     | 
| 
      
 149 
     | 
    
         
            +
                            return rb_funcall(rb_mKernel, id_Integer, 1, str);
         
     | 
| 
      
 150 
     | 
    
         
            +
                        } else {
         
     | 
| 
      
 151 
     | 
    
         
            +
                            return rb_funcall(rb_mKernel, id_BigDecimal, 1, str);
         
     | 
| 
      
 152 
     | 
    
         
            +
                        }
         
     | 
| 
       149 
153 
     | 
    
         
             
                    }
         
     | 
| 
       150 
154 
     | 
    
         
             
                    case TRILOGY_TYPE_FLOAT:
         
     | 
| 
       151 
155 
     | 
    
         
             
                    case TRILOGY_TYPE_DOUBLE: {
         
     | 
| 
         @@ -156,7 +160,7 @@ rb_trilogy_cast_value(const trilogy_value_t *value, const struct column_info *co 
     | 
|
| 
       156 
160 
     | 
    
         
             
                        double dbl = strtod(cstr, &err);
         
     | 
| 
       157 
161 
     | 
    
         | 
| 
       158 
162 
     | 
    
         
             
                        if (*err != 0) {
         
     | 
| 
       159 
     | 
    
         
            -
                            rb_raise( 
     | 
| 
      
 163 
     | 
    
         
            +
                            rb_raise(Trilogy_CastError, "Invalid double value: %.*s", (int)value->data_len, (char *)value->data);
         
     | 
| 
       160 
164 
     | 
    
         
             
                        }
         
     | 
| 
       161 
165 
     | 
    
         
             
                        return rb_float_new(dbl);
         
     | 
| 
       162 
166 
     | 
    
         
             
                    }
         
     | 
| 
         @@ -180,7 +184,7 @@ rb_trilogy_cast_value(const trilogy_value_t *value, const struct column_info *co 
     | 
|
| 
       180 
184 
     | 
    
         
             
                        }
         
     | 
| 
       181 
185 
     | 
    
         | 
| 
       182 
186 
     | 
    
         
             
                        if (month < 1 || day < 1) {
         
     | 
| 
       183 
     | 
    
         
            -
                            rb_raise( 
     | 
| 
      
 187 
     | 
    
         
            +
                            rb_raise(Trilogy_CastError, "Invalid date: %.*s", (int)value->data_len, (char *)value->data);
         
     | 
| 
       184 
188 
     | 
    
         
             
                        }
         
     | 
| 
       185 
189 
     | 
    
         | 
| 
       186 
190 
     | 
    
         
             
                        // pad out msec_char with zeroes at the end as it could be at any
         
     | 
| 
         @@ -211,7 +215,7 @@ rb_trilogy_cast_value(const trilogy_value_t *value, const struct column_info *co 
     | 
|
| 
       211 
215 
     | 
    
         
             
                        }
         
     | 
| 
       212 
216 
     | 
    
         | 
| 
       213 
217 
     | 
    
         
             
                        if (month < 1 || day < 1) {
         
     | 
| 
       214 
     | 
    
         
            -
                            rb_raise( 
     | 
| 
      
 218 
     | 
    
         
            +
                            rb_raise(Trilogy_CastError, "Invalid date: %.*s", (int)value->data_len, (char *)value->data);
         
     | 
| 
       215 
219 
     | 
    
         
             
                        }
         
     | 
| 
       216 
220 
     | 
    
         | 
| 
       217 
221 
     | 
    
         
             
                        return rb_funcall(Date, id_new, 3, INT2NUM(year), INT2NUM(month), INT2NUM(day));
         
     | 
| 
         @@ -265,6 +269,7 @@ void rb_trilogy_cast_init(void) 
     | 
|
| 
       265 
269 
     | 
    
         
             
                rb_require("date");
         
     | 
| 
       266 
270 
     | 
    
         | 
| 
       267 
271 
     | 
    
         
             
                id_BigDecimal = rb_intern("BigDecimal");
         
     | 
| 
      
 272 
     | 
    
         
            +
                id_Integer = rb_intern("Integer");
         
     | 
| 
       268 
273 
     | 
    
         
             
                id_new = rb_intern("new");
         
     | 
| 
       269 
274 
     | 
    
         
             
                id_local = rb_intern("local");
         
     | 
| 
       270 
275 
     | 
    
         
             
                id_localtime = rb_intern("localtime");
         
     | 
    
        data/ext/trilogy-ruby/cext.c
    CHANGED
    
    | 
         @@ -14,16 +14,16 @@ 
     | 
|
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         
             
            #define TRILOGY_RB_TIMEOUT 1
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
            VALUE
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
            static VALUE Trilogy_DatabaseError, Trilogy_Result;
         
     | 
| 
      
 17 
     | 
    
         
            +
            VALUE Trilogy_CastError;
         
     | 
| 
      
 18 
     | 
    
         
            +
            static VALUE Trilogy_BaseConnectionError, Trilogy_ProtocolError, Trilogy_SSLError, Trilogy_QueryError,
         
     | 
| 
      
 19 
     | 
    
         
            +
                Trilogy_ConnectionClosedError, Trilogy_TimeoutError, Trilogy_Result;
         
     | 
| 
       21 
20 
     | 
    
         | 
| 
       22 
21 
     | 
    
         
             
            static ID id_socket, id_host, id_port, id_username, id_password, id_found_rows, id_connect_timeout, id_read_timeout,
         
     | 
| 
       23 
22 
     | 
    
         
             
                id_write_timeout, id_keepalive_enabled, id_keepalive_idle, id_keepalive_interval, id_keepalive_count,
         
     | 
| 
       24 
23 
     | 
    
         
             
                id_ivar_affected_rows, id_ivar_fields, id_ivar_last_insert_id, id_ivar_rows, id_ivar_query_time, id_password,
         
     | 
| 
       25 
24 
     | 
    
         
             
                id_database, id_ssl_ca, id_ssl_capath, id_ssl_cert, id_ssl_cipher, id_ssl_crl, id_ssl_crlpath, id_ssl_key,
         
     | 
| 
       26 
     | 
    
         
            -
                id_ssl_mode, id_tls_ciphersuites, id_tls_min_version, id_tls_max_version 
     | 
| 
      
 25 
     | 
    
         
            +
                id_ssl_mode, id_tls_ciphersuites, id_tls_min_version, id_tls_max_version, id_multi_statement, id_from_code,
         
     | 
| 
      
 26 
     | 
    
         
            +
                id_connection_options;
         
     | 
| 
       27 
27 
     | 
    
         | 
| 
       28 
28 
     | 
    
         
             
            struct trilogy_ctx {
         
     | 
| 
       29 
29 
     | 
    
         
             
                trilogy_conn_t conn;
         
     | 
| 
         @@ -31,10 +31,39 @@ struct trilogy_ctx { 
     | 
|
| 
       31 
31 
     | 
    
         
             
                unsigned int query_flags;
         
     | 
| 
       32 
32 
     | 
    
         
             
            };
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
      
 34 
     | 
    
         
            +
            static void free_trilogy(void *ptr)
         
     | 
| 
      
 35 
     | 
    
         
            +
            {
         
     | 
| 
      
 36 
     | 
    
         
            +
                struct trilogy_ctx *ctx = ptr;
         
     | 
| 
      
 37 
     | 
    
         
            +
                if (ctx->conn.socket != NULL) {
         
     | 
| 
      
 38 
     | 
    
         
            +
                    trilogy_free(&ctx->conn);
         
     | 
| 
      
 39 
     | 
    
         
            +
                }
         
     | 
| 
      
 40 
     | 
    
         
            +
                xfree(ptr);
         
     | 
| 
      
 41 
     | 
    
         
            +
            }
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            static size_t trilogy_memsize(const void *ptr) {
         
     | 
| 
      
 44 
     | 
    
         
            +
                const struct trilogy_ctx *ctx = ptr;
         
     | 
| 
      
 45 
     | 
    
         
            +
                size_t memsize = sizeof(struct trilogy_ctx);
         
     | 
| 
      
 46 
     | 
    
         
            +
                if (ctx->conn.socket != NULL) {
         
     | 
| 
      
 47 
     | 
    
         
            +
                    memsize += sizeof(trilogy_sock_t);
         
     | 
| 
      
 48 
     | 
    
         
            +
                }
         
     | 
| 
      
 49 
     | 
    
         
            +
                memsize += ctx->conn.packet_buffer.cap;
         
     | 
| 
      
 50 
     | 
    
         
            +
                return memsize;
         
     | 
| 
      
 51 
     | 
    
         
            +
            }
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            const rb_data_type_t trilogy_data_type = {
         
     | 
| 
      
 54 
     | 
    
         
            +
                .wrap_struct_name = "trilogy",
         
     | 
| 
      
 55 
     | 
    
         
            +
                .function = {
         
     | 
| 
      
 56 
     | 
    
         
            +
                    .dmark = NULL,
         
     | 
| 
      
 57 
     | 
    
         
            +
                    .dfree = free_trilogy,
         
     | 
| 
      
 58 
     | 
    
         
            +
                    .dsize = trilogy_memsize,
         
     | 
| 
      
 59 
     | 
    
         
            +
                },
         
     | 
| 
      
 60 
     | 
    
         
            +
                .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
         
     | 
| 
      
 61 
     | 
    
         
            +
            };
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
       34 
63 
     | 
    
         
             
            static struct trilogy_ctx *get_ctx(VALUE obj)
         
     | 
| 
       35 
64 
     | 
    
         
             
            {
         
     | 
| 
       36 
65 
     | 
    
         
             
                struct trilogy_ctx *ctx;
         
     | 
| 
       37 
     | 
    
         
            -
                 
     | 
| 
      
 66 
     | 
    
         
            +
                TypedData_Get_Struct(obj, struct trilogy_ctx, &trilogy_data_type, ctx);
         
     | 
| 
       38 
67 
     | 
    
         
             
                return ctx;
         
     | 
| 
       39 
68 
     | 
    
         
             
            }
         
     | 
| 
       40 
69 
     | 
    
         | 
| 
         @@ -43,7 +72,7 @@ static struct trilogy_ctx *get_open_ctx(VALUE obj) 
     | 
|
| 
       43 
72 
     | 
    
         
             
                struct trilogy_ctx *ctx = get_ctx(obj);
         
     | 
| 
       44 
73 
     | 
    
         | 
| 
       45 
74 
     | 
    
         
             
                if (ctx->conn.socket == NULL) {
         
     | 
| 
       46 
     | 
    
         
            -
                    rb_raise( 
     | 
| 
      
 75 
     | 
    
         
            +
                    rb_raise(Trilogy_ConnectionClosedError, "Attempted to use closed connection");
         
     | 
| 
       47 
76 
     | 
    
         
             
                }
         
     | 
| 
       48 
77 
     | 
    
         | 
| 
       49 
78 
     | 
    
         
             
                return ctx;
         
     | 
| 
         @@ -59,16 +88,16 @@ static void handle_trilogy_error(struct trilogy_ctx *ctx, int rc, const char *ms 
     | 
|
| 
       59 
88 
     | 
    
         | 
| 
       60 
89 
     | 
    
         
             
                switch (rc) {
         
     | 
| 
       61 
90 
     | 
    
         
             
                case TRILOGY_SYSERR:
         
     | 
| 
       62 
     | 
    
         
            -
                     
     | 
| 
      
 91 
     | 
    
         
            +
                    if (errno == ECONNREFUSED || errno == ECONNRESET) {
         
     | 
| 
      
 92 
     | 
    
         
            +
                        rb_raise(Trilogy_BaseConnectionError, "%" PRIsVALUE, rbmsg);
         
     | 
| 
      
 93 
     | 
    
         
            +
                    } else {
         
     | 
| 
      
 94 
     | 
    
         
            +
                        // TODO: All syserr should be wrapped.
         
     | 
| 
      
 95 
     | 
    
         
            +
                        rb_syserr_fail_str(errno, rbmsg);
         
     | 
| 
      
 96 
     | 
    
         
            +
                    }
         
     | 
| 
       63 
97 
     | 
    
         | 
| 
       64 
98 
     | 
    
         
             
                case TRILOGY_ERR: {
         
     | 
| 
       65 
99 
     | 
    
         
             
                    VALUE message = rb_str_new(ctx->conn.error_message, ctx->conn.error_message_len);
         
     | 
| 
       66 
     | 
    
         
            -
                    VALUE exc =  
     | 
| 
       67 
     | 
    
         
            -
                                            rb_sprintf("%" PRIsVALUE ": %d %" PRIsVALUE, rbmsg, ctx->conn.error_code, message));
         
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
                    rb_ivar_set(exc, rb_intern("@error_code"), INT2FIX(ctx->conn.error_code));
         
     | 
| 
       70 
     | 
    
         
            -
                    rb_ivar_set(exc, rb_intern("@error_message"), message);
         
     | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
      
 100 
     | 
    
         
            +
                    VALUE exc = rb_funcall(Trilogy_ProtocolError, id_from_code, 2, message, INT2NUM(ctx->conn.error_code));
         
     | 
| 
       72 
101 
     | 
    
         
             
                    rb_exc_raise(exc);
         
     | 
| 
       73 
102 
     | 
    
         
             
                }
         
     | 
| 
       74 
103 
     | 
    
         | 
| 
         @@ -76,25 +105,29 @@ static void handle_trilogy_error(struct trilogy_ctx *ctx, int rc, const char *ms 
     | 
|
| 
       76 
105 
     | 
    
         
             
                    unsigned long ossl_error = ERR_get_error();
         
     | 
| 
       77 
106 
     | 
    
         
             
                    ERR_clear_error();
         
     | 
| 
       78 
107 
     | 
    
         
             
                    if (ERR_GET_LIB(ossl_error) == ERR_LIB_SYS) {
         
     | 
| 
       79 
     | 
    
         
            -
                         
     | 
| 
      
 108 
     | 
    
         
            +
                        int err_reason = ERR_GET_REASON(ossl_error);
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                        if (err_reason == ECONNREFUSED || err_reason == ECONNRESET) {
         
     | 
| 
      
 111 
     | 
    
         
            +
                            rb_raise(Trilogy_BaseConnectionError, "%" PRIsVALUE, rbmsg);
         
     | 
| 
      
 112 
     | 
    
         
            +
                        } else {
         
     | 
| 
      
 113 
     | 
    
         
            +
                            // TODO: All syserr should be wrapped.
         
     | 
| 
      
 114 
     | 
    
         
            +
                            rb_syserr_fail_str(err_reason, rbmsg);
         
     | 
| 
      
 115 
     | 
    
         
            +
                        }
         
     | 
| 
       80 
116 
     | 
    
         
             
                    }
         
     | 
| 
       81 
117 
     | 
    
         
             
                    // We can't recover from OpenSSL level errors if there's
         
     | 
| 
       82 
118 
     | 
    
         
             
                    // an active connection.
         
     | 
| 
       83 
119 
     | 
    
         
             
                    if (ctx->conn.socket != NULL) {
         
     | 
| 
       84 
120 
     | 
    
         
             
                        trilogy_sock_shutdown(ctx->conn.socket);
         
     | 
| 
       85 
121 
     | 
    
         
             
                    }
         
     | 
| 
       86 
     | 
    
         
            -
                    rb_raise( 
     | 
| 
      
 122 
     | 
    
         
            +
                    rb_raise(Trilogy_SSLError, "%" PRIsVALUE ": SSL Error: %s", rbmsg, ERR_reason_error_string(ossl_error));
         
     | 
| 
       87 
123 
     | 
    
         
             
                }
         
     | 
| 
       88 
124 
     | 
    
         | 
| 
       89 
     | 
    
         
            -
                 
     | 
| 
       90 
     | 
    
         
            -
                    rb_raise( 
     | 
| 
      
 125 
     | 
    
         
            +
                case TRILOGY_DNS_ERR: {
         
     | 
| 
      
 126 
     | 
    
         
            +
                    rb_raise(Trilogy_BaseConnectionError, "%" PRIsVALUE ": TRILOGY_DNS_ERROR", rbmsg);
         
     | 
| 
       91 
127 
     | 
    
         
             
                }
         
     | 
| 
       92 
     | 
    
         
            -
            }
         
     | 
| 
       93 
128 
     | 
    
         | 
| 
       94 
     | 
    
         
            -
             
     | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
       96 
     | 
    
         
            -
                if (ctx->conn.socket != NULL) {
         
     | 
| 
       97 
     | 
    
         
            -
                    trilogy_free(&ctx->conn);
         
     | 
| 
      
 129 
     | 
    
         
            +
                default:
         
     | 
| 
      
 130 
     | 
    
         
            +
                    rb_raise(Trilogy_QueryError, "%" PRIsVALUE ": %s", rbmsg, trilogy_error(rc));
         
     | 
| 
       98 
131 
     | 
    
         
             
                }
         
     | 
| 
       99 
132 
     | 
    
         
             
            }
         
     | 
| 
       100 
133 
     | 
    
         | 
| 
         @@ -102,14 +135,18 @@ static VALUE allocate_trilogy(VALUE klass) 
     | 
|
| 
       102 
135 
     | 
    
         
             
            {
         
     | 
| 
       103 
136 
     | 
    
         
             
                struct trilogy_ctx *ctx;
         
     | 
| 
       104 
137 
     | 
    
         | 
| 
       105 
     | 
    
         
            -
                VALUE obj =  
     | 
| 
       106 
     | 
    
         
            -
             
     | 
| 
       107 
     | 
    
         
            -
                memset(ctx->server_version, 0, sizeof(ctx->server_version));
         
     | 
| 
      
 138 
     | 
    
         
            +
                VALUE obj = TypedData_Make_Struct(klass, struct trilogy_ctx, &trilogy_data_type, ctx);
         
     | 
| 
       108 
139 
     | 
    
         | 
| 
       109 
140 
     | 
    
         
             
                ctx->query_flags = TRILOGY_FLAGS_DEFAULT;
         
     | 
| 
       110 
141 
     | 
    
         | 
| 
       111 
142 
     | 
    
         
             
                if (trilogy_init(&ctx->conn) < 0) {
         
     | 
| 
       112 
     | 
    
         
            -
                     
     | 
| 
      
 143 
     | 
    
         
            +
                    if (errno == ECONNREFUSED || errno == ECONNRESET) {
         
     | 
| 
      
 144 
     | 
    
         
            +
                        rb_raise(Trilogy_BaseConnectionError, "trilogy_init");
         
     | 
| 
      
 145 
     | 
    
         
            +
                    } else {
         
     | 
| 
      
 146 
     | 
    
         
            +
                        // TODO: All syserr should be wrapped.
         
     | 
| 
      
 147 
     | 
    
         
            +
                        VALUE rbmsg = rb_str_new("trilogy_init", 13);
         
     | 
| 
      
 148 
     | 
    
         
            +
                        rb_syserr_fail_str(errno, rbmsg);
         
     | 
| 
      
 149 
     | 
    
         
            +
                    }
         
     | 
| 
       113 
150 
     | 
    
         
             
                }
         
     | 
| 
       114 
151 
     | 
    
         | 
| 
       115 
152 
     | 
    
         
             
                return obj;
         
     | 
| 
         @@ -125,7 +162,7 @@ static int flush_writes(struct trilogy_ctx *ctx) 
     | 
|
| 
       125 
162 
     | 
    
         
             
                    }
         
     | 
| 
       126 
163 
     | 
    
         | 
| 
       127 
164 
     | 
    
         
             
                    if (trilogy_sock_wait_write(ctx->conn.socket) < 0) {
         
     | 
| 
       128 
     | 
    
         
            -
                         
     | 
| 
      
 165 
     | 
    
         
            +
                        rb_raise(Trilogy_TimeoutError, "trilogy_flush_writes");
         
     | 
| 
       129 
166 
     | 
    
         
             
                    }
         
     | 
| 
       130 
167 
     | 
    
         
             
                }
         
     | 
| 
       131 
168 
     | 
    
         
             
            }
         
     | 
| 
         @@ -259,7 +296,7 @@ static void auth_switch(struct trilogy_ctx *ctx, trilogy_handshake_t *handshake) 
     | 
|
| 
       259 
296 
     | 
    
         
             
                    }
         
     | 
| 
       260 
297 
     | 
    
         | 
| 
       261 
298 
     | 
    
         
             
                    if (trilogy_sock_wait_read(ctx->conn.socket) < 0) {
         
     | 
| 
       262 
     | 
    
         
            -
                         
     | 
| 
      
 299 
     | 
    
         
            +
                        rb_raise(Trilogy_TimeoutError, "trilogy_auth_recv");
         
     | 
| 
       263 
300 
     | 
    
         
             
                    }
         
     | 
| 
       264 
301 
     | 
    
         
             
                }
         
     | 
| 
       265 
302 
     | 
    
         
             
            }
         
     | 
| 
         @@ -285,7 +322,7 @@ static void authenticate(struct trilogy_ctx *ctx, trilogy_handshake_t *handshake 
     | 
|
| 
       285 
322 
     | 
    
         
             
                        }
         
     | 
| 
       286 
323 
     | 
    
         
             
                    } else {
         
     | 
| 
       287 
324 
     | 
    
         
             
                        if (ssl_mode != TRILOGY_SSL_PREFERRED_NOVERIFY) {
         
     | 
| 
       288 
     | 
    
         
            -
                            rb_raise( 
     | 
| 
      
 325 
     | 
    
         
            +
                            rb_raise(Trilogy_SSLError, "SSL required, not supported by server");
         
     | 
| 
       289 
326 
     | 
    
         
             
                        }
         
     | 
| 
       290 
327 
     | 
    
         
             
                    }
         
     | 
| 
       291 
328 
     | 
    
         
             
                }
         
     | 
| 
         @@ -312,7 +349,7 @@ static void authenticate(struct trilogy_ctx *ctx, trilogy_handshake_t *handshake 
     | 
|
| 
       312 
349 
     | 
    
         
             
                    }
         
     | 
| 
       313 
350 
     | 
    
         | 
| 
       314 
351 
     | 
    
         
             
                    if (trilogy_sock_wait_read(ctx->conn.socket) < 0) {
         
     | 
| 
       315 
     | 
    
         
            -
                         
     | 
| 
      
 352 
     | 
    
         
            +
                        rb_raise(Trilogy_TimeoutError, "trilogy_auth_recv");
         
     | 
| 
       316 
353 
     | 
    
         
             
                    }
         
     | 
| 
       317 
354 
     | 
    
         
             
                }
         
     | 
| 
       318 
355 
     | 
    
         | 
| 
         @@ -329,6 +366,7 @@ static VALUE rb_trilogy_initialize(VALUE self, VALUE opts) 
     | 
|
| 
       329 
366 
     | 
    
         
             
                VALUE val;
         
     | 
| 
       330 
367 
     | 
    
         | 
| 
       331 
368 
     | 
    
         
             
                Check_Type(opts, T_HASH);
         
     | 
| 
      
 369 
     | 
    
         
            +
                rb_ivar_set(self, id_connection_options, opts);
         
     | 
| 
       332 
370 
     | 
    
         | 
| 
       333 
371 
     | 
    
         
             
                if ((val = rb_hash_lookup(opts, ID2SYM(id_ssl_mode))) != Qnil) {
         
     | 
| 
       334 
372 
     | 
    
         
             
                    Check_Type(val, T_FIXNUM);
         
     | 
| 
         @@ -406,6 +444,10 @@ static VALUE rb_trilogy_initialize(VALUE self, VALUE opts) 
     | 
|
| 
       406 
444 
     | 
    
         
             
                    connopt.flags |= TRILOGY_CAPABILITIES_FOUND_ROWS;
         
     | 
| 
       407 
445 
     | 
    
         
             
                }
         
     | 
| 
       408 
446 
     | 
    
         | 
| 
      
 447 
     | 
    
         
            +
                if (RTEST(rb_hash_aref(opts, ID2SYM(id_multi_statement)))) {
         
     | 
| 
      
 448 
     | 
    
         
            +
                    connopt.flags |= TRILOGY_CAPABILITIES_MULTI_STATEMENTS;
         
     | 
| 
      
 449 
     | 
    
         
            +
                }
         
     | 
| 
      
 450 
     | 
    
         
            +
             
     | 
| 
       409 
451 
     | 
    
         
             
                if ((val = rb_hash_aref(opts, ID2SYM(id_ssl_ca))) != Qnil) {
         
     | 
| 
       410 
452 
     | 
    
         
             
                    Check_Type(val, T_STRING);
         
     | 
| 
       411 
453 
     | 
    
         
             
                    connopt.ssl_ca = StringValueCStr(val);
         
     | 
| 
         @@ -458,7 +500,7 @@ static VALUE rb_trilogy_initialize(VALUE self, VALUE opts) 
     | 
|
| 
       458 
500 
     | 
    
         | 
| 
       459 
501 
     | 
    
         
             
                int rc = try_connect(ctx, &handshake, &connopt);
         
     | 
| 
       460 
502 
     | 
    
         
             
                if (rc == TRILOGY_RB_TIMEOUT) {
         
     | 
| 
       461 
     | 
    
         
            -
                     
     | 
| 
      
 503 
     | 
    
         
            +
                    rb_raise(Trilogy_TimeoutError, "trilogy_connect_recv");
         
     | 
| 
       462 
504 
     | 
    
         
             
                }
         
     | 
| 
       463 
505 
     | 
    
         
             
                if (rc != TRILOGY_OK) {
         
     | 
| 
       464 
506 
     | 
    
         
             
                    if (connopt.path) {
         
     | 
| 
         @@ -505,7 +547,7 @@ static VALUE rb_trilogy_change_db(VALUE self, VALUE database) 
     | 
|
| 
       505 
547 
     | 
    
         
             
                    }
         
     | 
| 
       506 
548 
     | 
    
         | 
| 
       507 
549 
     | 
    
         
             
                    if (trilogy_sock_wait_read(ctx->conn.socket) < 0) {
         
     | 
| 
       508 
     | 
    
         
            -
                         
     | 
| 
      
 550 
     | 
    
         
            +
                        rb_raise(Trilogy_TimeoutError, "trilogy_change_db_recv");
         
     | 
| 
       509 
551 
     | 
    
         
             
                    }
         
     | 
| 
       510 
552 
     | 
    
         
             
                }
         
     | 
| 
       511 
553 
     | 
    
         | 
| 
         @@ -520,10 +562,9 @@ static void load_query_options(unsigned int query_flags, struct rb_trilogy_cast_ 
     | 
|
| 
       520 
562 
     | 
    
         
             
                cast_options->flatten_rows = (query_flags & TRILOGY_FLAGS_FLATTEN_ROWS) != 0;
         
     | 
| 
       521 
563 
     | 
    
         
             
            }
         
     | 
| 
       522 
564 
     | 
    
         | 
| 
       523 
     | 
    
         
            -
            struct  
     | 
| 
      
 565 
     | 
    
         
            +
            struct read_query_response_state {
         
     | 
| 
       524 
566 
     | 
    
         
             
                struct rb_trilogy_cast_options *cast_options;
         
     | 
| 
       525 
567 
     | 
    
         
             
                struct trilogy_ctx *ctx;
         
     | 
| 
       526 
     | 
    
         
            -
                VALUE query;
         
     | 
| 
       527 
568 
     | 
    
         | 
| 
       528 
569 
     | 
    
         
             
                // to free by caller:
         
     | 
| 
       529 
570 
     | 
    
         
             
                struct column_info *column_info;
         
     | 
| 
         @@ -550,34 +591,25 @@ static void get_timespec_monotonic(struct timespec *ts) 
     | 
|
| 
       550 
591 
     | 
    
         
             
            #endif
         
     | 
| 
       551 
592 
     | 
    
         
             
            }
         
     | 
| 
       552 
593 
     | 
    
         | 
| 
       553 
     | 
    
         
            -
            static VALUE read_query_error(struct  
     | 
| 
      
 594 
     | 
    
         
            +
            static VALUE read_query_error(struct read_query_response_state *args, int rc, const char *msg)
         
     | 
| 
       554 
595 
     | 
    
         
             
            {
         
     | 
| 
       555 
596 
     | 
    
         
             
                args->rc = rc;
         
     | 
| 
       556 
597 
     | 
    
         
             
                args->msg = msg;
         
     | 
| 
       557 
598 
     | 
    
         
             
                return Qundef;
         
     | 
| 
       558 
599 
     | 
    
         
             
            }
         
     | 
| 
       559 
600 
     | 
    
         | 
| 
       560 
     | 
    
         
            -
            static VALUE  
     | 
| 
      
 601 
     | 
    
         
            +
            static VALUE read_query_response(VALUE vargs)
         
     | 
| 
       561 
602 
     | 
    
         
             
            {
         
     | 
| 
       562 
     | 
    
         
            -
                struct  
     | 
| 
      
 603 
     | 
    
         
            +
                struct read_query_response_state *args = (void *)vargs;
         
     | 
| 
       563 
604 
     | 
    
         
             
                struct trilogy_ctx *ctx = args->ctx;
         
     | 
| 
       564 
     | 
    
         
            -
                VALUE query = args->query;
         
     | 
| 
       565 
605 
     | 
    
         | 
| 
       566 
606 
     | 
    
         
             
                struct timespec start;
         
     | 
| 
       567 
607 
     | 
    
         
             
                get_timespec_monotonic(&start);
         
     | 
| 
       568 
608 
     | 
    
         | 
| 
       569 
     | 
    
         
            -
                int rc = trilogy_query_send(&ctx->conn, RSTRING_PTR(query), RSTRING_LEN(query));
         
     | 
| 
       570 
     | 
    
         
            -
             
     | 
| 
       571 
     | 
    
         
            -
                if (rc == TRILOGY_AGAIN) {
         
     | 
| 
       572 
     | 
    
         
            -
                    rc = flush_writes(ctx);
         
     | 
| 
       573 
     | 
    
         
            -
                }
         
     | 
| 
       574 
     | 
    
         
            -
             
     | 
| 
       575 
     | 
    
         
            -
                if (rc < 0) {
         
     | 
| 
       576 
     | 
    
         
            -
                    return read_query_error(args, rc, "trilogy_query_send");
         
     | 
| 
       577 
     | 
    
         
            -
                }
         
     | 
| 
       578 
     | 
    
         
            -
             
     | 
| 
       579 
609 
     | 
    
         
             
                uint64_t column_count = 0;
         
     | 
| 
       580 
610 
     | 
    
         | 
| 
      
 611 
     | 
    
         
            +
                int rc;
         
     | 
| 
      
 612 
     | 
    
         
            +
             
     | 
| 
       581 
613 
     | 
    
         
             
                while (1) {
         
     | 
| 
       582 
614 
     | 
    
         
             
                    rc = trilogy_query_recv(&ctx->conn, &column_count);
         
     | 
| 
       583 
615 
     | 
    
         | 
| 
         @@ -590,7 +622,7 @@ static VALUE execute_read_query(VALUE vargs) 
     | 
|
| 
       590 
622 
     | 
    
         
             
                    }
         
     | 
| 
       591 
623 
     | 
    
         | 
| 
       592 
624 
     | 
    
         
             
                    if (trilogy_sock_wait_read(ctx->conn.socket) < 0) {
         
     | 
| 
       593 
     | 
    
         
            -
                         
     | 
| 
      
 625 
     | 
    
         
            +
                        rb_raise(Trilogy_TimeoutError, "trilogy_query_recv");
         
     | 
| 
       594 
626 
     | 
    
         
             
                    }
         
     | 
| 
       595 
627 
     | 
    
         
             
                }
         
     | 
| 
       596 
628 
     | 
    
         | 
| 
         @@ -636,7 +668,7 @@ static VALUE execute_read_query(VALUE vargs) 
     | 
|
| 
       636 
668 
     | 
    
         
             
                        }
         
     | 
| 
       637 
669 
     | 
    
         | 
| 
       638 
670 
     | 
    
         
             
                        if (trilogy_sock_wait_read(ctx->conn.socket) < 0) {
         
     | 
| 
       639 
     | 
    
         
            -
                             
     | 
| 
      
 671 
     | 
    
         
            +
                            rb_raise(Trilogy_TimeoutError, "trilogy_read_column");
         
     | 
| 
       640 
672 
     | 
    
         
             
                        }
         
     | 
| 
       641 
673 
     | 
    
         
             
                    }
         
     | 
| 
       642 
674 
     | 
    
         | 
| 
         @@ -653,6 +685,7 @@ static VALUE execute_read_query(VALUE vargs) 
     | 
|
| 
       653 
685 
     | 
    
         
             
                    column_info[i].flags = column.flags;
         
     | 
| 
       654 
686 
     | 
    
         
             
                    column_info[i].len = column.len;
         
     | 
| 
       655 
687 
     | 
    
         
             
                    column_info[i].charset = column.charset;
         
     | 
| 
      
 688 
     | 
    
         
            +
                    column_info[i].decimals = column.decimals;
         
     | 
| 
       656 
689 
     | 
    
         
             
                }
         
     | 
| 
       657 
690 
     | 
    
         | 
| 
       658 
691 
     | 
    
         
             
                trilogy_value_t *row_values = ALLOC_N(trilogy_value_t, column_count);
         
     | 
| 
         @@ -663,7 +696,7 @@ static VALUE execute_read_query(VALUE vargs) 
     | 
|
| 
       663 
696 
     | 
    
         | 
| 
       664 
697 
     | 
    
         
             
                    if (rc == TRILOGY_AGAIN) {
         
     | 
| 
       665 
698 
     | 
    
         
             
                        if (trilogy_sock_wait_read(ctx->conn.socket) < 0) {
         
     | 
| 
       666 
     | 
    
         
            -
                             
     | 
| 
      
 699 
     | 
    
         
            +
                            rb_raise(Trilogy_TimeoutError, "trilogy_read_row");
         
     | 
| 
       667 
700 
     | 
    
         
             
                        }
         
     | 
| 
       668 
701 
     | 
    
         
             
                        continue;
         
     | 
| 
       669 
702 
     | 
    
         
             
                    }
         
     | 
| 
         @@ -689,34 +722,25 @@ static VALUE execute_read_query(VALUE vargs) 
     | 
|
| 
       689 
722 
     | 
    
         
             
                    }
         
     | 
| 
       690 
723 
     | 
    
         
             
                }
         
     | 
| 
       691 
724 
     | 
    
         | 
| 
       692 
     | 
    
         
            -
                if (ctx->conn.server_status & TRILOGY_SERVER_STATUS_MORE_RESULTS_EXISTS) {
         
     | 
| 
       693 
     | 
    
         
            -
                    rb_raise(rb_cTrilogyError, "MORE_RESULTS_EXIST");
         
     | 
| 
       694 
     | 
    
         
            -
                }
         
     | 
| 
       695 
     | 
    
         
            -
             
     | 
| 
       696 
725 
     | 
    
         
             
                return result;
         
     | 
| 
       697 
726 
     | 
    
         
             
            }
         
     | 
| 
       698 
727 
     | 
    
         | 
| 
       699 
     | 
    
         
            -
            static VALUE  
     | 
| 
      
 728 
     | 
    
         
            +
            static VALUE execute_read_query_response(struct trilogy_ctx *ctx)
         
     | 
| 
       700 
729 
     | 
    
         
             
            {
         
     | 
| 
       701 
     | 
    
         
            -
                struct trilogy_ctx *ctx = get_open_ctx(self);
         
     | 
| 
       702 
     | 
    
         
            -
             
     | 
| 
       703 
     | 
    
         
            -
                StringValue(query);
         
     | 
| 
       704 
     | 
    
         
            -
             
     | 
| 
       705 
730 
     | 
    
         
             
                struct rb_trilogy_cast_options cast_options;
         
     | 
| 
       706 
731 
     | 
    
         
             
                load_query_options(ctx->query_flags, &cast_options);
         
     | 
| 
       707 
732 
     | 
    
         | 
| 
       708 
     | 
    
         
            -
                struct  
     | 
| 
      
 733 
     | 
    
         
            +
                struct read_query_response_state args = {
         
     | 
| 
       709 
734 
     | 
    
         
             
                    .cast_options = &cast_options,
         
     | 
| 
       710 
735 
     | 
    
         
             
                    .column_info = NULL,
         
     | 
| 
       711 
736 
     | 
    
         
             
                    .ctx = ctx,
         
     | 
| 
       712 
     | 
    
         
            -
                    .query = query,
         
     | 
| 
       713 
737 
     | 
    
         
             
                    .row_values = NULL,
         
     | 
| 
       714 
738 
     | 
    
         
             
                    .rc = TRILOGY_OK,
         
     | 
| 
       715 
739 
     | 
    
         
             
                    .msg = NULL,
         
     | 
| 
       716 
740 
     | 
    
         
             
                };
         
     | 
| 
       717 
741 
     | 
    
         | 
| 
       718 
742 
     | 
    
         
             
                int state = 0;
         
     | 
| 
       719 
     | 
    
         
            -
                VALUE result = rb_protect( 
     | 
| 
      
 743 
     | 
    
         
            +
                VALUE result = rb_protect(read_query_response, (VALUE)&args, &state);
         
     | 
| 
       720 
744 
     | 
    
         | 
| 
       721 
745 
     | 
    
         
             
                xfree(args.column_info);
         
     | 
| 
       722 
746 
     | 
    
         
             
                xfree(args.row_values);
         
     | 
| 
         @@ -736,6 +760,47 @@ static VALUE rb_trilogy_query(VALUE self, VALUE query) 
     | 
|
| 
       736 
760 
     | 
    
         
             
                return result;
         
     | 
| 
       737 
761 
     | 
    
         
             
            }
         
     | 
| 
       738 
762 
     | 
    
         | 
| 
      
 763 
     | 
    
         
            +
            static VALUE rb_trilogy_next_result(VALUE self)
         
     | 
| 
      
 764 
     | 
    
         
            +
            {
         
     | 
| 
      
 765 
     | 
    
         
            +
                struct trilogy_ctx *ctx = get_open_ctx(self);
         
     | 
| 
      
 766 
     | 
    
         
            +
             
     | 
| 
      
 767 
     | 
    
         
            +
                if (!(ctx->conn.server_status & TRILOGY_SERVER_STATUS_MORE_RESULTS_EXISTS)) {
         
     | 
| 
      
 768 
     | 
    
         
            +
                    return Qnil;
         
     | 
| 
      
 769 
     | 
    
         
            +
                }
         
     | 
| 
      
 770 
     | 
    
         
            +
             
     | 
| 
      
 771 
     | 
    
         
            +
                return execute_read_query_response(ctx);
         
     | 
| 
      
 772 
     | 
    
         
            +
            }
         
     | 
| 
      
 773 
     | 
    
         
            +
             
     | 
| 
      
 774 
     | 
    
         
            +
            static VALUE rb_trilogy_more_results_exist(VALUE self)
         
     | 
| 
      
 775 
     | 
    
         
            +
            {
         
     | 
| 
      
 776 
     | 
    
         
            +
                struct trilogy_ctx *ctx = get_open_ctx(self);
         
     | 
| 
      
 777 
     | 
    
         
            +
             
     | 
| 
      
 778 
     | 
    
         
            +
                if (ctx->conn.server_status & TRILOGY_SERVER_STATUS_MORE_RESULTS_EXISTS) {
         
     | 
| 
      
 779 
     | 
    
         
            +
                    return Qtrue;
         
     | 
| 
      
 780 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 781 
     | 
    
         
            +
                    return Qfalse;
         
     | 
| 
      
 782 
     | 
    
         
            +
                }
         
     | 
| 
      
 783 
     | 
    
         
            +
            }
         
     | 
| 
      
 784 
     | 
    
         
            +
             
     | 
| 
      
 785 
     | 
    
         
            +
            static VALUE rb_trilogy_query(VALUE self, VALUE query)
         
     | 
| 
      
 786 
     | 
    
         
            +
            {
         
     | 
| 
      
 787 
     | 
    
         
            +
                struct trilogy_ctx *ctx = get_open_ctx(self);
         
     | 
| 
      
 788 
     | 
    
         
            +
             
     | 
| 
      
 789 
     | 
    
         
            +
                StringValue(query);
         
     | 
| 
      
 790 
     | 
    
         
            +
             
     | 
| 
      
 791 
     | 
    
         
            +
                int rc = trilogy_query_send(&ctx->conn, RSTRING_PTR(query), RSTRING_LEN(query));
         
     | 
| 
      
 792 
     | 
    
         
            +
             
     | 
| 
      
 793 
     | 
    
         
            +
                if (rc == TRILOGY_AGAIN) {
         
     | 
| 
      
 794 
     | 
    
         
            +
                    rc = flush_writes(ctx);
         
     | 
| 
      
 795 
     | 
    
         
            +
                }
         
     | 
| 
      
 796 
     | 
    
         
            +
             
     | 
| 
      
 797 
     | 
    
         
            +
                if (rc < 0) {
         
     | 
| 
      
 798 
     | 
    
         
            +
                    handle_trilogy_error(ctx, rc, "trilogy_query_send");
         
     | 
| 
      
 799 
     | 
    
         
            +
                }
         
     | 
| 
      
 800 
     | 
    
         
            +
             
     | 
| 
      
 801 
     | 
    
         
            +
                return execute_read_query_response(ctx);
         
     | 
| 
      
 802 
     | 
    
         
            +
            }
         
     | 
| 
      
 803 
     | 
    
         
            +
             
     | 
| 
       739 
804 
     | 
    
         
             
            static VALUE rb_trilogy_ping(VALUE self)
         
     | 
| 
       740 
805 
     | 
    
         
             
            {
         
     | 
| 
       741 
806 
     | 
    
         
             
                struct trilogy_ctx *ctx = get_open_ctx(self);
         
     | 
| 
         @@ -762,7 +827,7 @@ static VALUE rb_trilogy_ping(VALUE self) 
     | 
|
| 
       762 
827 
     | 
    
         
             
                    }
         
     | 
| 
       763 
828 
     | 
    
         | 
| 
       764 
829 
     | 
    
         
             
                    if (trilogy_sock_wait_read(ctx->conn.socket) < 0) {
         
     | 
| 
       765 
     | 
    
         
            -
                         
     | 
| 
      
 830 
     | 
    
         
            +
                        rb_raise(Trilogy_TimeoutError, "trilogy_ping_recv");
         
     | 
| 
       766 
831 
     | 
    
         
             
                    }
         
     | 
| 
       767 
832 
     | 
    
         
             
                }
         
     | 
| 
       768 
833 
     | 
    
         | 
| 
         @@ -826,6 +891,17 @@ static VALUE rb_trilogy_close(VALUE self) 
     | 
|
| 
       826 
891 
     | 
    
         
             
                return Qnil;
         
     | 
| 
       827 
892 
     | 
    
         
             
            }
         
     | 
| 
       828 
893 
     | 
    
         | 
| 
      
 894 
     | 
    
         
            +
            static VALUE rb_trilogy_closed(VALUE self)
         
     | 
| 
      
 895 
     | 
    
         
            +
            {
         
     | 
| 
      
 896 
     | 
    
         
            +
                struct trilogy_ctx *ctx = get_ctx(self);
         
     | 
| 
      
 897 
     | 
    
         
            +
             
     | 
| 
      
 898 
     | 
    
         
            +
                if (ctx->conn.socket == NULL) {
         
     | 
| 
      
 899 
     | 
    
         
            +
                    return Qtrue;
         
     | 
| 
      
 900 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 901 
     | 
    
         
            +
                    return Qfalse;
         
     | 
| 
      
 902 
     | 
    
         
            +
                }
         
     | 
| 
      
 903 
     | 
    
         
            +
            }
         
     | 
| 
      
 904 
     | 
    
         
            +
             
     | 
| 
       829 
905 
     | 
    
         
             
            static VALUE rb_trilogy_last_insert_id(VALUE self) { return ULL2NUM(get_open_ctx(self)->conn.last_insert_id); }
         
     | 
| 
       830 
906 
     | 
    
         | 
| 
       831 
907 
     | 
    
         
             
            static VALUE rb_trilogy_affected_rows(VALUE self) { return ULL2NUM(get_open_ctx(self)->conn.affected_rows); }
         
     | 
| 
         @@ -887,8 +963,7 @@ static VALUE rb_trilogy_server_version(VALUE self) { return rb_str_new_cstr(get_ 
     | 
|
| 
       887 
963 
     | 
    
         | 
| 
       888 
964 
     | 
    
         
             
            void Init_cext()
         
     | 
| 
       889 
965 
     | 
    
         
             
            {
         
     | 
| 
       890 
     | 
    
         
            -
                VALUE Trilogy =  
     | 
| 
       891 
     | 
    
         
            -
             
     | 
| 
      
 966 
     | 
    
         
            +
                VALUE Trilogy = rb_const_get(rb_cObject, rb_intern("Trilogy"));
         
     | 
| 
       892 
967 
     | 
    
         
             
                rb_define_alloc_func(Trilogy, allocate_trilogy);
         
     | 
| 
       893 
968 
     | 
    
         | 
| 
       894 
969 
     | 
    
         
             
                rb_define_method(Trilogy, "initialize", rb_trilogy_initialize, 1);
         
     | 
| 
         @@ -897,6 +972,7 @@ void Init_cext() 
     | 
|
| 
       897 
972 
     | 
    
         
             
                rb_define_method(Trilogy, "ping", rb_trilogy_ping, 0);
         
     | 
| 
       898 
973 
     | 
    
         
             
                rb_define_method(Trilogy, "escape", rb_trilogy_escape, 1);
         
     | 
| 
       899 
974 
     | 
    
         
             
                rb_define_method(Trilogy, "close", rb_trilogy_close, 0);
         
     | 
| 
      
 975 
     | 
    
         
            +
                rb_define_method(Trilogy, "closed?", rb_trilogy_closed, 0);
         
     | 
| 
       900 
976 
     | 
    
         
             
                rb_define_method(Trilogy, "last_insert_id", rb_trilogy_last_insert_id, 0);
         
     | 
| 
       901 
977 
     | 
    
         
             
                rb_define_method(Trilogy, "affected_rows", rb_trilogy_affected_rows, 0);
         
     | 
| 
       902 
978 
     | 
    
         
             
                rb_define_method(Trilogy, "warning_count", rb_trilogy_warning_count, 0);
         
     | 
| 
         @@ -909,6 +985,8 @@ void Init_cext() 
     | 
|
| 
       909 
985 
     | 
    
         
             
                rb_define_method(Trilogy, "write_timeout=", rb_trilogy_write_timeout_set, 1);
         
     | 
| 
       910 
986 
     | 
    
         
             
                rb_define_method(Trilogy, "server_status", rb_trilogy_server_status, 0);
         
     | 
| 
       911 
987 
     | 
    
         
             
                rb_define_method(Trilogy, "server_version", rb_trilogy_server_version, 0);
         
     | 
| 
      
 988 
     | 
    
         
            +
                rb_define_method(Trilogy, "more_results_exist?", rb_trilogy_more_results_exist, 0);
         
     | 
| 
      
 989 
     | 
    
         
            +
                rb_define_method(Trilogy, "next_result", rb_trilogy_next_result, 0);
         
     | 
| 
       912 
990 
     | 
    
         
             
                rb_define_const(Trilogy, "TLS_VERSION_10", INT2NUM(TRILOGY_TLS_VERSION_10));
         
     | 
| 
       913 
991 
     | 
    
         
             
                rb_define_const(Trilogy, "TLS_VERSION_11", INT2NUM(TRILOGY_TLS_VERSION_11));
         
     | 
| 
       914 
992 
     | 
    
         
             
                rb_define_const(Trilogy, "TLS_VERSION_12", INT2NUM(TRILOGY_TLS_VERSION_12));
         
     | 
| 
         @@ -927,23 +1005,32 @@ void Init_cext() 
     | 
|
| 
       927 
1005 
     | 
    
         
             
                rb_define_const(Trilogy, "QUERY_FLAGS_FLATTEN_ROWS", INT2NUM(TRILOGY_FLAGS_FLATTEN_ROWS));
         
     | 
| 
       928 
1006 
     | 
    
         
             
                rb_define_const(Trilogy, "QUERY_FLAGS_DEFAULT", INT2NUM(TRILOGY_FLAGS_DEFAULT));
         
     | 
| 
       929 
1007 
     | 
    
         | 
| 
       930 
     | 
    
         
            -
                 
     | 
| 
       931 
     | 
    
         
            -
                rb_global_variable(& 
     | 
| 
      
 1008 
     | 
    
         
            +
                Trilogy_ProtocolError = rb_const_get(Trilogy, rb_intern("ProtocolError"));
         
     | 
| 
      
 1009 
     | 
    
         
            +
                rb_global_variable(&Trilogy_ProtocolError);
         
     | 
| 
      
 1010 
     | 
    
         
            +
             
     | 
| 
      
 1011 
     | 
    
         
            +
                Trilogy_SSLError = rb_const_get(Trilogy, rb_intern("SSLError"));
         
     | 
| 
      
 1012 
     | 
    
         
            +
                rb_global_variable(&Trilogy_SSLError);
         
     | 
| 
      
 1013 
     | 
    
         
            +
             
     | 
| 
      
 1014 
     | 
    
         
            +
                Trilogy_QueryError = rb_const_get(Trilogy, rb_intern("QueryError"));
         
     | 
| 
      
 1015 
     | 
    
         
            +
                rb_global_variable(&Trilogy_QueryError);
         
     | 
| 
       932 
1016 
     | 
    
         | 
| 
       933 
     | 
    
         
            -
                 
     | 
| 
       934 
     | 
    
         
            -
                rb_global_variable(& 
     | 
| 
      
 1017 
     | 
    
         
            +
                Trilogy_TimeoutError = rb_const_get(Trilogy, rb_intern("TimeoutError"));
         
     | 
| 
      
 1018 
     | 
    
         
            +
                rb_global_variable(&Trilogy_TimeoutError);
         
     | 
| 
       935 
1019 
     | 
    
         | 
| 
       936 
     | 
    
         
            -
                 
     | 
| 
       937 
     | 
    
         
            -
                 
     | 
| 
      
 1020 
     | 
    
         
            +
                Trilogy_BaseConnectionError = rb_const_get(Trilogy, rb_intern("BaseConnectionError"));
         
     | 
| 
      
 1021 
     | 
    
         
            +
                rb_global_variable(&Trilogy_BaseConnectionError);
         
     | 
| 
       938 
1022 
     | 
    
         | 
| 
       939 
     | 
    
         
            -
                 
     | 
| 
      
 1023 
     | 
    
         
            +
                Trilogy_ConnectionClosedError = rb_const_get(Trilogy, rb_intern("ConnectionClosed"));
         
     | 
| 
      
 1024 
     | 
    
         
            +
                rb_global_variable(&Trilogy_ConnectionClosedError);
         
     | 
| 
      
 1025 
     | 
    
         
            +
             
     | 
| 
      
 1026 
     | 
    
         
            +
                Trilogy_Result = rb_const_get(Trilogy, rb_intern("Result"));
         
     | 
| 
       940 
1027 
     | 
    
         
             
                rb_global_variable(&Trilogy_Result);
         
     | 
| 
       941 
1028 
     | 
    
         | 
| 
      
 1029 
     | 
    
         
            +
                Trilogy_CastError = rb_const_get(Trilogy, rb_intern("CastError"));
         
     | 
| 
      
 1030 
     | 
    
         
            +
                rb_global_variable(&Trilogy_CastError);
         
     | 
| 
      
 1031 
     | 
    
         
            +
             
     | 
| 
       942 
1032 
     | 
    
         
             
                rb_define_attr(Trilogy_Result, "affected_rows", 1, 0);
         
     | 
| 
       943 
     | 
    
         
            -
                rb_define_attr(Trilogy_Result, "fields", 1, 0);
         
     | 
| 
       944 
1033 
     | 
    
         
             
                rb_define_attr(Trilogy_Result, "last_insert_id", 1, 0);
         
     | 
| 
       945 
     | 
    
         
            -
                rb_define_attr(Trilogy_Result, "rows", 1, 0);
         
     | 
| 
       946 
     | 
    
         
            -
                rb_define_attr(Trilogy_Result, "query_time", 1, 0);
         
     | 
| 
       947 
1034 
     | 
    
         | 
| 
       948 
1035 
     | 
    
         
             
                id_socket = rb_intern("socket");
         
     | 
| 
       949 
1036 
     | 
    
         
             
                id_host = rb_intern("host");
         
     | 
| 
         @@ -970,12 +1057,14 @@ void Init_cext() 
     | 
|
| 
       970 
1057 
     | 
    
         
             
                id_tls_ciphersuites = rb_intern("tls_ciphersuites");
         
     | 
| 
       971 
1058 
     | 
    
         
             
                id_tls_min_version = rb_intern("tls_min_version");
         
     | 
| 
       972 
1059 
     | 
    
         
             
                id_tls_max_version = rb_intern("tls_max_version");
         
     | 
| 
       973 
     | 
    
         
            -
             
     | 
| 
      
 1060 
     | 
    
         
            +
                id_multi_statement = rb_intern("multi_statement");
         
     | 
| 
      
 1061 
     | 
    
         
            +
                id_from_code = rb_intern("from_code");
         
     | 
| 
       974 
1062 
     | 
    
         
             
                id_ivar_affected_rows = rb_intern("@affected_rows");
         
     | 
| 
       975 
1063 
     | 
    
         
             
                id_ivar_fields = rb_intern("@fields");
         
     | 
| 
       976 
1064 
     | 
    
         
             
                id_ivar_last_insert_id = rb_intern("@last_insert_id");
         
     | 
| 
       977 
1065 
     | 
    
         
             
                id_ivar_rows = rb_intern("@rows");
         
     | 
| 
       978 
1066 
     | 
    
         
             
                id_ivar_query_time = rb_intern("@query_time");
         
     | 
| 
      
 1067 
     | 
    
         
            +
                id_connection_options = rb_intern("@connection_options");
         
     | 
| 
       979 
1068 
     | 
    
         | 
| 
       980 
1069 
     | 
    
         
             
                rb_trilogy_cast_init();
         
     | 
| 
       981 
1070 
     | 
    
         | 
| 
         @@ -121,9 +121,7 @@ 
     | 
|
| 
       121 
121 
     | 
    
         
             
                 * query/ prepared statement.                                                                                      \
         
     | 
| 
       122 
122 
     | 
    
         
             
                 */                                                                                                                \
         
     | 
| 
       123 
123 
     | 
    
         
             
                XX(TRILOGY_CAPABILITIES_MULTI_STATEMENTS, 0x00010000)                                                              \
         
     | 
| 
       124 
     | 
    
         
            -
                /*  
     | 
| 
       125 
     | 
    
         
            -
                 *                                                                                                                 \
         
     | 
| 
       126 
     | 
    
         
            -
                 * From server: the server is capable of sending multiple result sets from                                         \
         
     | 
| 
      
 124 
     | 
    
         
            +
                /* From server: the server is capable of sending multiple result sets from                                         \
         
     | 
| 
       127 
125 
     | 
    
         
             
                 * a query.                                                                                                        \
         
     | 
| 
       128 
126 
     | 
    
         
             
                 *                                                                                                                 \
         
     | 
| 
       129 
127 
     | 
    
         
             
                 * From client: tells the server it's capable of handling multiple result                                          \
         
     | 
| 
         @@ -23,9 +23,10 @@ struct column_info { 
     | 
|
| 
       23 
23 
     | 
    
         
             
                TRILOGY_CHARSET_t charset;
         
     | 
| 
       24 
24 
     | 
    
         
             
                uint32_t len;
         
     | 
| 
       25 
25 
     | 
    
         
             
                uint16_t flags;
         
     | 
| 
      
 26 
     | 
    
         
            +
                uint8_t decimals;
         
     | 
| 
       26 
27 
     | 
    
         
             
            };
         
     | 
| 
       27 
28 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
            extern VALUE  
     | 
| 
      
 29 
     | 
    
         
            +
            extern VALUE Trilogy_CastError;
         
     | 
| 
       29 
30 
     | 
    
         | 
| 
       30 
31 
     | 
    
         
             
            VALUE
         
     | 
| 
       31 
32 
     | 
    
         
             
            rb_trilogy_cast_value(const trilogy_value_t *value, const struct column_info *column,
         
     | 
    
        data/lib/trilogy/version.rb
    CHANGED
    
    
    
        data/lib/trilogy.rb
    CHANGED
    
    | 
         @@ -1,7 +1,101 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require "trilogy/cext"
         
     | 
| 
       2 
1 
     | 
    
         
             
            require "trilogy/version"
         
     | 
| 
       3 
2 
     | 
    
         | 
| 
       4 
3 
     | 
    
         
             
            class Trilogy
         
     | 
| 
      
 4 
     | 
    
         
            +
              # Trilogy::Error is the base error type. All errors raised by Trilogy
         
     | 
| 
      
 5 
     | 
    
         
            +
              # should be descendants of Trilogy::Error
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Error
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              # Trilogy::ConnectionError is the base error type for all potentially transient
         
     | 
| 
      
 10 
     | 
    
         
            +
              # network errors.
         
     | 
| 
      
 11 
     | 
    
         
            +
              module ConnectionError
         
     | 
| 
      
 12 
     | 
    
         
            +
                include Error
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              class BaseError < StandardError
         
     | 
| 
      
 16 
     | 
    
         
            +
                include Error
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                attr_reader :error_code
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def initialize(error_message = nil, error_code = nil)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  message = error_code ? "#{error_code}: #{error_message}" : error_message
         
     | 
| 
      
 22 
     | 
    
         
            +
                  super(message)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @error_code = error_code
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              class BaseConnectionError < BaseError
         
     | 
| 
      
 28 
     | 
    
         
            +
                include ConnectionError
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              # Trilogy::ClientError is the base error type for invalid queries or parameters
         
     | 
| 
      
 32 
     | 
    
         
            +
              # that shouldn't be retried.
         
     | 
| 
      
 33 
     | 
    
         
            +
              class ClientError < BaseError
         
     | 
| 
      
 34 
     | 
    
         
            +
                include Error
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
              class QueryError < ClientError
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              class CastError < ClientError
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
              class TimeoutError < Errno::ETIMEDOUT
         
     | 
| 
      
 44 
     | 
    
         
            +
                include ConnectionError
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                attr_reader :error_code
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                def initialize(error_message = nil, error_code = nil)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  super
         
     | 
| 
      
 50 
     | 
    
         
            +
                  @error_code = error_code
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
              # DatabaseError was replaced by ProtocolError, but we'll keep it around as an
         
     | 
| 
      
 55 
     | 
    
         
            +
              # ancestor of ProtocolError for compatibility reasons (e.g. so `rescue DatabaseError`
         
     | 
| 
      
 56 
     | 
    
         
            +
              # still works. We can remove this class in the next major release.
         
     | 
| 
      
 57 
     | 
    
         
            +
              module DatabaseError
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
              class ProtocolError < BaseError
         
     | 
| 
      
 61 
     | 
    
         
            +
                include DatabaseError
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                ERROR_CODES = {
         
     | 
| 
      
 64 
     | 
    
         
            +
                  1205 => TimeoutError, # ER_LOCK_WAIT_TIMEOUT
         
     | 
| 
      
 65 
     | 
    
         
            +
                  1044 => BaseConnectionError, # ER_DBACCESS_DENIED_ERROR
         
     | 
| 
      
 66 
     | 
    
         
            +
                  1045 => BaseConnectionError, # ER_ACCESS_DENIED_ERROR
         
     | 
| 
      
 67 
     | 
    
         
            +
                  1064 => QueryError, # ER_PARSE_ERROR
         
     | 
| 
      
 68 
     | 
    
         
            +
                  1152 => BaseConnectionError, # ER_ABORTING_CONNECTION
         
     | 
| 
      
 69 
     | 
    
         
            +
                  1153 => BaseConnectionError, # ER_NET_PACKET_TOO_LARGE
         
     | 
| 
      
 70 
     | 
    
         
            +
                  1154 => BaseConnectionError, # ER_NET_READ_ERROR_FROM_PIPE
         
     | 
| 
      
 71 
     | 
    
         
            +
                  1155 => BaseConnectionError, # ER_NET_FCNTL_ERROR
         
     | 
| 
      
 72 
     | 
    
         
            +
                  1156 => BaseConnectionError, # ER_NET_PACKETS_OUT_OF_ORDER
         
     | 
| 
      
 73 
     | 
    
         
            +
                  1157 => BaseConnectionError, # ER_NET_UNCOMPRESS_ERROR
         
     | 
| 
      
 74 
     | 
    
         
            +
                  1158 => BaseConnectionError, # ER_NET_READ_ERROR
         
     | 
| 
      
 75 
     | 
    
         
            +
                  1159 => BaseConnectionError, # ER_NET_READ_INTERRUPTED
         
     | 
| 
      
 76 
     | 
    
         
            +
                  1160 => BaseConnectionError, # ER_NET_ERROR_ON_WRITE
         
     | 
| 
      
 77 
     | 
    
         
            +
                  1161 => BaseConnectionError, # ER_NET_WRITE_INTERRUPTED
         
     | 
| 
      
 78 
     | 
    
         
            +
                  1927 => BaseConnectionError, # ER_CONNECTION_KILLED
         
     | 
| 
      
 79 
     | 
    
         
            +
                }
         
     | 
| 
      
 80 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 81 
     | 
    
         
            +
                  def from_code(message, code)
         
     | 
| 
      
 82 
     | 
    
         
            +
                    ERROR_CODES.fetch(code, self).new(message, code)
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
              end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
              class SSLError < BaseError
         
     | 
| 
      
 88 
     | 
    
         
            +
                include ConnectionError
         
     | 
| 
      
 89 
     | 
    
         
            +
              end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
              class ConnectionClosed < IOError
         
     | 
| 
      
 92 
     | 
    
         
            +
                include ConnectionError
         
     | 
| 
      
 93 
     | 
    
         
            +
              end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
              def connection_options
         
     | 
| 
      
 96 
     | 
    
         
            +
                @connection_options.dup.freeze
         
     | 
| 
      
 97 
     | 
    
         
            +
              end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
       5 
99 
     | 
    
         
             
              def in_transaction?
         
     | 
| 
       6 
100 
     | 
    
         
             
                (server_status & SERVER_STATUS_IN_TRANS) != 0
         
     | 
| 
       7 
101 
     | 
    
         
             
              end
         
     | 
| 
         @@ -28,34 +122,38 @@ class Trilogy 
     | 
|
| 
       28 
122 
     | 
    
         
             
              ensure
         
     | 
| 
       29 
123 
     | 
    
         
             
                self.query_flags = old_flags
         
     | 
| 
       30 
124 
     | 
    
         
             
              end
         
     | 
| 
       31 
     | 
    
         
            -
            end
         
     | 
| 
       32 
125 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
      
 126 
     | 
    
         
            +
              class Result
         
     | 
| 
      
 127 
     | 
    
         
            +
                attr_reader :fields, :rows, :query_time
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                def count
         
     | 
| 
      
 130 
     | 
    
         
            +
                  rows.count
         
     | 
| 
      
 131 
     | 
    
         
            +
                end
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                def each_hash
         
     | 
| 
      
 134 
     | 
    
         
            +
                  return enum_for(:each_hash) unless block_given?
         
     | 
| 
       37 
135 
     | 
    
         | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
      
 136 
     | 
    
         
            +
                  rows.each do |row|
         
     | 
| 
      
 137 
     | 
    
         
            +
                    this_row = {}
         
     | 
| 
       40 
138 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
      
 139 
     | 
    
         
            +
                    idx = 0
         
     | 
| 
      
 140 
     | 
    
         
            +
                    row.each do |col|
         
     | 
| 
      
 141 
     | 
    
         
            +
                      this_row[fields[idx]] = col
         
     | 
| 
      
 142 
     | 
    
         
            +
                      idx += 1
         
     | 
| 
      
 143 
     | 
    
         
            +
                    end
         
     | 
| 
       43 
144 
     | 
    
         | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
                  row.each do |col|
         
     | 
| 
       46 
     | 
    
         
            -
                    this_row[fields[idx]] = col
         
     | 
| 
       47 
     | 
    
         
            -
                    idx += 1
         
     | 
| 
      
 145 
     | 
    
         
            +
                    yield this_row
         
     | 
| 
       48 
146 
     | 
    
         
             
                  end
         
     | 
| 
       49 
147 
     | 
    
         | 
| 
       50 
     | 
    
         
            -
                   
     | 
| 
      
 148 
     | 
    
         
            +
                  self
         
     | 
| 
       51 
149 
     | 
    
         
             
                end
         
     | 
| 
       52 
150 
     | 
    
         | 
| 
       53 
     | 
    
         
            -
                 
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
      
 151 
     | 
    
         
            +
                def each(&bk)
         
     | 
| 
      
 152 
     | 
    
         
            +
                  rows.each(&bk)
         
     | 
| 
      
 153 
     | 
    
         
            +
                end
         
     | 
| 
       55 
154 
     | 
    
         | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
                rows.each(&bk)
         
     | 
| 
      
 155 
     | 
    
         
            +
                include Enumerable
         
     | 
| 
       58 
156 
     | 
    
         
             
              end
         
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
              include Enumerable
         
     | 
| 
       61 
157 
     | 
    
         
             
            end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
            require "trilogy/cext"
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: trilogy
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 2. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 2.3.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - GitHub Engineering
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire:
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date:  
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2023-03-02 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: rake-compiler
         
     | 
| 
         @@ -99,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       99 
99 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       100 
100 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       101 
101 
     | 
    
         
             
            requirements: []
         
     | 
| 
       102 
     | 
    
         
            -
            rubygems_version: 3. 
     | 
| 
      
 102 
     | 
    
         
            +
            rubygems_version: 3.4.7
         
     | 
| 
       103 
103 
     | 
    
         
             
            signing_key:
         
     | 
| 
       104 
104 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       105 
105 
     | 
    
         
             
            summary: A friendly MySQL-compatible library for Ruby, binding to libtrilogy
         
     |