Re: Unable to prepare a statement when the object names contain more than one $ symbol - Mailing list pgsql-jdbc
From | Michael Paesold |
---|---|
Subject | Re: Unable to prepare a statement when the object names contain more than one $ symbol |
Date | |
Msg-id | 47178A73.9070500@gmx.at Whole thread Raw |
In response to | Re: Unable to prepare a statement when the object names contain more than one $ symbol (Michael Paesold <mpaesold@gmx.at>) |
List | pgsql-jdbc |
Now including the attachement... ;-) Michael Paesold wrote: > I wrote: > ... >> 1) In parseDollarQuotes(), we look at the character directly before >> the $-char and compare it against all valid identifier characters. If >> it is, we don't have a possible dollar-quote start: >> >> From scan.l: >> ident_start [A-Za-z\200-\377_] >> ident_cont [A-Za-z\200-\377_0-9\$] > ... >> Looking at gram.y and scan.l (...but I'm no expert) I can't see >> another case of a dollar-character that I missed, except the one >> allowed in ident_cont... so option 1) seems like the easiest solution. >> I will send a patch implementing option 1 shortly. > > Ok, here is the patch. It also adds your tests exposing the bug to the > test suite. The patch fixes both test cases and passes all other > regression tests (at least with JDK 1.5....). Does it look OK to you? > > Should we do anything additional about error-ing out when we detect an > unterminated dollar-quote (see previous mail)? > > Best Regards > Michael Paesold Fix dollar quote bug (identifiers may continue with a dollar-character) diff -r ee30bbde84f5 org/postgresql/core/Parser.java --- a/org/postgresql/core/Parser.java Thu Oct 18 16:27:52 2007 +0200 +++ b/org/postgresql/core/Parser.java Thu Oct 18 18:07:50 2007 +0200 @@ -89,7 +89,8 @@ public class Parser { * character. */ public static int parseDollarQuotes(final char[] query, int offset) { - if (offset + 1 < query.length) + if (offset + 1 < query.length + && (offset == 0 || !isIdentifierContChar(query[offset-1]))) { int endIdx = -1; if (query[offset + 1] == '$') @@ -205,6 +206,37 @@ public class Parser { } /** + * Checks if a character is valid as the start of an identifier. + * + * @param c the character to check + * @return true if valid as first character of an identifier; false if not + */ + public static boolean isIdentifierStartChar(char c) { + /* + * Extracted from {ident_start} and {ident_cont} in + * pgsql/src/backend/parser/scan.l: + * ident_start [A-Za-z\200-\377_] + * ident_cont [A-Za-z\200-\377_0-9\$] + */ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') + || c == '_' || c > 127 ; + } + + /** + * Checks if a character is valid as the second or later character of an + * identifier. + * + * @param c the character to check + * @return true if valid as second or later character of an identifier; false if not + */ + public static boolean isIdentifierContChar(char c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') + || c == '_' || c > 127 + || (c >= '0' && c <= '9') + || c == '$'; + } + + /** * @return true if the character terminates an identifier */ public static boolean charTerminatesIdentifier(char c) { @@ -228,7 +260,7 @@ public class Parser { } /** - * Checks if a character is valid as the second or latter character of a + * Checks if a character is valid as the second or later character of a * dollar quoting tag. * * @param c the character to check diff -r ee30bbde84f5 org/postgresql/test/jdbc2/PreparedStatementTest.java --- a/org/postgresql/test/jdbc2/PreparedStatementTest.java Thu Oct 18 16:27:52 2007 +0200 +++ b/org/postgresql/test/jdbc2/PreparedStatementTest.java Thu Oct 18 17:36:29 2007 +0200 @@ -405,6 +405,27 @@ public class PreparedStatementTest exten st.close(); } + public void testDollarQuotesAndIdentifiers() throws SQLException { + // dollar-quotes are supported in the backend since version 8.0 + if (!TestUtil.haveMinimumServerVersion(conn, "8.0")) + return; + + PreparedStatement st; + + conn.createStatement().execute("CREATE TEMP TABLE a$b$c(a varchar, b varchar)"); + st = conn.prepareStatement("INSERT INTO a$b$c (a, b) VALUES (?, ?)"); + st.setString(1, "a"); + st.setString(2, "b"); + st.executeUpdate(); + st.close(); + + conn.createStatement().execute("CREATE TEMP TABLE e$f$g(h varchar, e$f$g varchar) "); + st = conn.prepareStatement("UPDATE e$f$g SET h = ? || e$f$g"); + st.setString(1, "a"); + st.executeUpdate(); + st.close(); + } + public void testComments() throws SQLException { PreparedStatement st; ResultSet rs;
pgsql-jdbc by date: