pg 1.0.0 → 1.5.9
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/Gemfile +20 -0
- data/History.md +932 -0
- data/Manifest.txt +8 -3
- data/README-Windows.rdoc +4 -4
- data/README.ja.md +300 -0
- data/README.md +286 -0
- data/Rakefile +41 -138
- data/Rakefile.cross +71 -66
- data/certs/ged.pem +24 -0
- data/certs/kanis@comcard.de.pem +20 -0
- data/certs/larskanis-2022.pem +26 -0
- data/certs/larskanis-2023.pem +24 -0
- data/certs/larskanis-2024.pem +24 -0
- data/ext/errorcodes.def +84 -5
- data/ext/errorcodes.rb +1 -1
- data/ext/errorcodes.txt +23 -6
- data/ext/extconf.rb +109 -25
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +23 -0
- data/ext/pg.c +213 -155
- data/ext/pg.h +89 -23
- data/ext/pg_binary_decoder.c +164 -16
- data/ext/pg_binary_encoder.c +238 -13
- data/ext/pg_coder.c +159 -35
- data/ext/pg_connection.c +1584 -967
- data/ext/pg_copy_coder.c +373 -43
- data/ext/pg_errors.c +1 -1
- data/ext/pg_record_coder.c +522 -0
- data/ext/pg_result.c +710 -217
- data/ext/pg_text_decoder.c +630 -43
- data/ext/pg_text_encoder.c +222 -72
- data/ext/pg_tuple.c +572 -0
- data/ext/pg_type_map.c +45 -11
- data/ext/pg_type_map_all_strings.c +21 -7
- data/ext/pg_type_map_by_class.c +59 -27
- data/ext/pg_type_map_by_column.c +80 -37
- data/ext/pg_type_map_by_mri_type.c +49 -20
- data/ext/pg_type_map_by_oid.c +62 -29
- data/ext/pg_type_map_in_ruby.c +56 -22
- data/ext/{util.c → pg_util.c} +12 -12
- data/ext/{util.h → pg_util.h} +2 -2
- data/lib/pg/basic_type_map_based_on_result.rb +67 -0
- data/lib/pg/basic_type_map_for_queries.rb +202 -0
- data/lib/pg/basic_type_map_for_results.rb +104 -0
- data/lib/pg/basic_type_registry.rb +311 -0
- data/lib/pg/binary_decoder/date.rb +9 -0
- data/lib/pg/binary_decoder/timestamp.rb +26 -0
- data/lib/pg/binary_encoder/timestamp.rb +20 -0
- data/lib/pg/coder.rb +36 -13
- data/lib/pg/connection.rb +769 -70
- data/lib/pg/exceptions.rb +22 -2
- data/lib/pg/result.rb +14 -2
- data/lib/pg/text_decoder/date.rb +21 -0
- data/lib/pg/text_decoder/inet.rb +9 -0
- data/lib/pg/text_decoder/json.rb +17 -0
- data/lib/pg/text_decoder/numeric.rb +9 -0
- data/lib/pg/text_decoder/timestamp.rb +30 -0
- data/lib/pg/text_encoder/date.rb +13 -0
- data/lib/pg/text_encoder/inet.rb +31 -0
- data/lib/pg/text_encoder/json.rb +17 -0
- data/lib/pg/text_encoder/numeric.rb +9 -0
- data/lib/pg/text_encoder/timestamp.rb +24 -0
- data/lib/pg/tuple.rb +30 -0
- data/lib/pg/type_map_by_column.rb +3 -2
- data/lib/pg/version.rb +4 -0
- data/lib/pg.rb +106 -39
- data/misc/openssl-pg-segfault.rb +31 -0
- data/misc/postgres/History.txt +9 -0
- data/misc/postgres/Manifest.txt +5 -0
- data/misc/postgres/README.txt +21 -0
- data/misc/postgres/Rakefile +21 -0
- data/misc/postgres/lib/postgres.rb +16 -0
- data/misc/ruby-pg/History.txt +9 -0
- data/misc/ruby-pg/Manifest.txt +5 -0
- data/misc/ruby-pg/README.txt +21 -0
- data/misc/ruby-pg/Rakefile +21 -0
- data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
- data/pg.gemspec +36 -0
- data/rakelib/task_extension.rb +46 -0
- data/sample/array_insert.rb +20 -0
- data/sample/async_api.rb +102 -0
- data/sample/async_copyto.rb +39 -0
- data/sample/async_mixed.rb +56 -0
- data/sample/check_conn.rb +21 -0
- data/sample/copydata.rb +71 -0
- data/sample/copyfrom.rb +81 -0
- data/sample/copyto.rb +19 -0
- data/sample/cursor.rb +21 -0
- data/sample/disk_usage_report.rb +177 -0
- data/sample/issue-119.rb +94 -0
- data/sample/losample.rb +69 -0
- data/sample/minimal-testcase.rb +17 -0
- data/sample/notify_wait.rb +72 -0
- data/sample/pg_statistics.rb +285 -0
- data/sample/replication_monitor.rb +222 -0
- data/sample/test_binary_values.rb +33 -0
- data/sample/wal_shipper.rb +434 -0
- data/sample/warehouse_partitions.rb +311 -0
- data.tar.gz.sig +0 -0
- metadata +138 -223
- metadata.gz.sig +0 -0
- data/.gemtest +0 -0
- data/ChangeLog +0 -6595
- data/History.rdoc +0 -422
- data/README.ja.rdoc +0 -14
- data/README.rdoc +0 -167
- data/lib/pg/basic_type_mapping.rb +0 -426
- data/lib/pg/constants.rb +0 -11
- data/lib/pg/text_decoder.rb +0 -51
- data/lib/pg/text_encoder.rb +0 -35
- data/spec/data/expected_trace.out +0 -26
- data/spec/data/random_binary_data +0 -0
- data/spec/helpers.rb +0 -348
- data/spec/pg/basic_type_mapping_spec.rb +0 -305
- data/spec/pg/connection_spec.rb +0 -1719
- data/spec/pg/result_spec.rb +0 -456
- data/spec/pg/type_map_by_class_spec.rb +0 -138
- data/spec/pg/type_map_by_column_spec.rb +0 -222
- data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
- data/spec/pg/type_map_by_oid_spec.rb +0 -149
- data/spec/pg/type_map_in_ruby_spec.rb +0 -164
- data/spec/pg/type_map_spec.rb +0 -22
- data/spec/pg/type_spec.rb +0 -777
- data/spec/pg_spec.rb +0 -50
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_type_map_by_mri_type.c - PG::TypeMapByMriType class extension
|
3
|
-
* $Id
|
3
|
+
* $Id$
|
4
4
|
*
|
5
5
|
* This type map can be used to select value encoders based on the MRI-internal
|
6
6
|
* value type code.
|
@@ -71,16 +71,12 @@ pg_tmbmt_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int fiel
|
|
71
71
|
|
72
72
|
obj = rb_funcall(ask_for_coder, rb_intern("call"), 1, param_value);
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
}else{
|
77
|
-
rb_raise(rb_eTypeError, "argument %d has invalid type %s (should be nil or some kind of PG::Coder)",
|
78
|
-
field+1, rb_obj_classname( obj ));
|
79
|
-
}
|
74
|
+
/* Check argument type and store the coder pointer */
|
75
|
+
TypedData_Get_Struct(obj, t_pg_coder, &pg_coder_type, p_coder);
|
80
76
|
}
|
81
77
|
|
82
78
|
if( !p_coder ){
|
83
|
-
t_typemap *default_tm =
|
79
|
+
t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
84
80
|
return default_tm->funcs.typecast_query_param( default_tm, param_value, field );
|
85
81
|
}
|
86
82
|
|
@@ -90,24 +86,57 @@ pg_tmbmt_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int fiel
|
|
90
86
|
static VALUE
|
91
87
|
pg_tmbmt_fit_to_query( VALUE self, VALUE params )
|
92
88
|
{
|
93
|
-
t_tmbmt *this = (t_tmbmt *)
|
89
|
+
t_tmbmt *this = (t_tmbmt *)RTYPEDDATA_DATA(self);
|
94
90
|
/* Nothing to check at this typemap, but ensure that the default type map fits. */
|
95
|
-
t_typemap *default_tm =
|
91
|
+
t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
96
92
|
default_tm->funcs.fit_to_query( this->typemap.default_typemap, params );
|
97
93
|
return self;
|
98
94
|
}
|
99
95
|
|
100
96
|
#define GC_MARK_AS_USED(type) \
|
101
|
-
|
102
|
-
|
97
|
+
rb_gc_mark_movable( this->coders.ask_##type ); \
|
98
|
+
rb_gc_mark_movable( this->coders.coder_obj_##type );
|
103
99
|
|
104
100
|
static void
|
105
|
-
pg_tmbmt_mark(
|
101
|
+
pg_tmbmt_mark( void *_this )
|
106
102
|
{
|
107
|
-
|
103
|
+
t_tmbmt *this = (t_tmbmt *)_this;
|
104
|
+
pg_typemap_mark(&this->typemap);
|
108
105
|
FOR_EACH_MRI_TYPE( GC_MARK_AS_USED );
|
109
106
|
}
|
110
107
|
|
108
|
+
static size_t
|
109
|
+
pg_tmbmt_memsize( const void *_this )
|
110
|
+
{
|
111
|
+
const t_tmbmt *this = (const t_tmbmt *)_this;
|
112
|
+
return sizeof(*this);
|
113
|
+
}
|
114
|
+
|
115
|
+
#define GC_COMPACT(type) \
|
116
|
+
pg_gc_location( this->coders.ask_##type ); \
|
117
|
+
pg_gc_location( this->coders.coder_obj_##type );
|
118
|
+
|
119
|
+
static void
|
120
|
+
pg_tmbmt_compact( void *_this )
|
121
|
+
{
|
122
|
+
t_tmbmt *this = (t_tmbmt *)_this;
|
123
|
+
pg_typemap_compact(&this->typemap);
|
124
|
+
FOR_EACH_MRI_TYPE( GC_COMPACT );
|
125
|
+
}
|
126
|
+
|
127
|
+
static const rb_data_type_t pg_tmbmt_type = {
|
128
|
+
"PG::TypeMapByMriType",
|
129
|
+
{
|
130
|
+
pg_tmbmt_mark,
|
131
|
+
RUBY_TYPED_DEFAULT_FREE,
|
132
|
+
pg_tmbmt_memsize,
|
133
|
+
pg_compact_callback(pg_tmbmt_compact),
|
134
|
+
},
|
135
|
+
&pg_typemap_type,
|
136
|
+
0,
|
137
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
138
|
+
};
|
139
|
+
|
111
140
|
#define INIT_VARIABLES(type) \
|
112
141
|
this->coders.coder_##type = NULL; \
|
113
142
|
this->coders.ask_##type = Qnil; \
|
@@ -119,7 +148,7 @@ pg_tmbmt_s_allocate( VALUE klass )
|
|
119
148
|
t_tmbmt *this;
|
120
149
|
VALUE self;
|
121
150
|
|
122
|
-
self =
|
151
|
+
self = TypedData_Make_Struct( klass, t_tmbmt, &pg_tmbmt_type, this );
|
123
152
|
this->typemap.funcs.fit_to_result = pg_typemap_fit_to_result;
|
124
153
|
this->typemap.funcs.fit_to_query = pg_tmbmt_fit_to_query;
|
125
154
|
this->typemap.funcs.fit_to_copy_get = pg_typemap_fit_to_copy_get;
|
@@ -140,7 +169,7 @@ pg_tmbmt_s_allocate( VALUE klass )
|
|
140
169
|
this->coders.coder_##type = NULL; \
|
141
170
|
this->coders.ask_##type = Qnil; \
|
142
171
|
}else if(rb_obj_is_kind_of(coder, rb_cPG_Coder)){ \
|
143
|
-
|
172
|
+
TypedData_Get_Struct(coder, t_pg_coder, &pg_coder_type, this->coders.coder_##type); \
|
144
173
|
this->coders.ask_##type = Qnil; \
|
145
174
|
}else if(RB_TYPE_P(coder, T_SYMBOL)){ \
|
146
175
|
this->coders.coder_##type = NULL; \
|
@@ -188,7 +217,7 @@ pg_tmbmt_s_allocate( VALUE klass )
|
|
188
217
|
static VALUE
|
189
218
|
pg_tmbmt_aset( VALUE self, VALUE mri_type, VALUE coder )
|
190
219
|
{
|
191
|
-
t_tmbmt *this =
|
220
|
+
t_tmbmt *this = RTYPEDDATA_DATA( self );
|
192
221
|
char *p_mri_type;
|
193
222
|
|
194
223
|
p_mri_type = StringValueCStr(mri_type);
|
@@ -220,7 +249,7 @@ static VALUE
|
|
220
249
|
pg_tmbmt_aref( VALUE self, VALUE mri_type )
|
221
250
|
{
|
222
251
|
VALUE coder;
|
223
|
-
t_tmbmt *this =
|
252
|
+
t_tmbmt *this = RTYPEDDATA_DATA( self );
|
224
253
|
char *p_mri_type;
|
225
254
|
|
226
255
|
p_mri_type = StringValueCStr(mri_type);
|
@@ -248,7 +277,7 @@ pg_tmbmt_aref( VALUE self, VALUE mri_type )
|
|
248
277
|
static VALUE
|
249
278
|
pg_tmbmt_coders( VALUE self )
|
250
279
|
{
|
251
|
-
t_tmbmt *this =
|
280
|
+
t_tmbmt *this = RTYPEDDATA_DATA( self );
|
252
281
|
VALUE hash_coders = rb_hash_new();
|
253
282
|
|
254
283
|
FOR_EACH_MRI_TYPE( ADD_TO_HASH );
|
@@ -257,7 +286,7 @@ pg_tmbmt_coders( VALUE self )
|
|
257
286
|
}
|
258
287
|
|
259
288
|
void
|
260
|
-
init_pg_type_map_by_mri_type()
|
289
|
+
init_pg_type_map_by_mri_type(void)
|
261
290
|
{
|
262
291
|
/*
|
263
292
|
* Document-class: PG::TypeMapByMriType < PG::TypeMap
|
data/ext/pg_type_map_by_oid.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_type_map_by_oid.c - PG::TypeMapByOid class extension
|
3
|
-
* $Id
|
3
|
+
* $Id$
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -46,7 +46,7 @@ pg_tmbo_lookup_oid(t_tmbo *this, int format, Oid oid)
|
|
46
46
|
} else {
|
47
47
|
VALUE obj = rb_hash_lookup( this->format[format].oid_to_coder, UINT2NUM( oid ));
|
48
48
|
/* obj must be nil or some kind of PG::Coder, this is checked at insertion */
|
49
|
-
conv = NIL_P(obj) ? NULL :
|
49
|
+
conv = NIL_P(obj) ? NULL : RTYPEDDATA_DATA(obj);
|
50
50
|
/* Write the retrieved coder to the cache */
|
51
51
|
p_ce->oid = oid;
|
52
52
|
p_ce->p_coder = conv;
|
@@ -70,7 +70,7 @@ pg_tmbo_build_type_map_for_result2( t_tmbo *this, PGresult *pgresult )
|
|
70
70
|
p_colmap->typemap.default_typemap = pg_typemap_all_strings;
|
71
71
|
|
72
72
|
colmap = pg_tmbc_allocate();
|
73
|
-
|
73
|
+
RTYPEDDATA_DATA(colmap) = p_colmap;
|
74
74
|
|
75
75
|
for(i=0; i<nfields; i++)
|
76
76
|
{
|
@@ -110,21 +110,21 @@ pg_tmbo_result_value(t_typemap *p_typemap, VALUE result, int tuple, int field)
|
|
110
110
|
char * val = PQgetvalue( p_result->pgresult, tuple, field );
|
111
111
|
int len = PQgetlength( p_result->pgresult, tuple, field );
|
112
112
|
t_pg_coder_dec_func dec_func = pg_coder_dec_func( p_coder, format );
|
113
|
-
return dec_func( p_coder, val, len, tuple, field,
|
113
|
+
return dec_func( p_coder, val, len, tuple, field, p_result->enc_idx );
|
114
114
|
}
|
115
115
|
|
116
|
-
default_tm =
|
116
|
+
default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
117
117
|
return default_tm->funcs.typecast_result_value( default_tm, result, tuple, field );
|
118
118
|
}
|
119
119
|
|
120
120
|
static VALUE
|
121
121
|
pg_tmbo_fit_to_result( VALUE self, VALUE result )
|
122
122
|
{
|
123
|
-
t_tmbo *this =
|
123
|
+
t_tmbo *this = RTYPEDDATA_DATA( self );
|
124
124
|
PGresult *pgresult = pgresult_get( result );
|
125
125
|
|
126
|
-
/* Ensure that the default type map fits
|
127
|
-
t_typemap *default_tm =
|
126
|
+
/* Ensure that the default type map fits equally. */
|
127
|
+
t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
128
128
|
VALUE sub_typemap = default_tm->funcs.fit_to_result( this->typemap.default_typemap, result );
|
129
129
|
|
130
130
|
if( PQntuples( pgresult ) <= this->max_rows_for_online_lookup ){
|
@@ -137,7 +137,7 @@ pg_tmbo_fit_to_result( VALUE self, VALUE result )
|
|
137
137
|
/* The default type map built a new object, so we need to propagate it
|
138
138
|
* and build a copy of this type map. */
|
139
139
|
VALUE new_typemap = pg_tmbo_s_allocate( rb_cTypeMapByOid );
|
140
|
-
t_tmbo *p_new_typemap =
|
140
|
+
t_tmbo *p_new_typemap = RTYPEDDATA_DATA(new_typemap);
|
141
141
|
*p_new_typemap = *this;
|
142
142
|
p_new_typemap->typemap.default_typemap = sub_typemap;
|
143
143
|
return new_typemap;
|
@@ -147,23 +147,56 @@ pg_tmbo_fit_to_result( VALUE self, VALUE result )
|
|
147
147
|
* uses a fast array lookup.
|
148
148
|
*/
|
149
149
|
VALUE new_typemap = pg_tmbo_build_type_map_for_result2( this, pgresult );
|
150
|
-
t_tmbo *p_new_typemap =
|
150
|
+
t_tmbo *p_new_typemap = RTYPEDDATA_DATA(new_typemap);
|
151
151
|
p_new_typemap->typemap.default_typemap = sub_typemap;
|
152
152
|
return new_typemap;
|
153
153
|
}
|
154
154
|
}
|
155
155
|
|
156
156
|
static void
|
157
|
-
pg_tmbo_mark(
|
157
|
+
pg_tmbo_mark( void *_this )
|
158
158
|
{
|
159
|
+
t_tmbo *this = (t_tmbo *)_this;
|
159
160
|
int i;
|
160
161
|
|
161
|
-
|
162
|
+
pg_typemap_mark(&this->typemap);
|
162
163
|
for( i=0; i<2; i++){
|
163
|
-
|
164
|
+
rb_gc_mark_movable(this->format[i].oid_to_coder);
|
164
165
|
}
|
165
166
|
}
|
166
167
|
|
168
|
+
static size_t
|
169
|
+
pg_tmbo_memsize( const void *_this )
|
170
|
+
{
|
171
|
+
const t_tmbo *this = (const t_tmbo *)_this;
|
172
|
+
return sizeof(*this);
|
173
|
+
}
|
174
|
+
|
175
|
+
static void
|
176
|
+
pg_tmbo_compact( void *_this )
|
177
|
+
{
|
178
|
+
t_tmbo *this = (t_tmbo *)_this;
|
179
|
+
int i;
|
180
|
+
|
181
|
+
pg_typemap_compact(&this->typemap);
|
182
|
+
for( i=0; i<2; i++){
|
183
|
+
pg_gc_location(this->format[i].oid_to_coder);
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
static const rb_data_type_t pg_tmbo_type = {
|
188
|
+
"PG::TypeMapByOid",
|
189
|
+
{
|
190
|
+
pg_tmbo_mark,
|
191
|
+
RUBY_TYPED_DEFAULT_FREE,
|
192
|
+
pg_tmbo_memsize,
|
193
|
+
pg_compact_callback(pg_tmbo_compact),
|
194
|
+
},
|
195
|
+
&pg_typemap_type,
|
196
|
+
0,
|
197
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
198
|
+
};
|
199
|
+
|
167
200
|
static VALUE
|
168
201
|
pg_tmbo_s_allocate( VALUE klass )
|
169
202
|
{
|
@@ -171,7 +204,7 @@ pg_tmbo_s_allocate( VALUE klass )
|
|
171
204
|
VALUE self;
|
172
205
|
int i;
|
173
206
|
|
174
|
-
self =
|
207
|
+
self = TypedData_Make_Struct( klass, t_tmbo, &pg_tmbo_type, this );
|
175
208
|
|
176
209
|
this->typemap.funcs.fit_to_result = pg_tmbo_fit_to_result;
|
177
210
|
this->typemap.funcs.fit_to_query = pg_typemap_fit_to_query;
|
@@ -179,11 +212,11 @@ pg_tmbo_s_allocate( VALUE klass )
|
|
179
212
|
this->typemap.funcs.typecast_result_value = pg_tmbo_result_value;
|
180
213
|
this->typemap.funcs.typecast_query_param = pg_typemap_typecast_query_param;
|
181
214
|
this->typemap.funcs.typecast_copy_get = pg_typemap_typecast_copy_get;
|
182
|
-
this->typemap.default_typemap
|
215
|
+
RB_OBJ_WRITE(self, &this->typemap.default_typemap, pg_typemap_all_strings);
|
183
216
|
this->max_rows_for_online_lookup = 10;
|
184
217
|
|
185
218
|
for( i=0; i<2; i++){
|
186
|
-
this->format[i].oid_to_coder
|
219
|
+
RB_OBJ_WRITE(self, &this->format[i].oid_to_coder, rb_hash_new());
|
187
220
|
}
|
188
221
|
|
189
222
|
return self;
|
@@ -205,15 +238,12 @@ static VALUE
|
|
205
238
|
pg_tmbo_add_coder( VALUE self, VALUE coder )
|
206
239
|
{
|
207
240
|
VALUE hash;
|
208
|
-
t_tmbo *this =
|
241
|
+
t_tmbo *this = RTYPEDDATA_DATA( self );
|
209
242
|
t_pg_coder *p_coder;
|
210
243
|
struct pg_tmbo_oid_cache_entry *p_ce;
|
211
244
|
|
212
|
-
|
213
|
-
|
214
|
-
rb_obj_classname( coder ));
|
215
|
-
|
216
|
-
Data_Get_Struct(coder, t_pg_coder, p_coder);
|
245
|
+
rb_check_frozen(self);
|
246
|
+
TypedData_Get_Struct(coder, t_pg_coder, &pg_coder_type, p_coder);
|
217
247
|
|
218
248
|
if( p_coder->format < 0 || p_coder->format > 1 )
|
219
249
|
rb_raise(rb_eArgError, "invalid format code %d", p_coder->format);
|
@@ -243,10 +273,11 @@ pg_tmbo_rm_coder( VALUE self, VALUE format, VALUE oid )
|
|
243
273
|
{
|
244
274
|
VALUE hash;
|
245
275
|
VALUE coder;
|
246
|
-
t_tmbo *this =
|
276
|
+
t_tmbo *this = RTYPEDDATA_DATA( self );
|
247
277
|
int i_format = NUM2INT(format);
|
248
278
|
struct pg_tmbo_oid_cache_entry *p_ce;
|
249
279
|
|
280
|
+
rb_check_frozen(self);
|
250
281
|
if( i_format < 0 || i_format > 1 )
|
251
282
|
rb_raise(rb_eArgError, "invalid format code %d", i_format);
|
252
283
|
|
@@ -269,7 +300,7 @@ pg_tmbo_rm_coder( VALUE self, VALUE format, VALUE oid )
|
|
269
300
|
static VALUE
|
270
301
|
pg_tmbo_coders( VALUE self )
|
271
302
|
{
|
272
|
-
t_tmbo *this =
|
303
|
+
t_tmbo *this = RTYPEDDATA_DATA( self );
|
273
304
|
|
274
305
|
return rb_ary_concat(
|
275
306
|
rb_funcall(this->format[0].oid_to_coder, rb_intern("values"), 0),
|
@@ -288,7 +319,8 @@ pg_tmbo_coders( VALUE self )
|
|
288
319
|
static VALUE
|
289
320
|
pg_tmbo_max_rows_for_online_lookup_set( VALUE self, VALUE value )
|
290
321
|
{
|
291
|
-
t_tmbo *this =
|
322
|
+
t_tmbo *this = RTYPEDDATA_DATA( self );
|
323
|
+
rb_check_frozen(self);
|
292
324
|
this->max_rows_for_online_lookup = NUM2INT(value);
|
293
325
|
return value;
|
294
326
|
}
|
@@ -300,7 +332,7 @@ pg_tmbo_max_rows_for_online_lookup_set( VALUE self, VALUE value )
|
|
300
332
|
static VALUE
|
301
333
|
pg_tmbo_max_rows_for_online_lookup_get( VALUE self )
|
302
334
|
{
|
303
|
-
t_tmbo *this =
|
335
|
+
t_tmbo *this = RTYPEDDATA_DATA( self );
|
304
336
|
return INT2NUM(this->max_rows_for_online_lookup);
|
305
337
|
}
|
306
338
|
|
@@ -309,13 +341,13 @@ pg_tmbo_max_rows_for_online_lookup_get( VALUE self )
|
|
309
341
|
* typemap.build_column_map( result )
|
310
342
|
*
|
311
343
|
* This builds a PG::TypeMapByColumn that fits to the given PG::Result object
|
312
|
-
* based on it's type OIDs.
|
344
|
+
* based on it's type OIDs and binary/text format.
|
313
345
|
*
|
314
346
|
*/
|
315
347
|
static VALUE
|
316
348
|
pg_tmbo_build_column_map( VALUE self, VALUE result )
|
317
349
|
{
|
318
|
-
t_tmbo *this =
|
350
|
+
t_tmbo *this = RTYPEDDATA_DATA( self );
|
319
351
|
|
320
352
|
if ( !rb_obj_is_kind_of(result, rb_cPGresult) ) {
|
321
353
|
rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::Result)",
|
@@ -327,7 +359,7 @@ pg_tmbo_build_column_map( VALUE self, VALUE result )
|
|
327
359
|
|
328
360
|
|
329
361
|
void
|
330
|
-
init_pg_type_map_by_oid()
|
362
|
+
init_pg_type_map_by_oid(void)
|
331
363
|
{
|
332
364
|
s_id_decode = rb_intern("decode");
|
333
365
|
|
@@ -351,5 +383,6 @@ init_pg_type_map_by_oid()
|
|
351
383
|
rb_define_method( rb_cTypeMapByOid, "max_rows_for_online_lookup=", pg_tmbo_max_rows_for_online_lookup_set, 1 );
|
352
384
|
rb_define_method( rb_cTypeMapByOid, "max_rows_for_online_lookup", pg_tmbo_max_rows_for_online_lookup_get, 0 );
|
353
385
|
rb_define_method( rb_cTypeMapByOid, "build_column_map", pg_tmbo_build_column_map, 1 );
|
386
|
+
/* rb_mDefaultTypeMappable = rb_define_module_under( rb_cTypeMap, "DefaultTypeMappable"); */
|
354
387
|
rb_include_module( rb_cTypeMapByOid, rb_mDefaultTypeMappable );
|
355
388
|
}
|
data/ext/pg_type_map_in_ruby.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_type_map_in_ruby.c - PG::TypeMapInRuby class extension
|
3
|
-
* $Id
|
3
|
+
* $Id$
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -19,6 +19,33 @@ typedef struct {
|
|
19
19
|
VALUE self;
|
20
20
|
} t_tmir;
|
21
21
|
|
22
|
+
static size_t
|
23
|
+
pg_tmir_memsize( const void *_this )
|
24
|
+
{
|
25
|
+
const t_tmir *this = (const t_tmir *)_this;
|
26
|
+
return sizeof(*this);
|
27
|
+
}
|
28
|
+
|
29
|
+
static void
|
30
|
+
pg_tmir_compact( void *_this )
|
31
|
+
{
|
32
|
+
t_tmir *this = (t_tmir *)_this;
|
33
|
+
pg_typemap_compact(&this->typemap);
|
34
|
+
pg_gc_location(this->self);
|
35
|
+
}
|
36
|
+
|
37
|
+
static const rb_data_type_t pg_tmir_type = {
|
38
|
+
"PG::TypeMapInRuby",
|
39
|
+
{
|
40
|
+
pg_typemap_mark,
|
41
|
+
RUBY_TYPED_DEFAULT_FREE,
|
42
|
+
pg_tmir_memsize,
|
43
|
+
pg_compact_callback(pg_tmir_compact),
|
44
|
+
},
|
45
|
+
&pg_typemap_type,
|
46
|
+
0,
|
47
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
48
|
+
};
|
22
49
|
|
23
50
|
/*
|
24
51
|
* call-seq:
|
@@ -34,33 +61,37 @@ typedef struct {
|
|
34
61
|
static VALUE
|
35
62
|
pg_tmir_fit_to_result( VALUE self, VALUE result )
|
36
63
|
{
|
37
|
-
t_tmir *this =
|
64
|
+
t_tmir *this = RTYPEDDATA_DATA( self );
|
38
65
|
t_typemap *default_tm;
|
39
66
|
t_typemap *p_new_typemap;
|
40
67
|
VALUE sub_typemap;
|
41
68
|
VALUE new_typemap;
|
42
69
|
|
43
70
|
if( rb_respond_to(self, s_id_fit_to_result) ){
|
71
|
+
t_typemap *tm;
|
72
|
+
UNUSED(tm);
|
44
73
|
new_typemap = rb_funcall( self, s_id_fit_to_result, 1, result );
|
45
74
|
|
46
75
|
if ( !rb_obj_is_kind_of(new_typemap, rb_cTypeMap) ) {
|
76
|
+
/* TypedData_Get_Struct() raises "wrong argument type", which is misleading,
|
77
|
+
* so we better raise our own message */
|
47
78
|
rb_raise( rb_eTypeError, "wrong return type from fit_to_result: %s expected kind of PG::TypeMap",
|
48
79
|
rb_obj_classname( new_typemap ) );
|
49
80
|
}
|
50
|
-
|
81
|
+
TypedData_Get_Struct(new_typemap, t_typemap, &pg_typemap_type, tm);
|
51
82
|
} else {
|
52
83
|
new_typemap = self;
|
53
84
|
}
|
54
85
|
|
55
|
-
/* Ensure that the default type map fits
|
56
|
-
default_tm =
|
86
|
+
/* Ensure that the default type map fits equally. */
|
87
|
+
default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
57
88
|
sub_typemap = default_tm->funcs.fit_to_result( this->typemap.default_typemap, result );
|
58
89
|
|
59
90
|
if( sub_typemap != this->typemap.default_typemap ){
|
60
91
|
new_typemap = rb_obj_dup( new_typemap );
|
61
92
|
}
|
62
93
|
|
63
|
-
p_new_typemap =
|
94
|
+
p_new_typemap = RTYPEDDATA_DATA(new_typemap);
|
64
95
|
p_new_typemap->default_typemap = sub_typemap;
|
65
96
|
return new_typemap;
|
66
97
|
}
|
@@ -95,8 +126,8 @@ pg_tmir_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field )
|
|
95
126
|
static VALUE
|
96
127
|
pg_tmir_typecast_result_value( VALUE self, VALUE result, VALUE tuple, VALUE field )
|
97
128
|
{
|
98
|
-
t_tmir *this =
|
99
|
-
t_typemap *default_tm =
|
129
|
+
t_tmir *this = RTYPEDDATA_DATA( self );
|
130
|
+
t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
100
131
|
return default_tm->funcs.typecast_result_value( default_tm, result, NUM2INT(tuple), NUM2INT(field) );
|
101
132
|
}
|
102
133
|
|
@@ -113,15 +144,15 @@ pg_tmir_typecast_result_value( VALUE self, VALUE result, VALUE tuple, VALUE fiel
|
|
113
144
|
static VALUE
|
114
145
|
pg_tmir_fit_to_query( VALUE self, VALUE params )
|
115
146
|
{
|
116
|
-
t_tmir *this =
|
147
|
+
t_tmir *this = RTYPEDDATA_DATA( self );
|
117
148
|
t_typemap *default_tm;
|
118
149
|
|
119
150
|
if( rb_respond_to(self, s_id_fit_to_query) ){
|
120
151
|
rb_funcall( self, s_id_fit_to_query, 1, params );
|
121
152
|
}
|
122
153
|
|
123
|
-
/* Ensure that the default type map fits
|
124
|
-
default_tm =
|
154
|
+
/* Ensure that the default type map fits equally. */
|
155
|
+
default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
125
156
|
default_tm->funcs.fit_to_query( this->typemap.default_typemap, params );
|
126
157
|
|
127
158
|
return self;
|
@@ -137,7 +168,7 @@ pg_tmir_query_param( t_typemap *p_typemap, VALUE param_value, int field )
|
|
137
168
|
if ( NIL_P(coder) ){
|
138
169
|
return NULL;
|
139
170
|
} else if( rb_obj_is_kind_of(coder, rb_cPG_Coder) ) {
|
140
|
-
return
|
171
|
+
return RTYPEDDATA_DATA(coder);
|
141
172
|
} else {
|
142
173
|
rb_raise( rb_eTypeError, "wrong return type from typecast_query_param: %s expected nil or kind of PG::Coder",
|
143
174
|
rb_obj_classname( coder ) );
|
@@ -161,8 +192,8 @@ pg_tmir_query_param( t_typemap *p_typemap, VALUE param_value, int field )
|
|
161
192
|
static VALUE
|
162
193
|
pg_tmir_typecast_query_param( VALUE self, VALUE param_value, VALUE field )
|
163
194
|
{
|
164
|
-
t_tmir *this =
|
165
|
-
t_typemap *default_tm =
|
195
|
+
t_tmir *this = RTYPEDDATA_DATA( self );
|
196
|
+
t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
166
197
|
t_pg_coder *p_coder = default_tm->funcs.typecast_query_param( default_tm, param_value, NUM2INT(field) );
|
167
198
|
|
168
199
|
return p_coder ? p_coder->coder_obj : Qnil;
|
@@ -179,6 +210,9 @@ pg_tmir_typecast_query_param( VALUE self, VALUE param_value, VALUE field )
|
|
179
210
|
* This method is called, when a type map is used for decoding copy data,
|
180
211
|
* before the value is casted.
|
181
212
|
*
|
213
|
+
* Should return the expected number of columns or 0 if the number of columns is unknown.
|
214
|
+
* This number is only used for memory pre-allocation.
|
215
|
+
*
|
182
216
|
*/
|
183
217
|
static VALUE pg_tmir_fit_to_copy_get_dummy( VALUE self ){}
|
184
218
|
#endif
|
@@ -186,7 +220,7 @@ static VALUE pg_tmir_fit_to_copy_get_dummy( VALUE self ){}
|
|
186
220
|
static int
|
187
221
|
pg_tmir_fit_to_copy_get( VALUE self )
|
188
222
|
{
|
189
|
-
t_tmir *this =
|
223
|
+
t_tmir *this = RTYPEDDATA_DATA( self );
|
190
224
|
t_typemap *default_tm;
|
191
225
|
VALUE num_columns = INT2NUM(0);
|
192
226
|
|
@@ -198,8 +232,8 @@ pg_tmir_fit_to_copy_get( VALUE self )
|
|
198
232
|
rb_raise( rb_eTypeError, "wrong return type from fit_to_copy_get: %s expected kind of Integer",
|
199
233
|
rb_obj_classname( num_columns ) );
|
200
234
|
}
|
201
|
-
/* Ensure that the default type map fits
|
202
|
-
default_tm =
|
235
|
+
/* Ensure that the default type map fits equally. */
|
236
|
+
default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
203
237
|
default_tm->funcs.fit_to_copy_get( this->typemap.default_typemap );
|
204
238
|
|
205
239
|
return NUM2INT(num_columns);;
|
@@ -239,8 +273,8 @@ pg_tmir_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, int format
|
|
239
273
|
static VALUE
|
240
274
|
pg_tmir_typecast_copy_get( VALUE self, VALUE field_str, VALUE fieldno, VALUE format, VALUE enc )
|
241
275
|
{
|
242
|
-
t_tmir *this =
|
243
|
-
t_typemap *default_tm =
|
276
|
+
t_tmir *this = RTYPEDDATA_DATA( self );
|
277
|
+
t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
244
278
|
int enc_idx = rb_to_encoding_index( enc );
|
245
279
|
|
246
280
|
return default_tm->funcs.typecast_copy_get( default_tm, field_str, NUM2INT(fieldno), NUM2INT(format), enc_idx );
|
@@ -252,7 +286,7 @@ pg_tmir_s_allocate( VALUE klass )
|
|
252
286
|
t_tmir *this;
|
253
287
|
VALUE self;
|
254
288
|
|
255
|
-
self =
|
289
|
+
self = TypedData_Make_Struct( klass, t_tmir, &pg_tmir_type, this );
|
256
290
|
|
257
291
|
this->typemap.funcs.fit_to_result = pg_tmir_fit_to_result;
|
258
292
|
this->typemap.funcs.fit_to_query = pg_tmir_fit_to_query;
|
@@ -260,7 +294,7 @@ pg_tmir_s_allocate( VALUE klass )
|
|
260
294
|
this->typemap.funcs.typecast_result_value = pg_tmir_result_value;
|
261
295
|
this->typemap.funcs.typecast_query_param = pg_tmir_query_param;
|
262
296
|
this->typemap.funcs.typecast_copy_get = pg_tmir_copy_get;
|
263
|
-
this->typemap.default_typemap
|
297
|
+
RB_OBJ_WRITE(self, &this->typemap.default_typemap, pg_typemap_all_strings);
|
264
298
|
this->self = self;
|
265
299
|
|
266
300
|
return self;
|
@@ -268,7 +302,7 @@ pg_tmir_s_allocate( VALUE klass )
|
|
268
302
|
|
269
303
|
|
270
304
|
void
|
271
|
-
init_pg_type_map_in_ruby()
|
305
|
+
init_pg_type_map_in_ruby(void)
|
272
306
|
{
|
273
307
|
s_id_fit_to_result = rb_intern("fit_to_result");
|
274
308
|
s_id_fit_to_query = rb_intern("fit_to_query");
|
data/ext/{util.c → pg_util.c}
RENAMED
@@ -1,11 +1,11 @@
|
|
1
1
|
/*
|
2
|
-
*
|
3
|
-
* $Id
|
2
|
+
* pg_util.c - Utils for ruby-pg
|
3
|
+
* $Id$
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
7
7
|
#include "pg.h"
|
8
|
-
#include "
|
8
|
+
#include "pg_util.h"
|
9
9
|
|
10
10
|
static const char base64_encode_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
11
11
|
|
@@ -15,19 +15,19 @@ static const char base64_encode_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk
|
|
15
15
|
* in-place (with _out_ == _in_).
|
16
16
|
*/
|
17
17
|
void
|
18
|
-
base64_encode( char *out, char *in, int len)
|
18
|
+
base64_encode( char *out, const char *in, int len)
|
19
19
|
{
|
20
|
-
unsigned char *in_ptr = (unsigned char *)in + len;
|
20
|
+
const unsigned char *in_ptr = (const unsigned char *)in + len;
|
21
21
|
char *out_ptr = out + BASE64_ENCODED_SIZE(len);
|
22
22
|
int part_len = len % 3;
|
23
23
|
|
24
24
|
if( part_len > 0 ){
|
25
|
-
long byte2 =
|
25
|
+
long byte2 = 0;
|
26
26
|
long byte1 = part_len > 1 ? *--in_ptr : 0;
|
27
27
|
long byte0 = *--in_ptr;
|
28
28
|
long triple = (byte0 << 16) + (byte1 << 8) + byte2;
|
29
29
|
|
30
|
-
*--out_ptr =
|
30
|
+
*--out_ptr = '=';
|
31
31
|
*--out_ptr = part_len > 1 ? base64_encode_table[(triple >> 1 * 6) & 0x3F] : '=';
|
32
32
|
*--out_ptr = base64_encode_table[(triple >> 2 * 6) & 0x3F];
|
33
33
|
*--out_ptr = base64_encode_table[(triple >> 3 * 6) & 0x3F];
|
@@ -72,12 +72,12 @@ static const unsigned char base64_decode_table[] =
|
|
72
72
|
* It is possible to decode a string in-place (with _out_ == _in_).
|
73
73
|
*/
|
74
74
|
int
|
75
|
-
base64_decode( char *out, char *in, unsigned int len)
|
75
|
+
base64_decode( char *out, const char *in, unsigned int len)
|
76
76
|
{
|
77
77
|
unsigned char a, b, c, d;
|
78
|
-
unsigned char *in_ptr = (unsigned char *)in;
|
78
|
+
const unsigned char *in_ptr = (const unsigned char *)in;
|
79
79
|
unsigned char *out_ptr = (unsigned char *)out;
|
80
|
-
unsigned char *iend_ptr = (unsigned char *)in + len;
|
80
|
+
const unsigned char *iend_ptr = (unsigned char *)in + len;
|
81
81
|
|
82
82
|
for(;;){
|
83
83
|
if( in_ptr+3 < iend_ptr &&
|
@@ -91,7 +91,7 @@ base64_decode( char *out, char *in, unsigned int len)
|
|
91
91
|
*out_ptr++ = (b << 4) | (c >> 2);
|
92
92
|
*out_ptr++ = (c << 6) | d;
|
93
93
|
} else if (in_ptr < iend_ptr){
|
94
|
-
|
94
|
+
b = c = d = 0xff;
|
95
95
|
while ((a = base64_decode_table[*in_ptr++]) == 0xff && in_ptr < iend_ptr) {}
|
96
96
|
if (in_ptr < iend_ptr){
|
97
97
|
while ((b = base64_decode_table[*in_ptr++]) == 0xff && in_ptr < iend_ptr) {}
|
@@ -116,7 +116,7 @@ base64_decode( char *out, char *in, unsigned int len)
|
|
116
116
|
}
|
117
117
|
|
118
118
|
|
119
|
-
return (char*)out_ptr - out;
|
119
|
+
return (int)((char*)out_ptr - out);
|
120
120
|
}
|
121
121
|
|
122
122
|
/*
|
data/ext/{util.h → pg_util.h}
RENAMED
@@ -57,8 +57,8 @@
|
|
57
57
|
#define BASE64_ENCODED_SIZE(strlen) (((strlen) + 2) / 3 * 4)
|
58
58
|
#define BASE64_DECODED_SIZE(base64len) (((base64len) + 3) / 4 * 3)
|
59
59
|
|
60
|
-
void base64_encode( char *out, char *in, int len);
|
61
|
-
int base64_decode( char *out, char *in, unsigned int len);
|
60
|
+
void base64_encode( char *out, const char *in, int len);
|
61
|
+
int base64_decode( char *out, const char *in, unsigned int len);
|
62
62
|
|
63
63
|
int rbpg_strncasecmp(const char *s1, const char *s2, size_t n);
|
64
64
|
|