From 4123f6041e51056124950cf8e008fbb3c632df60 Mon Sep 17 00:00:00 2001 From: Armand Parajon Date: Wed, 5 Aug 2026 11:52:27 -0400 Subject: [PATCH] fix: accept VISIBLE/INVISIBLE index and column attributes in CREATE TABLE and CREATE INDEX MySQL 8.0 invisible indexes (KEY idx (col) INVISIBLE) and invisible columns failed to parse inside CREATE TABLE, and CREATE INDEX ... INVISIBLE failed too, because CreateParameter() did not accept the K_VISIBLE/K_INVISIBLE tokens. The ALTER TABLE productions already support them (#2076 was fixed for ALTER TABLE only, via #2234); this covers the CREATE statements, which share CreateParameter(). Tests cover index and column visibility, mixing visibility with other index options in either order, and quoted columns named visible/invisible. Co-Authored-By: Claude Fable 5 --- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 1 + .../statement/create/CreateIndexTest.java | 6 +++ .../statement/create/CreateTableTest.java | 44 +++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 2a28d21ba..0b53805d0 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -11046,6 +11046,7 @@ List CreateParameter(): | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk = | tk = | tk= | tk= | tk= | tk= | tk= + | tk= | tk= | tk="=" ) { param.add(tk.image); } diff --git a/src/test/java/net/sf/jsqlparser/statement/create/CreateIndexTest.java b/src/test/java/net/sf/jsqlparser/statement/create/CreateIndexTest.java index 0a95930a3..2096b9730 100644 --- a/src/test/java/net/sf/jsqlparser/statement/create/CreateIndexTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/create/CreateIndexTest.java @@ -168,4 +168,10 @@ public void testCreateIndexWithFunctionalKeyParts() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed(statement); } + + @Test + public void testCreateIndexVisibility() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed("CREATE INDEX idx_a ON t1 (a) INVISIBLE", true); + assertSqlCanBeParsedAndDeparsed("CREATE INDEX idx_a ON t1 (a) VISIBLE", true); + } } 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 646f406e8..0560422a1 100644 --- a/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java @@ -1162,4 +1162,48 @@ void testWithCatalog() throws JSQLParserException { assertEquals("session1", t.getSchemaName()); assertEquals("a", t.getUnquotedName()); } + + @Test + void testCreateTableIndexVisibility() throws JSQLParserException { + String sqlStr = "CREATE TABLE `orders` (" + + "`id` bigint NOT NULL AUTO_INCREMENT" + + ", `status` varchar (32) NOT NULL" + + ", `quote_id` varchar (191) NOT NULL" + + ", PRIMARY KEY (`id`)" + + ", KEY `idx_status` (`status`) INVISIBLE" + + ", UNIQUE KEY `idx_quote_id` (`quote_id`) VISIBLE" + + ") ENGINE = InnoDB"; + CreateTable createTable = (CreateTable) assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + assertEquals(Arrays.asList("INVISIBLE"), createTable.getIndexes().get(1).getIndexSpec()); + assertEquals(Arrays.asList("VISIBLE"), createTable.getIndexes().get(2).getIndexSpec()); + } + + @Test + void testCreateTableColumnVisibility() throws JSQLParserException { + String sqlStr = + "CREATE TABLE t1 (id bigint NOT NULL VISIBLE, secret varchar (10) INVISIBLE)"; + CreateTable createTable = (CreateTable) assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + assertEquals(Arrays.asList("NOT", "NULL", "VISIBLE"), + createTable.getColumnDefinitions().get(0).getColumnSpecs()); + assertEquals(Arrays.asList("INVISIBLE"), + createTable.getColumnDefinitions().get(1).getColumnSpecs()); + } + + @Test + void testCreateTableIndexVisibilityWithOtherIndexOptions() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed( + "CREATE TABLE t1 (a int, KEY idx_a (a) INVISIBLE COMMENT 'retiring')", true); + assertSqlCanBeParsedAndDeparsed( + "CREATE TABLE t1 (a int, KEY idx_a (a) COMMENT 'retiring' INVISIBLE)", true); + assertSqlCanBeParsedAndDeparsed( + "CREATE TABLE t1 (a int, KEY idx_a (a) USING BTREE INVISIBLE)", true); + } + + @Test + void testCreateTableQuotedColumnNamedVisible() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed( + "CREATE TABLE t1 (`visible` int, `invisible` varchar (10))", true); + } }