pg 0.11.0-x86-mingw32 → 0.12.0-x86-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/.gemtest +0 -0
  2. data/ChangeLog +1647 -462
  3. data/Contributors.rdoc +39 -0
  4. data/History.rdoc +61 -0
  5. data/Manifest.txt +43 -0
  6. data/README.OS_X.rdoc +68 -0
  7. data/README.ja.rdoc +7 -0
  8. data/{README → README.rdoc} +38 -18
  9. data/{README.windows → README.windows.rdoc} +23 -31
  10. data/Rakefile +104 -318
  11. data/Rakefile.cross +234 -0
  12. data/ext/compat.c +2 -2
  13. data/ext/extconf.rb +10 -2
  14. data/ext/pg.c +223 -43
  15. data/ext/vc/pg.sln +26 -0
  16. data/ext/vc/pg_18/pg.vcproj +216 -0
  17. data/ext/vc/pg_19/pg_19.vcproj +209 -0
  18. data/lib/1.8/pg_ext.so +0 -0
  19. data/lib/1.9/pg_ext.so +0 -0
  20. data/lib/pg.rb +5 -7
  21. data/misc/openssl-pg-segfault.rb +31 -0
  22. data/sample/async_api.rb +109 -0
  23. data/sample/async_copyto.rb +39 -0
  24. data/sample/copyfrom.rb +81 -0
  25. data/sample/copyto.rb +19 -0
  26. data/sample/cursor.rb +21 -0
  27. data/sample/losample.rb +69 -0
  28. data/sample/notify_wait.rb +43 -0
  29. data/sample/psql.rb +1181 -0
  30. data/sample/psqlHelp.rb +158 -0
  31. data/sample/test1.rb +60 -0
  32. data/sample/test2.rb +44 -0
  33. data/sample/test4.rb +71 -0
  34. data/sample/test_binary_values.rb +35 -0
  35. data/spec/lib/helpers.rb +6 -4
  36. data/spec/m17n_spec.rb +2 -2
  37. data/spec/pgconn_spec.rb +51 -6
  38. data/spec/pgresult_spec.rb +30 -4
  39. metadata +147 -86
  40. data.tar.gz.sig +0 -3
  41. data/Contributors +0 -32
  42. data/README.OS_X +0 -19
  43. data/README.ja +0 -183
  44. data/Rakefile.local +0 -312
  45. data/rake/191_compat.rb +0 -26
  46. data/rake/dependencies.rb +0 -76
  47. data/rake/documentation.rb +0 -123
  48. data/rake/helpers.rb +0 -502
  49. data/rake/hg.rb +0 -318
  50. data/rake/manual.rb +0 -787
  51. data/rake/packaging.rb +0 -129
  52. data/rake/publishing.rb +0 -341
  53. data/rake/style.rb +0 -62
  54. data/rake/svn.rb +0 -668
  55. data/rake/testing.rb +0 -152
  56. data/rake/verifytask.rb +0 -64
  57. metadata.gz.sig +0 -3
Binary file
Binary file
data/lib/pg.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  begin
4
4
  require 'pg_ext'
5
- rescue LoadError => err
5
+ rescue LoadError
6
6
  # If it's a Windows binary gem, try the <major>.<minor> subdirectory
7
7
  if RUBY_PLATFORM =~/(mswin|mingw)/i
8
8
  major_minor = RUBY_VERSION[ /^(\d+\.\d+)/ ] or
@@ -14,7 +14,8 @@ rescue LoadError => err
14
14
 
15
15
  end
16
16
 
17
- ### The PG connection class.
17
+ #--
18
+ # The PG connection class.
18
19
  class PGconn
19
20
 
20
21
  # The order the options are passed to the ::connect method.
@@ -22,16 +23,13 @@ class PGconn
22
23
 
23
24
 
24
25
  ### Quote the given +value+ for use in a connection-parameter string.
25
- ### @param [String] value the option value to be quoted.
26
- ### @return [String]
27
26
  def self::quote_connstr( value )
28
27
  return "'" + value.to_s.gsub( /[\\']/ ) {|m| '\\' + m } + "'"
29
28
  end
30
29
 
31
30
 
32
- ### Parse the connection +args+ into a connection-parameter string
33
- ### @param [Array<String>] args the connection parameters
34
- ### @return [String] a connection parameters string
31
+ ### Parse the connection +args+ into a connection-parameter string. See PGconn.new
32
+ ### for valid arguments.
35
33
  def self::parse_connect_args( *args )
36
34
  return '' if args.empty?
37
35
 
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ PGHOST = 'localhost'
4
+ PGDB = 'test'
5
+ #SOCKHOST = 'github.com'
6
+ SOCKHOST = 'it-trac.laika.com'
7
+
8
+ # Load pg first, so the libssl.so that libpq is linked against is loaded.
9
+ require 'pg'
10
+ $stderr.puts "connecting to postgres://#{PGHOST}/#{PGDB}"
11
+ conn = PGconn.connect( PGHOST, :dbname => PGDB )
12
+
13
+ # Now load OpenSSL, which might be linked against a different libssl.
14
+ require 'socket'
15
+ require 'openssl'
16
+ $stderr.puts "Connecting to #{SOCKHOST}"
17
+ sock = TCPSocket.open( SOCKHOST, 443 )
18
+ ctx = OpenSSL::SSL::SSLContext.new
19
+ sock = OpenSSL::SSL::SSLSocket.new( sock, ctx )
20
+ sock.sync_close = true
21
+
22
+ # The moment of truth...
23
+ $stderr.puts "Attempting to connect..."
24
+ begin
25
+ sock.connect
26
+ rescue Errno
27
+ $stderr.puts "Got an error connecting, but no segfault."
28
+ else
29
+ $stderr.puts "Nope, no segfault!"
30
+ end
31
+
@@ -0,0 +1,109 @@
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 PGconn#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
+ CONN_OPTS = {
12
+ :host => 'localhost',
13
+ :dbname => 'test',
14
+ :user => 'jrandom',
15
+ :password => 'banks!stealUR$',
16
+ }
17
+
18
+ # Print 'x' continuously to demonstrate that other threads aren't
19
+ # blocked while waiting for the connection, for the query to be sent,
20
+ # for results, etc. You might want to sleep inside the loop or
21
+ # comment this out entirely for cleaner output.
22
+ progress_thread = Thread.new { loop { print 'x' } }
23
+
24
+ # Output progress messages
25
+ def output_progress( msg )
26
+ puts "\n>>> #{msg}\n"
27
+ end
28
+
29
+ # Start the connection
30
+ output_progress "Starting connection..."
31
+ conn = PGconn.connect_start( CONN_OPTS ) or abort "Unable to create a new connection!"
32
+ abort "Connection failed: %s" % [ conn.error_message ] if
33
+ conn.status == PGconn::CONNECTION_BAD
34
+
35
+ # Now grab a reference to the underlying socket so we know when the
36
+ # connection is established
37
+ socket = IO.for_fd( conn.socket )
38
+
39
+ # Track the progress of the connection, waiting for the socket to become readable/writable
40
+ # 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
44
+
45
+ # If the socket needs to read, wait 'til it becomes readable to poll again
46
+ case poll_status
47
+ when PGconn::PGRES_POLLING_READING
48
+ output_progress " waiting for socket to become readable"
49
+ select( [socket], nil, nil, TIMEOUT ) or
50
+ raise "Asynchronous connection timed out!"
51
+
52
+ # ...and the same for when the socket needs to write
53
+ when PGconn::PGRES_POLLING_WRITING
54
+ output_progress " waiting for socket to become writable"
55
+ select( nil, [socket], nil, TIMEOUT ) or
56
+ raise "Asynchronous connection timed out!"
57
+ end
58
+
59
+ # Output a status message about the progress
60
+ case conn.status
61
+ when PGconn::CONNECTION_STARTED
62
+ output_progress " waiting for connection to be made."
63
+ when PGconn::CONNECTION_MADE
64
+ output_progress " connection OK; waiting to send."
65
+ when PGconn::CONNECTION_AWAITING_RESPONSE
66
+ output_progress " waiting for a response from the server."
67
+ when PGconn::CONNECTION_AUTH_OK
68
+ output_progress " received authentication; waiting for backend start-up to finish."
69
+ when PGconn::CONNECTION_SSL_STARTUP
70
+ output_progress " negotiating SSL encryption."
71
+ when PGconn::CONNECTION_SETENV
72
+ output_progress " negotiating environment-driven parameter settings."
73
+ end
74
+
75
+ # Check to see if it's finished or failed yet
76
+ poll_status = conn.connect_poll
77
+ end
78
+
79
+ abort "Connect failed: %s" % [ conn.error_message ] unless conn.status == PGconn::CONNECTION_OK
80
+
81
+ output_progress "Sending query"
82
+ conn.send_query( "SELECT * FROM pg_stat_activity" )
83
+
84
+ # Fetch results until there aren't any more
85
+ loop do
86
+ output_progress " waiting for a response"
87
+
88
+ # Buffer any incoming data on the socket until a full result is ready.
89
+ conn.consume_input
90
+ while conn.is_busy
91
+ select( [socket], nil, nil, TIMEOUT ) or
92
+ raise "Timeout waiting for query response."
93
+ conn.consume_input
94
+ end
95
+
96
+ # Fetch the next result. If there isn't one, the query is finished
97
+ result = conn.get_result or break
98
+
99
+ puts "\n\nQuery result:\n%p\n" % [ result.values ]
100
+ end
101
+
102
+ output_progress "Done."
103
+ conn.finish
104
+
105
+ if defined?( progress_thread )
106
+ progress_thread.kill
107
+ progress_thread.join
108
+ end
109
+
@@ -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 = PGconn.connect( :dbname => 'test' )
10
+ conn.setnonblocking( true )
11
+
12
+ socket = IO.for_fd( conn.socket )
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,81 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pg'
4
+ require 'stringio'
5
+
6
+ $stderr.puts "Opening database connection ..."
7
+ conn = PGconn.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
+
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pg'
4
+ require 'stringio'
5
+
6
+ # An example of how to stream data to your local host from the database as CSV.
7
+
8
+ $stderr.puts "Opening database connection ..."
9
+ conn = PGconn.connect( :dbname => 'test' )
10
+
11
+ $stderr.puts "Running COPY command ..."
12
+ buf = ''
13
+ conn.transaction do
14
+ conn.exec( "COPY logs TO STDOUT WITH csv" )
15
+ $stdout.puts( buf ) while buf = conn.get_copy_data
16
+ end
17
+
18
+ conn.finish
19
+
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pg'
4
+
5
+ # An example of how to use SQL cursors. This is mostly a straight port of
6
+ # the cursor portion of testlibpq.c from src/test/examples.
7
+
8
+ $stderr.puts "Opening database connection ..."
9
+ conn = PGconn.connect( :dbname => 'test' )
10
+
11
+ #
12
+ conn.transaction do
13
+ conn.exec( "DECLARE myportal CURSOR FOR select * from pg_database" )
14
+ res = conn.exec( "FETCH ALL IN myportal" )
15
+
16
+ puts res.fields.collect {|fname| "%-15s" % [fname] }.join( '' )
17
+ res.values.collect do |row|
18
+ puts row.collect {|col| "%-15s" % [col] }.join( '' )
19
+ end
20
+ end
21
+
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pg'
4
+
5
+ SAMPLE_WRITE_DATA = 'some sample data'
6
+ SAMPLE_EXPORT_NAME = 'lowrite.txt'
7
+
8
+ conn = PGconn.connect( :dbname => 'test', :host => 'localhost', :port => 5432 )
9
+ puts "dbname: " + conn.db + "\thost: " + conn.host + "\tuser: " + conn.user
10
+
11
+ # Start a transaction, as all large object functions require one.
12
+ puts "Beginning transaction"
13
+ conn.exec( 'BEGIN' )
14
+
15
+ # Test importing from a file
16
+ puts "Import test:"
17
+ puts " importing %s" % [ __FILE__ ]
18
+ oid = conn.lo_import( __FILE__ )
19
+ puts " imported as large object %d" % [ oid ]
20
+
21
+ # Read back 50 bytes of the imported data
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 )
25
+ buf = conn.lo_read( fd, 50 )
26
+ puts " read: %p" % [ buf ]
27
+ puts " read was ok!" if buf =~ /require 'pg'/
28
+
29
+ # Append some test data onto the end of the object
30
+ puts "Write test:"
31
+ conn.lo_lseek( fd, 0, PGconn::SEEK_END )
32
+ buf = SAMPLE_WRITE_DATA.dup
33
+ totalbytes = 0
34
+ until buf.empty?
35
+ bytes = conn.lo_write( fd, buf )
36
+ buf.slice!( 0, bytes )
37
+ totalbytes += bytes
38
+ end
39
+ puts " appended %d bytes" % [ totalbytes ]
40
+
41
+ # Now export it
42
+ puts "Export test:"
43
+ File.unlink( SAMPLE_EXPORT_NAME ) if File.exist?( SAMPLE_EXPORT_NAME )
44
+ conn.lo_export( oid, SAMPLE_EXPORT_NAME )
45
+ puts " success!" if File.exist?( SAMPLE_EXPORT_NAME )
46
+ puts " exported as %s (%d bytes)" % [ SAMPLE_EXPORT_NAME, File.size(SAMPLE_EXPORT_NAME) ]
47
+
48
+ conn.exec( 'COMMIT' )
49
+ puts "End of transaction."
50
+
51
+
52
+ puts 'Testing read and delete from a new transaction:'
53
+ puts ' starting a new transaction'
54
+ conn.exec( 'BEGIN' )
55
+
56
+ fd = conn.lo_open( oid, PGconn::INV_READ )
57
+ puts ' reopened okay.'
58
+ conn.lo_lseek( fd, 50, PGconn::SEEK_END )
59
+ buf = conn.lo_read( fd, 50 )
60
+ puts ' read okay.' if buf == SAMPLE_WRITE_DATA
61
+
62
+ puts 'Closing and unlinking:'
63
+ conn.lo_close( fd )
64
+ puts ' closed.'
65
+ conn.lo_unlink( oid )
66
+ puts ' unlinked.'
67
+ conn.exec( 'COMMIT' )
68
+ puts 'Done.'
69
+
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Test script, demonstrating a non-poll notification for a table event.
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
+
25
+ BEGIN {
26
+ require 'pathname'
27
+ basedir = Pathname.new( __FILE__ ).expand_path.dirname.parent
28
+ libdir = basedir + 'lib'
29
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
30
+ }
31
+
32
+ require 'pg'
33
+
34
+ conn = PGconn.connect( :dbname => 'test' )
35
+ conn.exec( 'LISTEN woo' ) # register interest in the 'woo' event
36
+
37
+ puts "Waiting up to 30 seconds for for an event!"
38
+ conn.wait_for_notify( 30 ) do |notify, pid|
39
+ puts "I got one from pid %d: %s" % [ pid, notify ]
40
+ end
41
+
42
+ puts "Awww, I didn't see any events."
43
+