⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 escapeprocessor.java

📁 Java写的TDS协议(JDBC/ODBC)实现
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
        if( startsWithIgnoreCase(str, ESCAPE_PREFIX_FUNCTION) )
        {
            str = str.substring(ESCAPE_PREFIX_FUNCTION.length());
            result = expandCommonFunction(str);

            if( result == null )
                result = expandDBSpecificFunction(str);

            if( result == null )
                result = str;
        }
        else if( startsWithIgnoreCase(str, ESCAPE_PREFIX_CALL) ||
            (str.startsWith("?=") && startsWithIgnoreCase(str.substring(2).trim(), ESCAPE_PREFIX_CALL)) )
        {
            boolean returnsVal = str.startsWith("?=");
            str = str.substring(str.indexOf("call")+4).trim();
            int pPos = str.indexOf('(');
            if( pPos >= 0 )
            {
                if( str.charAt(str.length()-1) != ')' )
                    throw new SQLException("Malformed procedure call: "+str);
                result = "exec "+(returnsVal ? "?=" : "")+str.substring(0, pPos)+
                    " "+str.substring(pPos+1, str.length()-1);
            }
            else
                result = "exec "+(returnsVal ? "?=" : "")+str;
        }
        else if( startsWithIgnoreCase(str, ESCAPE_PREFIX_DATE) )
            result = getDate(str);
        else if( startsWithIgnoreCase(str, ESCAPE_PREFIX_TIME) )
            result = getTime(str);
        else if( startsWithIgnoreCase(str, ESCAPE_PREFIX_TIMESTAMP) )
            result = getTimestamp(str);
        else if( startsWithIgnoreCase(str, ESCAPE_PREFIX_OUTER_JOIN) )
            result = str.substring(ESCAPE_PREFIX_OUTER_JOIN.length()).trim();
        else
            throw new SQLException("Unrecognized escape sequence: " + escapeSequence);

        return result;
    }

    /**
     * Expand functions that are common to both SQLServer and Sybase
     */
    public String expandCommonFunction(String str) throws SQLException
    {
        String result = null;
        int pPos = str.indexOf('(');

        if( pPos < 0 )
            throw new SQLException("Malformed function escape: "+str);
        String fName = str.substring(0, pPos).trim();

        // @todo Implement this in a smarter way
        if( fName.equalsIgnoreCase("user") )
            result = "user_name" + str.substring(pPos);
        else if( fName.equalsIgnoreCase("database") )
            result = "db_name" + str.substring(pPos);
        else if( fName.equalsIgnoreCase("ifnull") )
            result = "isnull" + str.substring(pPos);
        else if( fName.equalsIgnoreCase("now") )
            result = "getdate" + str.substring(pPos);
        else if( fName.equalsIgnoreCase("atan2") )
            result = "atn2" + str.substring(pPos);
        else if( fName.equalsIgnoreCase("length") )
            result = "len" + str.substring(pPos);
        else if( fName.equalsIgnoreCase("locate") )
            result = "charindex" + str.substring(pPos);
        else if( fName.equalsIgnoreCase("repeat") )
            result = "replicate" + str.substring(pPos);
        else if( fName.equalsIgnoreCase("insert") )
            result = "stuff" + str.substring(pPos);
        else if( fName.equalsIgnoreCase("lcase") )
            result = "lower" + str.substring(pPos);
        else if( fName.equalsIgnoreCase("ucase") )
            result = "upper" + str.substring(pPos);

        return result;
    }

    public String nativeString() throws SQLException
    {
        return nativeString(input, '\\');
    }

    private String nativeString(String sql, char escapeCharacter) throws SQLException
    {
        StringBuffer result = new StringBuffer(sql.length());

        String escape = "";
        int    i;

        // Simple finite state machine.  Bonehead, but it works.
        final int   normal                        = 0;

        final int   inString                      = 1;
        final int   inStringWithBackquote         = 2;

        final int   inEscape                      = 3;
        final int   inEscapeInString              = 4;
        final int   inEscapeInStringWithBackquote = 5;

        int         state = normal;
        char        ch;

        int escapeStartedAt = -1;
        i = 0;
        while( i < sql.length() )
        {
            ch = sql.charAt(i);
            switch( state )
            {
                case normal:
                {
                    if( ch == '{' )
                    {
                        escapeStartedAt = i;
                        state = inEscape;
                        escape = "";
                    }
                    else
                    {
                       result.append(ch);
                       if( ch == '\'' )
                           state = inString;
                    }
                    break;
                }
                case inString:
                case inStringWithBackquote:
                {
                    if( (i+1)<sql.length() && ch==escapeCharacter &&
                        (sql.charAt(i+1)=='_' || sql.charAt(i+1)=='%') )
                    {
                        i++;
                        ch = sql.charAt(i);
                        result.append('\\');
                        result.append(ch);
                    }
                    else
                    {
                        result.append(ch);
                        if( state == inStringWithBackquote )
                        {
                            state = inString;
                        }
                        else
                        {
                            if( ch == '\\' ) state = inStringWithBackquote;
                            if( ch == '\'' ) state = normal;
                        }
                    }
                    break;
                }
                case inEscape:
                {
                    if( ch == '}' )
                    {
                        // XXX Is it always okay to trim leading and trailing blanks?
                        escape = escape.trim();

                        // At this point there are a couple of things to
                        // consider.  First, if the escape is of the form
                        // "{escape 'c'} but it is not at the end of the SQL
                        // we consider that a malformed SQL string.  If it
                        // is the "{escape 'c'}" clause and it is at the end
                        // of the string then we have to go through and
                        // reparse this whole thing again, this time with an
                        // escape character.  Any other escape is handled in
                        // the expandEscape method()

                        if( startsWithIgnoreCase(escape, ESCAPE_PREFIX_ESCAPE_CHAR) )
                        {
                            char c;

                            // make sure it is the last thing in the sql
                            if( i+1 != sql.length() )
                                throw new SQLException("Malformed statement. Escape clause must " +
                                    "be at the end of the query.");

                            /** @todo Avoid reparsing the query with the escape character */
                            // parse the sql again, this time without the ending string but with the
                            // escape character set

                            c = findEscapeCharacter(escape);

                            result.delete(0,result.length());
                            result.append(nativeString(sql.substring(0, escapeStartedAt), c));
                            state = normal;
                        }
                        else
                        {
                            state = normal;
                            result.append(expandEscape(escape));
                            escapeStartedAt = -1;
                        }
                    }
                    else
                    {
                        escape = escape + ch;
                        if( ch == '\'' ) state = inEscapeInString;
                    }
                    break;
                }
                case inEscapeInString:
                case inEscapeInStringWithBackquote:
                {
                    escape = escape + ch;

                    if( state == inEscapeInStringWithBackquote )
                        state = inEscapeInString;
                    else
                    {
                        // SAfe This backslash in escape string is wrong. Someone might want to use backslash as escape
                        //      character. Then it would look like: {escape '\'} <- no backslash escaping.
//                        if( ch == '\\' ) state = inEscapeInStringWithBackquote;
                        if( ch == '\'' ) state = inEscape;
                    }
                    break;
                }
                default:
                    throw new SQLException("Internal error.  Unknown state in FSM");
            }
            i++;
        }

        if( state!=normal && state!=inString )
           throw new SQLException("Syntax error in SQL escape syntax");

        return result.toString();
    } // nativeString()

    static char findEscapeCharacter(String escape)
        throws SQLException
    {
        String str = escape.trim();

        if( !str.substring(0, 6).equalsIgnoreCase("escape") )
            throw new SQLException("Internal Error");

        str = str.substring(6).trim();
        if( str.length()!=3 || str.charAt(0)!='\'' || str.charAt(2)!='\'' )
            throw new SQLException("Malformed escape clause: |" + escape + "|");

        return str.charAt(1);
    }

    public static boolean startsWithIgnoreCase(String s, String prefix)
    {
        if( s.length() < prefix.length() )
            return false;

        for( int i=prefix.length()-1; i>=0; i-- )
            if( Character.toLowerCase(s.charAt(i)) != Character.toLowerCase(prefix.charAt(i)) )
                return false;

        return true;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -