sneaql 0.0.13-java → 0.0.15-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/sneaql +0 -1
- data/lib/sneaql.rb +28 -8
- data/lib/sneaql_lib/base.rb +15 -2
- data/lib/sneaql_lib/core.rb +126 -1
- data/lib/sneaql_lib/database_manager.rb +8 -8
- data/lib/sneaql_lib/database_prefs/redshift.rb +5 -6
- data/lib/sneaql_lib/database_prefs/sqlite.rb +2 -2
- data/lib/sneaql_lib/database_prefs/vertica.rb +4 -4
- data/lib/sneaql_lib/docker.rb +9 -9
- data/lib/sneaql_lib/exceptions.rb +36 -16
- data/lib/sneaql_lib/expressions.rb +85 -34
- data/lib/sneaql_lib/lock_manager.rb +7 -7
- data/lib/sneaql_lib/parser.rb +10 -3
- data/lib/sneaql_lib/repo_manager.rb +2 -3
- data/lib/sneaql_lib/standard_db_objects.rb +8 -8
- data/lib/sneaql_lib/step_manager.rb +35 -21
- data/lib/sneaql_lib/tokenizer.rb +183 -0
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91f871ef54dcf89b3664fc1752bfc13cfb6ce787
|
4
|
+
data.tar.gz: fd38d7bf1c632db20ae61ae88ec57872a370edf9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5d6fa48016600fde9277250a4b7bdde4f3d1e3cee7c6305af06b9b084ed00c8d2ea21739315cb68472a4b348b1b99858468d71a1bc9a08868e454c34fdb5df7
|
7
|
+
data.tar.gz: 9bd0b13170e52f50b961b65228a139f1c879ccd4780d3610665aecd6698741b15232fbd9023453f25c6ea121467a4126f51b878e3440a15003a5045d22cc2c5c
|
data/bin/sneaql
CHANGED
data/lib/sneaql.rb
CHANGED
@@ -13,6 +13,7 @@ require_relative 'sneaql_lib/recordset.rb'
|
|
13
13
|
require_relative 'sneaql_lib/database_manager.rb'
|
14
14
|
require_relative 'sneaql_lib/standard_db_objects.rb'
|
15
15
|
require_relative 'sneaql_lib/docker.rb'
|
16
|
+
require_relative 'sneaql_lib/tokenizer.rb'
|
16
17
|
|
17
18
|
# module for sneaql
|
18
19
|
module Sneaql
|
@@ -77,13 +78,15 @@ module Sneaql
|
|
77
78
|
@db_pass = @params[:db_pass]
|
78
79
|
@database = @params[:database]
|
79
80
|
|
81
|
+
@expression_handler = create_expression_handler
|
82
|
+
@recordset_manager = create_recordset_manager
|
83
|
+
@exception_manager = create_exception_manager
|
84
|
+
|
80
85
|
run if @params[:run] == true
|
81
86
|
end
|
82
87
|
|
83
88
|
# validate the transform.
|
84
89
|
def validate
|
85
|
-
@expression_handler = create_expression_handler
|
86
|
-
@recordset_manager = create_recordset_manager
|
87
90
|
@repo_manager = create_repo_manager
|
88
91
|
@steps = create_metadata_manager
|
89
92
|
@parsed_steps = create_parsed_steps(@steps)
|
@@ -116,8 +119,6 @@ module Sneaql
|
|
116
119
|
|
117
120
|
# Runs the actual transform.
|
118
121
|
def run
|
119
|
-
@expression_handler = create_expression_handler
|
120
|
-
@recordset_manager = create_recordset_manager
|
121
122
|
@repo_manager = create_repo_manager
|
122
123
|
@lock_manager = create_lock_manager if @params[:locked_transform] == true
|
123
124
|
@steps = create_metadata_manager
|
@@ -159,6 +160,11 @@ module Sneaql
|
|
159
160
|
Sneaql::Core::ExpressionHandler.new(@logger)
|
160
161
|
end
|
161
162
|
|
163
|
+
# Creates ExceptionHandler object
|
164
|
+
def create_exception_manager
|
165
|
+
Sneaql::Exceptions::ExceptionManager.new(@logger)
|
166
|
+
end
|
167
|
+
|
162
168
|
# Creates a RepoDownloadManager object
|
163
169
|
# The actual object returns depends upon params[:repo_type] provided at initialize.
|
164
170
|
# @return [Sneaql::Core::RepoDownloadManager]
|
@@ -236,9 +242,9 @@ module Sneaql
|
|
236
242
|
# not rollback automatically unless that is the default RDBMS
|
237
243
|
# behavior for a connection that closes before a commit.
|
238
244
|
def iterate_steps_and_statements
|
239
|
-
@parsed_steps.
|
240
|
-
#special handling is required for the exit_step_if command
|
241
|
-
#because there is a nested loop the exit_step var is needed
|
245
|
+
@parsed_steps.each_with_index do |this_step|
|
246
|
+
# special handling is required for the exit_step_if command
|
247
|
+
# because there is a nested loop the exit_step var is needed
|
242
248
|
exit_step = false
|
243
249
|
break if exit_step == true
|
244
250
|
# set this so that other processes can poll the state
|
@@ -247,7 +253,9 @@ module Sneaql
|
|
247
253
|
this_step[:parser].statements.each_with_index do |this_stmt, stmt_index|
|
248
254
|
# set this so that other processes can poll the state
|
249
255
|
@current_statement = stmt_index + 1
|
250
|
-
|
256
|
+
|
257
|
+
@exception_manager.output_pending_error
|
258
|
+
|
251
259
|
# log some useful info
|
252
260
|
@logger.info("step: #{@current_step} statement: #{@current_statement}")
|
253
261
|
@expression_handler.output_all_session_variables
|
@@ -267,12 +275,24 @@ module Sneaql
|
|
267
275
|
c = Sneaql::Core.find_class(:command, this_cmd[:command]).new(
|
268
276
|
@jdbc_connection,
|
269
277
|
@expression_handler,
|
278
|
+
@exception_manager,
|
270
279
|
@recordset_manager,
|
271
280
|
@expression_handler.evaluate_all_expressions(this_stmt),
|
272
281
|
@logger
|
273
282
|
)
|
274
283
|
|
275
284
|
c.action(*this_cmd[:arguments])
|
285
|
+
|
286
|
+
# check if there was an error from the action
|
287
|
+
if @exception_manager.pending_error != nil
|
288
|
+
# if there was an error... check to see if this is the last stmt in step
|
289
|
+
if stmt_index == (this_step[:parser].statements.length - 1)
|
290
|
+
# last step... so we know there is no error handler in this step
|
291
|
+
# therefore we should propagate the error
|
292
|
+
raise @exception_manager.pending_error
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
276
296
|
rescue Sneaql::Exceptions::SQLTestStepExitCondition => e
|
277
297
|
exit_step = true
|
278
298
|
@logger.info e.message
|
data/lib/sneaql_lib/base.rb
CHANGED
@@ -2,7 +2,7 @@ require 'zip/zip'
|
|
2
2
|
require 'fileutils'
|
3
3
|
require 'logger'
|
4
4
|
|
5
|
-
#top level namespace for sneaql objects
|
5
|
+
# top level namespace for sneaql objects
|
6
6
|
module Sneaql
|
7
7
|
# contains the base classes for the extendable parts of sneaql:
|
8
8
|
# commands (the actual commands specified in sneaql tags)
|
@@ -74,11 +74,12 @@ module Sneaql
|
|
74
74
|
# @param [Sneaql::Core::RecordsetManager] recordset_manager
|
75
75
|
# @param [String] statement SQL statement provided in body, with all variables resolved
|
76
76
|
# @param [Logger] logger object otherwise will default to new Logger
|
77
|
-
def initialize(jdbc_connection, expression_handler, recordset_manager, statement, logger = nil)
|
77
|
+
def initialize(jdbc_connection, expression_handler, exception_manager, recordset_manager, statement, logger = nil)
|
78
78
|
@logger = logger ? logger : Logger.new(STDOUT)
|
79
79
|
|
80
80
|
@jdbc_connection = jdbc_connection
|
81
81
|
@expression_handler = expression_handler
|
82
|
+
@exception_manager = exception_manager
|
82
83
|
@statement = statement
|
83
84
|
@recordset_manager = recordset_manager
|
84
85
|
end
|
@@ -110,6 +111,8 @@ module Sneaql
|
|
110
111
|
valid << valid_operator?(a)
|
111
112
|
when arg_definition[i] == :recordset then
|
112
113
|
valid << valid_recordset?(a)
|
114
|
+
when arg_definition[i] == :symbol then
|
115
|
+
valid << valid_symbol?(a)
|
113
116
|
else valid << false end
|
114
117
|
end
|
115
118
|
@logger.debug("arg validation results: #{valid}")
|
@@ -143,6 +146,16 @@ module Sneaql
|
|
143
146
|
def valid_recordset?(a)
|
144
147
|
@recordset_manager.valid_recordset_name?(a.to_s.strip)
|
145
148
|
end
|
149
|
+
|
150
|
+
# note that this is not a ruby symbol, but a sneaql symbol
|
151
|
+
# should be a contigiuous string consisting of only letters, digits
|
152
|
+
# and underscores
|
153
|
+
# @param [String] a value to test
|
154
|
+
# @return [Boolean]
|
155
|
+
def valid_symbol?(a)
|
156
|
+
return true if a.match(/^\w+$/)
|
157
|
+
false
|
158
|
+
end
|
146
159
|
|
147
160
|
private
|
148
161
|
|
data/lib/sneaql_lib/core.rb
CHANGED
@@ -5,7 +5,7 @@ require_relative 'exceptions.rb'
|
|
5
5
|
module Sneaql
|
6
6
|
module Core
|
7
7
|
# Core Sneaql language command tags.
|
8
|
-
# You can create your own tags by extending
|
8
|
+
# You can create your own tags by extending
|
9
9
|
# Sneaql::Core::SneaqlCommand and overriding the
|
10
10
|
# action method. You should also override arg_definition
|
11
11
|
# and potentially validate_args if have a complex argument
|
@@ -23,6 +23,8 @@ module Sneaql
|
|
23
23
|
# @param [String] value expression (must be a string)
|
24
24
|
def action(var_name, value)
|
25
25
|
@expression_handler.set_session_variable(var_name, value)
|
26
|
+
rescue => e
|
27
|
+
@exception_manager.pending_error = e
|
26
28
|
end
|
27
29
|
|
28
30
|
# argument types
|
@@ -46,6 +48,8 @@ module Sneaql
|
|
46
48
|
target_var_name,
|
47
49
|
sql_result
|
48
50
|
)
|
51
|
+
rescue => e
|
52
|
+
@exception_manager.pending_error = e
|
49
53
|
end
|
50
54
|
|
51
55
|
# argument types
|
@@ -78,6 +82,8 @@ module Sneaql
|
|
78
82
|
'last_statement_rows_affected',
|
79
83
|
rows_affected
|
80
84
|
)
|
85
|
+
rescue => e
|
86
|
+
@exception_manager.pending_error = e
|
81
87
|
end
|
82
88
|
|
83
89
|
# @return [Fixnum] rows affected by SQL statement
|
@@ -108,6 +114,8 @@ module Sneaql
|
|
108
114
|
rows_affected
|
109
115
|
)
|
110
116
|
end
|
117
|
+
rescue => e
|
118
|
+
@exception_manager.pending_error = e
|
111
119
|
end
|
112
120
|
|
113
121
|
# argument types
|
@@ -145,6 +153,8 @@ module Sneaql
|
|
145
153
|
)
|
146
154
|
raise Sneaql::Exceptions::SQLTestExitCondition
|
147
155
|
end
|
156
|
+
rescue => e
|
157
|
+
@exception_manager.pending_error = e
|
148
158
|
end
|
149
159
|
|
150
160
|
# argument types
|
@@ -223,6 +233,8 @@ module Sneaql
|
|
223
233
|
r = query_results
|
224
234
|
@logger.debug "adding #{r.length} recs as #{recordset_name}"
|
225
235
|
@recordset_manager.store_recordset(recordset_name, r)
|
236
|
+
rescue => e
|
237
|
+
@exception_manager.pending_error = e
|
226
238
|
end
|
227
239
|
|
228
240
|
# argument types
|
@@ -255,6 +267,8 @@ module Sneaql
|
|
255
267
|
elsif ((args.size - 1) % 4) == 0
|
256
268
|
iterate_records_conditionally(*args)
|
257
269
|
end
|
270
|
+
rescue => e
|
271
|
+
@exception_manager.pending_error = e
|
258
272
|
end
|
259
273
|
|
260
274
|
# custom method for argument validation
|
@@ -295,6 +309,9 @@ module Sneaql
|
|
295
309
|
rows_affected_current_statement(tmp)
|
296
310
|
)
|
297
311
|
end
|
312
|
+
rescue => e
|
313
|
+
@exception_manager.pending_error = e
|
314
|
+
raise e
|
298
315
|
end
|
299
316
|
|
300
317
|
# @param [*Array] args all the arguments passed to the calling function
|
@@ -312,6 +329,9 @@ module Sneaql
|
|
312
329
|
rows_affected_current_statement(tmp)
|
313
330
|
)
|
314
331
|
end
|
332
|
+
rescue => e
|
333
|
+
@exception_manager.pending_error = e
|
334
|
+
raise e
|
315
335
|
end
|
316
336
|
|
317
337
|
# @return [Fixnum] rows affected by the SQL statement
|
@@ -339,6 +359,111 @@ module Sneaql
|
|
339
359
|
r.map! { |d| { 'path_name' => d.to_s } }
|
340
360
|
@logger.debug "adding #{r.length} recs as #{recordset_name}"
|
341
361
|
@recordset_manager.store_recordset(recordset_name, r)
|
362
|
+
rescue => e
|
363
|
+
@exception_manager.pending_error = e
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
# stores all the file paths matching the dir glob into a recordset
|
368
|
+
class SneaqlOnError < Sneaql::Core::SneaqlCommand
|
369
|
+
Sneaql::Core::RegisterMappedClass.new(
|
370
|
+
:command,
|
371
|
+
'on_error',
|
372
|
+
Sneaql::Core::Commands::SneaqlOnError
|
373
|
+
)
|
374
|
+
|
375
|
+
# argument types
|
376
|
+
def arg_definition
|
377
|
+
[:symbol]
|
378
|
+
end
|
379
|
+
|
380
|
+
# @param [String] recordset_name
|
381
|
+
# @param [String] dirglob directory glob with optional wildcards
|
382
|
+
def action(handler_action)
|
383
|
+
# only take action if there is an error
|
384
|
+
if @exception_manager.pending_error
|
385
|
+
case handler_action.downcase
|
386
|
+
when 'continue' then
|
387
|
+
@logger.error("#{@exception_manager.pending_error.message}")
|
388
|
+
if @exception_manager.pending_error.backtrace
|
389
|
+
@exception_manager.pending_error.backtrace.each {|b| @logger.debug(b) }
|
390
|
+
end
|
391
|
+
@exception_manager.pending_error = nil
|
392
|
+
@exception_manager.last_iterated_record = nil
|
393
|
+
@logger.info("continuing after error due to on_error handling")
|
394
|
+
|
395
|
+
when 'exit_step' then
|
396
|
+
@logger.error("#{@exception_manager.pending_error.message}")
|
397
|
+
if @exception_manager.pending_error.backtrace
|
398
|
+
@exception_manager.pending_error.backtrace.each {|b| @logger.debug(b) }
|
399
|
+
end
|
400
|
+
@exception_manager.pending_error = nil
|
401
|
+
@exception_manager.last_iterated_record = nil
|
402
|
+
|
403
|
+
@logger.info("exiting step due to on_error handling")
|
404
|
+
raise Sneaql::Exceptions::SQLTestStepExitCondition
|
405
|
+
|
406
|
+
when 'execute' then
|
407
|
+
@logger.error("#{@exception_manager.pending_error.message}")
|
408
|
+
if @exception_manager.pending_error.backtrace
|
409
|
+
@exception_manager.pending_error.backtrace.each {|b| @logger.debug(b) }
|
410
|
+
end
|
411
|
+
@logger.info("executing sql block due to on_error handling")
|
412
|
+
|
413
|
+
@expression_handler.set_session_variable(
|
414
|
+
'last_statement_rows_affected',
|
415
|
+
rows_affected
|
416
|
+
)
|
417
|
+
|
418
|
+
@exception_manager.pending_error = nil
|
419
|
+
@exception_manager.last_iterated_record = nil
|
420
|
+
end
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
def rows_affected
|
425
|
+
tmp = @statement
|
426
|
+
tmp = replace_last_record(tmp)
|
427
|
+
tmp = replace_error_details(tmp)
|
428
|
+
JDBCHelpers::Execute.new(
|
429
|
+
@jdbc_connection,
|
430
|
+
tmp,
|
431
|
+
@logger
|
432
|
+
).rows_affected
|
433
|
+
end
|
434
|
+
|
435
|
+
# replaces a string with references to the field values in the last
|
436
|
+
# record iterated (if present). use :err_record.field_name syntax
|
437
|
+
# @param [String] input_string containing potential :err_record references
|
438
|
+
# @return [String] string with :err_record references replaced
|
439
|
+
def replace_last_record(input_string)
|
440
|
+
tmp = input_string
|
441
|
+
if @exception_manager.last_iterated_record != nil
|
442
|
+
@exception_manager.last_iterated_record.keys.sort.reverse.each do |k|
|
443
|
+
puts "replacing #{k}"
|
444
|
+
tmp = tmp.gsub(
|
445
|
+
":err_record.#{k}",
|
446
|
+
@exception_manager.last_iterated_record[k].to_s
|
447
|
+
)
|
448
|
+
end
|
449
|
+
end
|
450
|
+
tmp
|
451
|
+
end
|
452
|
+
|
453
|
+
# replaces text `:err_message` and `:err_type` with appropriate
|
454
|
+
# values from the pending error
|
455
|
+
# @param [String] input_string string containing potential err detail references
|
456
|
+
# @return [String] string with err details replaced
|
457
|
+
def replace_error_details(input_string)
|
458
|
+
tmp = input_string
|
459
|
+
tmp = tmp.gsub(
|
460
|
+
':err_message',
|
461
|
+
@exception_manager.pending_error.message.to_s
|
462
|
+
)
|
463
|
+
tmp = tmp.gsub(
|
464
|
+
':err_type',
|
465
|
+
@exception_manager.pending_error.class.to_s
|
466
|
+
)
|
342
467
|
end
|
343
468
|
end
|
344
469
|
end
|
@@ -7,7 +7,7 @@ module Sneaql
|
|
7
7
|
return d[:text] if jdbc_url.match(d[:text])
|
8
8
|
end
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
# Manages preferences for a specific RDBMS implementation.
|
12
12
|
class DatabaseManager
|
13
13
|
attr_reader(
|
@@ -19,7 +19,7 @@ module Sneaql
|
|
19
19
|
:commit_statement,
|
20
20
|
:rollback_statement
|
21
21
|
)
|
22
|
-
|
22
|
+
|
23
23
|
# @param [Hash] options values to override defaults
|
24
24
|
def initialize(options = {})
|
25
25
|
@has_boolean = options.fetch(:has_boolean, default_has_boolean)
|
@@ -30,17 +30,17 @@ module Sneaql
|
|
30
30
|
@commit_statement = options.fetch(:commit_statement, default_commit_statement)
|
31
31
|
@rollback_statement = options.fetch(:rollback_statement, default_rollback_statement)
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
# @return [Boolean]
|
35
35
|
def default_has_boolean
|
36
36
|
false
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
# @return [String]
|
40
40
|
def default_autocommit_off_statement
|
41
41
|
nil
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
# @return [Boolean]
|
45
45
|
def default_supports_transactions
|
46
46
|
true
|
@@ -50,7 +50,7 @@ module Sneaql
|
|
50
50
|
def default_supports_table_locking
|
51
51
|
false
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
# @return [String] begin statement
|
55
55
|
def default_begin_statement
|
56
56
|
"begin;"
|
@@ -60,12 +60,12 @@ module Sneaql
|
|
60
60
|
def default_commit_statement
|
61
61
|
"commit;"
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
# @return [String] rollback statement
|
65
65
|
def default_rollback_statement
|
66
66
|
"rollback;"
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
# @param [String] table_name
|
70
70
|
# @return [String] rollback statement
|
71
71
|
def lock_table_statement(table_name)
|
@@ -6,17 +6,16 @@ module Sneaql
|
|
6
6
|
:database,
|
7
7
|
'redshift',
|
8
8
|
Sneaql::Core::RedshiftDatabaseManager
|
9
|
-
)
|
10
|
-
|
11
|
-
def initialize
|
9
|
+
)
|
10
|
+
|
11
|
+
def initialize
|
12
12
|
super(
|
13
13
|
{
|
14
14
|
has_boolean: true,
|
15
15
|
autocommit_off_statement: 'set autocommit=off;'
|
16
16
|
}
|
17
|
-
)
|
17
|
+
)
|
18
18
|
end
|
19
|
-
|
20
19
|
end
|
21
20
|
end
|
22
|
-
end
|
21
|
+
end
|
@@ -6,16 +6,16 @@ module Sneaql
|
|
6
6
|
:database,
|
7
7
|
'vertica',
|
8
8
|
Sneaql::Core::VerticaDatabaseManager
|
9
|
-
)
|
10
|
-
|
9
|
+
)
|
10
|
+
|
11
11
|
def initialize
|
12
12
|
super(
|
13
13
|
{
|
14
14
|
has_boolean: true,
|
15
15
|
autocommit_off_statement: 'set session autocommit to off;'
|
16
16
|
}
|
17
|
-
)
|
17
|
+
)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
21
|
-
end
|
21
|
+
end
|
data/lib/sneaql_lib/docker.rb
CHANGED
@@ -3,26 +3,26 @@ require 'json'
|
|
3
3
|
module Sneaql
|
4
4
|
module Docker
|
5
5
|
class LocalTransformDockerfile
|
6
|
-
|
6
|
+
|
7
7
|
def initialize(repo_dir, repo_tag)
|
8
8
|
@repo_dir = repo_dir
|
9
9
|
@repo_tag = repo_tag
|
10
10
|
@steps = JSON.parse(
|
11
11
|
File.read("#{repo_dir}/sneaql.json")
|
12
12
|
)
|
13
|
-
|
13
|
+
|
14
14
|
create_step_files
|
15
15
|
create_dockerfile
|
16
16
|
end
|
17
|
-
|
18
|
-
def create_step_files
|
17
|
+
|
18
|
+
def create_step_files
|
19
19
|
@step_files = []
|
20
20
|
@step_files << {
|
21
21
|
docker_path: 'sneaql.json',
|
22
22
|
local_path: 'sneaql.json' #File.expand_path("#{repo_dir}/sneaql.json")
|
23
23
|
}
|
24
|
-
|
25
|
-
@steps.each { |s|
|
24
|
+
|
25
|
+
@steps.each { |s|
|
26
26
|
@step_files << {
|
27
27
|
docker_path: s['step_file'],
|
28
28
|
local_path: s['step_file'] # File.expand_path(s['step_file'])
|
@@ -30,9 +30,9 @@ module Sneaql
|
|
30
30
|
}
|
31
31
|
end
|
32
32
|
|
33
|
-
def dockerfile
|
33
|
+
def dockerfile
|
34
34
|
%{FROM full360/sneaql:latest
|
35
|
-
RUN mkdir /repo
|
35
|
+
RUN mkdir /repo
|
36
36
|
#{@step_files.map {|s| "ADD #{s[:local_path]} /repo/#{s[:docker_path]}"}.join("\n")}
|
37
37
|
}
|
38
38
|
end
|
@@ -56,4 +56,4 @@ RUN mkdir /repo
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
59
|
-
end
|
59
|
+
end
|
@@ -1,19 +1,39 @@
|
|
1
1
|
module Sneaql
|
2
2
|
# Exceptions for SneaQL
|
3
3
|
module Exceptions
|
4
|
+
class ExceptionManager
|
5
|
+
attr_accessor :pending_error
|
6
|
+
attr_accessor :last_iterated_record
|
7
|
+
|
8
|
+
def initialize(logger = nil)
|
9
|
+
@logger = logger ? logger : Logger.new(STDOUT)
|
10
|
+
end
|
11
|
+
|
12
|
+
def output_pending_error
|
13
|
+
@logger.error "pending error: #{@pending_error}" if @pending_error
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
4
17
|
# Base error class for Sneaql
|
5
18
|
class BaseError < StandardError; end
|
19
|
+
|
20
|
+
# Exception used to to gracefully exit test
|
21
|
+
class UnhandledException < BaseError
|
22
|
+
def initialize(msg = 'Previous error was not handled.')
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
6
26
|
|
7
27
|
# Exception used to to gracefully exit test
|
8
28
|
class SQLTestExitCondition < BaseError
|
9
|
-
def initialize(msg =
|
29
|
+
def initialize(msg = 'Exit condition met by test, this is not an error')
|
10
30
|
super
|
11
31
|
end
|
12
32
|
end
|
13
|
-
|
33
|
+
|
14
34
|
# Exception used to gracefully exit test step
|
15
35
|
class SQLTestStepExitCondition < BaseError
|
16
|
-
def initialize(msg =
|
36
|
+
def initialize(msg = 'Exit condition for this step has been met, this is not an error')
|
17
37
|
super
|
18
38
|
end
|
19
39
|
end
|
@@ -21,56 +41,56 @@ module Sneaql
|
|
21
41
|
# Transform is locked by another process. This is a
|
22
42
|
# possibility when using the LockManager
|
23
43
|
class TransformIsLocked < BaseError
|
24
|
-
def initialize(msg =
|
44
|
+
def initialize(msg = 'This transform is locked by another process')
|
25
45
|
super
|
26
46
|
end
|
27
47
|
end
|
28
48
|
|
29
49
|
# Recordset check failure indicator
|
30
50
|
class RecordsetContainsInconsistentOrInvalidTypes < BaseError
|
31
|
-
def initialize(msg =
|
51
|
+
def initialize(msg = 'Recordsets must have identical keys in every record')
|
32
52
|
super
|
33
53
|
end
|
34
54
|
end
|
35
|
-
|
55
|
+
|
36
56
|
# Recordset check failure indicator
|
37
57
|
class RecordsetIsNotAnArray < BaseError
|
38
|
-
def initialize(msg =
|
58
|
+
def initialize(msg = 'Recordset must be an array of hashes with identical keys')
|
39
59
|
super
|
40
60
|
end
|
41
61
|
end
|
42
62
|
|
43
|
-
# General error evaluating expression.
|
63
|
+
# General error evaluating expression.
|
44
64
|
class ExpressionEvaluationError < BaseError
|
45
|
-
def initialize(msg =
|
65
|
+
def initialize(msg = 'Error evaluating expression')
|
46
66
|
super
|
47
67
|
end
|
48
68
|
end
|
49
|
-
|
69
|
+
|
50
70
|
# Comparison operator must be explicitly supported.
|
51
71
|
class InvalidComparisonOperator < BaseError
|
52
|
-
def initialize(msg =
|
72
|
+
def initialize(msg = 'Invalid or no comparison operator provided')
|
53
73
|
super
|
54
74
|
end
|
55
75
|
end
|
56
|
-
|
76
|
+
|
57
77
|
# Error raised during parser validation process
|
58
78
|
class StatementParsingError < BaseError
|
59
|
-
def initialize(msg =
|
79
|
+
def initialize(msg = 'General error parsing Sneaql tag and statement')
|
60
80
|
super
|
61
81
|
end
|
62
82
|
end
|
63
|
-
|
83
|
+
|
64
84
|
# Sneaql step files must not be empty
|
65
85
|
class NoStatementsFoundInFile < BaseError
|
66
|
-
def initialize(msg =
|
86
|
+
def initialize(msg = 'No statements found in step file.')
|
67
87
|
super
|
68
88
|
end
|
69
89
|
end
|
70
90
|
|
71
91
|
# Sneaql command tags must be formed correctly
|
72
92
|
class MalformedSneaqlCommandsInStep < BaseError
|
73
|
-
def initialize(msg =
|
93
|
+
def initialize(msg = 'Sneaql command tag is malformed.')
|
74
94
|
super
|
75
95
|
end
|
76
96
|
end
|