pg 0.12.2-x86-mingw32 → 0.13.0-x86-mingw32

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 (50) hide show
  1. data/.hoerc +2 -0
  2. data/.tm_properties +12 -0
  3. data/ChangeLog +166 -59
  4. data/Contributors.rdoc +7 -0
  5. data/History.rdoc +29 -0
  6. data/LICENSE +12 -14
  7. data/Manifest.txt +15 -14
  8. data/{BSD → POSTGRES} +0 -0
  9. data/{README.OS_X.rdoc → README-OS_X.rdoc} +0 -0
  10. data/{README.windows.rdoc → README-Windows.rdoc} +0 -0
  11. data/README.ja.rdoc +1 -1
  12. data/README.rdoc +39 -27
  13. data/Rakefile +1 -5
  14. data/Rakefile.cross +2 -2
  15. data/ext/extconf.rb +8 -2
  16. data/ext/pg.c +232 -4297
  17. data/ext/pg.h +88 -23
  18. data/ext/pg_connection.c +3288 -0
  19. data/ext/pg_result.c +905 -0
  20. data/lib/1.8/pg_ext.so +0 -0
  21. data/lib/1.9/pg_ext.so +0 -0
  22. data/lib/pg.rb +26 -43
  23. data/lib/pg/connection.rb +58 -0
  24. data/lib/pg/constants.rb +11 -0
  25. data/lib/pg/exceptions.rb +11 -0
  26. data/lib/pg/result.rb +11 -0
  27. data/misc/openssl-pg-segfault.rb +1 -1
  28. data/sample/async_api.rb +16 -21
  29. data/sample/async_copyto.rb +1 -1
  30. data/sample/async_mixed.rb +56 -0
  31. data/sample/copyfrom.rb +1 -1
  32. data/sample/copyto.rb +1 -1
  33. data/sample/cursor.rb +1 -1
  34. data/sample/losample.rb +6 -6
  35. data/sample/notify_wait.rb +51 -22
  36. data/sample/test_binary_values.rb +4 -6
  37. data/spec/lib/helpers.rb +14 -10
  38. data/spec/{pgconn_spec.rb → pg/connection_spec.rb} +228 -60
  39. data/spec/{pgresult_spec.rb → pg/result_spec.rb} +31 -35
  40. data/spec/pg_spec.rb +22 -0
  41. metadata +52 -41
  42. data/GPL +0 -340
  43. data/ext/compat.c +0 -541
  44. data/ext/compat.h +0 -184
  45. data/sample/psql.rb +0 -1181
  46. data/sample/psqlHelp.rb +0 -158
  47. data/sample/test1.rb +0 -60
  48. data/sample/test2.rb +0 -44
  49. data/sample/test4.rb +0 -71
  50. data/spec/m17n_spec.rb +0 -170
Binary file
Binary file
data/lib/pg.rb CHANGED
@@ -14,56 +14,39 @@ rescue LoadError
14
14
 
15
15
  end
16
16
 
17
- #--
18
- # The PG connection class.
19
- class PGconn
20
17
 
21
- # The order the options are passed to the ::connect method.
22
- CONNECT_ARGUMENT_ORDER = %w[host port options tty dbname user password]
18
+ # The top-level PG namespace.
19
+ module PG
23
20
 
21
+ # Library version
22
+ VERSION = '0.13.0'
24
23
 
