sqlfinder 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.txt +48 -0
- data/Rakefile +5 -0
- data/bin/findsql +23 -0
- data/lib/sqlfinder/application.rb +110 -0
- data/lib/sqlfinder/find.rb +59 -0
- data/lib/sqlfinder.rb +1 -0
- data/sqlfinder.gemspec +16 -0
- data/test/test_sql_finder.rb +429 -0
- data/test/test_sql_regex.rb +302 -0
- metadata +59 -0
data/README.txt
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
= SQL Finder
|
2
|
+
|
3
|
+
SQL Finder is an executable gem that finds designated SQL statements in log/trace files.
|
4
|
+
|
5
|
+
== Use Case
|
6
|
+
|
7
|
+
Developers often have to comb through enormous log or trace files for SQL statements.
|
8
|
+
At one company, for example, the only way for developers to determine what SQL statements
|
9
|
+
a large banking application is generating is to examine the application's (often enormous)
|
10
|
+
trace files. SQL Finder makes this process much easier by automatically doing a
|
11
|
+
case-insensitive search for SQL statements.
|
12
|
+
|
13
|
+
== Running the program
|
14
|
+
|
15
|
+
Run the executable from a directory of your choice using the findsql command together
|
16
|
+
with a path to the log/trace file under consideration:
|
17
|
+
|
18
|
+
findsql logs/ep_trace.txt
|
19
|
+
|
20
|
+
By default, SQL Finder searches for all lines with SELECT,INSERT, UPDATE, or DELETE
|
21
|
+
keywords in them, capturing the SQL statements and writing them to STDOUT along with the line number.
|
22
|
+
Command line options make it possible to limit the search to a subset of keywords,
|
23
|
+
to search for statements involving a particular table, or both.
|
24
|
+
|
25
|
+
== Command Line Options
|
26
|
+
|
27
|
+
<tt>-h</tt>:: Help screen.
|
28
|
+
<tt>-o <file name></tt>:: Tells SQL finder to write the captured statements to the indicated file instead of SDTOUT
|
29
|
+
<tt>-t <table_name></tt>:: Tells SQL Finder to capture SQL statements only if they contain the table name indicated
|
30
|
+
<tt>-k <list of keywords></tt>:: Given a comma-separated set of SQL statements, SQL Finder will capture statements only if they contain one of the indicated keywords
|
31
|
+
|
32
|
+
Here are some sample commands:
|
33
|
+
|
34
|
+
findsql -o trace.out ep_trace.txt
|
35
|
+
|
36
|
+
* Writes the results to trace.out instead of STDOUT
|
37
|
+
|
38
|
+
findsql -t arcconfiguration ep_trace.txt
|
39
|
+
|
40
|
+
* Restricts the search to SELECT, INSERT, UPDATE, and DELETE statements for the ArcConfiguration table
|
41
|
+
|
42
|
+
findsql -k select,insert ep_trace.txt
|
43
|
+
|
44
|
+
* Restricts the search to SELECT and INSERT statements.
|
45
|
+
|
46
|
+
findsql -k select,insert -t arcconfiguration -o trace.out ep_trace.txt
|
47
|
+
|
48
|
+
* Writes all SELECT and INSERT statements for the ArcConfiguration table to
|
data/Rakefile
ADDED
data/bin/findsql
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!usr/bin/env ruby
|
2
|
+
|
3
|
+
##############################################################
|
4
|
+
# Copyright (c) 2012 Mark Buechler
|
5
|
+
# All rights reserved.
|
6
|
+
|
7
|
+
# Permission is granted for use, copying, modification, distribution,
|
8
|
+
# and distribution of modified versions of this work as long as the
|
9
|
+
# above copyright notice is included.
|
10
|
+
##############################################################
|
11
|
+
|
12
|
+
##############################################################
|
13
|
+
#Run this executable to find SQL statements in log files
|
14
|
+
##############################################################
|
15
|
+
|
16
|
+
require 'sqlfinder'
|
17
|
+
|
18
|
+
begin
|
19
|
+
SqlFinder::Application.new.run
|
20
|
+
rescue => e
|
21
|
+
puts "Error: #{e.message}"
|
22
|
+
exit 1
|
23
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'sqlfinder/find'
|
3
|
+
|
4
|
+
module SqlFinder
|
5
|
+
|
6
|
+
#Parses and validates command line options and runs the application.
|
7
|
+
class Application
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
prepare_options
|
11
|
+
validate_options
|
12
|
+
end
|
13
|
+
|
14
|
+
#Parses command line options
|
15
|
+
def prepare_options
|
16
|
+
@options = {}
|
17
|
+
OptionParser.new do |opts|
|
18
|
+
opts.banner = "usage: #{File.basename(__FILE__)} [options] file_to_search"
|
19
|
+
opts.on("-h", "--help", "Display help screen.") do
|
20
|
+
puts opts
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
opts.on("-k", "--keywords KEYWORDS", Array, "Using a comma-separated list, indicate whether you want to search for SELECT, INSERT, UPDATE, and/or DELETE statements (case-insensitive). By default, sqlfinder will search for all of them.") do |keywords|
|
24
|
+
@options[:keywords] = keywords
|
25
|
+
end
|
26
|
+
opts.on("-t", "--table_name TABLE_NAME", "Indicate whether you want to restrict your search to a single table (case-insensitive).") do |t|
|
27
|
+
@options[:table_name] = t
|
28
|
+
end
|
29
|
+
opts.on("-o", "--output_file OUTPUT_FILE", "If you want to write the results to a file rather than to standard out, provide the output file name.") do |o|
|
30
|
+
@options[:output_file] = o
|
31
|
+
end
|
32
|
+
end.parse!
|
33
|
+
@file_to_search = ARGV[0]
|
34
|
+
end
|
35
|
+
|
36
|
+
#Manages option validation
|
37
|
+
def validate_options
|
38
|
+
validate_required_options
|
39
|
+
validate_keywords
|
40
|
+
validate_file_to_search
|
41
|
+
end
|
42
|
+
|
43
|
+
#Ensures that required options are in place
|
44
|
+
def validate_required_options
|
45
|
+
missing_arg = false
|
46
|
+
if ( @options[:table_name] && (@options[:table_name].start_with?("-")) )
|
47
|
+
raise "If you use the -t option, you must provide a table name."
|
48
|
+
elsif ( @options[:output_file] && (@options[:output_file].start_with?("-")) )
|
49
|
+
raise "If you use the -o option, you must provide an output file name."
|
50
|
+
elsif (@options[:keywords] && @options[:keywords][0] && (@options[:keywords][0].start_with?("-")))
|
51
|
+
raise "If you use the -k option, you must provide at least one of the following SQL keywords (ignoring case): SELECT, INSERT, UPDATE, and DELETE."
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
#Ensures that we have no duplicate SQL keywords
|
56
|
+
def validate_keywords
|
57
|
+
if @options[:keywords]
|
58
|
+
duplicate_checker = []
|
59
|
+
if @options[:keywords].size > 4
|
60
|
+
raise "The maximum number of keywords is 4. Valid keywords include(ignoring case): SELECT, INSERT, UPDATE, and DELETE."
|
61
|
+
end
|
62
|
+
@options[:keywords].each do |keyword|
|
63
|
+
if !(keyword.match (/(?:select)|(?:insert)|(?:update)|(?:delete)/i))
|
64
|
+
raise "All keywords must match one of the following (ignoring case): SELECT, INSERT, UPDATE, and DELETE. Your keyword \"#{keyword}\" did not match."
|
65
|
+
end
|
66
|
+
duplicate_checker.each do |keyword2|
|
67
|
+
if (keyword.downcase == keyword2.downcase)
|
68
|
+
raise "You used the keyword \"#{keyword}\" more than once."
|
69
|
+
end
|
70
|
+
end
|
71
|
+
duplicate_checker << keyword
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
#Ensures that the file exists
|
77
|
+
def validate_file_to_search
|
78
|
+
if !@file_to_search
|
79
|
+
raise "Please provide the name of the file to search as a command-line argument."
|
80
|
+
end
|
81
|
+
if !(File.file?(@file_to_search))
|
82
|
+
raise "The file to search does not exist: #{@file_to_search}."
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
#Executes the program
|
87
|
+
def run
|
88
|
+
input_file_handle = File.new(@file_to_search)
|
89
|
+
output_file_handle = STDOUT
|
90
|
+
is_std_out = true;
|
91
|
+
if @options[:output_file]
|
92
|
+
output_file_handle = File.new((@options[:output_file]), "w")
|
93
|
+
is_std_out = false;
|
94
|
+
end
|
95
|
+
keywords = @options[:keywords]
|
96
|
+
table_name = @options[:table_name]
|
97
|
+
SqlFinder::Find.run do
|
98
|
+
@input_file_handle = input_file_handle
|
99
|
+
@output_file_handle = output_file_handle
|
100
|
+
@keywords = keywords
|
101
|
+
@table_name = table_name
|
102
|
+
do_find
|
103
|
+
end
|
104
|
+
input_file_handle.close()
|
105
|
+
output_file_handle.close() unless is_std_out
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module SqlFinder
|
2
|
+
|
3
|
+
#Using the options initialized by the block passed to the run method,
|
4
|
+
#this class builds a regular expression and applies it to the input file handle.
|
5
|
+
#All lines that match are written to the output file handle.
|
6
|
+
class Find
|
7
|
+
|
8
|
+
KEYWORD_REGEX_CONTENT_MAP = {
|
9
|
+
"select" => "(\\bselect\\b.+from.+)",
|
10
|
+
"delete" => "(\\bdelete\\b.+from.+)",
|
11
|
+
"insert" => "(\\binsert\\b.+into.+)",
|
12
|
+
"update" => "(\\bupdate\\b.+set.+)",
|
13
|
+
"update_with_table" => "(\\bupdate\\b.+)"
|
14
|
+
}
|
15
|
+
|
16
|
+
#Expects a block that defines instance variables and calls the do_find method.
|
17
|
+
#For example:
|
18
|
+
# SqlFinder::Find.run do
|
19
|
+
# @input_file_handle = input_file_handle
|
20
|
+
# @output_file_handle = output_file_handle
|
21
|
+
# @keywords = keywords
|
22
|
+
# @table_name = table_name
|
23
|
+
# do_find
|
24
|
+
#end
|
25
|
+
def self.run(&b)
|
26
|
+
finder = SqlFinder::Find.new
|
27
|
+
finder.instance_eval(&b)
|
28
|
+
end
|
29
|
+
|
30
|
+
#Dynamically builds the regular expression, uses it to search the file,
|
31
|
+
#and prints the results to the output file handle
|
32
|
+
def do_find
|
33
|
+
unless (@keywords && (@keywords.size > 0))
|
34
|
+
@keywords = %w[select delete insert update]
|
35
|
+
end
|
36
|
+
keyword_regex = build_keyword_regex_content()
|
37
|
+
regex = /^.*((#{keyword_regex})\b#{@table_name}\b.*)/i
|
38
|
+
@input_file_handle.each do |line|
|
39
|
+
m = line.match(regex)
|
40
|
+
@output_file_handle.puts "#{$.}: #{m[1]}" if m
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
#Dynamically builds the keyword component of the regular expression
|
45
|
+
def build_keyword_regex_content
|
46
|
+
regex_content_array = []
|
47
|
+
@keywords.each do |keyword|
|
48
|
+
key = keyword.downcase
|
49
|
+
if ((key == "update") && @table_name) #potentially a special case
|
50
|
+
key << "_with_table"
|
51
|
+
end
|
52
|
+
regex_content_array << KEYWORD_REGEX_CONTENT_MAP[key]
|
53
|
+
end
|
54
|
+
return regex_content_array.join "|"
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
data/lib/sqlfinder.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'sqlfinder/application'
|
data/sqlfinder.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name="sqlfinder"
|
3
|
+
s.version="0.0.5"
|
4
|
+
s.platform=Gem::Platform::RUBY
|
5
|
+
s.date="2012-11-03"
|
6
|
+
s.summary="Finds SQL statements in log files"
|
7
|
+
s.description="sqlfinder finds SQL statements in log or trace files. With command line options, users indicate whether they want to search for all SQL statements (SELECT, INSERT, UPDATE, DELETE), selected SQL statements, and/or selected tables."
|
8
|
+
s.author="Mark Buechler"
|
9
|
+
s.files=Dir["sqlfinder.gemspec", "Rakefile", "README.txt", "lib/**/*", "test/test*.rb"]
|
10
|
+
s.homepage="http://rubygems.org/sqlfinder"
|
11
|
+
s.executables=["findsql"]
|
12
|
+
s.require_paths=["lib"]
|
13
|
+
s.has_rdoc=true
|
14
|
+
s.extra_rdoc_files=["README.txt"]
|
15
|
+
s.rdoc_options=["--main", "README.txt"]
|
16
|
+
end
|
@@ -0,0 +1,429 @@
|
|
1
|
+
#run with lib directory in load path to simulate gem runtime environment
|
2
|
+
#ruby -I. -Ilib test/test_sql_finder.rb
|
3
|
+
|
4
|
+
require 'test/unit'
|
5
|
+
require 'sqlfinder/find'
|
6
|
+
require 'stringio'
|
7
|
+
|
8
|
+
#NOTE: The SqlFinder::Find class prints the line number at the beginning of each line
|
9
|
+
#it finds, using $. StringIO apparently registers this as 0 for each line returned.
|
10
|
+
#Hence the "0: " string that appears at the beginning of each expected_match line.
|
11
|
+
class SqlFinderTest < Test::Unit::TestCase
|
12
|
+
|
13
|
+
TEST_FILE = <<EOS
|
14
|
+
PersistencePreparedStatement.executeQuery(Connection con)|executing: Prepared: SELECT U.BNKUserKy, U.BNKPersonKy, U.BNKCustomerKy, U.BNKTimezoneKy, U.ARCPrincipalKy, U.ARCLocaleCdKy, U.givenName, U.middleName, U.familyName, U.titleEnum, U.suffixEnum, U.taxId, U.primaryPhoneNbr, U.secondaryPhoneNbr, U.primaryFaxNbr, U.emailAddress, U.jobTitle, U.approvalStatus, U.isBankUser, U.isActive, U.isCmpSysAdmin, U.isDlvrReqEntitled, U.isDeleted, U.isConfidentialBatch, U.isConfScrnEnabled, U.exitURL, U.defaultScreen, U.enrollDttm, U.entUpdateDttm, U.entUpdateUser, U.updateDttm, U.updateUser, U.versionStamp, P.name, I.userId, I.ARCIdentityKy,U.userAccessTypeCD,U.userLimitsTypeCD, U.LSTUSRSETUPFLWCD FROM BNKUser U, ARCPrincipal P, ARCIdentity I WHERE P.ARCPrincipalKy = U.ARCPrincipalKy AND I.ARCPrincipalKy = U.ARCPrincipalKy AND I.userId = ? ('CBuser15@CB10015')
|
15
|
+
PersistenceUtils.closeStuff(Connection con, Statement st, ResultSet rs)|
|
16
|
+
QueryCommand.execute()
|
17
|
+
PersistenceNonPreparedStatement.executeQuery(Connection con)|executing: NonPrepared: SELECT ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm FROM ARCConfiguration WHERE Domain = 'IRExport'
|
18
|
+
UpdateDatabaseSqlExecutor.invokeExecutor(PersistencePeer peer, PersistenceStatement stmt, List objs)|26|0|1 rows affected|Prepared: INSERT INTO BNKLimitStatus (BNKLimitStatusKy, BNKInstrKy, BNKLimitTypeKy, amount, ARCISOCURRENCYCDKY, userLoginId, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) (234001, 1002001, 1, 1.000, 169, 'CBuser10@CB10010', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
19
|
+
UpdateDatabaseSqlExecutor.invokeExecutor(PersistencePeer peer, PersistenceStatement stmt, List objs)|26|0|1 rows affected|Prepared: INSERT INTO ARCConfiguration (ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?) (234001, 'exitUrl', 's1', 'bank', 'app', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
20
|
+
QueryCommand.execute()
|
21
|
+
PersistencePreparedStatement.executeQuery(Connection con)|executing: Prepared: update ARCUserAuthnticn SET pswdexpirydttm = '2030-05-05 00:00:00.0'
|
22
|
+
PersistencePreparedStatement.executeQuery(Connection con)|executing: Prepared: delete from BNKACCTALTIDFR where BNKACCTky = 2
|
23
|
+
QueryCommand.delete()
|
24
|
+
EOS
|
25
|
+
|
26
|
+
#TEST KEYWORDS ONLY
|
27
|
+
|
28
|
+
def test_keyword_select
|
29
|
+
|
30
|
+
expected_match = <<EOS
|
31
|
+
0: SELECT U.BNKUserKy, U.BNKPersonKy, U.BNKCustomerKy, U.BNKTimezoneKy, U.ARCPrincipalKy, U.ARCLocaleCdKy, U.givenName, U.middleName, U.familyName, U.titleEnum, U.suffixEnum, U.taxId, U.primaryPhoneNbr, U.secondaryPhoneNbr, U.primaryFaxNbr, U.emailAddress, U.jobTitle, U.approvalStatus, U.isBankUser, U.isActive, U.isCmpSysAdmin, U.isDlvrReqEntitled, U.isDeleted, U.isConfidentialBatch, U.isConfScrnEnabled, U.exitURL, U.defaultScreen, U.enrollDttm, U.entUpdateDttm, U.entUpdateUser, U.updateDttm, U.updateUser, U.versionStamp, P.name, I.userId, I.ARCIdentityKy,U.userAccessTypeCD,U.userLimitsTypeCD, U.LSTUSRSETUPFLWCD FROM BNKUser U, ARCPrincipal P, ARCIdentity I WHERE P.ARCPrincipalKy = U.ARCPrincipalKy AND I.ARCPrincipalKy = U.ARCPrincipalKy AND I.userId = ? ('CBuser15@CB10015')
|
32
|
+
0: SELECT ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm FROM ARCConfiguration WHERE Domain = 'IRExport'
|
33
|
+
EOS
|
34
|
+
|
35
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
36
|
+
simulated_output_file_handle = StringIO.new
|
37
|
+
SqlFinder::Find.run do
|
38
|
+
@input_file_handle = simulated_input_file_handle
|
39
|
+
@output_file_handle = simulated_output_file_handle
|
40
|
+
@keywords = ["select"]
|
41
|
+
do_find
|
42
|
+
end
|
43
|
+
simulated_input_file_handle.close()
|
44
|
+
simulated_output_file_handle.close()
|
45
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_keyword_insert
|
50
|
+
|
51
|
+
expected_match = <<EOS
|
52
|
+
0: INSERT INTO BNKLimitStatus (BNKLimitStatusKy, BNKInstrKy, BNKLimitTypeKy, amount, ARCISOCURRENCYCDKY, userLoginId, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) (234001, 1002001, 1, 1.000, 169, 'CBuser10@CB10010', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
53
|
+
0: INSERT INTO ARCConfiguration (ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?) (234001, 'exitUrl', 's1', 'bank', 'app', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
54
|
+
EOS
|
55
|
+
|
56
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
57
|
+
simulated_output_file_handle = StringIO.new
|
58
|
+
SqlFinder::Find.run do
|
59
|
+
@input_file_handle = simulated_input_file_handle
|
60
|
+
@output_file_handle = simulated_output_file_handle
|
61
|
+
@keywords = ["INSERT"]
|
62
|
+
do_find
|
63
|
+
end
|
64
|
+
simulated_input_file_handle.close()
|
65
|
+
simulated_output_file_handle.close()
|
66
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def test_keyword_update
|
71
|
+
|
72
|
+
expected_match = <<EOS
|
73
|
+
0: update ARCUserAuthnticn SET pswdexpirydttm = '2030-05-05 00:00:00.0'
|
74
|
+
EOS
|
75
|
+
|
76
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
77
|
+
simulated_output_file_handle = StringIO.new
|
78
|
+
SqlFinder::Find.run do
|
79
|
+
@input_file_handle = simulated_input_file_handle
|
80
|
+
@output_file_handle = simulated_output_file_handle
|
81
|
+
@keywords = ["upDATE"]
|
82
|
+
do_find
|
83
|
+
end
|
84
|
+
simulated_input_file_handle.close()
|
85
|
+
simulated_output_file_handle.close()
|
86
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_keyword_delete
|
90
|
+
|
91
|
+
expected_match = <<EOS
|
92
|
+
0: delete from BNKACCTALTIDFR where BNKACCTky = 2
|
93
|
+
EOS
|
94
|
+
|
95
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
96
|
+
simulated_output_file_handle = StringIO.new
|
97
|
+
SqlFinder::Find.run do
|
98
|
+
@input_file_handle = simulated_input_file_handle
|
99
|
+
@output_file_handle = simulated_output_file_handle
|
100
|
+
@keywords = ["DELETE"]
|
101
|
+
do_find
|
102
|
+
end
|
103
|
+
simulated_input_file_handle.close()
|
104
|
+
simulated_output_file_handle.close()
|
105
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_keywords_select_insert
|
109
|
+
|
110
|
+
expected_match = <<EOS
|
111
|
+
0: SELECT U.BNKUserKy, U.BNKPersonKy, U.BNKCustomerKy, U.BNKTimezoneKy, U.ARCPrincipalKy, U.ARCLocaleCdKy, U.givenName, U.middleName, U.familyName, U.titleEnum, U.suffixEnum, U.taxId, U.primaryPhoneNbr, U.secondaryPhoneNbr, U.primaryFaxNbr, U.emailAddress, U.jobTitle, U.approvalStatus, U.isBankUser, U.isActive, U.isCmpSysAdmin, U.isDlvrReqEntitled, U.isDeleted, U.isConfidentialBatch, U.isConfScrnEnabled, U.exitURL, U.defaultScreen, U.enrollDttm, U.entUpdateDttm, U.entUpdateUser, U.updateDttm, U.updateUser, U.versionStamp, P.name, I.userId, I.ARCIdentityKy,U.userAccessTypeCD,U.userLimitsTypeCD, U.LSTUSRSETUPFLWCD FROM BNKUser U, ARCPrincipal P, ARCIdentity I WHERE P.ARCPrincipalKy = U.ARCPrincipalKy AND I.ARCPrincipalKy = U.ARCPrincipalKy AND I.userId = ? ('CBuser15@CB10015')
|
112
|
+
0: SELECT ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm FROM ARCConfiguration WHERE Domain = 'IRExport'
|
113
|
+
0: INSERT INTO BNKLimitStatus (BNKLimitStatusKy, BNKInstrKy, BNKLimitTypeKy, amount, ARCISOCURRENCYCDKY, userLoginId, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) (234001, 1002001, 1, 1.000, 169, 'CBuser10@CB10010', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
114
|
+
0: INSERT INTO ARCConfiguration (ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?) (234001, 'exitUrl', 's1', 'bank', 'app', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
115
|
+
EOS
|
116
|
+
|
117
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
118
|
+
simulated_output_file_handle = StringIO.new
|
119
|
+
SqlFinder::Find.run do
|
120
|
+
@input_file_handle = simulated_input_file_handle
|
121
|
+
@output_file_handle = simulated_output_file_handle
|
122
|
+
@keywords = %w[select insert]
|
123
|
+
do_find
|
124
|
+
end
|
125
|
+
simulated_input_file_handle.close()
|
126
|
+
simulated_output_file_handle.close()
|
127
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_keywords_insert_update_delete
|
131
|
+
|
132
|
+
expected_match = <<EOS
|
133
|
+
0: INSERT INTO BNKLimitStatus (BNKLimitStatusKy, BNKInstrKy, BNKLimitTypeKy, amount, ARCISOCURRENCYCDKY, userLoginId, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) (234001, 1002001, 1, 1.000, 169, 'CBuser10@CB10010', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
134
|
+
0: INSERT INTO ARCConfiguration (ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?) (234001, 'exitUrl', 's1', 'bank', 'app', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
135
|
+
0: update ARCUserAuthnticn SET pswdexpirydttm = '2030-05-05 00:00:00.0'
|
136
|
+
0: delete from BNKACCTALTIDFR where BNKACCTky = 2
|
137
|
+
EOS
|
138
|
+
|
139
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
140
|
+
simulated_output_file_handle = StringIO.new
|
141
|
+
SqlFinder::Find.run do
|
142
|
+
@input_file_handle = simulated_input_file_handle
|
143
|
+
@output_file_handle = simulated_output_file_handle
|
144
|
+
@keywords = %w[insert update delete]
|
145
|
+
do_find
|
146
|
+
end
|
147
|
+
simulated_input_file_handle.close()
|
148
|
+
simulated_output_file_handle.close()
|
149
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_all_keywords
|
153
|
+
|
154
|
+
expected_match = <<EOS
|
155
|
+
0: SELECT U.BNKUserKy, U.BNKPersonKy, U.BNKCustomerKy, U.BNKTimezoneKy, U.ARCPrincipalKy, U.ARCLocaleCdKy, U.givenName, U.middleName, U.familyName, U.titleEnum, U.suffixEnum, U.taxId, U.primaryPhoneNbr, U.secondaryPhoneNbr, U.primaryFaxNbr, U.emailAddress, U.jobTitle, U.approvalStatus, U.isBankUser, U.isActive, U.isCmpSysAdmin, U.isDlvrReqEntitled, U.isDeleted, U.isConfidentialBatch, U.isConfScrnEnabled, U.exitURL, U.defaultScreen, U.enrollDttm, U.entUpdateDttm, U.entUpdateUser, U.updateDttm, U.updateUser, U.versionStamp, P.name, I.userId, I.ARCIdentityKy,U.userAccessTypeCD,U.userLimitsTypeCD, U.LSTUSRSETUPFLWCD FROM BNKUser U, ARCPrincipal P, ARCIdentity I WHERE P.ARCPrincipalKy = U.ARCPrincipalKy AND I.ARCPrincipalKy = U.ARCPrincipalKy AND I.userId = ? ('CBuser15@CB10015')
|
156
|
+
0: SELECT ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm FROM ARCConfiguration WHERE Domain = 'IRExport'
|
157
|
+
0: INSERT INTO BNKLimitStatus (BNKLimitStatusKy, BNKInstrKy, BNKLimitTypeKy, amount, ARCISOCURRENCYCDKY, userLoginId, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) (234001, 1002001, 1, 1.000, 169, 'CBuser10@CB10010', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
158
|
+
0: INSERT INTO ARCConfiguration (ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?) (234001, 'exitUrl', 's1', 'bank', 'app', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
159
|
+
0: update ARCUserAuthnticn SET pswdexpirydttm = '2030-05-05 00:00:00.0'
|
160
|
+
0: delete from BNKACCTALTIDFR where BNKACCTky = 2
|
161
|
+
EOS
|
162
|
+
|
163
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
164
|
+
simulated_output_file_handle = StringIO.new
|
165
|
+
SqlFinder::Find.run do
|
166
|
+
@input_file_handle = simulated_input_file_handle
|
167
|
+
@output_file_handle = simulated_output_file_handle
|
168
|
+
@keywords = %w[select insert update delete]
|
169
|
+
@table_name = ""
|
170
|
+
do_find
|
171
|
+
end
|
172
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
173
|
+
end
|
174
|
+
|
175
|
+
#if there are no keywords, by default the sql finder uses all keywords
|
176
|
+
def test_no_keywords_same_as_all_keywords
|
177
|
+
|
178
|
+
expected_match = <<EOS
|
179
|
+
0: SELECT U.BNKUserKy, U.BNKPersonKy, U.BNKCustomerKy, U.BNKTimezoneKy, U.ARCPrincipalKy, U.ARCLocaleCdKy, U.givenName, U.middleName, U.familyName, U.titleEnum, U.suffixEnum, U.taxId, U.primaryPhoneNbr, U.secondaryPhoneNbr, U.primaryFaxNbr, U.emailAddress, U.jobTitle, U.approvalStatus, U.isBankUser, U.isActive, U.isCmpSysAdmin, U.isDlvrReqEntitled, U.isDeleted, U.isConfidentialBatch, U.isConfScrnEnabled, U.exitURL, U.defaultScreen, U.enrollDttm, U.entUpdateDttm, U.entUpdateUser, U.updateDttm, U.updateUser, U.versionStamp, P.name, I.userId, I.ARCIdentityKy,U.userAccessTypeCD,U.userLimitsTypeCD, U.LSTUSRSETUPFLWCD FROM BNKUser U, ARCPrincipal P, ARCIdentity I WHERE P.ARCPrincipalKy = U.ARCPrincipalKy AND I.ARCPrincipalKy = U.ARCPrincipalKy AND I.userId = ? ('CBuser15@CB10015')
|
180
|
+
0: SELECT ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm FROM ARCConfiguration WHERE Domain = 'IRExport'
|
181
|
+
0: INSERT INTO BNKLimitStatus (BNKLimitStatusKy, BNKInstrKy, BNKLimitTypeKy, amount, ARCISOCURRENCYCDKY, userLoginId, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) (234001, 1002001, 1, 1.000, 169, 'CBuser10@CB10010', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
182
|
+
0: INSERT INTO ARCConfiguration (ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?) (234001, 'exitUrl', 's1', 'bank', 'app', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
183
|
+
0: update ARCUserAuthnticn SET pswdexpirydttm = '2030-05-05 00:00:00.0'
|
184
|
+
0: delete from BNKACCTALTIDFR where BNKACCTky = 2
|
185
|
+
EOS
|
186
|
+
|
187
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
188
|
+
simulated_output_file_handle = StringIO.new
|
189
|
+
SqlFinder::Find.run do
|
190
|
+
@input_file_handle = simulated_input_file_handle
|
191
|
+
@output_file_handle = simulated_output_file_handle
|
192
|
+
@keywords = nil
|
193
|
+
@table_name = ""
|
194
|
+
do_find
|
195
|
+
end
|
196
|
+
simulated_input_file_handle.close()
|
197
|
+
simulated_output_file_handle.close()
|
198
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
199
|
+
end
|
200
|
+
|
201
|
+
#making sure we handle misses properly
|
202
|
+
def test_keyword_select_miss
|
203
|
+
|
204
|
+
no_select_file = <<EOS
|
205
|
+
0: QueryCommand.execute()
|
206
|
+
0: UpdateDatabaseSqlExecutor.invokeExecutor(PersistencePeer peer, PersistenceStatement stmt, List objs)|26|0|1 rows affected|Prepared: INSERT INTO BNKLimitStatus (BNKLimitStatusKy, BNKInstrKy, BNKLimitTypeKy, amount, ARCISOCURRENCYCDKY, userLoginId, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) (234001, 1002001, 1, 1.000, 169, 'CBuser10@CB10010', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
207
|
+
0: UpdateDatabaseSqlExecutor.invokeExecutor(PersistencePeer peer, PersistenceStatement stmt, List objs)|26|0|1 rows affected|Prepared: INSERT INTO ARCConfiguration (ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?) (234001, 'exitUrl', 's1', 'bank', 'app', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
208
|
+
0: QueryCommand.execute()
|
209
|
+
0: PersistencePreparedStatement.executeQuery(Connection con)|executing: Prepared: update ARCUserAuthnticn SET pswdexpirydttm = '2030-05-05 00:00:00.0'
|
210
|
+
0: PersistencePreparedStatement.executeQuery(Connection con)|executing: Prepared: delete from BNKACCTALTIDFR where BNKACCTky = 2
|
211
|
+
0: QueryCommand.delete()
|
212
|
+
EOS
|
213
|
+
|
214
|
+
expected_match = ""
|
215
|
+
simulated_input_file_handle = StringIO.new(no_select_file)
|
216
|
+
simulated_output_file_handle = StringIO.new
|
217
|
+
SqlFinder::Find.run do
|
218
|
+
@input_file_handle = simulated_input_file_handle
|
219
|
+
@output_file_handle = simulated_output_file_handle
|
220
|
+
@keywords = ["SELECT"]
|
221
|
+
do_find
|
222
|
+
end
|
223
|
+
simulated_input_file_handle.close()
|
224
|
+
simulated_output_file_handle.close()
|
225
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
226
|
+
end
|
227
|
+
|
228
|
+
#TEST TABLE NAME ONLY (uses all keywords by default)
|
229
|
+
|
230
|
+
def test_table_name_only
|
231
|
+
|
232
|
+
expected_match = <<EOS
|
233
|
+
0: SELECT ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm FROM ARCConfiguration WHERE Domain = 'IRExport'
|
234
|
+
0: INSERT INTO ARCConfiguration (ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?) (234001, 'exitUrl', 's1', 'bank', 'app', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
235
|
+
EOS
|
236
|
+
|
237
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
238
|
+
simulated_output_file_handle = StringIO.new
|
239
|
+
SqlFinder::Find.run do
|
240
|
+
@input_file_handle = simulated_input_file_handle
|
241
|
+
@output_file_handle = simulated_output_file_handle
|
242
|
+
@table_name = "ARCConfiguration"
|
243
|
+
do_find
|
244
|
+
end
|
245
|
+
simulated_input_file_handle.close()
|
246
|
+
simulated_output_file_handle.close()
|
247
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
248
|
+
end
|
249
|
+
|
250
|
+
def test_table_name_only_miss
|
251
|
+
|
252
|
+
expected_match = ""
|
253
|
+
|
254
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
255
|
+
simulated_output_file_handle = StringIO.new
|
256
|
+
SqlFinder::Find.run do
|
257
|
+
@input_file_handle = simulated_input_file_handle
|
258
|
+
@output_file_handle = simulated_output_file_handle
|
259
|
+
@table_name = "BNKCountry"
|
260
|
+
do_find
|
261
|
+
end
|
262
|
+
simulated_input_file_handle.close()
|
263
|
+
simulated_output_file_handle.close()
|
264
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
265
|
+
end
|
266
|
+
|
267
|
+
#if we're searching for a table_name of, say BNKUser,
|
268
|
+
#we don't want hits on tables with names such as BNKUserHistory or VfmBNKUser;
|
269
|
+
#we want exact matches (hence the use of word boundaries)
|
270
|
+
def test_miss_on_partial_table_name
|
271
|
+
|
272
|
+
expected_match = ""
|
273
|
+
|
274
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
275
|
+
simulated_output_file_handle = StringIO.new
|
276
|
+
SqlFinder::Find.run do
|
277
|
+
@input_file_handle = simulated_input_file_handle
|
278
|
+
@output_file_handle = simulated_output_file_handle
|
279
|
+
@table_name = "ARCConfig" #actual name is ARCConfigation
|
280
|
+
do_find
|
281
|
+
end
|
282
|
+
simulated_input_file_handle.close()
|
283
|
+
simulated_output_file_handle.close()
|
284
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
285
|
+
|
286
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
287
|
+
simulated_output_file_handle = StringIO.new
|
288
|
+
SqlFinder::Find.run do
|
289
|
+
@input_file_handle = simulated_input_file_handle
|
290
|
+
@output_file_handle = simulated_output_file_handle
|
291
|
+
@table_name = "ARCConfigationHistory" #actual name is ARCConfigation
|
292
|
+
do_find
|
293
|
+
end
|
294
|
+
simulated_input_file_handle.close()
|
295
|
+
simulated_output_file_handle.close()
|
296
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
297
|
+
|
298
|
+
end
|
299
|
+
|
300
|
+
|
301
|
+
#TEST TABLE NAME AND KEYWORDS
|
302
|
+
|
303
|
+
def test_table_name_with_single_keyword_select
|
304
|
+
|
305
|
+
expected_match = <<EOS
|
306
|
+
0: SELECT ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm FROM ARCConfiguration WHERE Domain = 'IRExport'
|
307
|
+
EOS
|
308
|
+
|
309
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
310
|
+
simulated_output_file_handle = StringIO.new
|
311
|
+
SqlFinder::Find.run do
|
312
|
+
@input_file_handle = simulated_input_file_handle
|
313
|
+
@output_file_handle = simulated_output_file_handle
|
314
|
+
@keywords = ["select"]
|
315
|
+
@table_name = "ARCConfiguration"
|
316
|
+
do_find
|
317
|
+
end
|
318
|
+
simulated_input_file_handle.close()
|
319
|
+
simulated_output_file_handle.close()
|
320
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
321
|
+
end
|
322
|
+
|
323
|
+
def test_table_name_with_single_keyword_insert
|
324
|
+
|
325
|
+
expected_match = <<EOS
|
326
|
+
0: INSERT INTO ARCConfiguration (ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?) (234001, 'exitUrl', 's1', 'bank', 'app', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
327
|
+
EOS
|
328
|
+
|
329
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
330
|
+
simulated_output_file_handle = StringIO.new
|
331
|
+
SqlFinder::Find.run do
|
332
|
+
@input_file_handle = simulated_input_file_handle
|
333
|
+
@output_file_handle = simulated_output_file_handle
|
334
|
+
@keywords = ["insert"]
|
335
|
+
@table_name = "ARCConfiguration"
|
336
|
+
do_find
|
337
|
+
end
|
338
|
+
simulated_input_file_handle.close()
|
339
|
+
simulated_output_file_handle.close()
|
340
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
341
|
+
end
|
342
|
+
|
343
|
+
#update is special case, need to pay special attention to it
|
344
|
+
def test_table_name_with_single_keyword_update
|
345
|
+
|
346
|
+
expected_match = <<EOS
|
347
|
+
0: update ARCUserAuthnticn SET pswdexpirydttm = '2030-05-05 00:00:00.0'
|
348
|
+
EOS
|
349
|
+
|
350
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
351
|
+
simulated_output_file_handle = StringIO.new
|
352
|
+
SqlFinder::Find.run do
|
353
|
+
@input_file_handle = simulated_input_file_handle
|
354
|
+
@output_file_handle = simulated_output_file_handle
|
355
|
+
@keywords = ["update"]
|
356
|
+
@table_name = "ARCUserAuthnticn"
|
357
|
+
do_find
|
358
|
+
end
|
359
|
+
simulated_input_file_handle.close()
|
360
|
+
simulated_output_file_handle.close()
|
361
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
362
|
+
end
|
363
|
+
|
364
|
+
def test_table_name_with_single_keyword_delete
|
365
|
+
|
366
|
+
expected_match = <<EOS
|
367
|
+
0: delete from BNKACCTALTIDFR where BNKACCTky = 2
|
368
|
+
EOS
|
369
|
+
|
370
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
371
|
+
simulated_output_file_handle = StringIO.new
|
372
|
+
SqlFinder::Find.run do
|
373
|
+
@input_file_handle = simulated_input_file_handle
|
374
|
+
@output_file_handle = simulated_output_file_handle
|
375
|
+
@keywords = ["delete"]
|
376
|
+
@table_name = "BNKACCTALTIDFR"
|
377
|
+
do_find
|
378
|
+
end
|
379
|
+
simulated_input_file_handle.close()
|
380
|
+
simulated_output_file_handle.close()
|
381
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
382
|
+
end
|
383
|
+
|
384
|
+
def test_table_name_with_double_keyword_select_insert
|
385
|
+
|
386
|
+
expected_match = <<EOS
|
387
|
+
0: SELECT ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm FROM ARCConfiguration WHERE Domain = 'IRExport'
|
388
|
+
0: INSERT INTO ARCConfiguration (ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?) (234001, 'exitUrl', 's1', 'bank', 'app', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
389
|
+
EOS
|
390
|
+
|
391
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
392
|
+
simulated_output_file_handle = StringIO.new
|
393
|
+
SqlFinder::Find.run do
|
394
|
+
@input_file_handle = simulated_input_file_handle
|
395
|
+
@output_file_handle = simulated_output_file_handle
|
396
|
+
@keywords = ["select", "insert"]
|
397
|
+
@table_name = "ARCConfiguration"
|
398
|
+
do_find
|
399
|
+
end
|
400
|
+
simulated_input_file_handle.close()
|
401
|
+
simulated_output_file_handle.close()
|
402
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
403
|
+
end
|
404
|
+
|
405
|
+
|
406
|
+
|
407
|
+
def test_table_name_with_all_keywords
|
408
|
+
|
409
|
+
expected_match = <<EOS
|
410
|
+
0: SELECT ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm FROM ARCConfiguration WHERE Domain = 'IRExport'
|
411
|
+
0: INSERT INTO ARCConfiguration (ARCConfigurationKy, PropertyName, PropertyValue, Domain, Root, versionStamp, updateUser, updateDttm) VALUES (?, ?, ?, ?, ?, ?, ?, ?) (234001, 'exitUrl', 's1', 'bank', 'app', 1, 'CBuser10@CB10010', '2012-09-28 09:37:30.845')
|
412
|
+
EOS
|
413
|
+
|
414
|
+
simulated_input_file_handle = StringIO.new(TEST_FILE)
|
415
|
+
simulated_output_file_handle = StringIO.new
|
416
|
+
SqlFinder::Find.run do
|
417
|
+
@input_file_handle = simulated_input_file_handle
|
418
|
+
@output_file_handle = simulated_output_file_handle
|
419
|
+
@keywords = %w[select insert update delete]
|
420
|
+
@table_name = "ARCConfiguration"
|
421
|
+
do_find
|
422
|
+
end
|
423
|
+
simulated_input_file_handle.close()
|
424
|
+
simulated_output_file_handle.close()
|
425
|
+
assert_equal(expected_match,simulated_output_file_handle.string);
|
426
|
+
end
|
427
|
+
|
428
|
+
|
429
|
+
end
|
@@ -0,0 +1,302 @@
|
|
1
|
+
#run with lib directory in load path to simulate gem runtime environment
|
2
|
+
#ruby -I. -Ilib test/test_sql_regex.rb
|
3
|
+
|
4
|
+
require 'test/unit'
|
5
|
+
require 'stringio'
|
6
|
+
|
7
|
+
class SqlRegexTest < Test::Unit::TestCase
|
8
|
+
|
9
|
+
#these constants model the part of the regex for each SQL keyword
|
10
|
+
SELECT_CONTENT = "(\\bselect\\b.+from.+)"
|
11
|
+
INSERT_CONTENT = "(\\binsert\\b.+into.+)"
|
12
|
+
UPDATE_CONTENT = "(\\bupdate\\b.+set.+)"
|
13
|
+
DELETE_CONTENT = "(\\bdelete\\b.+from.+)"
|
14
|
+
|
15
|
+
SELECT_LINE = "PersistencePreparedStatement.executeQuery(Connection con)|executing: Prepared: select * from BNKUser u where u.givenname = 'OboName'"
|
16
|
+
SELECT_MATCH = "select * from BNKUser u where u.givenname = 'OboName'"
|
17
|
+
|
18
|
+
SELECT_LINE_TWO = " PersistenceNonPreparedStatement.executeQuery(Connection con)|executing: NonPrepared: Select c.arcconfigurationky, c.propertyname from arcconfiguration"
|
19
|
+
SELECT_MATCH_TWO = "Select c.arcconfigurationky, c.propertyname from arcconfiguration"
|
20
|
+
|
21
|
+
INSERT_LINE = "UpdateDatabaseSqlExecutor.invokeExecutor(PersistencePeer peer, PersistenceStatement stmt, List objs)|26|0|1 rows affected|Prepared: INSERT INTO BNKLimitStatus (BNKLimitStatusKy, BNKInstrKy) VALUES (?, ?) (234001, 1002001)"
|
22
|
+
INSERT_MATCH = "INSERT INTO BNKLimitStatus (BNKLimitStatusKy, BNKInstrKy) VALUES (?, ?) (234001, 1002001)"
|
23
|
+
|
24
|
+
INSERT_LINE_TWO = "UpdateDatabaseSqlExecutor.invokeExecutor(PersistencePeer peer, PersistenceStatement stmt, List objs)|26|0|1 rows affected|Prepared: INSERT INTO ARCConfiguration (ARCConfigurationKy, PropertyName) VALUES (?, ?) (234001, 'exitUrl')"
|
25
|
+
INSERT_MATCH_TWO = "INSERT INTO ARCConfiguration (ARCConfigurationKy, PropertyName) VALUES (?, ?) (234001, 'exitUrl')"
|
26
|
+
|
27
|
+
UPDATE_LINE = "PersistencePreparedStatement.executeQuery(Connection con)|executing: Prepared: update ARCUserAuthnticn SET pswdexpirydttm = '2030-05-05 00:00:00.0'"
|
28
|
+
UPDATE_MATCH = "update ARCUserAuthnticn SET pswdexpirydttm = '2030-05-05 00:00:00.0'"
|
29
|
+
|
30
|
+
DELETE_LINE = "PersistencePreparedStatement.executeQuery(Connection con)|executing: Prepared: delete from BNKACCTALTIDFR where BNKACCTky = 2"
|
31
|
+
DELETE_MATCH = "delete from BNKACCTALTIDFR where BNKACCTky = 2"
|
32
|
+
|
33
|
+
SIMULATED_TEST_FILE = [
|
34
|
+
SELECT_LINE,
|
35
|
+
" PersistenceUtils.closeStuff(Connection con, Statement st, ResultSet rs)|",
|
36
|
+
"QueryCommand.execute()",
|
37
|
+
SELECT_LINE_TWO,
|
38
|
+
INSERT_LINE,
|
39
|
+
INSERT_LINE_TWO,
|
40
|
+
"QueryCommand.execute()",
|
41
|
+
UPDATE_LINE,
|
42
|
+
"#START#| AbstractAffiliateServiceBean.findByAffiliateId(com.s1.banking.common.organization.affiliate.AffiliateFIValue value,java.lang.String affiliateId)|",
|
43
|
+
DELETE_LINE
|
44
|
+
]
|
45
|
+
|
46
|
+
#HIT
|
47
|
+
|
48
|
+
def test_select_keyword_only_sql
|
49
|
+
#regex = /^.*\b(select\b.+from.+)$/i
|
50
|
+
regex = /^.*(#{SELECT_CONTENT}.*)/i
|
51
|
+
assert(m = SELECT_LINE.match(regex))
|
52
|
+
assert_equal(SELECT_MATCH,m[1]);
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_insert_keyword_only_sql
|
56
|
+
regex = /^.*(#{INSERT_CONTENT}.*)/i
|
57
|
+
assert(m = INSERT_LINE.match(regex))
|
58
|
+
assert_equal(INSERT_MATCH,m[1]);
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_update_keyword_only_sql
|
62
|
+
regex = /^.*(#{UPDATE_CONTENT}.*)/i
|
63
|
+
assert(m = UPDATE_LINE.match(regex))
|
64
|
+
assert_equal(UPDATE_MATCH,m[1]);
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_delete_keyword_only_sql
|
68
|
+
regex = /^.*(#{DELETE_CONTENT}.*)/i
|
69
|
+
assert(m = DELETE_LINE.match(regex))
|
70
|
+
assert_equal(DELETE_MATCH,m[1]);
|
71
|
+
end
|
72
|
+
|
73
|
+
#MISS
|
74
|
+
|
75
|
+
def test_insert_keyword_only_sql_miss
|
76
|
+
keyword = "insert"
|
77
|
+
regex = /^.*\b(#{keyword}\b.+)$/i
|
78
|
+
assert(!(m = SELECT_LINE.match(regex)))
|
79
|
+
assert_nil(m);
|
80
|
+
end
|
81
|
+
|
82
|
+
#TABLE NAME
|
83
|
+
|
84
|
+
def test_select_keyword_and_table_name_sql
|
85
|
+
table_name = "BNKUSER"
|
86
|
+
regex = /^.*(#{SELECT_CONTENT}\b#{table_name}\b.*)/i
|
87
|
+
#regex = /^.*\b(#{keyword}\b.+from.+\b#{table_name}\b.*)$/i
|
88
|
+
assert(m = SELECT_LINE.match(regex))
|
89
|
+
assert_equal(SELECT_MATCH,m[1]);
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_insert_keyword_and_table_name_sql
|
93
|
+
table_name = "BNKLimitStatus"
|
94
|
+
regex = /^.*(#{INSERT_CONTENT}\b#{table_name}\b.*)/i
|
95
|
+
assert(m = INSERT_LINE.match(regex))
|
96
|
+
assert_equal(INSERT_MATCH,m[1]);
|
97
|
+
end
|
98
|
+
|
99
|
+
#Update with table name is a special case.
|
100
|
+
#For the others, all we have to do is tack the table name
|
101
|
+
#onto the end of the regex, because the two keyword come first:
|
102
|
+
#select . . . from . . . tablename, delete . . . from . . . tablename,
|
103
|
+
#insert . . . into . . . tablename.
|
104
|
+
#But for update, the table name comes between the two keywords:
|
105
|
+
#update tablename set.
|
106
|
+
#So we have to use a different update_content string before proceeding.
|
107
|
+
#We also eliminate the use of "set" entirely,
|
108
|
+
#so we may get additional false positives for update.
|
109
|
+
def test_update_keyword_and_table_name_sql
|
110
|
+
table_name = "ARCUserAuthnticn"
|
111
|
+
revised_update_content = "(\\bupdate\\b.+)"
|
112
|
+
regex = /^.*(#{revised_update_content}\b#{table_name}\b.*)/i
|
113
|
+
puts
|
114
|
+
puts "UPDATE regex: #{regex.to_s}"
|
115
|
+
puts
|
116
|
+
assert(m = UPDATE_LINE.match(regex))
|
117
|
+
assert_equal(UPDATE_MATCH,m[1]);
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_select_keyword_and_table_name_sql_miss
|
121
|
+
table_name = "BNKUSERZZZ"
|
122
|
+
regex = /^.*(#{SELECT_CONTENT}\b#{table_name}\b.*)/i
|
123
|
+
assert(!(m = SELECT_LINE.match(regex)))
|
124
|
+
end
|
125
|
+
|
126
|
+
#make sure that if we provide a table name, the
|
127
|
+
#regex takes it into account and doesn't match
|
128
|
+
#on the insert keyword alone
|
129
|
+
def test_insert_keyword_and_table_name_sql_miss
|
130
|
+
table_name = "BNKLimitStatus"
|
131
|
+
regex = /^.*(#{INSERT_CONTENT}\b#{table_name}\b.*)/i
|
132
|
+
assert(!(m = INSERT_LINE_TWO.match(regex)))
|
133
|
+
end
|
134
|
+
|
135
|
+
#shows we can use a blank table name
|
136
|
+
def test__select_keyword_and_blank_table_name_sql
|
137
|
+
table_name = ""
|
138
|
+
regex = /^.*(#{SELECT_CONTENT}\b#{table_name}\b.*)/i
|
139
|
+
assert(m = SELECT_LINE.match(regex))
|
140
|
+
assert_equal(SELECT_MATCH,m[1]);
|
141
|
+
end
|
142
|
+
|
143
|
+
#table name with multiple keywords, checking the basic ones (update is a special case, treated separately)
|
144
|
+
def test_table_name_sql_with_select_insert_delete_single_match
|
145
|
+
table_name = "BNKUSER"
|
146
|
+
regex_content_array = []
|
147
|
+
regex_content_array << SELECT_CONTENT
|
148
|
+
regex_content_array << INSERT_CONTENT
|
149
|
+
regex_content_array << DELETE_CONTENT
|
150
|
+
regex_content = regex_content_array.join "|"
|
151
|
+
expected_match = [
|
152
|
+
SELECT_MATCH
|
153
|
+
]
|
154
|
+
actual_match = []
|
155
|
+
regex = /^.*((#{regex_content})\b#{table_name}\b.*)/i #regex: /^.*(((\bselect\b.+from.+)|(\binsert\b.+into.+)|(\bdelete\b.+from.+))BNKUSER.*)/
|
156
|
+
SIMULATED_TEST_FILE.each do |line|
|
157
|
+
if (m = line.match(regex))
|
158
|
+
actual_match << m[1]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
assert_equal(1,actual_match.size)
|
162
|
+
assert_equal(expected_match,actual_match);
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_table_name_sql_with_select_insert_delete_double_match
|
166
|
+
table_name = "arcconfiguration"
|
167
|
+
regex_content_array = []
|
168
|
+
regex_content_array << SELECT_CONTENT
|
169
|
+
regex_content_array << INSERT_CONTENT
|
170
|
+
regex_content_array << DELETE_CONTENT
|
171
|
+
regex_content = regex_content_array.join "|"
|
172
|
+
expected_match = [
|
173
|
+
SELECT_MATCH_TWO,
|
174
|
+
INSERT_MATCH_TWO
|
175
|
+
]
|
176
|
+
actual_match = []
|
177
|
+
regex = /^.*((#{regex_content})\b#{table_name}\b.*)/i #regex: /^.*(((\bselect\b.+from.+)|(\binsert\b.+into.+)|(\bdelete\b.+from.+))arcconfiguration.*)/
|
178
|
+
SIMULATED_TEST_FILE.each do |line|
|
179
|
+
if (m = line.match(regex))
|
180
|
+
actual_match << m[1]
|
181
|
+
end
|
182
|
+
end
|
183
|
+
assert_equal(2,actual_match.size)
|
184
|
+
assert_equal(expected_match,actual_match);
|
185
|
+
end
|
186
|
+
|
187
|
+
#As explained above, update is a special case.
|
188
|
+
#This test shows that if we add it, we don't mess up the other content
|
189
|
+
def test_table_name_sql_with_select_insert_delete_update
|
190
|
+
table_name = "BNKUSER"
|
191
|
+
regex_content_array = []
|
192
|
+
regex_content_array << SELECT_CONTENT
|
193
|
+
regex_content_array << INSERT_CONTENT
|
194
|
+
regex_content_array << DELETE_CONTENT
|
195
|
+
revised_update_content = "(\\bupdate\\b.+)"
|
196
|
+
regex_content_array << revised_update_content
|
197
|
+
regex_content = regex_content_array.join "|"
|
198
|
+
expected_match = [
|
199
|
+
SELECT_MATCH
|
200
|
+
]
|
201
|
+
actual_match = []
|
202
|
+
regex = /^.*((#{regex_content})\b#{table_name}\b.*)/i #regex: /^.*(((\bselect\b.+from.+)|(\binsert\b.+into.+)|(\bdelete\b.+from.+))BNKUSER.*)/
|
203
|
+
SIMULATED_TEST_FILE.each do |line|
|
204
|
+
if (m = line.match(regex))
|
205
|
+
actual_match << m[1]
|
206
|
+
end
|
207
|
+
end
|
208
|
+
assert_equal(1,actual_match.size)
|
209
|
+
assert_equal(expected_match,actual_match);
|
210
|
+
end
|
211
|
+
|
212
|
+
#here we use a table that is updated
|
213
|
+
def test_table_name_sql_with_select_insert_delete_match_update
|
214
|
+
table_name = "ARCUserAuthnticn"
|
215
|
+
regex_content_array = []
|
216
|
+
regex_content_array << SELECT_CONTENT
|
217
|
+
regex_content_array << INSERT_CONTENT
|
218
|
+
regex_content_array << DELETE_CONTENT
|
219
|
+
revised_update_content = "(\\bupdate\\b.+)"
|
220
|
+
regex_content_array << revised_update_content
|
221
|
+
regex_content = regex_content_array.join "|"
|
222
|
+
expected_match = [
|
223
|
+
UPDATE_MATCH
|
224
|
+
]
|
225
|
+
actual_match = []
|
226
|
+
regex = /^.*((#{regex_content})\b#{table_name}\b.*)/i #regex: /^.*(((\bselect\b.+from.+)|(\binsert\b.+into.+)|(\bdelete\b.+from.+))BNKUSER.*)/
|
227
|
+
SIMULATED_TEST_FILE.each do |line|
|
228
|
+
if (m = line.match(regex))
|
229
|
+
actual_match << m[1]
|
230
|
+
end
|
231
|
+
end
|
232
|
+
assert_equal(1,actual_match.size)
|
233
|
+
assert_equal(expected_match,actual_match);
|
234
|
+
end
|
235
|
+
|
236
|
+
#if we're searching for a table_name of, say BNKUser,
|
237
|
+
#we don't want hits on tables with names such as BNKUserHistory or VfmBNKUser;
|
238
|
+
#we want exact matches (hence the use of word boundaries)
|
239
|
+
def test_table_name_sql_with_partial_name
|
240
|
+
table_name = "BNKUS"
|
241
|
+
regex = /^.*(#{SELECT_CONTENT}\b#{table_name}\b.*)/i
|
242
|
+
assert_nil(SELECT_LINE.match(regex));
|
243
|
+
table_name = "User"
|
244
|
+
regex = /^.*(#{SELECT_CONTENT}\b#{table_name}\b.*)/i
|
245
|
+
assert_nil(SELECT_LINE.match(regex));
|
246
|
+
end
|
247
|
+
|
248
|
+
#TESTING REGEX "OR" STATEMENT USING MULTIPLE CONTENTS
|
249
|
+
#(we may be searching for lines with select or insert or update, but not delete, for example)
|
250
|
+
def test_find_select_or_insert_sql
|
251
|
+
regex_content_array = []
|
252
|
+
regex_content_array << SELECT_CONTENT
|
253
|
+
regex_content_array << INSERT_CONTENT
|
254
|
+
regex_content = regex_content_array.join "|"
|
255
|
+
expected_match = [
|
256
|
+
SELECT_MATCH,
|
257
|
+
SELECT_MATCH_TWO,
|
258
|
+
INSERT_MATCH,
|
259
|
+
INSERT_MATCH_TWO,
|
260
|
+
]
|
261
|
+
actual_match = []
|
262
|
+
regex = /^.*(#{regex_content}.*)/i
|
263
|
+
SIMULATED_TEST_FILE.each do |line|
|
264
|
+
if (m = line.match(regex))
|
265
|
+
actual_match << m[1]
|
266
|
+
end
|
267
|
+
end
|
268
|
+
assert_equal(4,actual_match.size)
|
269
|
+
assert_equal(expected_match,actual_match);
|
270
|
+
end
|
271
|
+
|
272
|
+
def test_find_all_sql
|
273
|
+
regex_content_array = []
|
274
|
+
regex_content_array << SELECT_CONTENT
|
275
|
+
regex_content_array << INSERT_CONTENT
|
276
|
+
regex_content_array << UPDATE_CONTENT
|
277
|
+
regex_content_array << DELETE_CONTENT
|
278
|
+
regex_content = regex_content_array.join "|"
|
279
|
+
expected_match_all_sql_result = [
|
280
|
+
SELECT_MATCH,
|
281
|
+
SELECT_MATCH_TWO,
|
282
|
+
INSERT_MATCH,
|
283
|
+
INSERT_MATCH_TWO,
|
284
|
+
UPDATE_MATCH,
|
285
|
+
DELETE_MATCH
|
286
|
+
]
|
287
|
+
match_all_sql_result = []
|
288
|
+
#regex = /^.*(((\bselect\b.+from.+)|(\binsert\b.+into.+)|(\bupdate\b.+set.+)|(\bdelete\b.+from.+)).*)$/i
|
289
|
+
regex = /^.*(#{regex_content}.*)/i
|
290
|
+
SIMULATED_TEST_FILE.each do |line|
|
291
|
+
if (m = line.match(regex))
|
292
|
+
match_all_sql_result << m[1]
|
293
|
+
end
|
294
|
+
end
|
295
|
+
assert_equal(6,match_all_sql_result.size)
|
296
|
+
assert_equal(expected_match_all_sql_result,match_all_sql_result);
|
297
|
+
end
|
298
|
+
|
299
|
+
end
|
300
|
+
|
301
|
+
#regex = /^.*((?:(\bselect\b.+from.+)|(\binsert\b.+into.+)|(\bupdate\b.+set.+)|(\bdelete\b.+from.+)).*)$/
|
302
|
+
#regex =
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sqlfinder
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.5
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mark Buechler
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-11-03 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: sqlfinder finds SQL statements in log or trace files. With command line
|
15
|
+
options, users indicate whether they want to search for all SQL statements (SELECT,
|
16
|
+
INSERT, UPDATE, DELETE), selected SQL statements, and/or selected tables.
|
17
|
+
email:
|
18
|
+
executables:
|
19
|
+
- findsql
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files:
|
22
|
+
- README.txt
|
23
|
+
files:
|
24
|
+
- sqlfinder.gemspec
|
25
|
+
- Rakefile
|
26
|
+
- README.txt
|
27
|
+
- lib/sqlfinder/application.rb
|
28
|
+
- lib/sqlfinder/find.rb
|
29
|
+
- lib/sqlfinder.rb
|
30
|
+
- test/test_sql_finder.rb
|
31
|
+
- test/test_sql_regex.rb
|
32
|
+
- bin/findsql
|
33
|
+
homepage: http://rubygems.org/sqlfinder
|
34
|
+
licenses: []
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options:
|
37
|
+
- --main
|
38
|
+
- README.txt
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 1.8.24
|
56
|
+
signing_key:
|
57
|
+
specification_version: 3
|
58
|
+
summary: Finds SQL statements in log files
|
59
|
+
test_files: []
|