diff --git a/src/main/java/net/sf/jsqlparser/statement/Statements.java b/src/main/java/net/sf/jsqlparser/statement/Statements.java index 950f52a4e..5f66f2d6f 100644 --- a/src/main/java/net/sf/jsqlparser/statement/Statements.java +++ b/src/main/java/net/sf/jsqlparser/statement/Statements.java @@ -30,6 +30,10 @@ public void accept(StatementVisitor statementVisitor) { statementVisitor.visit(this); } + public E get(Class type, int index) { + return type.cast(get(index)); + } + @Override public String toString() { StringBuilder b = new StringBuilder(); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 40e5dc913..a346a0604 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -554,7 +554,7 @@ TOKEN: input_stream.backup(image.length() - matchedToken.image.length() ); } } -| < S_QUOTED_IDENTIFIER: "\"" (~["\n","\r","\""])* "\"" | "$$" (~["$"])* "$$" | ("`" (~["\n","\r","`"])+ "`") | ( "[" (~["\n","\r","]"])* "]" ) > +| < S_QUOTED_IDENTIFIER: "\"" ( "\"\"" | ~["\n","\r","\""])* "\"" | "$$" (~["$"])* "$$" | ("`" (~["\n","\r","`"])+ "`") | ( "[" (~["\n","\r","]"])* "]" ) > { if ( !configuration.getAsBoolean(Feature.allowSquareBracketQuotation) && matchedToken.image.charAt(0) == '[' ) { matchedToken.image = "["; diff --git a/src/test/java/net/sf/jsqlparser/expression/JsonExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/JsonExpressionTest.java index d832c4474..860a69382 100644 --- a/src/test/java/net/sf/jsqlparser/expression/JsonExpressionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/JsonExpressionTest.java @@ -10,7 +10,6 @@ package net.sf.jsqlparser.expression; import net.sf.jsqlparser.JSQLParserException; -import net.sf.jsqlparser.test.TestUtils; import org.junit.jupiter.api.Test; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; @@ -21,11 +20,11 @@ class JsonExpressionTest { void testIssue1792() throws JSQLParserException, InterruptedException { String sqlStr = "SELECT ''::JSON -> 'obj'::TEXT"; - TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + assertSqlCanBeParsedAndDeparsed(sqlStr, true); sqlStr = "SELECT ('{\"obj\":{\"field\": \"value\"}}'::JSON -> 'obj'::TEXT ->> 'field'::TEXT)"; - TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + assertSqlCanBeParsedAndDeparsed(sqlStr, true); sqlStr = "SELECT\n" @@ -33,7 +32,7 @@ void testIssue1792() throws JSQLParserException, InterruptedException { + " WHEN true\n" + " THEN (SELECT ((('{\"obj\":{\"field\": \"value\"}}'::JSON -> 'obj'::TEXT ->> 'field'::TEXT))))\n" + " END"; - TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + assertSqlCanBeParsedAndDeparsed(sqlStr, true); } @Test diff --git a/src/test/java/net/sf/jsqlparser/statement/UnsupportedStatementTest.java b/src/test/java/net/sf/jsqlparser/statement/UnsupportedStatementTest.java index 2cc24e020..fe3ff1572 100644 --- a/src/test/java/net/sf/jsqlparser/statement/UnsupportedStatementTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/UnsupportedStatementTest.java @@ -85,7 +85,7 @@ void testAlter() throws JSQLParserException { String sqlStr = "ALTER INDEX idx_t_fa RENAME TO idx_t_fb"; Statement statement = TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); - Assertions.assertTrue(statement instanceof UnsupportedStatement); + assertTrue(statement instanceof UnsupportedStatement); } @Test diff --git a/src/test/java/net/sf/jsqlparser/statement/select/PostgresTest.java b/src/test/java/net/sf/jsqlparser/statement/select/PostgresTest.java index 1551321e0..921435026 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/PostgresTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/PostgresTest.java @@ -11,10 +11,16 @@ import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.JsonExpression; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.statement.Statements; +import net.sf.jsqlparser.statement.insert.Insert; import net.sf.jsqlparser.test.TestUtils; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.List; + import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; public class PostgresTest { @@ -62,4 +68,31 @@ public void testJSonOperatorIssue1571() throws JSQLParserException { "select visit_hour,json_array_elements(into_sex_json)->>'name',json_array_elements(into_sex_json)->>'value' from period_market"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + void testPostgresQuotingIssue1335() throws JSQLParserException { + String sqlStr = + "INSERT INTO \"table\"\"with\"\"quotes\" (\"column\"\"with\"\"quotes\")\n" + + "VALUES ('1'), ('2'), ('3');\n" + + "\n" + + "UPDATE \"table\"\"with\"\"quotes\" SET \"column\"\"with\"\"quotes\" = '1.0' \n" + + "WHERE \"column\"\"with\"\"quotes\" = '1';\n" + + "\n" + + "SELECT \"column\"\"with\"\"quotes\" FROM \"table\"\"with\"\"quotes\"\n" + + "WHERE \"column\"\"with\"\"quotes\" IS NOT NULL;"; + + Statements statements = CCJSqlParserUtil.parseStatements(sqlStr); + Assertions.assertEquals(3, statements.size()); + + Insert insert = statements.get(Insert.class, 0); + Assertions.assertEquals( + "\"table\"\"with\"\"quotes\"", insert.getTable().getFullyQualifiedName()); + + PlainSelect select = statements.get(PlainSelect.class, 2); + List> selectItems = select.getSelectItems(); + + Assertions.assertEquals( + "\"column\"\"with\"\"quotes\"", + selectItems.get(0).getExpression(Column.class).getColumnName()); + } }