vertica 0.8.1 → 0.9.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/Gemfile +2 -0
  2. data/Gemfile.lock +23 -0
  3. data/Rakefile +12 -9
  4. data/VERSION +1 -1
  5. data/lib/vertica.rb +2 -7
  6. data/lib/vertica/connection.rb +47 -57
  7. data/lib/vertica/messages/backend_messages/authentication.rb +6 -7
  8. data/lib/vertica/messages/backend_messages/backend_key_data.rb +4 -7
  9. data/lib/vertica/messages/backend_messages/bind_complete.rb +1 -1
  10. data/lib/vertica/messages/backend_messages/close_complete.rb +1 -1
  11. data/lib/vertica/messages/backend_messages/command_complete.rb +13 -7
  12. data/lib/vertica/messages/backend_messages/data_row.rb +10 -10
  13. data/lib/vertica/messages/backend_messages/empty_query_response.rb +1 -1
  14. data/lib/vertica/messages/backend_messages/error_response.rb +2 -30
  15. data/lib/vertica/messages/backend_messages/no_data.rb +1 -1
  16. data/lib/vertica/messages/backend_messages/notice_response.rb +33 -7
  17. data/lib/vertica/messages/backend_messages/notification_response.rb +4 -9
  18. data/lib/vertica/messages/backend_messages/parameter_description.rb +5 -9
  19. data/lib/vertica/messages/backend_messages/parameter_status.rb +4 -8
  20. data/lib/vertica/messages/backend_messages/parse_complete.rb +1 -1
  21. data/lib/vertica/messages/backend_messages/portal_suspended.rb +1 -1
  22. data/lib/vertica/messages/backend_messages/ready_for_query.rb +3 -4
  23. data/lib/vertica/messages/backend_messages/row_description.rb +15 -15
  24. data/lib/vertica/messages/backend_messages/unknown.rb +2 -2
  25. data/lib/vertica/messages/frontend_messages/bind.rb +3 -12
  26. data/lib/vertica/messages/frontend_messages/cancel_request.rb +1 -5
  27. data/lib/vertica/messages/frontend_messages/close.rb +5 -9
  28. data/lib/vertica/messages/frontend_messages/describe.rb +5 -9
  29. data/lib/vertica/messages/frontend_messages/execute.rb +2 -6
  30. data/lib/vertica/messages/frontend_messages/flush.rb +1 -1
  31. data/lib/vertica/messages/frontend_messages/parse.rb +2 -8
  32. data/lib/vertica/messages/frontend_messages/password.rb +5 -6
  33. data/lib/vertica/messages/frontend_messages/query.rb +2 -3
  34. data/lib/vertica/messages/frontend_messages/ssl_request.rb +1 -2
  35. data/lib/vertica/messages/frontend_messages/startup.rb +6 -8
  36. data/lib/vertica/messages/frontend_messages/sync.rb +1 -1
  37. data/lib/vertica/messages/frontend_messages/terminate.rb +1 -1
  38. data/lib/vertica/messages/message.rb +9 -18
  39. data/lib/vertica/result.rb +8 -1
  40. data/test/functional/connection_test.rb +73 -0
  41. data/test/functional/query_test.rb +150 -0
  42. data/test/test_helper.rb +7 -13
  43. data/test/unit/backend_message_test.rb +106 -0
  44. metadata +72 -20
  45. data/lib/vertica/bit_helper.rb +0 -34
  46. data/lib/vertica/core_ext/numeric.rb +0 -13
  47. data/lib/vertica/core_ext/string.rb +0 -22
  48. data/lib/vertica/notice.rb +0 -11
  49. data/lib/vertica/vertica_socket.rb +0 -19
  50. data/test/connection_test.rb +0 -191
@@ -1,7 +1,7 @@
1
1
  module Vertica
2
2
  module Messages
3
3
  class NoData < BackendMessage
4
- message_id ?n
4
+ message_id 'n'
5
5
  end
6
6
  end
7
7
  end
@@ -1,16 +1,42 @@
1
1
  module Vertica
2
2
  module Messages
3
3
  class NoticeResponse < BackendMessage
4
- message_id ?N
4
+ message_id 'N'
5
+
6
+ FIELDS_DEFINITIONS = [
7
+ { :type => 'q', :name => "Internal Query" },
8
+ { :type => 'S', :name => "Severity" },
9
+ { :type => 'M', :name => "Message" },
10
+ { :type => 'C', :name => "Sqlstate" },
11
+ { :type => 'D', :name => "Detail" },
12
+ { :type => 'H', :name => "Hint" },
13
+ { :type => 'P', :name => "Position" },
14
+ { :type => 'W', :name => "Where" },
15
+ { :type => 'p', :name => "Internal Position" },
16
+ { :type => 'R', :name => "Routine" },
17
+ { :type => 'F', :name => "File" },
18
+ { :type => 'L', :name => "Line" }
19
+ ]
20
+
21
+ FIELDS = Hash[*FIELDS_DEFINITIONS.map { |f| [f[:type], f[:name]] }.flatten]
22
+
23
+ attr_reader :values
5
24
 
