class Vertica::Query

The Query class handles the state of the connection while a SQL query is being executed. The connection should call {#run} and it will block until the query has been handled by the connection, after which control will be given back to the {Connection} instance.

@note This class is for internal use only, you should never interact with this class directly.

@see Vertica::Connection#query @see Vertica::Connection#copy

Public Class Methods

new(connection, sql, row_handler: nil, copy_handler: nil) click to toggle source

Instantiates a new query @param connection [Vertica::Connection] The connection to use for the query @param sql [String] The SQL statement to execute. @param row_handler [Proc, nil] Callback that will be called for every row that is returned.

If no handler is provided, all rows will be buffered so a {Vertica::Result} can be returned.

@param copy_handler [Proc, nil] Callback that will be called when the connection is ready

to receive data for a `COPY ... FROM STDIN` statement.
# File lib/vertica/query.rb, line 19
def initialize(connection, sql, row_handler: nil, copy_handler: nil)
  @connection, @sql = connection, sql
  @buffer = row_handler.nil? && copy_handler.nil? ? [] : nil
  @row_handler = row_handler || lambda { |row| buffer_row(row) }
  @copy_handler = copy_handler
  @row_description, @error = nil, nil
end

Public Instance Methods

inspect() click to toggle source

@return [String] Returns a user-consumable string representation of this query instance.

# File lib/vertica/query.rb, line 46
def inspect
  "#<Vertica::Query:#{object_id} sql=#{@sql.inspect}>"
end
run() click to toggle source

Sends the query to the server, and processes the results. @return [String] For an unbuffered query, the type of SQL command will be return as a string

(e.g. `"SELECT"` or `"COPY"`).

@return [Vertica::Result] For a buffered query, this method will return a {Vertica::Result} instance @raise [Vertica::Error::ConnectionError] if the connection between client and

server fails.

@raise [Vertica::Error::QueryError] if the server cannot evaluate the query.

# File lib/vertica/query.rb, line 34
def run
  @connection.write_message(Vertica::Protocol::Query.new(@sql))

  begin
    process_message(message = @connection.read_message)
  end until message.kind_of?(Vertica::Protocol::ReadyForQuery)

  raise @error unless @error.nil?
  return @result
end

Private Instance Methods

buffer_row(row) click to toggle source
# File lib/vertica/query.rb, line 105
def buffer_row(row)
  @buffer << row
end
buffer_rows?() click to toggle source
# File lib/vertica/query.rb, line 52
def buffer_rows?
  @buffer.is_a?(Array)
end
handle_command_complete(message) click to toggle source
# File lib/vertica/query.rb, line 83
def handle_command_complete(message)
  if buffer_rows?
    @result = Vertica::Result.new(row_description: @row_description, rows: @buffer, tag: message.tag)
    @row_description, @buffer = nil, nil
  else
    @result = message.tag
  end
end
handle_copy_in_response(_message) click to toggle source
# File lib/vertica/query.rb, line 92
def handle_copy_in_response(_message)
  if @copy_handler.nil?
    @connection.write_message(Vertica::Protocol::CopyFail.new('no handler provided'))
  else
    begin
      @copy_handler.call(CopyFromStdinWriter.new(@connection))
      @connection.write_message(Vertica::Protocol::CopyDone.new)
    rescue => e
      @connection.write_message(Vertica::Protocol::CopyFail.new(e.message))
    end
  end
end
handle_data_row(message) click to toggle source
# File lib/vertica/query.rb, line 79
def handle_data_row(message)
  @row_handler.call(@row_description.build_row(message))
end
handle_row_description(message) click to toggle source
# File lib/vertica/query.rb, line 75
def handle_row_description(message)
  @row_description = Vertica::RowDescription.build(message)
end
process_message(message) click to toggle source
# File lib/vertica/query.rb, line 56
def process_message(message)
  case message
  when Vertica::Protocol::ErrorResponse
    @error = Vertica::Error::QueryError.from_error_response(message, @sql)
  when Vertica::Protocol::EmptyQueryResponse
    @error = Vertica::Error::EmptyQueryError.new("A SQL string was expected, but the given string was blank or only contained SQL comments.")
  when Vertica::Protocol::CopyInResponse
    handle_copy_in_response(message)
  when Vertica::Protocol::RowDescription
    handle_row_description(message)
  when Vertica::Protocol::DataRow
    handle_data_row(message)
  when Vertica::Protocol::CommandComplete
    handle_command_complete(message)
  else
    @connection.process_message(message)
  end
end