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 [1m[35mSQL (#{((Time.now - start) * 1000).round(1)}ms)[0m #{statement}[0m"
-
- 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, " [1m[36mRUBY (#{((Time.now - start) * 1000).round(1)}ms)[0m [ Rows: #{query_header[:rows]}, Bytesize: #{response.bytesize} bytes ][0m"
- 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