pg 1.2.3 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.appveyor.yml +36 -0
  4. data/.gems +6 -0
  5. data/.github/workflows/binary-gems.yml +86 -0
  6. data/.github/workflows/source-gem.yml +130 -0
  7. data/.gitignore +13 -0
  8. data/.hgsigs +34 -0
  9. data/.hgtags +41 -0
  10. data/.irbrc +23 -0
  11. data/.pryrc +23 -0
  12. data/.tm_properties +21 -0
  13. data/.travis.yml +49 -0
  14. data/Gemfile +14 -0
  15. data/History.rdoc +95 -7
  16. data/Manifest.txt +0 -1
  17. data/README.rdoc +7 -6
  18. data/Rakefile +27 -138
  19. data/Rakefile.cross +6 -5
  20. data/certs/ged.pem +24 -0
  21. data/ext/errorcodes.def +8 -0
  22. data/ext/errorcodes.txt +3 -1
  23. data/ext/extconf.rb +91 -19
  24. data/ext/gvl_wrappers.c +4 -0
  25. data/ext/gvl_wrappers.h +23 -0
  26. data/ext/pg.c +59 -4
  27. data/ext/pg.h +18 -1
  28. data/ext/pg_coder.c +82 -28
  29. data/ext/pg_connection.c +673 -493
  30. data/ext/pg_copy_coder.c +45 -16
  31. data/ext/pg_record_coder.c +39 -11
  32. data/ext/pg_result.c +61 -31
  33. data/ext/pg_text_decoder.c +1 -1
  34. data/ext/pg_text_encoder.c +6 -6
  35. data/ext/pg_tuple.c +47 -21
  36. data/ext/pg_type_map.c +41 -8
  37. data/ext/pg_type_map_all_strings.c +14 -1
  38. data/ext/pg_type_map_by_class.c +49 -24
  39. data/ext/pg_type_map_by_column.c +64 -28
  40. data/ext/pg_type_map_by_mri_type.c +47 -18
  41. data/ext/pg_type_map_by_oid.c +52 -23
  42. data/ext/pg_type_map_in_ruby.c +50 -19
  43. data/ext/pg_util.c +2 -2
  44. data/lib/pg/basic_type_map_based_on_result.rb +47 -0
  45. data/lib/pg/basic_type_map_for_queries.rb +193 -0
  46. data/lib/pg/basic_type_map_for_results.rb +81 -0
  47. data/lib/pg/basic_type_registry.rb +296 -0
  48. data/lib/pg/coder.rb +1 -1
  49. data/lib/pg/connection.rb +588 -58
  50. data/lib/pg/version.rb +4 -0
  51. data/lib/pg.rb +47 -32
  52. data/misc/openssl-pg-segfault.rb +31 -0
  53. data/misc/postgres/History.txt +9 -0
  54. data/misc/postgres/Manifest.txt +5 -0
  55. data/misc/postgres/README.txt +21 -0
  56. data/misc/postgres/Rakefile +21 -0
  57. data/misc/postgres/lib/postgres.rb +16 -0
  58. data/misc/ruby-pg/History.txt +9 -0
  59. data/misc/ruby-pg/Manifest.txt +5 -0
  60. data/misc/ruby-pg/README.txt +21 -0
  61. data/misc/ruby-pg/Rakefile +21 -0
  62. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  63. data/pg.gemspec +32 -0
  64. data/sample/array_insert.rb +20 -0
  65. data/sample/async_api.rb +106 -0
  66. data/sample/async_copyto.rb +39 -0
  67. data/sample/async_mixed.rb +56 -0
  68. data/sample/check_conn.rb +21 -0
  69. data/sample/copydata.rb +71 -0
  70. data/sample/copyfrom.rb +81 -0
  71. data/sample/copyto.rb +19 -0
  72. data/sample/cursor.rb +21 -0
  73. data/sample/disk_usage_report.rb +177 -0
  74. data/sample/issue-119.rb +94 -0
  75. data/sample/losample.rb +69 -0
  76. data/sample/minimal-testcase.rb +17 -0
  77. data/sample/notify_wait.rb +72 -0
  78. data/sample/pg_statistics.rb +285 -0
  79. data/sample/replication_monitor.rb +222 -0
  80. data/sample/test_binary_values.rb +33 -0
  81. data/sample/wal_shipper.rb +434 -0
  82. data/sample/warehouse_partitions.rb +311 -0
  83. data.tar.gz.sig +0 -0
  84. metadata +76 -217
  85. metadata.gz.sig +0 -0
  86. data/ChangeLog +0 -0
  87. data/lib/pg/basic_type_mapping.rb +0 -522
  88. data/spec/data/expected_trace.out +0 -26
  89. data/spec/data/random_binary_data +0 -0
  90. data/spec/helpers.rb +0 -380
  91. data/spec/pg/basic_type_mapping_spec.rb +0 -630
  92. data/spec/pg/connection_spec.rb +0 -1949
  93. data/spec/pg/connection_sync_spec.rb +0 -41
  94. data/spec/pg/result_spec.rb +0 -681
  95. data/spec/pg/tuple_spec.rb +0 -333
  96. data/spec/pg/type_map_by_class_spec.rb +0 -138
  97. data/spec/pg/type_map_by_column_spec.rb +0 -226
  98. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  99. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  100. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  101. data/spec/pg/type_map_spec.rb +0 -22
  102. data/spec/pg/type_spec.rb +0 -1123
  103. data/spec/pg_spec.rb +0 -50
