This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new fed2b3e103 IGNITE-21964 Extend test coverage for SQL 
E031-01(Identifiers. Delimited identifiers) (#3899)
fed2b3e103 is described below

commit fed2b3e10368a5a375bbef7b9282cb188a90b07f
Author: Andrew V. Mashenkov <[email protected]>
AuthorDate: Mon Jun 17 10:59:05 2024 +0300

    IGNITE-21964 Extend test coverage for SQL E031-01(Identifiers. Delimited 
identifiers) (#3899)
---
 .../apache/ignite/lang/util/IgniteNameUtils.java   |  40 ++++-
 .../ignite/internal/util/IgniteNameUtilsTest.java  |   8 +-
 .../internal/sql/engine/ItCreateTableDdlTest.java  |  31 ++++
 .../identifiers/test_delimited_identifiers.test    | 173 +++++++++++++++++++++
 4 files changed, 244 insertions(+), 8 deletions(-)

diff --git 
a/modules/api/src/main/java/org/apache/ignite/lang/util/IgniteNameUtils.java 
b/modules/api/src/main/java/org/apache/ignite/lang/util/IgniteNameUtils.java
index 089f26b691..7c7c3e13ad 100644
--- a/modules/api/src/main/java/org/apache/ignite/lang/util/IgniteNameUtils.java
+++ b/modules/api/src/main/java/org/apache/ignite/lang/util/IgniteNameUtils.java
@@ -81,7 +81,25 @@ public final class IgniteNameUtils {
      * @return Quoted object name.
      */
     public static String quote(String name) {
-        return "\"" + name + "\"";
+        if (name == null || name.isEmpty()) {
+            return name;
+        }
+
+        if (name.chars().noneMatch(cp -> cp == '\"')) {
+            return '\"' + name + '\"';
+        }
+
+        StringBuilder sb = new StringBuilder(name.length() + 2).append('\"');
+        for (int currentPosition = 0; currentPosition < name.length(); 
currentPosition++) {
+            char ch = name.charAt(currentPosition);
+            if (ch == '\"') {
+                sb.append('\"');
+            }
+            sb.append(ch);
+        }
+        sb.append('\"');
+
+        return sb.toString();
     }
 
     /**
@@ -92,9 +110,21 @@ public final class IgniteNameUtils {
      * @return Quoted object name.
      */
     public static String quoteIfNeeded(String name) {
-        String simpleName = parseSimpleName(name);
+        if (name == null || name.isEmpty()) {
+            return null;
+        }
+
+        if (name.charAt(0) == '\"') {
+            String simpleName = parseSimpleName(name);
+
+            return name.equals(quote(simpleName)) ? name : quote(name);
+        }
+
+        if (!NAME_PATTER.matcher(name).matches()) {
+            return quote(name);
+        }
 
-        return name.equals(simpleName) || name.equals(quote(simpleName)) ? 
name : quote(name);
+        return name.toUpperCase().equals(name) ? name : quote(name); // NOPMD
     }
 
     /**
@@ -147,8 +177,8 @@ public final class IgniteNameUtils {
                     if (hasNextChar() && nextChar() == '"') {  // quote is 
escaped
                         sb.append(source, start, currentPosition + 1);
 
-                        currentPosition += 2;
-                        start = currentPosition;
+                        start = currentPosition + 2;
+                        currentPosition += 1;
 
                         continue;
                     } else if (!hasNextChar() || nextChar() == '.') {
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/util/IgniteNameUtilsTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/util/IgniteNameUtilsTest.java
index 34afbc4962..798d1457f2 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/util/IgniteNameUtilsTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/util/IgniteNameUtilsTest.java
@@ -50,7 +50,7 @@ public class IgniteNameUtilsTest {
 
     @ParameterizedTest
     @ValueSource(strings = {
-            "f.f", "f f", "f\"f", "f\"\"f", "\"foo", "\"fo\"o"
+            "f.f", "f f", "f\"f", "f\"\"f", "\"foo", "\"fo\"o\""
     })
     public void malformedSimpleNames(String source) {
         IllegalArgumentException ex = 
assertThrows(IllegalArgumentException.class, () -> 
IgniteNameUtils.parseSimpleName(source));
@@ -62,8 +62,10 @@ public class IgniteNameUtilsTest {
 
     @ParameterizedTest
     @CsvSource({
-            "foo, \"foo\"", "fOo, \"fOo\"", "FOO, FOO", "\"FOO\", \"FOO\"", 
"1o0, \"1o0\"", "@#$, @#$",
-            "\"foo\", \"foo\"", "\"fOo\", \"fOo\"", "\"f.f\", \"f.f\""
+            "foo, \"foo\"", "fOo, \"fOo\"", "FOO, FOO", "\"FOO\", \"FOO\"", 
"1o0, \"1o0\"", "@#$, \"@#$\"",
+            "\"foo\", \"foo\"", "\"fOo\", \"fOo\"", "\"f.f\", \"f.f\"",
+            "foo\"bar\", \"foo\"\"bar\"\"\"", "\"foo\"\"bar\"\"\", 
\"foo\"\"bar\"\"\"",
+            "foo\"bar, \"foo\"\"bar\"", "\"foo\"\"bar\", \"foo\"\"bar\""
     })
     public void quoteIfNeeded(String source, String expected) {
         assertThat(IgniteNameUtils.quoteIfNeeded(source), equalTo(expected));
diff --git 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
index a6bc7cbacc..82191c3b7c 100644
--- 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
+++ 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
@@ -25,8 +25,11 @@ import static 
org.apache.ignite.internal.sql.engine.util.SqlTestUtils.assertThro
 import static org.apache.ignite.lang.ErrorGroups.Sql.STMT_PARSE_ERR;
 import static org.apache.ignite.lang.ErrorGroups.Sql.STMT_VALIDATION_ERR;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.hasSize;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
 import java.util.List;
 import java.util.Objects;
@@ -39,6 +42,8 @@ import 
org.apache.ignite.internal.catalog.descriptors.CatalogZoneDescriptor;
 import org.apache.ignite.internal.schema.Column;
 import org.apache.ignite.internal.sql.BaseSqlIntegrationTest;
 import org.apache.ignite.sql.SqlException;
+import org.apache.ignite.table.Table;
+import org.apache.ignite.table.Tuple;
 import org.apache.ignite.tx.Transaction;
 import org.apache.ignite.tx.TransactionOptions;
 import org.junit.jupiter.api.AfterEach;
@@ -415,6 +420,32 @@ public class ItCreateTableDdlTest extends 
BaseSqlIntegrationTest {
         );
     }
 
+    @Test
+    public void quotedTableName() {
+        sql("CREATE TABLE \"table Test\" (key INT PRIMARY KEY, \"Col 1\" 
INT)");
+        sql("CREATE TABLE \"table\"\"Test\"\"\" (key INT PRIMARY KEY, 
\"Col\"\"1\"\"\" INT)");
+
+        sql("INSERT INTO \"table Test\" VALUES (1, 1)");
+        sql("INSERT INTO \"table\"\"Test\"\"\" VALUES (1, 2)");
+
+        IgniteImpl node = CLUSTER.node(0);
+
+        assertThrows(IllegalArgumentException.class, () -> 
node.tables().table("table Test"));
+        assertThrows(IllegalArgumentException.class, () -> 
node.tables().table("table\"Test\""));
+        assertThrows(IllegalArgumentException.class, () -> 
node.tables().table("table\"\"Test\"\""));
+
+        Table table = node.tables().table("\"table Test\"");
+        assertNotNull(table);
+        assertThat(table.keyValueView().get(null, Tuple.create().set("key", 
1)), equalTo(Tuple.create().set("\"Col 1\"", 1)));
+
+        table = node.tables().table("\"table\"\"Test\"\"\"");
+        assertNotNull(table);
+        assertThat(table.keyValueView().get(null, Tuple.create().set("key", 
1)), equalTo(Tuple.create().set("\"Col\"\"1\"\"\"", 2)));
+
+        sql("DROP TABLE \"table Test\"");
+        sql("DROP TABLE \"table\"\"Test\"\"\"");
+    }
+
     private static CatalogZoneDescriptor getDefaultZone(IgniteImpl node) {
         CatalogManager catalogManager = node.catalogManager();
         Catalog catalog = 
catalogManager.catalog(catalogManager.activeCatalogVersion(node.clock().nowLong()));
diff --git 
a/modules/sql-engine/src/integrationTest/sql/identifiers/test_delimited_identifiers.test
 
b/modules/sql-engine/src/integrationTest/sql/identifiers/test_delimited_identifiers.test
new file mode 100644
index 0000000000..1811d7262d
--- /dev/null
+++ 
b/modules/sql-engine/src/integrationTest/sql/identifiers/test_delimited_identifiers.test
@@ -0,0 +1,173 @@
+# name: sql/identifiers/test_identifiers_trailing_underscore.test
+# description: SQL feature E031-01 (Identifiers. Delimited identifiers)
+# group: [identifiers]
+
+statement ok
+PRAGMA enable_verification
+
+statement ok
+CREATE TABLE "Table_Test" ("col_Id" INTEGER, "col_Val" INTEGER, PRIMARY KEY 
("col_Id"))
+
+statement ok
+CREATE TABLE "Table Test" ("col Id" INTEGER, "col Val" INTEGER, PRIMARY KEY 
("col Id"))
+
+statement ok
+CREATE TABLE "Table""Test""" ("col""Id""" INTEGER, "col""Val""" INTEGER, 
PRIMARY KEY ("col""Id"""))
+
+
+
+statement error
+ALTER TABLE Table_Test ADD COLUMN (col1 INTEGER)
+
+statement error
+ALTER TABLE TableTest ADD COLUMN (col1 INTEGER)
+
+statement ok
+ALTER TABLE "Table_Test" ADD COLUMN ("Col_1" INTEGER)
+
+statement ok
+ALTER TABLE "Table Test" ADD COLUMN ("Col 1" INTEGER)
+
+statement ok
+ALTER TABLE "Table""Test""" ADD COLUMN ("Col""1""" INTEGER)
+
+
+
+statement ok
+INSERT INTO "Table_Test" VALUES (1, 1, 1)
+
+statement ok
+INSERT INTO "Table Test" VALUES (2, 2, 2)
+
+statement ok
+INSERT INTO "Table""Test""" VALUES (3, 3, 3)
+
+
+query II
+SELECT "col_Val", "Col_1" FROM "Table_Test"
+----
+1      1
+
+query II
+SELECT "col Val", "Col 1" FROM "Table Test"
+----
+2      2
+
+query II
+SELECT "col""Val""", "Col""1""" FROM "Table""Test"""
+----
+3      3
+
+statement error: Object 'TABLE_TEST' not found
+SELECT "col_Val" FROM Table_Test
+
+statement error: Object 'TableTest' not found
+SELECT "col""Val""" FROM "TableTest"
+
+statement error: Column 'COL_VAL' not found
+SELECT col_Val FROM "Table_Test"
+
+statement error: Column 'colVal' not found
+SELECT "colVal" FROM "Table""Test"""
+
+
+
+statement ok
+CREATE INDEX "Index_Test" on "Table_Test" ("Col_1")
+
+statement ok
+CREATE INDEX "Index Test" on "Table Test" ("Col 1")
+
+statement ok
+CREATE INDEX "Index""Test""" on "Table""Test""" ("Col""1""")
+
+
+statement error: Index with name 'PUBLIC.INDEX_TEST' not found
+DROP INDEX Index_Test
+
+statement error: Index with name 'PUBLIC.IndexTest' not found
+DROP INDEX "IndexTest"
+
+statement ok
+DROP INDEX "Index_Test"
+
+statement ok
+DROP INDEX "Index Test"
+
+statement ok
+DROP INDEX "Index""Test"""
+
+
+
+statement error: Table with name 'PUBLIC.TABLE_TEST' not found
+DROP TABLE Table_Test;
+
+statement error: Table with name 'PUBLIC.TableTest' not found
+DROP TABLE "TableTest";
+
+statement ok
+DROP TABLE "Table_Test";
+
+statement ok
+DROP TABLE "Table Test";
+
+statement ok
+DROP TABLE "Table""Test""";
+
+
+
+statement ok
+CREATE ZONE "zone_Test" WITH STORAGE_PROFILES='default', PARTITIONS=1, 
REPLICAS=3
+
+statement ok
+ALTER ZONE "zone_Test" SET REPLICAS = 4
+
+statement ok
+ALTER ZONE "zone_Test" RENAME TO "zone Test"
+
+statement error: Distribution zone with name 'zone_Test' not found
+ALTER ZONE "zone_Test" SET REPLICAS = 3
+
+statement error: Distribution zone with name 'zone_Test' not found
+DROP ZONE "zone_Test"
+
+statement ok
+DROP ZONE "zone Test"
+
+
+statement ok
+CREATE ZONE "zone Test" WITH STORAGE_PROFILES='default', PARTITIONS=1, 
REPLICAS=3
+
+statement ok
+ALTER ZONE "zone Test" SET REPLICAS = 4
+
+statement ok
+ALTER ZONE "zone Test" RENAME TO "zone""Test"""
+
+statement error: Distribution zone with name 'zone Test' not found
+ALTER ZONE "zone Test" SET REPLICAS = 3
+
+statement error: Distribution zone with name 'zone Test' not found
+DROP ZONE "zone Test"
+
+statement ok
+DROP ZONE "zone""Test"""
+
+
+statement ok
+CREATE ZONE "zone""Test""" WITH STORAGE_PROFILES='default', PARTITIONS=1, 
REPLICAS=3
+
+statement ok
+ALTER ZONE "zone""Test""" SET REPLICAS = 4
+
+statement ok
+ALTER ZONE "zone""Test""" RENAME TO "zone_Test"
+
+statement error: Distribution zone with name 'zone"Test"' not found
+ALTER ZONE "zone""Test""" SET REPLICAS = 3
+
+statement error: Distribution zone with name 'zone"Test"' not found
+DROP ZONE "zone""Test"""
+
+statement ok
+DROP ZONE "zone_Test"

Reply via email to