pg 0.15.0.pre.454-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.gemtest +0 -0
  3. data/BSDL +22 -0
  4. data/ChangeLog +2945 -0
  5. data/Contributors.rdoc +46 -0
  6. data/History.rdoc +205 -0
  7. data/LICENSE +56 -0
  8. data/Manifest.txt +53 -0
  9. data/POSTGRES +23 -0
  10. data/README-OS_X.rdoc +68 -0
  11. data/README-Windows.rdoc +67 -0
  12. data/README.ja.rdoc +14 -0
  13. data/README.rdoc +111 -0
  14. data/Rakefile +156 -0
  15. data/Rakefile.cross +271 -0
  16. data/ext/extconf.rb +91 -0
  17. data/ext/gvl_wrappers.c +13 -0
  18. data/ext/gvl_wrappers.h +185 -0
  19. data/ext/pg.c +525 -0
  20. data/ext/pg.h +126 -0
  21. data/ext/pg_connection.c +3600 -0
  22. data/ext/pg_result.c +939 -0
  23. data/ext/vc/pg.sln +26 -0
  24. data/ext/vc/pg_18/pg.vcproj +216 -0
  25. data/ext/vc/pg_19/pg_19.vcproj +209 -0
  26. data/lib/2.0/pg_ext.so +0 -0
  27. data/lib/pg.rb +52 -0
  28. data/lib/pg/connection.rb +71 -0
  29. data/lib/pg/constants.rb +11 -0
  30. data/lib/pg/exceptions.rb +11 -0
  31. data/lib/pg/result.rb +16 -0
  32. data/sample/array_insert.rb +20 -0
  33. data/sample/async_api.rb +106 -0
  34. data/sample/async_copyto.rb +39 -0
  35. data/sample/async_mixed.rb +56 -0
  36. data/sample/check_conn.rb +21 -0
  37. data/sample/copyfrom.rb +81 -0
  38. data/sample/copyto.rb +19 -0
  39. data/sample/cursor.rb +21 -0
  40. data/sample/disk_usage_report.rb +186 -0
  41. data/sample/issue-119.rb +94 -0
  42. data/sample/losample.rb +69 -0
  43. data/sample/minimal-testcase.rb +17 -0
  44. data/sample/notify_wait.rb +72 -0
  45. data/sample/pg_statistics.rb +294 -0
  46. data/sample/replication_monitor.rb +231 -0
  47. data/sample/test_binary_values.rb +33 -0
  48. data/sample/wal_shipper.rb +434 -0
  49. data/sample/warehouse_partitions.rb +320 -0
  50. data/spec/data/expected_trace.out +26 -0
  51. data/spec/data/random_binary_data +0 -0
  52. data/spec/lib/helpers.rb +279 -0
  53. data/spec/pg/connection_spec.rb +1013 -0
  54. data/spec/pg/result_spec.rb +278 -0
  55. data/spec/pg_spec.rb +31 -0
  56. metadata +275 -0
  57. metadata.gz.sig +0 -0