6
- attr_reader :notices
7
-
8
- def initialize(stream, size)
9
- super
10
- @notices, type = [], nil
11
- @notices << [type, stream.read_cstring] while (type = stream.read_byte) != 0
25
+ def initialize(data)
26
+ @values, pos = {}, 0
27
+ while pos < data.size - 1
28
+ key, value = data.unpack("@#{pos}aZ*")
29
+ @values[FIELDS[key]] = value
30
+ pos += value.size + 2
31
+ end
12
32
  end
13
33
 
34
+ def error_message
35
+ ordered_values = FIELDS_DEFINITIONS.map do |field|
36
+ "#{field[:name]}: #{@values[field[:name]]}" if @values[field[:name]]
37
+ end
38
+ ordered_values.compact.join(', ')
39
+ end
14
40
  end
15
41
  end
16
42
  end
@@ -1,17 +1,12 @@
1
1
  module Vertica
2
2
  module Messages
3
3
  class NotificationResponse < BackendMessage
4
- message_id ?A
4
+ message_id 'A'
5
5
 
6
- attr_reader :pid
7
- attr_reader :condition
8
- attr_reader :addition_info
6
+ attr_reader :pid, :condition, :addition_info
9
7
 
10
- def initialize(stream, size)
11
- super
12
- @pid = stream.read_network_int32
13
- @condition = stream.read_cstring
14
- @addition_info = stream.read_cstring
8
+ def initialize(data)
9
+ @pid, @condition, @addition_info = data.unpack('NZ*Z*')
15
10
  end
16
11
  end
17
12
  end
@@ -1,18 +1,14 @@
1
1
  module Vertica
2
2
  module Messages
3
3
  class ParameterDescription < BackendMessage
4
- message_id ?t
4
+ message_id 't'
5
5
 
6
- attr_reader :parameter_count
7
6
  attr_reader :parameter_types
8
7
 
9
- def initialize(stream, size)
10
- super
11
- @parameter_types = []
12
- @parameter_count = stream.read_network_int16
13
- @parameter_count.times do
14
- @parameter_types << Vertica::Column::DATA_TYPES[stream.read_network_int32]
15
- end
8
+ def initialize(data)
9
+ parameter_count = data.unpack('n').first
10
+ parameter_type_ids = data.unpack("@2N#{parameter_count}")
11
+ @parameter_types = parameter_type_ids.map { |id| Vertica::Column::DATA_TYPES[id] }
16
12
  end
17
13
  end
18
14
  end
@@ -1,17 +1,13 @@
1
1
  module Vertica
2
2
  module Messages
3
3
  class ParameterStatus < BackendMessage
4
- message_id ?S
4
+ message_id 'S'
5
5
 
6
- attr_reader :name
7
- attr_reader :value
6
+ attr_reader :name, :value
8
7
 
9
- def initialize(stream, size)
10
- super
11
- @name = stream.read_cstring
12
- @value = stream.read_cstring
8
+ def initialize(data)
9
+ @name, @value = data.unpack('Z*Z*')
13
10
  end
14
-
15
11
  end
16
12
  end
17
13
  end
@@ -1,7 +1,7 @@
1
1
  module Vertica
2
2
  module Messages
3
3
  class ParseComplete < BackendMessage
4
- message_id ?1
4
+ message_id '1'
5
5
  end
6
6
  end
7
7
  end
@@ -1,7 +1,7 @@
1
1
  module Vertica
2
2
  module Messages
3
3
  class PortalSuspended < BackendMessage
4
- message_id ?s
4
+ message_id 's'
5
5
  end
6
6
  end
7
7
  end
@@ -1,13 +1,12 @@
1
1
  module Vertica
2
2
  module Messages
3
3
  class ReadyForQuery < BackendMessage
4
- message_id ?Z
4
+ message_id 'Z'
5
5
 
6
6
  attr_reader :transaction_status
7
7
 
8
- def initialize(stream, size)
9
- super
10
- @transaction_status = stream.read_byte
8
+ def initialize(data)
9
+ @transaction_status = data.unpack('a').first
11
10
  end
12
11
  end
13
12
  end
@@ -1,27 +1,27 @@
1
1
  module Vertica
2
2
  module Messages
3
3
  class RowDescription < BackendMessage
