sqlfinder 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,5 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
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: []