net.sourceforge.jtds.jdbc

Class SQLParser


(package private) class SQLParser
extends java.lang.Object

Process JDBC escape strings and parameter markers in the SQL string.

This code recognizes the following escapes:

  1. Date {d 'yyyy-mm-dd'}
  2. Time {t 'hh:mm:ss'}
  3. Timestamp {ts 'yyyy-mm-dd hh:mm:ss.nnn'}
  4. ESCAPE {escape 'x'}
  5. Function {fn xxxx([arg,arg...])} NB The concat(arg, arg) operator is converted to (arg + arg)
  6. OuterJoin {oj .....}
  7. Call {?=call proc [arg, arg...]} or {call proc [arg, arg...]}
Notes:
  1. This code is designed to be as efficient as possible and as result the validation done here is limited.
  2. SQL comments are parsed correctly thanks to code supplied by Joel Fouse.
Version:
$Id: SQLParser.java,v 1.29 2007/07/08 17:28:23 bheineman Exp $
Author:
Mike Hutchinson

Nested Class Summary

private static class
SQLParser.CachedSQLQuery
Serialized version of a parsed SQL query (the value stored in the cache for a parsed SQL).

Field Summary

private static SimpleLRUCache
cache
LRU cache of previously parsed SQL
private ConnectionJDBC2
connection
Connection object for server specific parsing.
private static HashMap
cvMap
Map of jdbc to server data types for convert
private int
d
Current position in output buffer.
private static byte[]
dateMask
Syntax mask for date escape.
private static HashMap
fnMap
Map of jdbc to sybase function names.
private static boolean[]
identifierChar
Lookup table to test if character is part of an identifier.
private char[]
in
Input buffer with SQL statement.
private String
keyWord
First SQL keyword or identifier in statement.
private int
len
Length of input buffer.
private static HashMap
msFnMap
Map of jdbc to sql server function names.
private char[]
out
Output buffer to contain parsed SQL.
private ArrayList
params
Parameter list to be populated or null if no parameters are expected.
private String
procName
Procedure name in call escape.
private int
s
Current position in input buffer.
private String
sql
Original SQL string
private String
tableName
First table name in from clause
private char
terminator
Current expected terminator character.
private static byte[]
timeMask
Syntax mask for time escape.
(package private) static byte[]
timestampMask
Syntax mask for timestamp escape.

Constructor Summary

SQLParser(String sqlIn, ArrayList paramList, ConnectionJDBC2 connection)
Constructs a new parser object to process the supplied SQL.

Method Summary

private void
callEscape()
Processes the JDBC {call procedure [(?,?,?)]} type escape.
private String
copyKeyWord()
Copies over possible SQL keyword eg 'SELECT'
private void
copyLiteral(String txt)
Inserts a String literal in the output buffer.
private void
copyParam(String name, int pos)
Builds a new parameter item.
private String
copyParamName()
Copies an embedded parameter name to the output buffer.
private String
copyProcName()
Copies an embedded stored procedure identifier over to the output buffer.
private void
copyString()
Copies over an embedded string literal unchanged.
private void
copyWhiteSpace()
Copies over white space.
private void
escape()
Processes the JDBC escape sequences.
private void
functionEscape()
Processes the JDBC escape {fn function()}.
private static SimpleLRUCache
getCache(ConnectionJDBC2 connection)
Retrieves the statement cache, creating it if required.
private boolean
getDateTimeField(byte[] mask)
Utility routine to validate date and time escapes.
private String
getTableName()
Extracts the first table name following the keyword FROM.
private static boolean
isIdentifier(int ch)
Determines if character could be part of an SQL identifier.
private void
likeEscape()
Processes the JDBC escape {escape 'X'}.
private void
mustbe(char c, boolean copy)
Checks that the next character is as expected.
private void
outerJoinEscape()
Processes the JDBC escape {oj left outer join etc}.
(package private) static String[]
parse(String sql, ArrayList paramList, ConnectionJDBC2 connection, boolean extractTable)
Parse the SQL statement processing JDBC escapes and parameter markers.
(package private) String[]
parse(boolean extractTable)
Parses the SQL statement processing JDBC escapes and parameter markers.
private void
skipMultiComments()
Skips multi-line comments
private void
skipSingleComments()
Skips single-line comments.
private void
skipWhiteSpace()
Skips embedded white space.

Field Details

cache

private static SimpleLRUCache cache
LRU cache of previously parsed SQL

connection

private final ConnectionJDBC2 connection
Connection object for server specific parsing.

cvMap

private static HashMap cvMap
Map of jdbc to server data types for convert

d

private int d
Current position in output buffer.

dateMask

private static final byte[] dateMask
Syntax mask for date escape.

fnMap

private static HashMap fnMap
Map of jdbc to sybase function names.