data/spec/helpers.rb DELETED
@@ -1,380 +0,0 @@
1
- # -*- ruby -*-
2
-
3
- require 'pathname'
4
- require 'rspec'
5
- require 'shellwords'
6
- require 'pg'
7
-
8
- DEFAULT_TEST_DIR_STR = File.join(Dir.pwd, "tmp_test_specs")
9
- TEST_DIR_STR = ENV['RUBY_PG_TEST_DIR'] || DEFAULT_TEST_DIR_STR
10
- TEST_DIRECTORY = Pathname.new(TEST_DIR_STR)
11
-
12
- module PG::TestingHelpers
13
-
14
- ### Automatically set up the database when it's used, and wrap a transaction around
15
- ### examples that don't disable it.
16
- def self::included( mod )
17
- super
18
-
19
- if mod.respond_to?( :around )
20
-
21
- mod.before( :all ) { @conn = setup_testing_db(described_class ? described_class.name : mod.description) }
22
-
23
- mod.around( :each ) do |example|
24
- begin
25
- @conn.set_default_encoding
26
- @conn.exec( 'BEGIN' ) unless example.metadata[:without_transaction]
27
- desc = example.source_location.join(':')
28
- @conn.exec %Q{SET application_name TO '%s'} %
29
- [@conn.escape_string(desc.slice(-60))]
30
- example.run
31
- ensure
32
- @conn.exec( 'ROLLBACK' ) unless example.metadata[:without_transaction]
33
- end
34
- end
35
-
36
- mod.after( :all ) { teardown_testing_db(@conn) }
37
- end
38
-
39
- end
40
-
41
-
42
- #
43
- # Examples
44
- #
45
-
46
- # Set some ANSI escape code constants (Shamelessly stolen from Perl's
47
- # Term::ANSIColor by Russ Allbery <rra@stanford.edu> and Zenin <zenin@best.com>
48
- ANSI_ATTRIBUTES = {
49
- 'clear' => 0,
50
- 'reset' => 0,
51
- 'bold' => 1,
52
- 'dark' => 2,
53
- 'underline' => 4,
54
- 'underscore' => 4,
55
- 'blink' => 5,
56
- 'reverse' => 7,
57
- 'concealed' => 8,
58
-
59
- 'black' => 30, 'on_black' => 40,
60
- 'red' => 31, 'on_red' => 41,
61
- 'green' => 32, 'on_green' => 42,
62
- 'yellow' => 33, 'on_yellow' => 43,
63
- 'blue' => 34, 'on_blue' => 44,
64
- 'magenta' => 35, 'on_magenta' => 45,
65
- 'cyan' => 36, 'on_cyan' => 46,
66
- 'white' => 37, 'on_white' => 47
67
- }
68
-
69
-
70
- ###############
71
- module_function
72
- ###############
73
-
74
- ### Create a string that contains the ANSI codes specified and return it
75
- def ansi_code( *attributes )
76
- attributes.flatten!
77
- attributes.collect! {|at| at.to_s }
78
-
79
- return '' unless /(?:vt10[03]|xterm(?:-color)?|linux|screen)/i =~ ENV['TERM']
80
- attributes = ANSI_ATTRIBUTES.values_at( *attributes ).compact.join(';')
81
-
82
- # $stderr.puts " attr is: %p" % [attributes]
83
- if attributes.empty?
84
- return ''
85
- else
86
- return "\e[%sm" % attributes
87
- end
88
- end
89
-
90
-
91
- ### Colorize the given +string+ with the specified +attributes+ and return it, handling
92
- ### line-endings, color reset, etc.
93
- def colorize( *args )
94
- string = ''
95
-
96
- if block_given?
97
- string = yield
98
- else
99
- string = args.shift
100
- end
101
-
102
- ending = string[/(\s)$/] || ''
103
- string = string.rstrip
104
-
105
- return ansi_code( args.flatten ) + string + ansi_code( 'reset' ) + ending
106
- end
107
-
108
-
109
- ### Output a message with highlighting.
110
- def message( *msg )
111
- $stderr.puts( colorize(:bold) { msg.flatten.join(' ') } )
112
- end
113
-
114
-
115
- ### Output a logging message if $VERBOSE is true
116
- def trace( *msg )
117
- return unless $VERBOSE
118
- output = colorize( msg.flatten.join(' '), 'yellow' )
119
- $stderr.puts( output )
120
- end
121
-
122
-
123
- ### Return the specified args as a string, quoting any that have a space.
124
- def quotelist( *args )
125
- return args.flatten.collect {|part| part.to_s =~ /\s/ ? part.to_s.inspect : part.to_s }
126
- end
127
-
128
-
129
- ### Run the specified command +cmd+ with system(), failing if the execution
130
- ### fails.
131
- def run( *cmd )
132
- cmd.flatten!
133
-
134
- if cmd.length > 1
135
- trace( quotelist(*cmd) )
136
- else
137
- trace( cmd )
138
- end
139
-
140
- system( *cmd )
141
- raise "Command failed: [%s]" % [cmd.join(' ')] unless $?.success?
142
- end
143
-
144
-
145
- ### Run the specified command +cmd+ after redirecting stdout and stderr to the specified
146
- ### +logpath+, failing if the execution fails.
147
- def log_and_run( logpath, *cmd )
148
- cmd.flatten!
149
-
150
- if cmd.length > 1
151
- trace( quotelist(*cmd) )
152
- else
153
- trace( cmd )
154
- end
155
-
156
- # Eliminate the noise of creating/tearing down the database by
157
- # redirecting STDERR/STDOUT to a logfile
158
- logfh = File.open( logpath, File::WRONLY|File::CREAT|File::APPEND )
159
- system( *cmd, [STDOUT, STDERR] => logfh )
160
-
161
- raise "Command failed: [%s]" % [cmd.join(' ')] unless $?.success?
162
- end
163
-
164
-
165
- ### Check the current directory for directories that look like they're
166
- ### testing directories from previous tests, and tell any postgres instances
167
- ### running in them to shut down.
168
- def stop_existing_postmasters
169
- # tmp_test_0.22329534700318
170
- pat = Pathname.getwd + 'tmp_test_*'
171
- Pathname.glob( pat.to_s ).each do |testdir|
172
- datadir = testdir + 'data'
173
- pidfile = datadir + 'postmaster.pid'
174
- if pidfile.exist? && pid = pidfile.read.chomp.to_i
175
- trace "pidfile (%p) exists: %d" % [ pidfile, pid ]
176
- begin
177
- Process.kill( 0, pid )
178
- rescue Errno::ESRCH
179
- trace "No postmaster running for %s" % [ datadir ]
180
- # Process isn't alive, so don't try to stop it
181
- else
182
- trace "Stopping lingering database at PID %d" % [ pid ]
183
- run 'pg_ctl', '-D', datadir.to_s, '-m', 'fast', 'stop'
184
- end
185
- else
186
- trace "No pidfile (%p)" % [ pidfile ]
187
- end
188
- end
189
- end
190
-
191
-
192
- ### Set up a PostgreSQL database instance for testing.
193
- def setup_testing_db( description )
194
- require 'pg'
195
- stop_existing_postmasters()
196
-
197
- trace "Setting up test database for #{description}"
198
- @test_pgdata = TEST_DIRECTORY + 'data'
199
- @test_pgdata.mkpath
200
-
201
- ENV['PGPORT'] ||= "54321"
202
- @port = ENV['PGPORT'].to_i
203
- ENV['PGHOST'] = 'localhost'
204
- @conninfo = "host=localhost port=#{@port} dbname=test"
205
-
206
- @logfile = TEST_DIRECTORY + 'setup.log'
207
- trace "Command output logged to #{@logfile}"
208
-
209
- begin
210
- unless (@test_pgdata+"postgresql.conf").exist?
211
- FileUtils.rm_rf( @test_pgdata, :verbose => $DEBUG )
212
- trace "Running initdb"
213
- log_and_run @logfile, 'initdb', '-E', 'UTF8', '--no-locale', '-D', @test_pgdata.to_s
214
- end
215
-
216
- trace "Starting postgres"
217
- log_and_run @logfile, 'pg_ctl', '-w', '-o', "-k #{TEST_DIRECTORY.to_s.dump}",
218
- '-D', @test_pgdata.to_s, 'start'
219
- sleep 2
220
-
221
- trace "Creating the test DB"
222
- log_and_run @logfile, 'psql', '-e', '-c', 'DROP DATABASE IF EXISTS test', 'postgres'
223
- log_and_run @logfile, 'createdb', '-e', 'test'
224
-
225
- rescue => err
226
- $stderr.puts "%p during test setup: %s" % [ err.class, err.message ]
227
- $stderr.puts "See #{@logfile} for details."
228
- $stderr.puts err.backtrace if $DEBUG
229
- fail
230
- end
231
-
232
- conn = PG.connect( @conninfo )
233
- conn.set_notice_processor do |message|
234
- $stderr.puts( description + ':' + message ) if $DEBUG
235
- end
236
-
237
- return conn
238
- end
239
-
240
-
241
- def teardown_testing_db( conn )
242
- trace "Tearing down test database"
243
-
244
- if conn
245
- check_for_lingering_connections( conn )
246
- conn.finish
247
- end
248
-
249
- log_and_run @logfile, 'pg_ctl', '-D', @test_pgdata.to_s, 'stop'
250
- end
251
-
252
-
253
- def check_for_lingering_connections( conn )
254
- conn.exec( "SELECT * FROM pg_stat_activity" ) do |res|
255
- conns = res.find_all {|row| row['pid'].to_i != conn.backend_pid && ["client backend", nil].include?(row["backend_type"]) }
256
- unless conns.empty?
257
- puts "Lingering connections remain:"
258
- conns.each do |row|
259
- puts " [%s] {%s} %s -- %s" % row.values_at( 'pid', 'state', 'application_name', 'query' )
260
- end
261
- end
262
- end
263
- end
264
-
265
-
266
- # Retrieve the names of the column types of a given result set.
267
- def result_typenames(res)
268
- @conn.exec_params( "SELECT " + res.nfields.times.map{|i| "format_type($#{i*2+1},$#{i*2+2})"}.join(","),
269
- res.nfields.times.map{|i| [res.ftype(i), res.fmod(i)] }.flatten ).
270
- values[0]
271
- end
272
-
273
-
274
- # A matcher for checking the status of a PG::Connection to ensure it's still
275
- # usable.
276
- class ConnStillUsableMatcher
277
-
278
- def initialize
279
- @conn = nil
280
- @problem = nil
281
- end
282
-
283
- def matches?( conn )
284
- @conn = conn
285
- @problem = self.check_for_problems
286
- return @problem.nil?
287
- end
288
-
289
- def check_for_problems
290
- return "is finished" if @conn.finished?
291
- return "has bad status" unless @conn.status == PG::CONNECTION_OK
292
- return "has bad transaction status (%d)" % [ @conn.transaction_status ] unless
293
- @conn.transaction_status.between?( PG::PQTRANS_IDLE, PG::PQTRANS_INTRANS )
294
- return "is not usable." unless self.can_exec_query?
295
- return nil
296
- end
297
-
298
- def can_exec_query?
299
- @conn.send_query( "VALUES (1)" )
300
- @conn.get_last_result.values == [["1"]]
301
- end
302
-
303
- def failure_message
304
- return "expected %p to be usable, but it %s" % [ @conn, @problem ]
305
- end
306
-
307
- def failure_message_when_negated
308
- "expected %p not to be usable, but it still is" % [ @conn ]
309
- end
310
-
311
- end
312
-
313
-
314
- ### Return a ConnStillUsableMatcher to be used like:
315
- ###
316
- ### expect( pg_conn ).to still_be_usable
317
- ###
318
- def still_be_usable
319
- return ConnStillUsableMatcher.new
320
- end
321
-
322
- def wait_for_polling_ok(conn, meth = :connect_poll)
323
- status = conn.send(meth)
324
-
325
- while status != PG::PGRES_POLLING_OK
326
- if status == PG::PGRES_POLLING_READING
327
- select( [conn.socket_io], [], [], 5.0 ) or
328
- raise "Asynchronous connection timed out!"
329
-
330
- elsif status == PG::PGRES_POLLING_WRITING
331
- select( [], [conn.socket_io], [], 5.0 ) or
332
- raise "Asynchronous connection timed out!"
333
- end
334
- status = conn.send(meth)
335
- end
336
- end
337
-
338
- def wait_for_query_result(conn)
339
- result = nil
340
- loop do
341
- # Buffer any incoming data on the socket until a full result is ready.
342
- conn.consume_input
343
- while conn.is_busy
344
- select( [conn.socket_io], nil, nil, 5.0 ) or
345
- raise "Timeout waiting for query response."
346
- conn.consume_input
347
- end
348
-
349
- # Fetch the next result. If there isn't one, the query is finished
350
- result = conn.get_result || break
351
- end
352
- result
353
- end
354
-
355
- end
356
-
357
-
358
- RSpec.configure do |config|
359
- config.include( PG::TestingHelpers )
360
-
361
- config.run_all_when_everything_filtered = true
362
- config.filter_run :focus
363
- config.order = 'random'
364
- config.mock_with( :rspec ) do |mock|
365
- mock.syntax = :expect
366
- end
367
-
368
- if RUBY_PLATFORM =~ /mingw|mswin/
369
- config.filter_run_excluding :unix
370
- else
371
- config.filter_run_excluding :windows
372
- end
373
-
374
- config.filter_run_excluding( :postgresql_93 ) if PG.library_version < 90300
375
- config.filter_run_excluding( :postgresql_94 ) if PG.library_version < 90400
376
- config.filter_run_excluding( :postgresql_95 ) if PG.library_version < 90500
377
- config.filter_run_excluding( :postgresql_96 ) if PG.library_version < 90600
378
- config.filter_run_excluding( :postgresql_10 ) if PG.library_version < 100000
379
- config.filter_run_excluding( :postgresql_12 ) if PG.library_version < 120000
380
- end