pg 1.1.4

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.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +3 -0
  3. data.tar.gz.sig +0 -0
  4. data/.gemtest +0 -0
  5. data/BSDL +22 -0
  6. data/ChangeLog +6595 -0
  7. data/Contributors.rdoc +46 -0
  8. data/History.rdoc +492 -0
  9. data/LICENSE +56 -0
  10. data/Manifest.txt +72 -0
  11. data/POSTGRES +23 -0
  12. data/README-OS_X.rdoc +68 -0
  13. data/README-Windows.rdoc +56 -0
  14. data/README.ja.rdoc +14 -0
  15. data/README.rdoc +178 -0
  16. data/Rakefile +215 -0
  17. data/Rakefile.cross +298 -0
  18. data/ext/errorcodes.def +968 -0
  19. data/ext/errorcodes.rb +45 -0
  20. data/ext/errorcodes.txt +478 -0
  21. data/ext/extconf.rb +94 -0
  22. data/ext/gvl_wrappers.c +17 -0
  23. data/ext/gvl_wrappers.h +241 -0
  24. data/ext/pg.c +640 -0
  25. data/ext/pg.h +365 -0
  26. data/ext/pg_binary_decoder.c +229 -0
  27. data/ext/pg_binary_encoder.c +162 -0
  28. data/ext/pg_coder.c +549 -0
  29. data/ext/pg_connection.c +4252 -0
  30. data/ext/pg_copy_coder.c +596 -0
  31. data/ext/pg_errors.c +95 -0
  32. data/ext/pg_result.c +1501 -0
  33. data/ext/pg_text_decoder.c +981 -0
  34. data/ext/pg_text_encoder.c +682 -0
  35. data/ext/pg_tuple.c +541 -0
  36. data/ext/pg_type_map.c +166 -0
  37. data/ext/pg_type_map_all_strings.c +116 -0
  38. data/ext/pg_type_map_by_class.c +239 -0
  39. data/ext/pg_type_map_by_column.c +312 -0
  40. data/ext/pg_type_map_by_mri_type.c +284 -0
  41. data/ext/pg_type_map_by_oid.c +355 -0
  42. data/ext/pg_type_map_in_ruby.c +299 -0
  43. data/ext/util.c +149 -0
  44. data/ext/util.h +65 -0
  45. data/ext/vc/pg.sln +26 -0
  46. data/ext/vc/pg_18/pg.vcproj +216 -0
  47. data/ext/vc/pg_19/pg_19.vcproj +209 -0
  48. data/lib/pg.rb +74 -0
  49. data/lib/pg/basic_type_mapping.rb +459 -0
  50. data/lib/pg/binary_decoder.rb +22 -0
  51. data/lib/pg/coder.rb +83 -0
  52. data/lib/pg/connection.rb +291 -0
  53. data/lib/pg/constants.rb +11 -0
  54. data/lib/pg/exceptions.rb +11 -0
  55. data/lib/pg/result.rb +31 -0
  56. data/lib/pg/text_decoder.rb +47 -0
  57. data/lib/pg/text_encoder.rb +69 -0
  58. data/lib/pg/tuple.rb +30 -0
  59. data/lib/pg/type_map_by_column.rb +15 -0
  60. data/spec/data/expected_trace.out +26 -0
  61. data/spec/data/random_binary_data +0 -0
  62. data/spec/helpers.rb +380 -0
  63. data/spec/pg/basic_type_mapping_spec.rb +508 -0
  64. data/spec/pg/connection_spec.rb +1872 -0
  65. data/spec/pg/connection_sync_spec.rb +41 -0
  66. data/spec/pg/result_spec.rb +491 -0
  67. data/spec/pg/tuple_spec.rb +280 -0
  68. data/spec/pg/type_map_by_class_spec.rb +138 -0
  69. data/spec/pg/type_map_by_column_spec.rb +222 -0
  70. data/spec/pg/type_map_by_mri_type_spec.rb +136 -0
  71. data/spec/pg/type_map_by_oid_spec.rb +149 -0
  72. data/spec/pg/type_map_in_ruby_spec.rb +164 -0
  73. data/spec/pg/type_map_spec.rb +22 -0
  74. data/spec/pg/type_spec.rb +949 -0
  75. data/spec/pg_spec.rb +50 -0
  76. metadata +322 -0
  77. metadata.gz.sig +0 -0