Binary file
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require 'pg_ext'
5
+ rescue LoadError
6
+ # If it's a Windows binary gem, try the <major>.<minor> subdirectory
7
+ if RUBY_PLATFORM =~/(mswin|mingw)/i
8
+ major_minor = RUBY_VERSION[ /^(\d+\.\d+)/ ] or
9
+ raise "Oops, can't extract the major/minor version from #{RUBY_VERSION.dump}"
10
+ require "#{major_minor}/pg_ext"
11
+ else
12
+ raise
13
+ end
14
+
15
+ end
16
+
17
+
18
+ # The top-level PG namespace.
19
+ module PG
20
+
21
+ # Library version
22
+ VERSION = '0.15.0.pre.454'
23
+
24
+ # VCS revision
25
+ REVISION = %q$Revision$
26
+
27
+
28
+ ### Get the PG library version. If +include_buildnum+ is +true+, include the build ID.
29
+ def self::version_string( include_buildnum=false )
30
+ vstring = "%s %s" % [ self.name, VERSION ]
31
+ vstring << " (build %s)" % [ REVISION[/: ([[:xdigit:]]+)/, 1] || '0' ] if include_buildnum
32
+ return vstring
33
+ end
34
+
35
+
36
+ ### Convenience alias for PG::Connection.new.
37
+ def self::connect( *args )
38
+ return PG::Connection.new( *args )
39
+ end
40
+
41
+
42
+ require 'pg/exceptions'
43
+ require 'pg/constants'
44
+ require 'pg/connection'
45
+ require 'pg/result'
46
+
47
+ end # module PG
48
+
49
+
50
+ # Backward-compatible aliase
51
+ PGError = PG::Error
52
+
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pg' unless defined?( PG )
4
+
5
+ # The PG connection class.
6
+ class PG::Connection
7
+
8
+ # The order the options are passed to the ::connect method.
9
+ CONNECT_ARGUMENT_ORDER = %w[host port options tty dbname user password]
10
+
11
+
12
+ ### Quote the given +value+ for use in a connection-parameter string.
13
+ def self::quote_connstr( value )
14
+ return "'" + value.to_s.gsub( /[\\']/ ) {|m| '\\' + m } + "'"
15
+ end
16
+
17
+
18
+ ### Parse the connection +args+ into a connection-parameter string. See PG::Connection.new
19
+ ### for valid arguments.
20
+ def self::parse_connect_args( *args )
21
+ return '' if args.empty?
22
+
23
+ # This will be swapped soon for code that makes options like those required for
24
+ # PQconnectdbParams()/PQconnectStartParams(). For now, stick to an options string for
25
+ # PQconnectdb()/PQconnectStart().
26
+
27
+ # Parameter 'fallback_application_name' was introduced in PostgreSQL 9.0
28
+ # together with PQescapeLiteral().
29
+ if PG::Connection.instance_methods.find{|m| m.to_sym == :escape_literal }
30
+ appname = PG::Connection.quote_connstr( $0 )
31
+ connopts = ["fallback_application_name=#{appname}"]
32
+ else
33
+ connopts = []
34
+ end
35
+
36
+ # Handle an options hash first
37
+ if args.last.is_a?( Hash )
38
+ opthash = args.pop
39
+ opthash.each do |key, val|
40
+ connopts.push( "%s=%s" % [key, PG::Connection.quote_connstr(val)] )
41
+ end
42
+ end
43
+
44
+ # Option string style
45
+ if args.length == 1 && args.first.to_s.index( '=' )
46
+ connopts.unshift( args.first )
47
+
48
+ # Append positional parameters
49
+ else
50
+ args.each_with_index do |val, i|
51
+ next unless val # Skip nil placeholders
52
+
53
+ key = CONNECT_ARGUMENT_ORDER[ i ] or
54
+ raise ArgumentError, "Extra positional parameter %d: %p" % [ i+1, val ]
55
+ connopts.push( "%s=%s" % [key, PG::Connection.quote_connstr(val.to_s)] )
56
+ end
57
+ end
58
+
59
+ return connopts.join(' ')
60
+ end
61
+
62
+
63
+ # Backward-compatibility aliases for stuff that's moved into PG.
64
+ class << self
65
+ define_method( :isthreadsafe, &PG.method(:isthreadsafe) )
66
+ end
67
+ end # class PG::Connection
68
+
69
+ # Backward-compatible alias
70
+ PGconn = PG::Connection
71
+
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env 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
+ #!/usr/bin/env 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,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pg' unless defined?( PG )
4
+
5
+
6
+ class PG::Result
7
+
8
+ ### Returns all tuples as an array of arrays
9
+ def values
10
+ return enum_for(:each_row).to_a
11
+ end
12
+
13
+ end # class PG::Result
14
+
15
+ # Backward-compatible alias
16
+ PGresult = PG::Result
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pg'
4
+
5
+ c = PG.connect( dbname: 'test' )
6
+
7
+ # this one works:
8
+ c.exec( "DROP TABLE IF EXISTS foo" )
9
+ c.exec( "CREATE TABLE foo (strings character varying[]);" )
10
+
11
+ # But using a prepared statement works:
12
+ c.set_error_verbosity( PG::PQERRORS_VERBOSE )
13
+ c.prepare( 'stmt', "INSERT INTO foo VALUES ($1);" )
14
+
15
+ # This won't work
16
+ #c.exec_prepared( 'stmt', ["ARRAY['this','that']"] )
17
+
18
+ # but this will:
19
+ c.exec_prepared( 'stmt', ["{'this','that'}"] )
20
+
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pg'
4
+
5
+ # This is a example of how to use the asynchronous API to query the
6
+ # server without blocking other threads. It's intentionally low-level;
7
+ # if you hooked up the PG::Connection#socket to some kind of reactor, you
8
+ # could make this much nicer.
9
+
10
+ TIMEOUT = 5.0 # seconds to wait for an async operation to complete
11
+
12
+ # Print 'x' continuously to demonstrate that other threads aren't
13
+ # blocked while waiting for the connection, for the query to be sent,
14
+ # for results, etc. You might want to sleep inside the loop or
15
+ # comment this out entirely for cleaner output.
16
+ progress_thread = Thread.new { loop { print 'x' } }
17
+
18
+ # Output progress messages
19
+ def output_progress( msg )
20
+ puts "\n>>> #{msg}\n"
21
+ end
22
+
23
+ # Start the connection
24
+ output_progress "Starting connection..."
25
+ conn = PG::Connection.connect_start( :dbname => 'test' ) or
26
+ abort "Unable to create a new connection!"
27
+ abort "Connection failed: %s" % [ conn.error_message ] if
28
+ conn.status == PG::CONNECTION_BAD
29
+
30
+ # Now grab a reference to the underlying socket so we know when the
31
+ # connection is established
32
+ socket = conn.socket_io
33
+
34
+ # Track the progress of the connection, waiting for the socket to become readable/writable
35
+ # before polling it
36
+ poll_status = PG::PGRES_POLLING_WRITING
37
+ until poll_status == PG::PGRES_POLLING_OK ||
38
+ poll_status == PG::PGRES_POLLING_FAILED
39
+
40
+ # If the socket needs to read, wait 'til it becomes readable to poll again
41
+ case poll_status
42
+ when PG::PGRES_POLLING_READING
43
+ output_progress " waiting for socket to become readable"
44
+ select( [socket], nil, nil, TIMEOUT ) or
45
+ raise "Asynchronous connection timed out!"
46
+
47
+ # ...and the same for when the socket needs to write
48
+ when PG::PGRES_POLLING_WRITING
49
+ output_progress " waiting for socket to become writable"
50
+ select( nil, [socket], nil, TIMEOUT ) or
51
+ raise "Asynchronous connection timed out!"
52
+ end
53
+
54
+ # Output a status message about the progress
55
+ case conn.status
56
+ when PG::CONNECTION_STARTED
57
+ output_progress " waiting for connection to be made."
58
+ when PG::CONNECTION_MADE
59
+ output_progress " connection OK; waiting to send."
60
+ when PG::CONNECTION_AWAITING_RESPONSE
61
+ output_progress " waiting for a response from the server."
62
+ when PG::CONNECTION_AUTH_OK
63
+ output_progress " received authentication; waiting for backend start-up to finish."
64
+ when PG::CONNECTION_SSL_STARTUP
65
+ output_progress " negotiating SSL encryption."
66
+ when PG::CONNECTION_SETENV
67
+ output_progress " negotiating environment-driven parameter settings."
68
+ when PG::CONNECTION_NEEDED
69
+ output_progress " internal state: connect() needed."
70
+ end
71
+
72
+ # Check to see if it's finished or failed yet
73
+ poll_status = conn.connect_poll
74
+ end
75
+
76
+ abort "Connect failed: %s" % [ conn.error_message ] unless conn.status == PG::CONNECTION_OK
77
+
78
+ output_progress "Sending query"
79
+ conn.send_query( "SELECT * FROM pg_stat_activity" )
80
+
81
+ # Fetch results until there aren't any more
82
+ loop do
83
+ output_progress " waiting for a response"
84
+
85
+ # Buffer any incoming data on the socket until a full result is ready.
86
+ conn.consume_input
87
+ while conn.is_busy
88
+ select( [socket], nil, nil, TIMEOUT ) or
89
+ raise "Timeout waiting for query response."
90
+ conn.consume_input
91
+ end
92
+
93
+ # Fetch the next result. If there isn't one, the query is finished
94
+ result = conn.get_result or break
95
+
96
+ puts "\n\nQuery result:\n%p\n" % [ result.values ]
97
+ end
98
+
99
+ output_progress "Done."
100
+ conn.finish
101
+
102
+ if defined?( progress_thread )
103
+ progress_thread.kill
104
+ progress_thread.join
105
+ end
106
+
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pg'
4
+ require 'stringio'
5
+
6
+ # Using COPY asynchronously
7
+
8
+ $stderr.puts "Opening database connection ..."
9
+ conn = PG.connect( :dbname => 'test' )
10
+ conn.setnonblocking( true )
11
+
12
+ socket = conn.socket_io
13
+
14
+ $stderr.puts "Running COPY command ..."
15
+ buf = ''
16
+ conn.transaction do
17
+ conn.send_query( "COPY logs TO STDOUT WITH csv" )
18
+ buf = nil
19
+
20
+ # #get_copy_data returns a row if there's a whole one to return, false
21
+ # if there isn't one but the COPY is still running, or nil when it's
22
+ # finished.
23
+ begin
24
+ $stderr.puts "COPY loop"
25
+ conn.consume_input
26
+ while conn.is_busy
27
+ $stderr.puts " ready loop"
28
+ select( [socket], nil, nil, 5.0 ) or
29
+ raise "Timeout (5s) waiting for query response."
30
+ conn.consume_input
31
+ end
32
+
33
+ buf = conn.get_copy_data
34
+ $stdout.puts( buf ) if buf
35
+ end until buf.nil?
36
+ end
37
+
38
+ conn.finish
39
+
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pg'
4
+
5
+ $stdout.sync = true
6
+
7
+ # This is a example of how to mix and match synchronous and async APIs. In this case,
8
+ # the connection to the server is made syncrhonously, and then queries are
9
+ # asynchronous.
10
+
11
+ TIMEOUT = 5.0 # seconds to wait for an async operation to complete
12
+ CONN_OPTS = {
13
+ :host => 'localhost',
14
+ :dbname => 'test',
15
+ }
16
+
17
+ # Output progress messages
18
+ def output_progress( msg )
19
+ puts ">>> #{msg}\n"
20
+ end
21
+
22
+ # Start the (synchronous) connection
23
+ output_progress "Starting connection..."
24
+ conn = PG.connect( CONN_OPTS ) or abort "Unable to create a new connection!"
25
+
26
+ abort "Connect failed: %s" % [ conn.error_message ] unless conn.status == PG::CONNECTION_OK
27
+
28
+ # Now grab a reference to the underlying socket to select() on while the query is running
29
+ socket = conn.socket_io
30
+
31
+ # Send the (asynchronous) query
32
+ output_progress "Sending query"
33
+ conn.send_query( "SELECT * FROM pg_stat_activity" )
34
+
35
+ # Fetch results until there aren't any more
36
+ loop do
37
+ output_progress " waiting for a response"
38
+
39
+ # Buffer any incoming data on the socket until a full result is ready.
40
+ conn.consume_input
41
+ while conn.is_busy
42
+ output_progress " waiting for data to be available on %p..." % [ socket ]
43
+ select( [socket], nil, nil, TIMEOUT ) or
44
+ raise "Timeout waiting for query response."
45
+ conn.consume_input
46
+ end
47
+
48
+ # Fetch the next result. If there isn't one, the query is finished
49
+ result = conn.get_result or break
50
+
51
+ output_progress "Query result:\n%p\n" % [ result.values ]
52
+ end
53
+
54
+ output_progress "Done."
55
+ conn.finish
56
+
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set nosta noet ts=4 sw=4:
3
+ # encoding: utf-8
4
+
5
+ require 'pg'
6
+
7
+ # This is a minimal example of a function that can test an existing PG::Connection and
8
+ # reset it if necessary.
9
+
10
+ def check_connection( conn )
11
+ begin
12
+ conn.exec( "SELECT 1" )
13
+ rescue PG::Error => err
14
+ $stderr.puts "%p while testing connection: %s" % [ err.class, err.message ]
15
+ conn.reset
16
+ end
17
+ end
18
+
19
+ conn = PG.connect( dbname: 'test' )
20
+ check_connection( conn )
21
+
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pg'
4
+ require 'stringio'
5
+
6
+ $stderr.puts "Opening database connection ..."
7
+ conn = PG.connect( :dbname => 'test' )
8
+
9
+ conn.exec( <<END_SQL )
10
+ DROP TABLE IF EXISTS logs;
11
+ CREATE TABLE logs (
12
+ client_ip inet,
13
+ username text,
14
+ ts timestamp,
15
+ request text,
16
+ status smallint,
17
+ bytes int
18
+ );
19
+ END_SQL
20
+
21
+ copy_data = StringIO.new( <<"END_DATA" )
22
+ "127.0.0.1","","30/Aug/2010:08:21:24 -0700","GET /manual/ HTTP/1.1",404,205
23
+ "127.0.0.1","","30/Aug/2010:08:21:24 -0700","GET /favicon.ico HTTP/1.1",404,209
24
+ "127.0.0.1","","30/Aug/2010:08:21:24 -0700","GET /favicon.ico HTTP/1.1",404,209
25
+ "127.0.0.1","","30/Aug/2010:08:22:29 -0700","GET /manual/ HTTP/1.1",200,11094
26
+ "127.0.0.1","","30/Aug/2010:08:22:38 -0700","GET /manual/index.html HTTP/1.1",200,725
27
+ "127.0.0.1","","30/Aug/2010:08:27:56 -0700","GET /manual/ HTTP/1.1",200,11094
28
+ "127.0.0.1","","30/Aug/2010:08:27:57 -0700","GET /manual/ HTTP/1.1",200,11094
29
+ "127.0.0.1","","30/Aug/2010:08:28:06 -0700","GET /manual/index.html HTTP/1.1",200,7709
30
+ "127.0.0.1","","30/Aug/2010:08:28:06 -0700","GET /manual/images/feather.gif HTTP/1.1",200,6471
31
+ "127.0.0.1","","30/Aug/2010:08:28:06 -0700","GET /manual/images/left.gif HTTP/1.1",200,60
32
+ "127.0.0.1","","30/Aug/2010:08:28:06 -0700","GET /manual/style/css/manual.css HTTP/1.1",200,18674
33
+ "127.0.0.1","","30/Aug/2010:08:28:06 -0700","GET /manual/style/css/manual-print.css HTTP/1.1",200,13200
34
+ "127.0.0.1","","30/Aug/2010:08:28:06 -0700","GET /manual/images/favicon.ico HTTP/1.1",200,1078
35
+ "127.0.0.1","","30/Aug/2010:08:28:06 -0700","GET /manual/style/css/manual-loose-100pc.css HTTP/1.1",200,3065
36
+ "127.0.0.1","","30/Aug/2010:08:28:14 -0700","OPTIONS * HTTP/1.0",200,0
37
+ "127.0.0.1","","30/Aug/2010:08:28:15 -0700","OPTIONS * HTTP/1.0",200,0
38
+ "127.0.0.1","","30/Aug/2010:08:28:47 -0700","GET /manual/mod/directives.html HTTP/1.1",200,33561
39
+ "127.0.0.1","","30/Aug/2010:08:28:53 -0700","GET /manual/mod/mpm_common.html HTTP/1.1",200,67683
40
+ "127.0.0.1","","30/Aug/2010:08:28:53 -0700","GET /manual/images/down.gif HTTP/1.1",200,56
41
+ "127.0.0.1","","30/Aug/2010:08:28:53 -0700","GET /manual/images/up.gif HTTP/1.1",200,57
42
+ "127.0.0.1","","30/Aug/2010:09:19:58 -0700","GET /manual/mod/mod_log_config.html HTTP/1.1",200,28307
43
+ "127.0.0.1","","30/Aug/2010:09:20:19 -0700","GET /manual/mod/core.html HTTP/1.1",200,194144
44
+ "127.0.0.1","","30/Aug/2010:16:02:56 -0700","GET /manual/ HTTP/1.1",200,11094
45
+ "127.0.0.1","","30/Aug/2010:16:03:00 -0700","GET /manual/ HTTP/1.1",200,11094
46
+ "127.0.0.1","","30/Aug/2010:16:06:16 -0700","GET /manual/mod/mod_dir.html HTTP/1.1",200,10583
47
+ "127.0.0.1","","30/Aug/2010:16:06:44 -0700","GET /manual/ HTTP/1.1",200,7709
48
+ END_DATA
49
+
50
+ ### You can test the error case from the database side easily by
51
+ ### changing one of the numbers at the end of one of the above rows to
52
+ ### something non-numeric like "-".
53
+
54
+ $stderr.puts "Running COPY command with data ..."
55
+ buf = ''
56
+ conn.transaction do
57
+ conn.exec( "COPY logs FROM STDIN WITH csv" )
58
+ begin
59
+ while copy_data.read( 256, buf )
60
+ ### Uncomment this to test error-handling for exceptions from the reader side:
61
+ # raise Errno::ECONNRESET, "socket closed while reading"
62
+ $stderr.puts " sending %d bytes of data..." % [ buf.length ]
63
+ until conn.put_copy_data( buf )
64
+ $stderr.puts " waiting for connection to be writable..."
65
+ sleep 0.1
66
+ end
67
+ end
68
+ rescue Errno => err
69
+ errmsg = "%s while reading copy data: %s" % [ err.class.name, err.message ]
70
+ conn.put_copy_end( errmsg )
71
+ else
72
+ conn.put_copy_end
73
+ while res = conn.get_result
74
+ $stderr.puts "Result of COPY is: %s" % [ res.res_status(res.result_status) ]
75
+ end
76
+ end
77
+ end
78
+
79
+
80
+ conn.finish
81
+