@@ -109,7 +109,6 @@ public class Compass {
109109 protected static boolean pgImport = false ;
110110 protected static boolean pgImportAppend = false ;
111111 protected static boolean pgImportTable = false ;
112- protected static boolean anonymizedReport = false ;
113112 protected static boolean importFormatArg = false ;
114113 protected static String mergeReport = "" ;
115114 protected static String userCfgFile = "" ;
@@ -133,6 +132,7 @@ public class Compass {
133132 public static String sessionLog ;
134133
135134 public static List <String > inputFiles = new ArrayList <>();
135+ public static Map <String , Integer > inputFilesLastLine = new HashMap <>();
136136 public static List <String > inputFilesOrig = new ArrayList <>();
137137 public static Map <String ,String > inputFilesMapped = new HashMap <>();
138138 public static List <String > cmdFlags = new ArrayList <>();
@@ -278,6 +278,7 @@ public Compass(String[] args) {
278278 u .appOutput (" -recursive : recursively add files if inputfile is a directory" );
279279 u .appOutput (" -include <list> : pattern of input file types to include (e.g.: .txt,.ddl)" );
280280 u .appOutput (" -exclude <list> : pattern of input file types to exclude (e.g.: .pptx)" );
281+ u .appOutput (" -anon : remove all customer-specific identifiers" );
281282 u .appOutput (" -rewrite : rewrites selected unsupported SQL features" );
282283 u .appOutput (" -noupdatechk : do not check for " + CompassUtilities .thisProgName + " updates" );
283284 u .appOutput (" -importformat <fmt> : process special-format captured query files" );
@@ -721,7 +722,10 @@ else if (option.equals("hints")) {
721722 i ++;
722723 continue ;
723724 }
724-
725+ if (arg .equals ("-anon" )) {
726+ u .anonymizedData = true ;
727+ continue ;
728+ }
725729 if (arg .equals ("-sqlendpoint" )) {
726730 if (i >= args .length ) {
727731 System .out .println ("Must specify value with -sqlendpoint" );
@@ -889,11 +893,7 @@ else if (option.equals("hints")) {
889893 if (arg .equals ("-symtab_all" )) { // development only: load symtab for all applications -- but we shouldn't need this
890894 u .symTabAll = true ;
891895 continue ;
892- }
893- if (arg .equals ("-anon" )) { // development only
894- anonymizedReport = true ;
895- continue ;
896- }
896+ }
897897 }
898898 // arguments must start with [A-Za-z0-9 _-./] : anything else is invalid
899899 if (CompassUtilities .getPatternGroup (arg .substring (0 ,1 ), "^([\\ w\\ -\\ .\\ /])$" , 1 ).isEmpty ()) {
@@ -1038,13 +1038,7 @@ public static void main(String[] args) throws Exception {
10381038 // generate DDL through SMO
10391039 if (autoDDL ) {
10401040 getAutoDDL ();
1041- }
1042-
1043- // generate anon report file
1044- if (anonymizedReport ) {
1045- runAnonymizedReport ();
1046- return ;
1047- }
1041+ }
10481042
10491043 // only for debugging the config class:
10501044// if (u.debugCfg) {
@@ -1209,7 +1203,7 @@ public static void main(String[] args) throws Exception {
12091203
12101204 // read custom item ID file, if applicable
12111205 u .openCustomItemIDFile ();
1212-
1206+
12131207 if (reportOnly ) {
12141208 // only generate reported from already-captured items
12151209 startTime = System .currentTimeMillis ();
@@ -1275,7 +1269,7 @@ public static void main(String[] args) throws Exception {
12751269 endRun = System .currentTimeMillis ();
12761270 endRunFmt = new SimpleDateFormat ("dd-MMM-yyyy HH:mm:ss" ).format (new Date ());
12771271 elapsedRun = (endRun - startRun )/ 1000 ;
1278-
1272+
12791273 comp .reportFinalStats ();
12801274 if (generateReport ) {
12811275 if (!(parseOnly || importOnly )) {
@@ -1590,13 +1584,17 @@ private static boolean optionsValid() throws Exception {
15901584 }
15911585 }
15921586
1593- if (anonymizedReport ) {
1594- if (readStdin || listContents || importOnly || reAnalyze || deleteReport || reportOnly ) {
1587+ if (u . anonymizedData ) {
1588+ if (readStdin || listContents ) {
15951589 u .appOutput ("-anon cannot be combined with other options" );
15961590 return false ;
15971591 }
1598- if ((inputFiles .size () > 0 ) || autoDDL ) {
1599- u .appOutput ("-anon cannot be combined with input files" );
1592+ if (reportOption ) {
1593+ u .appOutput ("-anon cannot be combined with -reportoption" );
1594+ return false ;
1595+ }
1596+ if ((inputFiles .size () == 0 ) && !pgImport && !reportOnly && !reAnalyze ) {
1597+ u .appOutput ("-anon can only be specified when analyzing input files" );
16001598 return false ;
16011599 }
16021600 return true ;
@@ -1947,25 +1945,20 @@ private static boolean optionsValid() throws Exception {
19471945 }
19481946
19491947 private static void runPGImport () throws Exception {
1950- // import the captured.dat file into a PG table
1951-
1952- // try {
1953- u .importPG (pgImportAppend , pgImportFlags );
1954- // }
1955- // catch (Exception e) {
1956- // u.appOutput(u.thisProc()+"error in importPG");
1957- // throw e;
1958- // }
1948+ // import the captured.dat file into a PG table
1949+ u .importPG (pgImportAppend , pgImportFlags );
19591950
19601951 //Note: by exiting here, the password entered on command line is not getting written into the log files
19611952 // If this is ever changed, the password should be blanked out in the command-line argument before written to the log file
19621953 u .errorExit ();
19631954 }
19641955
1965- private static void runAnonymizedReport () {
1956+ private static void anonymizeCapturedData () {
19661957 // generated anon report file
1967- try { u .createAnonymizedReport (); } catch (Exception e ) { /*nothing*/ }
1968- u .errorExit ();
1958+ try { u .anonymizeCapturedData (); } catch (Exception e ) {
1959+ //System.out.println(e.toString());
1960+ e .printStackTrace ();
1961+ }
19691962 }
19701963
19711964 private void reportFinalStats () throws Exception {
@@ -2390,10 +2383,16 @@ private void processInput(String runStartTime) throws Exception {
23902383 // set QUOTED_IDENTIFIER to the default value at the start of the input file
23912384 a .setQuotedIdentifier (quotedIdentifier );
23922385
2393- // process input file line by line, identifying batches to be parsed
2394- // this follows the 'sqlcmd' utility which uses 'go' and 'reset' as batch terminators
2395- // other sqlcmd commands/directives are not handled except 'exit'/'quit'; such sqlcmd
2396- // commands/directives can only be handled by sqlcmd itself
2386+ // Process input file line by line, identifying batches to be parsed
2387+ // This follows the 'sqlcmd' utility which uses 'go' and 'reset' as batch terminators
2388+ // Other sqlcmd commands/directives are not handled except 'exit'/'quit'
2389+ // Note that we are not trying to parse the entire input file, which would require the
2390+ // sqlcmd commands to be part of the grammar. Not only would this complicate the grammar,
2391+ // slow down parsing and complicate overall processing, but more importantly it would lead
2392+ // to the entire file being rejected if there is a single syntax error or bad character
2393+ // somewhere, instead of just rejecting the offending batch.
2394+ // The price to pay is having to work through each input file to properly process these
2395+ // sqlcmd commands.
23972396
23982397 StringBuilder batchText = new StringBuilder ();
23992398 int batchLines = 0 ;
@@ -2436,19 +2435,35 @@ private void processInput(String runStartTime) throws Exception {
24362435 dynamicSQLContext = "" ;
24372436 dynamicSQLSubContext = "" ;
24382437 u .dynamicSQLFlag = false ;
2438+
2439+ int lastLineWithoutTerminator = -1 ;
2440+ if (u .analysisPass == 2 ) {
2441+ if (inputFilesLastLine .containsKey (inFile )) {
2442+ lastLineWithoutTerminator = inputFilesLastLine .get (inFile );
2443+ if (u .debugging ) u .dbgOutput (u .thisProc ()+"getting lastLineWithoutTerminator for inFile=[" +inFile +"]=[" +lastLineWithoutTerminator +"] " , u .debugBatch ||u .debugDynamicSQL );
2444+ }
2445+ }
24392446
24402447 while (true ) {
24412448 boolean somethingFoundOnLine = false ;
24422449 boolean orphanSquareBracket = false ;
24432450 if (!lastLineRead ) {
2444- line = inFileReader .readLine ();
2451+ if ((u .analysisPass == 2 ) && (lastLineWithoutTerminator == lineNr )) {
2452+ if (u .debugging ) u .dbgOutput ("inserting lastLineWithoutTerminator, lineNr=[" +lineNr +"]" , u .debugBatch ||u .debugDynamicSQL );
2453+ line = "go" ; // this only applies in case the last batch does not have a terminator AND there is dynamic SQL to process
2454+ }
2455+ else {
2456+ line = inFileReader .readLine ();
2457+ }
24452458 }
24462459 else if (u .analysisPass == 2 ) {
2460+ if (u .debugging ) u .dbgOutput (u .thisProc ()+"dynSQLCount=[" +dynSQLCount +"] u.dynamicSQLBuffer.size()=[" +u .dynamicSQLBuffer .size ()+"] " , u .debugDynamicSQL );
24472461 if (dynSQLCount < u .dynamicSQLBuffer .size ()) {
24482462 if (!analyzingDynamicSQL ) {
24492463 u .dynamicSQLBuffer .add (0 , "go" );
2450- analyzingDynamicSQL = true ;
2464+ analyzingDynamicSQL = true ;
24512465 }
2466+ if (u .debugging ) u .dbgOutput (u .thisProc ()+"u.dynamicSQLBuffer=[" +u .dynamicSQLBuffer +"] " , u .debugDynamicSQL );
24522467 line = u .dynamicSQLBuffer .get (dynSQLCount );
24532468 dynSQLCount ++;
24542469 if (u .debugging ) u .dbgOutput (u .thisProc ()+"dynamic SQL: line=[" +line +"] " , u .debugDynamicSQL );
@@ -2471,6 +2486,11 @@ else if (dynSQLCount == u.dynamicSQLBuffer.size()) {
24712486 line = null ;
24722487 }
24732488 }
2489+ if ((line == null ) && (u .analysisPass == 1 ) && !lastLineRead && !startOfNewBatch ) {
2490+ // this only matters in case there is dynamic SQL to process AND the last batch does not have a terminator
2491+ inputFilesLastLine .put (inFile , lineNr );
2492+ if (u .debugging ) u .dbgOutput ("last line read without GO: lineNr=[" +lineNr +"] startOfNewBatch=[" +startOfNewBatch +"] lastLineWithoutTerminator=[" +inputFilesLastLine .get (lineNr )+"]" , u .debugBatch ||u .debugDynamicSQL );
2493+ }
24742494 if ((line == null ) && (u .analysisPass == 2 ) && !lastLineRead ) {
24752495 lastLineRead = true ;
24762496 if (u .debugging ) u .dbgOutput ("last line was read! " , u .debugBatch );
@@ -2507,7 +2527,7 @@ else if (dynSQLCount == u.dynamicSQLBuffer.size()) {
25072527 if (!u .importFileAttribute (line ,2 ).isEmpty ()) {
25082528 // this is the header line from the import copy, abort
25092529 u .appOutput ("This file contains a header line that indicates it was taken from an 'imported' subdirectory\n of a " +u .thisProgName +" report." );
2510- u .appOutput ("Remove the first line; when reprocessing, ensure the file is encoded as UTF-8, or use '-encoding utf8'." );
2530+ u .appOutput ("You must remove the first line; when reprocessing, ensure the file is encoded as UTF-8, or use '-encoding utf8'." );
25112531 u .appOutput ("Aborting..." );
25122532 u .errorExit ();
25132533 }
@@ -2882,6 +2902,7 @@ else if (dynSQLCount == u.dynamicSQLBuffer.size()) {
28822902 }
28832903
28842904 if ((u .analysisPass == 1 ) || ((u .analysisPass == 2 ) && analyzingDynamicSQL )) {
2905+ if (u .debugging ) u .dbgOutput ("u.analysisPass=[" +u .analysisPass +"] analyzingDynamicSQL=[" +analyzingDynamicSQL +"] dumpParseTree=[" +dumpParseTree +"] " , u .debugBatch );
28852906 if (hasParseError ) {
28862907 // write error batch
28872908 if (u .errBatchFileWriter == null ) {
@@ -2922,7 +2943,7 @@ else if (dynSQLCount == u.dynamicSQLBuffer.size()) {
29222943 }
29232944 else if (exportedParseTree != null ) {
29242945 // even with -parseonly, we need to run analysis in order to process set quoted_identifier, which affects parsing
2925- if (u .debugging ) u .dbgOutput ("Analyzing tree for batch " , u .debugBatch );
2946+ if (u .debugging ) u .dbgOutput ("pass=[" + u . analysisPass + "] Analyzing tree for batchNr=[" + batchNr + "] batchLines=[" + batchLines + "] " , u .debugBatch );
29262947 String phase = "analysisTimeP" + u .analysisPass ;
29272948 startTime = System .currentTimeMillis ();
29282949
@@ -2999,7 +3020,7 @@ else if (exportedParseTree != null) {
29993020 }
30003021 }
30013022
3002- if (u .analysisPass == 2 ) {
3023+ if (u .analysisPass == 2 ) {
30033024 if (CompassUtilities .devOptions ) {
30043025 // temporary, for development
30053026 int secs = ((int ) timeElapsedFile / 1000 );
@@ -3026,6 +3047,14 @@ else if (exportedParseTree != null) {
30263047 u .closeErrBatchFile ();
30273048 }
30283049 } //for inputfiles
3050+
3051+
3052+ // generate anonymized capture files
3053+ if (u .analysisPass == 2 ) {
3054+ if (u .anonymizedData ) {
3055+ anonymizeCapturedData ();
3056+ }
3057+ }
30293058 }
30303059
30313060 private static void getAutoDDL () throws Exception {
@@ -3317,7 +3346,7 @@ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int
33173346 }
33183347
33193348 // export the parse tree
3320- if (batchNr > 0 ) {
3349+ if (( batchNr > 0 ) || ( batchNr == 0 ) && analyzingDynamicSQL ) {
33213350 exportedParseTree = tree ;
33223351 }
33233352
0 commit comments