class DB::Postgres::Native::Connection
Public Class Methods
# File lib/db/postgres/native/connection.rb, line 106 def self.connect(wrapper: IO, types: DEFAULT_TYPES, **options) # Postgres expects "dbname" as the key name: if database = options.delete(:database) options[:dbname] = database end # Postgres expects "user" as the key name: if username = options.delete(:username) options[:user] = username end keys = Strings.new(options.keys) values = Strings.new(options.values) pointer = Native.connect_start_params(keys.array, values.array, 0) Native.set_nonblocking(pointer, 1) io = wrapper.new(Native.socket(pointer), "r+") while status = Native.connect_poll(pointer) break if status == :ok || status == :failed # one of :wait_readable or :wait_writable io.send(status) end if status == :failed io.close error_message = Native.error_message(pointer) Native.finish(pointer) raise Error, "Could not connect: #{error_message}" end return self.new(pointer, io, types) end
# File lib/db/postgres/native/connection.rb, line 145 def initialize(address, io, types) super(address) @io = io @types = types end
Public Instance Methods
Close the connection.
# File lib/db/postgres/native/connection.rb, line 168 def close Native.finish(self) @io.close end
Silently discard any results that application didn't read.
# File lib/db/postgres/native/connection.rb, line 225 def discard_results while result = self.get_result status = Native.result_status(result) Native.clear(result) case status when :copy_in self.put_copy_end("Discard results") when :copy_out self.flush_copy_out end end return nil end
Return the last error message.
# File lib/db/postgres/native/connection.rb, line 158 def error_message Native.error_message(self) end
# File lib/db/postgres/native/connection.rb, line 186 def escape_identifier(value) value = value.to_s result = Native.escape_identifier(self, value, value.bytesize) string = result.read_string Native.free_memory(result) return string end
# File lib/db/postgres/native/connection.rb, line 174 def escape_literal(value) value = value.to_s result = Native.escape_literal(self, value, value.bytesize) string = result.read_string Native.free_memory(result) return string end
# File lib/db/postgres/native/connection.rb, line 208 def next_result(types: @types) if result = self.get_result status = Native.result_status(result) if status == :fatal_error message = Native.result_error_message(result) Native.clear(result) raise Error, message end return Result.new(self, types, result) end end
# File lib/db/postgres/native/connection.rb, line 202 def send_query(statement) check! Native.send_query(self, statement) flush end
# File lib/db/postgres/native/connection.rb, line 198 def single_row_mode! Native.set_single_row_mode(self) end
Return the underlying socket used for IO
.
# File lib/db/postgres/native/connection.rb, line 163 def socket Native.socket(self) end
Return the status of the connection.
# File lib/db/postgres/native/connection.rb, line 153 def status Native.status(self) end
Protected Instance Methods
# File lib/db/postgres/native/connection.rb, line 310 def check!(result) if result == 0 message = Native.error_message(self) raise Error, message end end
After sending any command or data on a nonblocking connection, call PQflush. If it returns 1, wait for the socket to become read- or write-ready. If it becomes write-ready, call PQflush again. If it becomes read-ready, call PQconsumeInput, then call PQflush again. Repeat until PQflush returns 0. (It is necessary to check for read-ready and drain the input with PQconsumeInput, because the server can block trying to send us data, e.g. NOTICE messages, and won't read our data until we read its.) Once PQflush returns 0, wait for the socket to be read-ready and then read the response as described above.
# File lib/db/postgres/native/connection.rb, line 297 def flush while true case Native.flush(self) when 1 @io.wait_any check! Native.consume_input(self) when 0 return end end end
# File lib/db/postgres/native/connection.rb, line 277 def flush_copy_out buffer = FFI::MemoryPointer.new(:pointer, 1) while true status = Native.get_copy_data(self, buffer, 1) if status == -2 message = Native.error_message(self) raise Error, message elsif status == -1 break elsif status == 0 @io.wait_readable else Native.free_memory(buffer.read_pointer) end end end
# File lib/db/postgres/native/connection.rb, line 243 def get_result while true check! Native.consume_input(self) while Native.is_busy(self) == 0 result = Native.get_result(self) # Did we finish reading all results? if result.null? return nil else return result end end @io.wait_readable end end
# File lib/db/postgres/native/connection.rb, line 262 def put_copy_end(message = nil) while true status = Native.put_copy_end(self, message) if status == -1 message = Native.error_message(self) raise Error, message elsif status == 0 @io.wait_writable else break end end end