@@ -0,0 +1,94 @@
1
+ require 'pp'
2
+ require 'mkmf'
3
+
4
+
5
+ if ENV['MAINTAINER_MODE']
6
+ $stderr.puts "Maintainer mode enabled."
7
+ $CFLAGS <<
8
+ ' -Wall' <<
9
+ ' -ggdb' <<
10
+ ' -DDEBUG' <<
11
+ ' -pedantic'
12
+ end
13
+
14
+ if pgdir = with_config( 'pg' )
15
+ ENV['PATH'] = "#{pgdir}/bin" + File::PATH_SEPARATOR + ENV['PATH']
16
+ end
17
+
18
+ if enable_config("windows-cross")
19
+ # Avoid dependency to external libgcc.dll on x86-mingw32
20
+ $LDFLAGS << " -static-libgcc"
21
+ # Don't use pg_config for cross build, but --with-pg-* path options
22
+ dir_config 'pg'
23
+
24
+ else
25
+ # Native build
26
+
27
+ pgconfig = with_config('pg-config') ||
28
+ with_config('pg_config') ||
29
+ find_executable('pg_config')
30
+
31
+ if pgconfig && pgconfig != 'ignore'
32
+ $stderr.puts "Using config values from %s" % [ pgconfig ]
33
+ incdir = `"#{pgconfig}" --includedir`.chomp
34
+ libdir = `"#{pgconfig}" --libdir`.chomp
35
+ dir_config 'pg', incdir, libdir
36
+
37
+ # Try to use runtime path linker option, even if RbConfig doesn't know about it.
38
+ # The rpath option is usually set implicit by dir_config(), but so far not
39
+ # on MacOS-X.
40
+ if RbConfig::CONFIG["RPATHFLAG"].to_s.empty? && try_link('int main() {return 0;}', " -Wl,-rpath,#{libdir}")
41
+ $LDFLAGS << " -Wl,-rpath,#{libdir}"
42
+ end
43
+ else
44
+ $stderr.puts "No pg_config... trying anyway. If building fails, please try again with",
45
+ " --with-pg-config=/path/to/pg_config"
46
+ dir_config 'pg'
47
+ end
48
+ end
49
+
50
+ if RUBY_VERSION >= '2.3.0' && /solaris/ =~ RUBY_PLATFORM
51
+ append_cppflags( '-D__EXTENSIONS__' )
52
+ end
53
+
54
+ find_header( 'libpq-fe.h' ) or abort "Can't find the 'libpq-fe.h header"
55
+ find_header( 'libpq/libpq-fs.h' ) or abort "Can't find the 'libpq/libpq-fs.h header"
56
+ find_header( 'pg_config_manual.h' ) or abort "Can't find the 'pg_config_manual.h' header"
57
+
58
+ abort "Can't find the PostgreSQL client library (libpq)" unless
59
+ have_library( 'pq', 'PQconnectdb', ['libpq-fe.h'] ) ||
60
+ have_library( 'libpq', 'PQconnectdb', ['libpq-fe.h'] ) ||
61
+ have_library( 'ms/libpq', 'PQconnectdb', ['libpq-fe.h'] )
62
+
63
+ if /mingw/ =~ RUBY_PLATFORM && RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
64
+ # Work around: https://sourceware.org/bugzilla/show_bug.cgi?id=22504
65
+ checking_for "workaround gcc version with link issue" do
66
+ `#{RbConfig::MAKEFILE_CONFIG['CC']} --version`.chomp =~ /\s(\d+)\.\d+\.\d+(\s|$)/ &&
67
+ $1.to_i >= 6 &&
68
+ have_library(':libpq.lib') # Prefer linking to libpq.lib over libpq.dll if available
69
+ end
70
+ end
71
+
72
+ # optional headers/functions
73
+ have_func 'PQsetSingleRowMode' or
74
+ abort "Your PostgreSQL is too old. Either install an older version " +
75
+ "of this gem or upgrade your database to at least PostgreSQL-9.2."
76
+ have_func 'PQconninfo'
77
+ have_func 'PQsslAttribute'
78
+ have_func 'PQencryptPasswordConn'
79
+ have_func 'timegm'
80
+ have_func 'rb_gc_adjust_memory_usage'
81
+
82
+ have_const 'PG_DIAG_TABLE_NAME', 'libpq-fe.h'
83
+
84
+ # unistd.h confilicts with ruby/win32.h when cross compiling for win32 and ruby 1.9.1
85
+ have_header 'unistd.h'
86
+ have_header 'inttypes.h'
87
+
88
+ checking_for "C99 variable length arrays" do
89
+ $defs.push( "-DHAVE_VARIABLE_LENGTH_ARRAYS" ) if try_compile('void test_vla(int l){ int vla[l]; }')
90
+ end
91
+
92
+ create_header()
93
+ create_makefile( "pg_ext" )
94
+
@@ -0,0 +1,17 @@
1
+ /*
2
+ * gvl_wrappers.c - Wrapper functions for locking/unlocking the Ruby GVL
3
+ *
4
+ */
5
+
6
+ #include "pg.h"
7
+
8
+ #ifndef HAVE_PQENCRYPTPASSWORDCONN
9
+ char *PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user, const char *algorithm){return NULL;}
10
+ #endif
11
+
12
+ FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_WRAPPER_STRUCT );
13
+ FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_SKELETON );
14
+ FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB );
15
+ FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVL_WRAPPER_STRUCT );
16
+ FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_SKELETON );
17
+ FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_STUB );
@@ -0,0 +1,241 @@
1
+ /*
2
+ * gvl_wrappers.h - Wrapper functions for locking/unlocking the Ruby GVL
3
+ *
4
+ * These are some obscure preprocessor directives that allow to generate
5
+ * drop-in replacement wrapper functions in a declarative manner.
6
+ * These wrapper functions ensure that ruby's GVL is released on each
7
+ * function call and reacquired at the end of the call or in callbacks.
8
+ * This way blocking functions calls don't block concurrent ruby threads.
9
+ *
10
+ * The wrapper of each function is prefixed by "gvl_".
11
+ *
12
+ * Use "gcc -E" to retrieve the generated code.
13
+ */
14
+
15
+ #ifndef __gvl_wrappers_h
16
+ #define __gvl_wrappers_h
17
+
18
+ #include <ruby/thread.h>
19
+
20
+ #define DEFINE_PARAM_LIST1(type, name) \
21
+ name,
22
+
23
+ #define DEFINE_PARAM_LIST2(type, name) \
24
+ p->params.name,
25
+
26
+ #define DEFINE_PARAM_LIST3(type, name) \
27
+ type name,
28
+
29
+ #define DEFINE_PARAM_DECL(type, name) \
30
+ type name;
31
+
32
+ #define DEFINE_GVL_WRAPPER_STRUCT(name, when_non_void, rettype, lastparamtype, lastparamname) \
33
+ struct gvl_wrapper_##name##_params { \
34
+ struct { \
35
+ FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_DECL) \
36
+ lastparamtype lastparamname; \
37
+ } params; \
38
+ when_non_void( rettype retval; ) \
39
+ };
40
+
41
+ #define DEFINE_GVL_SKELETON(name, when_non_void, rettype, lastparamtype, lastparamname) \
42
+ static void * gvl_##name##_skeleton( void *data ){ \
43
+ struct gvl_wrapper_##name##_params *p = (struct gvl_wrapper_##name##_params*)data; \
44
+ when_non_void( p->retval = ) \
45
+ name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST2) p->params.lastparamname ); \
46
+ return NULL; \
47
+ }
48
+
49
+ #define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
50
+ rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
51
+ struct gvl_wrapper_##name##_params params = { \
52
+ {FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname}, when_non_void((rettype)0) \
53
+ }; \
54
+ rb_thread_call_without_gvl(gvl_##name##_skeleton, &params, RUBY_UBF_IO, 0); \
55
+ when_non_void( return params.retval; ) \
56
+ }
57
+
58
+ #define DEFINE_GVL_STUB_DECL(name, when_non_void, rettype, lastparamtype, lastparamname) \
59
+ rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname);
60
+
61
+ #define DEFINE_GVLCB_SKELETON(name, when_non_void, rettype, lastparamtype, lastparamname) \
62
+ static void * gvl_##name##_skeleton( void *data ){ \
63
+ struct gvl_wrapper_##name##_params *p = (struct gvl_wrapper_##name##_params*)data; \
64
+ when_non_void( p->retval = ) \
65
+ name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST2) p->params.lastparamname ); \
66
+ return NULL; \
67
+ }
68
+
69
+ #define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
70
+ rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
71
+ struct gvl_wrapper_##name##_params params = { \
72
+ {FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname}, when_non_void((rettype)0) \
73
+ }; \
74
+ rb_thread_call_with_gvl(gvl_##name##_skeleton, &params); \
75
+ when_non_void( return params.retval; ) \
76
+ }
77
+
78
+ #define GVL_TYPE_VOID(string)
79
+ #define GVL_TYPE_NONVOID(string) string
80
+
81
+
82
+ /*
83
+ * Definitions of blocking functions and their parameters
84
+ */
85
+
86
+ #define FOR_EACH_PARAM_OF_PQconnectdb(param)
87
+
88
+ #define FOR_EACH_PARAM_OF_PQconnectStart(param)
89
+
90
+ #define FOR_EACH_PARAM_OF_PQconnectPoll(param)
91
+
92
+ #define FOR_EACH_PARAM_OF_PQreset(param)
93
+
94
+ #define FOR_EACH_PARAM_OF_PQresetStart(param)
95
+
96
+ #define FOR_EACH_PARAM_OF_PQresetPoll(param)
97
+
98
+ #define FOR_EACH_PARAM_OF_PQexec(param) \
99
+ param(PGconn *, conn)
100
+
101
+ #define FOR_EACH_PARAM_OF_PQexecParams(param) \
102
+ param(PGconn *, conn) \
103
+ param(const char *, command) \
104
+ param(int, nParams) \
105
+ param(const Oid *, paramTypes) \
106
+ param(const char * const *, paramValues) \
107
+ param(const int *, paramLengths) \
108
+ param(const int *, paramFormats)
109
+
110
+ #define FOR_EACH_PARAM_OF_PQexecPrepared(param) \
111
+ param(PGconn *, conn) \
112
+ param(const char *, stmtName) \
113
+ param(int, nParams) \
114
+ param(const char * const *, paramValues) \
115
+ param(const int *, paramLengths) \
116
+ param(const int *, paramFormats)
117
+
118
+ #define FOR_EACH_PARAM_OF_PQprepare(param) \
119
+ param(PGconn *, conn) \
120
+ param(const char *, stmtName) \
121
+ param(const char *, query) \
122
+ param(int, nParams)
123
+
124
+ #define FOR_EACH_PARAM_OF_PQdescribePrepared(param) \
125
+ param(PGconn *, conn)
126
+
127
+ #define FOR_EACH_PARAM_OF_PQdescribePortal(param) \
128
+ param(PGconn *, conn)
129
+
130
+ #define FOR_EACH_PARAM_OF_PQgetResult(param)
131
+
132
+ #define FOR_EACH_PARAM_OF_PQputCopyData(param) \
133
+ param(PGconn *, conn) \
134
+ param(const char *, buffer)
135
+
136
+ #define FOR_EACH_PARAM_OF_PQputCopyEnd(param) \
137
+ param(PGconn *, conn)
138
+
139
+ #define FOR_EACH_PARAM_OF_PQgetCopyData(param) \
140
+ param(PGconn *, conn) \
141
+ param(char **, buffer)
142
+
143
+ #define FOR_EACH_PARAM_OF_PQnotifies(param)
144
+
145
+ #define FOR_EACH_PARAM_OF_PQsendQuery(param) \
146
+ param(PGconn *, conn)
147
+
148
+ #define FOR_EACH_PARAM_OF_PQsendQueryParams(param) \
149
+ param(PGconn *, conn) \
150
+ param(const char *, command) \
151
+ param(int, nParams) \
152
+ param(const Oid *, paramTypes) \
153
+ param(const char *const *, paramValues) \
154
+ param(const int *, paramLengths) \
155
+ param(const int *, paramFormats)
156
+
157
+ #define FOR_EACH_PARAM_OF_PQsendPrepare(param) \
158
+ param(PGconn *, conn) \
159
+ param(const char *, stmtName) \
160
+ param(const char *, query) \
161
+ param(int, nParams)
162
+
163
+ #define FOR_EACH_PARAM_OF_PQsendQueryPrepared(param) \
164
+ param(PGconn *, conn) \
165
+ param(const char *, stmtName) \
166
+ param(int, nParams) \
167
+ param(const char *const *, paramValues) \
168
+ param(const int *, paramLengths) \
169
+ param(const int *, paramFormats)
170
+
171
+ #define FOR_EACH_PARAM_OF_PQsendDescribePrepared(param) \
172
+ param(PGconn *, conn)
173
+
174
+ #define FOR_EACH_PARAM_OF_PQsendDescribePortal(param) \
175
+ param(PGconn *, conn)
176
+
177
+ #define FOR_EACH_PARAM_OF_PQsetClientEncoding(param) \
178
+ param(PGconn *, conn)
179
+
180
+ #define FOR_EACH_PARAM_OF_PQisBusy(param)
181
+
182
+ #define FOR_EACH_PARAM_OF_PQencryptPasswordConn(param) \
183
+ param(PGconn *, conn) \
184
+ param(const char *, passwd) \
185
+ param(const char *, user)
186
+
187
+ #define FOR_EACH_PARAM_OF_PQcancel(param) \
188
+ param(PGcancel *, cancel) \
189
+ param(char *, errbuf)
190
+
191
+ /* function( name, void_or_nonvoid, returntype, lastparamtype, lastparamname ) */
192
+ #define FOR_EACH_BLOCKING_FUNCTION(function) \
193
+ function(PQconnectdb, GVL_TYPE_NONVOID, PGconn *, const char *, conninfo) \
194
+ function(PQconnectStart, GVL_TYPE_NONVOID, PGconn *, const char *, conninfo) \
195
+ function(PQconnectPoll, GVL_TYPE_NONVOID, PostgresPollingStatusType, PGconn *, conn) \
196
+ function(PQreset, GVL_TYPE_VOID, void, PGconn *, conn) \
197
+ function(PQresetStart, GVL_TYPE_NONVOID, int, PGconn *, conn) \
198
+ function(PQresetPoll, GVL_TYPE_NONVOID, PostgresPollingStatusType, PGconn *, conn) \
199
+ function(PQexec, GVL_TYPE_NONVOID, PGresult *, const char *, command) \
200
+ function(PQexecParams, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
201
+ function(PQexecPrepared, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
202
+ function(PQprepare, GVL_TYPE_NONVOID, PGresult *, const Oid *, paramTypes) \
203
+ function(PQdescribePrepared, GVL_TYPE_NONVOID, PGresult *, const char *, stmtName) \
204
+ function(PQdescribePortal, GVL_TYPE_NONVOID, PGresult *, const char *, portalName) \
205
+ function(PQgetResult, GVL_TYPE_NONVOID, PGresult *, PGconn *, conn) \
206
+ function(PQputCopyData, GVL_TYPE_NONVOID, int, int, nbytes) \
207
+ function(PQputCopyEnd, GVL_TYPE_NONVOID, int, const char *, errormsg) \
208
+ function(PQgetCopyData, GVL_TYPE_NONVOID, int, int, async) \
209
+ function(PQnotifies, GVL_TYPE_NONVOID, PGnotify *, PGconn *, conn) \
210
+ function(PQsendQuery, GVL_TYPE_NONVOID, int, const char *, query) \
211
+ function(PQsendQueryParams, GVL_TYPE_NONVOID, int, int, resultFormat) \
212
+ function(PQsendPrepare, GVL_TYPE_NONVOID, int, const Oid *, paramTypes) \
213
+ function(PQsendQueryPrepared, GVL_TYPE_NONVOID, int, int, resultFormat) \
214
+ function(PQsendDescribePrepared, GVL_TYPE_NONVOID, int, const char *, stmt) \
215
+ function(PQsendDescribePortal, GVL_TYPE_NONVOID, int, const char *, portal) \
216
+ function(PQsetClientEncoding, GVL_TYPE_NONVOID, int, const char *, encoding) \
217
+ function(PQisBusy, GVL_TYPE_NONVOID, int, PGconn *, conn) \
218
+ function(PQencryptPasswordConn, GVL_TYPE_NONVOID, char *, const char *, algorithm) \
219
+ function(PQcancel, GVL_TYPE_NONVOID, int, int, errbufsize);
220
+
221
+ FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB_DECL );
222
+
223
+
224
+ /*
225
+ * Definitions of callback functions and their parameters
226
+ */
227
+
228
+ #define FOR_EACH_PARAM_OF_notice_processor_proxy(param) \
229
+ param(void *, arg)
230
+
231
+ #define FOR_EACH_PARAM_OF_notice_receiver_proxy(param) \
232
+ param(void *, arg)
233
+
234
+ /* function( name, void_or_nonvoid, returntype, lastparamtype, lastparamname ) */
235
+ #define FOR_EACH_CALLBACK_FUNCTION(function) \
236
+ function(notice_processor_proxy, GVL_TYPE_VOID, void, const char *, message) \
237
+ function(notice_receiver_proxy, GVL_TYPE_VOID, void, const PGresult *, result) \
238
+
239
+ FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVL_STUB_DECL );
240
+
241
+ #endif /* end __gvl_wrappers_h */
@@ -0,0 +1,640 @@
1
+ /*
2
+ * pg.c - Toplevel extension
3
+ * $Id: pg.c,v 2d334508484a 2018/08/27 11:33:43 lars $
4
+ *
5
+ * Author/s:
6
+ *
7
+ * - Jeff Davis <ruby-pg@j-davis.com>
8
+ * - Guy Decoux (ts) <decoux@moulon.inra.fr>
9
+ * - Michael Granger <ged@FaerieMUD.org>
10
+ * - Lars Kanis <lars@greiz-reinsdorf.de>
11
+ * - Dave Lee
12
+ * - Eiji Matsumoto <usagi@ruby.club.or.jp>
13
+ * - Yukihiro Matsumoto <matz@ruby-lang.org>
14
+ * - Noboru Saitou <noborus@netlab.jp>
15
+ *
16
+ * See Contributors.rdoc for the many additional fine people that have contributed
17
+ * to this library over the years.
18
+ *
19
+ * Copyright (c) 1997-2016 by the authors.
20
+ *
21
+ * You may redistribute this software under the same terms as Ruby itself; see
22
+ * https://www.ruby-lang.org/en/about/license.txt or the BSDL file in the source
23
+ * for details.
24
+ *
25
+ * Portions of the code are from the PostgreSQL project, and are distributed
26
+ * under the terms of the PostgreSQL license, included in the file "POSTGRES".
27
+ *
28
+ * Portions copyright LAIKA, Inc.
29
+ *
30
+ *
31
+ * The following functions are part of libpq, but not available from ruby-pg,
32
+ * because they are deprecated, obsolete, or generally not useful:
33
+ *
34
+ * - PQfreemem -- unnecessary: copied to ruby object, then freed. Ruby object's
35
+ * memory is freed when it is garbage collected.
36
+ * - PQbinaryTuples -- better to use PQfformat
37
+ * - PQprint -- not very useful
38
+ * - PQsetdb -- not very useful
39
+ * - PQoidStatus -- deprecated, use PQoidValue
40
+ * - PQrequestCancel -- deprecated, use PQcancel
41
+ * - PQfn -- use a prepared statement instead
42
+ * - PQgetline -- deprecated, use PQgetCopyData
43
+ * - PQgetlineAsync -- deprecated, use PQgetCopyData
44
+ * - PQputline -- deprecated, use PQputCopyData
45
+ * - PQputnbytes -- deprecated, use PQputCopyData
46
+ * - PQendcopy -- deprecated, use PQputCopyEnd
47
+ */
48
+
49
+ #include "pg.h"
50
+
51
+ int pg_skip_deprecation_warning;
52
+ VALUE rb_mPG;
53
+ VALUE rb_mPGconstants;
54
+
55
+
56
+ /*
57
+ * Document-class: PG::Error
58
+ *
59
+ * This is the exception class raised when an error is returned from
60
+ * a libpq API call.
61
+ *
62
+ * The attributes +connection+ and +result+ are set to the connection
63
+ * object and result set object, respectively.
64
+ *
65
+ * If the connection object or result set object is not available from
66
+ * the context in which the error was encountered, it is +nil+.
67
+ */
68
+
69
+ /*
70
+ * M17n functions
71
+ */
72
+
73
+ /**
74
+ * The mapping from canonical encoding names in PostgreSQL to ones in Ruby.
75
+ */
76
+ const char * const (pg_enc_pg2ruby_mapping[][2]) = {
77
+ {"BIG5", "Big5" },
78
+ {"EUC_CN", "GB2312" },
79
+ {"EUC_JP", "EUC-JP" },
80
+ {"EUC_JIS_2004", "EUC-JP" },
81
+ {"EUC_KR", "EUC-KR" },
82
+ {"EUC_TW", "EUC-TW" },
83
+ {"GB18030", "GB18030" },
84
+ {"GBK", "GBK" },
85
+ {"ISO_8859_5", "ISO-8859-5" },
86
+ {"ISO_8859_6", "ISO-8859-6" },
87
+ {"ISO_8859_7", "ISO-8859-7" },
88
+ {"ISO_8859_8", "ISO-8859-8" },
89
+ /* {"JOHAB", "JOHAB" }, dummy */
90
+ {"KOI8", "KOI8-R" },
91
+ {"KOI8R", "KOI8-R" },
92
+ {"KOI8U", "KOI8-U" },
93
+ {"LATIN1", "ISO-8859-1" },
94
+ {"LATIN2", "ISO-8859-2" },
95
+ {"LATIN3", "ISO-8859-3" },
96
+ {"LATIN4", "ISO-8859-4" },
97
+ {"LATIN5", "ISO-8859-9" },
98
+ {"LATIN6", "ISO-8859-10" },
99
+ {"LATIN7", "ISO-8859-13" },
100
+ {"LATIN8", "ISO-8859-14" },
101
+ {"LATIN9", "ISO-8859-15" },
102
+ {"LATIN10", "ISO-8859-16" },
103
+ {"MULE_INTERNAL", "Emacs-Mule" },
104
+ {"SJIS", "Windows-31J" },
105
+ {"SHIFT_JIS_2004","Windows-31J" },
106
+ /* {"SQL_ASCII", NULL }, special case*/
107
+ {"UHC", "CP949" },
108
+ {"UTF8", "UTF-8" },
109
+ {"WIN866", "IBM866" },
110
+ {"WIN874", "Windows-874" },
111
+ {"WIN1250", "Windows-1250"},
112
+ {"WIN1251", "Windows-1251"},
113
+ {"WIN1252", "Windows-1252"},
114
+ {"WIN1253", "Windows-1253"},
115
+ {"WIN1254", "Windows-1254"},
116
+ {"WIN1255", "Windows-1255"},
117
+ {"WIN1256", "Windows-1256"},
118
+ {"WIN1257", "Windows-1257"},
119
+ {"WIN1258", "Windows-1258"}
120
+ };
121
+
122
+
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
+ /*
150
+ * Return the given PostgreSQL encoding ID as an rb_encoding.
151
+ *
152
+ * - returns NULL if the client encoding is 'SQL_ASCII'.
153
+ * - returns ASCII-8BIT if the client encoding is unknown.
154
+ */
155
+ rb_encoding *
156
+ pg_get_pg_encoding_as_rb_encoding( int enc_id )
157
+ {
158
+ rb_encoding *enc;
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
+
173
+ }
174
+
175
+ /*
176
+ * Return the given PostgreSQL encoding name as an rb_encoding.
177
+ */
178
+ rb_encoding *
179
+ pg_get_pg_encname_as_rb_encoding( const char *pg_encname )
180
+ {
181
+ size_t i;
182
+
183
+ /* Trying looking it up in the conversion table */
184
+ for ( i = 0; i < sizeof(pg_enc_pg2ruby_mapping)/sizeof(pg_enc_pg2ruby_mapping[0]); ++i ) {
185
+ if ( strcmp(pg_encname, pg_enc_pg2ruby_mapping[i][0]) == 0 )
186
+ return rb_enc_find( pg_enc_pg2ruby_mapping[i][1] );
187
+ }
188
+
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
+ /* Fallthrough to ASCII-8BIT */
194
+ return rb_ascii8bit_encoding();
195
+ }
196
+
197
+ /*
198
+ * Get the client encoding of the specified connection handle and return it as a rb_encoding.
199
+ */
200
+ rb_encoding *
201
+ pg_conn_enc_get( PGconn *conn )
202
+ {
203
+ int enc_id = PQclientEncoding( conn );
204
+ return pg_get_pg_encoding_as_rb_encoding( enc_id );
205
+ }
206
+
207
+
208
+ /*
209
+ * Returns the given rb_encoding as the equivalent PostgreSQL encoding string.
210
+ */
211
+ const char *
212
+ pg_get_rb_encoding_as_pg_encoding( rb_encoding *enc )
213
+ {
214
+ const char *rb_encname = rb_enc_name( enc );
215
+ const char *encname = NULL;
216
+ size_t i;
217
+
218
+ for (i = 0; i < sizeof(pg_enc_pg2ruby_mapping)/sizeof(pg_enc_pg2ruby_mapping[0]); ++i) {
219
+ if (strcmp(rb_encname, pg_enc_pg2ruby_mapping[i][1]) == 0) {
220
+ encname = pg_enc_pg2ruby_mapping[i][0];
221
+ }
222
+ }
223
+
224
+ if ( !encname ) encname = "SQL_ASCII";
225
+
226
+ return encname;
227
+ }
228
+
229
+
230
+ /*
231
+ * Ensures that the given string has enough capacity to take expand_len
232
+ * more data bytes. The new data part of the String is not initialized.
233
+ *
234
+ * current_out must be a pointer within the data part of the String object.
235
+ * This pointer is returned and possibly adjusted, because the location of the data
236
+ * part of the String can change through this function.
237
+ *
238
+ * PG_RB_STR_ENSURE_CAPA can be used to do fast inline checks of the remaining capacity.
239
+ * end_capa it is then set to the first byte after the currently reserved memory,
240
+ * if not NULL.
241
+ *
242
+ * Before the String can be used with other string functions or returned to Ruby space,
243
+ * the string length has to be set with rb_str_set_len().
244
+ *
245
+ * Usage example:
246
+ *
247
+ * VALUE string;
248
+ * char *current_out, *end_capa;
249
+ * PG_RB_STR_NEW( string, current_out, end_capa );
250
+ * while( data_is_going_to_be_processed ){
251
+ * PG_RB_STR_ENSURE_CAPA( string, 2, current_out, end_capa );
252
+ * *current_out++ = databyte1;
253
+ * *current_out++ = databyte2;
254
+ * }
255
+ * rb_str_set_len( string, current_out - RSTRING_PTR(string) );
256
+ *
257
+ */
258
+ char *
259
+ pg_rb_str_ensure_capa( VALUE str, long expand_len, char *curr_ptr, char **end_ptr )
260
+ {
261
+ long curr_len = curr_ptr - RSTRING_PTR(str);
262
+ long curr_capa = rb_str_capacity( str );
263
+ if( curr_capa < curr_len + expand_len ){
264
+ rb_str_set_len( str, curr_len );
265
+ rb_str_modify_expand( str, (curr_len + expand_len) * 2 - curr_capa );
266
+ curr_ptr = RSTRING_PTR(str) + curr_len;
267
+ }
268
+ if( end_ptr )
269
+ *end_ptr = RSTRING_PTR(str) + rb_str_capacity( str );
270
+ return curr_ptr;
271
+ }
272
+
273
+
274
+ /**************************************************************************
275
+ * Module Methods
276
+ **************************************************************************/
277
+
278
+ /*
279
+ * call-seq:
280
+ * PG.library_version -> Integer
281
+ *
282
+ * Get the version of the libpq library in use. The number is formed by
283
+ * converting the major, minor, and revision numbers into two-decimal-
284
+ * digit numbers and appending them together.
285
+ * For example, version 7.4.2 will be returned as 70402, and version
286
+ * 8.1 will be returned as 80100 (leading zeroes are not shown). Zero
287
+ * is returned if the connection is bad.
288
+ */
289
+ static VALUE
290
+ pg_s_library_version(VALUE self)
291
+ {
292
+ UNUSED( self );
293
+ return INT2NUM(PQlibVersion());
294
+ }
295
+
296
+
297
+ /*
298
+ * call-seq:
299
+ * PG.isthreadsafe -> Boolean
300
+ * PG.is_threadsafe? -> Boolean
301
+ * PG.threadsafe? -> Boolean
302
+ *
303
+ * Returns +true+ if libpq is thread-safe, +false+ otherwise.
304
+ */
305
+ static VALUE
306
+ pg_s_threadsafe_p(VALUE self)
307
+ {
308
+ UNUSED( self );
309
+ return PQisthreadsafe() ? Qtrue : Qfalse;
310
+ }
311
+
312
+ static int
313
+ pg_to_bool_int(VALUE value)
314
+ {
315
+ switch( TYPE(value) ){
316
+ case T_FALSE:
317
+ return 0;
318
+ case T_TRUE:
319
+ return 1;
320
+ default:
321
+ return NUM2INT(value);
322
+ }
323
+ }
324
+
325
+ /*
326
+ * call-seq:
327
+ * PG.init_openssl(do_ssl, do_crypto) -> nil
328
+ *
329
+ * Allows applications to select which security libraries to initialize.
330
+ *
331
+ * If your application initializes libssl and/or libcrypto libraries and libpq is
332
+ * built with SSL support, you should call PG.init_openssl() to tell libpq that the
333
+ * libssl and/or libcrypto libraries have been initialized by your application,
334
+ * so that libpq will not also initialize those libraries. See
335
+ * http://h71000.www7.hp.com/doc/83final/BA554_90007/ch04.html for details on the SSL API.
336
+ *
337
+ * When do_ssl is +true+, libpq will initialize the OpenSSL library before first
338
+ * opening a database connection. When do_crypto is +true+, the libcrypto library
339
+ * will be initialized. By default (if PG.init_openssl() is not called), both libraries
340
+ * are initialized. When SSL support is not compiled in, this function is present but does nothing.
341
+ *
342
+ * If your application uses and initializes either OpenSSL or its underlying libcrypto library,
343
+ * you must call this function with +false+ for the appropriate parameter(s) before first opening
344
+ * a database connection. Also be sure that you have done that initialization before opening a
345
+ * database connection.
346
+ *
347
+ */
348
+ static VALUE
349
+ pg_s_init_openssl(VALUE self, VALUE do_ssl, VALUE do_crypto)
350
+ {
351
+ UNUSED( self );
352
+ PQinitOpenSSL(pg_to_bool_int(do_ssl), pg_to_bool_int(do_crypto));
353
+ return Qnil;
354
+ }
355
+
356
+
357
+ /*
358
+ * call-seq:
359
+ * PG.init_ssl(do_ssl) -> nil
360
+ *
361
+ * Allows applications to select which security libraries to initialize.
362
+ *
363
+ * This function is equivalent to <tt>PG.init_openssl(do_ssl, do_ssl)</tt> . It is sufficient for
364
+ * applications that initialize both or neither of OpenSSL and libcrypto.
365
+ */
366
+ static VALUE
367
+ pg_s_init_ssl(VALUE self, VALUE do_ssl)
368
+ {
369
+ UNUSED( self );
370
+ PQinitSSL(pg_to_bool_int(do_ssl));
371
+ return Qnil;
372
+ }
373
+
374
+
375
+ /**************************************************************************
376
+ * Initializer
377
+ **************************************************************************/
378
+
379
+ void
380
+ Init_pg_ext()
381
+ {
382
+ if( RTEST(rb_eval_string("ENV['PG_SKIP_DEPRECATION_WARNING']")) ){
383
+ /* Set all bits to disable all deprecation warnings. */
384
+ pg_skip_deprecation_warning = 0xFFFF;
385
+ } else {
386
+ pg_skip_deprecation_warning = 0;
387
+ }
388
+
389
+ rb_mPG = rb_define_module( "PG" );
390
+ rb_mPGconstants = rb_define_module_under( rb_mPG, "Constants" );
391
+
392
+ /*************************
393
+ * PG module methods
394
+ *************************/
395
+ rb_define_singleton_method( rb_mPG, "library_version", pg_s_library_version, 0 );
396
+ rb_define_singleton_method( rb_mPG, "isthreadsafe", pg_s_threadsafe_p, 0 );
397
+ SINGLETON_ALIAS( rb_mPG, "is_threadsafe?", "isthreadsafe" );
398
+ SINGLETON_ALIAS( rb_mPG, "threadsafe?", "isthreadsafe" );
399
+
400
+ rb_define_singleton_method( rb_mPG, "init_openssl", pg_s_init_openssl, 2 );
401
+ rb_define_singleton_method( rb_mPG, "init_ssl", pg_s_init_ssl, 1 );
402
+
403
+
404
+ /****** PG::Connection CLASS CONSTANTS: Connection Status ******/
405
+
406
+ /* Connection succeeded */
407
+ rb_define_const(rb_mPGconstants, "CONNECTION_OK", INT2FIX(CONNECTION_OK));
408
+ /* Connection failed */
409
+ rb_define_const(rb_mPGconstants, "CONNECTION_BAD", INT2FIX(CONNECTION_BAD));
410
+
411
+ /****** PG::Connection CLASS CONSTANTS: Nonblocking connection status ******/
412
+
413
+ /* Waiting for connection to be made. */
414
+ rb_define_const(rb_mPGconstants, "CONNECTION_STARTED", INT2FIX(CONNECTION_STARTED));
415
+ /* Connection OK; waiting to send. */
416
+ rb_define_const(rb_mPGconstants, "CONNECTION_MADE", INT2FIX(CONNECTION_MADE));
417
+ /* Waiting for a response from the server. */
418
+ rb_define_const(rb_mPGconstants, "CONNECTION_AWAITING_RESPONSE", INT2FIX(CONNECTION_AWAITING_RESPONSE));
419
+ /* Received authentication; waiting for backend start-up to finish. */
420
+ rb_define_const(rb_mPGconstants, "CONNECTION_AUTH_OK", INT2FIX(CONNECTION_AUTH_OK));
421
+ /* Negotiating SSL encryption. */
422
+ rb_define_const(rb_mPGconstants, "CONNECTION_SSL_STARTUP", INT2FIX(CONNECTION_SSL_STARTUP));
423
+ /* Negotiating environment-driven parameter settings. */
424
+ rb_define_const(rb_mPGconstants, "CONNECTION_SETENV", INT2FIX(CONNECTION_SETENV));
425
+ /* Internal state: connect() needed. */
426
+ rb_define_const(rb_mPGconstants, "CONNECTION_NEEDED", INT2FIX(CONNECTION_NEEDED));
427
+
428
+ /****** PG::Connection CLASS CONSTANTS: Nonblocking connection polling status ******/
429
+
430
+ /* Async connection is waiting to read */
431
+ rb_define_const(rb_mPGconstants, "PGRES_POLLING_READING", INT2FIX(PGRES_POLLING_READING));
432
+ /* Async connection is waiting to write */
433
+ rb_define_const(rb_mPGconstants, "PGRES_POLLING_WRITING", INT2FIX(PGRES_POLLING_WRITING));
434
+ /* Async connection failed or was reset */
435
+ rb_define_const(rb_mPGconstants, "PGRES_POLLING_FAILED", INT2FIX(PGRES_POLLING_FAILED));
436
+ /* Async connection succeeded */
437
+ rb_define_const(rb_mPGconstants, "PGRES_POLLING_OK", INT2FIX(PGRES_POLLING_OK));
438
+
439
+ /****** PG::Connection CLASS CONSTANTS: Transaction Status ******/
440
+
441
+ /* Transaction is currently idle (#transaction_status) */
442
+ rb_define_const(rb_mPGconstants, "PQTRANS_IDLE", INT2FIX(PQTRANS_IDLE));
443
+ /* Transaction is currently active; query has been sent to the server, but not yet completed. (#transaction_status) */
444
+ rb_define_const(rb_mPGconstants, "PQTRANS_ACTIVE", INT2FIX(PQTRANS_ACTIVE));
445
+ /* Transaction is currently idle, in a valid transaction block (#transaction_status) */
446
+ rb_define_const(rb_mPGconstants, "PQTRANS_INTRANS", INT2FIX(PQTRANS_INTRANS));
447
+ /* Transaction is currently idle, in a failed transaction block (#transaction_status) */
448
+ rb_define_const(rb_mPGconstants, "PQTRANS_INERROR", INT2FIX(PQTRANS_INERROR));
449
+ /* Transaction's connection is bad (#transaction_status) */
450
+ rb_define_const(rb_mPGconstants, "PQTRANS_UNKNOWN", INT2FIX(PQTRANS_UNKNOWN));
451
+
452
+ /****** PG::Connection CLASS CONSTANTS: Error Verbosity ******/
453
+
454
+ /* Terse error verbosity level (#set_error_verbosity) */
455
+ rb_define_const(rb_mPGconstants, "PQERRORS_TERSE", INT2FIX(PQERRORS_TERSE));
456
+ /* Default error verbosity level (#set_error_verbosity) */
457
+ rb_define_const(rb_mPGconstants, "PQERRORS_DEFAULT", INT2FIX(PQERRORS_DEFAULT));
458
+ /* Verbose error verbosity level (#set_error_verbosity) */
459
+ rb_define_const(rb_mPGconstants, "PQERRORS_VERBOSE", INT2FIX(PQERRORS_VERBOSE));
460
+
461
+ /****** PG::Connection CLASS CONSTANTS: Check Server Status ******/
462
+
463
+ /* Server is accepting connections. */
464
+ rb_define_const(rb_mPGconstants, "PQPING_OK", INT2FIX(PQPING_OK));
465
+ /* Server is alive but rejecting connections. */
466
+ rb_define_const(rb_mPGconstants, "PQPING_REJECT", INT2FIX(PQPING_REJECT));
467
+ /* Could not establish connection. */
468
+ rb_define_const(rb_mPGconstants, "PQPING_NO_RESPONSE", INT2FIX(PQPING_NO_RESPONSE));
469
+ /* Connection not attempted (bad params). */
470
+ rb_define_const(rb_mPGconstants, "PQPING_NO_ATTEMPT", INT2FIX(PQPING_NO_ATTEMPT));
471
+
472
+ /****** PG::Connection CLASS CONSTANTS: Large Objects ******/
473
+
474
+ /* Flag for #lo_creat, #lo_open -- open for writing */
475
+ rb_define_const(rb_mPGconstants, "INV_WRITE", INT2FIX(INV_WRITE));
476
+ /* Flag for #lo_creat, #lo_open -- open for reading */
477
+ rb_define_const(rb_mPGconstants, "INV_READ", INT2FIX(INV_READ));
478
+ /* Flag for #lo_lseek -- seek from object start */
479
+ rb_define_const(rb_mPGconstants, "SEEK_SET", INT2FIX(SEEK_SET));
480
+ /* Flag for #lo_lseek -- seek from current position */
481
+ rb_define_const(rb_mPGconstants, "SEEK_CUR", INT2FIX(SEEK_CUR));
482
+ /* Flag for #lo_lseek -- seek from object end */
483
+ rb_define_const(rb_mPGconstants, "SEEK_END", INT2FIX(SEEK_END));
484
+
485
+ /****** PG::Result CONSTANTS: result status ******/
486
+
487
+ /* #result_status constant: The string sent to the server was empty. */
488
+ rb_define_const(rb_mPGconstants, "PGRES_EMPTY_QUERY", INT2FIX(PGRES_EMPTY_QUERY));
489
+ /* #result_status constant: Successful completion of a command returning no data. */
490
+ rb_define_const(rb_mPGconstants, "PGRES_COMMAND_OK", INT2FIX(PGRES_COMMAND_OK));
491
+ /* #result_status constant: Successful completion of a command returning data
492
+ (such as a SELECT or SHOW). */
493
+ rb_define_const(rb_mPGconstants, "PGRES_TUPLES_OK", INT2FIX(PGRES_TUPLES_OK));
494
+ /* #result_status constant: Copy Out (from server) data transfer started. */
495
+ rb_define_const(rb_mPGconstants, "PGRES_COPY_OUT", INT2FIX(PGRES_COPY_OUT));
496
+ /* #result_status constant: Copy In (to server) data transfer started. */
497
+ rb_define_const(rb_mPGconstants, "PGRES_COPY_IN", INT2FIX(PGRES_COPY_IN));
498
+ /* #result_status constant: The server’s response was not understood. */
499
+ rb_define_const(rb_mPGconstants, "PGRES_BAD_RESPONSE", INT2FIX(PGRES_BAD_RESPONSE));
500
+ /* #result_status constant: A nonfatal error (a notice or warning) occurred. */
501
+ rb_define_const(rb_mPGconstants, "PGRES_NONFATAL_ERROR",INT2FIX(PGRES_NONFATAL_ERROR));
502
+ /* #result_status constant: A fatal error occurred. */
503
+ rb_define_const(rb_mPGconstants, "PGRES_FATAL_ERROR", INT2FIX(PGRES_FATAL_ERROR));
504
+ /* #result_status constant: Copy In/Out data transfer in progress. */
505
+ rb_define_const(rb_mPGconstants, "PGRES_COPY_BOTH", INT2FIX(PGRES_COPY_BOTH));
506
+ /* #result_status constant: Single tuple from larger resultset. */
507
+ rb_define_const(rb_mPGconstants, "PGRES_SINGLE_TUPLE", INT2FIX(PGRES_SINGLE_TUPLE));
508
+
509
+ /****** Result CONSTANTS: result error field codes ******/
510
+
511
+ /* #result_error_field argument constant: The severity; the field contents
512
+ * are ERROR, FATAL, or PANIC (in an error message), or WARNING, NOTICE,
513
+ * DEBUG, INFO, or LOG (in a notice message), or a localized translation
514
+ * of one of these. Always present.
515
+ */
516
+ rb_define_const(rb_mPGconstants, "PG_DIAG_SEVERITY", INT2FIX(PG_DIAG_SEVERITY));
517
+
518
+ /* #result_error_field argument constant: The SQLSTATE code for the
519
+ * error. The SQLSTATE code identies the type of error that has occurred;
520
+ * it can be used by front-end applications to perform specic operations
521
+ * (such as er- ror handling) in response to a particular database
522
+ * error. For a list of the possible SQLSTATE codes, see Appendix A.
523
+ * This eld is not localizable, and is always present.
524
+ */
525
+ rb_define_const(rb_mPGconstants, "PG_DIAG_SQLSTATE", INT2FIX(PG_DIAG_SQLSTATE));
526
+
527
+ /* #result_error_field argument constant: The primary human-readable
528
+ * error message (typically one line). Always present. */
529
+ rb_define_const(rb_mPGconstants, "PG_DIAG_MESSAGE_PRIMARY", INT2FIX(PG_DIAG_MESSAGE_PRIMARY));
530
+
531
+ /* #result_error_field argument constant: Detail: an optional secondary
532
+ * error message carrying more detail about the problem. Might run to
533
+ * multiple lines.
534
+ */
535
+ rb_define_const(rb_mPGconstants, "PG_DIAG_MESSAGE_DETAIL", INT2FIX(PG_DIAG_MESSAGE_DETAIL));
536
+
537
+ /* #result_error_field argument constant: Hint: an optional suggestion
538
+ * what to do about the problem. This is intended to differ from detail
539
+ * in that it offers advice (potentially inappropriate) rather than
540
+ * hard facts. Might run to multiple lines.
541
+ */
542
+
543
+ rb_define_const(rb_mPGconstants, "PG_DIAG_MESSAGE_HINT", INT2FIX(PG_DIAG_MESSAGE_HINT));
544
+ /* #result_error_field argument constant: A string containing a decimal
545
+ * integer indicating an error cursor position as an index into the
546
+ * original statement string. The rst character has index 1, and
547
+ * positions are measured in characters not bytes.
548
+ */
549
+
550
+ rb_define_const(rb_mPGconstants, "PG_DIAG_STATEMENT_POSITION", INT2FIX(PG_DIAG_STATEMENT_POSITION));
551
+ /* #result_error_field argument constant: This is dened the same as
552
+ * the PG_DIAG_STATEMENT_POSITION eld, but it is used when the cursor
553
+ * position refers to an internally generated command rather than the
554
+ * one submitted by the client. The PG_DIAG_INTERNAL_QUERY eld will
555
+ * always appear when this eld appears.
556
+ */
557
+
558
+ rb_define_const(rb_mPGconstants, "PG_DIAG_INTERNAL_POSITION", INT2FIX(PG_DIAG_INTERNAL_POSITION));
559
+ /* #result_error_field argument constant: The text of a failed
560
+ * internally-generated command. This could be, for example, a SQL
561
+ * query issued by a PL/pgSQL function.
562
+ */
563
+
564
+ rb_define_const(rb_mPGconstants, "PG_DIAG_INTERNAL_QUERY", INT2FIX(PG_DIAG_INTERNAL_QUERY));
565
+ /* #result_error_field argument constant: An indication of the context
566
+ * in which the error occurred. Presently this includes a call stack
567
+ * traceback of active procedural language functions and internally-generated
568
+ * queries. The trace is one entry per line, most recent rst.
569
+ */
570
+
571
+ rb_define_const(rb_mPGconstants, "PG_DIAG_CONTEXT", INT2FIX(PG_DIAG_CONTEXT));
572
+ /* #result_error_field argument constant: The le name of the source-code
573
+ * location where the error was reported. */
574
+ rb_define_const(rb_mPGconstants, "PG_DIAG_SOURCE_FILE", INT2FIX(PG_DIAG_SOURCE_FILE));
575
+
576
+ /* #result_error_field argument constant: The line number of the
577
+ * source-code location where the error was reported. */
578
+ rb_define_const(rb_mPGconstants, "PG_DIAG_SOURCE_LINE", INT2FIX(PG_DIAG_SOURCE_LINE));
579
+
580
+ /* #result_error_field argument constant: The name of the source-code
581
+ * function reporting the error. */
582
+ rb_define_const(rb_mPGconstants, "PG_DIAG_SOURCE_FUNCTION", INT2FIX(PG_DIAG_SOURCE_FUNCTION));
583
+
584
+ #ifdef HAVE_CONST_PG_DIAG_TABLE_NAME
585
+ /* #result_error_field argument constant: If the error was associated with a
586
+ * specific database object, the name of the schema containing that object, if any. */
587
+ rb_define_const(rb_mPGconstants, "PG_DIAG_SCHEMA_NAME", INT2FIX(PG_DIAG_SCHEMA_NAME));
588
+
589
+ /* #result_error_field argument constant: If the error was associated with a
590
+ *specific table, the name of the table. (When this field is present, the schema name
591
+ * field provides the name of the table's schema.) */
592
+ rb_define_const(rb_mPGconstants, "PG_DIAG_TABLE_NAME", INT2FIX(PG_DIAG_TABLE_NAME));
593
+
594
+ /* #result_error_field argument constant: If the error was associated with a
595
+ * specific table column, the name of the column. (When this field is present, the
596
+ * schema and table name fields identify the table.) */
597
+ rb_define_const(rb_mPGconstants, "PG_DIAG_COLUMN_NAME", INT2FIX(PG_DIAG_COLUMN_NAME));
598
+
599
+ /* #result_error_field argument constant: If the error was associated with a
600
+ * specific datatype, the name of the datatype. (When this field is present, the
601
+ * schema name field provides the name of the datatype's schema.) */
602
+ rb_define_const(rb_mPGconstants, "PG_DIAG_DATATYPE_NAME", INT2FIX(PG_DIAG_DATATYPE_NAME));
603
+
604
+ /* #result_error_field argument constant: If the error was associated with a
605
+ * specific constraint, the name of the constraint. The table or domain that the
606
+ * constraint belongs to is reported using the fields listed above. (For this
607
+ * purpose, indexes are treated as constraints, even if they weren't created with
608
+ * constraint syntax.) */
609
+ rb_define_const(rb_mPGconstants, "PG_DIAG_CONSTRAINT_NAME", INT2FIX(PG_DIAG_CONSTRAINT_NAME));
610
+ #endif
611
+
612
+ /* Invalid OID constant */
613
+ rb_define_const(rb_mPGconstants, "INVALID_OID", INT2FIX(InvalidOid));
614
+ rb_define_const(rb_mPGconstants, "InvalidOid", INT2FIX(InvalidOid));
615
+
616
+ /* Add the constants to the toplevel namespace */
617
+ rb_include_module( rb_mPG, rb_mPGconstants );
618
+
619
+ enc_pg2ruby = st_init_numtable();
620
+
621
+ /* Initialize the main extension classes */
622
+ init_pg_connection();
623
+ init_pg_result();
624
+ init_pg_errors();
625
+ init_pg_type_map();
626
+ init_pg_type_map_all_strings();
627
+ init_pg_type_map_by_class();
628
+ init_pg_type_map_by_column();
629
+ init_pg_type_map_by_mri_type();
630
+ init_pg_type_map_by_oid();
631
+ init_pg_type_map_in_ruby();
632
+ init_pg_coder();
633
+ init_pg_text_encoder();
634
+ init_pg_text_decoder();
635
+ init_pg_binary_encoder();
636
+ init_pg_binary_decoder();
637
+ init_pg_copycoder();
638
+ init_pg_tuple();
639
+ }
640
+