lib/monetdb/connection/query.rb in monetdb-0.2.3 vs lib/monetdb/connection/query.rb in monetdb-0.2.4

- old
+ new

@@ -1,31 +1,26 @@ +require "monetdb/connection/query/table" + module MonetDB class Connection module Query + def self.included(base) + base.send :include, Table + end + def query(statement) + check_connectivity! raise ConnectionError, "Not connected to server" unless connected? start = Time.now write "s#{statement};" response = read.split("\n") log :info, "\n SQL (#{((Time.now - start) * 1000).round(1)}ms) #{statement}" - - query_header, table_header = extract_headers!(response) - - if query_header[:type] == Q_TABLE - unless query_header[:rows] == response.size - raise QueryError, "Amount of fetched rows does not match header value (#{response.size} instead of #{query_header[:rows]})" - end - response = parse_rows(query_header, table_header, response.join("\n")) - else - response = true - end - - response + parse_response response end alias :select_rows :query def select_values(query) @@ -37,20 +32,30 @@ row[0] if row end private + def parse_response(response) + query_header, table_header = extract_headers!(response) + if query_header[:type] == Q_TABLE + parse_table_response query_header, table_header, response + else + true + end + end + def extract_headers!(response) [parse_query_header!(response), parse_scheme_header!(response)] end def parse_query_header!(response) header = response.shift raise QueryError, header if header[0].chr == MSG_ERROR unless header[0].chr == MSG_QUERY + ENV["MONETDB_QUERY_RESPONSE"] = ([header] + response).join("\n").inspect raise QueryError, "Expected an query header (#{MSG_QUERY}) but got (#{header[0].chr})" end to_query_header_hash header end @@ -83,70 +88,9 @@ column_names = header[1] column_types = header[2].collect(&:to_sym) column_lengths = header[3].collect(&:to_i) {:table_name => table_name, :column_names => column_names, :column_types => column_types, :column_lengths => column_lengths}.freeze - end - - def parse_rows(query_header, table_header, response) - start = Time.now - column_types = table_header[:column_types] - - response.slice(0..-3).split("\t]\n").collect do |row| - parsed, values = [], row.slice(1..-1).split(",\t") - values.each_with_index do |value, index| - parsed << parse_value(column_types[index], value.strip) - end - parsed - end.tap do - log :info, " RUBY (#{((Time.now - start) * 1000).round(1)}ms) [ Rows: #{query_header[:rows]}, Bytesize: #{response.bytesize} bytes ]" - end - end - - def parse_value(type, value) - unless value == "NULL" - case type - when :varchar, :text - parse_string_value value - when :int, :smallint, :bigint - parse_integer_value value - when :double, :float, :real - parse_float_value value - when :date - parse_date_value value - when :timestamp - parse_date_time_value value - when :tinyint - parse_boolean_value value - else - raise NotImplementedError, "Cannot parse value of type #{type.inspect}" - end - end - end - - def parse_string_value(value) - value.slice(1..-2).force_encoding("UTF-8") - end - - def parse_integer_value(value) - value.to_i - end - - def parse_float_value(value) - value.to_f - end - - def parse_date_value(value) - Date.new *value.split("-").collect(&:to_i) - end - - def parse_date_time_value(value) - date, time = value.split(" ") - Time.new *(date.split("-") + time.split(":")).collect(&:to_i) - end - - def parse_boolean_value(value) - value == "1" end end end end