identifierChar

private static boolean[] identifierChar
Lookup table to test if character is part of an identifier.

in

private final char[] in
Input buffer with SQL statement.

keyWord

private String keyWord
First SQL keyword or identifier in statement.

len

private final int len
Length of input buffer.

msFnMap

private static HashMap msFnMap
Map of jdbc to sql server function names.

out

private final char[] out
Output buffer to contain parsed SQL.

params

private final ArrayList params
Parameter list to be populated or null if no parameters are expected.

procName

private String procName
Procedure name in call escape.

s

private int s
Current position in input buffer.

sql

private final String sql
Original SQL string

tableName

private String tableName
First table name in from clause

terminator

private char terminator
Current expected terminator character.

timeMask

private static final byte[] timeMask
Syntax mask for time escape.

timestampMask

(package private) static final byte[] timestampMask
Syntax mask for timestamp escape.

Constructor Details

SQLParser

private SQLParser(String sqlIn,
                  ArrayList paramList,
                  ConnectionJDBC2 connection)
Constructs a new parser object to process the supplied SQL.
Parameters:
sqlIn - the SQL statement to parse
paramList - the parameter list array to populate or null if no parameters are expected
connection - the parent Connection object

Method Details

callEscape

private void callEscape()
            throws SQLException
Processes the JDBC {call procedure [(?,?,?)]} type escape.

copyKeyWord

private String copyKeyWord()
Copies over possible SQL keyword eg 'SELECT'

copyLiteral

private void copyLiteral(String txt)
            throws SQLException
Inserts a String literal in the output buffer.
Parameters:
txt - The text to insert.

copyParam

private void copyParam(String name,
                       int pos)
            throws SQLException
Builds a new parameter item.
Parameters:
name - Optional parameter name or null.
pos - The parameter marker position in the output buffer.

copyParamName

private String copyParamName()
Copies an embedded parameter name to the output buffer.
Returns:
The identifier as a String.

copyProcName

private String copyProcName()
            throws SQLException
Copies an embedded stored procedure identifier over to the output buffer.
Returns:
The identifier as a String.

copyString

private void copyString()
Copies over an embedded string literal unchanged.

copyWhiteSpace

private void copyWhiteSpace()
Copies over white space.

escape

private void escape()
            throws SQLException
Processes the JDBC escape sequences.

functionEscape

private void functionEscape()
            throws SQLException
Processes the JDBC escape {fn function()}.

getCache

private static SimpleLRUCache getCache(ConnectionJDBC2 connection)
Retrieves the statement cache, creating it if required.
Returns:
the cache as a SimpleLRUCache

getDateTimeField

private boolean getDateTimeField(byte[] mask)
            throws SQLException
Utility routine to validate date and time escapes.
Parameters:
mask - The validation mask
Returns:
True if the escape was valid and processed OK.

getTableName

private String getTableName()
            throws SQLException
Extracts the first table name following the keyword FROM.
Returns:
the table name as a String

isIdentifier

private static boolean isIdentifier(int ch)
Determines if character could be part of an SQL identifier.

Characters > 127 are assumed to be unicode letters in other languages than english which is reasonable in this application.

Parameters:
ch - the character to test.
Returns:
boolean true if ch in A-Z a-z 0-9 @ $ # _.

likeEscape

private void likeEscape()
            throws SQLException
Processes the JDBC escape {escape 'X'}.

mustbe

private void mustbe(char c,
                    boolean copy)
            throws SQLException
Checks that the next character is as expected.
Parameters:
c - The expected character.
copy - True if found character should be copied.

outerJoinEscape

private void outerJoinEscape()
            throws SQLException
Processes the JDBC escape {oj left outer join etc}.

parse

(package private) static String[] parse(String sql,
                                        ArrayList paramList,
                                        ConnectionJDBC2 connection,
                                        boolean extractTable)
            throws SQLException
Parse the SQL statement processing JDBC escapes and parameter markers.
Parameters:
extractTable - true to return the first table name in the FROM clause of a select
Returns:
The processed SQL statement, any procedure name, the first SQL keyword and (optionally) the first table name as elements 0 1, 2 and 3 of the returned String[].

parse

(package private)  String[] parse(boolean extractTable)
            throws SQLException
Parses the SQL statement processing JDBC escapes and parameter markers.
Parameters:
extractTable - true to return the first table name in the FROM clause of a select
Returns:
The processed SQL statement, any procedure name, the first SQL keyword and (optionally) the first table name as elements 0 1, 2 and 3 of the returned String[].

skipMultiComments

private void skipMultiComments()
            throws SQLException
Skips multi-line comments

skipSingleComments

private void skipSingleComments()
Skips single-line comments.

skipWhiteSpace

private void skipWhiteSpace()
Skips embedded white space.

Generated on September 18 2009