diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 130627139..8acc47e4a 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -16055,6 +16055,10 @@ TableOption CreateTableOption(): } | LOOKAHEAD({ isMySqlTableOptionAhead() }) option=MySqlTableOption() + | + // Snowflake: COPY is reserved because it starts the COPY statement + LOOKAHEAD({ getToken(1).kind == K_COPY && "GRANTS".equalsIgnoreCase(getToken(2).image) }) + ContextualKeyword("GRANTS") { option = TableOption.raw("COPY", "GRANTS"); } | tokens=CreateParameter() { option = TableOption.raw(tokens); } ) { return option; } } diff --git a/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java b/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java index 2385c0414..26bc31cc7 100644 --- a/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java @@ -60,6 +60,14 @@ public void testCreateTableOrReplace() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed(statement); } + @Test + public void testCreateTableCopyGrants() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed( + "CREATE OR REPLACE TABLE testtab COPY GRANTS AS (SELECT a FROM tbl)"); + assertSqlCanBeParsedAndDeparsed( + "CREATE OR REPLACE TABLE testtab (a VARCHAR (255)) COPY GRANTS"); + } + @Test public void testCreateTable2() throws JSQLParserException { String statement = "CREATE TABLE testtab (\"test\" varchar (255))";