[Squirrel-sql-commits] sql12/plugins/oracle/src/net/sourceforge/squirrel_sql/plugins/oracle/tokeniz
A Java SQL client for any JDBC compliant database
Brought to you by:
colbell,
gerdwagner
From: Rob M. <man...@us...> - 2007-04-10 10:30:13
|
Update of /cvsroot/squirrel-sql/sql12/plugins/oracle/src/net/sourceforge/squirrel_sql/plugins/oracle/tokenizer In directory sc8-pr-cvs8.sourceforge.net:/tmp/cvs-serv4251/plugins/oracle/src/net/sourceforge/squirrel_sql/plugins/oracle/tokenizer Modified Files: OracleQueryTokenizer.java Log Message: Handle slashes when they are used as statement separators. Index: OracleQueryTokenizer.java =================================================================== RCS file: /cvsroot/squirrel-sql/sql12/plugins/oracle/src/net/sourceforge/squirrel_sql/plugins/oracle/tokenizer/OracleQueryTokenizer.java,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** OracleQueryTokenizer.java 6 Apr 2007 23:25:57 -0000 1.5 --- OracleQueryTokenizer.java 10 Apr 2007 10:30:03 -0000 1.6 *************** *** 21,24 **** --- 21,25 ---- */ import java.util.ArrayList; + import java.util.Arrays; import java.util.Iterator; import java.util.regex.Pattern; *************** *** 31,34 **** --- 32,48 ---- import net.sourceforge.squirrel_sql.plugins.oracle.prefs.OraclePreferenceBean; + /** + * This class is loaded by the Oracle Plugin and registered with all Oracle + * Sessions as the query tokenizer if the plugin is loaded. It handles some + * of the syntax allowed in SQL-Plus scripts that would be hard to parse in a + * generic way for any database. It handles create statements for stored + * procedures, triggers, functions and anonymous procedure blocks. It can also + * handle "/" as the statement terminator in leiu of or in addition to the + * default statement separator which is ";". This class is not meant to fully + * replicate all of the syntax available in the highly expressive and venerable + * SQL-Plus reporting tool. + * + * @author manningr + */ public class OracleQueryTokenizer extends QueryTokenizer implements IQueryTokenizer { *************** *** 46,51 **** "^\\s*CREATE\\s+TRIGGER.*|^\\s*CREATE\\s+OR\\s+REPLACE\\s+TRIGGER\\s+.*"; ! private static final String DECLARE_PATTERN = ! "^\\s*DECLARE\\s*.*"; private Pattern procPattern = Pattern.compile(PROCEDURE_PATTERN, Pattern.DOTALL); --- 60,70 ---- "^\\s*CREATE\\s+TRIGGER.*|^\\s*CREATE\\s+OR\\s+REPLACE\\s+TRIGGER\\s+.*"; ! private static final String DECLARE_PATTERN = "^\\s*DECLARE\\s*.*"; ! ! /** Finds any "\n/" (slash) characters on their own line (no sep) */ ! private static final String SLASH_PATTERN = ".*\\n/\\n.*"; ! ! /** Finds any "\n/" (slash) characters on their own line (no sep) */ ! private static final String SLASH_SPLIT_PATTERN = "\\n/\\n"; private Pattern procPattern = Pattern.compile(PROCEDURE_PATTERN, Pattern.DOTALL); *************** *** 57,60 **** --- 76,81 ---- private Pattern declPattern = Pattern.compile(DECLARE_PATTERN, Pattern.DOTALL); + private Pattern slashPattern = Pattern.compile(SLASH_PATTERN, Pattern.DOTALL); + private static final String ORACLE_SCRIPT_INCLUDE_PREFIX = "@"; *************** *** 85,93 **** // statements, which is invalid for Oracle. Since "/" is the way // in SQL-Plus to denote the end of a procedure or function, we ! // re-assemble any create procedure statements that we find. ! // This should be done before expanding file includes. Otherwise, any ! // create sql found in files will already be joined, causing this to // find create SQL without matching "/". The process of ! // expanding file includes already joins the sql it finds. joinFragments(procPattern, false); joinFragments(funcPattern, false); --- 106,115 ---- // statements, which is invalid for Oracle. Since "/" is the way // in SQL-Plus to denote the end of a procedure or function, we ! // re-assemble any create procedure/function/trigger statements that we ! // find. This should be done before expanding file includes. Otherwise, ! // any create sql found in files will already be joined, causing this to // find create SQL without matching "/". The process of ! // expanding 'file includes' already joins the sql fragments that it ! // finds. joinFragments(procPattern, false); joinFragments(funcPattern, false); *************** *** 97,100 **** --- 119,124 ---- expandFileIncludes(ORACLE_SCRIPT_INCLUDE_PREFIX); + removeRemainingSlashes(); + _queryIterator = _queries.iterator(); } *************** *** 113,116 **** --- 137,188 ---- } + /** + * This is to take care of scripts that have no statement separators. + * Like : + * + * select * from sometable1 + * / + * + * select * from sometable2 + * / + * + * SQL-Plus allows "/" to terminate statements as well as multiple statement + * blocks, so someone will probably have written a script that does this. + */ + private void removeRemainingSlashes() { + + ArrayList<String> tmp = new ArrayList<String>(); + boolean foundEOLSlash = false; + for (Iterator<String> iter = _queries.iterator(); iter.hasNext();) { + String next = iter.next(); + if (slashPattern.matcher(next).matches()) { + foundEOLSlash = true; + String[] parts = next.split(SLASH_SPLIT_PATTERN); + for (int i = 0; i < parts.length; i++) { + String part = parts[i]; + if (slashPattern.matcher(part).matches()) { + int lastIndex = part.lastIndexOf("/"); + tmp.add(part.substring(0, lastIndex)); + } else { + if (part.endsWith("/")) { + part = part.substring(0, part.lastIndexOf("/")); + } + tmp.add(part); + } + } + } else if (next.endsWith("/")) { + foundEOLSlash = true; + int lastIndex = next.lastIndexOf("/"); + tmp.add(next.substring(0, lastIndex)); + } else { + tmp.add(next); + } + } + if (foundEOLSlash == true) { + _queries = tmp; + } + + } + /** * This will loop through _queries and break apart lines that look like *************** *** 123,130 **** */ private void breakApartNewLines() { ! ArrayList tmp = new ArrayList(); String sep = _prefs.getProcedureSeparator(); ! for (Iterator iter = _queries.iterator(); iter.hasNext();) { ! String next = (String) iter.next(); if (next.startsWith(sep)) { tmp.add(sep); --- 195,202 ---- */ private void breakApartNewLines() { ! ArrayList<String> tmp = new ArrayList<String>(); String sep = _prefs.getProcedureSeparator(); ! for (Iterator<String> iter = _queries.iterator(); iter.hasNext();) { ! String next = iter.next(); if (next.startsWith(sep)) { tmp.add(sep); *************** *** 155,162 **** boolean inMultiSQLStatement = false; StringBuffer collector = null; ! ArrayList tmp = new ArrayList(); String sep = _prefs.getProcedureSeparator(); ! for (Iterator iter = _queries.iterator(); iter.hasNext();) { ! String next = (String) iter.next(); if (pattern.matcher(next.toUpperCase()).matches()) { inMultiSQLStatement = true; --- 227,234 ---- boolean inMultiSQLStatement = false; StringBuffer collector = null; ! ArrayList<String> tmp = new ArrayList<String>(); String sep = _prefs.getProcedureSeparator(); ! for (Iterator<String> iter = _queries.iterator(); iter.hasNext();) { ! String next = iter.next(); if (pattern.matcher(next.toUpperCase()).matches()) { inMultiSQLStatement = true; *************** *** 174,178 **** // Stray sep - or we failed to find pattern if (s_log.isDebugEnabled()) { ! s_log.debug("Detected stray proc separator("+sep+"). Skipping"); } } else { --- 246,251 ---- // Stray sep - or we failed to find pattern if (s_log.isDebugEnabled()) { ! s_log.debug( ! "Detected stray proc separator("+sep+"). Skipping"); } } else { |