vertica 0.11.4 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6e07644b7c78ebdd916a6217ec0ee06663e45192
4
- data.tar.gz: faaf32f0340c205bcbc3483b6a5d463d55932bf7
3
+ metadata.gz: 8a40a34bb03e1ca8ad79adeb83e8573146675288
4
+ data.tar.gz: e80aa43026917a4e59da7f794c4d45d23153c297
5
5
  SHA512:
6
- metadata.gz: be92da24d4ffda0a4de1df5898723f04a6ee6a60d2f704277bc44ad80ec4f2c281ac0ba9b1dbe27df94e7629b4321153d4361afcca5a57b22162fc0a44ec111f
7
- data.tar.gz: 921509af156198086b7c490a2400671e68032c1a49d35f8046dab99204a440de679b848307f8659b34140dc7cb88fb256669508eb3a0c1b219d1fe150cd8702b
6
+ metadata.gz: e1430c2ed8107e26c1a0724d2f0c0ea9e3d21122958e2b9d2b5550a478e83f3a207dc6620a8aa05eb3e76793651237e683769b8ec2c3c4896a8460762b6508be
7
+ data.tar.gz: fe886807f5aa39f036dd7d975889fd989283f92068b7a357fa0e479c8af12c016b13a05f6eaa76f104087261ec88b88b2b1e1fa805710aeecf18dbb03f136e39
data/.gitignore CHANGED
@@ -4,4 +4,6 @@ Gemfile.lock
4
4
  test/connection.yml
5
5
  *.rbc
6
6
  .yardoc/
7
- doc/
7
+ doc/
8
+ vagrant/vertica*.deb
9
+ vagrant/.vagrant/
@@ -1,8 +1,18 @@
1
1
  language: ruby
2
2
  rvm:
3
- - "2.0"
4
- - "2.1"
5
- - "2.2"
3
+ - 2.0
4
+ - 2.1
5
+ - 2.2
6
+ - 2.3.1
7
+ - jruby-9.1.1.0
8
+ - jruby-head
9
+ - ruby-head
10
+
11
+ matrix:
12
+ allow_failures:
13
+ - rvm: jruby-head
14
+ - rvm: ruby-head
15
+ fast_finish: true
6
16
 
7
17
  before_install:
8
18
  - sudo wget -nv https://s3.amazonaws.com/circle-support-bucket/vertica_7.0.1-0_amd64.deb
@@ -14,6 +24,7 @@ before_install:
14
24
  - sudo -u dbadmin /opt/vertica/bin/adminTools -t stop_db --database ci -p dbadmin
15
25
  - sudo -u dbadmin sh -c 'echo "EnableSSL = 1" > /home/dbadmin/ci/v_ci_node0001_catalog/vertica.conf'
16
26
  - sudo -u dbadmin /opt/vertica/bin/adminTools -t start_db --database ci -p dbadmin
27
+ - gem update bundler
17
28
 
18
29
  before_script:
19
30
  - cp ./test/connection.yml.example ./test/connection.yml
data/README.md CHANGED
@@ -6,8 +6,8 @@ about Vertica at http://www.vertica.com.
6
6
  - Connecting, including over SSL.
7
7
  - Executing queries, with results as streaming rows or buffered resultsets.
8
8
  - `COPY table FROM STDIN` statement to load data from your application.
9
- - Confirmed to work with Ruby 1.9, 2.0, and 2.1 and with Vertica version 6.x,
10
- and 7.x.
9
+ - Confirmed to work with Ruby 1.9, 2.0, and 2.1; JRuby 1.7.23 and 9.0.4.0; and
10
+ with Vertica version 6.x, and 7.x.
11
11
  - The library is thread-safe as of version 0.11. However, you can only run one
12
12
  statement at the time per connection, because the protocol is stateful.
13
13
 
@@ -21,44 +21,53 @@ module Vertica
21
21
  end
22
22
  end
23
23
 
24
- DATA_TYPE_CONVERSIONS = [
25
- [:unspecified, nil],
26
- [:tuple, nil],
27
- [:pos, nil],
28
- [:record, nil],
29
- [:unknown, nil],
30
- [:bool, lambda { |s| s == 't' }],
31
- [:integer, lambda { |s| s.to_i }],
32
- [:float, FLOAT_CONVERTER],
33
- [:char, STRING_CONVERTER],
34
- [:varchar, STRING_CONVERTER],
35
- [:date, lambda { |s| Date.new(*s.split("-").map{|x| x.to_i}) }],
36
- [:time, nil],
37
- [:timestamp, lambda { |s| DateTime.parse(s, true) }],
38
- [:timestamp_tz, lambda { |s| DateTime.parse(s, true) }],
39
- [:interval, nil],
40
- [:time_tz, nil],
41
- [:numeric, lambda { |s| BigDecimal.new(s) }],
42
- [:bytea, nil],
43
- [:rle_tuple, nil]
44
- ]
24
+ DATA_TYPE_CONVERSIONS = {
25
+ 0 => [:unspecified, nil],
26
+ 1 => [:tuple, nil],
27
+ 2 => [:pos, nil],
28
+ 3 => [:record, nil],
29
+ 4 => [:unknown, nil],
30
+ 5 => [:bool, lambda { |s| s == 't' }],
31
+ 6 => [:integer, lambda { |s| s.to_i }],
32
+ 7 => [:float, FLOAT_CONVERTER],
33
+ 8 => [:char, STRING_CONVERTER],
34
+ 9 => [:varchar, STRING_CONVERTER],
35
+ 10 => [:date, lambda { |s| Date.new(*s.split("-").map{|x| x.to_i}) }],
36
+ 11 => [:time, nil],
37
+ 12 => [:timestamp, lambda { |s| DateTime.parse(s, true) }],
38
+ 13 => [:timestamp_tz, lambda { |s| DateTime.parse(s, true) }],
39
+ 14 => [:interval, nil],
40
+ 15 => [:time_tz, nil],
41
+ 16 => [:numeric, lambda { |s| BigDecimal.new(s) }],
42
+ 17 => [:bytea, lambda { |s| s.gsub(/\\([0-3][0-7][0-7])/) { $1.to_i(8).chr }} ],
43
+ 18 => [:rle_tuple, nil],
44
+ 115 => [:long_varchar, STRING_CONVERTER],
45
+ }
45
46
 