25
- ### Quote the given +value+ for use in a connection-parameter string.
26
- def self::quote_connstr( value )
27
- return "'" + value.to_s.gsub( /[\\']/ ) {|m| '\\' + m } + "'"
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
28
33
  end
29
34
 
30
35
 
31
- ### Parse the connection +args+ into a connection-parameter string. See PGconn.new
32
- ### for valid arguments.
33
- def self::parse_connect_args( *args )
34
- return '' if args.empty?
35
-
36
- # This will be swapped soon for code that makes options like those required for
37
- # PQconnectdbParams()/PQconnectStartParams(). For now, stick to an options string for
38
- # PQconnectdb()/PQconnectStart().
39
- connopts = []
40
-
41
- # Handle an options hash first
42
- if args.last.is_a?( Hash )
43
- opthash = args.pop
44
- opthash.each do |key, val|
45
- connopts.push( "%s=%s" % [key, PGconn.quote_connstr(val)] )
46
- end
47
- end
48
-
49
- # Option string style
50
- if args.length == 1 && args.first.to_s.index( '=' )
51
- connopts.unshift( args.first )
52
-
53
- # Append positional parameters
54
- else
55
- args.each_with_index do |val, i|
56
- next unless val # Skip nil placeholders
57
-
58
- key = CONNECT_ARGUMENT_ORDER[ i ] or
59
- raise ArgumentError, "Extra positional parameter %d: %p" % [ i+1, val ]
60
- connopts.push( "%s=%s" % [key, PGconn.quote_connstr(val.to_s)] )
61
- end
62
- end
63
-
64
- return connopts.join(' ')
36
+ ### Convenience alias for PG::Connection.new.
37
+ def self::connect( *args )
38
+ return PG::Connection.new( *args )
65
39
  end
66
40
 
67
- end # class PGconn
68
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
69
52
 
@@ -0,0 +1,58 @@
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
+ connopts = []
27
+
28
+ # Handle an options hash first
29
+ if args.last.is_a?( Hash )
30
+ opthash = args.pop
31
+ opthash.each do |key, val|
32
+ connopts.push( "%s=%s" % [key, PG::Connection.quote_connstr(val)] )
33
+ end
34
+ end
35
+
36
+ # Option string style
37
+ if args.length == 1 && args.first.to_s.index( '=' )
38
+ connopts.unshift( args.first )
39
+
40
+ # Append positional parameters
41
+ else
42
+ args.each_with_index do |val, i|
43
+ next unless val # Skip nil placeholders
44
+
45
+ key = CONNECT_ARGUMENT_ORDER[ i ] or
46
+ raise ArgumentError, "Extra positional parameter %d: %p" % [ i+1, val ]
47
+ connopts.push( "%s=%s" % [key, PG::Connection.quote_connstr(val.to_s)] )
48
+ end
49
+ end
50
+
51
+ return connopts.join(' ')
52
+ end
53
+
54
+ end # class PG::Connection
55
+
56
+ # Backward-compatible alias
57
+ PGconn = PG::Connection
58
+
@@ -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,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pg' unless defined?( PG )
4
+
5
+
6
+ class PG::Result
7
+
8
+ end # class PG::Result
9
+
10
+ # Backward-compatible alias
11
+ PGresult = PG::Result
@@ -8,7 +8,7 @@ SOCKHOST = 'it-trac.laika.com'
8
8
  # Load pg first, so the libssl.so that libpq is linked against is loaded.
9
9
  require 'pg'
10
10
  $stderr.puts "connecting to postgres://#{PGHOST}/#{PGDB}"
11
- conn = PGconn.connect( PGHOST, :dbname => PGDB )
11
+ conn = PG.connect( PGHOST, :dbname => PGDB )
12
12
 
13
13
  # Now load OpenSSL, which might be linked against a different libssl.
14
14
  require 'socket'
@@ -4,16 +4,10 @@ require 'pg'
4
4
 
5
5
  # This is a example of how to use the asynchronous API to query the
6
6
  # server without blocking other threads. It's intentionally low-level;
7
- # if you hooked up the PGconn#socket to some kind of reactor, you
7
+ # if you hooked up the PG::Connection#socket to some kind of reactor, you
8
8
  # could make this much nicer.
9
9
 
10
10
  TIMEOUT = 5.0 # seconds to wait for an async operation to complete
11
- CONN_OPTS = {
12
- :host => 'localhost',
13
- :dbname => 'test',
14
- :user => 'jrandom',
15
- :password => 'banks!stealUR$',
16
- }
17
11
 
18
12
  # Print 'x' continuously to demonstrate that other threads aren't
19
13
  # blocked while waiting for the connection, for the query to be sent,
@@ -28,9 +22,10 @@ end
28
22
 
29
23
  # Start the connection
30
24
  output_progress "Starting connection..."
31
- conn = PGconn.connect_start( CONN_OPTS ) or abort "Unable to create a new connection!"
25
+ conn = PG::Connection.connect_start( :dbname => 'test' ) or
26
+ abort "Unable to create a new connection!"
32
27
  abort "Connection failed: %s" % [ conn.error_message ] if
33
- conn.status == PGconn::CONNECTION_BAD
28
+ conn.status == PG::CONNECTION_BAD
34
29
 
35
30
  # Now grab a reference to the underlying socket so we know when the
36
31
  # connection is established
@@ -38,19 +33,19 @@ socket = IO.for_fd( conn.socket )
38
33
 
39
34
  # Track the progress of the connection, waiting for the socket to become readable/writable
40
35
  # before polling it
41
- poll_status = PGconn::PGRES_POLLING_WRITING
42
- until poll_status == PGconn::PGRES_POLLING_OK ||
43
- poll_status == PGconn::PGRES_POLLING_FAILED
36
+ poll_status = PG::PGRES_POLLING_WRITING
37
+ until poll_status == PG::PGRES_POLLING_OK ||
38
+ poll_status == PG::PGRES_POLLING_FAILED
44
39
 
45
40
  # If the socket needs to read, wait 'til it becomes readable to poll again
46
41
  case poll_status
47
- when PGconn::PGRES_POLLING_READING
42
+ when PG::PGRES_POLLING_READING
48
43
  output_progress " waiting for socket to become readable"
49
44
  select( [socket], nil, nil, TIMEOUT ) or
50
45
  raise "Asynchronous connection timed out!"
51
46
 
52
47
  # ...and the same for when the socket needs to write
53
- when PGconn::PGRES_POLLING_WRITING
48
+ when PG::PGRES_POLLING_WRITING
54
49
  output_progress " waiting for socket to become writable"
55
50
  select( nil, [socket], nil, TIMEOUT ) or
56
51
  raise "Asynchronous connection timed out!"
@@ -58,17 +53,17 @@ until poll_status == PGconn::PGRES_POLLING_OK ||
58
53
 
59
54
  # Output a status message about the progress
60
55
  case conn.status
61
- when PGconn::CONNECTION_STARTED
56
+ when PG::CONNECTION_STARTED
62
57
  output_progress " waiting for connection to be made."
63
- when PGconn::CONNECTION_MADE
58
+ when PG::CONNECTION_MADE
64
59
  output_progress " connection OK; waiting to send."
65
- when PGconn::CONNECTION_AWAITING_RESPONSE
60
+ when PG::CONNECTION_AWAITING_RESPONSE
66
61
  output_progress " waiting for a response from the server."
67
- when PGconn::CONNECTION_AUTH_OK
62
+ when PG::CONNECTION_AUTH_OK
68
63
  output_progress " received authentication; waiting for backend start-up to finish."
69
- when PGconn::CONNECTION_SSL_STARTUP
64
+ when PG::CONNECTION_SSL_STARTUP
70
65
  output_progress " negotiating SSL encryption."
71
- when PGconn::CONNECTION_SETENV
66
+ when PG::CONNECTION_SETENV
72
67
  output_progress " negotiating environment-driven parameter settings."
73
68
  end
74
69
 
@@ -76,7 +71,7 @@ until poll_status == PGconn::PGRES_POLLING_OK ||
76
71
  poll_status = conn.connect_poll
77
72
  end
78
73
 
79
- abort "Connect failed: %s" % [ conn.error_message ] unless conn.status == PGconn::CONNECTION_OK
74
+ abort "Connect failed: %s" % [ conn.error_message ] unless conn.status == PG::CONNECTION_OK
80
75
 
81
76
  output_progress "Sending query"
82
77
  conn.send_query( "SELECT * FROM pg_stat_activity" )
@@ -6,7 +6,7 @@ require 'stringio'
6
6
  # Using COPY asynchronously
7
7
 
8
8
  $stderr.puts "Opening database connection ..."
9
- conn = PGconn.connect( :dbname => 'test' )
9
+ conn = PG.connect( :dbname => 'test' )
10
10
  conn.setnonblocking( true )
11
11
 
12
12
  socket = IO.for_fd( conn.socket )
@@ -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 = IO.for_fd( conn.socket )
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
+
@@ -4,7 +4,7 @@ require 'pg'
4
4
  require 'stringio'
5
5
 
6
6
  $stderr.puts "Opening database connection ..."
7
- conn = PGconn.connect( :dbname => 'test' )
7
+ conn = PG.connect( :dbname => 'test' )
8
8
 
9
9
  conn.exec( <<END_SQL )
10
10
  DROP TABLE IF EXISTS logs;
@@ -6,7 +6,7 @@ require 'stringio'
6
6
  # An example of how to stream data to your local host from the database as CSV.
7
7
 
8
8
  $stderr.puts "Opening database connection ..."
9
- conn = PGconn.connect( :dbname => 'test' )
9
+ conn = PG.connect( :dbname => 'test' )
10
10
 
11
11
  $stderr.puts "Running COPY command ..."
12
12
  buf = ''
@@ -6,7 +6,7 @@ require 'pg'
6
6
  # the cursor portion of testlibpq.c from src/test/examples.
7
7
 
8
8
  $stderr.puts "Opening database connection ..."
9
- conn = PGconn.connect( :dbname => 'test' )
9
+ conn = PG.connect( :dbname => 'test' )
10
10
 
11
11
  #
12
12
  conn.transaction do
@@ -5,7 +5,7 @@ require 'pg'
5
5
  SAMPLE_WRITE_DATA = 'some sample data'
6
6
  SAMPLE_EXPORT_NAME = 'lowrite.txt'
7
7
 
8
- conn = PGconn.connect( :dbname => 'test', :host => 'localhost', :port => 5432 )
8
+ conn = PG.connect( :dbname => 'test', :host => 'localhost', :port => 5432 )
9
9
  puts "dbname: " + conn.db + "\thost: " + conn.host + "\tuser: " + conn.user
10
10
 
11
11
  # Start a transaction, as all large object functions require one.
@@ -20,15 +20,15 @@ puts " imported as large object %d" % [ oid ]
20
20
 
21
21
  # Read back 50 bytes of the imported data
22
22
  puts "Read test:"
23
- fd = conn.lo_open( oid, PGconn::INV_READ|PGconn::INV_WRITE )
24
- conn.lo_lseek( fd, 0, PGconn::SEEK_SET )
23
+ fd = conn.lo_open( oid, PG::INV_READ|PG::INV_WRITE )
24
+ conn.lo_lseek( fd, 0, PG::SEEK_SET )
25
25
  buf = conn.lo_read( fd, 50 )
26
26
  puts " read: %p" % [ buf ]
27
27
  puts " read was ok!" if buf =~ /require 'pg'/
28
28
 
29
29
  # Append some test data onto the end of the object
30
30
  puts "Write test:"
31
- conn.lo_lseek( fd, 0, PGconn::SEEK_END )
31
+ conn.lo_lseek( fd, 0, PG::SEEK_END )
32
32
  buf = SAMPLE_WRITE_DATA.dup
33
33
  totalbytes = 0
34
34
  until buf.empty?
@@ -53,9 +53,9 @@ puts 'Testing read and delete from a new transaction:'
53
53
  puts ' starting a new transaction'
54
54
  conn.exec( 'BEGIN' )
55
55
 
56
- fd = conn.lo_open( oid, PGconn::INV_READ )
56
+ fd = conn.lo_open( oid, PG::INV_READ )
57
57
  puts ' reopened okay.'
58
- conn.lo_lseek( fd, 50, PGconn::SEEK_END )
58
+ conn.lo_lseek( fd, 50, PG::SEEK_END )
59
59
  buf = conn.lo_read( fd, 50 )
60
60
  puts ' read okay.' if buf == SAMPLE_WRITE_DATA
61
61
 
@@ -2,25 +2,6 @@
2
2
  #
3
3
  # Test script, demonstrating a non-poll notification for a table event.
4
4
  #
5
- # To use, create a table called 'test', and attach a NOTIFY trigger to it
6
- # like so:
7
- #
8
- # CREATE OR REPLACE FUNCTION notify_test()
9
- # RETURNS TRIGGER
10
- # LANGUAGE plpgsql
11
- # AS $$
12
- # BEGIN
13
- # NOTIFY woo;
14
- # RETURN NULL;
15
- # END
16
- # $$
17
- #
18
- # CREATE TRIGGER notify_trigger
19
- # AFTER UPDATE OR INSERT OR DELETE
20
- # ON test
21
- # FOR EACH STATEMENT
22
- # EXECUTE PROCEDURE notify_test()
23
- #
24
5
 
25
6
  BEGIN {
26
7
  require 'pathname'
@@ -31,13 +12,61 @@ BEGIN {
31
12
 
32
13
  require 'pg'
33
14
 
34
- conn = PGconn.connect( :dbname => 'test' )
15
+ TRIGGER_TABLE = %{
16
+ CREATE TABLE IF NOT EXISTS test ( message text );
17
+ }
18
+
19
+ TRIGGER_FUNCTION = %{
20
+ CREATE OR REPLACE FUNCTION notify_test()
21
+ RETURNS TRIGGER
22
+ LANGUAGE plpgsql
23
+ AS $$
24
+ BEGIN
25
+ NOTIFY woo;
26
+ RETURN NULL;
27
+ END
28
+ $$
29
+ }
30
+
31
+ DROP_TRIGGER = %{
32
+ DROP TRIGGER IF EXISTS notify_trigger ON test
33
+ }
34
+
35
+
36
+ TRIGGER = %{
37
+ CREATE TRIGGER notify_trigger
38
+ AFTER UPDATE OR INSERT OR DELETE
39
+ ON test
40
+ FOR EACH STATEMENT
41
+ EXECUTE PROCEDURE notify_test();
42
+ }
43
+
44
+ conn = PG.connect( :dbname => 'test' )
45
+
46
+ conn.exec( TRIGGER_TABLE )
47
+ conn.exec( TRIGGER_FUNCTION )
48
+ conn.exec( DROP_TRIGGER )
49
+ conn.exec( TRIGGER )
50
+
35
51
  conn.exec( 'LISTEN woo' ) # register interest in the 'woo' event
36
52
 
53
+ notifications = []
54
+
55
+ puts "Now switch to a different term and run:",
56
+ '',
57
+ %{ psql test -c "insert into test values ('A message.')"},
58
+ ''
59
+
37
60
  puts "Waiting up to 30 seconds for for an event!"
38
61
  conn.wait_for_notify( 30 ) do |notify, pid|
39
- puts "I got one from pid %d: %s" % [ pid, notify ]
62
+ notifications << [ pid, notify ]
63
+ end
64
+
65
+ if notifications.empty?
66
+ puts "Awww, I didn't see any events."
67
+ else
68
+ puts "I got one from pid %d: %s" % notifications.first
40
69
  end
41
70
 
42
- puts "Awww, I didn't see any events."
71
+
43
72