package net.sourceforge.sqlexplorer.util; import java.util.StringTokenizer; /** * QueryTokenizer based on original SquirreL SQL tokenizer, but adds the * possibility to use multiple characters as the sql delimeter. * * This is used for splitting the input text in the editor into * multiple executable sql statements. * * @author Davy Vanherbergen */ public class QueryTokenizer { private static String _alternateQuerySeparator; private static String _querySeparator; private String _sQuerys; private String _sNextQuery; /** * These characters at the beginning of an SQL statement indicate that it is * a comment. */ private String _solComment; /** * QueryTokenizer constructor comment. */ public QueryTokenizer(String sql, String querySeparator, String alternateSeparator, String solComment) { if (querySeparator != null && querySeparator.trim().length() > 0) { _querySeparator = querySeparator.substring(0, 1); } else { // failsave.. _querySeparator = ";"; } if (alternateSeparator != null && alternateSeparator.trim().length() > 0) { _alternateQuerySeparator = alternateSeparator; } else { _alternateQuerySeparator = null; } if (solComment != null && solComment.trim().length() > 0) { _solComment = solComment; } else { _solComment = null; } if (sql != null) { _sQuerys = prepareSQL(sql); _sNextQuery = parse(); } else { _sQuerys = ""; } } public boolean hasQuery() { return _sNextQuery != null; } public String nextQuery() { String sReturnQuery = _sNextQuery; _sNextQuery = parse(); return sReturnQuery; } private int findFirstSeparator() { String separator = _querySeparator; int separatorLength = _querySeparator.length(); int iQuoteCount = 1; int iIndex1 = 0 - separatorLength; while (iQuoteCount % 2 != 0) { iQuoteCount = 0; iIndex1 = _sQuerys.indexOf(separator, iIndex1 + separatorLength); if (iIndex1 > -1) { int iIndex2 = _sQuerys.lastIndexOf('\'', iIndex1 + separatorLength - 1); while (iIndex2 != -1) { if (_sQuerys.charAt(iIndex2 - 1) != '\\') { iQuoteCount++; } iIndex2 = _sQuerys.lastIndexOf('\'', iIndex2 - 1); } } else { return -1; } } return iIndex1; } private int findFirstAlternateSeparator() { if (_alternateQuerySeparator == null) { return -1; } String separator = _alternateQuerySeparator; int separatorLength = _alternateQuerySeparator.length(); int iQuoteCount = 1; int iIndex1 = 0 - separatorLength; while (iQuoteCount % 2 != 0) { iQuoteCount = 0; iIndex1 = _sQuerys.indexOf(separator, iIndex1 + separatorLength); if (iIndex1 > -1) { int iIndex2 = _sQuerys.lastIndexOf('\'', iIndex1 + separatorLength - 1); while (iIndex2 != -1) { if (_sQuerys.charAt(iIndex2 - 1) != '\\') { iQuoteCount++; } iIndex2 = _sQuerys.lastIndexOf('\'', iIndex2 - 1); } } else { return -1; } } return iIndex1; } public String parse() { if (_sQuerys.length() == 0) { return null; } String separator = _querySeparator; int indexSep = findFirstSeparator(); int indexAltSep = findFirstAlternateSeparator(); if (indexAltSep > -1) { if (indexSep < 0 || indexAltSep < indexSep) { // use alternate separator separator = _alternateQuerySeparator; } } int separatorLength = separator.length(); int iQuoteCount = 1; int iIndex1 = 0 - separatorLength; while (iQuoteCount % 2 != 0) { iQuoteCount = 0; iIndex1 = _sQuerys.indexOf(separator, iIndex1 + separatorLength); if (iIndex1 > -1) { int iIndex2 = _sQuerys.lastIndexOf('\'', iIndex1 + separatorLength - 1); while (iIndex2 != -1) { if (_sQuerys.charAt(iIndex2 - 1) != '\\') { iQuoteCount++; } iIndex2 = _sQuerys.lastIndexOf('\'', iIndex2 - 1); } } else { String sNextQuery = _sQuerys; _sQuerys = ""; if (_solComment != null && sNextQuery.startsWith(_solComment)) { return parse(); } return replaceLineFeeds(sNextQuery); } } String sNextQuery = _sQuerys.substring(0, iIndex1); _sQuerys = _sQuerys.substring(iIndex1 + separatorLength).trim(); if (_solComment != null && sNextQuery.startsWith(_solComment)) { return parse(); } return replaceLineFeeds(sNextQuery); } private String prepareSQL(String sql) { StringBuffer results = new StringBuffer(1024); for (StringTokenizer tok = new StringTokenizer(sql.trim(), "\n", false); tok.hasMoreTokens();) { String line = tok.nextToken(); if (!line.startsWith(_solComment)) { results.append(line).append('\n'); } } return results.toString(); } private String replaceLineFeeds(String sql) { StringBuffer sbReturn = new StringBuffer(); int iPrev = 0; int linefeed = sql.indexOf('\n'); int iQuote = -1; while (linefeed != -1) { iQuote = sql.indexOf('\'', iQuote + 1); if (iQuote != -1 && iQuote < linefeed) { int iNextQute = sql.indexOf('\'', iQuote + 1); if (iNextQute > linefeed) { sbReturn.append(sql.substring(iPrev, linefeed)); sbReturn.append('\n'); iPrev = linefeed + 1; linefeed = sql.indexOf('\n', iPrev); } } else { linefeed = sql.indexOf('\n', linefeed + 1); } } sbReturn.append(sql.substring(iPrev)); return sbReturn.toString(); } }