4
- message_id ?T
4
+ message_id 'T'
5
5
 
6
- attr_reader :field_count
7
6
  attr_reader :fields
8
7
 
9
- def initialize(stream, size)
10
- super
11
-
8
+ def initialize(data)
12
9
  @fields = []
13
-
14
- @field_count = stream.read_network_int16
15
- @field_count.times do |field_index|
10
+ field_count = data.unpack('n').first
11
+ pos = 2
12
+ field_count.times do |field_index|
13
+ field_info = data.unpack("@#{pos}Z*NnNnNn")
16
14
  @fields << {
17
- :name => stream.read_cstring,
18
- :table_oid => stream.read_network_int32,
19
- :attribute_number => stream.read_network_int16,
20
- :data_type_oid => stream.read_network_int32,
21
- :data_type_size => stream.read_network_int16,
22
- :type_modifier => stream.read_network_int32,
23
- :format_code => stream.read_network_int16
15
+ :name => field_info[0],
16
+ :table_oid => field_info[1],
17
+ :attribute_number => field_info[2],
18
+ :data_type_oid => field_info[3],
19
+ :data_type_size => field_info[4],
20
+ :type_modifier => field_info[5],
21
+ :format_code => field_info[6],
24
22
  }
23
+
24
+ pos += 19 + field_info[0].size
25
25
  end
26
26
  end
27
27
  end
@@ -3,8 +3,8 @@ module Vertica
3
3
  class Unknown < BackendMessage
4
4
  attr_reader :message_id
5
5
 
6
- def initialize(stream, size)
7
- @message_id = message_id
6
+ def initialize(message_id, data)
7
+ @message_id, @data = message_id, data
8
8
  end
9
9
  end
10
10
  end
@@ -1,7 +1,7 @@
1
1
  module Vertica
2
2
  module Messages
3
3
  class Bind < FrontendMessage
4
- message_id ?B
4
+ message_id 'B'
5
5
 
6
6
  def initialize(portal_name, prepared_statement_name, parameter_values)
7
7
  @portal_name = portal_name
@@ -10,19 +10,10 @@ module Vertica
10
10
  end
11
11
 
12
12
  def to_bytes
13
- bytes = [
14
- @portal_name.to_cstring, # portal name ("")
15
- @prepared_statement_name.to_cstring, # prep
16
- 0.to_network_int16, # format codes (0 - default text format)
17
- @parameter_values.length.to_network_int16, # number of parameters
18
- ]
19
- @parameter_values.each do |parameter_value|
20
- bytes << parameter_value.length.to_network_int32 # parameter value (which is represented as a string) length
21
- bytes << parameter_value # parameter value written out in text representation
22
- end
13
+ bytes = [@portal_name, @prepared_statement_name, 0, @parameter_values.length].pack('Z*Z*nn')
14
+ bytes << @parameter_values.map { |val| [val.length, val].pack('Na*') }.join('') << [0].pack('n')
23
15
  message_string bytes
24
16
  end
25
-
26
17
  end
27
18
  end
28
19
  end
@@ -9,11 +9,7 @@ module Vertica
9
9
  end
10
10
 
11
11
  def to_bytes
12
- message_string([
13
- 80877102.to_network_int32,
14
- @backend_pid.to_network_int32,
15
- @backend_key.to_network_int32
16
- ])
12
+ message_string [80877102, @backend_pid, @backend_key].pack('N3')
17
13
  end
18
14
 
19
15
  end
@@ -1,24 +1,20 @@
1
1
  module Vertica
2
2
  module Messages
3
3
  class Close < FrontendMessage
4
- message_id ?C
4
+ message_id 'C'
5
5
 
6
6
  def initialize(close_type, close_name)
7
7
  @close_name = close_name
8
8
  @close_type = case close_type
9
- when :portal then ?P
10
- when :prepared_statement then ?S
11
- else raise ArgumentError.new("#{close_type} is not a valid close_type. Must be either :portal or :prepared_statement.")
9
+ when :portal then 'P'
10
+ when :prepared_statement then 'S'
11
+ else raise ArgumentError.new("#{close_type} is not a valid close_type. Must be either :portal or :prepared_statement.")
12
12
  end
13
13
  end
14
14
 
15
15
  def to_bytes
16
- message_string([
17
- @close_type.to_byte,
18
- @close_name.to_cstring
19
- ])
16
+ message_string [@close_type, @close_name].pack('AZ*')
20
17
  end
21
-
22
18
  end
23
19
  end
24
20
  end
@@ -1,24 +1,20 @@
1
1
  module Vertica
2
2
  module Messages
3
3
  class Describe < FrontendMessage
