class DB::Postgres::Native::Connection

Public Class Methods

connect(wrapper: IO, types: DEFAULT_TYPES, **options) click to toggle source
# 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
new(address, io, types) click to toggle source
Calls superclass method
# 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() click to toggle source

Close the connection.

# File lib/db/postgres/native/connection.rb, line 168
def close
        Native.finish(self)
        
        @io.close
end
discard_results() click to toggle source

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
error_message() click to toggle source

Return the last error message.

# File lib/db/postgres/native/connection.rb, line 158
def error_message
        Native.error_message(self)
end
escape_identifier(value) click to toggle source
# 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
escape_literal(value) click to toggle source
# 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
next_result(types: @types) click to toggle source
# 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
send_query(statement) click to toggle source
# File lib/db/postgres/native/connection.rb, line 202
def send_query(statement)
        check! Native.send_query(self, statement)
        
        flush
end
single_row_mode!() click to toggle source
# File lib/db/postgres/native/connection.rb, line 198
def single_row_mode!
        Native.set_single_row_mode(self)
end
socket() click to toggle source

Return the underlying socket used for IO.

# File lib/db/postgres/native/connection.rb, line 163
def socket
        Native.socket(self)
end
status() click to toggle source

Return the status of the connection.

# File lib/db/postgres/native/connection.rb, line 153
def status
        Native.status(self)
end

Protected Instance Methods

check!(result) click to toggle source
# 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
flush() click to toggle source

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
flush_copy_out() click to toggle source
# 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
get_result() click to toggle source
# 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
put_copy_end(message = nil) click to toggle source
# 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