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,22 @@
1
+ # -*- ruby -*-
2
+
3
+ module PG
4
+ module BinaryDecoder
5
+ # Convenience classes for timezone options
6
+ class TimestampUtc < Timestamp
7
+ def initialize(params={})
8
+ super(params.merge(flags: PG::Coder::TIMESTAMP_DB_UTC | PG::Coder::TIMESTAMP_APP_UTC))
9
+ end
10
+ end
11
+ class TimestampUtcToLocal < Timestamp
12
+ def initialize(params={})
13
+ super(params.merge(flags: PG::Coder::TIMESTAMP_DB_UTC | PG::Coder::TIMESTAMP_APP_LOCAL))
14
+ end
15
+ end
16
+ class TimestampLocal < Timestamp
17
+ def initialize(params={})
18
+ super(params.merge(flags: PG::Coder::TIMESTAMP_DB_LOCAL | PG::Coder::TIMESTAMP_APP_LOCAL))
19
+ end
20
+ end
21
+ end
22
+ end # module PG
@@ -0,0 +1,83 @@
1
+ # -*- ruby -*-
2
+
3
+ module PG
4
+
5
+ class Coder
6
+
7
+ module BinaryFormatting
8
+ Params = { format: 1 }
9
+ def initialize( params={} )
10
+ super(params.merge(Params))
11
+ end
12
+ end
13
+
14
+
15
+ # Create a new coder object based on the attribute Hash.
16
+ def initialize(params={})
17
+ params.each do |key, val|
18
+ send("#{key}=", val)
19
+ end
20
+ end
21
+
22
+ def dup
23
+ self.class.new(to_h)
24
+ end
25
+
26
+ # Returns coder attributes as Hash.
27
+ def to_h
28
+ {
29
+ oid: oid,
30
+ format: format,
31
+ name: name,
32
+ }
33
+ end
34
+
35
+ def ==(v)
36
+ self.class == v.class && to_h == v.to_h
37
+ end
38
+
39
+ def marshal_dump
40
+ Marshal.dump(to_h)
41
+ end
42
+
43
+ def marshal_load(str)
44
+ initialize Marshal.load(str)
45
+ end
46
+
47
+ def inspect
48
+ str = self.to_s
49
+ oid_str = " oid=#{oid}" unless oid==0
50
+ format_str = " format=#{format}" unless format==0
51
+ name_str = " #{name.inspect}" if name
52
+ str[-1,0] = "#{name_str} #{oid_str}#{format_str}"
53
+ str
54
+ end
55
+ end
56
+
57
+ class CompositeCoder < Coder
58
+ def to_h
59
+ super.merge!({
60
+ elements_type: elements_type,
61
+ needs_quotation: needs_quotation?,
62
+ delimiter: delimiter,
63
+ })
64
+ end
65
+
66
+ def inspect
67
+ str = super
68
+ str[-1,0] = " elements_type=#{elements_type.inspect} #{needs_quotation? ? 'needs' : 'no'} quotation"
69
+ str
70
+ end
71
+ end
72
+
73
+ class CopyCoder < Coder
74
+ def to_h
75
+ super.merge!({
76
+ type_map: type_map,
77
+ delimiter: delimiter,
78
+ null_string: null_string,
79
+ })
80
+ end
81
+ end
82
+ end # module PG
83
+
@@ -0,0 +1,291 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'pg' unless defined?( PG )
4
+ require 'uri'
5
+
6
+ # The PostgreSQL connection class. The interface for this class is based on
7
+ # {libpq}[http://www.postgresql.org/docs/9.2/interactive/libpq.html], the C
8
+ # application programmer's interface to PostgreSQL. Some familiarity with libpq
9
+ # is recommended, but not necessary.
10
+ #
11
+ # For example, to send query to the database on the localhost:
12
+ #
13
+ # require 'pg'
14
+ # conn = PG::Connection.open(:dbname => 'test')
15
+ # res = conn.exec_params('SELECT $1 AS a, $2 AS b, $3 AS c', [1, 2, nil])
16
+ # # Equivalent to:
17
+ # # res = conn.exec('SELECT 1 AS a, 2 AS b, NULL AS c')
18
+ #
19
+ # See the PG::Result class for information on working with the results of a query.
20
+ #
21
+ class PG::Connection
22
+
23
+ # The order the options are passed to the ::connect method.
24
+ CONNECT_ARGUMENT_ORDER = %w[host port options tty dbname user password]
25
+
26
+
27
+ ### Quote the given +value+ for use in a connection-parameter string.
28
+ def self::quote_connstr( value )
29
+ return "'" + value.to_s.gsub( /[\\']/ ) {|m| '\\' + m } + "'"
30
+ end
31
+
32
+
33
+ ### Parse the connection +args+ into a connection-parameter string. See PG::Connection.new
34
+ ### for valid arguments.
35
+ def self::parse_connect_args( *args )
36
+ return '' if args.empty?
37
+
38
+ hash_arg = args.last.is_a?( Hash ) ? args.pop : {}
39
+ option_string = ''
40
+ options = {}
41
+
42
+ # Parameter 'fallback_application_name' was introduced in PostgreSQL 9.0
43
+ # together with PQescapeLiteral().
44
+ if PG::Connection.instance_methods.find {|m| m.to_sym == :escape_literal }
45
+ options[:fallback_application_name] = $0.sub( /^(.{30}).{4,}(.{30})$/ ){ $1+"..."+$2 }
46
+ end
47
+
48
+ if args.length == 1
49
+ case args.first
50
+ when URI, /\A#{URI.regexp}\z/
51
+ uri = URI(args.first)
52
+ options.merge!( Hash[URI.decode_www_form( uri.query )] ) if uri.query
53
+ when /=/
54
+ # Option string style
55
+ option_string = args.first.to_s
56
+ else
57
+ # Positional parameters
58
+ options[CONNECT_ARGUMENT_ORDER.first.to_sym] = args.first
59
+ end
60
+ else
61
+ max = CONNECT_ARGUMENT_ORDER.length
62
+ raise ArgumentError,
63
+ "Extra positional parameter %d: %p" % [ max + 1, args[max] ] if args.length > max
64
+
65
+ CONNECT_ARGUMENT_ORDER.zip( args ) do |(k,v)|
66
+ options[ k.to_sym ] = v if v
67
+ end
68
+ end
69
+
70
+ options.merge!( hash_arg )
71
+
72
+ if uri
73
+ uri.host = nil if options[:host]
74
+ uri.port = nil if options[:port]
75
+ uri.user = nil if options[:user]
76
+ uri.password = nil if options[:password]
77
+ uri.path = '' if options[:dbname]
78
+ uri.query = URI.encode_www_form( options )
79
+ return uri.to_s.sub( /^#{uri.scheme}:(?!\/\/)/, "#{uri.scheme}://" )
80
+ else
81
+ option_string += ' ' unless option_string.empty? && options.empty?
82
+ return option_string + options.map { |k,v| "#{k}=#{quote_connstr(v)}" }.join( ' ' )
83
+ end
84
+ end
85
+
86
+
87
+ # call-seq:
88
+ # conn.copy_data( sql [, coder] ) {|sql_result| ... } -> PG::Result
89
+ #
90
+ # Execute a copy process for transfering data to or from the server.
91
+ #
92
+ # This issues the SQL COPY command via #exec. The response to this
93
+ # (if there is no error in the command) is a PG::Result object that
94
+ # is passed to the block, bearing a status code of PGRES_COPY_OUT or
95
+ # PGRES_COPY_IN (depending on the specified copy direction).
96
+ # The application should then use #put_copy_data or #get_copy_data
97
+ # to receive or transmit data rows and should return from the block
98
+ # when finished.
99
+ #
100
+ # #copy_data returns another PG::Result object when the data transfer
101
+ # is complete. An exception is raised if some problem was encountered,
102
+ # so it isn't required to make use of any of them.
103
+ # At this point further SQL commands can be issued via #exec.
104
+ # (It is not possible to execute other SQL commands using the same
105
+ # connection while the COPY operation is in progress.)
106
+ #
107
+ # This method ensures, that the copy process is properly terminated
108
+ # in case of client side or server side failures. Therefore, in case
109
+ # of blocking mode of operation, #copy_data is preferred to raw calls
110
+ # of #put_copy_data, #get_copy_data and #put_copy_end.
111
+ #
112
+ # _coder_ can be a PG::Coder derivation
113
+ # (typically PG::TextEncoder::CopyRow or PG::TextDecoder::CopyRow).
114
+ # This enables encoding of data fields given to #put_copy_data
115
+ # or decoding of fields received by #get_copy_data.
116
+ #
117
+ # Example with CSV input format:
118
+ # conn.exec "create table my_table (a text,b text,c text,d text)"
119
+ # conn.copy_data "COPY my_table FROM STDIN CSV" do
120
+ # conn.put_copy_data "some,data,to,copy\n"
121
+ # conn.put_copy_data "more,data,to,copy\n"
122
+ # end
123
+ # This creates +my_table+ and inserts two CSV rows.
124
+ #
125
+ # The same with text format encoder PG::TextEncoder::CopyRow
126
+ # and Array input:
127
+ # enco = PG::TextEncoder::CopyRow.new
128
+ # conn.copy_data "COPY my_table FROM STDIN", enco do
129
+ # conn.put_copy_data ['some', 'data', 'to', 'copy']
130
+ # conn.put_copy_data ['more', 'data', 'to', 'copy']
131
+ # end
132
+ #
133
+ # Example with CSV output format:
134
+ # conn.copy_data "COPY my_table TO STDOUT CSV" do
135
+ # while row=conn.get_copy_data
136
+ # p row
137
+ # end
138
+ # end
139
+ # This prints all rows of +my_table+ to stdout:
140
+ # "some,data,to,copy\n"
141
+ # "more,data,to,copy\n"
142
+ #
143
+ # The same with text format decoder PG::TextDecoder::CopyRow
144
+ # and Array output:
145
+ # deco = PG::TextDecoder::CopyRow.new
146
+ # conn.copy_data "COPY my_table TO STDOUT", deco do
147
+ # while row=conn.get_copy_data
148
+ # p row
149
+ # end
150
+ # end
151
+ # This receives all rows of +my_table+ as ruby array:
152
+ # ["some", "data", "to", "copy"]
153
+ # ["more", "data", "to", "copy"]
154
+
155
+ def copy_data( sql, coder=nil )
156
+ res = exec( sql )
157
+
158
+ case res.result_status
159
+ when PGRES_COPY_IN
160
+ begin
161
+ if coder
162
+ old_coder = self.encoder_for_put_copy_data
163
+ self.encoder_for_put_copy_data = coder
164
+ end
165
+ yield res
166
+ rescue Exception => err
167
+ errmsg = "%s while copy data: %s" % [ err.class.name, err.message ]
168
+ put_copy_end( errmsg )
169
+ get_result
170
+ raise
171
+ else
172
+ put_copy_end
173
+ get_last_result
174
+ ensure
175
+ self.encoder_for_put_copy_data = old_coder if coder
176
+ end
177
+
178
+ when PGRES_COPY_OUT
179
+ begin
180
+ if coder
181
+ old_coder = self.decoder_for_get_copy_data
182
+ self.decoder_for_get_copy_data = coder
183
+ end
184
+ yield res
185
+ rescue Exception => err
186
+ cancel
187
+ while get_copy_data
188
+ end
189
+ while get_result
190
+ end
191
+ raise
192
+ else
193
+ res = get_last_result
194
+ if !res || res.result_status != PGRES_COMMAND_OK
195
+ while get_copy_data
196
+ end
197
+ while get_result
198
+ end
199
+ raise PG::NotAllCopyDataRetrieved, "Not all COPY data retrieved"
200
+ end
201
+ res
202
+ ensure
203
+ self.decoder_for_get_copy_data = old_coder if coder
204
+ end
205
+
206
+ else
207
+ raise ArgumentError, "SQL command is no COPY statement: #{sql}"
208
+ end
209
+ end
210
+
211
+ # Backward-compatibility aliases for stuff that's moved into PG.
212
+ class << self
213
+ define_method( :isthreadsafe, &PG.method(:isthreadsafe) )
214
+ end
215
+
216
+
217
+ ### Returns an array of Hashes with connection defaults. See ::conndefaults
218
+ ### for details.
219
+ def conndefaults
220
+ return self.class.conndefaults
221
+ end
222
+
223
+ ### Return the Postgres connection defaults structure as a Hash keyed by option
224
+ ### keyword (as a Symbol).
225
+ ###
226
+ ### See also #conndefaults
227
+ def self.conndefaults_hash
228
+ return self.conndefaults.each_with_object({}) do |info, hash|
229
+ hash[ info[:keyword].to_sym ] = info[:val]
230
+ end
231
+ end
232
+
233
+ ### Returns a Hash with connection defaults. See ::conndefaults_hash
234
+ ### for details.
235
+ def conndefaults_hash
236
+ return self.class.conndefaults_hash
237
+ end
238
+
239
+ # Method 'conninfo' was introduced in PostgreSQL 9.3.
240
+ if self.instance_methods.find{|m| m.to_sym == :conninfo }
241
+
242
+ ### Return the Postgres connection info structure as a Hash keyed by option
243
+ ### keyword (as a Symbol).
244
+ ###
245
+ ### See also #conninfo
246
+ def conninfo_hash
247
+ return self.conninfo.each_with_object({}) do |info, hash|
248
+ hash[ info[:keyword].to_sym ] = info[:val]
249
+ end
250
+ end
251
+ end
252
+
253
+ # Method 'ssl_attribute' was introduced in PostgreSQL 9.5.
254
+ if self.instance_methods.find{|m| m.to_sym == :ssl_attribute }
255
+ # call-seq:
256
+ # conn.ssl_attributes -> Hash<String,String>
257
+ #
258
+ # Returns SSL-related information about the connection as key/value pairs
259
+ #
260
+ # The available attributes varies depending on the SSL library being used,
261
+ # and the type of connection.
262
+ #
263
+ # See also #ssl_attribute
264
+ def ssl_attributes
265
+ ssl_attribute_names.each.with_object({}) do |n,h|
266
+ h[n] = ssl_attribute(n)
267
+ end
268
+ end
269
+ end
270
+
271
+ REDIRECT_METHODS = {
272
+ :exec => [:async_exec, :sync_exec],
273
+ :query => [:async_exec, :sync_exec],
274
+ :exec_params => [:async_exec_params, :sync_exec_params],
275
+ :prepare => [:async_prepare, :sync_prepare],
276
+ :exec_prepared => [:async_exec_prepared, :sync_exec_prepared],
277
+ :describe_portal => [:async_describe_portal, :sync_describe_portal],
278
+ :describe_prepared => [:async_describe_prepared, :sync_describe_prepared],
279
+ }
280
+
281
+ def self.async_api=(enable)
282
+ REDIRECT_METHODS.each do |ali, (async, sync)|
283
+ remove_method(ali) if method_defined?(ali)
284
+ alias_method( ali, enable ? async : sync )
285
+ end
286
+ end
287
+
288
+ # pg-1.1.0+ defaults to libpq's async API for query related blocking methods
289
+ self.async_api = true
290
+ end # class PG::Connection
291
+
@@ -0,0 +1,11 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'pg' unless defined?( PG )
4
+
5
+
6
+ module PG::Constants
7
+
8
+ # Most of these are defined in the extension.
9
+
10
+ end # module PG::Constants
11
+
@@ -0,0 +1,11 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'pg' unless defined?( PG )
4
+
5
+
6
+ module PG
7
+
8
+ class Error < StandardError; end
9
+
10
+ end # module PG
11
+
@@ -0,0 +1,31 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'pg' unless defined?( PG )
4
+
5
+
6
+ class PG::Result
7
+
8
+ # Apply a type map for all value retrieving methods.
9
+ #
10
+ # +type_map+: a PG::TypeMap instance.
11
+ #
12
+ # See PG::BasicTypeMapForResults
13
+ def map_types!(type_map)
14
+ self.type_map = type_map
15
+ return self
16
+ end
17
+
18
+
19
+ ### Return a String representation of the object suitable for debugging.
20
+ def inspect
21
+ str = self.to_s
22
+ str[-1,0] = if cleared?
23
+ " cleared"
24
+ else
25
+ " status=#{res_status(result_status)} ntuples=#{ntuples} nfields=#{nfields} cmd_tuples=#{cmd_tuples}"
26
+ end
27
+ return str
28
+ end
29
+
30
+ end # class PG::Result
31
+