4
- message_id ?D
4
+ message_id 'D'
5
5
 
6
6
  def initialize(describe_type, describe_name)
7
7
  @describe_name = describe_name
8
8
  @describe_type = case describe_type
9
- when :portal then ?P
10
- when :prepared_statement then ?S
11
- else raise ArgumentError.new("#{describe_type} is not a valid describe_type. Must be either :portal or :prepared_statement.")
9
+ when :portal then 'P'
10
+ when :prepared_statement then 'S'
11
+ else raise ArgumentError.new("#{describe_type} is not a valid describe_type. Must be either :portal or :prepared_statement.")
12
12
  end
13
13
  end
14
14
 
15
15
  def to_bytes
16
- message_string([
17
- @describe_type.to_byte,
18
- @describe_name.to_cstring
19
- ])
16
+ message_string [@describe_type, @describe_name].pack('AZ*')
20
17
  end
21
-
22
18
  end
23
19
  end
24
20
  end
@@ -1,7 +1,7 @@
1
1
  module Vertica
2
2
  module Messages
3
3
  class Execute < FrontendMessage
4
- message_id ?E
4
+ message_id 'E'
5
5
 
6
6
  def initialize(portal_name, max_rows)
7
7
  @portal_name = portal_name
@@ -9,12 +9,8 @@ module Vertica
9
9
  end
10
10
 
11
11
  def to_bytes
12
- message_string([
13
- @portal_name.to_cstring,
14
- @max_rows.to_network_int32
15
- ])
12
+ message_string [@portal_name, @max_rows].pack('Z*N')
16
13
  end
17
-
18
14
  end
19
15
  end
20
16
  end
@@ -1,7 +1,7 @@
1
1
  module Vertica
2
2
  module Messages
3
3
  class Flush < FrontendMessage
4
- message_id ?H
4
+ message_id 'H'
5
5
  end
6
6
  end
7
7
  end
@@ -1,7 +1,7 @@
1
1
  module Vertica
2
2
  module Messages
3
3
  class Parse < FrontendMessage
4
- message_id ?P
4
+ message_id 'P'
5
5
 
6
6
  def initialize(name, query, param_types)
7
7
  @name = name
@@ -10,14 +10,8 @@ module Vertica
10
10
  end
11
11
 
12
12
  def to_bytes
13
- message_string([
14
- @name.to_cstring,
15
- @query.to_cstring,
16
- @param_types.length.to_network_int16,
17
- @param_types.map { |type| type.to_network_int32 }
18
- ].flatten)
13
+ message_string([@name, @query, @param_types.length, *@param_types].pack('Z*Z*nN*'))
19
14
  end
20
-
21
15
  end
22
16
  end
23
17
  end
@@ -2,7 +2,7 @@
2
2
  module Vertica
3
3
  module Messages
4
4
  class Password < FrontendMessage
5
- message_id ?p
5
+ message_id 'p'
6
6
 
7
7
  def initialize(password, auth_method = nil, options = {})
8
8
  @password = password
@@ -10,16 +10,16 @@ module Vertica
10
10
  @options = options
11
11
  end
12
12
 
13
- def password
13
+ def encoded_password
14
14
  case @auth_method
15
15
  when Authentication::CLEARTEXT_PASSWORD
16
16
  @password
17
17
  when Authentication::CRYPT_PASSWORD
18
- @password.crypt(options[:salt])
18
+ @password.crypt(@options[:salt])
19
19
  when Authentication::MD5_PASSWORD
20
20
  require 'digest/md5'
21
21
  @password = Digest::MD5.hexdigest(@password + @options[:user])
22
- @password = Digest::MD5.hexdigest(m + @options[:salt])
22
+ @password = Digest::MD5.hexdigest(@password + @options[:salt])
23
23
  @password = 'md5' + @password
24
24
  else
25
25
  raise ArgumentError.new("unsupported authentication method: #{@auth_method}")
@@ -27,9 +27,8 @@ module Vertica
27
27
  end
28
28
 
29
29
  def to_bytes
30
- message_string password.to_cstring
30
+ message_string [encoded_password].pack('Z*')
31
31
  end
32
-
33
32
  end
34
33
  end
35
34
  end
@@ -2,16 +2,15 @@ module Vertica
2
2
  module Messages
3
3
 
4
4
  class Query < FrontendMessage
5
- message_id ?Q
5
+ message_id 'Q'
6
6
 
7
7
  def initialize(query_string)
8
8
  @query_string = query_string
9
9
  end
10
10
 
11
11
  def to_bytes
12
- message_string @query_string.to_cstring
12
+ message_string [@query_string].pack('Z*')
13
13
  end
14
14
  end
15
-
16
15
  end
17
16
  end