46
- DATA_TYPES = DATA_TYPE_CONVERSIONS.map { |t| t[0] }
47
+ DATA_TYPES = DATA_TYPE_CONVERSIONS.values.map { |t| t[0] }
47
48
 
48
49
  def initialize(col)
49
- @type_modifier = col[:type_modifier]
50
- @format = col[:format_code] == 0 ? :text : :binary
51
- @table_oid = col[:table_oid]
52
- @name = col[:name].to_sym
53
- @attribute_number = col[:attribute_number]
54
- @data_type = DATA_TYPE_CONVERSIONS[col[:data_type_oid]][0]
55
- @converter = DATA_TYPE_CONVERSIONS[col[:data_type_oid]][1]
56
- @size = col[:data_type_size]
50
+ @type_modifier = col.fetch(:type_modifier)
51
+ @format = col.fetch(:format_code) == 0 ? :text : :binary
52
+ @table_oid = col.fetch(:table_oid)
53
+ @name = col.fetch(:name).to_sym
54
+ @attribute_number = col.fetch(:attribute_number)
55
+ @size = col.fetch(:data_type_size)
56
+
57
+ @data_type, @converter = column_type_from_oid(col.fetch(:data_type_oid))
57
58
  end
58
59
 
59
60
  def convert(s)
60
61
  return unless s
61
62
  @converter ? @converter.call(s) : s
62
63
  end
64
+
65
+ private
66
+
67
+ def column_type_from_oid(oid)
68
+ DATA_TYPE_CONVERSIONS.fetch(oid) do |unknown_oid|
69
+ raise Vertica::Error::UnknownTypeError, "Unknown type OID: #{unknown_oid}"
70
+ end
71
+ end
63
72
  end
64
73
  end
@@ -14,8 +14,10 @@ class Vertica::Connection
14
14
  # @param [Hash] options The connection options to use.
15
15
  def initialize(options = {})
16
16
  reset_values
17
+ @notice_handler = nil
17
18
 
18
19
  @options = {}
20
+ @debug = false
19
21
 
20
22
  options.each { |key, value| @options[key.to_s.to_sym] = value if value}
21
23
 
@@ -162,7 +164,7 @@ class Vertica::Connection
162
164
  job = Vertica::Query.new(self, sql, :row_style => @row_style)
163
165
  if block_given?
164
166
  job.copy_handler = block
165
- elsif source && File.exists?(source.to_s)
167
+ elsif source && File.exist?(source.to_s)
166
168
  job.copy_handler = lambda { |data| file_copy_handler(source, data) }
167
169
  elsif source.respond_to?(:read) && source.respond_to?(:eof?)
168
170
  job.copy_handler = lambda { |data| io_copy_handler(source, data) }
@@ -216,7 +218,7 @@ class Vertica::Connection
216
218
  io_select(wait_error)
217
219
  retry
218
220
  end
219
- end
221
+ end
220
222
  bytes
221
223
  end
222
224
 
@@ -227,7 +229,7 @@ class Vertica::Connection
227
229
  io_select(wait_error)
228
230
  retry
229
231
  end
230
-
232
+
231
233
  def io_select(exception)
232
234
  readers, writers = nil, nil
233
235
  readers = [socket] if exception.is_a?(IO::WaitReadable)
@@ -1,13 +1,14 @@
1
1
  # Main class for exceptions relating to Vertica.
2
2
  class Vertica::Error < StandardError
3
-
3
+
4
4
  class ConnectionError < Vertica::Error; end
5
5
  class SSLNotSupported < ConnectionError; end
6
6
  class InterruptImpossible < Vertica::Error; end
7
7
  class MessageError < Vertica::Error; end
8
8
  class EmptyQueryError < Vertica::Error; end
9
9
  class TimedOutError < ConnectionError; end
10
-
10
+ class UnknownTypeError < Vertica::Error; end
11
+
11
12
  class SynchronizeError < Vertica::Error
12
13
  attr_reader :running_job, :requested_job
13
14
 
@@ -18,24 +19,25 @@ class Vertica::Error < StandardError
18
19
  end
19
20
 
20
21
  class QueryError < Vertica::Error
21
-
22
+
22
23
  attr_reader :error_response, :sql
23
-
24
+
24
25
  def initialize(error_response, sql)
25
26
  @error_response, @sql = error_response, sql
26
- super("#{error_response.error_message}, SQL: #{one_line_sql.inspect}" )
27
+ utf8_encoded_error = error_response.error_message.encode('utf-8', :invalid => :replace, :undef => :replace)
28
+ super("#{utf8_encoded_error}, SQL: #{one_line_sql.inspect}" )
27
29
  end
28
-
30
+
29
31
  def one_line_sql
30
- @sql.gsub(/[\r\n]+/, ' ')
32
+ @sql.to_s.encode('utf-8', :invalid => :replace, :undef => :replace).gsub(/[\r\n]+/, ' ')
31
33
  end
32
-
34
+
33
35
  def self.from_error_response(error_response, sql)
34
36
  klass = QUERY_ERROR_CLASSES[error_response.sqlstate] || self
