pg 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
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
+