public static void parse(String sqlString,
ParameterParser.Recognizer recognizer) throws QueryException {
boolean hasMainOutputParameter = sqlString.indexOf( "call" ) > 0 &&
sqlString.indexOf( "?" ) < sqlString.indexOf( "call" ) &&
sqlString.indexOf( "=" ) < sqlString.indexOf( "call" );
boolean foundMainOutputParam = false;
int stringLength = sqlString.length();
boolean inQuote = false;
for ( int indx = 0; indx < stringLength; indx++ ) {
char c = sqlString.charAt( indx );
if ( inQuote ) {
if ( '\'" == c ) {
inQuote = false;
}
recognizer.other( c );
}
else if ( '\'" == c ) {
inQuote = true;
recognizer.other( c );
}
else {
if ( c == ':" ) {
// named parameter
int right = StringHelper.firstIndexOfChar( sqlString, ParserHelper.HQL_SEPARATORS, indx + 1 );
int chopLocation = right < 0 ? sqlString.length() : right;
String param = sqlString.substring( indx + 1, chopLocation );
recognizer.namedParameter( param, indx );
indx = chopLocation - 1;
}
else if ( c == '?" ) {
// could be either an ordinal or ejb3-positional parameter
if ( indx < stringLength - 1 && Character.isDigit( sqlString.charAt( indx + 1 ) ) ) {
// a peek ahead showed this as an ejb3-positional parameter
int right = StringHelper.firstIndexOfChar( sqlString, ParserHelper.HQL_SEPARATORS, indx + 1 );
int chopLocation = right < 0 ? sqlString.length() : right;
String param = sqlString.substring( indx + 1, chopLocation );
// make sure this "name" is an integral
try {
new Integer( param );
}
catch( NumberFormatException e ) {
throw new QueryException( "ejb3-style positional param was not an integral ordinal" );
}
recognizer.ejb3PositionalParameter( param, indx );
indx = chopLocation - 1;
}
else {
if ( hasMainOutputParameter && !foundMainOutputParam ) {
foundMainOutputParam = true;
recognizer.outParameter( indx );
}
else {
recognizer.ordinalParameter( indx );
}
}
}
else {
recognizer.other( c );
}
}
}
}
Performs the actual parsing and tokenizing of the query string making appropriate
callbacks to the given recognizer upon recognition of the various tokens.
Note that currently, this only knows how to deal with a single output
parameter (for callable statements). If we later add support for
multiple output params, this, obviously, needs to change. |