pg 1.6.0.rc1-x86_64-linux
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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +4 -0
- data/BSDL +22 -0
- data/Contributors.rdoc +46 -0
- data/Gemfile +23 -0
- data/History.md +958 -0
- data/LICENSE +56 -0
- data/Manifest.txt +72 -0
- data/POSTGRES +23 -0
- data/README-OS_X.rdoc +68 -0
- data/README-Windows.rdoc +56 -0
- data/README.ja.md +300 -0
- data/README.md +286 -0
- data/Rakefile +161 -0
- data/certs/ged.pem +24 -0
- data/certs/kanis@comcard.de.pem +20 -0
- data/certs/larskanis-2022.pem +26 -0
- data/certs/larskanis-2023.pem +24 -0
- data/certs/larskanis-2024.pem +24 -0
- data/ext/errorcodes.def +1043 -0
- data/ext/errorcodes.rb +45 -0
- data/ext/errorcodes.txt +494 -0
- data/ext/extconf.rb +282 -0
- data/ext/gvl_wrappers.c +32 -0
- data/ext/gvl_wrappers.h +297 -0
- data/ext/pg.c +703 -0
- data/ext/pg.h +390 -0
- data/ext/pg_binary_decoder.c +460 -0
- data/ext/pg_binary_encoder.c +583 -0
- data/ext/pg_cancel_connection.c +360 -0
- data/ext/pg_coder.c +622 -0
- data/ext/pg_connection.c +4869 -0
- data/ext/pg_copy_coder.c +921 -0
- data/ext/pg_errors.c +95 -0
- data/ext/pg_record_coder.c +522 -0
- data/ext/pg_result.c +1764 -0
- data/ext/pg_text_decoder.c +1008 -0
- data/ext/pg_text_encoder.c +833 -0
- data/ext/pg_tuple.c +572 -0
- data/ext/pg_type_map.c +200 -0
- data/ext/pg_type_map_all_strings.c +130 -0
- data/ext/pg_type_map_by_class.c +271 -0
- data/ext/pg_type_map_by_column.c +355 -0
- data/ext/pg_type_map_by_mri_type.c +313 -0
- data/ext/pg_type_map_by_oid.c +388 -0
- data/ext/pg_type_map_in_ruby.c +333 -0
- data/ext/pg_util.c +149 -0
- data/ext/pg_util.h +65 -0
- data/ext/vc/pg.sln +26 -0
- data/ext/vc/pg_18/pg.vcproj +216 -0
- data/ext/vc/pg_19/pg_19.vcproj +209 -0
- data/lib/2.7/pg_ext.so +0 -0
- data/lib/3.0/pg_ext.so +0 -0
- data/lib/3.1/pg_ext.so +0 -0
- data/lib/3.2/pg_ext.so +0 -0
- data/lib/3.3/pg_ext.so +0 -0
- data/lib/pg/basic_type_map_based_on_result.rb +67 -0
- data/lib/pg/basic_type_map_for_queries.rb +202 -0
- data/lib/pg/basic_type_map_for_results.rb +104 -0
- data/lib/pg/basic_type_registry.rb +311 -0
- data/lib/pg/binary_decoder/date.rb +9 -0
- data/lib/pg/binary_decoder/timestamp.rb +26 -0
- data/lib/pg/binary_encoder/timestamp.rb +20 -0
- data/lib/pg/cancel_connection.rb +30 -0
- data/lib/pg/coder.rb +106 -0
- data/lib/pg/connection.rb +1027 -0
- data/lib/pg/exceptions.rb +31 -0
- data/lib/pg/result.rb +43 -0
- data/lib/pg/text_decoder/date.rb +21 -0
- data/lib/pg/text_decoder/inet.rb +9 -0
- data/lib/pg/text_decoder/json.rb +17 -0
- data/lib/pg/text_decoder/numeric.rb +9 -0
- data/lib/pg/text_decoder/timestamp.rb +30 -0
- data/lib/pg/text_encoder/date.rb +13 -0
- data/lib/pg/text_encoder/inet.rb +31 -0
- data/lib/pg/text_encoder/json.rb +17 -0
- data/lib/pg/text_encoder/numeric.rb +9 -0
- data/lib/pg/text_encoder/timestamp.rb +24 -0
- data/lib/pg/tuple.rb +30 -0
- data/lib/pg/type_map_by_column.rb +16 -0
- data/lib/pg/version.rb +4 -0
- data/lib/pg.rb +144 -0
- data/misc/openssl-pg-segfault.rb +31 -0
- data/misc/postgres/History.txt +9 -0
- data/misc/postgres/Manifest.txt +5 -0
- data/misc/postgres/README.txt +21 -0
- data/misc/postgres/Rakefile +21 -0
- data/misc/postgres/lib/postgres.rb +16 -0
- data/misc/ruby-pg/History.txt +9 -0
- data/misc/ruby-pg/Manifest.txt +5 -0
- data/misc/ruby-pg/README.txt +21 -0
- data/misc/ruby-pg/Rakefile +21 -0
- data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
- data/pg.gemspec +36 -0
- data/ports/x86_64-linux/lib/libpq-ruby-pg.so.1 +0 -0
- data/rakelib/task_extension.rb +46 -0
- data/sample/array_insert.rb +20 -0
- data/sample/async_api.rb +102 -0
- data/sample/async_copyto.rb +39 -0
- data/sample/async_mixed.rb +56 -0
- data/sample/check_conn.rb +21 -0
- data/sample/copydata.rb +71 -0
- data/sample/copyfrom.rb +81 -0
- data/sample/copyto.rb +19 -0
- data/sample/cursor.rb +21 -0
- data/sample/disk_usage_report.rb +177 -0
- data/sample/issue-119.rb +94 -0
- data/sample/losample.rb +69 -0
- data/sample/minimal-testcase.rb +17 -0
- data/sample/notify_wait.rb +72 -0
- data/sample/pg_statistics.rb +285 -0
- data/sample/replication_monitor.rb +222 -0
- data/sample/test_binary_values.rb +33 -0
- data/sample/wal_shipper.rb +434 -0
- data/sample/warehouse_partitions.rb +311 -0
- data.tar.gz.sig +0 -0
- metadata +252 -0
- metadata.gz.sig +0 -0
data/pg.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# -*- encoding: utf-8 -*-
|
3
|
+
|
4
|
+
require_relative 'lib/pg/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "pg"
|
8
|
+
spec.version = PG::VERSION
|
9
|
+
spec.authors = ["Michael Granger", "Lars Kanis"]
|
10
|
+
spec.email = ["ged@FaerieMUD.org", "lars@greiz-reinsdorf.de"]
|
11
|
+
|
12
|
+
spec.summary = "Pg is the Ruby interface to the PostgreSQL RDBMS"
|
13
|
+
spec.description = "Pg is the Ruby interface to the PostgreSQL RDBMS. It works with PostgreSQL 10 and later."
|
14
|
+
spec.homepage = "https://github.com/ged/ruby-pg"
|
15
|
+
spec.license = "BSD-2-Clause"
|
16
|
+
spec.required_ruby_version = ">= 2.7"
|
17
|
+
|
18
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
19
|
+
spec.metadata["source_code_uri"] = "https://github.com/ged/ruby-pg"
|
20
|
+
spec.metadata["changelog_uri"] = "https://github.com/ged/ruby-pg/blob/master/History.md"
|
21
|
+
spec.metadata["documentation_uri"] = "http://deveiate.org/code/pg"
|
22
|
+
|
23
|
+
# Specify which files should be added to the gem when it is released.
|
24
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
26
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
27
|
+
f.match(%r{\A(?:test|spec|features|translation|\.)})
|
28
|
+
end
|
29
|
+
end
|
30
|
+
spec.extensions = ["ext/extconf.rb"]
|
31
|
+
spec.require_paths = ["lib"]
|
32
|
+
spec.cert_chain = ["certs/ged.pem"]
|
33
|
+
spec.rdoc_options = ["--main", "README.md",
|
34
|
+
"--title", "PG: The Ruby PostgreSQL Driver"]
|
35
|
+
spec.extra_rdoc_files = `git ls-files -z *.rdoc *.md lib/*.rb lib/*/*.rb lib/*/*/*.rb ext/*.c ext/*.h`.split("\x0")
|
36
|
+
end
|
Binary file
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# This source code is borrowed from:
|
2
|
+
# https://github.com/oneclick/rubyinstaller2/blob/b3dcbf69f131e44c78ea3a1c5e0041c223f266ce/lib/ruby_installer/build/utils.rb#L104-L144
|
3
|
+
|
4
|
+
module TaskExtension
|
5
|
+
# Extend rake's file task to be defined only once and to check the expected file is indeed generated
|
6
|
+
#
|
7
|
+
# The same as #task, but for #file.
|
8
|
+
# In addition this file task raises an error, if the file that is expected to be generated is not present after the block was executed.
|
9
|
+
def file(name, *args, &block)
|
10
|
+
task_once(name, block) do
|
11
|
+
super(name, *args) do |ta|
|
12
|
+
block&.call(ta).tap do
|
13
|
+
raise "file #{ta.name} is missing after task executed" unless File.exist?(ta.name)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Extend rake's task definition to be defined only once, even if called several times
|
20
|
+
#
|
21
|
+
# This allows to define common tasks next to specific tasks.
|
22
|
+
# It is expected that any variation of the task's block is reflected in the task name or namespace.
|
23
|
+
# If the task name is identical, the task block is executed only once, even if the file task definition is executed twice.
|
24
|
+
def task(name, *args, &block)
|
25
|
+
task_once(name, block) do
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private def task_once(name, block)
|
31
|
+
name = name.keys.first if name.is_a?(Hash)
|
32
|
+
if block &&
|
33
|
+
Rake::Task.task_defined?(name) &&
|
34
|
+
Rake::Task[name].instance_variable_get('@task_block_location') == block.source_location
|
35
|
+
# task is already defined for this target and the same block
|
36
|
+
# So skip double definition of the same action
|
37
|
+
Rake::Task[name]
|
38
|
+
elsif block
|
39
|
+
yield.tap do
|
40
|
+
Rake::Task[name].instance_variable_set('@task_block_location', block.source_location)
|
41
|
+
end
|
42
|
+
else
|
43
|
+
yield
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- 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
|
+
|
data/sample/async_api.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# -*- 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
|
+
# Track the progress of the connection, waiting for the socket to become readable/writable
|
31
|
+
# before polling it
|
32
|
+
poll_status = PG::PGRES_POLLING_WRITING
|
33
|
+
until poll_status == PG::PGRES_POLLING_OK ||
|
34
|
+
poll_status == PG::PGRES_POLLING_FAILED
|
35
|
+
|
36
|
+
# If the socket needs to read, wait 'til it becomes readable to poll again
|
37
|
+
case poll_status
|
38
|
+
when PG::PGRES_POLLING_READING
|
39
|
+
output_progress " waiting for socket to become readable"
|
40
|
+
select( [conn.socket_io], nil, nil, TIMEOUT ) or
|
41
|
+
raise "Asynchronous connection timed out!"
|
42
|
+
|
43
|
+
# ...and the same for when the socket needs to write
|
44
|
+
when PG::PGRES_POLLING_WRITING
|
45
|
+
output_progress " waiting for socket to become writable"
|
46
|
+
select( nil, [conn.socket_io], nil, TIMEOUT ) or
|
47
|
+
raise "Asynchronous connection timed out!"
|
48
|
+
end
|
49
|
+
|
50
|
+
# Output a status message about the progress
|
51
|
+
case conn.status
|
52
|
+
when PG::CONNECTION_STARTED
|
53
|
+
output_progress " waiting for connection to be made."
|
54
|
+
when PG::CONNECTION_MADE
|
55
|
+
output_progress " connection OK; waiting to send."
|
56
|
+
when PG::CONNECTION_AWAITING_RESPONSE
|
57
|
+
output_progress " waiting for a response from the server."
|
58
|
+
when PG::CONNECTION_AUTH_OK
|
59
|
+
output_progress " received authentication; waiting for backend start-up to finish."
|
60
|
+
when PG::CONNECTION_SSL_STARTUP
|
61
|
+
output_progress " negotiating SSL encryption."
|
62
|
+
when PG::CONNECTION_SETENV
|
63
|
+
output_progress " negotiating environment-driven parameter settings."
|
64
|
+
when PG::CONNECTION_NEEDED
|
65
|
+
output_progress " internal state: connect() needed."
|
66
|
+
end
|
67
|
+
|
68
|
+
# Check to see if it's finished or failed yet
|
69
|
+
poll_status = conn.connect_poll
|
70
|
+
end
|
71
|
+
|
72
|
+
abort "Connect failed: %s" % [ conn.error_message ] unless conn.status == PG::CONNECTION_OK
|
73
|
+
|
74
|
+
output_progress "Sending query"
|
75
|
+
conn.send_query( "SELECT * FROM pg_stat_activity" )
|
76
|
+
|
77
|
+
# Fetch results until there aren't any more
|
78
|
+
loop do
|
79
|
+
output_progress " waiting for a response"
|
80
|
+
|
81
|
+
# Buffer any incoming data on the socket until a full result is ready.
|
82
|
+
conn.consume_input
|
83
|
+
while conn.is_busy
|
84
|
+
select( [conn.socket_io], nil, nil, TIMEOUT ) or
|
85
|
+
raise "Timeout waiting for query response."
|
86
|
+
conn.consume_input
|
87
|
+
end
|
88
|
+
|
89
|
+
# Fetch the next result. If there isn't one, the query is finished
|
90
|
+
result = conn.get_result or break
|
91
|
+
|
92
|
+
puts "\n\nQuery result:\n%p\n" % [ result.values ]
|
93
|
+
end
|
94
|
+
|
95
|
+
output_progress "Done."
|
96
|
+
conn.finish
|
97
|
+
|
98
|
+
if defined?( progress_thread )
|
99
|
+
progress_thread.kill
|
100
|
+
progress_thread.join
|
101
|
+
end
|
102
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- 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
|
+
# -*- 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
|
+
# -*- 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
|
+
|
data/sample/copydata.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# -*- 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
|
+
csv_io = 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
|
+
res = conn.copy_data( "COPY logs FROM STDIN WITH csv" ) do
|
58
|
+
$stderr.print "Sending lines... "
|
59
|
+
csv_io.each_line.with_index do |buf, i|
|
60
|
+
$stderr.print "#{i + 1} "
|
61
|
+
conn.put_copy_data( buf )
|
62
|
+
end
|
63
|
+
$stderr.puts "done."
|
64
|
+
end
|
65
|
+
$stderr.puts "Result of COPY is: %s" % [ res.res_status(res.result_status) ]
|
66
|
+
$stderr.puts " tuples copied: %p" % [ res.cmd_tuples ]
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
conn.finish
|
71
|
+
|
data/sample/copyfrom.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# -*- 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
|
+
|
data/sample/copyto.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- 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 = PG.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
|
+
|
data/sample/cursor.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- 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 = PG.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
|
+
|