Skip to content
Browse files

Fix exception handling in multi execute and query functions

  • Loading branch information...
1 parent 81e7d9a commit 1d0b709839b50e1aa1d084d27415d518f8975d5e @wdavidw committed
Showing with 127 additions and 52 deletions.
  1. +40 −23 lib/hive.coffee
  2. +66 −0 test/MultiExecuteTest.coffee
  3. +21 −29 test/{MultiTest.coffee → MultiQueryTest.coffee}
View
63 lib/hive.coffee
@@ -6,12 +6,12 @@ thrift = require 'thrift'
transport = require 'thrift/lib/thrift/transport'
EventEmitter = require('events').EventEmitter
-split = module.exports.split = (queries) ->
- return queries if Array.isArray queries
- queries = queries.split('\n').filter( (line) -> line.trim().indexOf('--') isnt 0 ).join('\n')
- queries = queries.split ';'
- queries = queries.map (query) -> query.trim()
- queries = queries.filter (query) -> query.indexOf('--') isnt 0 and query isnt ''
+split = module.exports.split = (hqls) ->
+ return hqls if Array.isArray hqls
+ hqls = hqls.split('\n').filter( (line) -> line.trim().indexOf('--') isnt 0 ).join('\n')
+ hqls = hqls.split ';'
+ hqls = hqls.map (query) -> query.trim()
+ hqls = hqls.filter (query) -> query.indexOf('--') isnt 0 and query isnt ''
module.exports.createClient = (options = {}) ->
options.version ?= '0.7.1-cdh3u2'
@@ -30,10 +30,19 @@ module.exports.createClient = (options = {}) ->
process.nextTick ->
emitter.emit 'before', query
client.execute query, (err) ->
- #if err
- #then emitter.emit 'error', err
- #else emitter.emit 'end', query
- callback err, callback
+ if err
+ emitter.readable = false
+ # emit error only if
+ # - an error callback or
+ # - no error callback, no both callback, no user callback
+ lerror = emitter.listeners('error').length
+ lboth = emitter.listeners('both').length
+ emitError = lerror or (not lerror and not lboth and not callback )
+ emitter.emit 'error', err if emitError
+ else
+ emitter.emit 'end', null, query
+ emitter.emit 'both', err, query
+ callback err, callback if callback
emitter
query: (query, size) ->
if arguments.length is 2 and typeof size is 'function'
@@ -45,11 +54,11 @@ module.exports.createClient = (options = {}) ->
if err
emitter.readable = false
# emit error only if
- # - there is an error callback
- # - there is no error callback and no both callback
+ # - an error callback or
+ # - no error callback and no both callback
lerror = emitter.listeners('error').length
lboth = emitter.listeners('both').length
- emitError = lerror or (not lerror and not lboth)
+ emitError = lerror or (not lerror and not lboth) # and not callback if we add callback support
emitter.emit 'error', err if emitError
emitter.emit 'both', err, query
return
@@ -75,8 +84,8 @@ module.exports.createClient = (options = {}) ->
if err
emitter.readable = false
# emit error only if
- # - there is an error callback
- # - there is no error callback and no both callback
+ # - an error callback or
+ # - no error callback and no both callback
lerror = emitter.listeners('error').length
lboth = emitter.listeners('both').length
emitError = lerror or (not lerror and not lboth)
@@ -100,14 +109,13 @@ module.exports.createClient = (options = {}) ->
then client.fetchN size, handle
else client.fetchAll handle
emitter
- multi_execute: (queries, callback) ->
+ multi_execute: (hqls, callback) ->
emitter = new EventEmitter
- queries = split(queries)
- each(queries)
+ hqls = split(hqls)
+ each(hqls)
.on 'item', (next, query) =>
exec = @execute query, next
exec.on 'before', -> emitter.emit.call emitter, 'before', arguments...
- exec.on 'error', -> emitter.emit.call emitter, 'error', arguments...
.on 'both', (err) ->
if err
then emitter.emit.call emitter, 'error', arguments...
@@ -115,17 +123,26 @@ module.exports.createClient = (options = {}) ->
emitter.emit.call emitter, 'both', arguments...
callback err if callback
emitter
- multi_query: (hqls, callback) ->
+ multi_query: (hqls) ->
hqls = split(hqls)
query = @query()
each(hqls)
.on 'item', (next, hql, i) =>
unless hqls.length is i + 1
- exec = @execute hql, next
+ exec = @execute hql#, next
exec.on 'before', -> query.emit.call query, 'before', arguments...
- exec.on 'error', -> query.emit.call query, 'error', arguments...
+ exec.on 'error', (err) ->
+ query.readable = false
+ # emit error only if
+ # - an error callback or
+ # - no error callback and no both callback
+ lerror = query.listeners('error').length
+ lboth = query.listeners('both').length
+ emitError = lerror or (not lerror and not lboth)
+ query.emit 'error', err if emitError
+ query.emit 'both', err, query
+ exec.on 'end', -> next()
else
query.query(hql)
- .on 'both', (err) -> callback err
query
View
66 test/MultiExecuteTest.coffee
@@ -0,0 +1,66 @@
+
+assert = require 'assert'
+hive = require "#{__dirname}/.."
+
+db = 'test_database'
+table = 'test_table'
+
+client = hive.createClient require './config.json'
+
+module.exports =
+ 'Multi # Execute # String': (next) ->
+ count_before = 0
+ count_end = 0
+ count_both = 0
+ execute = client.multi_execute """
+ -- create db
+ CREATE DATABASE IF NOT EXISTS #{db};
+ -- create table
+ CREATE TABLE IF NOT EXISTS #{table} (
+ a_bigint BIGINT,
+ an_int INT,
+ a_date STRING
+ )
+ ROW FORMAT DELIMITED
+ FIELDS TERMINATED BY ',';
+ -- load data
+ LOAD DATA LOCAL INPATH '#{__dirname}/data.csv' OVERWRITE INTO TABLE #{table};
+ """, (err) ->
+ assert.ifError err
+ assert.eql count_before, 3
+ assert.eql count_end, 1
+ assert.eql count_both, 1
+ next()
+ execute.on 'before', (query) ->
+ count_before++
+ execute.on 'end', (query) ->
+ count_end++
+ execute.on 'both', (query) ->
+ count_both++
+ 'Multi # Execute # Error': (next) ->
+ count_before = 0
+ count_error = 0
+ count_both = 0
+ execute = client.multi_execute """
+ -- Throw err
+ Whow, that should throw an exception!;
+ -- create db
+ CREATE DATABASE IF NOT EXISTS #{db};
+ """, (err) ->
+ assert.ok err instanceof Error
+ assert.eql err.name, 'HiveServerException'
+ assert.eql count_before, 1
+ assert.eql count_error, 1
+ assert.eql count_both, 1
+ next()
+ execute.on 'before', (query) ->
+ count_before++
+ execute.on 'error', (err) ->
+ assert.ok err instanceof Error
+ assert.eql err.name, 'HiveServerException'
+ count_error++
+ execute.on 'both', (query) ->
+ count_both++
+ 'Close': (next) ->
+ client.end()
+ next()
View
50 test/MultiTest.coffee → test/MultiQueryTest.coffee
@@ -8,35 +8,6 @@ table = 'test_table'
client = hive.createClient require './config.json'
module.exports =
- 'Multi # Execute # String': (next) ->
- count_before = 0
- count_end = 0
- count_both = 0
- execute = client.multi_execute """
- -- create db
- CREATE DATABASE IF NOT EXISTS #{db};
- -- create table
- CREATE TABLE IF NOT EXISTS #{table} (
- a_bigint BIGINT,
- an_int INT,
- a_date STRING
- )
- ROW FORMAT DELIMITED
- FIELDS TERMINATED BY ',';
- -- load data
- LOAD DATA LOCAL INPATH '#{__dirname}/data.csv' OVERWRITE INTO TABLE #{table};
- """, (err) ->
- assert.ifError err
- assert.eql count_before, 3
- assert.eql count_end, 1
- assert.eql count_both, 1
- next()
- execute.on 'before', (query) ->
- count_before++
- execute.on 'end', (query) ->
- count_end++
- execute.on 'both', (query) ->
- count_both++
'Multi # Query # String': (next) ->
count_before = 0
count_row = 0
@@ -67,6 +38,27 @@ module.exports =
assert.eql count_row, 54
assert.eql query, "SELECT * FROM #{table}"
next()
+ 'Multi # Query # Error in execute # No callback': (next) ->
+ count_before = 0
+ count_error = 0
+ client.multi_query("""
+ -- Throw err
+ Whow, that should throw an exception!;
+ -- create db
+ CREATE DATABASE IF NOT EXISTS #{db};
+ """)
+ .on 'before', (query) ->
+ count_before++
+ .on 'error', (err) ->
+ count_error++
+ .on 'end', (query) ->
+ assert.ok false
+ .on 'both', (err) ->
+ assert.ok err instanceof Error
+ assert.eql err.name, 'HiveServerException'
+ assert.eql count_before, 1
+ assert.eql count_error, 1
+ next()
'Close': (next) ->
client.end()
next()

0 comments on commit 1d0b709

Please sign in to comment.
Something went wrong with that request. Please try again.