35
37
  klass.new(error_response, sql)
36
38
  end
37
39
  end
38
-
40
+
39
41
  QUERY_ERROR_CLASSES = {
40
42
  '55V03' => (LockFailure = Class.new(Vertica::Error::QueryError)),
41
43
  '53000' => (InsufficientResources = Class.new(Vertica::Error::QueryError)),
@@ -7,7 +7,7 @@ class Vertica::Query
7
7
  @connection, @sql = connection, sql
8
8
 
9
9
  @row_style = options[:row_style] || @connection.row_style || :hash
10
- @row_handler = options[:row_handler]
10
+ @row_handler = options[:row_handler]
11
11
  @copy_handler = options[:copy_handler]
12
12
 
13
13
  @error = nil
@@ -15,8 +15,8 @@ class Vertica::Query
15
15
  end
16
16
 
17
17
  def run
18
- @connection.write_message Vertica::Messages::Query.new(sql)
19
-
18
+ @connection.write_message(Vertica::Messages::Query.new(sql))
19
+
20
20
  begin
21
21
  process_message(message = @connection.read_message)
22
22
  end until message.kind_of?(Vertica::Messages::ReadyForQuery)
@@ -24,20 +24,20 @@ class Vertica::Query
24
24
  raise error unless error.nil?
25
25
  return result
26
26
  end
27
-
27
+
28
28
  def write(data)
29
- @connection.write_message Vertica::Messages::CopyData.new(data)
29
+ @connection.write_message(Vertica::Messages::CopyData.new(data))
30
30
  return self
31
31
  end
32
-
32
+
33
33
  alias_method :<<, :write
34
34
 
35
35
  def to_s
36
36
  @sql
37
37
  end
38
-
38
+
39
39
  protected
40
-
40
+
41
41
  def process_message(message)
42
42
  case message
43
43
  when Vertica::Messages::ErrorResponse
@@ -56,19 +56,19 @@ class Vertica::Query
56
56
  @connection.process_message(message)
57
57
  end
58
58
  end
59
-
59
+
60
60
  def handle_copy_from_stdin
61
61
  if copy_handler.nil?
62
- @connection.write_message Vertica::Messages::CopyFail.new('no handler provided')
62
+ @connection.write_message(Vertica::Messages::CopyFail.new('no handler provided'))
63
63
  else
64
64
  begin
65
65
  if copy_handler.call(self) == :rollback
66
- @connection.write_message Vertica::Messages::CopyFail.new("rollback")
66
+ @connection.write_message(Vertica::Messages::CopyFail.new("rollback"))
67
67
  else
68
- @connection.write_message Vertica::Messages::CopyDone.new
68
+ @connection.write_message(Vertica::Messages::CopyDone.new)
69
69
  end
70
70
  rescue => e
71
- @connection.write_message Vertica::Messages::CopyFail.new(e.message)
71
+ @connection.write_message(Vertica::Messages::CopyFail.new(e.message))
72
72
  end
73
73
  end
74
74
  end
@@ -78,7 +78,7 @@ class Vertica::Query
78
78
  result.add_row(record) if buffer_rows?
79
79
  row_handler.call(record) if row_handler
80
80
  end
81
-
81
+
82
82
  def buffer_rows?
83
83
  row_handler.nil? && copy_handler.nil?
84
84
  end
@@ -1,6 +1,6 @@
1
1
  class Vertica::Result
2
2
  include Enumerable
3
-
3
+
4
4
  attr_reader :columns
5
5
  attr_reader :rows
6
6
  attr_accessor :tag, :notice
@@ -17,20 +17,20 @@ class Vertica::Result
17
17
  def format_row_as_hash(row_data)
18
18
  row = {}
19
19
  row_data.values.each_with_index do |value, idx|
20
- col = columns[idx]
20
+ col = columns.fetch(idx)
21
21
  row[col.name] = col.convert(value)
22
22
  end
23
23
  row
24
24
  end
25
-
25
+
26
26
  def format_row(row_data)
27
27
  send("format_row_as_#{@row_style}", row_data)
28
28
  end
29
-
29
+
30
30
  def format_row_as_array(row_data)
31
31
  row = []
32
32
  row_data.values.each_with_index do |value, idx|
33
- row << columns[idx].convert(value)
33
+ row << columns.fetch(idx).convert(value)
34
34
  end
35
35
  row
36
36
  end
@@ -42,11 +42,11 @@ class Vertica::Result
42
42
  def each_row(&block)
43
43
  @rows.each(&block)
44
44
  end
45
-
45
+
46
46
  def empty?
47
47
  @rows.empty?
48
48
  end
49
-
49
+
50
50
  def the_value
51
51
  if empty?
52
52
  nil
@@ -58,7 +58,7 @@ class Vertica::Result
58
58
  def [](row, col = nil)
59
59
  col.nil? ? row[row] : rows[row][col]
60
60
  end
61
-
61
+
62
62
  alias_method :each, :each_row
63
63
 
64
64
  def row_count
@@ -1,3 +1,3 @@
1
1
  module Vertica
2
- VERSION = "0.11.4"
2
+ VERSION = "0.12.0"
3
3
  end
@@ -1,42 +1,14 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class ConnectionTest < Minitest::Test
4
-
5
- def teardown
6
- @connection.close if @connection
7
- end
8
-
9
- def assert_valid_open_connection(connection)
10
- assert connection.opened?
11
- assert !connection.closed?
12
-
13
- # connection variables
14
- assert connection.backend_pid
15
- assert connection.backend_key
16
- assert connection.transaction_status
17
-
18
- # parameters
19
- assert connection.parameters.kind_of?(Hash)
20
- assert connection.parameters.include?('server_version')
21
- end
22
-
23
- def assert_valid_closed_connection(connection)
24
- assert !connection.opened?
25
- assert connection.closed?
26
- assert_equal({}, connection.parameters)
27
- assert_nil connection.backend_pid
28
- assert_nil connection.backend_key
29
- assert_nil connection.transaction_status
30
- end
31
-
32
4
  def test_opening_and_closing_connection
33
5
  connection = Vertica::Connection.new(TEST_CONNECTION_HASH)
34
6
  assert_valid_open_connection(connection)
35
7
 
36
8
  connection.close
37
- assert_valid_closed_connection(connection)
9
+ assert_valid_closed_connection(connection)
38
10
  end
39
-
11
+
40
12
  def test_connection_with_ssl
41
13
  connection = Vertica::Connection.new(TEST_CONNECTION_HASH.merge(:ssl => true))
42
14
  assert_valid_open_connection(connection)
@@ -45,8 +17,8 @@ class ConnectionTest < Minitest::Test
45
17
  connection.close
46
18
  assert_valid_closed_connection(connection)
47
19
  assert !connection.ssl?
48
-
49
- rescue Vertica::Error::SSLNotSupported => e
20
+
21
+ rescue Vertica::Error::SSLNotSupported
50
22
  puts "\nThe test server doesn't support SSL, so SSL connections could not be tested."
51
23
  end
52
24
 
@@ -61,7 +33,7 @@ class ConnectionTest < Minitest::Test
61
33
  assert original_backend_key != connection.backend_key
62
34
  assert_equal :no_transaction, connection.transaction_status
63
35
  end
64
-
36
+
65
37
  def test_interruptable_connection
66
38
  connection = Vertica::Connection.new(TEST_CONNECTION_HASH.merge(:interruptable => true))
67
39
  assert connection.interruptable?, "The connection should be interruptable!"
@@ -72,7 +44,7 @@ class ConnectionTest < Minitest::Test
72
44
  Vertica::Connection.new(TEST_CONNECTION_HASH.merge('database' => 'nonexistant_db'))
73
45
  end
74
46
  end
75
-
47
+
76
48
  def test_connection_inspect_should_not_print_password
77
49
  connection = Vertica::Connection.new(TEST_CONNECTION_HASH)
78
50
  inspected_string = connection.inspect
@@ -100,7 +72,7 @@ class ConnectionTest < Minitest::Test
100
72
  end
101
73
  end
102
74
 
103
- assert_raises(Vertica::Error::ConnectionError) {connection.query('select 1')}
75
+ assert_raises(Vertica::Error::ConnectionError) { connection.query('select 1') }
104
76
  assert connection.closed?
105
77
  end
106
78
 
@@ -120,12 +92,37 @@ class ConnectionTest < Minitest::Test
120
92
  connection = Vertica::Connection.new(TEST_CONNECTION_HASH)
121
93
  t = Thread.new { connection.query("SELECT sleep(1)") }
122
94
  sleep(0.1)
123
-
95
+
124
96
  assert connection.busy?, "The connection should be busy while executing a query"
125
97
  assert_raises(Vertica::Error::SynchronizeError) { connection.query('SELECT 1') }
126
-
98
+
127
99
  t.join
128
100
  assert connection.ready_for_query?, "The connection should be available again."
129
101
  connection.close
130
102
  end
103
+
104
+ private
105
+
106
+ def assert_valid_open_connection(connection)
107
+ assert connection.opened?
108
+ assert !connection.closed?
109
+
110
+ # connection variables
111
+ assert connection.backend_pid
112
+ assert connection.backend_key
113
+ assert connection.transaction_status
114
+
115
+ # parameters
116
+ assert connection.parameters.kind_of?(Hash)
117
+ assert connection.parameters.include?('server_version')
118
+ end
119
+
120
+ def assert_valid_closed_connection(connection)
121
+ assert !connection.opened?
122
+ assert connection.closed?
123
+ assert_equal({}, connection.parameters)
124
+ assert_nil connection.backend_pid
125
+ assert_nil connection.backend_key
126
+ assert_nil connection.transaction_status
127
+ end
131
128
  end
@@ -1,18 +1,16 @@
1
1
  require 'test_helper'
2
2
  require 'zlib'
3
- class TestError < StandardError; end
4
3
 
5
4
  class QueryTest < Minitest::Test
6
-
7
5
  def setup
8
6
  @connection = Vertica::Connection.new(TEST_CONNECTION_HASH)
9
- @connection.query("DROP TABLE IF EXISTS test_ruby_vertica_table CASCADE;")
7
+ @connection.query("DROP TABLE IF EXISTS test_ruby_vertica_table CASCADE;")
10
8
  @connection.query("CREATE TABLE test_ruby_vertica_table (id int, name varchar(100))")
11
9
  @connection.query("CREATE PROJECTION IF NOT EXISTS test_ruby_vertica_table_p (id, name) AS SELECT * FROM test_ruby_vertica_table SEGMENTED BY HASH(id) ALL NODES OFFSET 1")
12
10
  @connection.query("INSERT INTO test_ruby_vertica_table VALUES (1, 'matt')")
13
11
  @connection.query("COMMIT")
14
12
  end
15
-
13
+
16
14
  def teardown
17
15
  if @connection.ready_for_query?
18
16
  @connection.close
@@ -20,7 +18,7 @@ class QueryTest < Minitest::Test
20
18
  @connection.interrupt
21
19
  end
22
20
  end
23
-
21
+
24
22
  def test_select_query_with_results_as_hash
25
23
  r = @connection.query("SELECT * FROM test_ruby_vertica_table")
26
24
  assert_equal 1, r.row_count
@@ -29,10 +27,10 @@ class QueryTest < Minitest::Test
29
27
  assert_equal :id, r.columns[0].name
30
28
  assert_equal :varchar, r.columns[1].data_type
31
29
  assert_equal :name, r.columns[1].name
32
-
30
+
33
31
  assert_equal [{:id => 1, :name => "matt"}], r.rows
34
32
  end
35
-
33
+
36
34
  def test_select_query_with_results_as_array
37
35
  @connection.row_style = :array
38
36
  r = @connection.query("SELECT * FROM test_ruby_vertica_table")
@@ -42,11 +40,32 @@ class QueryTest < Minitest::Test
42
40
  assert_equal :id, r.columns[0].name
43
41
  assert_equal :varchar, r.columns[1].data_type
44
42
  assert_equal :name, r.columns[1].name
45
-
43
+
46
44
  assert_equal [[1, "matt"]], r.rows
47
45
  end
48
-
49
-
46
+
47
+ def test_select_query_with_streaming_results
48
+ result = []
49
+ @connection.query("SELECT 1 AS a, 2 AS b UNION ALL SELECT 3, 4", row_style: :hash) do |row|
50
+ result << row
51
+ end
52
+
53
+ assert_equal 2, result.length
54
+ assert_equal 1, result[0].fetch(:a)
55
+ assert_equal 2, result[0].fetch(:b)
56
+ assert_equal 3, result[1].fetch(:a)
57
+ assert_equal 4, result[1].fetch(:b)
58
+ end
59
+
60
+ def test_select_query_with_zero_streaming_results
61
+ result = []
62
+ @connection.query("SELECT 'impossible' WHERE 1=2", row_style: :hash) do |row|
63
+ result << row
64
+ end
65
+
66
+ assert_equal 0, result.length
67
+ end
68
+
50
69
  def test_select_query_with_no_results
51
70
  r = @connection.query("SELECT * FROM test_ruby_vertica_table WHERE 1 != 1")
52
71
  assert_equal 0, r.row_count
@@ -57,7 +76,7 @@ class QueryTest < Minitest::Test
57
76
  assert_equal :name, r.columns[1].name
58
77
  assert_equal [], r.rows
59
78
  end
60
-
79
+
61
80
  def test_insert
62
81
  r = @connection.query("INSERT INTO test_ruby_vertica_table VALUES (2, 'stefanie')")
63
82
  assert_equal 1, r.row_count
@@ -66,8 +85,8 @@ class QueryTest < Minitest::Test
66
85
  assert_equal :OUTPUT, r.columns[0].name
67
86
  assert_equal [{:OUTPUT => 1}], r.rows
68
87
  end
69
-
70
-
88
+
89
+
71
90
  def test_delete_of_no_rows
72
91
  r = @connection.query("DELETE FROM test_ruby_vertica_table WHERE 1 != 1")
73
92
  assert_equal 1, r.row_count
@@ -76,7 +95,7 @@ class QueryTest < Minitest::Test
76
95
  assert_equal :OUTPUT, r.columns[0].name
77
96
  assert_equal [{:OUTPUT => 0}], r.rows
78
97
  end
79
-
98
+
80
99
  def test_delete_of_a_row
81
100
  r = @connection.query("DELETE FROM test_ruby_vertica_table WHERE id = 1")
82
101
  assert_equal 1, r.row_count
@@ -85,7 +104,7 @@ class QueryTest < Minitest::Test
85
104
  assert_equal :OUTPUT, r.columns[0].name
86
105
  assert_equal [{:OUTPUT => 1}], r.rows
87
106
  end
88
-
107
+
89
108
  def test_empty_query
90
109
  assert_raises Vertica::Error::EmptyQueryError do
91
110
  @connection.query("")
@@ -93,11 +112,11 @@ class QueryTest < Minitest::Test
93
112
  assert_raises Vertica::Error::EmptyQueryError do
94
113
  @connection.query(nil)
95
114
  end
96
- assert_raises Vertica::Error::EmptyQueryError do
115
+ assert_raises Vertica::Error::EmptyQueryError do
97
116
  @connection.query("-- just a SQL comment")
98
117
  end
99
118
  end
100
-
119
+
101
120
  def test_cleanup_after_select
102
121
  3.times do
103
122
  r = @connection.query("SELECT * FROM test_ruby_vertica_table")
@@ -109,8 +128,8 @@ class QueryTest < Minitest::Test
109
128
  assert_equal :name, r.columns[1].name
110
129
  assert_equal [{:id => 1, :name => "matt"}], r.rows
111
130
  end
112
- end
113
-
131
+ end
132
+
114
133
  def test_read_timeout
115
134
  assert_raises(Vertica::Error::TimedOutError) do
116
135
  @connection.options[:read_timeout] = 0.0001
@@ -119,13 +138,13 @@ class QueryTest < Minitest::Test
119
138
  end
120
139
 
121
140
  def test_sql_error
122
- assert_raises Vertica::Error::MissingColumn do
123
- @connection.query("SELECT asad FROM test_ruby_vertica_table")
141
+ assert_raises(Vertica::Error::MissingColumn) do
142
+ @connection.query("SELECT missing FROM test_ruby_vertica_table")
124
143
  end
125
- assert_raises Vertica::Error::MissingRelation do
144
+ assert_raises(Vertica::Error::MissingRelation) do
126
145
  @connection.query("SELECT * FROM nonexisting_dsfdfsdfsdfs")
127
146
  end
128
- assert_raises Vertica::Error::SyntaxError do
147
+ assert_raises(Vertica::Error::SyntaxError) do
129
148
  @connection.query("BLAH")
130
149
  end
131
150
  end
@@ -134,40 +153,40 @@ class QueryTest < Minitest::Test
134
153
  @connection.copy "COPY test_ruby_vertica_table FROM STDIN" do |data|
135
154
  data.write "11|#{"a" * 1_000_000}\n"
136
155
  end
137
-
156
+
138
157
  result = @connection.query("SELECT id FROM test_ruby_vertica_table ORDER BY id", :row_style => :array)
139
158
  assert_equal 2, result.length
140
159
  end
141
-
160
+
142
161
  def test_copy_in_with_customer_handler
143
162
  @connection.copy "COPY test_ruby_vertica_table FROM STDIN" do |data|
144
163
  data.write "11|Stuff\r\n"
145
164
  data << "12|More stuff\n13|Fin" << "al stuff\n"
146
165
  end
147
-
166
+
148
167
  result = @connection.query("SELECT * FROM test_ruby_vertica_table ORDER BY id", :row_style => :array)
149
168
  assert_equal 4, result.length
150
169
  assert_equal [[1, "matt"], [11, "Stuff"], [12, "More stuff"], [13, "Final stuff"]], result.rows
151
170
  end
152
-
171
+
153
172
  def test_copy_in_with_gzip
154
173
  @connection.copy "COPY test_ruby_vertica_table FROM STDIN GZIP" do |data|
155
- gz = Zlib::GzipWriter.new(data)
156
- gz << "11|Stuff\n12|More stuff\n13|Final stuff\n"
157
- gz.close
174
+ gz = Zlib::GzipWriter.new(data)
175
+ gz << "11|Stuff\n12|More stuff\n13|Final stuff\n"
176
+ gz.close
158
177
  end
159
-
178
+
160
179
  result = @connection.query("SELECT * FROM test_ruby_vertica_table ORDER BY id", :row_style => :array)
161
180
  assert_equal 4, result.length
162
181
  assert_equal [[1, "matt"], [11, "Stuff"], [12, "More stuff"], [13, "Final stuff"]], result.rows
163
- end
164
-
182
+ end
183
+
165
184
  def test_copy_with_ruby_exception
166
185
  2.times do
167
186
  begin
168
187
  @connection.copy "COPY test_ruby_vertica_table FROM STDIN" do |data|
169
188
  data.write "11|#{"a" * 10}\n"
170
- raise TestError
189
+ raise "some error"
171
190
  end
172
191
  rescue Vertica::Error::CopyFromStdinFailed
173
192
  end
@@ -176,7 +195,7 @@ class QueryTest < Minitest::Test
176
195
  assert_equal 1, result.length
177
196
  end
178
197
  end
179
-
198
+
180
199
  def test_copy_with_backend_exception
181
200
  2.times do
182
201
  begin
@@ -206,14 +225,14 @@ class QueryTest < Minitest::Test
206
225
  assert_equal 4, result.length
207
226
  assert_equal [[1, "matt"], [11, "Stuff"], [12, "More stuff"], [13, "Final stuff"]], result.rows
208
227
  end
209
-
228
+
210
229
  def test_notice_handler
211
230
  notice_received = false
212
231
  @connection.on_notice { |notice| notice_received = true }
213
232
  @connection.query('COMMIT')
214
233
  assert notice_received
215
234
  end
216
-
235
+
217
236
  def test_query_mutex
218
237
  mutex = Mutex.new
219
238
  values = []
@@ -239,7 +258,7 @@ class QueryTest < Minitest::Test
239
258
 
240
259
  assert_equal values.sort, [1,1,1,2,2,2,3,3,3]
241
260
  end
242
-
261
+
243
262
  def test_raise_when_connection_is_in_use
244
263
  assert_raises(Vertica::Error::SynchronizeError) do
245
264
  @connection.query("SELECT 1 UNION SELECT 2") do |record|
@@ -247,7 +266,19 @@ class QueryTest < Minitest::Test
247
266
  end
248
267
  end
249
268
  end
250
-
269
+
270
+ def test_sql_with_non_unicode_characters
271
+ assert_raises(Vertica::Error::MissingColumn) do
272
+ sql = "select あ".encode('EUC-JP').force_encoding('BINARY')
273
+ @connection.query(sql)
274
+ end
275
+
276
+ sql = "select 'あ'".encode('EUC-JP')
277
+ result = @connection.query(sql)
278
+ assert_equal "\xA4\xA2", result.the_value
279
+ assert_equal Encoding::UTF_8, result.the_value.encoding
280
+ end
281
+
251
282
  def test_interrupting_connections
252
283
  before = @connection.query("SELECT COUNT(1) FROM test_ruby_vertica_table").the_value
253
284
  interruptable = Vertica::Connection.new(TEST_CONNECTION_HASH.merge(:interruptable => true))
@@ -255,16 +286,16 @@ class QueryTest < Minitest::Test
255
286
  t = Thread.new do
256
287
  Thread.current[:error_occurred] = false
257
288
  begin
258
- 10.times { |n| interruptable.query("INSERT INTO test_ruby_vertica_table VALUES (#{n}, 'interrupt test')") }
289
+ 10.times { |n| interruptable.query("INSERT INTO test_ruby_vertica_table VALUES (#{n}, 'interrupt test')") }
259
290
  interruptable.query("COMMIT")
260
291
  rescue Vertica::Error::ConnectionError
261
292
  Thread.current[:error_occurred] = true
262
293
  end
263
294
  end
264
-
295
+
265
296
  interruptable.interrupt
266
297
  t.join
267
-
298
+
268
299
  assert t[:error_occurred], "Expected an exception to occur"
269
300
  assert_equal before, @connection.query("SELECT COUNT(1) FROM test_ruby_vertica_table").the_value
270
301
  end
@@ -2,13 +2,13 @@
2
2
  require 'test_helper'
3
3
 
4
4
  class ValueConversionTest < Minitest::Test
5
-
5
+
6
6
  def setup
7
7
  @connection = Vertica::Connection.new(TEST_CONNECTION_HASH.merge(:row_style => :array))
8
8
 
9
9
  @connection.query <<-SQL
10
10
  CREATE TABLE IF NOT EXISTS conversions_table (
11
- "int_field" int,
11
+ "int_field" int,
12
12
  "string_field" varchar(100),
13
13
  "date_field" date,
14
14
  "timestamp_field" timestamp,
@@ -16,46 +16,73 @@ class ValueConversionTest < Minitest::Test
16
16
  "interval_field" interval,
17
17
  "boolean_field" boolean,
18
18
  "float_field" float,
19
- "float_zero" float
19
+ "float_zero" float,
20
+ "binary_field" varbinary,
21
+ "long_varchar_field" long varchar
20
22
  )
21
23
  SQL
22
24
  end
23
-
24
-
25
+
26
+
25
27
  def teardown
26
28
  @connection.query("DROP TABLE IF EXISTS conversions_table CASCADE;")
27
29
  @connection.close
28
30
  end
29
-
31
+
30
32
  def test_value_conversions
31
- @connection.query "INSERT INTO conversions_table VALUES (123, 'hello world', '2010-01-01', '2010-01-01 12:00:00', '12:00:00', INTERVAL '1 DAY', TRUE, 1.0, 0.0)"
32
- result = @connection.query "SELECT *,
33
- float_field / float_zero as infinity,
34
- float_field / float_zero - float_field / float_zero as nan
35
- FROM conversions_table LIMIT 1"
33
+ @connection.query <<-SQL
34
+ INSERT INTO conversions_table VALUES (
35
+ 123,
36
+ 'hello world',
37
+ '2010-01-01',
38
+ '2010-01-01 12:00:00',
39
+ '12:00:00',
40
+ INTERVAL '1 DAY',
41
+ TRUE,
42
+ 1.0,
43
+ 0.0,
44
+ HEX_TO_BINARY('d09fd180d0b8d0b2d0b5d1822c2068656c6c6f21'),
45
+ 'hello world'
46
+ )
47
+ SQL
48
+
49
+ result = @connection.query <<-SQL
50
+ SELECT *,
51
+ float_field / float_zero as infinity,
52
+ float_field / float_zero - float_field / float_zero as nan
53
+ FROM conversions_table LIMIT 1
54
+ SQL
55
+
36
56
  assert_equal result.rows.length, 1
37
57
  assert_equal [
38
- 123,
39
- 'hello world',
40
- Date.parse('2010-01-01'),
58
+ 123,
59
+ 'hello world',
60
+ Date.parse('2010-01-01'),
41
61
  DateTime.parse('2010-01-01 12:00:00'),
42
- "12:00:00",
43
- "1",
62
+ "12:00:00",
63
+ "1",
44
64
  true,
45
65
  1.0,
46
66
  0.0,
67
+ ['d09fd180d0b8d0b2d0b5d1822c2068656c6c6f21'].pack('H*'),
68
+ 'hello world',
47
69
  Float::INFINITY,
48
70
  Float::NAN], result.rows.first
49
71
  end
50
-
72
+
51
73
  def test_nil_conversions
52
- @connection.query "INSERT INTO conversions_table VALUES (NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)"
74
+ @connection.query "INSERT INTO conversions_table VALUES (NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)"
53
75
  result = @connection.query "SELECT * FROM conversions_table LIMIT 1"
54
76
  assert_equal result.rows.length, 1
55
- assert_equal [nil, nil, nil, nil, nil, nil, nil, nil, nil], result.rows.first
77
+ assert_equal [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], result.rows.first
56
78
  end
57
-
79
+
58
80
  def test_string_encoding
59
81
  assert_equal 'åßç∂ë', @connection.query("SELECT 'åßç∂ë'").the_value
60
82
  end
83
+
84
+ def test_binary_encoding
85
+ assert_equal ['d09fd180d0b8d0b2d0b5d1822c2068656c6c6f21'].pack('H*'), @connection.query("SELECT HEX_TO_BINARY('d09fd180d0b8d0b2d0b5d1822c2068656c6c6f21')").the_value
86
+ assert_equal Encoding::BINARY, @connection.query("SELECT HEX_TO_BINARY('d09fd180d0b8d0b2d0b5d1822c2068656c6c6f21')").the_value.encoding
87
+ end
61
88
  end
@@ -17,4 +17,4 @@ else
17
17
  puts "for your Vertica test database in order to run the test suite."
18
18
  puts
19
19
  exit(1)
20
- end
20
+ end
@@ -0,0 +1,51 @@
1
+ require 'test_helper'
2
+
3
+ class ColumnTest < Minitest::Test
4
+
5
+ def test_initialize_from_row_description
6
+ field_description = {
7
+ :name => "OUTPUT",
8
+ :table_oid => 0,
9
+ :attribute_number => 0,
10
+ :data_type_oid => 6,
11
+ :data_type_size => 8,
12
+ :type_modifier => 8,
13
+ :format_code => 0
14
+ }
15
+
16
+ column = Vertica::Column.new(field_description)
17
+ assert_equal :OUTPUT, column.name
18
+ assert_equal :integer, column.data_type
19
+ assert_equal 8, column.type_modifier
20
+ end
21
+
22
+ def test_unknown_type_oid
23
+ field_description = {
24
+ :name => "OUTPUT",
25
+ :table_oid => 0,
26
+ :attribute_number => 0,
27
+ :data_type_oid => 123456,
28
+ :data_type_size => 8,
29
+ :type_modifier => 8,
30
+ :format_code => 0
31
+ }
32
+
33
+ assert_raises(Vertica::Error::UnknownTypeError) { Vertica::Column.new(field_description) }
34
+ end
35
+
36
+ def test_integer_converter
37
+ field_description = {
38
+ :name => "OUTPUT",
39
+ :table_oid => 0,
40
+ :attribute_number => 0,
41
+ :data_type_oid => 6,
42
+ :data_type_size => 8,
43
+ :type_modifier => 8,
44
+ :format_code => 0
45
+ }
46
+
47
+ column = Vertica::Column.new(field_description)
48
+ assert_equal :integer, column.data_type
49
+ assert_equal 1234, column.convert('1234')
50
+ end
51
+ end
@@ -0,0 +1,40 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ vertica_version = Dir['vertica_*.deb'].first
5
+ if vertica_version.nil?
6
+ raise "Please place a vertica .deb pacakge in the \`vagrant\` folder."
7
+ end
8
+
9
+ # Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
10
+ VAGRANTFILE_API_VERSION = "2"
11
+
12
+ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
13
+ # All Vagrant configuration is done here. The most common configuration
14
+ # options are documented and commented below. For a complete reference,
15
+ # please see the online documentation at vagrantup.com.
16
+
17
+ # Every Vagrant virtual environment requires a box to build off of.
18
+ config.vm.box = "puphpet/ubuntu1404-x64"
19
+
20
+ # Disable automatic box update checking. If you disable this, then
21
+ # boxes will only be checked for updates when the user runs
22
+ # `vagrant box outdated`. This is not recommended.
23
+ # config.vm.box_check_update = false
24
+
25
+ # Create a forwarded port mapping which allows access to a specific port
26
+ # within the machine from a port on the host machine. In the example below,
27
+ # accessing "localhost:8080" will access port 80 on the guest machine.
28
+ config.vm.network "forwarded_port", guest: 5433, host: 5433
29
+
30
+ # Create a private network, which allows host-only access to the machine
31
+ # using a specific IP.
32
+ # config.vm.network "private_network", ip: "192.168.33.10"
33
+
34
+ config.vm.provision "shell", path: "setup_vertica.sh"
35
+
36
+ config.vm.provider "vmware_fusion" do |v|
37
+ v.vmx["memsize"] = "2048"
38
+ v.vmx["numvcpus"] = "2"
39
+ end
40
+ end
@@ -0,0 +1,16 @@
1
+ #!/bin/bash
2
+ set -ex
3
+
4
+ : ${VERTICA_VERSION:=7.2.3-0}
5
+
6
+ apt-get install dialog pstack sysstat mcelog -y
7
+
8
+ dpkg -i /vagrant/vertica_${VERTICA_VERSION}_amd64.deb
9
+ /opt/vertica/sbin/install_vertica --failure-threshold HALT --accept-eula --dba-user-password dbadmin --license CE -s localhost
10
+
11
+ sudo -u dbadmin /opt/vertica/bin/adminTools -t create_db --database ci -s localhost -p dbadmin
12
+ # sudo -u dbadmin openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /home/dbadmin/ci/v_ci_node0001_catalog/server.key -out /home/dbadmin/ci/v_ci_node0001_catalog/server.crt -batch
13
+ # sudo -u dbadmin chmod 600 /home/dbadmin/ci/v_ci_node0001_catalog/server.key /home/dbadmin/ci/v_ci_node0001_catalog/server.crt
14
+ # sudo -u dbadmin /opt/vertica/bin/adminTools -t stop_db --database ci -p dbadmin
15
+ # sudo -u dbadmin sh -c 'echo "EnableSSL = 1" > /home/dbadmin/ci/v_ci_node0001_catalog/vertica.conf'
16
+ # sudo -u dbadmin /opt/vertica/bin/adminTools -t start_db --database ci -p dbadmin
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
8
8
  s.name = "vertica"
9
9
  s.summary = "Pure Ruby library for interacting with Vertica"
10
10
  s.description = "Query Vertica with ruby"
11
- s.homepage = "https://github.com/sprsquish/vertica"
11
+ s.homepage = "https://github.com/wvanbergen/vertica"
12
12
  s.license = "MIT"
13
13
  s.version = Vertica::VERSION
14
14
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vertica
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.4
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Smick
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-09-16 00:00:00.000000000 Z
13
+ date: 2016-07-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
@@ -119,10 +119,13 @@ files:
119
119
  - test/resources/test_ruby_vertica_table.csv
120
120
  - test/test_helper.rb
121
121
  - test/unit/backend_message_test.rb
122
+ - test/unit/column_test.rb
122
123
  - test/unit/frontend_message_test.rb
123
124
  - test/unit/quoting_test.rb
125
+ - vagrant/Vagrantfile
126
+ - vagrant/setup_vertica.sh
124
127
  - vertica.gemspec
125
- homepage: https://github.com/sprsquish/vertica
128
+ homepage: https://github.com/wvanbergen/vertica
126
129
  licenses:
127
130
  - MIT
128
131
  metadata: {}
@@ -142,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
145
  version: '0'
143
146
  requirements: []
144
147
  rubyforge_project:
145
- rubygems_version: 2.0.14
148
+ rubygems_version: 2.0.14.1
146
149
  signing_key:
147
150
  specification_version: 4
148
151
  summary: Pure Ruby library for interacting with Vertica
@@ -154,6 +157,7 @@ test_files:
154
157
  - test/resources/test_ruby_vertica_table.csv
155
158
  - test/test_helper.rb
156
159
  - test/unit/backend_message_test.rb
160
+ - test/unit/column_test.rb
157
161
  - test/unit/frontend_message_test.rb
158
162
  - test/unit/quoting_test.rb
159
163
  has_rdoc: