Class Parser


  • public class Parser
    extends java.lang.Object
    Basic query parser infrastructure. Note: This class should not be considered as pgjdbc public API.
    • Nested Class Summary

      Nested Classes 
      Modifier and Type Class Description
      private static class  Parser.SqlParseState  
    • Constructor Summary

      Constructors 
      Constructor Description
      Parser()  
    • Method Summary

      All Methods Static Methods Concrete Methods 
      Modifier and Type Method Description
      private static boolean addReturning​(java.lang.StringBuilder nativeSql, SqlCommandType currentCommandType, java.lang.String[] returningColumnNames, boolean isReturningPresent)  
      static boolean charTerminatesIdentifier​(char c)  
      private static void checkParsePosition​(int i, int len, int i0, char[] sql, java.lang.String message)  
      static int digitAt​(java.lang.String s, int pos)
      Converts digit at position pos in string s to integer or throws.
      private static int escapeFunction​(char[] sql, int i, java.lang.StringBuilder newsql, boolean stdStrings)  
      private static int escapeFunctionArguments​(java.lang.StringBuilder newsql, java.lang.String functionName, char[] sql, int i, boolean stdStrings)
      Generate sql for escaped functions.
      private static int findOpenBrace​(char[] sql, int i)  
      static boolean isArrayWhiteSpace​(char c)
      Identifies white space characters which the backend uses to determine if a String value needs to be quoted in array representation.
      static boolean isDigitAt​(java.lang.String s, int pos)
      Returns true if a given string s has digit at position pos.
      static boolean isDollarQuoteContChar​(char c)
      Checks if a character is valid as the second or later character of a dollar quoting tag.
      static boolean isDollarQuoteStartChar​(char c)
      Checks if a character is valid as the start of a dollar quoting tag.
      static boolean isIdentifierContChar​(char c)
      Checks if a character is valid as the second or later character of an identifier.
      static boolean isIdentifierStartChar​(char c)
      Checks if a character is valid as the start of an identifier.
      static boolean isOperatorChar​(char c)  
      static boolean isSpace​(char c)
      Identifies characters which the backend scanner considers to be whitespace.
      static JdbcCallParseInfo modifyJdbcCall​(java.lang.String jdbcSql, boolean stdStrings, int serverVersion, int protocolVersion, EscapeSyntaxCallMode escapeSyntaxCallMode)
      Converts JDBC-specific callable statement escapes { [? =] call <some_function> [(?, [?,..])] } into the PostgreSQL format which is select <some_function> (?, [?, ...]) as result or select * from <some_function> (?, [?, ...]) as result (7.3)
      static boolean parseAsKeyword​(char[] query, int offset)
      Parse string to check presence of AS keyword regardless of case.
      static int parseBlockComment​(char[] query, int offset)
      Test if the / character at offset starts a block comment, and return the position of the last / character.
      static boolean parseDeleteKeyword​(char[] query, int offset)
      Parse string to check presence of DELETE keyword regardless of case.
      static int parseDollarQuotes​(char[] query, int offset)
      Test if the dollar character ($) at the given offset starts a dollar-quoted string and return the offset of the ending dollar character.
      static int parseDoubleQuotes​(char[] query, int offset)
      Find the end of the double-quoted string starting at the given offset.
      static boolean parseInsertKeyword​(char[] query, int offset)
      Parse string to check presence of INSERT keyword regardless of case.
      static java.util.List<NativeQuery> parseJdbcSql​(java.lang.String query, boolean standardConformingStrings, boolean withParameters, boolean splitStatements, boolean isBatchedReWriteConfigured, java.lang.String... returningColumnNames)
      Parses JDBC query into PostgreSQL's native format.
      static int parseLineComment​(char[] query, int offset)
      Test if the - character at offset starts a -- style line comment, and return the position of the first \r or \n character.
      static long parseLong​(java.lang.String s, int beginIndex, int endIndex)
      Faster version of Long.parseLong(String) when parsing a substring is required
      static boolean parseMoveKeyword​(char[] query, int offset)
      Parse string to check presence of MOVE keyword regardless of case.
      static boolean parseReturningKeyword​(char[] query, int offset)
      Parse string to check presence of RETURNING keyword regardless of case.
      static boolean parseSelectKeyword​(char[] query, int offset)
      Parse string to check presence of SELECT keyword regardless of case.
      static int parseSingleQuotes​(char[] query, int offset, boolean standardConformingStrings)
      Find the end of the single-quoted string starting at the given offset.
      private static int parseSql​(char[] sql, int i, java.lang.StringBuilder newsql, boolean stopOnComma, boolean stdStrings)
      parse the given sql from index i, appending it to the given buffer until we hit an unmatched right parentheses or end of string.
      static boolean parseUpdateKeyword​(char[] query, int offset)
      Parse string to check presence of UPDATE keyword regardless of case.
      static boolean parseValuesKeyword​(char[] query, int offset)
      Parse string to check presence of VALUES keyword regardless of case.
      private static SqlCommandType parseWithCommandType​(char[] aChars, int i, int keywordStart, int wordLength)  
      static boolean parseWithKeyword​(char[] query, int offset)
      Parse string to check presence of WITH keyword regardless of case.
      static java.lang.String replaceProcessing​(java.lang.String sql, boolean replaceProcessingEnabled, boolean standardConformingStrings)
      Filter the SQL string of Java SQL Escape clauses.
      private static boolean subArraysEqual​(char[] arr, int offA, int offB, int len)
      Compares two sub-arrays of the given character array for equalness.
      private static int[] toIntArray​(java.util.List<java.lang.Integer> list)
      Converts List<Integer> to int[].
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Field Detail

      • NO_BINDS

        private static final int[] NO_BINDS
      • QUOTE_OR_ALPHABETIC_MARKER

        private static final char[] QUOTE_OR_ALPHABETIC_MARKER
      • QUOTE_OR_ALPHABETIC_MARKER_OR_PARENTHESIS

        private static final char[] QUOTE_OR_ALPHABETIC_MARKER_OR_PARENTHESIS
      • SINGLE_QUOTE

        private static final char[] SINGLE_QUOTE
    • Constructor Detail

      • Parser

        public Parser()
    • Method Detail

      • parseJdbcSql

        public static java.util.List<NativeQuery> parseJdbcSql​(java.lang.String query,
                                                               boolean standardConformingStrings,
                                                               boolean withParameters,
                                                               boolean splitStatements,
                                                               boolean isBatchedReWriteConfigured,
                                                               java.lang.String... returningColumnNames)
                                                        throws java.sql.SQLException
        Parses JDBC query into PostgreSQL's native format. Several queries might be given if separated by semicolon.
        Parameters:
        query - jdbc query to parse
        standardConformingStrings - whether to allow backslashes to be used as escape characters in single quote literals
        withParameters - whether to replace ?, ? with $1, $2, etc
        splitStatements - whether to split statements by semicolon
        isBatchedReWriteConfigured - whether re-write optimization is enabled
        returningColumnNames - for simple insert, update, delete add returning with given column names
        Returns:
        list of native queries
        Throws:
        java.sql.SQLException - if unable to add returning clause (invalid column names)
      • parseWithCommandType

        private static SqlCommandType parseWithCommandType​(char[] aChars,
                                                           int i,
                                                           int keywordStart,
                                                           int wordLength)
      • addReturning

        private static boolean addReturning​(java.lang.StringBuilder nativeSql,
                                            SqlCommandType currentCommandType,
                                            java.lang.String[] returningColumnNames,
                                            boolean isReturningPresent)
                                     throws java.sql.SQLException
        Throws:
        java.sql.SQLException
      • toIntArray

        private static int[] toIntArray​(java.util.List<java.lang.Integer> list)
        Converts List<Integer> to int[]. Empty and null lists are converted to empty array.
        Parameters:
        list - input list
        Returns:
        output array
      • parseSingleQuotes

        public static int parseSingleQuotes​(char[] query,
                                            int offset,
                                            boolean standardConformingStrings)

        Find the end of the single-quoted string starting at the given offset.

        Note: for 'single '' quote in string', this method currently returns the offset of first ' character after the initial one. The caller must call the method a second time for the second part of the quoted string.

        Parameters:
        query - query
        offset - start offset
        standardConformingStrings - standard conforming strings
        Returns:
        position of the end of the single-quoted string
      • parseDoubleQuotes

        public static int parseDoubleQuotes​(char[] query,
                                            int offset)

        Find the end of the double-quoted string starting at the given offset.

        Note: for "double "" quote in string", this method currently returns the offset of first &quot; character after the initial one. The caller must call the method a second time for the second part of the quoted string.

        Parameters:
        query - query
        offset - start offset
        Returns:
        position of the end of the double-quoted string
      • parseDollarQuotes

        public static int parseDollarQuotes​(char[] query,
                                            int offset)
        Test if the dollar character ($) at the given offset starts a dollar-quoted string and return the offset of the ending dollar character.
        Parameters:
        query - query
        offset - start offset
        Returns:
        offset of the ending dollar character
      • parseLineComment

        public static int parseLineComment​(char[] query,
                                           int offset)
        Test if the - character at offset starts a -- style line comment, and return the position of the first \r or \n character.
        Parameters:
        query - query
        offset - start offset
        Returns:
        position of the first \r or \n character
      • parseBlockComment

        public static int parseBlockComment​(char[] query,
                                            int offset)
        Test if the / character at offset starts a block comment, and return the position of the last / character.
        Parameters:
        query - query
        offset - start offset
        Returns:
        position of the last / character
      • parseDeleteKeyword

        public static boolean parseDeleteKeyword​(char[] query,
                                                 int offset)
        Parse string to check presence of DELETE keyword regardless of case. The initial character is assumed to have been matched.
        Parameters:
        query - char[] of the query statement
        offset - position of query to start checking
        Returns:
        boolean indicates presence of word
      • parseInsertKeyword

        public static boolean parseInsertKeyword​(char[] query,
                                                 int offset)
        Parse string to check presence of INSERT keyword regardless of case.
        Parameters:
        query - char[] of the query statement
        offset - position of query to start checking
        Returns:
        boolean indicates presence of word
      • parseMoveKeyword

        public static boolean parseMoveKeyword​(char[] query,
                                               int offset)
        Parse string to check presence of MOVE keyword regardless of case.
        Parameters:
        query - char[] of the query statement
        offset - position of query to start checking
        Returns:
        boolean indicates presence of word
      • parseReturningKeyword

        public static boolean parseReturningKeyword​(char[] query,
                                                    int offset)
        Parse string to check presence of RETURNING keyword regardless of case.
        Parameters:
        query - char[] of the query statement
        offset - position of query to start checking
        Returns:
        boolean indicates presence of word
      • parseSelectKeyword

        public static boolean parseSelectKeyword​(char[] query,
                                                 int offset)
        Parse string to check presence of SELECT keyword regardless of case.
        Parameters:
        query - char[] of the query statement
        offset - position of query to start checking
        Returns:
        boolean indicates presence of word
      • parseUpdateKeyword

        public static boolean parseUpdateKeyword​(char[] query,
                                                 int offset)
        Parse string to check presence of UPDATE keyword regardless of case.
        Parameters:
        query - char[] of the query statement
        offset - position of query to start checking
        Returns:
        boolean indicates presence of word
      • parseValuesKeyword

        public static boolean parseValuesKeyword​(char[] query,
                                                 int offset)
        Parse string to check presence of VALUES keyword regardless of case.
        Parameters:
        query - char[] of the query statement
        offset - position of query to start checking
        Returns:
        boolean indicates presence of word
      • parseLong

        public static long parseLong​(java.lang.String s,
                                     int beginIndex,
                                     int endIndex)
        Faster version of Long.parseLong(String) when parsing a substring is required
        Parameters:
        s - string to parse
        beginIndex - begin index
        endIndex - end index
        Returns:
        long value
      • parseWithKeyword

        public static boolean parseWithKeyword​(char[] query,
                                               int offset)
        Parse string to check presence of WITH keyword regardless of case.
        Parameters:
        query - char[] of the query statement
        offset - position of query to start checking
        Returns:
        boolean indicates presence of word
      • parseAsKeyword

        public static boolean parseAsKeyword​(char[] query,
                                             int offset)
        Parse string to check presence of AS keyword regardless of case.
        Parameters:
        query - char[] of the query statement
        offset - position of query to start checking
        Returns:
        boolean indicates presence of word
      • isDigitAt

        public static boolean isDigitAt​(java.lang.String s,
                                        int pos)
        Returns true if a given string s has digit at position pos.
        Parameters:
        s - input string
        pos - position (0-based)
        Returns:
        true if input string s has digit at position pos
      • digitAt

        public static int digitAt​(java.lang.String s,
                                  int pos)
        Converts digit at position pos in string s to integer or throws.
        Parameters:
        s - input string
        pos - position (0-based)
        Returns:
        integer value of a digit at position pos
        Throws:
        java.lang.NumberFormatException - if character at position pos is not an integer
      • isSpace

        public static boolean isSpace​(char c)
        Identifies characters which the backend scanner considers to be whitespace.

        https://github.com/postgres/postgres/blob/17bb62501787c56e0518e61db13a523d47afd724/src/backend/parser/scan.l#L194-L198

        Parameters:
        c - character
        Returns:
        true if the character is a whitespace character as defined in the backend's parser
      • isArrayWhiteSpace

        public static boolean isArrayWhiteSpace​(char c)
        Identifies white space characters which the backend uses to determine if a String value needs to be quoted in array representation.

        https://github.com/postgres/postgres/blob/f2c587067a8eb9cf1c8f009262381a6576ba3dd0/src/backend/utils/adt/arrayfuncs.c#L421-L438

        Parameters:
        c - Character to examine.
        Returns:
        Indication if the character is a whitespace which back end will escape.
      • isOperatorChar

        public static boolean isOperatorChar​(char c)
        Parameters:
        c - character
        Returns:
        true if the given character is a valid character for an operator in the backend's parser
      • isIdentifierStartChar

        public static boolean isIdentifierStartChar​(char c)
        Checks if a character is valid as the start of an identifier. PostgreSQL 9.4 allows column names like _, ‿, ⁀, ⁔, ︳, ︴, ﹍, ﹎, ﹏, _, so it is assumed isJavaIdentifierPart is good enough for PostgreSQL.
        Parameters:
        c - the character to check
        Returns:
        true if valid as first character of an identifier; false if not
        See Also:
        Identifiers and Key Words
      • isIdentifierContChar

        public static boolean isIdentifierContChar​(char c)
        Checks if a character is valid as the second or later character of an identifier.
        Parameters:
        c - the character to check
        Returns:
        true if valid as second or later character of an identifier; false if not
      • charTerminatesIdentifier

        public static boolean charTerminatesIdentifier​(char c)
        Parameters:
        c - character
        Returns:
        true if the character terminates an identifier
      • isDollarQuoteStartChar

        public static boolean isDollarQuoteStartChar​(char c)
        Checks if a character is valid as the start of a dollar quoting tag.
        Parameters:
        c - the character to check
        Returns:
        true if valid as first character of a dollar quoting tag; false if not
      • isDollarQuoteContChar

        public static boolean isDollarQuoteContChar​(char c)
        Checks if a character is valid as the second or later character of a dollar quoting tag.
        Parameters:
        c - the character to check
        Returns:
        true if valid as second or later character of a dollar quoting tag; false if not
      • subArraysEqual

        private static boolean subArraysEqual​(char[] arr,
                                              int offA,
                                              int offB,
                                              int len)
        Compares two sub-arrays of the given character array for equalness. If the length is zero, the result is true if and only if the offsets are within the bounds of the array.
        Parameters:
        arr - a char array
        offA - first sub-array start offset
        offB - second sub-array start offset
        len - length of the sub arrays to compare
        Returns:
        true if the sub-arrays are equal; false if not
      • modifyJdbcCall

        public static JdbcCallParseInfo modifyJdbcCall​(java.lang.String jdbcSql,
                                                       boolean stdStrings,
                                                       int serverVersion,
                                                       int protocolVersion,
                                                       EscapeSyntaxCallMode escapeSyntaxCallMode)
                                                throws java.sql.SQLException
        Converts JDBC-specific callable statement escapes { [? =] call <some_function> [(?, [?,..])] } into the PostgreSQL format which is select <some_function> (?, [?, ...]) as result or select * from <some_function> (?, [?, ...]) as result (7.3)
        Parameters:
        jdbcSql - sql text with JDBC escapes
        stdStrings - if backslash in single quotes should be regular character or escape one
        serverVersion - server version
        protocolVersion - protocol version
        escapeSyntaxCallMode - mode specifying whether JDBC escape call syntax is transformed into a CALL/SELECT statement
        Returns:
        SQL in appropriate for given server format
        Throws:
        java.sql.SQLException - if given SQL is malformed
      • replaceProcessing

        public static java.lang.String replaceProcessing​(java.lang.String sql,
                                                         boolean replaceProcessingEnabled,
                                                         boolean standardConformingStrings)
                                                  throws java.sql.SQLException

        Filter the SQL string of Java SQL Escape clauses.

        Currently implemented Escape clauses are those mentioned in 11.3 in the specification. Basically we look through the sql string for {d xxx}, {t xxx}, {ts xxx}, {oj xxx} or {fn xxx} in non-string sql code. When we find them, we just strip the escape part leaving only the xxx part. So, something like "select * from x where d={d '2001-10-09'}" would return "select * from x where d= '2001-10-09'".

        Parameters:
        sql - the original query text
        replaceProcessingEnabled - whether replace_processing_enabled is on
        standardConformingStrings - whether standard_conforming_strings is on
        Returns:
        PostgreSQL-compatible SQL
        Throws:
        java.sql.SQLException - if given SQL is wrong
      • parseSql

        private static int parseSql​(char[] sql,
                                    int i,
                                    java.lang.StringBuilder newsql,
                                    boolean stopOnComma,
                                    boolean stdStrings)
                             throws java.sql.SQLException
        parse the given sql from index i, appending it to the given buffer until we hit an unmatched right parentheses or end of string. When the stopOnComma flag is set we also stop processing when a comma is found in sql text that isn't inside nested parenthesis.
        Parameters:
        sql - the original query text
        i - starting position for replacing
        newsql - where to write the replaced output
        stopOnComma - should we stop after hitting the first comma in sql text?
        stdStrings - whether standard_conforming_strings is on
        Returns:
        the position we stopped processing at
        Throws:
        java.sql.SQLException - if given SQL is wrong
      • findOpenBrace

        private static int findOpenBrace​(char[] sql,
                                         int i)
      • checkParsePosition

        private static void checkParsePosition​(int i,
                                               int len,
                                               int i0,
                                               char[] sql,
                                               java.lang.String message)
                                        throws PSQLException
        Throws:
        PSQLException
      • escapeFunction

        private static int escapeFunction​(char[] sql,
                                          int i,
                                          java.lang.StringBuilder newsql,
                                          boolean stdStrings)
                                   throws java.sql.SQLException
        Throws:
        java.sql.SQLException
      • escapeFunctionArguments

        private static int escapeFunctionArguments​(java.lang.StringBuilder newsql,
                                                   java.lang.String functionName,
                                                   char[] sql,
                                                   int i,
                                                   boolean stdStrings)
                                            throws java.sql.SQLException
        Generate sql for escaped functions.
        Parameters:
        newsql - destination StringBuilder
        functionName - the escaped function name
        sql - input SQL text (containing arguments of a function call with possible JDBC escapes)
        i - position in the input SQL
        stdStrings - whether standard_conforming_strings is on
        Returns:
        the right PostgreSQL sql
        Throws:
        java.sql.SQLException - if something goes wrong