pg 1.2.3 → 1.5.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/.appveyor.yml +42 -0
- data/.gems +6 -0
- data/.github/workflows/binary-gems.yml +117 -0
- data/.github/workflows/source-gem.yml +137 -0
- data/.gitignore +22 -0
- data/.hgsigs +34 -0
- data/.hgtags +41 -0
- data/.irbrc +23 -0
- data/.pryrc +23 -0
- data/.tm_properties +21 -0
- data/.travis.yml +49 -0
- data/Gemfile +14 -0
- data/History.md +876 -0
- data/Manifest.txt +0 -1
- data/README.ja.md +276 -0
- data/README.md +286 -0
- data/Rakefile +33 -135
- data/Rakefile.cross +12 -13
- data/certs/ged.pem +24 -0
- data/certs/larskanis-2022.pem +26 -0
- data/certs/larskanis-2023.pem +24 -0
- data/ext/errorcodes.def +12 -0
- data/ext/errorcodes.rb +0 -0
- data/ext/errorcodes.txt +4 -1
- data/ext/extconf.rb +100 -25
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +23 -0
- data/ext/pg.c +72 -57
- data/ext/pg.h +28 -4
- data/ext/pg_binary_decoder.c +80 -1
- data/ext/pg_binary_encoder.c +225 -1
- data/ext/pg_coder.c +96 -33
- data/ext/pg_connection.c +996 -697
- data/ext/pg_copy_coder.c +351 -33
- data/ext/pg_errors.c +1 -1
- data/ext/pg_record_coder.c +50 -19
- data/ext/pg_result.c +177 -64
- data/ext/pg_text_decoder.c +29 -11
- data/ext/pg_text_encoder.c +29 -16
- data/ext/pg_tuple.c +83 -60
- data/ext/pg_type_map.c +44 -10
- data/ext/pg_type_map_all_strings.c +17 -3
- data/ext/pg_type_map_by_class.c +54 -27
- data/ext/pg_type_map_by_column.c +73 -31
- data/ext/pg_type_map_by_mri_type.c +48 -19
- data/ext/pg_type_map_by_oid.c +59 -27
- data/ext/pg_type_map_in_ruby.c +55 -21
- data/ext/pg_util.c +2 -2
- data/lib/pg/basic_type_map_based_on_result.rb +67 -0
- data/lib/pg/basic_type_map_for_queries.rb +198 -0
- data/lib/pg/basic_type_map_for_results.rb +104 -0
- data/lib/pg/basic_type_registry.rb +299 -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 +15 -13
- data/lib/pg/connection.rb +743 -83
- data/lib/pg/exceptions.rb +14 -1
- data/lib/pg/text_decoder/date.rb +18 -0
- data/lib/pg/text_decoder/inet.rb +9 -0
- data/lib/pg/text_decoder/json.rb +14 -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 +12 -0
- data/lib/pg/text_encoder/inet.rb +28 -0
- data/lib/pg/text_encoder/json.rb +14 -0
- data/lib/pg/text_encoder/numeric.rb +9 -0
- data/lib/pg/text_encoder/timestamp.rb +24 -0
- data/lib/pg/version.rb +4 -0
- data/lib/pg.rb +94 -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 +34 -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/translation/.po4a-version +7 -0
- data/translation/po/all.pot +910 -0
- data/translation/po/ja.po +1047 -0
- data/translation/po4a.cfg +12 -0
- data.tar.gz.sig +0 -0
- metadata +142 -210
- metadata.gz.sig +0 -0
- data/ChangeLog +0 -0
- data/History.rdoc +0 -578
- data/README.ja.rdoc +0 -13
- data/README.rdoc +0 -213
- data/lib/pg/basic_type_mapping.rb +0 -522
- data/lib/pg/binary_decoder.rb +0 -23
- data/lib/pg/constants.rb +0 -12
- data/lib/pg/text_decoder.rb +0 -46
- data/lib/pg/text_encoder.rb +0 -59
- data/spec/data/expected_trace.out +0 -26
- data/spec/data/random_binary_data +0 -0
- data/spec/helpers.rb +0 -380
- data/spec/pg/basic_type_mapping_spec.rb +0 -630
- data/spec/pg/connection_spec.rb +0 -1949
- data/spec/pg/connection_sync_spec.rb +0 -41
- data/spec/pg/result_spec.rb +0 -681
- data/spec/pg/tuple_spec.rb +0 -333
- data/spec/pg/type_map_by_class_spec.rb +0 -138
- data/spec/pg/type_map_by_column_spec.rb +0 -226
- 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 -1123
- data/spec/pg_spec.rb +0 -50
data/ext/gvl_wrappers.h
CHANGED
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
|
|
18
18
|
#include <ruby/thread.h>
|
|
19
19
|
|
|
20
|
+
#ifdef RUBY_EXTCONF_H
|
|
21
|
+
# include RUBY_EXTCONF_H
|
|
22
|
+
#endif
|
|
23
|
+
|
|
20
24
|
#define DEFINE_PARAM_LIST1(type, name) \
|
|
21
25
|
name,
|
|
22
26
|
|
|
@@ -46,6 +50,7 @@
|
|
|
46
50
|
return NULL; \
|
|
47
51
|
}
|
|
48
52
|
|
|
53
|
+
#ifdef ENABLE_GVL_UNLOCK
|
|
49
54
|
#define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
|
50
55
|
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
|
|
51
56
|
struct gvl_wrapper_##name##_params params = { \
|
|
@@ -54,6 +59,13 @@
|
|
|
54
59
|
rb_thread_call_without_gvl(gvl_##name##_skeleton, ¶ms, RUBY_UBF_IO, 0); \
|
|
55
60
|
when_non_void( return params.retval; ) \
|
|
56
61
|
}
|
|
62
|
+
#else
|
|
63
|
+
#define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
|
64
|
+
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
|
|
65
|
+
when_non_void( return ) \
|
|
66
|
+
name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname ); \
|
|
67
|
+
}
|
|
68
|
+
#endif
|
|
57
69
|
|
|
58
70
|
#define DEFINE_GVL_STUB_DECL(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
|
59
71
|
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname);
|
|
@@ -66,6 +78,7 @@
|
|
|
66
78
|
return NULL; \
|
|
67
79
|
}
|
|
68
80
|
|
|
81
|
+
#ifdef ENABLE_GVL_UNLOCK
|
|
69
82
|
#define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
|
70
83
|
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
|
|
71
84
|
struct gvl_wrapper_##name##_params params = { \
|
|
@@ -74,6 +87,13 @@
|
|
|
74
87
|
rb_thread_call_with_gvl(gvl_##name##_skeleton, ¶ms); \
|
|
75
88
|
when_non_void( return params.retval; ) \
|
|
76
89
|
}
|
|
90
|
+
#else
|
|
91
|
+
#define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
|
92
|
+
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
|
|
93
|
+
when_non_void( return ) \
|
|
94
|
+
name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname ); \
|
|
95
|
+
}
|
|
96
|
+
#endif
|
|
77
97
|
|
|
78
98
|
#define GVL_TYPE_VOID(string)
|
|
79
99
|
#define GVL_TYPE_NONVOID(string) string
|
|
@@ -95,6 +115,8 @@
|
|
|
95
115
|
|
|
96
116
|
#define FOR_EACH_PARAM_OF_PQresetPoll(param)
|
|
97
117
|
|
|
118
|
+
#define FOR_EACH_PARAM_OF_PQping(param)
|
|
119
|
+
|
|
98
120
|
#define FOR_EACH_PARAM_OF_PQexec(param) \
|
|
99
121
|
param(PGconn *, conn)
|
|
100
122
|
|
|
@@ -196,6 +218,7 @@
|
|
|
196
218
|
function(PQreset, GVL_TYPE_VOID, void, PGconn *, conn) \
|
|
197
219
|
function(PQresetStart, GVL_TYPE_NONVOID, int, PGconn *, conn) \
|
|
198
220
|
function(PQresetPoll, GVL_TYPE_NONVOID, PostgresPollingStatusType, PGconn *, conn) \
|
|
221
|
+
function(PQping, GVL_TYPE_NONVOID, PGPing, const char *, conninfo) \
|
|
199
222
|
function(PQexec, GVL_TYPE_NONVOID, PGresult *, const char *, command) \
|
|
200
223
|
function(PQexecParams, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
|
|
201
224
|
function(PQexecPrepared, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
|
data/ext/pg.c
CHANGED
|
@@ -33,7 +33,6 @@
|
|
|
33
33
|
*
|
|
34
34
|
* - PQfreemem -- unnecessary: copied to ruby object, then freed. Ruby object's
|
|
35
35
|
* memory is freed when it is garbage collected.
|
|
36
|
-
* - PQbinaryTuples -- better to use PQfformat
|
|
37
36
|
* - PQprint -- not very useful
|
|
38
37
|
* - PQsetdb -- not very useful
|
|
39
38
|
* - PQoidStatus -- deprecated, use PQoidValue
|
|
@@ -74,6 +73,7 @@ VALUE rb_mPGconstants;
|
|
|
74
73
|
* The mapping from canonical encoding names in PostgreSQL to ones in Ruby.
|
|
75
74
|
*/
|
|
76
75
|
const char * const (pg_enc_pg2ruby_mapping[][2]) = {
|
|
76
|
+
{"UTF8", "UTF-8" },
|
|
77
77
|
{"BIG5", "Big5" },
|
|
78
78
|
{"EUC_CN", "GB2312" },
|
|
79
79
|
{"EUC_JP", "EUC-JP" },
|
|
@@ -105,7 +105,6 @@ const char * const (pg_enc_pg2ruby_mapping[][2]) = {
|
|
|
105
105
|
{"SHIFT_JIS_2004","Windows-31J" },
|
|
106
106
|
/* {"SQL_ASCII", NULL }, special case*/
|
|
107
107
|
{"UHC", "CP949" },
|
|
108
|
-
{"UTF8", "UTF-8" },
|
|
109
108
|
{"WIN866", "IBM866" },
|
|
110
109
|
{"WIN874", "Windows-874" },
|
|
111
110
|
{"WIN1250", "Windows-1250"},
|
|
@@ -120,32 +119,6 @@ const char * const (pg_enc_pg2ruby_mapping[][2]) = {
|
|
|
120
119
|
};
|
|
121
120
|
|
|
122
121
|
|
|
123
|
-
/*
|
|
124
|
-
* A cache of mapping from PostgreSQL's encoding indices to Ruby's rb_encoding*s.
|
|
125
|
-
*/
|
|
126
|
-
static struct st_table *enc_pg2ruby;
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
/*
|
|
130
|
-
* Look up the JOHAB encoding, creating it as a dummy encoding if it's not
|
|
131
|
-
* already defined.
|
|
132
|
-
*/
|
|
133
|
-
static rb_encoding *
|
|
134
|
-
pg_find_or_create_johab(void)
|
|
135
|
-
{
|
|
136
|
-
static const char * const aliases[] = { "JOHAB", "Windows-1361", "CP1361" };
|
|
137
|
-
int enc_index;
|
|
138
|
-
size_t i;
|
|
139
|
-
|
|
140
|
-
for (i = 0; i < sizeof(aliases)/sizeof(aliases[0]); ++i) {
|
|
141
|
-
enc_index = rb_enc_find_index(aliases[i]);
|
|
142
|
-
if (enc_index > 0) return rb_enc_from_index(enc_index);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
enc_index = rb_define_dummy_encoding(aliases[0]);
|
|
146
|
-
return rb_enc_from_index(enc_index);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
122
|
/*
|
|
150
123
|
* Return the given PostgreSQL encoding ID as an rb_encoding.
|
|
151
124
|
*
|
|
@@ -155,21 +128,8 @@ pg_find_or_create_johab(void)
|
|
|
155
128
|
rb_encoding *
|
|
156
129
|
pg_get_pg_encoding_as_rb_encoding( int enc_id )
|
|
157
130
|
{
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
/* Use the cached value if it exists */
|
|
161
|
-
if ( st_lookup(enc_pg2ruby, (st_data_t)enc_id, (st_data_t*)&enc) ) {
|
|
162
|
-
return enc;
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
const char *name = pg_encoding_to_char( enc_id );
|
|
166
|
-
|
|
167
|
-
enc = pg_get_pg_encname_as_rb_encoding( name );
|
|
168
|
-
st_insert( enc_pg2ruby, (st_data_t)enc_id, (st_data_t)enc );
|
|
169
|
-
|
|
170
|
-
return enc;
|
|
171
|
-
}
|
|
172
|
-
|
|
131
|
+
const char *name = pg_encoding_to_char( enc_id );
|
|
132
|
+
return pg_get_pg_encname_as_rb_encoding( name );
|
|
173
133
|
}
|
|
174
134
|
|
|
175
135
|
/*
|
|
@@ -186,10 +146,6 @@ pg_get_pg_encname_as_rb_encoding( const char *pg_encname )
|
|
|
186
146
|
return rb_enc_find( pg_enc_pg2ruby_mapping[i][1] );
|
|
187
147
|
}
|
|
188
148
|
|
|
189
|
-
/* JOHAB isn't a builtin encoding, so make up a dummy encoding if it's seen */
|
|
190
|
-
if ( strncmp(pg_encname, "JOHAB", 5) == 0 )
|
|
191
|
-
return pg_find_or_create_johab();
|
|
192
|
-
|
|
193
149
|
/* Fallthrough to ASCII-8BIT */
|
|
194
150
|
return rb_ascii8bit_encoding();
|
|
195
151
|
}
|
|
@@ -376,8 +332,13 @@ pg_s_init_ssl(VALUE self, VALUE do_ssl)
|
|
|
376
332
|
**************************************************************************/
|
|
377
333
|
|
|
378
334
|
void
|
|
379
|
-
Init_pg_ext()
|
|
335
|
+
Init_pg_ext(void)
|
|
380
336
|
{
|
|
337
|
+
|
|
338
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
|
339
|
+
rb_ext_ractor_safe(PQisthreadsafe());
|
|
340
|
+
#endif
|
|
341
|
+
|
|
381
342
|
if( RTEST(rb_eval_string("ENV['PG_SKIP_DEPRECATION_WARNING']")) ){
|
|
382
343
|
/* Set all bits to disable all deprecation warnings. */
|
|
383
344
|
pg_skip_deprecation_warning = 0xFFFF;
|
|
@@ -396,8 +357,8 @@ Init_pg_ext()
|
|
|
396
357
|
SINGLETON_ALIAS( rb_mPG, "is_threadsafe?", "isthreadsafe" );
|
|
397
358
|
SINGLETON_ALIAS( rb_mPG, "threadsafe?", "isthreadsafe" );
|
|
398
359
|
|
|
399
|
-
|
|
400
|
-
|
|
360
|
+
rb_define_singleton_method( rb_mPG, "init_openssl", pg_s_init_openssl, 2 );
|
|
361
|
+
rb_define_singleton_method( rb_mPG, "init_ssl", pg_s_init_ssl, 1 );
|
|
401
362
|
|
|
402
363
|
|
|
403
364
|
/****** PG::Connection CLASS CONSTANTS: Connection Status ******/
|
|
@@ -415,14 +376,34 @@ Init_pg_ext()
|
|
|
415
376
|
rb_define_const(rb_mPGconstants, "CONNECTION_MADE", INT2FIX(CONNECTION_MADE));
|
|
416
377
|
/* Waiting for a response from the server. */
|
|
417
378
|
rb_define_const(rb_mPGconstants, "CONNECTION_AWAITING_RESPONSE", INT2FIX(CONNECTION_AWAITING_RESPONSE));
|
|
418
|
-
/* Received authentication; waiting for backend
|
|
379
|
+
/* Received authentication; waiting for backend startup. */
|
|
419
380
|
rb_define_const(rb_mPGconstants, "CONNECTION_AUTH_OK", INT2FIX(CONNECTION_AUTH_OK));
|
|
381
|
+
/* This state is no longer used. */
|
|
382
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_SETENV", INT2FIX(CONNECTION_SETENV));
|
|
420
383
|
/* Negotiating SSL encryption. */
|
|
421
384
|
rb_define_const(rb_mPGconstants, "CONNECTION_SSL_STARTUP", INT2FIX(CONNECTION_SSL_STARTUP));
|
|
422
|
-
/* Negotiating environment-driven parameter settings. */
|
|
423
|
-
rb_define_const(rb_mPGconstants, "CONNECTION_SETENV", INT2FIX(CONNECTION_SETENV));
|
|
424
385
|
/* Internal state - PG.connect() needed. */
|
|
425
386
|
rb_define_const(rb_mPGconstants, "CONNECTION_NEEDED", INT2FIX(CONNECTION_NEEDED));
|
|
387
|
+
#if PG_MAJORVERSION_NUM >= 10
|
|
388
|
+
/* Checking if session is read-write. Available since PostgreSQL-10. */
|
|
389
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_CHECK_WRITABLE", INT2FIX(CONNECTION_CHECK_WRITABLE));
|
|
390
|
+
#endif
|
|
391
|
+
#if PG_MAJORVERSION_NUM >= 10
|
|
392
|
+
/* Consuming any extra messages. Available since PostgreSQL-10. */
|
|
393
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_CONSUME", INT2FIX(CONNECTION_CONSUME));
|
|
394
|
+
#endif
|
|
395
|
+
#if PG_MAJORVERSION_NUM >= 12
|
|
396
|
+
/* Negotiating GSSAPI. Available since PostgreSQL-12. */
|
|
397
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_GSS_STARTUP", INT2FIX(CONNECTION_GSS_STARTUP));
|
|
398
|
+
#endif
|
|
399
|
+
#if PG_MAJORVERSION_NUM >= 13
|
|
400
|
+
/* Checking target server properties. Available since PostgreSQL-13. */
|
|
401
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_CHECK_TARGET", INT2FIX(CONNECTION_CHECK_TARGET));
|
|
402
|
+
#endif
|
|
403
|
+
#if PG_MAJORVERSION_NUM >= 14
|
|
404
|
+
/* Checking if server is in standby mode. Available since PostgreSQL-14. */
|
|
405
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_CHECK_STANDBY", INT2FIX(CONNECTION_CHECK_STANDBY));
|
|
406
|
+
#endif
|
|
426
407
|
|
|
427
408
|
/****** PG::Connection CLASS CONSTANTS: Nonblocking connection polling status ******/
|
|
428
409
|
|
|
@@ -526,6 +507,19 @@ Init_pg_ext()
|
|
|
526
507
|
/* Result#result_status constant - Single tuple from larger resultset. */
|
|
527
508
|
rb_define_const(rb_mPGconstants, "PGRES_SINGLE_TUPLE", INT2FIX(PGRES_SINGLE_TUPLE));
|
|
528
509
|
|
|
510
|
+
#ifdef HAVE_PQENTERPIPELINEMODE
|
|
511
|
+
/* Result#result_status constant - The PG::Result represents a synchronization point in pipeline mode, requested by Connection#pipeline_sync.
|
|
512
|
+
*
|
|
513
|
+
* This status occurs only when pipeline mode has been selected. */
|
|
514
|
+
rb_define_const(rb_mPGconstants, "PGRES_PIPELINE_SYNC", INT2FIX(PGRES_PIPELINE_SYNC));
|
|
515
|
+
|
|
516
|
+
/* Result#result_status constant - The PG::Result represents a pipeline that has received an error from the server.
|
|
517
|
+
*
|
|
518
|
+
* Connection#get_result must be called repeatedly, and each time it will return this status code until the end of the current pipeline, at which point it will return PG::PGRES_PIPELINE_SYNC and normal processing can resume.
|
|
519
|
+
*/
|
|
520
|
+
rb_define_const(rb_mPGconstants, "PGRES_PIPELINE_ABORTED", INT2FIX(PGRES_PIPELINE_ABORTED));
|
|
521
|
+
#endif
|
|
522
|
+
|
|
529
523
|
/****** Result CONSTANTS: result error field codes ******/
|
|
530
524
|
|
|
531
525
|
/* Result#result_error_field argument constant
|
|
@@ -549,7 +543,7 @@ Init_pg_ext()
|
|
|
549
543
|
/* Result#result_error_field argument constant
|
|
550
544
|
*
|
|
551
545
|
* The SQLSTATE code for the error.
|
|
552
|
-
* The SQLSTATE code identies the type of error that has occurred; it can be used by front-end applications to perform
|
|
546
|
+
* The SQLSTATE code identies the type of error that has occurred; it can be used by front-end applications to perform specific operations (such as error handling) in response to a particular database error.
|
|
553
547
|
* For a list of the possible SQLSTATE codes, see Appendix A.
|
|
554
548
|
* This field is not localizable, and is always present.
|
|
555
549
|
*/
|
|
@@ -645,15 +639,37 @@ Init_pg_ext()
|
|
|
645
639
|
rb_define_const(rb_mPGconstants, "PG_DIAG_CONSTRAINT_NAME", INT2FIX(PG_DIAG_CONSTRAINT_NAME));
|
|
646
640
|
#endif
|
|
647
641
|
|
|
642
|
+
#ifdef HAVE_PQENTERPIPELINEMODE
|
|
643
|
+
/* Connection#pipeline_status constant
|
|
644
|
+
*
|
|
645
|
+
* The libpq connection is in pipeline mode.
|
|
646
|
+
*/
|
|
647
|
+
rb_define_const(rb_mPGconstants, "PQ_PIPELINE_ON", INT2FIX(PQ_PIPELINE_ON));
|
|
648
|
+
|
|
649
|
+
/* Connection#pipeline_status constant
|
|
650
|
+
*
|
|
651
|
+
* The libpq connection is not in pipeline mode.
|
|
652
|
+
*/
|
|
653
|
+
rb_define_const(rb_mPGconstants, "PQ_PIPELINE_OFF", INT2FIX(PQ_PIPELINE_OFF));
|
|
654
|
+
|
|
655
|
+
/* Connection#pipeline_status constant
|
|
656
|
+
*
|
|
657
|
+
* The libpq connection is in pipeline mode and an error occurred while processing the current pipeline.
|
|
658
|
+
* The aborted flag is cleared when PQgetResult returns a result of type PGRES_PIPELINE_SYNC.
|
|
659
|
+
*/
|
|
660
|
+
rb_define_const(rb_mPGconstants, "PQ_PIPELINE_ABORTED", INT2FIX(PQ_PIPELINE_ABORTED));
|
|
661
|
+
#endif
|
|
662
|
+
|
|
648
663
|
/* Invalid OID constant */
|
|
649
664
|
rb_define_const(rb_mPGconstants, "INVALID_OID", INT2FIX(InvalidOid));
|
|
650
665
|
rb_define_const(rb_mPGconstants, "InvalidOid", INT2FIX(InvalidOid));
|
|
651
666
|
|
|
667
|
+
/* PostgreSQL compiled in default port */
|
|
668
|
+
rb_define_const(rb_mPGconstants, "DEF_PGPORT", INT2FIX(DEF_PGPORT));
|
|
669
|
+
|
|
652
670
|
/* Add the constants to the toplevel namespace */
|
|
653
671
|
rb_include_module( rb_mPG, rb_mPGconstants );
|
|
654
672
|
|
|
655
|
-
enc_pg2ruby = st_init_numtable();
|
|
656
|
-
|
|
657
673
|
/* Initialize the main extension classes */
|
|
658
674
|
init_pg_connection();
|
|
659
675
|
init_pg_result();
|
|
@@ -674,4 +690,3 @@ Init_pg_ext()
|
|
|
674
690
|
init_pg_recordcoder();
|
|
675
691
|
init_pg_tuple();
|
|
676
692
|
}
|
|
677
|
-
|
data/ext/pg.h
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
#include <sys/types.h>
|
|
12
12
|
#if !defined(_WIN32)
|
|
13
13
|
# include <sys/time.h>
|
|
14
|
+
# include <sys/socket.h>
|
|
14
15
|
#endif
|
|
15
16
|
#if defined(HAVE_UNISTD_H) && !defined(_WIN32)
|
|
16
17
|
# include <unistd.h>
|
|
@@ -56,6 +57,7 @@
|
|
|
56
57
|
#endif
|
|
57
58
|
|
|
58
59
|
/* PostgreSQL headers */
|
|
60
|
+
#include "pg_config.h"
|
|
59
61
|
#include "libpq-fe.h"
|
|
60
62
|
#include "libpq/libpq-fs.h" /* large-object interface */
|
|
61
63
|
#include "pg_config_manual.h"
|
|
@@ -74,10 +76,21 @@ typedef long suseconds_t;
|
|
|
74
76
|
#define PG_MAX_COLUMNS 4000
|
|
75
77
|
#endif
|
|
76
78
|
|
|
77
|
-
#
|
|
78
|
-
#define
|
|
79
|
+
#ifdef HAVE_RB_GC_MARK_MOVABLE
|
|
80
|
+
#define pg_compact_callback(x) (x)
|
|
81
|
+
#define pg_gc_location(x) x = rb_gc_location(x)
|
|
82
|
+
#else
|
|
83
|
+
#define rb_gc_mark_movable(x) rb_gc_mark(x)
|
|
84
|
+
#define pg_compact_callback(x) {(x)}
|
|
85
|
+
#define pg_gc_location(x) UNUSED(x)
|
|
79
86
|
#endif
|
|
80
87
|
|
|
88
|
+
/* For compatibility with ruby < 3.0 */
|
|
89
|
+
#ifndef RUBY_TYPED_FROZEN_SHAREABLE
|
|
90
|
+
#define PG_RUBY_TYPED_FROZEN_SHAREABLE 0
|
|
91
|
+
#else
|
|
92
|
+
#define PG_RUBY_TYPED_FROZEN_SHAREABLE RUBY_TYPED_FROZEN_SHAREABLE
|
|
93
|
+
#endif
|
|
81
94
|
#define PG_ENC_IDX_BITS 28
|
|
82
95
|
|
|
83
96
|
/* The data behind each PG::Connection object */
|
|
@@ -86,6 +99,9 @@ typedef struct {
|
|
|
86
99
|
|
|
87
100
|
/* Cached IO object for the socket descriptor */
|
|
88
101
|
VALUE socket_io;
|
|
102
|
+
/* function pointers of the original libpq notice receivers */
|
|
103
|
+
PQnoticeReceiver default_notice_receiver;
|
|
104
|
+
PQnoticeProcessor default_notice_processor;
|
|
89
105
|
/* Proc object that receives notices as PG::Result objects */
|
|
90
106
|
VALUE notice_receiver;
|
|
91
107
|
/* Proc object that receives notices as String objects */
|
|
@@ -104,6 +120,8 @@ typedef struct {
|
|
|
104
120
|
int enc_idx : PG_ENC_IDX_BITS;
|
|
105
121
|
/* flags controlling Symbol/String field names */
|
|
106
122
|
unsigned int flags : 2;
|
|
123
|
+
/* enable automatic flushing of send data at the end of send_query calls */
|
|
124
|
+
unsigned int flush_data : 1;
|
|
107
125
|
|
|
108
126
|
#if defined(_WIN32)
|
|
109
127
|
/* File descriptor to be used for rb_w32_unwrap_io_handle() */
|
|
@@ -220,6 +238,8 @@ typedef struct {
|
|
|
220
238
|
} convs[0];
|
|
221
239
|
} t_tmbc;
|
|
222
240
|
|
|
241
|
+
extern const rb_data_type_t pg_typemap_type;
|
|
242
|
+
extern const rb_data_type_t pg_coder_type;
|
|
223
243
|
|
|
224
244
|
#include "gvl_wrappers.h"
|
|
225
245
|
|
|
@@ -299,12 +319,12 @@ int pg_coder_enc_to_s _(( t_pg_coder*, VALUE, c
|
|
|
299
319
|
int pg_text_enc_identifier _(( t_pg_coder*, VALUE, char *, VALUE *, int));
|
|
300
320
|
t_pg_coder_enc_func pg_coder_enc_func _(( t_pg_coder* ));
|
|
301
321
|
t_pg_coder_dec_func pg_coder_dec_func _(( t_pg_coder*, int ));
|
|
302
|
-
|
|
322
|
+
VALUE pg_define_coder _(( const char *, void *, VALUE, VALUE ));
|
|
303
323
|
VALUE pg_obj_to_i _(( VALUE ));
|
|
304
324
|
VALUE pg_tmbc_allocate _(( void ));
|
|
305
325
|
void pg_coder_init_encoder _(( VALUE ));
|
|
306
326
|
void pg_coder_init_decoder _(( VALUE ));
|
|
307
|
-
void
|
|
327
|
+
void pg_coder_compact _(( void * ));
|
|
308
328
|
char *pg_rb_str_ensure_capa _(( VALUE, long, char *, char ** ));
|
|
309
329
|
|
|
310
330
|
#define PG_RB_STR_ENSURE_CAPA( str, expand_len, curr_ptr, end_ptr ) \
|
|
@@ -324,9 +344,13 @@ int pg_typemap_fit_to_copy_get _(( VALUE ));
|
|
|
324
344
|
VALUE pg_typemap_result_value _(( t_typemap *, VALUE, int, int ));
|
|
325
345
|
t_pg_coder *pg_typemap_typecast_query_param _(( t_typemap *, VALUE, int ));
|
|
326
346
|
VALUE pg_typemap_typecast_copy_get _(( t_typemap *, VALUE, int, int, int ));
|
|
347
|
+
void pg_typemap_mark _(( void * ));
|
|
348
|
+
size_t pg_typemap_memsize _(( const void * ));
|
|
349
|
+
void pg_typemap_compact _(( void * ));
|
|
327
350
|
|
|
328
351
|
PGconn *pg_get_pgconn _(( VALUE ));
|
|
329
352
|
t_pg_connection *pg_get_connection _(( VALUE ));
|
|
353
|
+
VALUE pgconn_block _(( int, VALUE *, VALUE ));
|
|
330
354
|
|
|
331
355
|
VALUE pg_new_result _(( PGresult *, VALUE ));
|
|
332
356
|
VALUE pg_new_result_autoclear _(( PGresult *, VALUE ));
|
data/ext/pg_binary_decoder.c
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
#endif
|
|
13
13
|
|
|
14
14
|
VALUE rb_mPG_BinaryDecoder;
|
|
15
|
+
static VALUE s_Date;
|
|
16
|
+
static ID s_id_new;
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
/*
|
|
@@ -195,6 +197,82 @@ pg_bin_dec_timestamp(t_pg_coder *conv, const char *val, int len, int tuple, int
|
|
|
195
197
|
}
|
|
196
198
|
}
|
|
197
199
|
|
|
200
|
+
#define PG_INT32_MIN (-0x7FFFFFFF-1)
|
|
201
|
+
#define PG_INT32_MAX (0x7FFFFFFF)
|
|
202
|
+
#define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */
|
|
203
|
+
#define MONTHS_PER_YEAR 12
|
|
204
|
+
|
|
205
|
+
/* taken from PostgreSQL sources at src/backend/utils/adt/datetime.c */
|
|
206
|
+
void
|
|
207
|
+
j2date(int jd, int *year, int *month, int *day)
|
|
208
|
+
{
|
|
209
|
+
unsigned int julian;
|
|
210
|
+
unsigned int quad;
|
|
211
|
+
unsigned int extra;
|
|
212
|
+
int y;
|
|
213
|
+
|
|
214
|
+
julian = jd;
|
|
215
|
+
julian += 32044;
|
|
216
|
+
quad = julian / 146097;
|
|
217
|
+
extra = (julian - quad * 146097) * 4 + 3;
|
|
218
|
+
julian += 60 + quad * 3 + extra / 146097;
|
|
219
|
+
quad = julian / 1461;
|
|
220
|
+
julian -= quad * 1461;
|
|
221
|
+
y = julian * 4 / 1461;
|
|
222
|
+
julian = ((y != 0) ? ((julian + 305) % 365) : ((julian + 306) % 366))
|
|
223
|
+
+ 123;
|
|
224
|
+
y += quad * 4;
|
|
225
|
+
*year = y - 4800;
|
|
226
|
+
quad = julian * 2141 / 65536;
|
|
227
|
+
*day = julian - 7834 * quad / 256;
|
|
228
|
+
*month = (quad + 10) % MONTHS_PER_YEAR + 1;
|
|
229
|
+
} /* j2date() */
|
|
230
|
+
|
|
231
|
+
/*
|
|
232
|
+
* Document-class: PG::BinaryDecoder::Date < PG::SimpleDecoder
|
|
233
|
+
*
|
|
234
|
+
* This is a decoder class for conversion of PostgreSQL binary date
|
|
235
|
+
* to Ruby Date objects.
|
|
236
|
+
*/
|
|
237
|
+
static VALUE
|
|
238
|
+
pg_bin_dec_date(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
|
239
|
+
{
|
|
240
|
+
int year, month, day;
|
|
241
|
+
int date;
|
|
242
|
+
|
|
243
|
+
if (len != 4) {
|
|
244
|
+
rb_raise(rb_eTypeError, "unexpected date format != 4 bytes");
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
date = read_nbo32(val);
|
|
248
|
+
switch(date){
|
|
249
|
+
case PG_INT32_MAX:
|
|
250
|
+
return rb_str_new2("infinity");
|
|
251
|
+
case PG_INT32_MIN:
|
|
252
|
+
return rb_str_new2("-infinity");
|
|
253
|
+
default:
|
|
254
|
+
j2date(date + POSTGRES_EPOCH_JDATE, &year, &month, &day);
|
|
255
|
+
|
|
256
|
+
return rb_funcall(s_Date, s_id_new, 3, INT2NUM(year), INT2NUM(month), INT2NUM(day));
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/* called per autoload when BinaryDecoder::Date is used */
|
|
261
|
+
static VALUE
|
|
262
|
+
init_pg_bin_decoder_date(VALUE rb_mPG_BinaryDecoder)
|
|
263
|
+
{
|
|
264
|
+
rb_require("date");
|
|
265
|
+
s_Date = rb_const_get(rb_cObject, rb_intern("Date"));
|
|
266
|
+
rb_gc_register_mark_object(s_Date);
|
|
267
|
+
s_id_new = rb_intern("new");
|
|
268
|
+
|
|
269
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Date", rb_cPG_SimpleDecoder ); */
|
|
270
|
+
pg_define_coder( "Date", pg_bin_dec_date, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
|
|
271
|
+
|
|
272
|
+
return Qnil;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
|
|
198
276
|
/*
|
|
199
277
|
* Document-class: PG::BinaryDecoder::String < PG::SimpleDecoder
|
|
200
278
|
*
|
|
@@ -205,10 +283,11 @@ pg_bin_dec_timestamp(t_pg_coder *conv, const char *val, int len, int tuple, int
|
|
|
205
283
|
*/
|
|
206
284
|
|
|
207
285
|
void
|
|
208
|
-
init_pg_binary_decoder()
|
|
286
|
+
init_pg_binary_decoder(void)
|
|
209
287
|
{
|
|
210
288
|
/* This module encapsulates all decoder classes with binary input format */
|
|
211
289
|
rb_mPG_BinaryDecoder = rb_define_module_under( rb_mPG, "BinaryDecoder" );
|
|
290
|
+
rb_define_private_method(rb_singleton_class(rb_mPG_BinaryDecoder), "init_date", init_pg_bin_decoder_date, 0);
|
|
212
291
|
|
|
213
292
|
/* Make RDoc aware of the decoder classes... */
|
|
214
293
|
/* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Boolean", rb_cPG_SimpleDecoder ); */
|