vertica 1.0.0.rc1 → 1.0.0.rc2
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 +4 -4
- data/.yardopts +4 -0
- data/README.md +97 -62
- data/lib/vertica.rb +3 -2
- data/lib/vertica/column.rb +50 -84
- data/lib/vertica/connection.rb +173 -18
- data/lib/vertica/data_type.rb +146 -0
- data/lib/vertica/error.rb +1 -0
- data/lib/vertica/protocol/backend/command_complete.rb +2 -11
- data/lib/vertica/protocol/backend/row_description.rb +1 -1
- data/lib/vertica/query.rb +36 -18
- data/lib/vertica/result.rb +69 -5
- data/lib/vertica/row.rb +57 -6
- data/lib/vertica/row_description.rb +56 -3
- data/lib/vertica/version.rb +3 -1
- data/test/functional/functional_connection_test.rb +2 -2
- data/test/functional/functional_query_test.rb +14 -11
- data/test/functional/functional_type_deserialization_test.rb +179 -0
- data/test/unit/backend_message_test.rb +3 -5
- data/test/unit/column_test.rb +21 -31
- data/test/unit/data_type_test.rb +72 -0
- data/test/unit/result_test.rb +2 -2
- data/test/unit/row_description_test.rb +31 -2
- data/test/unit/row_test.rb +26 -2
- metadata +8 -4
- data/test/functional/functional_value_conversion_test.rb +0 -117
@@ -0,0 +1,146 @@
|
|
1
|
+
# Class that represents a data type of a column.
|
2
|
+
#
|
3
|
+
# This gem is only able to handle registered types. Types are registered using {.register}.
|
4
|
+
# If an unregistered type is encountered, the library will raise {Vertica::Error::UnknownTypeError}.
|
5
|
+
#
|
6
|
+
# @example Handling an unknown OID:
|
7
|
+
# Vertica::DataType.register 12345, 'fancy_type', lambda { |bytes| ... }
|
8
|
+
#
|
9
|
+
# @attr_reader oid [Integer] The object ID of the type.
|
10
|
+
# @attr_reader name [String] The name of the type as it can be used in SQL.
|
11
|
+
# @attr_reader size [Integer] The size of the type.
|
12
|
+
# @attr_reader modifier [Integer] A modifier of the type.
|
13
|
+
# @attr_reader format [Integer] The serialization format of this type.
|
14
|
+
# @attr_reader deserializer [Proc] Proc that can deserialize values of this type coming from the database.
|
15
|
+
#
|
16
|
+
# @see Vertica::Column
|
17
|
+
class Vertica::DataType
|
18
|
+
|
19
|
+
class << self
|
20
|
+
# @return [Hash<Integer, Hash>] The Vertica types that are registered with this library, indexed by OID.
|
21
|
+
# @see .register
|
22
|
+
attr_accessor :registered_types
|
23
|
+
|
24
|
+
# Registers a new type by OID.
|
25
|
+
#
|
26
|
+
# @param oid [Integer] The object ID of the type.
|
27
|
+
# @param name [String] The name of the type as it can be used in SQL.
|
28
|
+
# @param deserializer [Proc] Proc that can deserialize values of this type coming
|
29
|
+
# from the database.
|
30
|
+
# @return [void]
|
31
|
+
def register(oid, name, deserializer = self.default_deserializer)
|
32
|
+
self.registered_types ||= {}
|
33
|
+
self.registered_types[oid] = { oid: oid, name: name, deserializer: TYPE_DESERIALIZERS.fetch(deserializer) }
|
34
|
+
end
|
35
|
+
|
36
|
+
# Builds a new type instance based on an OID.
|
37
|
+
# @param (see Vertica::DataType#initialize)
|
38
|
+
# @return [Vertica::DataType]
|
39
|
+
# @raise [Vertica::Error::UnknownTypeError] if the OID is not registered.
|
40
|
+
def build(oid: nil, **kwargs)
|
41
|
+
args = registered_types.fetch(oid) do |unknown_oid|
|
42
|
+
raise Vertica::Error::UnknownTypeError, "Unknown type OID: #{unknown_oid}"
|
43
|
+
end
|
44
|
+
|
45
|
+
new(args.merge(kwargs))
|
46
|
+
end
|
47
|
+
|
48
|
+
# The name of the default deserializer proc.
|
49
|
+
# @return [Symbol]
|
50
|
+
def default_deserializer
|
51
|
+
:generic
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
attr_reader :oid, :name, :size, :modifier, :format, :deserializer
|
56
|
+
|
57
|
+
# Instantiates a new DataType.
|
58
|
+
#
|
59
|
+
# @param oid [Integer] The object ID of the type.
|
60
|
+
# @param name [String] The name of the type as it can be used in SQL.
|
61
|
+
# @param size [Integer] The size of the type.
|
62
|
+
# @param modifier [Integer] A modifier of the type.
|
63
|
+
# @param format [Integer] The serialization format of this type.
|
64
|
+
# @param deserializer [Proc] Proc that can deserialize values of this type coming
|
65
|
+
# from the database.
|
66
|
+
# @see .build
|
67
|
+
def initialize(oid: nil, name: nil, size: nil, modifier: nil, format: 0, deserializer: nil)
|
68
|
+
@oid, @name, @size, @modifier, @format, @deserializer = oid, name, size, modifier, format, deserializer
|
69
|
+
end
|
70
|
+
|
71
|
+
# @return [Integer] Returns a hash digtest of this object.
|
72
|
+
def hash
|
73
|
+
[oid, size, modifier, format].hash
|
74
|
+
end
|
75
|
+
|
76
|
+
# @return [Boolean] Returns true iff this record is equal to the other provided object
|
77
|
+
def eql?(other)
|
78
|
+
other.kind_of?(Vertica::DataType) && oid == other.oid && size == other.size &&
|
79
|
+
modifier == other.modifier && other.format == format
|
80
|
+
end
|
81
|
+
|
82
|
+
alias_method :==, :eql?
|
83
|
+
|
84
|
+
# Deserializes a value of this type as returned by the server.
|
85
|
+
# @param bytes [String, nil] The representation of the value returned by the server.
|
86
|
+
# @return [Object] The Ruby-value taht repesents the value returned from the DB.
|
87
|
+
# @see Vertica::Protocol::DataRow
|
88
|
+
def deserialize(bytes)
|
89
|
+
return nil if bytes.nil?
|
90
|
+
deserializer.call(bytes)
|
91
|
+
end
|
92
|
+
|
93
|
+
# @return [String] Returns a user-consumable string representation of this type.
|
94
|
+
def inspect
|
95
|
+
"#<#{self.class.name}:#{oid} #{sql.inspect}>"
|
96
|
+
end
|
97
|
+
|
98
|
+
# Returns a SQL representation of this type.
|
99
|
+
# @return [String]
|
100
|
+
# @todo Take size and modifier into account.
|
101
|
+
def sql
|
102
|
+
name
|
103
|
+
end
|
104
|
+
|
105
|
+
TYPE_DESERIALIZERS = {
|
106
|
+
generic: lambda { |bytes| bytes },
|
107
|
+
bool: lambda { |bytes|
|
108
|
+
case bytes
|
109
|
+
when 't'; true
|
110
|
+
when 'f'; false
|
111
|
+
else raise ArgumentError, "Cannot convert #{bytes.inspect} to a boolean value"
|
112
|
+
end
|
113
|
+
},
|
114
|
+
integer: lambda { |bytes| Integer(bytes) },
|
115
|
+
float: lambda { |bytes|
|
116
|
+
case bytes
|
117
|
+
when 'Infinity'; Float::INFINITY
|
118
|
+
when '-Infinity'; -Float::INFINITY
|
119
|
+
when 'NaN'; Float::NAN
|
120
|
+
else Float(bytes)
|
121
|
+
end
|
122
|
+
},
|
123
|
+
bigdecimal: lambda { |bytes| BigDecimal(bytes) },
|
124
|
+
unicode_string: lambda { |bytes| bytes.force_encoding(Encoding::UTF_8) },
|
125
|
+
binary_string: lambda { |bytes| bytes.gsub(/\\([0-3][0-7][0-7])/) { $1.to_i(8).chr }.force_encoding(Encoding::BINARY) },
|
126
|
+
date: lambda { |bytes| Date.parse(bytes) },
|
127
|
+
timestamp: lambda { |bytes| Time.parse(bytes) },
|
128
|
+
}.freeze
|
129
|
+
|
130
|
+
private_constant :TYPE_DESERIALIZERS
|
131
|
+
end
|
132
|
+
|
133
|
+
Vertica::DataType.register 5, 'bool', :bool
|
134
|
+
Vertica::DataType.register 6, 'integer', :integer
|
135
|
+
Vertica::DataType.register 7, 'float', :float
|
136
|
+
Vertica::DataType.register 8, 'char', :unicode_string
|
137
|
+
Vertica::DataType.register 9, 'varchar', :unicode_string
|
138
|
+
Vertica::DataType.register 10, 'date', :date
|
139
|
+
Vertica::DataType.register 11, 'time'
|
140
|
+
Vertica::DataType.register 12, 'timestamp', :timestamp
|
141
|
+
Vertica::DataType.register 13, 'timestamp_tz', :timestamp
|
142
|
+
Vertica::DataType.register 14, 'time_tz'
|
143
|
+
Vertica::DataType.register 15, 'interval'
|
144
|
+
Vertica::DataType.register 16, 'numeric', :bigdecimal
|
145
|
+
Vertica::DataType.register 17, 'bytes', :binary_string
|
146
|
+
Vertica::DataType.register 115, 'long varchar', :unicode_string
|
data/lib/vertica/error.rb
CHANGED
@@ -8,6 +8,7 @@ class Vertica::Error < StandardError
|
|
8
8
|
class EmptyQueryError < Vertica::Error; end
|
9
9
|
class TimedOutError < ConnectionError; end
|
10
10
|
class UnknownTypeError < Vertica::Error; end
|
11
|
+
class DuplicateColumnName < Vertica::Error; end
|
11
12
|
|
12
13
|
class SynchronizeError < Vertica::Error
|
13
14
|
attr_reader :running_job, :requested_job
|
@@ -3,19 +3,10 @@ module Vertica
|
|
3
3
|
class CommandComplete < BackendMessage
|
4
4
|
message_id 'C'
|
5
5
|
|
6
|
-
attr_reader :tag
|
6
|
+
attr_reader :tag
|
7
7
|
|
8
8
|
def initialize(data)
|
9
|
-
|
10
|
-
when /^INSERT /
|
11
|
-
@tag, oid, rows = data.split(' ', 3)
|
12
|
-
@oid, @rows = oid.to_i, rows.to_i
|
13
|
-
when /^DELETE /, /^UPDATE /, /^MOVE /, /^FETCH /, /^COPY /
|
14
|
-
@tag, @rows = data.split(' ', 2)
|
15
|
-
@rows = rows.to_i
|
16
|
-
else
|
17
|
-
@tag = data
|
18
|
-
end
|
9
|
+
@tag = data.unpack('Z*').first
|
19
10
|
end
|
20
11
|
end
|
21
12
|
end
|
data/lib/vertica/query.rb
CHANGED
@@ -1,38 +1,56 @@
|
|
1
|
+
# The Query class handles the state of the connection while a SQL query is being executed.
|
2
|
+
# The connection should call {#run} and it will block until the query has been handled by
|
3
|
+
# the connection, after which control will be given back to the {Connection} instance.
|
4
|
+
#
|
5
|
+
# @note This class is for internal use only, you should never interact with this class directly.
|
6
|
+
#
|
7
|
+
# @see Vertica::Connection#query
|
8
|
+
# @see Vertica::Connection#copy
|
1
9
|
class Vertica::Query
|
2
10
|
|
3
|
-
|
4
|
-
|
11
|
+
# Instantiates a new query
|
12
|
+
# @param connection [Vertica::Connection] The connection to use for the query
|
13
|
+
# @param sql [String] The SQL statement to execute.
|
14
|
+
# @param row_handler [Proc, nil] Callback that will be called for every row that is returned.
|
15
|
+
# If no handler is provided, all rows will be buffered so a {Vertica::Result} can be returned.
|
16
|
+
#
|
17
|
+
# @param copy_handler [Proc, nil] Callback that will be called when the connection is ready
|
18
|
+
# to receive data for a `COPY ... FROM STDIN` statement.
|
5
19
|
def initialize(connection, sql, row_handler: nil, copy_handler: nil)
|
6
20
|
@connection, @sql = connection, sql
|
7
|
-
|
8
|
-
|
9
|
-
@row_handler = lambda { |row| buffer_row(row) }
|
10
|
-
else
|
11
|
-
@row_handler = row_handler
|
12
|
-
end
|
21
|
+
@buffer = row_handler.nil? && copy_handler.nil? ? [] : nil
|
22
|
+
@row_handler = row_handler || lambda { |row| buffer_row(row) }
|
13
23
|
@copy_handler = copy_handler
|
14
|
-
@error = nil
|
24
|
+
@row_description, @error = nil, nil
|
15
25
|
end
|
16
26
|
|
27
|
+
# Sends the query to the server, and processes the results.
|
28
|
+
# @return [String] For an unbuffered query, the type of SQL command will be return as a string
|
29
|
+
# (e.g. `"SELECT"` or `"COPY"`).
|
30
|
+
# @return [Vertica::Result] For a buffered query, this method will return a {Vertica::Result} instance
|
31
|
+
# @raise [Vertica::Error::ConnectionError] if the connection between client and
|
32
|
+
# server fails.
|
33
|
+
# @raise [Vertica::Error::QueryError] if the server cannot evaluate the query.
|
17
34
|
def run
|
18
|
-
@connection.write_message(Vertica::Protocol::Query.new(sql))
|
35
|
+
@connection.write_message(Vertica::Protocol::Query.new(@sql))
|
19
36
|
|
20
37
|
begin
|
21
38
|
process_message(message = @connection.read_message)
|
22
39
|
end until message.kind_of?(Vertica::Protocol::ReadyForQuery)
|
23
40
|
|
24
|
-
raise error unless error.nil?
|
25
|
-
return result
|
41
|
+
raise @error unless @error.nil?
|
42
|
+
return @result
|
26
43
|
end
|
27
44
|
|
28
|
-
|
29
|
-
|
45
|
+
# @return [String] Returns a user-consumable string representation of this query instance.
|
46
|
+
def inspect
|
47
|
+
"#<Vertica::Query:#{object_id} sql=#{@sql.inspect}>"
|
30
48
|
end
|
31
49
|
|
32
|
-
|
50
|
+
private
|
33
51
|
|
34
52
|
def buffer_rows?
|
35
|
-
|
53
|
+
@buffer.is_a?(Array)
|
36
54
|
end
|
37
55
|
|
38
56
|
def process_message(message)
|
@@ -64,7 +82,7 @@ class Vertica::Query
|
|
64
82
|
|
65
83
|
def handle_command_complete(message)
|
66
84
|
if buffer_rows?
|
67
|
-
@result = Vertica::Result.
|
85
|
+
@result = Vertica::Result.new(row_description: @row_description, rows: @buffer, tag: message.tag)
|
68
86
|
@row_description, @buffer = nil, nil
|
69
87
|
else
|
70
88
|
@result = message.tag
|
@@ -76,7 +94,7 @@ class Vertica::Query
|
|
76
94
|
@connection.write_message(Vertica::Protocol::CopyFail.new('no handler provided'))
|
77
95
|
else
|
78
96
|
begin
|
79
|
-
@copy_handler.call(CopyFromStdinWriter.new(connection))
|
97
|
+
@copy_handler.call(CopyFromStdinWriter.new(@connection))
|
80
98
|
@connection.write_message(Vertica::Protocol::CopyDone.new)
|
81
99
|
rescue => e
|
82
100
|
@connection.write_message(Vertica::Protocol::CopyFail.new(e.message))
|
data/lib/vertica/result.rb
CHANGED
@@ -1,22 +1,62 @@
|
|
1
|
+
# Class that represents a buffered resultset.
|
2
|
+
#
|
3
|
+
# This class implements the Enumerable interface for easy iteration through
|
4
|
+
# the rows. You can also address specific values in the result using {#fetch}.
|
5
|
+
# To leanr more about the shape of the result {#row_description} will give you
|
6
|
+
# an ordered list of all the {Vertica::Column}s in this result.
|
7
|
+
#
|
8
|
+
# @example Iterating over the rows
|
9
|
+
# result = connection.query("SELECT name, id")
|
10
|
+
# result.each do |row|
|
11
|
+
# puts "#{row[:id]}: #{row[:name]}"
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# @example Fetching specific values in the result
|
15
|
+
# result = connection.query('SELECT id, name FROM people WHERE id = 1')
|
16
|
+
# name = result.fetch(0, 'name')
|
17
|
+
# id = result[0,0]
|
18
|
+
#
|
19
|
+
# @example Retrieving the only value in a result
|
20
|
+
# average_salery = connection.query("SELECT AVG(salery) FROM employees").the_value
|
21
|
+
#
|
22
|
+
# @attr_reader [Vertica::RowDescription] row_description The columns in the result.
|
23
|
+
# @attr_reader [String] tag The kind of SQL command that produced this reuslt.
|
24
|
+
#
|
25
|
+
# @see Vertica::Connection#query
|
1
26
|
class Vertica::Result
|
2
27
|
include Enumerable
|
3
28
|
|
4
|
-
attr_reader :row_description
|
5
|
-
attr_reader :rows
|
6
|
-
attr_reader :tag
|
29
|
+
attr_reader :row_description, :tag
|
7
30
|
|
31
|
+
# Initializes a new Vertica::Result instance.
|
32
|
+
#
|
33
|
+
# The constructor assumes that the row description, and the list of rows match up.
|
34
|
+
# If you're unsure, use {Vertica::Result.build} which will assert this is the case.
|
35
|
+
#
|
36
|
+
# @param row_description [Vertica::RowDescription] The description of the rows
|
37
|
+
# @param rows [Array<Vertica::Row>] The array of rows
|
38
|
+
# @param tag [String] The kind of command that returned this result.
|
39
|
+
# @see Vertica::Result.build
|
8
40
|
def initialize(row_description: nil, rows: nil, tag: nil)
|
9
41
|
@row_description, @rows, @tag = row_description, rows, tag
|
10
42
|
end
|
11
43
|
|
44
|
+
# Iterates through the resultset. This class also includes the `Enumerable`
|
45
|
+
# interface, which means you can use all the `Enumerable` methods like `map`
|
46
|
+
# and `inject` as well.
|
47
|
+
# @yield The provided block will be called for every row in the resutset.
|
48
|
+
# @yieldparam row [Vertica::Row]
|
49
|
+
# @return [void]
|
12
50
|
def each(&block)
|
13
51
|
@rows.each(&block)
|
14
52
|
end
|
15
53
|
|
54
|
+
# @return [Boolean] Returns `true` if the result has no rows.
|
16
55
|
def empty?
|
17
56
|
@rows.empty?
|
18
57
|
end
|
19
58
|
|
59
|
+
# @return [Integer] The number of rows in this result
|
20
60
|
def size
|
21
61
|
@rows.length
|
22
62
|
end
|
@@ -24,14 +64,31 @@ class Vertica::Result
|
|
24
64
|
alias_method :count, :size
|
25
65
|
alias_method :length, :size
|
26
66
|
|
27
|
-
|
28
|
-
|
67
|
+
# Retrieves a row or value from the result.
|
68
|
+
# @return [Vertica::Row, Object]
|
69
|
+
#
|
70
|
+
# @overload fetch(row)
|
71
|
+
# Returns a row from the result.
|
72
|
+
# @param row [Integer] The 0-indexed row number.
|
73
|
+
# @raise [IndexError] if the row index is out of bounds.
|
74
|
+
# @return [Vertica::Row]
|
75
|
+
# @overload fetch(row, column)
|
76
|
+
# Returns a singular value from the result.
|
77
|
+
# @param row [Integer] The 0-indexed row number.
|
78
|
+
# @param col [Symbol, String, Integer] The name or index of the column.
|
79
|
+
# @raise [IndexError] if the row index is out of bounds.
|
80
|
+
# @raise [KeyError] if the requested column is not part of the result
|
81
|
+
# @return The value at the given row and column in the result.
|
82
|
+
def fetch(row, col = nil)
|
83
|
+
row = @rows.fetch(row)
|
29
84
|
return row if col.nil?
|
30
85
|
row.fetch(col)
|
31
86
|
end
|
32
87
|
|
33
88
|
alias_method :[], :fetch
|
34
89
|
|
90
|
+
# Shorthand to return the value of a query that only returns a single value.
|
91
|
+
# @return The first value of the first row, i.e. `fetch(0, 0)`.
|
35
92
|
def value
|
36
93
|
fetch(0, 0)
|
37
94
|
end
|
@@ -40,6 +97,13 @@ class Vertica::Result
|
|
40
97
|
|
41
98
|
alias_method :columns, :row_description
|
42
99
|
|
100
|
+
# Builds a {Vertica::Result} from a row description and a list of compatible rows.
|
101
|
+
# @param row_description An object that can be built into a {Vertica::RowDescription}.
|
102
|
+
# See {Vertica::RowDescription.build} for more info
|
103
|
+
# @param rows [Array] An array of objects that can be turned into a {Vertica::Row}.
|
104
|
+
# See {Vertica::RowDescription#build_row} for more info
|
105
|
+
# @param tag [String] The type of SQL command that yielded the result.
|
106
|
+
# @return [Vertica::Result]
|
43
107
|
def self.build(row_description: nil, rows: [], tag: nil)
|
44
108
|
row_description = Vertica::RowDescription.build(row_description)
|
45
109
|
rows = rows.map { |values| row_description.build_row(values) }
|
data/lib/vertica/row.rb
CHANGED
@@ -1,35 +1,86 @@
|
|
1
|
+
# Class to represent a row returns by a query.
|
2
|
+
#
|
3
|
+
# Row instances can either be yielded to the block passed to {Vertica::Connection#query},
|
4
|
+
# or be part of a buffered {Vertica::Result} returned by {Vertica::Connection#query}.
|
5
|
+
#
|
6
|
+
# @attr_reader row_description [Vertica::RowDescription] The ordered list of columns this
|
7
|
+
# row conforms to.
|
8
|
+
#
|
9
|
+
# @see Vertica::RowDescription#build_row
|
1
10
|
class Vertica::Row
|
2
11
|
include Enumerable
|
3
12
|
|
13
|
+
attr_reader :row_description
|
14
|
+
|
15
|
+
# Initializes a new row instance for a given row description and values. The
|
16
|
+
# number of values MUST match the number of columns in the row description.
|
17
|
+
# @param row_description [Vertica::RowDescription] The row description the
|
18
|
+
# values will conform to.
|
19
|
+
# @param values [Array] The values for the columns in the row description
|
20
|
+
# @see Vertica::RowDescription#build_row
|
4
21
|
def initialize(row_description, values)
|
5
22
|
@row_description, @values = row_description, values
|
6
23
|
end
|
7
24
|
|
25
|
+
# Iterates over the values in this row.
|
26
|
+
# @yield [value] The provided block will get called with the values in the order of
|
27
|
+
# the columns in the row_description.
|
8
28
|
def each(&block)
|
9
29
|
@values.each(&block)
|
10
30
|
end
|
11
31
|
|
32
|
+
# Fetches a value from this row.
|
33
|
+
# @param name_or_index [Symbol, String, Integer] The name of the column as string or symbol,
|
34
|
+
# or the index of the column in the row description.
|
35
|
+
# @raise KeyError A KeyError is raised if the field connot be found.
|
12
36
|
def fetch(name_or_index)
|
13
37
|
@values.fetch(column_index(name_or_index))
|
14
38
|
end
|
15
39
|
|
16
|
-
def inspect
|
17
|
-
"<Vertica::Row#{@values.inspect}>"
|
18
|
-
end
|
19
|
-
|
20
40
|
alias_method :[], :fetch
|
21
41
|
|
42
|
+
# Returns an array representation of the row. The values will
|
43
|
+
# be ordered like the order of the fields in the {#row_description}.
|
44
|
+
# @return [Array]
|
22
45
|
def to_a
|
23
|
-
@values
|
46
|
+
@values
|
24
47
|
end
|
25
48
|
|
49
|
+
# Returns a hash representation of this rows, using the name of the
|
50
|
+
# fields as keys.
|
51
|
+
# @param symbolize_keys [true, false] Set to true to use symbols instead
|
52
|
+
# of strings for the field names.
|
53
|
+
# @return [Hash]
|
54
|
+
# @raise [Vertica::Error::DuplicateColumnName] If the row contains multiple
|
55
|
+
# columns with the same name
|
26
56
|
def to_h(symbolize_keys: false)
|
27
57
|
@row_description.inject({}) do |carry, column|
|
28
58
|
key = symbolize_keys ? column.name.to_sym : column.name
|
29
|
-
carry.
|
59
|
+
raise Vertica::Error::DuplicateColumnName, "Column with name #{key} occurs more than once in this row." if carry.key?(key)
|
60
|
+
carry[key] = fetch(column.name)
|
61
|
+
carry
|
30
62
|
end
|
31
63
|
end
|
32
64
|
|
65
|
+
# @return [Boolean] Returns true iff this record is equal to the other provided object
|
66
|
+
def eql?(other)
|
67
|
+
other.kind_of?(Vertica::Row) && other.row_description == row_description && other.to_a == to_a
|
68
|
+
end
|
69
|
+
|
70
|
+
alias_method :==, :eql?
|
71
|
+
|
72
|
+
# @return [Integer] Returns a hash digtest of this object.
|
73
|
+
def hash
|
74
|
+
[row_description, values].hash
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return [String] Returns a user-consumable string representation of this row.
|
78
|
+
def inspect
|
79
|
+
"#<#{self.class.name}#{@values.inspect}>"
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
33
84
|
def column(name_or_index)
|
34
85
|
column_with_index(name_or_index).fetch(0)
|
35
86
|
end
|