vertica 0.11.4 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
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: