sequel_impala 1.1.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.
Files changed (129) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +50 -0
  3. data/LICENSE +463 -0
  4. data/README.md +45 -0
  5. data/Rakefile +39 -0
  6. data/lib/driver/commons-collections-3.2.1.jar +0 -0
  7. data/lib/driver/commons-configuration-1.10.jar +0 -0
  8. data/lib/driver/commons-logging-1.2.jar +0 -0
  9. data/lib/driver/hadoop-auth-2.9.0.jar +0 -0
  10. data/lib/driver/hadoop-common-2.9.0.jar +0 -0
  11. data/lib/driver/hadoop-core-2.6.0.jar +0 -0
  12. data/lib/driver/hive-exec-1.1.0.jar +0 -0
  13. data/lib/driver/hive-jdbc-1.1.0.jar +0 -0
  14. data/lib/driver/hive-metastore-1.1.0.jar +0 -0
  15. data/lib/driver/hive-service-1.1.0.jar +0 -0
  16. data/lib/driver/httpclient-4.3.jar +0 -0
  17. data/lib/driver/httpcore-4.3.jar +0 -0
  18. data/lib/driver/libfb303-0.9.0.jar +0 -0
  19. data/lib/driver/log4j-1.2.17.jar +0 -0
  20. data/lib/driver/slf4j-api-1.7.5.jar +0 -0
  21. data/lib/driver/stax2-api-3.1.4.jar +0 -0
  22. data/lib/driver/woodstox-core-asl-4.4.1.jar +0 -0
  23. data/lib/impala.rb +55 -0
  24. data/lib/impala/connection.rb +180 -0
  25. data/lib/impala/cursor.rb +200 -0
  26. data/lib/impala/progress_reporter.rb +40 -0
  27. data/lib/impala/protocol.rb +8 -0
  28. data/lib/impala/protocol/beeswax_constants.rb +15 -0
  29. data/lib/impala/protocol/beeswax_service.rb +747 -0
  30. data/lib/impala/protocol/beeswax_types.rb +193 -0
  31. data/lib/impala/protocol/exec_stats_constants.rb +13 -0
  32. data/lib/impala/protocol/exec_stats_types.rb +133 -0
  33. data/lib/impala/protocol/facebook_service.rb +706 -0
  34. data/lib/impala/protocol/fb303_constants.rb +15 -0
  35. data/lib/impala/protocol/fb303_types.rb +25 -0
  36. data/lib/impala/protocol/hive_metastore_constants.rb +53 -0
  37. data/lib/impala/protocol/hive_metastore_types.rb +698 -0
  38. data/lib/impala/protocol/impala_hive_server2_service.rb +137 -0
  39. data/lib/impala/protocol/impala_service.rb +443 -0
  40. data/lib/impala/protocol/impala_service_constants.rb +13 -0
  41. data/lib/impala/protocol/impala_service_types.rb +192 -0
  42. data/lib/impala/protocol/status_constants.rb +13 -0
  43. data/lib/impala/protocol/status_types.rb +46 -0
  44. data/lib/impala/protocol/t_c_l_i_service.rb +1108 -0
  45. data/lib/impala/protocol/t_c_l_i_service_constants.rb +72 -0
  46. data/lib/impala/protocol/t_c_l_i_service_types.rb +1802 -0
  47. data/lib/impala/protocol/thrift_hive_metastore.rb +4707 -0
  48. data/lib/impala/protocol/types_constants.rb +13 -0
  49. data/lib/impala/protocol/types_types.rb +332 -0
  50. data/lib/impala/sasl_transport.rb +117 -0
  51. data/lib/impala/thrift_patch.rb +31 -0
  52. data/lib/impala/version.rb +3 -0
  53. data/lib/jdbc/hive2.rb +52 -0
  54. data/lib/jdbc/impala.rb +50 -0
  55. data/lib/rbhive.rb +8 -0
  56. data/lib/rbhive/connection.rb +150 -0
  57. data/lib/rbhive/explain_result.rb +46 -0
  58. data/lib/rbhive/result_set.rb +37 -0
  59. data/lib/rbhive/schema_definition.rb +86 -0
  60. data/lib/rbhive/t_c_l_i_connection.rb +466 -0
  61. data/lib/rbhive/t_c_l_i_result_set.rb +3 -0
  62. data/lib/rbhive/t_c_l_i_schema_definition.rb +87 -0
  63. data/lib/rbhive/table_schema.rb +122 -0
  64. data/lib/rbhive/version.rb +3 -0
  65. data/lib/sequel/adapters/impala.rb +220 -0
  66. data/lib/sequel/adapters/jdbc/hive2.rb +36 -0
  67. data/lib/sequel/adapters/jdbc/impala.rb +38 -0
  68. data/lib/sequel/adapters/rbhive.rb +177 -0
  69. data/lib/sequel/adapters/shared/impala.rb +808 -0
  70. data/lib/sequel/extensions/csv_to_parquet.rb +166 -0
  71. data/lib/thrift/facebook_service.rb +700 -0
  72. data/lib/thrift/fb303_constants.rb +9 -0
  73. data/lib/thrift/fb303_types.rb +19 -0
  74. data/lib/thrift/hive_metastore_constants.rb +41 -0
  75. data/lib/thrift/hive_metastore_types.rb +630 -0
  76. data/lib/thrift/hive_service_constants.rb +13 -0
  77. data/lib/thrift/hive_service_types.rb +72 -0
  78. data/lib/thrift/queryplan_constants.rb +13 -0
  79. data/lib/thrift/queryplan_types.rb +261 -0
  80. data/lib/thrift/sasl_client_transport.rb +161 -0
  81. data/lib/thrift/serde_constants.rb +92 -0
  82. data/lib/thrift/serde_types.rb +7 -0
  83. data/lib/thrift/t_c_l_i_service.rb +1054 -0
  84. data/lib/thrift/t_c_l_i_service_constants.rb +72 -0
  85. data/lib/thrift/t_c_l_i_service_types.rb +1768 -0
  86. data/lib/thrift/thrift_hive.rb +508 -0
  87. data/lib/thrift/thrift_hive_metastore.rb +3856 -0
  88. data/spec/database_test.rb +56 -0
  89. data/spec/dataset_test.rb +1268 -0
  90. data/spec/files/bad_down_migration/001_create_alt_basic.rb +4 -0
  91. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +4 -0
  92. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +9 -0
  93. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +9 -0
  94. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +3 -0
  95. data/spec/files/bad_up_migration/001_create_alt_basic.rb +4 -0
  96. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +3 -0
  97. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +9 -0
  98. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +9 -0
  99. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +4 -0
  100. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +9 -0
  101. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +9 -0
  102. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +9 -0
  103. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +9 -0
  104. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +4 -0
  105. data/spec/files/integer_migrations/001_create_sessions.rb +9 -0
  106. data/spec/files/integer_migrations/002_create_nodes.rb +9 -0
  107. data/spec/files/integer_migrations/003_3_create_users.rb +4 -0
  108. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +9 -0
  109. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +9 -0
  110. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +9 -0
  111. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +9 -0
  112. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +4 -0
  113. data/spec/files/reversible_migrations/001_reversible.rb +5 -0
  114. data/spec/files/reversible_migrations/002_reversible.rb +5 -0
  115. data/spec/files/reversible_migrations/003_reversible.rb +5 -0
  116. data/spec/files/reversible_migrations/004_reversible.rb +5 -0
  117. data/spec/files/reversible_migrations/005_reversible.rb +10 -0
  118. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +9 -0
  119. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +9 -0
  120. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +4 -0
  121. data/spec/impala_test.rb +290 -0
  122. data/spec/migrator_test.rb +240 -0
  123. data/spec/plugin_test.rb +91 -0
  124. data/spec/prepared_statement_test.rb +327 -0
  125. data/spec/schema_test.rb +356 -0
  126. data/spec/spec_helper.rb +19 -0
  127. data/spec/timezone_test.rb +86 -0
  128. data/spec/type_test.rb +99 -0
  129. metadata +294 -0
@@ -0,0 +1,466 @@
1
+ # suppress warnings
2
+ old_verbose, $VERBOSE = $VERBOSE, nil
3
+
4
+ raise 'Thrift is not loaded' unless defined?(Thrift)
5
+ raise 'RBHive is not loaded' unless defined?(RBHive)
6
+
7
+ # require thrift autogenerated files
8
+ require File.join(File.dirname(__FILE__), *%w[.. thrift t_c_l_i_service_constants])
9
+ require File.join(File.dirname(__FILE__), *%w[.. thrift t_c_l_i_service])
10
+ require File.join(File.dirname(__FILE__), *%w[.. thrift sasl_client_transport])
11
+
12
+ # restore warnings
13
+ $VERBOSE = old_verbose
14
+
15
+ # Monkey patch thrift to set an infinite read timeout
16
+ module Thrift
17
+ class HTTPClientTransport < BaseTransport
18
+ def flush
19
+ http = Net::HTTP.new @url.host, @url.port
20
+ http.use_ssl = @url.scheme == 'https'
21
+ http.read_timeout = nil
22
+ http.verify_mode = @ssl_verify_mode if @url.scheme == 'https'
23
+ resp = http.post(@url.request_uri, @outbuf, @headers)
24
+ data = resp.body
25
+ data = Bytes.force_binary_encoding(data)
26
+ @inbuf = StringIO.new data
27
+ @outbuf = Bytes.empty_byte_buffer
28
+ end
29
+ end
30
+ end
31
+
32
+ module RBHive
33
+
34
+ HIVE_THRIFT_MAPPING = {
35
+ 10 => 0,
36
+ 11 => 1,
37
+ 12 => 2,
38
+ 13 => 6,
39
+ :cdh4 => 0,
40
+ :cdh5 => 4,
41
+ :PROTOCOL_V1 => 0,
42
+ :PROTOCOL_V2 => 1,
43
+ :PROTOCOL_V3 => 2,
44
+ :PROTOCOL_V4 => 3,
45
+ :PROTOCOL_V5 => 4,
46
+ :PROTOCOL_V6 => 5,
47
+ :PROTOCOL_V7 => 6
48
+ }
49
+
50
+ def tcli_connect(server, port = 10_000, options={})
51
+ logger = options.key?(:logger) ? options.delete(:logger) : StdOutLogger.new
52
+ connection = RBHive::TCLIConnection.new(server, port, options, logger)
53
+ ret = nil
54
+ begin
55
+ connection.open
56
+ connection.open_session
57
+ ret = yield(connection)
58
+
59
+ ensure
60
+ # Try to close the session and our connection if those are still open, ignore io errors
61
+ begin
62
+ connection.close_session if connection.session
63
+ connection.close
64
+ rescue IOError => e
65
+ # noop
66
+ end
67
+ end
68
+
69
+ ret
70
+ end
71
+ module_function :tcli_connect
72
+
73
+ class StdOutLogger
74
+ %w(fatal error warn info debug).each do |level|
75
+ define_method level.to_sym do |message|
76
+ STDOUT.puts(message)
77
+ end
78
+ end
79
+ end
80
+
81
+ class TCLIConnection
82
+ attr_reader :client
83
+
84
+ def initialize(server, port = 10_000, options = {}, logger = StdOutLogger.new)
85
+ options ||= {} # backwards compatibility
86
+ raise "'options' parameter must be a hash" unless options.is_a?(Hash)
87
+ @sasl_params = options.delete(:sasl_params) || {}
88
+
89
+ if options[:transport] == :sasl and @sasl_params.empty?
90
+ raise ":transport is set to :sasl, but no :sasl_params option was supplied"
91
+ end
92
+
93
+ # Defaults to buffered transport, Hive 0.10, 1800 second timeout
94
+ options[:transport] ||= :buffered
95
+ options[:hive_version] ||= 10
96
+ options[:timeout] ||= 1800
97
+ @options = options
98
+ # Look up the appropriate Thrift protocol version for the supplied Hive version
99
+ @thrift_protocol_version = thrift_hive_protocol(options[:hive_version])
100
+
101
+ @logger = logger
102
+ @transport = thrift_transport(server, port)
103
+ @protocol = Thrift::BinaryProtocol.new(@transport)
104
+ @client = Hive2::Thrift::TCLIService::Client.new(@protocol)
105
+ @session = nil
106
+ @logger.info("Connecting to HiveServer2 #{server} on port #{port}")
107
+ end
108
+
109
+ def thrift_hive_protocol(version)
110
+ HIVE_THRIFT_MAPPING[version] || raise("Invalid Hive version")
111
+ end
112
+
113
+ def thrift_transport(server, port)
114
+ @logger.info("Initializing transport #{@options[:transport]}")
115
+ case @options[:transport]
116
+ when :buffered
117
+ return Thrift::BufferedTransport.new(thrift_socket(server, port, @options[:timeout]))
118
+ when :sasl
119
+ return Thrift::SaslClientTransport.new(thrift_socket(server, port, @options[:timeout]),
120
+ parse_sasl_params(@sasl_params))
121
+ when :http
122
+ return Thrift::HTTPClientTransport.new("http://#{server}:#{port}/cliservice")
123
+ else
124
+ raise "Unrecognised transport type '#{transport}'"
125
+ end
126
+ end
127
+
128
+ def thrift_socket(server, port, timeout)
129
+ socket = Thrift::Socket.new(server, port)
130
+ socket.timeout = timeout
131
+ socket
132
+ end
133
+
134
+ # Processes SASL connection params and returns a hash with symbol keys or a nil
135
+ def parse_sasl_params(sasl_params)
136
+ # Symbilize keys in a hash
137
+ if sasl_params.kind_of?(Hash)
138
+ return sasl_params.inject({}) do |memo,(k,v)|
139
+ memo[k.to_sym] = v;
140
+ memo
141
+ end
142
+ end
143
+ return nil
144
+ end
145
+
146
+ def open
147
+ @transport.open
148
+ end
149
+
150
+ def close
151
+ @transport.close
152
+ end
153
+
154
+ def open_session
155
+ @session = @client.OpenSession(prepare_open_session(@thrift_protocol_version))
156
+ end
157
+
158
+ def close_session
159
+ @client.CloseSession prepare_close_session
160
+ @session = nil
161
+ end
162
+
163
+ def session
164
+ @session && @session.sessionHandle
165
+ end
166
+
167
+ def client
168
+ @client
169
+ end
170
+
171
+ def execute(query)
172
+ @logger.info("Executing Hive Query: #{query}")
173
+ req = prepare_execute_statement(query)
174
+ exec_result = client.ExecuteStatement(req)
175
+ raise_error_if_failed!(exec_result)
176
+ exec_result
177
+ end
178
+
179
+ def priority=(priority)
180
+ set("mapred.job.priority", priority)
181
+ end
182
+
183
+ def queue=(queue)
184
+ set("mapred.job.queue.name", queue)
185
+ end
186
+
187
+ def set(name,value)
188
+ @logger.info("Setting #{name}=#{value}")
189
+ self.execute("SET #{name}=#{value}")
190
+ end
191
+
192
+ # Async execute
193
+ def async_execute(query)
194
+ @logger.info("Executing query asynchronously: #{query}")
195
+ exec_result = @client.ExecuteStatement(
196
+ Hive2::Thrift::TExecuteStatementReq.new(
197
+ sessionHandle: @session.sessionHandle,
198
+ statement: query,
199
+ runAsync: true
200
+ )
201
+ )
202
+ raise_error_if_failed!(exec_result)
203
+ op_handle = exec_result.operationHandle
204
+
205
+ # Return handles to get hold of this query / session again
206
+ {
207
+ session: @session.sessionHandle,
208
+ guid: op_handle.operationId.guid,
209
+ secret: op_handle.operationId.secret
210
+ }
211
+ end
212
+
213
+ # Is the query complete?
214
+ def async_is_complete?(handles)
215
+ async_state(handles) == :finished
216
+ end
217
+
218
+ # Is the query actually running?
219
+ def async_is_running?(handles)
220
+ async_state(handles) == :running
221
+ end
222
+
223
+ # Has the query failed?
224
+ def async_is_failed?(handles)
225
+ async_state(handles) == :error
226
+ end
227
+
228
+ def async_is_cancelled?(handles)
229
+ async_state(handles) == :cancelled
230
+ end
231
+
232
+ def async_cancel(handles)
233
+ @client.CancelOperation(prepare_cancel_request(handles))
234
+ end
235
+
236
+ # Map states to symbols
237
+ def async_state(handles)
238
+ response = @client.GetOperationStatus(
239
+ Hive2::Thrift::TGetOperationStatusReq.new(operationHandle: prepare_operation_handle(handles))
240
+ )
241
+
242
+ case response.operationState
243
+ when Hive2::Thrift::TOperationState::FINISHED_STATE
244
+ return :finished
245
+ when Hive2::Thrift::TOperationState::INITIALIZED_STATE
246
+ return :initialized
247
+ when Hive2::Thrift::TOperationState::RUNNING_STATE
248
+ return :running
249
+ when Hive2::Thrift::TOperationState::CANCELED_STATE
250
+ return :cancelled
251
+ when Hive2::Thrift::TOperationState::CLOSED_STATE
252
+ return :closed
253
+ when Hive2::Thrift::TOperationState::ERROR_STATE
254
+ return :error
255
+ when Hive2::Thrift::TOperationState::UKNOWN_STATE
256
+ return :unknown
257
+ when Hive2::Thrift::TOperationState::PENDING_STATE
258
+ return :pending
259
+ when nil
260
+ raise "No operation state found for handles - has the session been closed?"
261
+ else
262
+ return :state_not_in_protocol
263
+ end
264
+ end
265
+
266
+ # Async fetch results from an async execute
267
+ def async_fetch(handles, max_rows = 100)
268
+ # Can't get data from an unfinished query
269
+ unless async_is_complete?(handles)
270
+ raise "Can't perform fetch on a query in state: #{async_state(handles)}"
271
+ end
272
+
273
+ # Fetch and
274
+ fetch_rows(prepare_operation_handle(handles), :first, max_rows)
275
+ end
276
+
277
+ # Performs a query on the server, fetches the results in batches of *batch_size* rows
278
+ # and yields the result batches to a given block as arrays of rows.
279
+ def async_fetch_in_batch(handles, batch_size = 1000, &block)
280
+ raise "No block given for the batch fetch request!" unless block_given?
281
+ # Can't get data from an unfinished query
282
+ unless async_is_complete?(handles)
283
+ raise "Can't perform fetch on a query in state: #{async_state(handles)}"
284
+ end
285
+
286
+ # Now let's iterate over the results
287
+ loop do
288
+ rows = fetch_rows(prepare_operation_handle(handles), :next, batch_size)
289
+ break if rows.empty?
290
+ yield rows
291
+ end
292
+ end
293
+
294
+ def async_close_session(handles)
295
+ validate_handles!(handles)
296
+ @client.CloseSession(Hive2::Thrift::TCloseSessionReq.new( sessionHandle: handles[:session] ))
297
+ end
298
+
299
+ def get_column_info(op_handle)
300
+ cols = get_schema_for(op_handle).columns
301
+ [cols.map(&:columnName), cols.map{|c| c.typeDesc.types.first.primitiveEntry.type}]
302
+ end
303
+
304
+ def yield_hash_rows(op_handle, columns, convertors)
305
+ i = -1
306
+ cols = columns.zip(convertors).map{|col, conv| [i+=1, col, conv]}
307
+ rows = fetch_rows(op_handle)
308
+ until rows.empty?
309
+ rows.each do |row|
310
+ h = {}
311
+ vals = row.colVals
312
+ cols.each do |i, col, conv|
313
+ v = vals[i].get_value.value
314
+ h[col] = unless v.nil?
315
+ conv ? conv[v] : v
316
+ end
317
+ end
318
+ yield h
319
+ end
320
+ rows = fetch_rows(op_handle, :next)
321
+ end
322
+ end
323
+
324
+ # Pull rows from the query result
325
+ def fetch_rows(op_handle, orientation = :first, max_rows = 1000)
326
+ fetch_req = prepare_fetch_results(op_handle, orientation, max_rows)
327
+ fetch_results = @client.FetchResults(fetch_req)
328
+ raise_error_if_failed!(fetch_results)
329
+ fetch_results.results.rows
330
+ #TCLIResultSet.new(rows, TCLISchemaDefinition.new(get_schema_for(op_handle), rows.first))
331
+ end
332
+
333
+ # Performs a explain on the supplied query on the server, returns it as a ExplainResult.
334
+ # (Only works on 0.12 if you have this patch - https://issues.apache.org/jira/browse/HIVE-5492)
335
+ def explain(query)
336
+ rows = []
337
+ fetch_in_batch("EXPLAIN " + query) do |batch|
338
+ rows << batch.map { |b| b[:Explain] }
339
+ end
340
+ ExplainResult.new(rows.flatten)
341
+ end
342
+
343
+ # Performs a query on the server, fetches up to *max_rows* rows and returns them as an array.
344
+ def fetch(query, max_rows = 100)
345
+ # Execute the query and check the result
346
+ exec_result = execute(query)
347
+ raise_error_if_failed!(exec_result)
348
+
349
+ # Get search operation handle to fetch the results
350
+ op_handle = exec_result.operationHandle
351
+
352
+ # Fetch the rows
353
+ fetch_rows(op_handle, :first, max_rows)
354
+ end
355
+
356
+ # Performs a query on the server, fetches the results in batches of *batch_size* rows
357
+ # and yields the result batches to a given block as arrays of rows.
358
+ def fetch_in_batch(query, batch_size = 1000, &block)
359
+ raise "No block given for the batch fetch request!" unless block_given?
360
+
361
+ # Execute the query and check the result
362
+ exec_result = execute(query)
363
+ raise_error_if_failed!(exec_result)
364
+
365
+ # Get search operation handle to fetch the results
366
+ op_handle = exec_result.operationHandle
367
+
368
+ # Prepare fetch results request
369
+ fetch_req = prepare_fetch_results(op_handle, :next, batch_size)
370
+
371
+ # Now let's iterate over the results
372
+ loop do
373
+ rows = fetch_rows(op_handle, :next, batch_size)
374
+ break if rows.empty?
375
+ yield rows
376
+ end
377
+ end
378
+
379
+ def create_table(schema)
380
+ execute(schema.create_table_statement)
381
+ end
382
+
383
+ def drop_table(name)
384
+ name = name.name if name.is_a?(TableSchema)
385
+ execute("DROP TABLE `#{name}`")
386
+ end
387
+
388
+ def replace_columns(schema)
389
+ execute(schema.replace_columns_statement)
390
+ end
391
+
392
+ def add_columns(schema)
393
+ execute(schema.add_columns_statement)
394
+ end
395
+
396
+ def method_missing(meth, *args)
397
+ client.send(meth, *args)
398
+ end
399
+
400
+ private
401
+
402
+ def prepare_open_session(client_protocol)
403
+ req = ::Hive2::Thrift::TOpenSessionReq.new( @sasl_params.empty? ? [] : @sasl_params )
404
+ req.client_protocol = client_protocol
405
+ req
406
+ end
407
+
408
+ def prepare_close_session
409
+ ::Hive2::Thrift::TCloseSessionReq.new( sessionHandle: self.session )
410
+ end
411
+
412
+ def prepare_execute_statement(query)
413
+ ::Hive2::Thrift::TExecuteStatementReq.new( sessionHandle: self.session, statement: query.to_s, confOverlay: {"impala.resultset.cache.size"=>"100000"} )
414
+ end
415
+
416
+ def prepare_fetch_results(handle, orientation=:first, rows=100)
417
+ orientation_value = "FETCH_#{orientation.to_s.upcase}"
418
+ valid_orientations = ::Hive2::Thrift::TFetchOrientation::VALUE_MAP.values
419
+ unless valid_orientations.include?(orientation_value)
420
+ raise ArgumentError, "Invalid orientation: #{orientation.inspect}"
421
+ end
422
+ orientation_const = eval("::Hive2::Thrift::TFetchOrientation::#{orientation_value}")
423
+ ::Hive2::Thrift::TFetchResultsReq.new(
424
+ operationHandle: handle,
425
+ orientation: orientation_const,
426
+ maxRows: rows
427
+ )
428
+ end
429
+
430
+ def prepare_operation_handle(handles)
431
+ validate_handles!(handles)
432
+ Hive2::Thrift::TOperationHandle.new(
433
+ operationId: Hive2::Thrift::THandleIdentifier.new(guid: handles[:guid], secret: handles[:secret]),
434
+ operationType: Hive2::Thrift::TOperationType::EXECUTE_STATEMENT,
435
+ hasResultSet: false
436
+ )
437
+ end
438
+
439
+ def prepare_cancel_request(handles)
440
+ Hive2::Thrift::TCancelOperationReq.new(
441
+ operationHandle: prepare_operation_handle(handles)
442
+ )
443
+ end
444
+
445
+ def validate_handles!(handles)
446
+ unless handles.has_key?(:guid) and handles.has_key?(:secret) and handles.has_key?(:session)
447
+ raise "Invalid handles hash: #{handles.inspect}"
448
+ end
449
+ end
450
+
451
+ def get_schema_for(handle)
452
+ req = ::Hive2::Thrift::TGetResultSetMetadataReq.new( operationHandle: handle )
453
+ metadata = client.GetResultSetMetadata( req )
454
+ metadata.schema
455
+ end
456
+
457
+ # Raises an exception if given operation result is a failure
458
+ def raise_error_if_failed!(result)
459
+ return if result.status.statusCode == 0
460
+ error_message = result.status.errorMessage || 'Execution failed!'
461
+ raise RBHive::TCLIConnectionError.new(error_message)
462
+ end
463
+ end
464
+
465
+ class TCLIConnectionError < StandardError; end
466
+ end