Class: PG::Connection
- Inherits:
-
Object
- Object
- PG::Connection
- Defined in:
- lib/pg/connection.rb
Overview
The PostgreSQL connection class. The interface for this class is based on libpq, the C application programmer’s interface to PostgreSQL. Some familiarity with libpq is recommended, but not necessary.
For example, to send query to the database on the localhost:
require 'pg'
conn = PG::Connection.open(:dbname => 'test')
res = conn.exec_params('SELECT $1 AS a, $2 AS b, $3 AS c', [1, 2, nil])
# Equivalent to:
# res = conn.exec('SELECT 1 AS a, 2 AS b, NULL AS c')
See the PG::Result class for information on working with the results of a query.
Many methods of this class have three variants kind of:
-
#exec - the base method which is an alias to #async_exec . This is the method that should be used in general.
-
#async_exec - the async aware version of the method, implemented by libpq’s async API.
-
#sync_exec - the method version that is implemented by blocking function(s) of libpq.
Sync and async version of the method can be switched by Connection.async_api= , however it is not recommended to change the default.
Constant Summary collapse
- CONNECT_ARGUMENT_ORDER =
The order the options are passed to the ::connect method.
%w[host port options tty dbname user password]
- HOST_AND_PORT =
URI defined in RFC3986 This regexp is modified to allow host to specify multiple comma separated components captured as <hostports> and to disallow comma in hostnames. Taken from: github.com/ruby/ruby/blob/be04006c7d2f9aeb7e9d8d09d945b3a9c7850202/lib/uri/rfc3986_parser.rb#L6
/(?<hostport>(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[-\.!$&-+0-9;=A-Z_a-z~])+))?(?::(?<port>\d*))?)/- POSTGRESQL_URI =
/\A(?<URI>(?<scheme>[A-Za-z][+\-.0-9A-Za-z]*):(?<hier-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?<hostports>#{HOST_AND_PORT}(?:,\g<hostport>)*))(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g<segment>)*)?)|(?<path-rootless>\g<segment-nz>(?:\/\g<segment>)*)|(?<path-empty>))(?:\?(?<query>[^#]*))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/- REDIRECT_CLASS_METHODS =
{ :new => [:async_connect, :sync_connect], :connect => [:async_connect, :sync_connect], :open => [:async_connect, :sync_connect], :setdb => [:async_connect, :sync_connect], :setdblogin => [:async_connect, :sync_connect], :ping => [:async_ping, :sync_ping], }
- REDIRECT_SEND_METHODS =
These methods are affected by PQsetnonblocking
{ :isnonblocking => [:async_isnonblocking, :sync_isnonblocking], :nonblocking? => [:async_isnonblocking, :sync_isnonblocking], :put_copy_data => [:async_put_copy_data, :sync_put_copy_data], :put_copy_end => [:async_put_copy_end, :sync_put_copy_end], :flush => [:async_flush, :sync_flush], }
- REDIRECT_METHODS =
{ :exec => [:async_exec, :sync_exec], :query => [:async_exec, :sync_exec], :exec_params => [:async_exec_params, :sync_exec_params], :prepare => [:async_prepare, :sync_prepare], :exec_prepared => [:async_exec_prepared, :sync_exec_prepared], :describe_portal => [:async_describe_portal, :sync_describe_portal], :describe_prepared => [:async_describe_prepared, :sync_describe_prepared], :setnonblocking => [:async_setnonblocking, :sync_setnonblocking], :get_result => [:async_get_result, :sync_get_result], :get_last_result => [:async_get_last_result, :sync_get_last_result], :get_copy_data => [:async_get_copy_data, :sync_get_copy_data], :reset => [:async_reset, :sync_reset], :set_client_encoding => [:async_set_client_encoding, :sync_set_client_encoding], :client_encoding= => [:async_set_client_encoding, :sync_set_client_encoding], :cancel => [:async_cancel, :sync_cancel], }
Class Method Summary collapse
-
.async_api=(enable) ⇒ Object
Switch between sync and async libpq API.
- .async_send_api=(enable) ⇒ Object
-
.conndefaults_hash ⇒ Object
Return the Postgres connection defaults structure as a Hash keyed by option keyword (as a Symbol).
-
.connect_hash_to_string(hash) ⇒ Object
Convert Hash options to connection String.
-
.connect_string_to_hash(str) ⇒ Object
Decode a connection string to Hash options.
-
.new(*args, **kwargs) ⇒ Object
(also: async_connect, connect, open, setdb, setdblogin)
call-seq: PG::Connection.new -> conn PG::Connection.new(connection_hash) -> conn PG::Connection.new(connection_string) -> conn PG::Connection.new(host, port, options, tty, dbname, user, password) -> conn.
-
.parse_connect_args(*args) ⇒ Object
Parse the connection
argsinto a connection-parameter string. -
.ping(*args) ⇒ Object
(also: async_ping)
call-seq: PG::Connection.ping(connection_hash) -> Integer PG::Connection.ping(connection_string) -> Integer PG::Connection.ping(host, port, options, tty, dbname, login, password) -> Integer.
-
.quote_connstr(value) ⇒ Object
Quote a single
valuefor use in a connection-parameter string.
Instance Method Summary collapse
-
#cancel ⇒ Object
(also: #async_cancel)
call-seq: conn.cancel() -> String.
-
#conndefaults ⇒ Object
Returns an array of Hashes with connection defaults.
-
#conndefaults_hash ⇒ Object
Returns a Hash with connection defaults.
-
#conninfo_hash ⇒ Object
Return the Postgres connection info structure as a Hash keyed by option keyword (as a Symbol).
-
#copy_data(sql, coder = nil) ⇒ Object
call-seq: conn.copy_data( sql [, coder] ) {|sql_result| … } -> PG::Result.
-
#encrypt_password(password, username, algorithm = nil) ⇒ Object
(also: #async_encrypt_password)
call-seq: conn.encrypt_password( password, username, algorithm=nil ) -> String.
-
#get_copy_data(async = false, decoder = nil) ⇒ Object
(also: #async_get_copy_data)
call-seq: conn.get_copy_data( [ nonblock = false [, decoder = nil ]] ) -> Object.
-
#get_result ⇒ Object
(also: #async_get_result)
call-seq: conn.get_result() -> PG::Result conn.get_result() {|pg_result| block }.
-
#isnonblocking ⇒ Object
(also: #async_isnonblocking, #nonblocking?)
call-seq: conn.isnonblocking() -> Boolean.
-
#put_copy_data(buffer, encoder = nil) ⇒ Object
(also: #async_put_copy_data)
call-seq: conn.put_copy_data( buffer [, encoder] ) -> Boolean.
-
#put_copy_end(*args) ⇒ Object
(also: #async_put_copy_end)
call-seq: conn.put_copy_end( [ error_message ] ) -> Boolean.
-
#reset ⇒ Object
(also: #async_reset)
call-seq: conn.reset().
-
#setnonblocking(enabled) ⇒ Object
(also: #async_setnonblocking)
call-seq: conn.setnonblocking(Boolean) -> nil.
-
#ssl_attributes ⇒ Object
call-seq: conn.ssl_attributes -> Hash<String,String>.
-
#transaction ⇒ Object
call-seq: conn.transaction { |conn| … } -> result of the block.
Class Method Details
.async_api=(enable) ⇒ Object
Switch between sync and async libpq API.
PG::Connection.async_api = true
this is the default. It sets an alias from #exec to #async_exec, #reset to #async_reset and so on.
PG::Connection.async_api = false
sets an alias from #exec to #sync_exec, #reset to #sync_reset and so on.
pg-1.1.0+ defaults to libpq’s async API for query related blocking methods. pg-1.3.0+ defaults to libpq’s async API for all possibly blocking methods.
PLEASE NOTE: This method is not part of the public API and is for debug and development use only. Do not use this method in production code. Any issues with the default setting of async_api=true should be reported to the maintainers instead.
808 809 810 811 812 813 814 815 816 817 818 |
# File 'lib/pg/connection.rb', line 808 def async_api=(enable) self.async_send_api = enable REDIRECT_METHODS.each do |ali, (async, sync)| remove_method(ali) if method_defined?(ali) alias_method( ali, enable ? async : sync ) end REDIRECT_CLASS_METHODS.each do |ali, (async, sync)| singleton_class.remove_method(ali) if method_defined?(ali) singleton_class.alias_method(ali, enable ? async : sync ) end end |
.async_send_api=(enable) ⇒ Object
785 786 787 788 789 790 |
# File 'lib/pg/connection.rb', line 785 def async_send_api=(enable) REDIRECT_SEND_METHODS.each do |ali, (async, sync)| undef_method(ali) if method_defined?(ali) alias_method( ali, enable ? async : sync ) end end |
.conndefaults_hash ⇒ Object
Return the Postgres connection defaults structure as a Hash keyed by option keyword (as a Symbol).
See also #conndefaults
335 336 337 338 339 |
# File 'lib/pg/connection.rb', line 335 def self.conndefaults_hash return self.conndefaults.each_with_object({}) do |info, hash| hash[ info[:keyword].to_sym ] = info[:val] end end |
.connect_hash_to_string(hash) ⇒ Object
Convert Hash options to connection String
Values are properly quoted and escaped.
45 46 47 |
# File 'lib/pg/connection.rb', line 45 def self.connect_hash_to_string( hash ) hash.map { |k,v| "#{k}=#{quote_connstr(v)}" }.join( ' ' ) end |
.connect_string_to_hash(str) ⇒ Object
Decode a connection string to Hash options
Value are properly unquoted and unescaped.
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/pg/connection.rb', line 52 def self.connect_string_to_hash( str ) = {} key = nil value = String.new str.scan(/\G\s*(?>([^\s\\\']+)\s*=\s*|([^\s\\\']+)|'((?:[^\'\\]|\\.)*)'|(\\.?)|(\S))(\s|\z)?/m) do |k, word, sq, esc, garbage, sep| raise ArgumentError, "unterminated quoted string in connection info string: #{str.inspect}" if garbage if k key = k else value << (word || (sq || esc).gsub(/\\(.)/, '\\1')) end if sep raise ArgumentError, "missing = after #{value.inspect}" unless key [key.to_sym] = value key = nil value = String.new end end end |
.new(*args, **kwargs) ⇒ Object Also known as: async_connect, connect, open, setdb, setdblogin
call-seq:
PG::Connection.new -> conn
PG::Connection.new(connection_hash) -> conn
PG::Connection.new(connection_string) -> conn
PG::Connection.new(host, port, options, tty, dbname, user, password) -> conn
Create a connection to the specified server.
connection_hash must be a ruby Hash with connection parameters. See the list of valid parameters in the PostgreSQL documentation.
There are two accepted formats for connection_string: plain keyword = value strings and URIs. See the documentation of connection strings.
The positional parameter form has the same functionality except that the missing parameters will always take on default values. The parameters are:
host-
server hostname
port-
server port number
options-
backend options
tty-
(ignored in all versions of PostgreSQL)
dbname-
connecting database name
user-
login user name
password-
login password
Examples:
# Connect using all defaults
PG::Connection.new
# As a Hash
PG::Connection.new( dbname: 'test', port: 5432 )
# As a String
PG::Connection.new( "dbname=test port=5432" )
# As an Array
PG::Connection.new( nil, 5432, nil, nil, 'test', nil, nil )
# As an URI
PG::Connection.new( "postgresql://user:[email protected]:5432/testdb?sslmode=require" )
If the Ruby default internal encoding is set (i.e., Encoding.default_internal != nil), the connection will have its client_encoding set accordingly.
Raises a PG::Error if the connection fails.
701 702 703 704 705 706 707 708 |
# File 'lib/pg/connection.rb', line 701 def new(*args, **kwargs) conn = self.connect_start(*args, **kwargs ) or raise(PG::Error, "Unable to create a new connection") raise(PG::ConnectionBad, conn.) if conn.status == PG::CONNECTION_BAD conn.send(:async_connect_or_reset, :connect_poll) end |
.parse_connect_args(*args) ⇒ Object
Parse the connection args into a connection-parameter string. See PG::Connection.new for valid arguments.
It accepts:
-
an option String kind of “host=name port=5432”
-
an option Hash kind of “name”, port: 5432
-
URI string
-
URI object
-
positional arguments
The method adds the option “hostaddr” and “fallback_application_name” if they aren’t already set. The URI and the options string is passed through and “hostaddr” as well as “fallback_application_name” are added to the end.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/pg/connection.rb', line 93 def self::parse_connect_args( *args ) hash_arg = args.last.is_a?( Hash ) ? args.pop.transform_keys(&:to_sym) : {} option_string = "" iopts = {} if args.length == 1 case args.first when URI, POSTGRESQL_URI uri = args.first.to_s uri_match = POSTGRESQL_URI.match(uri) if uri_match['query'] iopts = URI.decode_www_form(uri_match['query']).to_h.transform_keys(&:to_sym) end # extract "host1,host2" from "host1:5432,host2:5432" iopts[:host] = uri_match['hostports'].split(',', -1).map do |hostport| hostmatch = /\A#{HOST_AND_PORT}\z/.match(hostport) hostmatch['IPv6address'] || hostmatch['IPv4address'] || hostmatch['reg-name']&.gsub(/%(\h\h)/){ $1.hex.chr } end.join(',') oopts = {} when /=/ # Option string style option_string = args.first.to_s iopts = connect_string_to_hash(option_string) oopts = {} else # Positional parameters (only host given) iopts[CONNECT_ARGUMENT_ORDER.first.to_sym] = args.first oopts = iopts.dup end else # Positional parameters max = CONNECT_ARGUMENT_ORDER.length raise ArgumentError, "Extra positional parameter %d: %p" % [ max + 1, args[max] ] if args.length > max CONNECT_ARGUMENT_ORDER.zip( args ) do |(k,v)| iopts[ k.to_sym ] = v if v end iopts.delete(:tty) # ignore obsolete tty parameter oopts = iopts.dup end iopts.merge!( hash_arg ) oopts.merge!( hash_arg ) # Resolve DNS in Ruby to avoid blocking state while connecting, when it ... if (host=iopts[:host]) && !iopts[:hostaddr] hostaddrs = host.split(",", -1).map do |mhost| if !mhost.empty? && !mhost.start_with?("/") && # isn't UnixSocket # isn't a path on Windows (RUBY_PLATFORM !~ /mingw|mswin/ || mhost !~ /\A\w:[\/\\]/) if Fiber.respond_to?(:scheduler) && Fiber.scheduler && RUBY_VERSION < '3.1.' # Use a second thread to avoid blocking of the scheduler. # `IPSocket.getaddress` isn't fiber aware before ruby-3.1. Thread.new{ IPSocket.getaddress(mhost) rescue '' }.value else IPSocket.getaddress(mhost) rescue '' end end end oopts[:hostaddr] = hostaddrs.join(",") if hostaddrs.any? end if !iopts[:fallback_application_name] oopts[:fallback_application_name] = $0.sub( /^(.{30}).{4,}(.{30})$/ ){ $1+"..."+$2 } end if uri uri += uri_match['query'] ? "&" : "?" uri += URI.encode_www_form( oopts ) return uri else option_string += ' ' unless option_string.empty? && oopts.empty? return option_string + connect_hash_to_string(oopts) end end |
.ping(*args) ⇒ Object Also known as: async_ping
call-seq:
PG::Connection.ping(connection_hash) -> Integer
PG::Connection.ping(connection_string) -> Integer
PG::Connection.ping(host, port, options, tty, dbname, login, password) -> Integer
Check server status.
See PG::Connection.new for a description of the parameters.
Returns one of:
PQPING_OK-
server is accepting connections
PQPING_REJECT-
server is alive but rejecting connections
PQPING_NO_RESPONSE-
could not establish connection
PQPING_NO_ATTEMPT-
connection not attempted (bad params)
733 734 735 736 737 738 739 740 741 |
# File 'lib/pg/connection.rb', line 733 def ping(*args) if Fiber.respond_to?(:scheduler) && Fiber.scheduler # Run PQping in a second thread to avoid blocking of the scheduler. # Unfortunately there's no nonblocking way to run ping. Thread.new { sync_ping(*args) }.value else sync_ping(*args) end end |
.quote_connstr(value) ⇒ Object
Quote a single value for use in a connection-parameter string.
38 39 40 |
# File 'lib/pg/connection.rb', line 38 def self.quote_connstr( value ) return "'" + value.to_s.gsub( /[\\']/ ) {|m| '\\' + m } + "'" end |
Instance Method Details
#cancel ⇒ Object Also known as: async_cancel
call-seq:
conn.cancel() -> String
Requests cancellation of the command currently being processed.
Returns nil on success, or a string containing the error message if a failure occurs.
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 |
# File 'lib/pg/connection.rb', line 559 def cancel be_pid = backend_pid be_key = backend_key cancel_request = [0x10, 1234, 5678, be_pid, be_key].pack("NnnNN") if Fiber.respond_to?(:scheduler) && Fiber.scheduler && RUBY_PLATFORM =~ /mingw|mswin/ # Ruby's nonblocking IO is not really supported on Windows. # We work around by using threads and explicit calls to wait_readable/wait_writable. cl = Thread.new(socket_io.remote_address) { |ra| ra.connect }.value begin cl.write_nonblock(cancel_request) rescue IO::WaitReadable, Errno::EINTR cl.wait_writable retry end begin cl.read_nonblock(1) rescue IO::WaitReadable, Errno::EINTR cl.wait_readable retry rescue EOFError end elsif RUBY_ENGINE == 'truffleruby' begin cl = socket_io.remote_address.connect rescue NotImplementedError # Workaround for truffleruby < 21.3.0 cl2 = Socket.for_fd(socket_io.fileno) cl2.autoclose = false adr = cl2.remote_address if adr.ip? cl = TCPSocket.new(adr.ip_address, adr.ip_port) cl.autoclose = false else cl = UNIXSocket.new(adr.unix_path) cl.autoclose = false end end cl.write(cancel_request) cl.read(1) else cl = socket_io.remote_address.connect # Send CANCEL_REQUEST_CODE and parameters cl.write(cancel_request) # Wait for the postmaster to close the connection, which indicates that it's processed the request. cl.read(1) end cl.close nil rescue SystemCallError => err err.to_s end |
#conndefaults ⇒ Object
Returns an array of Hashes with connection defaults. See ::conndefaults for details.
327 328 329 |
# File 'lib/pg/connection.rb', line 327 def conndefaults return self.class.conndefaults end |
#conndefaults_hash ⇒ Object
Returns a Hash with connection defaults. See ::conndefaults_hash for details.
343 344 345 |
# File 'lib/pg/connection.rb', line 343 def conndefaults_hash return self.class.conndefaults_hash end |
#conninfo_hash ⇒ Object
Return the Postgres connection info structure as a Hash keyed by option keyword (as a Symbol).
See also #conninfo
351 352 353 354 355 |
# File 'lib/pg/connection.rb', line 351 def conninfo_hash return self.conninfo.each_with_object({}) do |info, hash| hash[ info[:keyword].to_sym ] = info[:val] end end |
#copy_data(sql, coder = nil) ⇒ Object
call-seq:
conn.copy_data( sql [, coder] ) {|sql_result| ... } -> PG::Result
Execute a copy process for transferring data to or from the server.
This issues the SQL COPY command via #exec. The response to this (if there is no error in the command) is a PG::Result object that is passed to the block, bearing a status code of PGRES_COPY_OUT or PGRES_COPY_IN (depending on the specified copy direction). The application should then use #put_copy_data or #get_copy_data to receive or transmit data rows and should return from the block when finished.
#copy_data returns another PG::Result object when the data transfer is complete. An exception is raised if some problem was encountered, so it isn’t required to make use of any of them. At this point further SQL commands can be issued via #exec. (It is not possible to execute other SQL commands using the same connection while the COPY operation is in progress.)
This method ensures, that the copy process is properly terminated in case of client side or server side failures. Therefore, in case of blocking mode of operation, #copy_data is preferred to raw calls of #put_copy_data, #get_copy_data and #put_copy_end.
coder can be a PG::Coder derivation (typically PG::TextEncoder::CopyRow or PG::TextDecoder::CopyRow). This enables encoding of data fields given to #put_copy_data or decoding of fields received by #get_copy_data.
Example with CSV input format:
conn.exec "create table my_table (a text,b text,c text,d text)"
conn.copy_data "COPY my_table FROM STDIN CSV" do
conn.put_copy_data "some,data,to,copy\n"
conn.put_copy_data "more,data,to,copy\n"
end
This creates my_table and inserts two CSV rows.
The same with text format encoder PG::TextEncoder::CopyRow and Array input:
enco = PG::TextEncoder::CopyRow.new
conn.copy_data "COPY my_table FROM STDIN", enco do
conn.put_copy_data ['some', 'data', 'to', 'copy']
conn.put_copy_data ['more', 'data', 'to', 'copy']
end
Example with CSV output format:
conn.copy_data "COPY my_table TO STDOUT CSV" do
while row=conn.get_copy_data
p row
end
end
This prints all rows of my_table to stdout:
"some,data,to,copy\n"
"more,data,to,copy\n"
The same with text format decoder PG::TextDecoder::CopyRow and Array output:
deco = PG::TextDecoder::CopyRow.new
conn.copy_data "COPY my_table TO STDOUT", deco do
while row=conn.get_copy_data
p row
end
end
This receives all rows of my_table as ruby array:
["some", "data", "to", "copy"]
["more", "data", "to", "copy"]
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
# File 'lib/pg/connection.rb', line 243 def copy_data( sql, coder=nil ) raise PG::NotInBlockingMode, "copy_data can not be used in nonblocking mode" if nonblocking? res = exec( sql ) case res.result_status when PGRES_COPY_IN begin if coder old_coder = self.encoder_for_put_copy_data self.encoder_for_put_copy_data = coder end yield res rescue Exception => err errmsg = "%s while copy data: %s" % [ err.class.name, err. ] put_copy_end( errmsg ) get_result raise else put_copy_end get_last_result ensure self.encoder_for_put_copy_data = old_coder if coder end when PGRES_COPY_OUT begin if coder old_coder = self.decoder_for_get_copy_data self.decoder_for_get_copy_data = coder end yield res rescue Exception => err cancel while get_copy_data end while get_result end raise else res = get_last_result if !res || res.result_status != PGRES_COMMAND_OK while get_copy_data end while get_result end raise PG::NotAllCopyDataRetrieved, "Not all COPY data retrieved" end res ensure self.decoder_for_get_copy_data = old_coder if coder end else raise ArgumentError, "SQL command is no COPY statement: #{sql}" end end |
#encrypt_password(password, username, algorithm = nil) ⇒ Object Also known as: async_encrypt_password
call-seq:
conn.encrypt_password( password, username, algorithm=nil ) -> String
This function is intended to be used by client applications that wish to send commands like ALTER USER joe PASSWORD 'pwd'. It is good practice not to send the original cleartext password in such a command, because it might be exposed in command logs, activity displays, and so on. Instead, use this function to convert the password to encrypted form before it is sent.
The password and username arguments are the cleartext password, and the SQL name of the user it is for. algorithm specifies the encryption algorithm to use to encrypt the password. Currently supported algorithms are md5 and scram-sha-256 (on and off are also accepted as aliases for md5, for compatibility with older server versions). Note that support for scram-sha-256 was introduced in PostgreSQL version 10, and will not work correctly with older server versions. If algorithm is omitted or nil, this function will query the server for the current value of the password_encryption setting. That can block, and will fail if the current transaction is aborted, or if the connection is busy executing another query. If you wish to use the default algorithm for the server but want to avoid blocking, query password_encryption yourself before calling #encrypt_password, and pass that value as the algorithm.
Return value is the encrypted password. The caller can assume the string doesn’t contain any special characters that would require escaping.
Available since PostgreSQL-10. See also corresponding libpq function.
533 534 535 536 |
# File 'lib/pg/connection.rb', line 533 def encrypt_password( password, username, algorithm=nil ) algorithm ||= exec("SHOW password_encryption").getvalue(0,0) sync_encrypt_password(password, username, algorithm) end |
#get_copy_data(async = false, decoder = nil) ⇒ Object Also known as: async_get_copy_data
call-seq:
conn.get_copy_data( [ nonblock = false [, decoder = nil ]] ) -> Object
Return one row of data, nil if the copy is done, or false if the call would block (only possible if nonblock is true).
If decoder is not set or nil, data is returned as binary string.
If decoder is set to a PG::Coder derivation, the return type depends on this decoder. PG::TextDecoder::CopyRow decodes the received data fields from one row of PostgreSQL’s COPY text format to an Array of Strings. Optionally the decoder can type cast the single fields to various Ruby types in one step, if PG::TextDecoder::CopyRow#type_map is set accordingly.
See also #copy_data.
412 413 414 415 416 417 418 419 420 421 422 |
# File 'lib/pg/connection.rb', line 412 def get_copy_data(async=false, decoder=nil) if async return sync_get_copy_data(async, decoder) else while (res=sync_get_copy_data(true, decoder)) == false socket_io.wait_readable consume_input end return res end end |
#get_result ⇒ Object Also known as: async_get_result
call-seq:
conn.get_result() -> PG::Result
conn.get_result() {|pg_result| block }
Blocks waiting for the next result from a call to #send_query (or another asynchronous command), and returns it. Returns nil if no more results are available.
Note: call this function repeatedly until it returns nil, or else you will not be able to issue further commands.
If the optional code block is given, it will be passed result as an argument, and the PG::Result object will automatically be cleared when the block terminates. In this instance, conn.exec returns the value of the block.
389 390 391 392 |
# File 'lib/pg/connection.rb', line 389 def get_result block sync_get_result end |
#isnonblocking ⇒ Object Also known as: async_isnonblocking, nonblocking?
call-seq:
conn.isnonblocking() -> Boolean
Returns the blocking status of the database connection. Returns true if the connection is set to nonblocking mode and false if blocking.
460 461 462 |
# File 'lib/pg/connection.rb', line 460 def isnonblocking false end |
#put_copy_data(buffer, encoder = nil) ⇒ Object Also known as: async_put_copy_data
call-seq:
conn.put_copy_data( buffer [, encoder] ) -> Boolean
Transmits buffer as copy data to the server. Returns true if the data was sent, false if it was not sent (false is only possible if the connection is in nonblocking mode, and this command would block).
encoder can be a PG::Coder derivation (typically PG::TextEncoder::CopyRow). This encodes the data fields given as buffer from an Array of Strings to PostgreSQL’s COPY text format inclusive proper escaping. Optionally the encoder can type cast the fields from various Ruby types in one step, if PG::TextEncoder::CopyRow#type_map is set accordingly.
Raises an exception if an error occurs.
See also #copy_data.
484 485 486 487 488 489 |
# File 'lib/pg/connection.rb', line 484 def put_copy_data(buffer, encoder=nil) until sync_put_copy_data(buffer, encoder) flush end flush end |
#put_copy_end(*args) ⇒ Object Also known as: async_put_copy_end
call-seq:
conn.put_copy_end( [ error_message ] ) -> Boolean
Sends end-of-data indication to the server.
error_message is an optional parameter, and if set, forces the COPY command to fail with the string error_message.
Returns true if the end-of-data was sent, #false* if it was not sent (false is only possible if the connection is in nonblocking mode, and this command would block).
504 505 506 507 508 509 |
# File 'lib/pg/connection.rb', line 504 def put_copy_end(*args) until sync_put_copy_end(*args) flush end flush end |
#reset ⇒ Object Also known as: async_reset
call-seq:
conn.reset()
Resets the backend connection. This method closes the backend connection and tries to re-connect.
545 546 547 548 |
# File 'lib/pg/connection.rb', line 545 def reset reset_start async_connect_or_reset(:reset_poll) end |
#setnonblocking(enabled) ⇒ Object Also known as: async_setnonblocking
call-seq:
conn.setnonblocking(Boolean) -> nil
Sets the nonblocking status of the connection. In the blocking state, calls to #send_query will block until the message is sent to the server, but will not wait for the query results. In the nonblocking state, calls to #send_query will return an error if the socket is not ready for writing. Note: This function does not affect #exec, because that function doesn’t return until the server has processed the query and returned the results.
Returns nil.
446 447 448 449 450 |
# File 'lib/pg/connection.rb', line 446 def setnonblocking(enabled) singleton_class.async_send_api = !enabled self.flush_data = !enabled sync_setnonblocking(true) end |
#ssl_attributes ⇒ Object
call-seq:
conn.ssl_attributes -> Hash<String,String>
Returns SSL-related information about the connection as key/value pairs
The available attributes varies depending on the SSL library being used, and the type of connection.
See also #ssl_attribute
368 369 370 371 372 |
# File 'lib/pg/connection.rb', line 368 def ssl_attributes ssl_attribute_names.each.with_object({}) do |n,h| h[n] = ssl_attribute(n) end end |
#transaction ⇒ Object
call-seq:
conn.transaction { |conn| ... } -> result of the block
Executes a BEGIN at the start of the block, and a COMMIT at the end of the block, or ROLLBACK if any exception occurs.
312 313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/pg/connection.rb', line 312 def transaction exec "BEGIN" res = yield(self) rescue Exception cancel if transaction_status == PG::PQTRANS_ACTIVE block exec "ROLLBACK" raise else exec "COMMIT" res end |