pg 1.1.4 → 1.2.3
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
 - checksums.yaml.gz.sig +0 -0
 - data.tar.gz.sig +0 -0
 - data/ChangeLog +0 -6595
 - data/History.rdoc +86 -0
 - data/Manifest.txt +3 -2
 - data/README-Windows.rdoc +4 -4
 - data/README.ja.rdoc +1 -2
 - data/README.rdoc +44 -9
 - data/Rakefile +8 -6
 - data/Rakefile.cross +57 -56
 - data/ext/errorcodes.def +64 -0
 - data/ext/errorcodes.txt +18 -2
 - data/ext/extconf.rb +6 -6
 - data/ext/pg.c +132 -95
 - data/ext/pg.h +21 -18
 - data/ext/pg_binary_decoder.c +9 -9
 - data/ext/pg_binary_encoder.c +13 -12
 - data/ext/pg_coder.c +21 -9
 - data/ext/pg_connection.c +388 -298
 - data/ext/pg_copy_coder.c +6 -3
 - data/ext/pg_record_coder.c +491 -0
 - data/ext/pg_result.c +279 -127
 - data/ext/pg_text_decoder.c +14 -8
 - data/ext/pg_text_encoder.c +180 -48
 - data/ext/pg_tuple.c +14 -6
 - data/ext/pg_type_map.c +1 -1
 - data/ext/pg_type_map_all_strings.c +4 -4
 - data/ext/pg_type_map_by_class.c +9 -4
 - data/ext/pg_type_map_by_column.c +7 -6
 - data/ext/pg_type_map_by_mri_type.c +1 -1
 - data/ext/pg_type_map_by_oid.c +3 -2
 - data/ext/pg_type_map_in_ruby.c +1 -1
 - data/ext/{util.c → pg_util.c} +5 -5
 - data/ext/{util.h → pg_util.h} +0 -0
 - data/lib/pg.rb +4 -4
 - data/lib/pg/basic_type_mapping.rb +81 -18
 - data/lib/pg/binary_decoder.rb +1 -0
 - data/lib/pg/coder.rb +22 -1
 - data/lib/pg/connection.rb +2 -2
 - data/lib/pg/constants.rb +1 -0
 - data/lib/pg/exceptions.rb +1 -0
 - data/lib/pg/result.rb +13 -1
 - data/lib/pg/text_decoder.rb +2 -3
 - data/lib/pg/text_encoder.rb +8 -18
 - data/lib/pg/type_map_by_column.rb +2 -1
 - data/spec/helpers.rb +11 -11
 - data/spec/pg/basic_type_mapping_spec.rb +140 -18
 - data/spec/pg/connection_spec.rb +166 -89
 - data/spec/pg/result_spec.rb +194 -4
 - data/spec/pg/tuple_spec.rb +55 -2
 - data/spec/pg/type_map_by_class_spec.rb +1 -1
 - data/spec/pg/type_map_by_column_spec.rb +5 -1
 - data/spec/pg/type_map_by_oid_spec.rb +2 -2
 - data/spec/pg/type_spec.rb +180 -6
 - metadata +31 -30
 - metadata.gz.sig +0 -0
 
    
        data/ext/pg_text_decoder.c
    CHANGED
    
    | 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            /*
         
     | 
| 
       2 
2 
     | 
    
         
             
             * pg_text_decoder.c - PG::TextDecoder module
         
     | 
| 
       3 
     | 
    
         
            -
             * $Id 
     | 
| 
      
 3 
     | 
    
         
            +
             * $Id$
         
     | 
| 
       4 
4 
     | 
    
         
             
             *
         
     | 
| 
       5 
5 
     | 
    
         
             
             */
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
         @@ -30,7 +30,7 @@ 
     | 
|
| 
       30 
30 
     | 
    
         | 
| 
       31 
31 
     | 
    
         
             
            #include "ruby/version.h"
         
     | 
| 
       32 
32 
     | 
    
         
             
            #include "pg.h"
         
     | 
| 
       33 
     | 
    
         
            -
            #include " 
     | 
| 
      
 33 
     | 
    
         
            +
            #include "pg_util.h"
         
     | 
| 
       34 
34 
     | 
    
         
             
            #ifdef HAVE_INTTYPES_H
         
     | 
| 
       35 
35 
     | 
    
         
             
            #include <inttypes.h>
         
     | 
| 
       36 
36 
     | 
    
         
             
            #endif
         
     | 
| 
         @@ -89,7 +89,7 @@ pg_text_dec_boolean(t_pg_coder *conv, const char *val, int len, int tuple, int f 
     | 
|
| 
       89 
89 
     | 
    
         
             
            VALUE
         
     | 
| 
       90 
90 
     | 
    
         
             
            pg_text_dec_string(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
         
     | 
| 
       91 
91 
     | 
    
         
             
            {
         
     | 
| 
       92 
     | 
    
         
            -
            	VALUE ret =  
     | 
| 
      
 92 
     | 
    
         
            +
            	VALUE ret = rb_str_new( val, len );
         
     | 
| 
       93 
93 
     | 
    
         
             
            	PG_ENCODING_SET_NOCHECK( ret, enc_idx );
         
     | 
| 
       94 
94 
     | 
    
         
             
            	return ret;
         
     | 
| 
       95 
95 
     | 
    
         
             
            }
         
     | 
| 
         @@ -204,7 +204,12 @@ struct pg_blob_initialization { 
     | 
|
| 
       204 
204 
     | 
    
         | 
| 
       205 
205 
     | 
    
         
             
            static VALUE pg_create_blob(VALUE v) {
         
     | 
| 
       206 
206 
     | 
    
         
             
            	struct pg_blob_initialization *bi = (struct pg_blob_initialization *)v;
         
     | 
| 
       207 
     | 
    
         
            -
            	return  
     | 
| 
      
 207 
     | 
    
         
            +
            	return rb_str_new(bi->blob_string, bi->length);
         
     | 
| 
      
 208 
     | 
    
         
            +
            }
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
      
 210 
     | 
    
         
            +
            static VALUE pg_pq_freemem(VALUE mem) {
         
     | 
| 
      
 211 
     | 
    
         
            +
              PQfreemem((void *)mem);
         
     | 
| 
      
 212 
     | 
    
         
            +
              return Qfalse;
         
     | 
| 
       208 
213 
     | 
    
         
             
            }
         
     | 
| 
       209 
214 
     | 
    
         | 
| 
       210 
215 
     | 
    
         
             
            /*
         
     | 
| 
         @@ -223,7 +228,7 @@ pg_text_dec_bytea(t_pg_coder *conv, const char *val, int len, int tuple, int fie 
     | 
|
| 
       223 
228 
     | 
    
         
             
            	if (bi.blob_string == NULL) {
         
     | 
| 
       224 
229 
     | 
    
         
             
            		rb_raise(rb_eNoMemError, "PQunescapeBytea failure: probably not enough memory");
         
     | 
| 
       225 
230 
     | 
    
         
             
            	}
         
     | 
| 
       226 
     | 
    
         
            -
            	return rb_ensure(pg_create_blob, (VALUE)&bi,  
     | 
| 
      
 231 
     | 
    
         
            +
            	return rb_ensure(pg_create_blob, (VALUE)&bi, pg_pq_freemem, (VALUE)bi.blob_string);
         
     | 
| 
       227 
232 
     | 
    
         
             
            }
         
     | 
| 
       228 
233 
     | 
    
         | 
| 
       229 
234 
     | 
    
         
             
            /*
         
     | 
| 
         @@ -558,7 +563,7 @@ pg_text_dec_from_base64(t_pg_coder *conv, const char *val, int len, int tuple, i 
     | 
|
| 
       558 
563 
     | 
    
         
             
            	t_pg_coder_dec_func dec_func = pg_coder_dec_func(this->elem, this->comp.format);
         
     | 
| 
       559 
564 
     | 
    
         
             
            	int decoded_len;
         
     | 
| 
       560 
565 
     | 
    
         
             
            	/* create a buffer of the expected decoded length */
         
     | 
| 
       561 
     | 
    
         
            -
            	VALUE out_value =  
     | 
| 
      
 566 
     | 
    
         
            +
            	VALUE out_value = rb_str_new(NULL, BASE64_DECODED_SIZE(len));
         
     | 
| 
       562 
567 
     | 
    
         | 
| 
       563 
568 
     | 
    
         
             
            	decoded_len = base64_decode( RSTRING_PTR(out_value), val, len );
         
     | 
| 
       564 
569 
     | 
    
         
             
            	rb_str_set_len(out_value, decoded_len);
         
     | 
| 
         @@ -610,7 +615,7 @@ static int parse_year(const char **str) { 
     | 
|
| 
       610 
615 
     | 
    
         
             
             * This is a decoder class for conversion of PostgreSQL text timestamps
         
     | 
| 
       611 
616 
     | 
    
         
             
             * to Ruby Time objects.
         
     | 
| 
       612 
617 
     | 
    
         
             
             *
         
     | 
| 
       613 
     | 
    
         
            -
             * The following flags can be used to specify timezone  
     | 
| 
      
 618 
     | 
    
         
            +
             * The following flags can be used to specify time interpretation when no timezone is given:
         
     | 
| 
       614 
619 
     | 
    
         
             
             * * +PG::Coder::TIMESTAMP_DB_UTC+ : Interpret timestamp as UTC time (default)
         
     | 
| 
       615 
620 
     | 
    
         
             
             * * +PG::Coder::TIMESTAMP_DB_LOCAL+ : Interpret timestamp as local time
         
     | 
| 
       616 
621 
     | 
    
         
             
             * * +PG::Coder::TIMESTAMP_APP_UTC+ : Return timestamp as UTC time (default)
         
     | 
| 
         @@ -619,6 +624,7 @@ static int parse_year(const char **str) { 
     | 
|
| 
       619 
624 
     | 
    
         
             
             * Example:
         
     | 
| 
       620 
625 
     | 
    
         
             
             *   deco = PG::TextDecoder::Timestamp.new(flags: PG::Coder::TIMESTAMP_DB_UTC | PG::Coder::TIMESTAMP_APP_LOCAL)
         
     | 
| 
       621 
626 
     | 
    
         
             
             *   deco.decode("2000-01-01 00:00:00")  # => 2000-01-01 01:00:00 +0100
         
     | 
| 
      
 627 
     | 
    
         
            +
             *   deco.decode("2000-01-01 00:00:00.123-06")  # => 2000-01-01 00:00:00 -0600
         
     | 
| 
       622 
628 
     | 
    
         
             
             */
         
     | 
| 
       623 
629 
     | 
    
         
             
            static VALUE pg_text_dec_timestamp(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
         
     | 
| 
       624 
630 
     | 
    
         
             
            {
         
     | 
| 
         @@ -961,7 +967,7 @@ init_pg_text_decoder() 
     | 
|
| 
       961 
967 
     | 
    
         
             
            	pg_define_coder( "Integer", pg_text_dec_integer, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder );
         
     | 
| 
       962 
968 
     | 
    
         
             
            	/* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Float", rb_cPG_SimpleDecoder ); */
         
     | 
| 
       963 
969 
     | 
    
         
             
            	pg_define_coder( "Float", pg_text_dec_float, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder );
         
     | 
| 
       964 
     | 
    
         
            -
            	/* dummy = rb_define_class_under( rb_mPG_TextDecoder, " 
     | 
| 
      
 970 
     | 
    
         
            +
            	/* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Numeric", rb_cPG_SimpleDecoder ); */
         
     | 
| 
       965 
971 
     | 
    
         
             
            	pg_define_coder( "Numeric", pg_text_dec_numeric, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder );
         
     | 
| 
       966 
972 
     | 
    
         
             
            	/* dummy = rb_define_class_under( rb_mPG_TextDecoder, "String", rb_cPG_SimpleDecoder ); */
         
     | 
| 
       967 
973 
     | 
    
         
             
            	pg_define_coder( "String", pg_text_dec_string, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder );
         
     | 
    
        data/ext/pg_text_encoder.c
    CHANGED
    
    | 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            /*
         
     | 
| 
       2 
2 
     | 
    
         
             
             * pg_text_encoder.c - PG::TextEncoder module
         
     | 
| 
       3 
     | 
    
         
            -
             * $Id 
     | 
| 
      
 3 
     | 
    
         
            +
             * $Id$
         
     | 
| 
       4 
4 
     | 
    
         
             
             *
         
     | 
| 
       5 
5 
     | 
    
         
             
             */
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
         @@ -41,7 +41,7 @@ 
     | 
|
| 
       41 
41 
     | 
    
         | 
| 
       42 
42 
     | 
    
         | 
| 
       43 
43 
     | 
    
         
             
            #include "pg.h"
         
     | 
| 
       44 
     | 
    
         
            -
            #include " 
     | 
| 
      
 44 
     | 
    
         
            +
            #include "pg_util.h"
         
     | 
| 
       45 
45 
     | 
    
         
             
            #ifdef HAVE_INTTYPES_H
         
     | 
| 
       46 
46 
     | 
    
         
             
            #include <inttypes.h>
         
     | 
| 
       47 
47 
     | 
    
         
             
            #endif
         
     | 
| 
         @@ -50,6 +50,9 @@ 
     | 
|
| 
       50 
50 
     | 
    
         
             
            VALUE rb_mPG_TextEncoder;
         
     | 
| 
       51 
51 
     | 
    
         
             
            static ID s_id_encode;
         
     | 
| 
       52 
52 
     | 
    
         
             
            static ID s_id_to_i;
         
     | 
| 
      
 53 
     | 
    
         
            +
            static ID s_id_to_s;
         
     | 
| 
      
 54 
     | 
    
         
            +
            static ID s_cBigDecimal;
         
     | 
| 
      
 55 
     | 
    
         
            +
            static VALUE s_str_F;
         
     | 
| 
       53 
56 
     | 
    
         | 
| 
       54 
57 
     | 
    
         
             
            static int pg_text_enc_integer(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx);
         
     | 
| 
       55 
58 
     | 
    
         | 
| 
         @@ -125,11 +128,29 @@ pg_coder_enc_to_s(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, 
     | 
|
| 
       125 
128 
     | 
    
         
             
            	return -1;
         
     | 
| 
       126 
129 
     | 
    
         
             
            }
         
     | 
| 
       127 
130 
     | 
    
         | 
| 
      
 131 
     | 
    
         
            +
            static int
         
     | 
| 
      
 132 
     | 
    
         
            +
            count_leading_zero_bits(unsigned long long x)
         
     | 
| 
      
 133 
     | 
    
         
            +
            {
         
     | 
| 
      
 134 
     | 
    
         
            +
            #if defined(__GNUC__) || defined(__clang__)
         
     | 
| 
      
 135 
     | 
    
         
            +
            	return __builtin_clzll(x);
         
     | 
| 
      
 136 
     | 
    
         
            +
            #elif defined(_MSC_VER)
         
     | 
| 
      
 137 
     | 
    
         
            +
            	DWORD r = 0;
         
     | 
| 
      
 138 
     | 
    
         
            +
            	_BitScanForward64(&r, x);
         
     | 
| 
      
 139 
     | 
    
         
            +
            	return (int)r;
         
     | 
| 
      
 140 
     | 
    
         
            +
            #else
         
     | 
| 
      
 141 
     | 
    
         
            +
            	unsigned int a;
         
     | 
| 
      
 142 
     | 
    
         
            +
            	for(a=0; a < sizeof(unsigned long long) * 8; a++){
         
     | 
| 
      
 143 
     | 
    
         
            +
            		if( x & (1 << (sizeof(unsigned long long) * 8 - 1))) return a;
         
     | 
| 
      
 144 
     | 
    
         
            +
            		x <<= 1;
         
     | 
| 
      
 145 
     | 
    
         
            +
            	}
         
     | 
| 
      
 146 
     | 
    
         
            +
            	return a;
         
     | 
| 
      
 147 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 148 
     | 
    
         
            +
            }
         
     | 
| 
       128 
149 
     | 
    
         | 
| 
       129 
150 
     | 
    
         
             
            /*
         
     | 
| 
       130 
151 
     | 
    
         
             
             * Document-class: PG::TextEncoder::Integer < PG::SimpleEncoder
         
     | 
| 
       131 
152 
     | 
    
         
             
             *
         
     | 
| 
       132 
     | 
    
         
            -
             * This is the encoder class for the PostgreSQL  
     | 
| 
      
 153 
     | 
    
         
            +
             * This is the encoder class for the PostgreSQL integer types.
         
     | 
| 
       133 
154 
     | 
    
         
             
             *
         
     | 
| 
       134 
155 
     | 
    
         
             
             * Non-Integer values are expected to have method +to_i+ defined.
         
     | 
| 
       135 
156 
     | 
    
         
             
             *
         
     | 
| 
         @@ -144,20 +165,23 @@ pg_text_enc_integer(t_pg_coder *this, VALUE value, char *out, VALUE *intermediat 
     | 
|
| 
       144 
165 
     | 
    
         
             
            			char *start = out;
         
     | 
| 
       145 
166 
     | 
    
         
             
            			int len;
         
     | 
| 
       146 
167 
     | 
    
         
             
            			int neg = 0;
         
     | 
| 
       147 
     | 
    
         
            -
            			long long  
     | 
| 
      
 168 
     | 
    
         
            +
            			long long sll = NUM2LL(*intermediate);
         
     | 
| 
      
 169 
     | 
    
         
            +
            			unsigned long long ll;
         
     | 
| 
       148 
170 
     | 
    
         | 
| 
       149 
     | 
    
         
            -
            			if ( 
     | 
| 
       150 
     | 
    
         
            -
            				/*  
     | 
| 
       151 
     | 
    
         
            -
            				 * as a positive integer,  
     | 
| 
      
 171 
     | 
    
         
            +
            			if (sll < 0) {
         
     | 
| 
      
 172 
     | 
    
         
            +
            				/* Avoid problems with the most negative integer not being representable
         
     | 
| 
      
 173 
     | 
    
         
            +
            				 * as a positive integer, by using unsigned long long for encoding.
         
     | 
| 
       152 
174 
     | 
    
         
             
            				 */
         
     | 
| 
       153 
     | 
    
         
            -
            				ll = - 
     | 
| 
      
 175 
     | 
    
         
            +
            				ll = -sll;
         
     | 
| 
       154 
176 
     | 
    
         
             
            				neg = 1;
         
     | 
| 
      
 177 
     | 
    
         
            +
            			} else {
         
     | 
| 
      
 178 
     | 
    
         
            +
            				ll = sll;
         
     | 
| 
       155 
179 
     | 
    
         
             
            			}
         
     | 
| 
       156 
180 
     | 
    
         | 
| 
       157 
181 
     | 
    
         
             
            			/* Compute the result string backwards. */
         
     | 
| 
       158 
182 
     | 
    
         
             
            			do {
         
     | 
| 
       159 
     | 
    
         
            -
            				long long remainder;
         
     | 
| 
       160 
     | 
    
         
            -
            				long long oldval = ll;
         
     | 
| 
      
 183 
     | 
    
         
            +
            				unsigned long long remainder;
         
     | 
| 
      
 184 
     | 
    
         
            +
            				unsigned long long oldval = ll;
         
     | 
| 
       161 
185 
     | 
    
         | 
| 
       162 
186 
     | 
    
         
             
            				ll /= 10;
         
     | 
| 
       163 
187 
     | 
    
         
             
            				remainder = oldval - ll * 10;
         
     | 
| 
         @@ -184,45 +208,17 @@ pg_text_enc_integer(t_pg_coder *this, VALUE value, char *out, VALUE *intermediat 
     | 
|
| 
       184 
208 
     | 
    
         
             
            	}else{
         
     | 
| 
       185 
209 
     | 
    
         
             
            		*intermediate = pg_obj_to_i(value);
         
     | 
| 
       186 
210 
     | 
    
         
             
            		if(TYPE(*intermediate) == T_FIXNUM){
         
     | 
| 
       187 
     | 
    
         
            -
            			int len;
         
     | 
| 
       188 
211 
     | 
    
         
             
            			long long sll = NUM2LL(*intermediate);
         
     | 
| 
       189 
     | 
    
         
            -
            			long long ll = sll < 0 ? -sll : sll;
         
     | 
| 
       190 
     | 
    
         
            -
            			 
     | 
| 
       191 
     | 
    
         
            -
             
     | 
| 
       192 
     | 
    
         
            -
            					if( ll < 100 ){
         
     | 
| 
       193 
     | 
    
         
            -
            						len = ll < 10 ? 1 : 2;
         
     | 
| 
       194 
     | 
    
         
            -
            					}else{
         
     | 
| 
       195 
     | 
    
         
            -
            						len = ll < 1000 ? 3 : 4;
         
     | 
| 
       196 
     | 
    
         
            -
            					}
         
     | 
| 
       197 
     | 
    
         
            -
            				}else{
         
     | 
| 
       198 
     | 
    
         
            -
            					if( ll < 1000000 ){
         
     | 
| 
       199 
     | 
    
         
            -
            						len = ll < 100000 ? 5 : 6;
         
     | 
| 
       200 
     | 
    
         
            -
            					}else{
         
     | 
| 
       201 
     | 
    
         
            -
            						len = ll < 10000000 ? 7 : 8;
         
     | 
| 
       202 
     | 
    
         
            -
            					}
         
     | 
| 
       203 
     | 
    
         
            -
            				}
         
     | 
| 
       204 
     | 
    
         
            -
            			}else{
         
     | 
| 
       205 
     | 
    
         
            -
            				if( ll < 1000000000000LL ){
         
     | 
| 
       206 
     | 
    
         
            -
            					if( ll < 10000000000LL ){
         
     | 
| 
       207 
     | 
    
         
            -
            						len = ll < 1000000000LL ? 9 : 10;
         
     | 
| 
       208 
     | 
    
         
            -
            					}else{
         
     | 
| 
       209 
     | 
    
         
            -
            						len = ll < 100000000000LL ? 11 : 12;
         
     | 
| 
       210 
     | 
    
         
            -
            					}
         
     | 
| 
       211 
     | 
    
         
            -
            				}else{
         
     | 
| 
       212 
     | 
    
         
            -
            					if( ll < 100000000000000LL ){
         
     | 
| 
       213 
     | 
    
         
            -
            						len = ll < 10000000000000LL ? 13 : 14;
         
     | 
| 
       214 
     | 
    
         
            -
            					}else{
         
     | 
| 
       215 
     | 
    
         
            -
            						return pg_coder_enc_to_s(this, *intermediate, NULL, intermediate, enc_idx);
         
     | 
| 
       216 
     | 
    
         
            -
            					}
         
     | 
| 
       217 
     | 
    
         
            -
            				}
         
     | 
| 
       218 
     | 
    
         
            -
            			}
         
     | 
| 
       219 
     | 
    
         
            -
            			return sll < 0 ? len+1 : len;
         
     | 
| 
      
 212 
     | 
    
         
            +
            			unsigned long long ll = sll < 0 ? -sll : sll;
         
     | 
| 
      
 213 
     | 
    
         
            +
            			int len = (sizeof(unsigned long long) * 8 - count_leading_zero_bits(ll)) / 3;
         
     | 
| 
      
 214 
     | 
    
         
            +
            			return sll < 0 ? len+2 : len+1;
         
     | 
| 
       220 
215 
     | 
    
         
             
            		}else{
         
     | 
| 
       221 
216 
     | 
    
         
             
            			return pg_coder_enc_to_s(this, *intermediate, NULL, intermediate, enc_idx);
         
     | 
| 
       222 
217 
     | 
    
         
             
            		}
         
     | 
| 
       223 
218 
     | 
    
         
             
            	}
         
     | 
| 
       224 
219 
     | 
    
         
             
            }
         
     | 
| 
       225 
220 
     | 
    
         | 
| 
      
 221 
     | 
    
         
            +
            #define MAX_DOUBLE_DIGITS 16
         
     | 
| 
       226 
222 
     | 
    
         | 
| 
       227 
223 
     | 
    
         
             
            /*
         
     | 
| 
       228 
224 
     | 
    
         
             
             * Document-class: PG::TextEncoder::Float < PG::SimpleEncoder
         
     | 
| 
         @@ -235,6 +231,12 @@ pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, 
     | 
|
| 
       235 
231 
     | 
    
         
             
            {
         
     | 
| 
       236 
232 
     | 
    
         
             
            	if(out){
         
     | 
| 
       237 
233 
     | 
    
         
             
            		double dvalue = NUM2DBL(value);
         
     | 
| 
      
 234 
     | 
    
         
            +
            		int len = 0;
         
     | 
| 
      
 235 
     | 
    
         
            +
            		int neg = 0;
         
     | 
| 
      
 236 
     | 
    
         
            +
            		int exp2i, exp10i, i;
         
     | 
| 
      
 237 
     | 
    
         
            +
            		unsigned long long ll, remainder, oldval;
         
     | 
| 
      
 238 
     | 
    
         
            +
            		VALUE intermediate;
         
     | 
| 
      
 239 
     | 
    
         
            +
             
     | 
| 
       238 
240 
     | 
    
         
             
            		/* Cast to the same strings as value.to_s . */
         
     | 
| 
       239 
241 
     | 
    
         
             
            		if( isinf(dvalue) ){
         
     | 
| 
       240 
242 
     | 
    
         
             
            			if( dvalue < 0 ){
         
     | 
| 
         @@ -248,12 +250,128 @@ pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, 
     | 
|
| 
       248 
250 
     | 
    
         
             
            			memcpy( out, "NaN", 3);
         
     | 
| 
       249 
251 
     | 
    
         
             
            			return 3;
         
     | 
| 
       250 
252 
     | 
    
         
             
            		}
         
     | 
| 
       251 
     | 
    
         
            -
             
     | 
| 
      
 253 
     | 
    
         
            +
             
     | 
| 
      
 254 
     | 
    
         
            +
            		/*
         
     | 
| 
      
 255 
     | 
    
         
            +
            		 * The following computaion is roughly a conversion kind of
         
     | 
| 
      
 256 
     | 
    
         
            +
            		 *   sprintf( out, "%.16E", dvalue);
         
     | 
| 
      
 257 
     | 
    
         
            +
            		 */
         
     | 
| 
      
 258 
     | 
    
         
            +
             
     | 
| 
      
 259 
     | 
    
         
            +
            		/* write the algebraic sign */
         
     | 
| 
      
 260 
     | 
    
         
            +
            		if( dvalue < 0 ) {
         
     | 
| 
      
 261 
     | 
    
         
            +
            			dvalue = -dvalue;
         
     | 
| 
      
 262 
     | 
    
         
            +
            			*out++ = '-';
         
     | 
| 
      
 263 
     | 
    
         
            +
            			neg++;
         
     | 
| 
      
 264 
     | 
    
         
            +
            		}
         
     | 
| 
      
 265 
     | 
    
         
            +
             
     | 
| 
      
 266 
     | 
    
         
            +
            		/* retrieve the power of 2 exponent */
         
     | 
| 
      
 267 
     | 
    
         
            +
            		frexp(dvalue, &exp2i);
         
     | 
| 
      
 268 
     | 
    
         
            +
            		/* compute the power of 10 exponent */
         
     | 
| 
      
 269 
     | 
    
         
            +
            		exp10i = (int)floor(exp2i * 0.30102999566398114); /* Math.log(2)/Math.log(10) */
         
     | 
| 
      
 270 
     | 
    
         
            +
            		/* move the decimal point, so that we get an integer of MAX_DOUBLE_DIGITS decimal digits */
         
     | 
| 
      
 271 
     | 
    
         
            +
            		ll = (unsigned long long)(dvalue * pow(10, MAX_DOUBLE_DIGITS - 1 - exp10i) + 0.5);
         
     | 
| 
      
 272 
     | 
    
         
            +
             
     | 
| 
      
 273 
     | 
    
         
            +
            		/* avoid leading zeros due to inaccuracy of deriving exp10i from exp2i */
         
     | 
| 
      
 274 
     | 
    
         
            +
            		/* otherwise we would print "09.0" instead of "9.0" */
         
     | 
| 
      
 275 
     | 
    
         
            +
            		if( ll < 1000000000000000 ){ /* pow(10, MAX_DOUBLE_DIGITS-1) */
         
     | 
| 
      
 276 
     | 
    
         
            +
            			exp10i--;
         
     | 
| 
      
 277 
     | 
    
         
            +
            			ll *= 10;
         
     | 
| 
      
 278 
     | 
    
         
            +
            		}
         
     | 
| 
      
 279 
     | 
    
         
            +
             
     | 
| 
      
 280 
     | 
    
         
            +
            		if( exp10i <= -5 || exp10i >= 15 ) {
         
     | 
| 
      
 281 
     | 
    
         
            +
            			/* Write the float in exponent format (1.23e45) */
         
     | 
| 
      
 282 
     | 
    
         
            +
             
     | 
| 
      
 283 
     | 
    
         
            +
            			/* write fraction digits from right to left */
         
     | 
| 
      
 284 
     | 
    
         
            +
            			for( i = MAX_DOUBLE_DIGITS; i > 1; i--){
         
     | 
| 
      
 285 
     | 
    
         
            +
            				oldval = ll;
         
     | 
| 
      
 286 
     | 
    
         
            +
            				ll /= 10;
         
     | 
| 
      
 287 
     | 
    
         
            +
            				remainder = oldval - ll * 10;
         
     | 
| 
      
 288 
     | 
    
         
            +
            				/* omit trailing zeros */
         
     | 
| 
      
 289 
     | 
    
         
            +
            				if(remainder != 0 || len ) {
         
     | 
| 
      
 290 
     | 
    
         
            +
            					out[i] = '0' + remainder;
         
     | 
| 
      
 291 
     | 
    
         
            +
            					len++;
         
     | 
| 
      
 292 
     | 
    
         
            +
            				}
         
     | 
| 
      
 293 
     | 
    
         
            +
            			}
         
     | 
| 
      
 294 
     | 
    
         
            +
             
     | 
| 
      
 295 
     | 
    
         
            +
            			/* write decimal point */
         
     | 
| 
      
 296 
     | 
    
         
            +
            			if( len ){
         
     | 
| 
      
 297 
     | 
    
         
            +
            				out[1] = '.';
         
     | 
| 
      
 298 
     | 
    
         
            +
            				len++;
         
     | 
| 
      
 299 
     | 
    
         
            +
            			}
         
     | 
| 
      
 300 
     | 
    
         
            +
             
     | 
| 
      
 301 
     | 
    
         
            +
            			/* write remaining single digit left to the decimal point */
         
     | 
| 
      
 302 
     | 
    
         
            +
            			oldval = ll;
         
     | 
| 
      
 303 
     | 
    
         
            +
            			ll /= 10;
         
     | 
| 
      
 304 
     | 
    
         
            +
            			remainder = oldval - ll * 10;
         
     | 
| 
      
 305 
     | 
    
         
            +
            			out[0] = '0' + remainder;
         
     | 
| 
      
 306 
     | 
    
         
            +
            			len++;
         
     | 
| 
      
 307 
     | 
    
         
            +
             
     | 
| 
      
 308 
     | 
    
         
            +
            			/* write exponent */
         
     | 
| 
      
 309 
     | 
    
         
            +
            			out[len++] = 'e';
         
     | 
| 
      
 310 
     | 
    
         
            +
            			intermediate = INT2NUM(exp10i);
         
     | 
| 
      
 311 
     | 
    
         
            +
             
     | 
| 
      
 312 
     | 
    
         
            +
            			return neg + len + pg_text_enc_integer(conv, Qnil, out + len, &intermediate, enc_idx);
         
     | 
| 
      
 313 
     | 
    
         
            +
            		} else {
         
     | 
| 
      
 314 
     | 
    
         
            +
            			/* write the float in non exponent format (0.001234 or 123450.0) */
         
     | 
| 
      
 315 
     | 
    
         
            +
             
     | 
| 
      
 316 
     | 
    
         
            +
            			/* write digits from right to left */
         
     | 
| 
      
 317 
     | 
    
         
            +
            			int lz = exp10i < 0 ? 0 : exp10i;
         
     | 
| 
      
 318 
     | 
    
         
            +
            			for( i = MAX_DOUBLE_DIGITS - (exp10i < 0 ? exp10i : 0); i >= 0; i-- ){
         
     | 
| 
      
 319 
     | 
    
         
            +
            				oldval = ll;
         
     | 
| 
      
 320 
     | 
    
         
            +
            				ll /= 10;
         
     | 
| 
      
 321 
     | 
    
         
            +
            				remainder = oldval - ll * 10;
         
     | 
| 
      
 322 
     | 
    
         
            +
            				/* write decimal point */
         
     | 
| 
      
 323 
     | 
    
         
            +
            				if( i - 1 == lz ){
         
     | 
| 
      
 324 
     | 
    
         
            +
            					out[i--] = '.';
         
     | 
| 
      
 325 
     | 
    
         
            +
            					len++;
         
     | 
| 
      
 326 
     | 
    
         
            +
            				}
         
     | 
| 
      
 327 
     | 
    
         
            +
            				/* if possible then omit trailing zeros */
         
     | 
| 
      
 328 
     | 
    
         
            +
            				if(remainder != 0 || len || i - 2 == lz) {
         
     | 
| 
      
 329 
     | 
    
         
            +
            					out[i] = '0' + remainder;
         
     | 
| 
      
 330 
     | 
    
         
            +
            					len++;
         
     | 
| 
      
 331 
     | 
    
         
            +
            				}
         
     | 
| 
      
 332 
     | 
    
         
            +
            			}
         
     | 
| 
      
 333 
     | 
    
         
            +
            			return neg + len;
         
     | 
| 
      
 334 
     | 
    
         
            +
            		}
         
     | 
| 
       252 
335 
     | 
    
         
             
            	}else{
         
     | 
| 
       253 
     | 
    
         
            -
            		return  
     | 
| 
      
 336 
     | 
    
         
            +
            		return 1 /*sign*/ + MAX_DOUBLE_DIGITS + 1 /*dot*/ + 1 /*e*/ + 1 /*exp sign*/ + 3 /*exp digits*/;
         
     | 
| 
       254 
337 
     | 
    
         
             
            	}
         
     | 
| 
       255 
338 
     | 
    
         
             
            }
         
     | 
| 
       256 
339 
     | 
    
         | 
| 
      
 340 
     | 
    
         
            +
             
     | 
| 
      
 341 
     | 
    
         
            +
            /*
         
     | 
| 
      
 342 
     | 
    
         
            +
             * Document-class: PG::TextEncoder::Numeric < PG::SimpleEncoder
         
     | 
| 
      
 343 
     | 
    
         
            +
             *
         
     | 
| 
      
 344 
     | 
    
         
            +
             * This is the encoder class for the PostgreSQL numeric types.
         
     | 
| 
      
 345 
     | 
    
         
            +
             *
         
     | 
| 
      
 346 
     | 
    
         
            +
             * It converts Integer, Float and BigDecimal objects.
         
     | 
| 
      
 347 
     | 
    
         
            +
             * All other objects are expected to respond to +to_s+.
         
     | 
| 
      
 348 
     | 
    
         
            +
             */
         
     | 
| 
      
 349 
     | 
    
         
            +
            static int
         
     | 
| 
      
 350 
     | 
    
         
            +
            pg_text_enc_numeric(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx)
         
     | 
| 
      
 351 
     | 
    
         
            +
            {
         
     | 
| 
      
 352 
     | 
    
         
            +
            	switch(TYPE(value)){
         
     | 
| 
      
 353 
     | 
    
         
            +
            		case T_FIXNUM:
         
     | 
| 
      
 354 
     | 
    
         
            +
            		case T_BIGNUM:
         
     | 
| 
      
 355 
     | 
    
         
            +
            			return pg_text_enc_integer(this, value, out, intermediate, enc_idx);
         
     | 
| 
      
 356 
     | 
    
         
            +
            		case T_FLOAT:
         
     | 
| 
      
 357 
     | 
    
         
            +
            			return pg_text_enc_float(this, value, out, intermediate, enc_idx);
         
     | 
| 
      
 358 
     | 
    
         
            +
            		default:
         
     | 
| 
      
 359 
     | 
    
         
            +
            			if(out){ /* second pass */
         
     | 
| 
      
 360 
     | 
    
         
            +
            				rb_bug("unexpected value type: %d", TYPE(value));
         
     | 
| 
      
 361 
     | 
    
         
            +
            			} else { /* first pass */
         
     | 
| 
      
 362 
     | 
    
         
            +
            				if( rb_obj_is_kind_of(value, s_cBigDecimal) ){
         
     | 
| 
      
 363 
     | 
    
         
            +
            					/* value.to_s('F') */
         
     | 
| 
      
 364 
     | 
    
         
            +
            					*intermediate = rb_funcall(value, s_id_to_s, 1, s_str_F);
         
     | 
| 
      
 365 
     | 
    
         
            +
            					return -1; /* no second pass */
         
     | 
| 
      
 366 
     | 
    
         
            +
            				} else {
         
     | 
| 
      
 367 
     | 
    
         
            +
            					return pg_coder_enc_to_s(this, value, NULL, intermediate, enc_idx);
         
     | 
| 
      
 368 
     | 
    
         
            +
            					/* no second pass */
         
     | 
| 
      
 369 
     | 
    
         
            +
            				}
         
     | 
| 
      
 370 
     | 
    
         
            +
            			}
         
     | 
| 
      
 371 
     | 
    
         
            +
            	}
         
     | 
| 
      
 372 
     | 
    
         
            +
            }
         
     | 
| 
      
 373 
     | 
    
         
            +
             
     | 
| 
      
 374 
     | 
    
         
            +
             
     | 
| 
       257 
375 
     | 
    
         
             
            static const char hextab[] = {
         
     | 
| 
       258 
376 
     | 
    
         
             
            	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
         
     | 
| 
       259 
377 
     | 
    
         
             
            };
         
     | 
| 
         @@ -261,8 +379,7 @@ static const char hextab[] = { 
     | 
|
| 
       261 
379 
     | 
    
         
             
            /*
         
     | 
| 
       262 
380 
     | 
    
         
             
             * Document-class: PG::TextEncoder::Bytea < PG::SimpleEncoder
         
     | 
| 
       263 
381 
     | 
    
         
             
             *
         
     | 
| 
       264 
     | 
    
         
            -
             * This is an encoder class for the PostgreSQL bytea type 
     | 
| 
       265 
     | 
    
         
            -
             * or newer.
         
     | 
| 
      
 382 
     | 
    
         
            +
             * This is an encoder class for the PostgreSQL +bytea+ type.
         
     | 
| 
       266 
383 
     | 
    
         
             
             *
         
     | 
| 
       267 
384 
     | 
    
         
             
             * The binary String is converted to hexadecimal representation for transmission
         
     | 
| 
       268 
385 
     | 
    
         
             
             * in text format. For query bind parameters it is recommended to use
         
     | 
| 
         @@ -520,7 +637,8 @@ pg_text_enc_array_identifier(VALUE value, VALUE string, char *out, int enc_idx) 
     | 
|
| 
       520 
637 
     | 
    
         
             
             *
         
     | 
| 
       521 
638 
     | 
    
         
             
             * This is the encoder class for PostgreSQL identifiers.
         
     | 
| 
       522 
639 
     | 
    
         
             
             *
         
     | 
| 
       523 
     | 
    
         
            -
             * An Array value can be used for "schema.table.column" 
     | 
| 
      
 640 
     | 
    
         
            +
             * An Array value can be used for identifiers of the kind "schema.table.column".
         
     | 
| 
      
 641 
     | 
    
         
            +
             * This ensures that each element is properly quoted:
         
     | 
| 
       524 
642 
     | 
    
         
             
             *   PG::TextEncoder::Identifier.new.encode(['schema', 'table', 'column'])
         
     | 
| 
       525 
643 
     | 
    
         
             
             *      => '"schema"."table"."column"'
         
     | 
| 
       526 
644 
     | 
    
         
             
             *
         
     | 
| 
         @@ -588,7 +706,13 @@ quote_literal_buffer( void *_this, char *p_in, int strlen, char *p_out ){ 
     | 
|
| 
       588 
706 
     | 
    
         
             
             *
         
     | 
| 
       589 
707 
     | 
    
         
             
             * This is the encoder class for PostgreSQL literals.
         
     | 
| 
       590 
708 
     | 
    
         
             
             *
         
     | 
| 
       591 
     | 
    
         
            -
             * A literal is quoted and escaped by the  
     | 
| 
      
 709 
     | 
    
         
            +
             * A literal is quoted and escaped by the <tt>'</tt> character, so that it can be inserted into SQL queries.
         
     | 
| 
      
 710 
     | 
    
         
            +
             * It works equal to PG::Connection#escape_literal, but integrates into the type cast system of ruby-pg.
         
     | 
| 
      
 711 
     | 
    
         
            +
             *
         
     | 
| 
      
 712 
     | 
    
         
            +
             * Both expressions have the same result:
         
     | 
| 
      
 713 
     | 
    
         
            +
             *   conn.escape_literal(PG::TextEncoder::Array.new.encode(["v1","v2"])) # => "'{v1,v2}'"
         
     | 
| 
      
 714 
     | 
    
         
            +
             *   PG::TextEncoder::QuotedLiteral.new(elements_type: PG::TextEncoder::Array.new).encode(["v1","v2"]) # => "'{v1,v2}'"
         
     | 
| 
      
 715 
     | 
    
         
            +
             * While escape_literal requires a intermediate ruby string allocation, QuotedLiteral encodes the values directly to the result string.
         
     | 
| 
       592 
716 
     | 
    
         
             
             *
         
     | 
| 
       593 
717 
     | 
    
         
             
             */
         
     | 
| 
       594 
718 
     | 
    
         
             
            static int
         
     | 
| 
         @@ -655,6 +779,12 @@ init_pg_text_encoder() 
     | 
|
| 
       655 
779 
     | 
    
         
             
            {
         
     | 
| 
       656 
780 
     | 
    
         
             
            	s_id_encode = rb_intern("encode");
         
     | 
| 
       657 
781 
     | 
    
         
             
            	s_id_to_i = rb_intern("to_i");
         
     | 
| 
      
 782 
     | 
    
         
            +
            	s_id_to_s = rb_intern("to_s");
         
     | 
| 
      
 783 
     | 
    
         
            +
            	s_str_F = rb_str_freeze(rb_str_new_cstr("F"));
         
     | 
| 
      
 784 
     | 
    
         
            +
            	rb_global_variable(&s_str_F);
         
     | 
| 
      
 785 
     | 
    
         
            +
            	rb_require("bigdecimal");
         
     | 
| 
      
 786 
     | 
    
         
            +
            	s_cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
         
     | 
| 
      
 787 
     | 
    
         
            +
             
     | 
| 
       658 
788 
     | 
    
         | 
| 
       659 
789 
     | 
    
         
             
            	/* This module encapsulates all encoder classes with text output format */
         
     | 
| 
       660 
790 
     | 
    
         
             
            	rb_mPG_TextEncoder = rb_define_module_under( rb_mPG, "TextEncoder" );
         
     | 
| 
         @@ -666,6 +796,8 @@ init_pg_text_encoder() 
     | 
|
| 
       666 
796 
     | 
    
         
             
            	pg_define_coder( "Integer", pg_text_enc_integer, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
         
     | 
| 
       667 
797 
     | 
    
         
             
            	/* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Float", rb_cPG_SimpleEncoder ); */
         
     | 
| 
       668 
798 
     | 
    
         
             
            	pg_define_coder( "Float", pg_text_enc_float, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
         
     | 
| 
      
 799 
     | 
    
         
            +
            	/* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Numeric", rb_cPG_SimpleEncoder ); */
         
     | 
| 
      
 800 
     | 
    
         
            +
            	pg_define_coder( "Numeric", pg_text_enc_numeric, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
         
     | 
| 
       669 
801 
     | 
    
         
             
            	/* dummy = rb_define_class_under( rb_mPG_TextEncoder, "String", rb_cPG_SimpleEncoder ); */
         
     | 
| 
       670 
802 
     | 
    
         
             
            	pg_define_coder( "String", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
         
     | 
| 
       671 
803 
     | 
    
         
             
            	/* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Bytea", rb_cPG_SimpleEncoder ); */
         
     | 
    
        data/ext/pg_tuple.c
    CHANGED
    
    | 
         @@ -132,7 +132,6 @@ pg_tuple_new(VALUE result, int row_num) 
     | 
|
| 
       132 
132 
     | 
    
         
             
            		sizeof(*this) +
         
     | 
| 
       133 
133 
     | 
    
         
             
            		sizeof(*this->values) * num_fields +
         
     | 
| 
       134 
134 
     | 
    
         
             
            		sizeof(*this->values) * (dup_names ? 1 : 0));
         
     | 
| 
       135 
     | 
    
         
            -
            	RTYPEDDATA_DATA(self) = this;
         
     | 
| 
       136 
135 
     | 
    
         | 
| 
       137 
136 
     | 
    
         
             
            	this->result = result;
         
     | 
| 
       138 
137 
     | 
    
         
             
            	this->typemap = p_result->typemap;
         
     | 
| 
         @@ -151,6 +150,8 @@ pg_tuple_new(VALUE result, int row_num) 
     | 
|
| 
       151 
150 
     | 
    
         
             
            		this->values[num_fields] = rb_obj_freeze(rb_ary_new4(num_fields, p_result->fnames));
         
     | 
| 
       152 
151 
     | 
    
         
             
            	}
         
     | 
| 
       153 
152 
     | 
    
         | 
| 
      
 153 
     | 
    
         
            +
            	RTYPEDDATA_DATA(self) = this;
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
       154 
155 
     | 
    
         
             
            	return self;
         
     | 
| 
       155 
156 
     | 
    
         
             
            }
         
     | 
| 
       156 
157 
     | 
    
         | 
| 
         @@ -211,7 +212,7 @@ pg_tuple_materialize(t_pg_tuple *this) 
     | 
|
| 
       211 
212 
     | 
    
         
             
             * An integer +key+ is interpreted as column index.
         
     | 
| 
       212 
213 
     | 
    
         
             
             * Negative values of index count from the end of the array.
         
     | 
| 
       213 
214 
     | 
    
         
             
             *
         
     | 
| 
       214 
     | 
    
         
            -
             *  
     | 
| 
      
 215 
     | 
    
         
            +
             * Depending on Result#field_name_type= a string or symbol +key+ is interpreted as column name.
         
     | 
| 
       215 
216 
     | 
    
         
             
             *
         
     | 
| 
       216 
217 
     | 
    
         
             
             * If the key can't be found, there are several options:
         
     | 
| 
       217 
218 
     | 
    
         
             
             * With no other arguments, it will raise a IndexError exception;
         
     | 
| 
         @@ -264,9 +265,16 @@ pg_tuple_fetch(int argc, VALUE *argv, VALUE self) 
     | 
|
| 
       264 
265 
     | 
    
         | 
| 
       265 
266 
     | 
    
         
             
            /*
         
     | 
| 
       266 
267 
     | 
    
         
             
             * call-seq:
         
     | 
| 
       267 
     | 
    
         
            -
             *     
     | 
| 
      
 268 
     | 
    
         
            +
             *    tup[ key ] -> value
         
     | 
| 
      
 269 
     | 
    
         
            +
             *
         
     | 
| 
      
 270 
     | 
    
         
            +
             * Returns a field value by either column index or column name.
         
     | 
| 
      
 271 
     | 
    
         
            +
             *
         
     | 
| 
      
 272 
     | 
    
         
            +
             * An integer +key+ is interpreted as column index.
         
     | 
| 
      
 273 
     | 
    
         
            +
             * Negative values of index count from the end of the array.
         
     | 
| 
      
 274 
     | 
    
         
            +
             *
         
     | 
| 
      
 275 
     | 
    
         
            +
             * Depending on Result#field_name_type= a string or symbol +key+ is interpreted as column name.
         
     | 
| 
       268 
276 
     | 
    
         
             
             *
         
     | 
| 
       269 
     | 
    
         
            -
             *  
     | 
| 
      
 277 
     | 
    
         
            +
             * If the key can't be found, it returns +nil+ .
         
     | 
| 
       270 
278 
     | 
    
         
             
             */
         
     | 
| 
       271 
279 
     | 
    
         
             
            static VALUE
         
     | 
| 
       272 
280 
     | 
    
         
             
            pg_tuple_aref(VALUE self, VALUE key)
         
     | 
| 
         @@ -457,7 +465,6 @@ pg_tuple_load(VALUE self, VALUE a) 
     | 
|
| 
       457 
465 
     | 
    
         
             
            	int dup_names;
         
     | 
| 
       458 
466 
     | 
    
         | 
| 
       459 
467 
     | 
    
         
             
            	rb_check_frozen(self);
         
     | 
| 
       460 
     | 
    
         
            -
            	rb_check_trusted(self);
         
     | 
| 
       461 
468 
     | 
    
         | 
| 
       462 
469 
     | 
    
         
             
            	TypedData_Get_Struct(self, t_pg_tuple, &pg_tuple_type, this);
         
     | 
| 
       463 
470 
     | 
    
         
             
            	if (this)
         
     | 
| 
         @@ -489,7 +496,6 @@ pg_tuple_load(VALUE self, VALUE a) 
     | 
|
| 
       489 
496 
     | 
    
         
             
            		sizeof(*this) +
         
     | 
| 
       490 
497 
     | 
    
         
             
            		sizeof(*this->values) * num_fields +
         
     | 
| 
       491 
498 
     | 
    
         
             
            		sizeof(*this->values) * (dup_names ? 1 : 0));
         
     | 
| 
       492 
     | 
    
         
            -
            	RTYPEDDATA_DATA(self) = this;
         
     | 
| 
       493 
499 
     | 
    
         | 
| 
       494 
500 
     | 
    
         
             
            	this->result = Qnil;
         
     | 
| 
       495 
501 
     | 
    
         
             
            	this->typemap = Qnil;
         
     | 
| 
         @@ -508,6 +514,8 @@ pg_tuple_load(VALUE self, VALUE a) 
     | 
|
| 
       508 
514 
     | 
    
         
             
            		this->values[num_fields] = field_names;
         
     | 
| 
       509 
515 
     | 
    
         
             
            	}
         
     | 
| 
       510 
516 
     | 
    
         | 
| 
      
 517 
     | 
    
         
            +
            	RTYPEDDATA_DATA(self) = this;
         
     | 
| 
      
 518 
     | 
    
         
            +
             
     | 
| 
       511 
519 
     | 
    
         
             
            	if (FL_TEST(a, FL_EXIVAR)) {
         
     | 
| 
       512 
520 
     | 
    
         
             
            		rb_copy_generic_ivar(self, a);
         
     | 
| 
       513 
521 
     | 
    
         
             
            		FL_SET(self, FL_EXIVAR);
         
     |