|
What this is
Other links
The source code/* * MM JDBC Drivers for MySQL * * $Id: EscapeProcessor.java,v 1.2 1998/08/25 00:53:47 mmatthew Exp $ * * Copyright (C) 1998 Mark Matthews <mmatthew@worldserver.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * See the COPYING file located in the top-level-directory of * the archive of this library for complete text of license. */ /** * EscapeProcessor performs all escape code processing as outlined * in the JDBC spec by JavaSoft. * * @author Mark Matthews <mmatthew@worldserver.com> * @version $Id$ */ package org.gjt.mm.mysql; import java.util.StringTokenizer; import java.util.Vector; import java.util.Stack; class EscapeProcessor { /** * Escape process one string * * @param SQL the SQL to escape process. * @return the SQL after it has been escape processed. */ public synchronized String escapeSQL(String SQL) throws java.sql.SQLException { boolean replaceEscapeSequence = false; String EscapeSequence = null; StringBuffer NewSQL = new StringBuffer(); boolean inBraces = false; boolean inQuotes = false; boolean escaped = false; boolean unrecognizedEscape = false; String OpeningBrace=""; if (SQL == null) { return null; } /* * Short circuit this code if we don't have a matching pair of * "{}". - Suggested by Ryan Gustafason */ int begin_brace = SQL.indexOf("{"); int next_end_brace = SQL.indexOf("}", begin_brace); if (next_end_brace == -1) { return SQL; } PushBackTokenizer PBT = new PushBackTokenizer(SQL, "{}'", true); while (PBT.hasMoreTokens()) { String Token = PBT.nextToken(); if (Token.startsWith("{")) { if (escaped) { NewSQL.append(Token); escaped = false; } else { NewSQL.append(OpeningBrace); inBraces = true; OpeningBrace = Token; } } else if (Token.startsWith("}")) { if (escaped) { NewSQL.append(Token); escaped = false; } else { if (inBraces == false) { NewSQL.append(Token); } else { inBraces = false; if (!OpeningBrace.equals("")) { NewSQL.append(OpeningBrace); NewSQL.append(Token); OpeningBrace=""; } if (unrecognizedEscape) { NewSQL.append(Token); unrecognizedEscape = false; } } } } else if (Token.startsWith("'")) { if (escaped) { NewSQL.append(Token); escaped = false; } else { NewSQL.append(Token); inQuotes = !inQuotes; } } else { if (inBraces && !inQuotes) { /* * Process the escape code */ if (Token.startsWith("escape")) { try { StringTokenizer ST = new StringTokenizer(Token, " '"); ST.nextToken(); // eat the "escape" token EscapeSequence = ST.nextToken(); if (EscapeSequence.length() < 3) { throw new java.sql.SQLException("Syntax error for escape sequence '" + Token + "'", "42000"); } EscapeSequence = EscapeSequence.substring( 1, EscapeSequence.length() - 1); replaceEscapeSequence = true; } catch (java.util.NoSuchElementException E) { throw new java.sql.SQLException("Syntax error for escape sequence '" + Token + "'", "42000"); } } else if (Token.startsWith("fn")) { // just pass functions right to the DB int start_pos = Token.indexOf("fn ") + 3; int end_pos = Token.length(); NewSQL.append(Token.substring(start_pos, end_pos)); try { NewSQL.append(parseComplexArgument(PBT)); } catch (java.util.NoSuchElementException NSE) { throw new java.sql.SQLException("Syntax error for FN escape code", "42000"); } } else if (Token.startsWith("d")) { String Argument = ""; try { Argument = parseArgument(PBT); } catch (java.util.NoSuchElementException NSE) { throw new java.sql.SQLException("Illegal argument for DATE escape code '" + Argument + "'", "42000"); } try { StringTokenizer ST = new StringTokenizer(Argument, " -"); String YYYY = ST.nextToken(); String MM = ST.nextToken(); String DD = ST.nextToken(); String DateString = "'" + YYYY + "-" + MM + "-" + DD + "'"; NewSQL.append(DateString); } catch (java.util.NoSuchElementException E) { throw new java.sql.SQLException("Syntax error for DATE escape sequence '" + Argument + "'", "42000"); } } else if (Token.startsWith("ts")) { String Argument = ""; try { Argument = parseArgument(PBT); } catch (java.util.NoSuchElementException NSE) { throw new java.sql.SQLException("Illegal argument for TIMESTAMP escape code '" + Argument + "'", "42000"); } try { StringTokenizer ST = new StringTokenizer(Argument, " .-:"); String YYYY = ST.nextToken(); String MM = ST.nextToken(); String DD = ST.nextToken(); String HH = ST.nextToken(); String Mm = ST.nextToken(); String SS = ST.nextToken(); /* * For now, we get the fractional seconds * part, but we don't use it, as MySQL doesn't * support it in it's TIMESTAMP data type */ String F = ""; if (ST.hasMoreTokens()) { F = ST.nextToken(); } /* * Use the full format because number format * will not work for "between" clauses. * * Ref. Mysql Docs * * You can specify DATETIME, DATE and TIMESTAMP values * using any of a common set of formats: * * As a string in either 'YYYY-MM-DD HH:MM:SS' or * 'YY-MM-DD HH:MM:SS' format. * * Thanks to Craig Longman for pointing out this bug */ NewSQL.append("'").append(YYYY).append("-").append(MM).append("-").append(DD).append(" ").append(HH).append(":").append(Mm).append(":").append(SS).append("'"); } catch (java.util.NoSuchElementException E) { throw new java.sql.SQLException("Syntax error for TIMESTAMP escape sequence '" + Argument + "'", "42000"); } } else if (Token.startsWith("t")) { String Argument = ""; try { Argument = parseArgument(PBT); } catch (java.util.NoSuchElementException NSE) { throw new java.sql.SQLException("Illegal argument for TIME escape code '" + Argument + "'", "42000"); } try { StringTokenizer ST = new StringTokenizer(Argument, " ':"); String HH = ST.nextToken(); String MM = ST.nextToken(); String SS = ST.nextToken(); String TimeString = "'" + HH + ":" + MM + ":" +SS + "'"; NewSQL.append(TimeString); } catch (java.util.NoSuchElementException E) { throw new java.sql.SQLException("Syntax error for escape sequence '" + Argument + "'", "42000"); } } else if (Token.startsWith("call") || Token.startsWith("? = call")) { throw new java.sql.SQLException("Stored procedures not supported: " + Token, "S1C00"); } else if (Token.startsWith("oj")) { // MySQL already handles this escape sequence // because of ODBC. Cool. try { NewSQL.append(parseComplexArgument(PBT)); } catch (java.util.NoSuchElementException NSE) { throw new java.sql.SQLException("Syntax error for OJ escape code", "42000"); } } else { NewSQL.append(OpeningBrace); NewSQL.append(Token); unrecognizedEscape = true; OpeningBrace = ""; } OpeningBrace=""; } else { NewSQL.append(Token); } } if (Token.endsWith("\\")) { escaped = true; } } NewSQL.append(OpeningBrace); String EscapedSQL = NewSQL.toString(); if (replaceEscapeSequence) { String CurrentSQL = EscapedSQL; while (CurrentSQL.indexOf(EscapeSequence) != -1) { int escapePos = CurrentSQL.indexOf(EscapeSequence); String LHS = CurrentSQL.substring(0, escapePos); String RHS = CurrentSQL.substring(escapePos + 1, CurrentSQL.length()); CurrentSQL = LHS + "\\" + RHS; } EscapedSQL = CurrentSQL; } // Do we need to do the concatenation operator? if (EscapedSQL.indexOf("||") != -1) { EscapedSQL = doConcat(EscapedSQL); } return EscapedSQL; } /** * Do concatenation for the SQL operator "||" because * MySQL doesn't support it, but some IDEs (i.e. VisualAge) * use it. * * @param SQL A String to do concatenation operations on */ static String doConcat(String SQL) { Vector TokenList = new Vector(); StringTokenizer ST = new StringTokenizer(SQL, " '", true); boolean inquotes = false; StringBuffer QuotedString = null; while (ST.hasMoreTokens()) { String T = ST.nextToken(); if (T.equals("'")) { if (inquotes == true) { inquotes = false; Token Tok = new Token(QuotedString.toString(), true); TokenList.addElement(Tok); } else { inquotes = true; QuotedString = new StringBuffer(); } } else { if (inquotes) { QuotedString.append(T); } else { Token Tok = new Token(T, false); TokenList.addElement(Tok); } } } // Now go through and find what we need to concatenate int pos = 0; int length = TokenList.size(); Stack ToDo = new Stack(); while (pos < length) { Token T1 = (Token)TokenList.elementAt(pos); if (T1.Value.equals("||")) { Token Pre = (Token)ToDo.pop(); pos++; Token Post = (Token)TokenList.elementAt(pos); Token Concat = new Token(Pre.Value + Post.Value, true); ToDo.push(Concat); pos++; } else { ToDo.push(T1); pos++; } } length = ToDo.size(); StringBuffer NewQuery = new StringBuffer(); for (int i = 0; i < length; i++) { Token T = (Token)ToDo.elementAt(i); if (T.quoted) { NewQuery.append("'"); NewQuery.append(T.Value); NewQuery.append("'"); } else { NewQuery.append(T.Value); } } return NewQuery.toString(); } /** * Given the current tokenizer, assemble an escape code argument */ private final static String parseArgument(PushBackTokenizer Tokenizer) throws java.util.NoSuchElementException { StringBuffer Argument = new StringBuffer(); boolean done_parsing = false; boolean seen_one_quote = false; while (!done_parsing) { String Tok = Tokenizer.nextToken(); if (Tok.equals("'")) { if (seen_one_quote) { done_parsing = true; } else { seen_one_quote = true; } } else { Argument.append(Tok); } } return Argument.toString(); } /** * Given the current tokenizer, assemble an escape code argument */ private final static String parseComplexArgument(PushBackTokenizer Tokenizer) throws java.util.NoSuchElementException { StringBuffer Argument = new StringBuffer(); boolean done_parsing = false; boolean in_quotes = false; while (!done_parsing) { String Tok = Tokenizer.nextToken(); if (Tok.equals("'")) { in_quotes = !in_quotes; Argument.append(Tok); } else { if (!in_quotes && Tok.equals("}")) { done_parsing = true; Tokenizer.pushBack(); } else { Argument.append(Tok); } } } return Argument.toString(); } }; |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.