Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Firebird Open Source J2ee connector - jdbc driver
   *
   * Distributable under LGPL license.
   * You may obtain a copy of the License at http://www.gnu.org/copyleft/lgpl.html
   *
   * This program 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
  * LGPL License for more details.
  *
  * This file was created by members of the firebird development team.
  * All individual contributions remain the Copyright (C) of those
  * individuals.  Contributors to this file are either listed here or
  * can be obtained from a CVS history command.
  *
  * All rights reserved.
  */
 
 package org.firebirdsql.jdbc;
 
The class FBEscapedParser parses the SQL and converts escaped syntax to native form.

Author(s):
Roman Rokytskyy
Version:
1.0
 
 public class FBEscapedParser {
     
     public static final int USE_BUILT_IN = 0;
     public static final int USE_STANDARD_UDF = 1;
     
     /*
      * Currently we have three states, normal when we simply copy characters
      * from source to destination, escape state, when we extract the escaped
      * syntax and  literal, when we do copy characters from  source to
      * destination but we cannot enter the escape state.
      *
      * Currently these states seems to be exclusive, but later meanings may be
      * extended, so we use the bit scale to map the state.
      */
     protected static final int UNDEFINED_STATE = 0;
     protected static final int NORMAL_STATE = 1;
     protected static final int LITERAL_STATE = 2;
     protected static final int ESCAPE_STATE = 4;
 
     /*
      Stored procedure calls support both following syntax:
         {call procedure_name[(arg1, arg2, ...)]}
      or
         {?= call procedure_name[(arg1, arg2, ...)]}
      */
     public static final String ESCAPE_CALL_KEYWORD = "call";
     public static final String ESCAPE_CALL_KEYWORD3 = "?";
     public static final String ESCAPE_DATE_KEYWORD = "d";
     public static final String ESCAPE_TIME_KEYWORD = "t";
     public static final String ESCAPE_TIMESTAMP_KEYWORD = "ts";
     public static final String ESCAPE_FUNCTION_KEYWORD = "fn";
     public static final String ESCAPE_ESCAPE_KEYWORD = "escape";
     public static final String ESCAPE_OUTERJOIN_KEYWORS = "oj";
 
     /*
      * These constants are necessary to speed up checking the
      * SQL statements by avoiding the complete parsing if the
      * SQL statement does not contain any of the substrings.
      */
     protected static final String CHECK_CALL_1 = "{call";
     protected static final String CHECK_CALL_2 = "{?";
     protected static final String CHECK_DATE = "{d";
     protected static final String CHECK_TIME = "{t";
     protected static final String CHECK_TIMESTAMP = "{ts";
     protected static final String CHECK_FUNCTION = "{fn";
     protected static final String CHECK_ESCAPE = "{escape";
     protected static final String CHECK_OUTERJOIN = "{oj";
 
     private int state = ;
     private int lastState = ;
     private int nestedEscaped = 0;
 
     private int mode;
     
     public FBEscapedParser(int mode) {
         this. = mode;
     }
    
    
Returns the current state.
 
     protected int getLastState() { return ; }

    
Returns the current state.
 
     protected int getState() { return ; }

    
Sets the current state.

Parameters:
state to enter.
Throws:
java.lang.IllegalStateException if the system cannot enter the desired state.
    protected void setState(int statethrows IllegalStateException {
        int tempState = getLastState();
         = getState();
        if (state == )
            this. = ;
        else
        if (state == )
            this. = ;
        else
        if (state == )
            this. = ;
        else {
             = tempState;
            throw new IllegalStateException("State " + state + " is unknown.");
        }
    }

    
Returns if the system is in state state.

Parameters:
state we're testing
Returns:
true if the system is in state state.
    protected boolean isInState(int state) { return getState() == state; }

    
Returns if the system was in state state.

Parameters:
state we're testing
Returns:
true if the system was in state state.
    protected boolean wasInState(int state) { return getLastState() == state; }

    
Test the character to be the state switching character and switches the state if necessary.

Parameters:
testChar character to test
    protected void switchState(char testChar) {
            switch (testChar) {
                case '\'' : {
                    if (isInState())
                        setState();
                    else
                    if (isInState())
                        setState();
                    break;
                }
                case '{' : {
                    if (isInState())
                        setState();
                    ++;
                    break;
                }
                case '}' : {
                    if (isInState())
                        --;
                    if ( == 0)
                        setState();
                    break;
                }
            }
    }

    
Check if the target SQL contains at least one of the escaped syntax commands. This method performs simple substring matching, so it may report that SQL contains escaped syntax when the "{" is followed by the escaped syntax command in regular string constants that are passed as parameters. In this case parse(java.lang.String) will perform complete SQL parsing.

Parameters:
sql to test
Returns:
true if the sql is suspected to contain escaped syntax.
    protected boolean checkForEscapes(String sql) {
        sql = sql.toLowerCase();
        
        return  sql.indexOf() != -1 ||
                sql.indexOf() != -1 ||
                sql.indexOf() != -1 ||
                sql.indexOf() != -1 ||
                sql.indexOf() != -1 ||
                sql.indexOf() != -1 ||
                sql.indexOf() != -1 ||
                sql.indexOf() != -1;
    }

    
Converts escaped parts in the passed SQL to native representation.

Parameters:
sql to parse
Returns:
native form of the sql.
    public String parse(String sqlthrows FBSQLException {
        
         = ;
         = ;
         = 0;
        if (!checkForEscapes(sql))
            return sql;
        char[] sqlbuff = sql.toCharArray();
        StringBuffer buffer = new StringBuffer();
        StringBuffer escape = new StringBuffer();
        for(int i = 0; i < sqlbuff.lengthi++) {
            switchState(sqlbuff[i]);
            if (isInState() &&
                    (wasInState() || wasInState()))
                buffer.append(sqlbuff[i]);
            else
            if (isInState() && wasInState()) {
                // escape now is in form "{...." without trailing '}'...
                buffer.append(escapeToNative(escape.substring(1, escape.length())));
                escape = new StringBuffer();
                setState();
            } else
            if (isInState())
                escape.append(sqlbuff[i]);
            else
            if (isInState())
                buffer.append(sqlbuff[i]);
        }
        return buffer.toString();
    }
    protected void processEscaped(String escapedStringBuffer keyword,
        StringBuffer payload)
    {
        if (keyword.length() != 0) keyword.delete(0, keyword.length());
        if (payload.length() != 0) payload.delete(0, payload.length());
        /*
         * Extract the keyword from the escaped syntax.
         */
        BreakIterator iterator = BreakIterator.getWordInstance();
        iterator.setText(escaped);
        int keyStart = iterator.first();
        int keyEnd = iterator.next();
        keyword.append(escaped.substring(keyStartkeyEnd));
        payload.append(escaped.substring(keyEndescaped.length()));
    }

    
This method checks the passed parameter to conform the escaped syntax, checks for the unknown keywords and re-formats result according to the Firebird SQL syntax.

Parameters:
escaped the part of escaped SQL between the '{' and '}'.
Returns:
the native representation of the SQL code.
    protected String escapeToNative(String escapedthrows FBSQLException {
        StringBuffer keyword = new StringBuffer();
        StringBuffer payload = new StringBuffer();
        processEscaped(escapedkeywordpayload);
        /*
         * Handle keywords.
         */
        if (keyword.toString().equalsIgnoreCase()){
            
            StringBuffer call = new StringBuffer();
            call
                .append('{')
                .append(keyword)
                .append(' ')
                .append(payload)
                .append('}');
            
            return convertProcedureCall(call.toString());
        
        } else
        if (keyword.toString().equalsIgnoreCase()) {
            
            StringBuffer call = new StringBuffer();
            
            call
                .append('{')
                .append()
                .append(payload)
                .append('}');
            
            return convertProcedureCall(call.toString());
        } else
        if (keyword.toString().equalsIgnoreCase())
            return toDateString(payload.toString().trim());
        else
        if (keyword.toString().equalsIgnoreCase())
            return convertEscapeString(payload.toString().trim());
        else
        if (keyword.toString().equalsIgnoreCase())
            return convertEscapedFunction(payload.toString().trim());
        else
        if (keyword.toString().equalsIgnoreCase())
            return convertOuterJoin(payload.toString().trim());
        else
        if (keyword.toString().equalsIgnoreCase())
            return toTimeString(payload.toString().trim());
        else
        if (keyword.toString().equalsIgnoreCase())
            return toTimestampString(payload.toString().trim());
        else
            throw new FBSQLParseException(
                "Unknown keyword " + keyword + " for escaped syntax.");
    }

    
This method converts the 'yyyy-mm-dd' date format into the Firebird understandable format.

Parameters:
dateStr the date in the 'yyyy-mm-dd' format.
Returns:
Firebird understandable date format.
    protected String toDateString(String dateStrthrows FBSQLParseException {
        /*
         * We assume that Firebird can handle the 'yyyy-mm-dd' date format.
         */
        return dateStr;
    }

    
This method converts the 'hh:mm:ss' time format into the Firebird understandable format.

Parameters:
timeStr the date in the 'hh:mm:ss' format.
Returns:
Firebird understandable date format.
    protected String toTimeString(String timeStrthrows FBSQLParseException {
        /*
         * We assume that Firebird can handle the 'hh:mm:ss' date format.
         */
        return timeStr;
    }

    
This method converts the 'yyyy-mm-dd hh:mm:ss' timestamp format into the Firebird understandable format.

Parameters:
timestampStr the date in the 'yyyy-mm-dd hh:mm:ss' format.
Returns:
Firebird understandable date format.
    protected String toTimestampString(String timestampStr)
        throws FBSQLParseException
    {
        /*
         * We assume that Firebird can handle the 'dd.mm.yyyy hh:mm:ss' date format.
         */
        return timestampStr;
    }

    
This methods converts the escaped procedure call syntax into the native procedure call.

Parameters:
procedureCall part of {call proc_name(...)} without curly braces and "call" word.
Returns:
native procedure call.
    protected String convertProcedureCall(String procedureCall)
        throws FBSQLException
    {
        FBEscapedCallParser tempParser = new FBEscapedCallParser();
        FBProcedureCall call = tempParser.parseCall(procedureCall);
        return call.getSQL(false);
    }

    
This method converts the escaped outer join call syntax into the native outer join. Actually, we do not change anything here, since Firebird's syntax is the same.
    protected String convertOuterJoin(String outerJoin)
        throws FBSQLParseException
    {
        return outerJoin;
    }

    
Convert the "{escape '...'}" call into the corresponding escape clause for Firebird.

Parameters:
escapeString escape string to convert
Returns:
converted code.
    protected String convertEscapeString(String escapeString) {
        return "ESCAPE " + escapeString;
    }
    
    
This method converts escaped function to a server function call. Actually we do not change anything here, we hope that all UDF are defined.

Parameters:
escapedFunction escaped function call
Returns:
server-side function call.
Throws:
FBSQLParseException if something was wrong.
    protected String convertEscapedFunction(String escapedFunction)
        throws FBSQLParseException
    {
        String templateResult = 
            FBEscapedFunctionHelper.convertTemplate(escapedFunction);
        
        if (templateResult != null)
            return templateResult;
        else
            return escapedFunction;
    }
    public static boolean supportsStoredProcedures() {
        return true;
    }
    public static boolean supportsLikeEscapeClause() {
        return false;
    }
New to GrepCode? Check out our FAQ X