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 fe461cd1e09 IGNITE-24315 Catalog. DropTable. Name part is invalid
error (#5652)
fe461cd1e09 is described below
commit fe461cd1e09efca2c233c42c514da35d973f3ef9
Author: Max Zhuravkov <[email protected]>
AuthorDate: Thu Apr 24 11:09:42 2025 +0300
IGNITE-24315 Catalog. DropTable. Name part is invalid error (#5652)
---
.../java/org/apache/ignite/catalog/ColumnType.java | 30 ++---
.../java/org/apache/ignite/catalog/SortOrder.java | 16 +--
.../ignite/internal/catalog/ItCatalogDslTest.java | 80 +++++++++---
.../ignite/internal/catalog/sql/Colocate.java | 2 +-
.../apache/ignite/internal/catalog/sql/Column.java | 4 +-
.../internal/catalog/sql/CreateIndexImpl.java | 6 +-
.../internal/catalog/sql/CreateTableImpl.java | 4 +-
.../internal/catalog/sql/CreateZoneImpl.java | 6 +-
.../ignite/internal/catalog/sql/DropTableImpl.java | 2 +-
.../ignite/internal/catalog/sql/DropZoneImpl.java | 6 +-
.../internal/catalog/sql/IndexColumnImpl.java | 2 +-
.../apache/ignite/internal/catalog/sql/Name.java | 77 ++++++++----
.../apache/ignite/internal/catalog/sql/Zone.java | 9 +-
.../catalog/sql/CreateFromAnnotationsTest.java | 102 ++++++++++++----
.../catalog/sql/CreateFromDefinitionTest.java | 65 +++++++---
.../internal/catalog/sql/CreateTableTest.java | 50 ++++----
.../internal/catalog/sql/CreateZoneTest.java | 14 ++-
.../ignite/internal/catalog/sql/DropTableTest.java | 16 ++-
.../ignite/internal/catalog/sql/DropZoneTest.java | 16 ++-
.../ignite/internal/catalog/sql/QueryPartTest.java | 136 +++++++++++++--------
20 files changed, 432 insertions(+), 211 deletions(-)
diff --git
a/modules/api/src/main/java/org/apache/ignite/catalog/ColumnType.java
b/modules/api/src/main/java/org/apache/ignite/catalog/ColumnType.java
index b384896d098..aafb49d8be6 100644
--- a/modules/api/src/main/java/org/apache/ignite/catalog/ColumnType.java
+++ b/modules/api/src/main/java/org/apache/ignite/catalog/ColumnType.java
@@ -32,19 +32,19 @@ public class ColumnType<T> {
private static final Map<Class<?>, ColumnType<?>> TYPES = new
LinkedHashMap<>();
/** {@code BOOLEAN} SQL column type. */
- public static final ColumnType<Boolean> BOOLEAN = new
ColumnType<>(Boolean.class, "boolean");
+ public static final ColumnType<Boolean> BOOLEAN = new
ColumnType<>(Boolean.class, "BOOLEAN");
/** {@code TINYINT} SQL column type. */
- public static final ColumnType<Byte> TINYINT = new
ColumnType<>(Byte.class, "tinyint");
+ public static final ColumnType<Byte> TINYINT = new
ColumnType<>(Byte.class, "TINYINT");
/** {@code SMALLINT} SQL column type. */
- public static final ColumnType<Short> SMALLINT = new
ColumnType<>(Short.class, "smallint");
+ public static final ColumnType<Short> SMALLINT = new
ColumnType<>(Short.class, "SMALLINT");
/** {@code INTEGER} SQL column type. */
- public static final ColumnType<Integer> INTEGER = new
ColumnType<>(Integer.class, "int");
+ public static final ColumnType<Integer> INTEGER = new
ColumnType<>(Integer.class, "INT");
/** {@code BIGINT} SQL column type. */
- public static final ColumnType<Long> BIGINT = new ColumnType<>(Long.class,
"bigint");
+ public static final ColumnType<Long> BIGINT = new ColumnType<>(Long.class,
"BIGINT");
/** 8-bit signed integer. An alias for {@link #TINYINT}. */
public static final ColumnType<Byte> INT8 = TINYINT;
@@ -59,16 +59,16 @@ public class ColumnType<T> {
public static final ColumnType<Long> INT64 = BIGINT;
/** {@code REAL} SQL column type. */
- public static final ColumnType<Float> REAL = new ColumnType<>(Float.class,
"real");
+ public static final ColumnType<Float> REAL = new ColumnType<>(Float.class,
"REAL");
/** 32-bit single-precision floating-point number. An alias for {@link
#REAL}. */
public static final ColumnType<Float> FLOAT = REAL;
/** {@code DOUBLE} SQL column type. */
- public static final ColumnType<Double> DOUBLE = new
ColumnType<>(Double.class, "double");
+ public static final ColumnType<Double> DOUBLE = new
ColumnType<>(Double.class, "DOUBLE");
/** {@code VARCHAR} SQL column type. */
- public static final ColumnType<String> VARCHAR = new
ColumnType<>(String.class, "varchar");
+ public static final ColumnType<String> VARCHAR = new
ColumnType<>(String.class, "VARCHAR");
/** {@code VARCHAR} with specified length. */
public static ColumnType<String> varchar(int length) {
@@ -76,7 +76,7 @@ public class ColumnType<T> {
}
/** {@code VARBINARY} SQL column type. */
- public static final ColumnType<byte[]> VARBINARY = new
ColumnType<>(byte[].class, "varbinary");
+ public static final ColumnType<byte[]> VARBINARY = new
ColumnType<>(byte[].class, "VARBINARY");
/** {@code VARBINARY} with specified length. */
public static ColumnType<byte[]> varbinary(int length) {
@@ -84,7 +84,7 @@ public class ColumnType<T> {
}
/** {@code TIME} SQL column type. */
- public static final ColumnType<LocalTime> TIME = new
ColumnType<>(LocalTime.class, "time");
+ public static final ColumnType<LocalTime> TIME = new
ColumnType<>(LocalTime.class, "TIME");
/** {@code TIME} with specified precision. */
public static ColumnType<LocalTime> time(int precision) {
@@ -92,7 +92,7 @@ public class ColumnType<T> {
}
/** {@code TIMESTAMP} SQL column type. */
- public static final ColumnType<LocalDateTime> TIMESTAMP = new
ColumnType<>(LocalDateTime.class, "timestamp");
+ public static final ColumnType<LocalDateTime> TIMESTAMP = new
ColumnType<>(LocalDateTime.class, "TIMESTAMP");
/** {@code TIMESTAMP} with specified precision. */
public static ColumnType<LocalDateTime> timestamp(int precision) {
@@ -100,10 +100,10 @@ public class ColumnType<T> {
}
/** {@code DATE} SQL column type. */
- public static final ColumnType<LocalDate> DATE = new
ColumnType<>(LocalDate.class, "date");
+ public static final ColumnType<LocalDate> DATE = new
ColumnType<>(LocalDate.class, "DATE");
/** {@code DECIMAL} SQL column type. */
- public static final ColumnType<BigDecimal> DECIMAL = new
ColumnType<>(BigDecimal.class, "decimal");
+ public static final ColumnType<BigDecimal> DECIMAL = new
ColumnType<>(BigDecimal.class, "DECIMAL");
/** {@code DECIMAL} with specified precision and scale. */
public static ColumnType<BigDecimal> decimal(int precision, int scale) {
@@ -111,11 +111,11 @@ public class ColumnType<T> {
}
/** {@code UUID} SQL column type. */
- public static final ColumnType<UUID> UUID = new ColumnType<>(UUID.class,
"uuid");
+ public static final ColumnType<UUID> UUID = new ColumnType<>(UUID.class,
"UUID");
/** {@code TIMESTAMP WITH LOCAL TIME ZONE} SQL column type. */
public static final ColumnType<Instant> TIMESTAMP_WITH_LOCAL_TIME_ZONE =
new ColumnType<>(
- Instant.class, "timestamp with local time zone");
+ Instant.class, "TIMESTAMP WITH LOCAL TIME ZONE");
private final Class<T> type;
diff --git a/modules/api/src/main/java/org/apache/ignite/catalog/SortOrder.java
b/modules/api/src/main/java/org/apache/ignite/catalog/SortOrder.java
index 709f9ad7fc7..0e8018e4b2f 100644
--- a/modules/api/src/main/java/org/apache/ignite/catalog/SortOrder.java
+++ b/modules/api/src/main/java/org/apache/ignite/catalog/SortOrder.java
@@ -22,14 +22,14 @@ package org.apache.ignite.catalog;
*/
public enum SortOrder {
DEFAULT(""),
- ASC("asc"),
- ASC_NULLS_FIRST("asc nulls first"),
- ASC_NULLS_LAST("asc nulls last"),
- DESC("desc"),
- DESC_NULLS_FIRST("desc nulls first"),
- DESC_NULLS_LAST("desc nulls last"),
- NULLS_FIRST("nulls first"),
- NULLS_LAST("nulls last");
+ ASC("ASC"),
+ ASC_NULLS_FIRST("ASC NULLS FIRST"),
+ ASC_NULLS_LAST("ASC NULLS LAST"),
+ DESC("DESC"),
+ DESC_NULLS_FIRST("DESC NULLS FIRST"),
+ DESC_NULLS_LAST("DESC NULLS LAST"),
+ NULLS_FIRST("NULLS FIRST"),
+ NULLS_LAST("NULLS LAST");
private final String sql;
diff --git
a/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/catalog/ItCatalogDslTest.java
b/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/catalog/ItCatalogDslTest.java
index 191bb2183e0..5794531b852 100644
---
a/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/catalog/ItCatalogDslTest.java
+++
b/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/catalog/ItCatalogDslTest.java
@@ -32,6 +32,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@@ -524,49 +525,98 @@ class ItCatalogDslTest extends
ClusterPerClassIntegrationTest {
assertEquals(15, columns.size());
assertEquals("STR", columns.get(0).name());
- assertEquals("varchar", columns.get(0).type().typeName());
+ assertEquals("VARCHAR", columns.get(0).type().typeName());
assertEquals("BYTECOL", columns.get(1).name());
- assertEquals("tinyint", columns.get(1).type().typeName());
+ assertEquals("TINYINT", columns.get(1).type().typeName());
assertEquals("SHORTCOL", columns.get(2).name());
- assertEquals("smallint", columns.get(2).type().typeName());
+ assertEquals("SMALLINT", columns.get(2).type().typeName());
assertEquals("INTCOL", columns.get(3).name());
- assertEquals("int", columns.get(3).type().typeName());
+ assertEquals("INT", columns.get(3).type().typeName());
assertEquals("LONGCOL", columns.get(4).name());
- assertEquals("bigint", columns.get(4).type().typeName());
+ assertEquals("BIGINT", columns.get(4).type().typeName());
assertEquals("FLOATCOL", columns.get(5).name());
- assertEquals("real", columns.get(5).type().typeName());
+ assertEquals("REAL", columns.get(5).type().typeName());
assertEquals("DOUBLECOL", columns.get(6).name());
- assertEquals("double", columns.get(6).type().typeName());
+ assertEquals("DOUBLE", columns.get(6).type().typeName());
assertEquals("DECIMALCOL", columns.get(7).name());
- assertEquals("decimal", columns.get(7).type().typeName());
+ assertEquals("DECIMAL", columns.get(7).type().typeName());
assertEquals("BOOLCOL", columns.get(8).name());
- assertEquals("boolean", columns.get(8).type().typeName());
+ assertEquals("BOOLEAN", columns.get(8).type().typeName());
assertEquals("BYTESCOL", columns.get(9).name());
- assertEquals("varbinary", columns.get(9).type().typeName());
+ assertEquals("VARBINARY", columns.get(9).type().typeName());
assertEquals("UUIDCOL", columns.get(10).name());
- assertEquals("uuid", columns.get(10).type().typeName());
+ assertEquals("UUID", columns.get(10).type().typeName());
assertEquals("DATECOL", columns.get(11).name());
- assertEquals("date", columns.get(11).type().typeName());
+ assertEquals("DATE", columns.get(11).type().typeName());
assertEquals("TIMECOL", columns.get(12).name());
- assertEquals("time", columns.get(12).type().typeName());
+ assertEquals("TIME", columns.get(12).type().typeName());
assertEquals("DATETIMECOL", columns.get(13).name());
- assertEquals("timestamp", columns.get(13).type().typeName());
+ assertEquals("TIMESTAMP", columns.get(13).type().typeName());
assertEquals("INSTANTCOL", columns.get(14).name());
- assertEquals("timestamp with local time zone",
columns.get(14).type().typeName());
+ assertEquals("TIMESTAMP WITH LOCAL TIME ZONE",
columns.get(14).type().typeName());
+ }
+
+ @Test
+ public void testQuotedZoneName() {
+ IgniteCatalog catalog = CLUSTER.node(0).catalog();
+
+ sql("CREATE ZONE \"Some Zone\" STORAGE PROFILES ['" +
DEFAULT_AIPERSIST_PROFILE_NAME + "']");
+
+ ZoneDefinition zone = catalog.zoneDefinition("Some Zone");
+ assertNotNull(zone);
+ assertEquals("Some Zone", zone.zoneName());
+ }
+
+ @Test
+ public void testQuotedTableName() {
+ IgniteCatalog catalog = CLUSTER.node(0).catalog();
+
+ sql("CREATE SCHEMA \"Table Schema\"");
+ sql("CREATE TABLE \"Table Schema\".\"a b\" (id INT PRIMARY KEY, \"int
val\" INT)");
+ sql("CREATE INDEX \"a b index\" ON \"Table Schema\".\"a b\" (\"int
val\")");
+
+ QualifiedName name = QualifiedName.parse("\"Table Schema\".\"a b\"");
+
+ TableDefinition table = catalog.tableDefinition(name);
+ assertNotNull(table);
+ // Table Name
+ assertEquals("a b", table.tableName());
+ // Schema name
+ assertEquals("Table Schema", table.schemaName());
+
+ // Column
+ List<ColumnDefinition> columns = table.columns();
+ assertNotNull(columns);
+ ColumnDefinition col = columns.stream()
+ .filter(c -> "int val".equals(c.name()))
+ .findAny()
+ .orElse(null);
+ assertNotNull(col, "Columns: " +
columns.stream().map(ColumnDefinition::name).collect(Collectors.toList()));
+
+ // Index
+ List<IndexDefinition> indexes = table.indexes();
+ assertNotNull(indexes);
+
+ IndexDefinition index = indexes
+ .stream().filter(idx -> Objects.equals(idx.name(), "a b
index"))
+ .findAny().orElse(null);
+ assertNotNull(index, "Indexes: " +
indexes.stream().map(IndexDefinition::name).collect(Collectors.toList()));
+
+ catalog.dropTable(table);
}
private static IgniteCatalog catalog() {
diff --git
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Colocate.java
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Colocate.java
index 07e4f95e0d6..1659b4034a5 100644
---
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Colocate.java
+++
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Colocate.java
@@ -32,7 +32,7 @@ class Colocate extends QueryPart {
}
Colocate(List<String> columnNames) {
- names =
columnNames.stream().map(Name::new).collect(Collectors.toList());
+ names =
columnNames.stream().map(Name::simple).collect(Collectors.toList());
}
@Override
diff --git
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Column.java
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Column.java
index c0febc22024..bd98aca4fde 100644
---
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Column.java
+++
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Column.java
@@ -25,13 +25,13 @@ class Column extends QueryPart {
private final String definition;
Column(String name, ColumnTypeImpl<?> type) {
- this.name = new Name(name);
+ this.name = Name.simple(name);
this.type = type;
this.definition = null;
}
Column(String name, String definition) {
- this.name = new Name(name);
+ this.name = Name.simple(name);
this.type = null;
this.definition = definition;
}
diff --git
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateIndexImpl.java
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateIndexImpl.java
index d10afbdeb40..eb69edd69b3 100644
---
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateIndexImpl.java
+++
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateIndexImpl.java
@@ -52,10 +52,10 @@ class CreateIndexImpl extends AbstractCatalogQuery<Name> {
return indexName;
}
- CreateIndexImpl name(String... names) {
- Objects.requireNonNull(names, "Index name must not be null.");
+ CreateIndexImpl name(String name) {
+ Objects.requireNonNull(name, "Index name must not be null.");
- indexName = new Name(names);
+ indexName = Name.simple(name);
return this;
}
diff --git
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateTableImpl.java
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateTableImpl.java
index e4a26506ea7..abb472d90a8 100644
---
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateTableImpl.java
+++
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateTableImpl.java
@@ -61,7 +61,7 @@ class CreateTableImpl extends AbstractCatalogQuery<Name> {
CreateTableImpl name(String... names) {
Objects.requireNonNull(names, "Table name must not be null.");
- this.tableName = new Name(names);
+ this.tableName = Name.compound(names);
return this;
}
@@ -111,7 +111,7 @@ class CreateTableImpl extends AbstractCatalogQuery<Name> {
CreateTableImpl zone(String zone) {
Objects.requireNonNull(zone, "Zone name must not be null.");
- this.zone = new Zone(zone.toUpperCase());
+ this.zone = new Zone(zone);
return this;
}
diff --git
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateZoneImpl.java
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateZoneImpl.java
index dfdb07921e0..ff8a3e7f333 100644
---
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateZoneImpl.java
+++
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateZoneImpl.java
@@ -45,10 +45,10 @@ class CreateZoneImpl extends AbstractCatalogQuery<Name> {
return zoneName;
}
- CreateZoneImpl name(String... names) {
- Objects.requireNonNull(names, "Zone name must not be null.");
+ CreateZoneImpl name(String name) {
+ Objects.requireNonNull(name, "Zone name must not be null.");
- this.zoneName = new Name(names);
+ this.zoneName = Name.simple(name);
return this;
}
diff --git
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/DropTableImpl.java
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/DropTableImpl.java
index ede2dfca078..8dae6e86adf 100644
---
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/DropTableImpl.java
+++
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/DropTableImpl.java
@@ -37,7 +37,7 @@ class DropTableImpl extends AbstractCatalogQuery<Name> {
DropTableImpl name(String... names) {
Objects.requireNonNull(names, "Table name must not be null");
- this.tableName = new Name(names);
+ this.tableName = Name.compound(names);
return this;
}
diff --git
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/DropZoneImpl.java
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/DropZoneImpl.java
index db11b136ad9..2ec0c6b9b9e 100644
---
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/DropZoneImpl.java
+++
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/DropZoneImpl.java
@@ -34,10 +34,10 @@ class DropZoneImpl extends AbstractCatalogQuery<Name> {
return zoneName;
}
- DropZoneImpl name(String... names) {
- Objects.requireNonNull(names, "Zone name must not be null");
+ DropZoneImpl name(String name) {
+ Objects.requireNonNull(name, "Zone name must not be null");
- this.zoneName = new Name(names);
+ this.zoneName = Name.simple(name);
return this;
}
diff --git
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/IndexColumnImpl.java
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/IndexColumnImpl.java
index ec661d4dbdf..c26fa8e9faf 100644
---
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/IndexColumnImpl.java
+++
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/IndexColumnImpl.java
@@ -87,7 +87,7 @@ class IndexColumnImpl extends QueryPart {
@Override
protected void accept(QueryContext ctx) {
- ctx.visit(new Name(wrapped.columnName()));
+ ctx.visit(Name.simple(wrapped.columnName()));
SortOrder sortOrder = wrapped.sortOrder();
if (sortOrder != null && sortOrder != SortOrder.DEFAULT) {
ctx.sql(" ").sql(sortOrder.sql());
diff --git
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Name.java
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Name.java
index 7a3c7cd7497..f14e34ba6ec 100644
---
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Name.java
+++
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Name.java
@@ -18,49 +18,84 @@
package org.apache.ignite.internal.catalog.sql;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
-import java.util.Objects;
-import java.util.regex.Pattern;
-import org.apache.ignite.internal.util.StringUtils;
+import org.apache.ignite.lang.util.IgniteNameUtils;
/**
* SQL identifier.
*/
class Name extends QueryPart {
+ private final List<String> names;
+
/**
- * Pattern to find possible SQL injections in identifiers.
+ * Creates a simple name.
+ *
+ * @param name Name.
+ * @return Name.
*/
- private static final Pattern PATTERN =
Pattern.compile("[';\r\n\t\\s\\/]|(--[^\r\n]*)");
-
- private final List<String> names = new ArrayList<>();
+ static Name simple(String name) {
+ return new Name(List.of(name));
+ }
/**
- * Identifier name. E.g [db, schema, table] become 'db.schema.table' or
'"db"."schema"."table"' depending on DDL options.
+ * Creates a compound name (e.g. {@code my_schema.my_table} or {@code
my_table}). Accepts both simple and compound names.
*
- * @param names name parts of qualified identifier.
+ * @param names Array of names.
+ * @return Name.
*/
- Name(String... names) {
- Objects.requireNonNull(names, "Names must not be null");
+ static Name compound(String... names) {
+ List<String> parts = new ArrayList<>(2);
- for (String name : names) {
- if (StringUtils.nullOrBlank(name)) {
- // Skip parts instead of failure as nulls can be used as
defaults from annotations or builders.
- continue;
+ if (names.length == 0) {
+ throw new IllegalArgumentException("Names can not be empty");
+ } else if (names.length == 1) {
+ return new Name(Arrays.asList(names));
+ } else {
+ boolean canSkipEmpty = true;
+ for (String part : names) {
+ if (part == null || part.isEmpty()) {
+ if (canSkipEmpty) {
+ canSkipEmpty = false;
+ continue;
+ }
+ } else {
+ // Do not allow non-leading elements to be empty
+ canSkipEmpty = false;
+ }
+ parts.add(part);
}
- // We need to sanitize the identifiers to prevent SQL injection.
- // Ignite DDL doesn't have prepared statements yet which could be
used instead of creating a raw query.
- if (PATTERN.matcher(name).find()) {
- throw new IllegalArgumentException("Name part " + name + " is
invalid");
+
+ return new Name(parts);
+ }
+ }
+
+ private Name(List<String> names) {
+ for (String name : names) {
+ if (name == null || name.isEmpty()) {
+ throw new IllegalArgumentException("Name parts can not be null
or empty: " + names);
}
- this.names.add(name);
}
+ this.names = names;
}
@Override
protected void accept(QueryContext ctx) {
String separator = "";
for (String name : names) {
- ctx.sql(separator).sql(name);
+ // If a name is quoted, we must preserve case sensitivity -> write
it as is
+ // If a name UPPER(name) is a valid normalized id, then this is a
case insensitive name, write it in uppercase for consistency.
+ // Otherwise we must quote it.
+ if (name.startsWith("\"")) {
+ ctx.sql(separator).sql(name);
+ } else {
+ String upperCase = name.toUpperCase();
+ if (IgniteNameUtils.isValidNormalizedIdentifier(upperCase)) {
+ ctx.sql(separator).sql(upperCase);
+ } else {
+
ctx.sql(separator).sql(IgniteNameUtils.quoteIfNeeded(name));
+ }
+ }
separator = ".";
}
}
diff --git
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Zone.java
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Zone.java
index 54ca13f54f3..48d7f126f3e 100644
---
a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Zone.java
+++
b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/Zone.java
@@ -19,14 +19,15 @@ package org.apache.ignite.internal.catalog.sql;
class Zone extends QueryPart {
- private final String zone;
+ private final Name name;
- Zone(String zone) {
- this.zone = zone;
+ Zone(String name) {
+ this.name = Name.simple(name);
}
@Override
protected void accept(QueryContext ctx) {
- ctx.sql("ZONE " + zone);
+ ctx.sql("ZONE ");
+ ctx.visit(name);
}
}
diff --git
a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateFromAnnotationsTest.java
b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateFromAnnotationsTest.java
index 9368ec9204d..653c3751651 100644
---
a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateFromAnnotationsTest.java
+++
b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateFromAnnotationsTest.java
@@ -102,15 +102,15 @@ class CreateFromAnnotationsTest {
CreateFromAnnotationsImpl query =
createTable().processKeyValueClasses(Integer.class, PojoValue.class);
assertThat(
query.toString(),
- is("CREATE ZONE IF NOT EXISTS zone_test WITH
STORAGE_PROFILES='default', PARTITIONS=1, REPLICAS=3,"
+ is("CREATE ZONE IF NOT EXISTS ZONE_TEST WITH
STORAGE_PROFILES='default', PARTITIONS=1, REPLICAS=3,"
+ " DISTRIBUTION_ALGORITHM='partitionDistribution',"
+ " DATA_NODES_AUTO_ADJUST=1,
DATA_NODES_AUTO_ADJUST_SCALE_UP=3, DATA_NODES_AUTO_ADJUST_SCALE_DOWN=2,"
+ " DATA_NODES_FILTER='filter',
CONSISTENCY_MODE='HIGH_AVAILABILITY';"
+ System.lineSeparator()
- + "CREATE TABLE IF NOT EXISTS PUBLIC.pojo_value_test
(id int, f_name varchar, l_name varchar, str varchar,"
- + " PRIMARY KEY (id)) COLOCATE BY (id, id_str) ZONE
ZONE_TEST;"
+ + "CREATE TABLE IF NOT EXISTS PUBLIC.POJO_VALUE_TEST
(ID INT, F_NAME VARCHAR, L_NAME VARCHAR, STR VARCHAR,"
+ + " PRIMARY KEY (ID)) COLOCATE BY (ID, ID_STR) ZONE
ZONE_TEST;"
+ System.lineSeparator()
- + "CREATE INDEX IF NOT EXISTS ix_pojo ON
PUBLIC.pojo_value_test (f_name, l_name desc);")
+ + "CREATE INDEX IF NOT EXISTS IX_POJO ON
PUBLIC.POJO_VALUE_TEST (F_NAME, L_NAME DESC);")
);
}
@@ -120,15 +120,15 @@ class CreateFromAnnotationsTest {
CreateFromAnnotationsImpl query =
createTable().processKeyValueClasses(PojoKey.class, PojoValue.class);
assertThat(
query.toString(),
- is("CREATE ZONE IF NOT EXISTS zone_test WITH
STORAGE_PROFILES='default', PARTITIONS=1, REPLICAS=3,"
+ is("CREATE ZONE IF NOT EXISTS ZONE_TEST WITH
STORAGE_PROFILES='default', PARTITIONS=1, REPLICAS=3,"
+ " DISTRIBUTION_ALGORITHM='partitionDistribution',"
+ " DATA_NODES_AUTO_ADJUST=1,
DATA_NODES_AUTO_ADJUST_SCALE_UP=3, DATA_NODES_AUTO_ADJUST_SCALE_DOWN=2,"
+ " DATA_NODES_FILTER='filter',
CONSISTENCY_MODE='HIGH_AVAILABILITY';"
+ System.lineSeparator()
- + "CREATE TABLE IF NOT EXISTS PUBLIC.pojo_value_test
(id int, id_str varchar(20), f_name varchar, l_name varchar,"
- + " str varchar, PRIMARY KEY (id, id_str)) COLOCATE BY
(id, id_str) ZONE ZONE_TEST;"
+ + "CREATE TABLE IF NOT EXISTS PUBLIC.POJO_VALUE_TEST
(ID INT, ID_STR VARCHAR(20), F_NAME VARCHAR, L_NAME VARCHAR,"
+ + " STR VARCHAR, PRIMARY KEY (ID, ID_STR)) COLOCATE BY
(ID, ID_STR) ZONE ZONE_TEST;"
+ System.lineSeparator()
- + "CREATE INDEX IF NOT EXISTS ix_pojo ON
PUBLIC.pojo_value_test (f_name, l_name desc);")
+ + "CREATE INDEX IF NOT EXISTS IX_POJO ON
PUBLIC.POJO_VALUE_TEST (F_NAME, L_NAME DESC);")
);
}
@@ -137,17 +137,36 @@ class CreateFromAnnotationsTest {
CreateFromAnnotationsImpl query =
createTable().processRecordClass(Pojo.class);
assertThat(
query.toString(),
- is("CREATE ZONE IF NOT EXISTS zone_test WITH
STORAGE_PROFILES='default', PARTITIONS=1, REPLICAS=3,"
+ is("CREATE ZONE IF NOT EXISTS ZONE_TEST WITH
STORAGE_PROFILES='default', PARTITIONS=1, REPLICAS=3,"
+ " DISTRIBUTION_ALGORITHM='partitionDistribution',"
+ " DATA_NODES_AUTO_ADJUST=1,
DATA_NODES_AUTO_ADJUST_SCALE_UP=3, DATA_NODES_AUTO_ADJUST_SCALE_DOWN=2,"
+ " DATA_NODES_FILTER='filter',
CONSISTENCY_MODE='STRONG_CONSISTENCY';"
+ System.lineSeparator()
- + "CREATE TABLE IF NOT EXISTS PUBLIC.pojo_test"
- + " (id int, id_str varchar(20), f_name varchar(20)
not null default 'a',"
- + " l_name varchar, str varchar, PRIMARY KEY (id,
id_str))"
- + " COLOCATE BY (id, id_str) ZONE ZONE_TEST;"
+ + "CREATE TABLE IF NOT EXISTS PUBLIC.POJO_TEST"
+ + " (ID INT, ID_STR VARCHAR(20), F_NAME varchar(20)
not null default 'a',"
+ + " L_NAME VARCHAR, STR VARCHAR, PRIMARY KEY (ID,
ID_STR))"
+ + " COLOCATE BY (ID, ID_STR) ZONE ZONE_TEST;"
+ System.lineSeparator()
- + "CREATE INDEX IF NOT EXISTS ix_pojo ON
PUBLIC.pojo_test (f_name, l_name desc);")
+ + "CREATE INDEX IF NOT EXISTS IX_POJO ON
PUBLIC.POJO_TEST (F_NAME, L_NAME DESC);")
+ );
+ }
+
+ @Test
+ void createFromRecordQuoted() {
+ CreateFromAnnotationsImpl query =
createTable().processRecordClass(PojoQuoted.class);
+ assertThat(
+ query.toString(),
+ is("CREATE ZONE IF NOT EXISTS \"zone test\" WITH
STORAGE_PROFILES='default', PARTITIONS=1, REPLICAS=3,"
+ + " DISTRIBUTION_ALGORITHM='partitionDistribution',"
+ + " DATA_NODES_AUTO_ADJUST=1,
DATA_NODES_AUTO_ADJUST_SCALE_UP=3, DATA_NODES_AUTO_ADJUST_SCALE_DOWN=2,"
+ + " DATA_NODES_FILTER='filter',
CONSISTENCY_MODE='STRONG_CONSISTENCY';"
+ + System.lineSeparator()
+ + "CREATE TABLE IF NOT EXISTS \"sche ma\".\"pojo
test\""
+ + " (ID INT, \"id str\" VARCHAR(20), \"f name\"
varchar(20) not null default 'a',"
+ + " \"l name\" VARCHAR, STR VARCHAR, PRIMARY KEY (ID,
\"id str\"))"
+ + " COLOCATE BY (ID, \"id str\") ZONE \"zone test\";"
+ + System.lineSeparator()
+ + "CREATE INDEX IF NOT EXISTS \"ix pojo\" ON \"sche
ma\".\"pojo test\" (\"f name\", \"l name\" DESC);")
);
}
@@ -161,9 +180,9 @@ class CreateFromAnnotationsTest {
CreateFromAnnotationsImpl query =
createTable().processRecordClass(NameGeneration.class);
assertThat(
query.toString(),
- is("CREATE TABLE IF NOT EXISTS PUBLIC.NameGeneration (col1
int, col2 varchar);"
+ is("CREATE TABLE IF NOT EXISTS PUBLIC.NAMEGENERATION (COL1
INT, COL2 VARCHAR);"
+ System.lineSeparator()
- + "CREATE INDEX IF NOT EXISTS ix_col1_col2 ON
PUBLIC.NameGeneration (col1, col2);")
+ + "CREATE INDEX IF NOT EXISTS IX_COL1_COL2 ON
PUBLIC.NAMEGENERATION (COL1, COL2);")
);
}
@@ -172,7 +191,7 @@ class CreateFromAnnotationsTest {
CreateFromAnnotationsImpl query =
createTable().processRecordClass(PkSort.class);
assertThat(
query.toString(),
- is("CREATE TABLE IF NOT EXISTS PUBLIC.PkSort (id int, PRIMARY
KEY USING SORTED (id desc));")
+ is("CREATE TABLE IF NOT EXISTS PUBLIC.PKSORT (ID INT, PRIMARY
KEY USING SORTED (ID DESC));")
);
}
@@ -192,11 +211,11 @@ class CreateFromAnnotationsTest {
CreateFromAnnotationsImpl query =
createTable().processRecordClass(AllColumnsPojo.class);
assertThat(
query.toString(),
- is("CREATE TABLE IF NOT EXISTS PUBLIC.AllColumnsPojo ("
- + "str varchar, byteCol tinyint, shortCol smallint,
intCol int, longCol bigint, floatCol real, "
- + "doubleCol double, decimalCol decimal, boolCol
boolean, bytesCol varbinary, uuidCol uuid, "
- + "dateCol date, timeCol time, datetimeCol timestamp,
instantCol timestamp with local time zone, "
- + "PRIMARY KEY (str));")
+ is("CREATE TABLE IF NOT EXISTS PUBLIC.ALLCOLUMNSPOJO ("
+ + "STR VARCHAR, BYTECOL TINYINT, SHORTCOL SMALLINT,
INTCOL INT, LONGCOL BIGINT, FLOATCOL REAL, "
+ + "DOUBLECOL DOUBLE, DECIMALCOL DECIMAL, BOOLCOL
BOOLEAN, BYTESCOL VARBINARY, UUIDCOL UUID, "
+ + "DATECOL DATE, TIMECOL TIME, DATETIMECOL TIMESTAMP,
INSTANTCOL TIMESTAMP WITH LOCAL TIME ZONE, "
+ + "PRIMARY KEY (STR));")
);
}
@@ -346,6 +365,45 @@ class CreateFromAnnotationsTest {
private static class NoAnnotations {
}
+ @SuppressWarnings("unused")
+ @Table(
+ value = "pojo test",
+ schemaName = "sche ma",
+ zone = @Zone(
+ value = "zone test",
+ partitions = 1,
+ replicas = 3,
+ distributionAlgorithm = "partitionDistribution",
+ dataNodesAutoAdjust = 1,
+ dataNodesAutoAdjustScaleDown = 2,
+ dataNodesAutoAdjustScaleUp = 3,
+ filter = "filter",
+ storageProfiles = "default",
+ consistencyMode = "STRONG_CONSISTENCY"
+ ),
+ colocateBy = {@ColumnRef("id"), @ColumnRef("id str")},
+ indexes = @Index(value = "ix pojo", columns = {
+ @ColumnRef("f name"),
+ @ColumnRef(value = "l name", sort = SortOrder.DESC)
+ })
+ )
+ static class PojoQuoted {
+ @Id
+ Integer id;
+
+ @Id
+ @Column(value = "id str", length = 20)
+ String idStr;
+
+ @Column(value = "f name", columnDefinition = "varchar(20) not null
default 'a'")
+ String firstName;
+
+ @Column("l name")
+ String lastName;
+
+ String str;
+ }
+
private static CreateFromAnnotationsImpl createTable() {
return new CreateFromAnnotationsImpl(null);
}
diff --git
a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateFromDefinitionTest.java
b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateFromDefinitionTest.java
index 23635f610e3..78fe9ae2d00 100644
---
a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateFromDefinitionTest.java
+++
b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateFromDefinitionTest.java
@@ -42,7 +42,7 @@ class CreateFromDefinitionTest {
void createFromZoneBuilderSimple() {
ZoneDefinition zone =
ZoneDefinition.builder("zone_test").storageProfiles("default").build();
- assertThat(createZone(zone), is("CREATE ZONE zone_test WITH
STORAGE_PROFILES='default';"));
+ assertThat(createZone(zone), is("CREATE ZONE ZONE_TEST WITH
STORAGE_PROFILES='default';"));
}
@Test
@@ -62,7 +62,7 @@ class CreateFromDefinitionTest {
assertThat(
createZone(zone),
- is("CREATE ZONE IF NOT EXISTS zone_test WITH
STORAGE_PROFILES='default', PARTITIONS=3, REPLICAS=3,"
+ is("CREATE ZONE IF NOT EXISTS ZONE_TEST WITH
STORAGE_PROFILES='default', PARTITIONS=3, REPLICAS=3,"
+ " DISTRIBUTION_ALGORITHM='partitionDistribution',"
+ " DATA_NODES_AUTO_ADJUST=1,
DATA_NODES_AUTO_ADJUST_SCALE_UP=3, DATA_NODES_AUTO_ADJUST_SCALE_DOWN=2,"
+ " DATA_NODES_FILTER='filter',
CONSISTENCY_MODE='HIGH_AVAILABILITY';")
@@ -100,7 +100,7 @@ class CreateFromDefinitionTest {
.columns(column("id", INTEGER))
.build();
- assertThat(createTable(table), is("CREATE TABLE PUBLIC.builder_test
(id int);"));
+ assertThat(createTable(table), is("CREATE TABLE PUBLIC.BUILDER_TEST
(ID INT);"));
}
@Test
@@ -121,13 +121,44 @@ class CreateFromDefinitionTest {
assertThat(
createTable(table),
- is("CREATE TABLE IF NOT EXISTS PUBLIC.builder_test"
- + " (id int, id_str varchar, f_name varchar(20) NOT
NULL DEFAULT 'a', PRIMARY KEY (id, id_str))"
- + " COLOCATE BY (id, id_str) ZONE ZONE_TEST;"
+ is("CREATE TABLE IF NOT EXISTS PUBLIC.BUILDER_TEST"
+ + " (ID INT, ID_STR VARCHAR, F_NAME VARCHAR(20) NOT
NULL DEFAULT 'a', PRIMARY KEY (ID, ID_STR))"
+ + " COLOCATE BY (ID, ID_STR) ZONE ZONE_TEST;"
+ System.lineSeparator()
- + "CREATE INDEX IF NOT EXISTS ix_id_str_f_name ON
PUBLIC.builder_test (id_str, f_name);"
+ + "CREATE INDEX IF NOT EXISTS IX_ID_STR_F_NAME ON
PUBLIC.BUILDER_TEST (ID_STR, F_NAME);"
+ System.lineSeparator()
- + "CREATE INDEX IF NOT EXISTS ix_test ON
PUBLIC.builder_test USING SORTED (id_str asc, f_name desc nulls last);")
+ + "CREATE INDEX IF NOT EXISTS IX_TEST ON
PUBLIC.BUILDER_TEST USING SORTED (ID_STR ASC, F_NAME DESC NULLS LAST);")
+ );
+ }
+
+
+ @Test
+ void createFromTableBuilderQuoteNames() {
+ TableDefinition table = TableDefinition.builder("builder test")
+ .ifNotExists()
+ .schema("sche ma")
+ .colocateBy("id", "id str")
+ .zone("zone test")
+ .columns(
+ column("id", INTEGER),
+ column("id str", VARCHAR),
+ column("f name",
ColumnType.varchar(20).notNull().defaultValue("a"))
+ )
+ .primaryKey("id", "id str")
+ .index("id str", "f name")
+ .index("ix test", IndexType.SORTED, column("id str").asc(),
column("f name").sort(DESC_NULLS_LAST))
+ .build();
+
+ assertThat(
+ createTable(table),
+ is("CREATE TABLE IF NOT EXISTS \"sche ma\".\"builder test\""
+ + " (ID INT, \"id str\" VARCHAR, \"f name\"
VARCHAR(20) NOT NULL DEFAULT 'a', PRIMARY KEY (ID, \"id str\"))"
+ + " COLOCATE BY (ID, \"id str\") ZONE \"zone test\";"
+ + System.lineSeparator()
+ + "CREATE INDEX IF NOT EXISTS \"ix_id str_f name\" ON
\"sche ma\".\"builder test\" (\"id str\", \"f name\");"
+ + System.lineSeparator()
+ + "CREATE INDEX IF NOT EXISTS \"ix test\" ON \"sche
ma\".\"builder test\" USING SORTED"
+ + " (\"id str\" ASC, \"f name\" DESC NULLS LAST);")
);
}
@@ -141,7 +172,7 @@ class CreateFromDefinitionTest {
assertThat(
createTable(tableDefinition),
- is("CREATE TABLE PUBLIC.primitive_test (id int, val int,
PRIMARY KEY (id));")
+ is("CREATE TABLE PUBLIC.PRIMITIVE_TEST (ID INT, VAL INT,
PRIMARY KEY (ID));")
);
}
@@ -155,7 +186,7 @@ class CreateFromDefinitionTest {
assertThat(
createTable(tableDefinition),
- is("CREATE TABLE PUBLIC.pojo_value_test (id int, f_name
varchar, l_name varchar, str varchar, PRIMARY KEY (id));")
+ is("CREATE TABLE PUBLIC.POJO_VALUE_TEST (ID INT, F_NAME
VARCHAR, L_NAME VARCHAR, STR VARCHAR, PRIMARY KEY (ID));")
);
}
@@ -171,9 +202,9 @@ class CreateFromDefinitionTest {
assertThat(
createTable(tableDefinition),
- is("CREATE TABLE PUBLIC.pojo_value_test"
- + " (id int, id_str varchar(20), f_name varchar,
l_name varchar, str varchar, PRIMARY KEY (id, id_str))"
- + " COLOCATE BY (id, id_str) ZONE ZONE_TEST;")
+ is("CREATE TABLE PUBLIC.POJO_VALUE_TEST"
+ + " (ID INT, ID_STR VARCHAR(20), F_NAME VARCHAR,
L_NAME VARCHAR, STR VARCHAR, PRIMARY KEY (ID, ID_STR))"
+ + " COLOCATE BY (ID, ID_STR) ZONE ZONE_TEST;")
);
}
@@ -188,9 +219,9 @@ class CreateFromDefinitionTest {
assertThat(
createTable(tableDefinition),
- is("CREATE TABLE IF NOT EXISTS PUBLIC.pojo_test (id int,
id_str varchar(20),"
- + " f_name varchar(20) not null default 'a', l_name
varchar, str varchar,"
- + " PRIMARY KEY (id, id_str)) COLOCATE BY (id, id_str)
ZONE ZONE_TEST;")
+ is("CREATE TABLE IF NOT EXISTS PUBLIC.POJO_TEST (ID INT,
ID_STR VARCHAR(20),"
+ + " F_NAME varchar(20) not null default 'a', L_NAME
VARCHAR, STR VARCHAR,"
+ + " PRIMARY KEY (ID, ID_STR)) COLOCATE BY (ID, ID_STR)
ZONE ZONE_TEST;")
);
}
@@ -202,7 +233,7 @@ class CreateFromDefinitionTest {
assertThat(
createTable(tableDefinition),
- is("CREATE TABLE PUBLIC.primitive_test (id int, PRIMARY KEY
(id));")
+ is("CREATE TABLE PUBLIC.PRIMITIVE_TEST (ID INT, PRIMARY KEY
(ID));")
);
}
diff --git
a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateTableTest.java
b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateTableTest.java
index 04987590e1b..f1feefcd82e 100644
---
a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateTableTest.java
+++
b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateTableTest.java
@@ -21,7 +21,6 @@ import static org.apache.ignite.catalog.ColumnType.INTEGER;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.is;
-import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.List;
import org.apache.ignite.catalog.ColumnSorted;
@@ -34,29 +33,30 @@ class CreateTableTest {
void ifNotExists() {
Query query1 =
createTable().ifNotExists().name("table1").addColumn("col1", INTEGER);
String sql = query1.toString();
- assertThat(sql, is("CREATE TABLE IF NOT EXISTS table1 (col1 int);"));
+ assertThat(sql, is("CREATE TABLE IF NOT EXISTS TABLE1 (COL1 INT);"));
}
@Test
void names() {
- Query query5 = createTable().name("", "table1").addColumn("col1",
INTEGER);
- String sql = query5.toString();
- assertThat(sql, is("CREATE TABLE table1 (col1 int);"));
+ Query query1 = createTable().name("", "table1").addColumn("col1",
INTEGER);
+ String sql = query1.toString();
+ assertThat(sql, is("CREATE TABLE TABLE1 (COL1 INT);"));
- Query query4 = createTable().name(null, "table1").addColumn("col1",
INTEGER);
- sql = query4.toString();
- assertThat(sql, is("CREATE TABLE table1 (col1 int);"));
+ Query query2 = createTable().name(null, "table1").addColumn("col1",
INTEGER);
+ sql = query2.toString();
+ assertThat(sql, is("CREATE TABLE TABLE1 (COL1 INT);"));
Query query3 = createTable().name("public",
"table1").addColumn("col1", INTEGER);
sql = query3.toString();
- assertThat(sql, is("CREATE TABLE public.table1 (col1 int);"));
- }
+ assertThat(sql, is("CREATE TABLE PUBLIC.TABLE1 (COL1 INT);"));
- @Test
- void invalidNames() {
- assertThrows(NullPointerException.class, () ->
createTable().name((String[]) null));
+ Query query4 = createTable().name("public", "Tabl
e").addColumn("col1", INTEGER);
+ sql = query4.toString();
+ assertThat(sql, is("CREATE TABLE PUBLIC.\"Tabl e\" (COL1 INT);"));
- assertThrows(IllegalArgumentException.class, () ->
createTable().name("table;1--test\n\r\t;"));
+ Query query5 = createTable().name("PUB lic", "Tabl
e").addColumn("col1", INTEGER);
+ sql = query5.toString();
+ assertThat(sql, is("CREATE TABLE \"PUB lic\".\"Tabl e\" (COL1 INT);"));
}
@Test
@@ -64,13 +64,13 @@ class CreateTableTest {
Query query3 = createTable().name("table1")
.addColumn("col", INTEGER);
String sql = query3.toString();
- assertThat(sql, is("CREATE TABLE table1 (col int);"));
+ assertThat(sql, is("CREATE TABLE TABLE1 (COL INT);"));
Query query2 = createTable().name("table1")
.addColumn("col1", INTEGER)
.addColumn("col2", INTEGER);
sql = query2.toString();
- assertThat(sql, is("CREATE TABLE table1 (col1 int, col2 int);"));
+ assertThat(sql, is("CREATE TABLE TABLE1 (COL1 INT, COL2 INT);"));
}
@Test
@@ -79,20 +79,20 @@ class CreateTableTest {
.addColumn("col", INTEGER)
.primaryKey(List.of("col"));
String sql = query5.toString();
- assertThat(sql, is("CREATE TABLE table1 (col int, PRIMARY KEY
(col));"));
+ assertThat(sql, is("CREATE TABLE TABLE1 (COL INT, PRIMARY KEY
(COL));"));
Query query4 = createTable().name("table1")
.addColumn("col1", INTEGER)
.addColumn("col2", INTEGER)
.primaryKey(List.of("col1", "col2"));
sql = query4.toString();
- assertThat(sql, is("CREATE TABLE table1 (col1 int, col2 int, PRIMARY
KEY (col1, col2));"));
+ assertThat(sql, is("CREATE TABLE TABLE1 (COL1 INT, COL2 INT, PRIMARY
KEY (COL1, COL2));"));
Query query3 = createTable().name("table1")
.addColumn("col1", INTEGER)
.primaryKey(IndexType.SORTED,
List.of(ColumnSorted.column("col1", SortOrder.ASC_NULLS_FIRST)));
sql = query3.toString();
- assertThat(sql, is("CREATE TABLE table1 (col1 int, PRIMARY KEY USING
SORTED (col1 asc nulls first));"));
+ assertThat(sql, is("CREATE TABLE TABLE1 (COL1 INT, PRIMARY KEY USING
SORTED (COL1 ASC NULLS FIRST));"));
}
@Test
@@ -100,17 +100,17 @@ class CreateTableTest {
Query query5 = createTable().name("table1").addColumn("col1", INTEGER)
.colocateBy("col1");
String sql = query5.toString();
- assertThat(sql, is("CREATE TABLE table1 (col1 int) COLOCATE BY
(col1);"));
+ assertThat(sql, is("CREATE TABLE TABLE1 (COL1 INT) COLOCATE BY
(COL1);"));
Query query4 = createTable().name("table1").addColumn("col1", INTEGER)
.colocateBy("col1", "col2");
sql = query4.toString();
- assertThat(sql, is("CREATE TABLE table1 (col1 int) COLOCATE BY (col1,
col2);"));
+ assertThat(sql, is("CREATE TABLE TABLE1 (COL1 INT) COLOCATE BY (COL1,
COL2);"));
Query query3 = createTable().name("table1").addColumn("col1", INTEGER)
.colocateBy("col1", "col2");
sql = query3.toString();
- assertThat(sql, is("CREATE TABLE table1 (col1 int) COLOCATE BY (col1,
col2);"));
+ assertThat(sql, is("CREATE TABLE TABLE1 (COL1 INT) COLOCATE BY (COL1,
COL2);"));
}
@Test
@@ -118,7 +118,7 @@ class CreateTableTest {
Query query1 = createTable().name("table1").addColumn("col1", INTEGER)
.zone("zone1");
String sql = query1.toString(); // zone param is lowercase
- assertThat(sql, is("CREATE TABLE table1 (col1 int) ZONE ZONE1;")); //
zone result is uppercase
+ assertThat(sql, is("CREATE TABLE TABLE1 (COL1 INT) ZONE ZONE1;")); //
zone result is uppercase
}
@Test
@@ -131,12 +131,12 @@ class CreateTableTest {
)
);
String sql = query3.toString();
- assertThat(sql, endsWith("CREATE INDEX IF NOT EXISTS ix_test1 ON
table1 USING SORTED (col1, COL2_UPPER desc nulls last);"));
+ assertThat(sql, endsWith("CREATE INDEX IF NOT EXISTS IX_TEST1 ON
TABLE1 USING SORTED (COL1, COL2_UPPER DESC NULLS LAST);"));
Query query2 = createTable().name("table1").addColumn("col1", INTEGER)
.addIndex("ix_test1", IndexType.HASH,
List.of(ColumnSorted.column("col1")));
sql = query2.toString();
- assertThat(sql, endsWith("CREATE INDEX IF NOT EXISTS ix_test1 ON
table1 USING HASH (col1);"));
+ assertThat(sql, endsWith("CREATE INDEX IF NOT EXISTS IX_TEST1 ON
TABLE1 USING HASH (COL1);"));
}
private static CreateTableImpl createTable() {
diff --git
a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateZoneTest.java
b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateZoneTest.java
index 92a828412a0..5702d6209c0 100644
---
a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateZoneTest.java
+++
b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateZoneTest.java
@@ -27,25 +27,29 @@ class CreateZoneTest {
void testIfNotExists() {
Query query1 = createZone().ifNotExists().name("zone1");
String sql = query1.toString();
- assertThat(sql, is("CREATE ZONE IF NOT EXISTS zone1;"));
+ assertThat(sql, is("CREATE ZONE IF NOT EXISTS ZONE1;"));
}
@Test
void testNames() {
- Query query1 = createZone().name("public", "zone1");
+ Query query1 = createZone().name("zone1");
String sql = query1.toString();
- assertThat(sql, is("CREATE ZONE public.zone1;"));
+ assertThat(sql, is("CREATE ZONE ZONE1;"));
+
+ Query query2 = createZone().name("Zo Ne");
+ sql = query2.toString();
+ assertThat(sql, is("CREATE ZONE \"Zo Ne\";"));
}
@Test
void testWithOptions() {
Query query4 = createZone().name("zone1").partitions(1);
String sql = query4.toString();
- assertThat(sql, is("CREATE ZONE zone1 WITH PARTITIONS=1;"));
+ assertThat(sql, is("CREATE ZONE ZONE1 WITH PARTITIONS=1;"));
Query query3 = createZone().name("zone1").partitions(1).replicas(1);
sql = query3.toString();
- assertThat(sql, is("CREATE ZONE zone1 WITH PARTITIONS=1,
REPLICAS=1;"));
+ assertThat(sql, is("CREATE ZONE ZONE1 WITH PARTITIONS=1,
REPLICAS=1;"));
}
private static CreateZoneImpl createZone() {
diff --git
a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/DropTableTest.java
b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/DropTableTest.java
index bcb8b5a46ff..afea81d4420 100644
---
a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/DropTableTest.java
+++
b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/DropTableTest.java
@@ -25,13 +25,17 @@ import org.junit.jupiter.api.Test;
class DropTableTest {
@Test
void testDropTable() {
- Query query2 = dropTable().name("table1");
- String sql = query2.toString();
- assertThat(sql, is("DROP TABLE table1;"));
+ Query query1 = dropTable().name("table1");
+ String sql = query1.toString();
+ assertThat(sql, is("DROP TABLE TABLE1;"));
- Query query1 = dropTable().ifExists().name("table1");
- sql = query1.toString();
- assertThat(sql, is("DROP TABLE IF EXISTS table1;"));
+ Query query2 = dropTable().ifExists().name("table1");
+ sql = query2.toString();
+ assertThat(sql, is("DROP TABLE IF EXISTS TABLE1;"));
+
+ Query query3 = dropTable().ifExists().name("a b");
+ sql = query3.toString();
+ assertThat(sql, is("DROP TABLE IF EXISTS \"a b\";"));
}
private static DropTableImpl dropTable() {
diff --git
a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/DropZoneTest.java
b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/DropZoneTest.java
index 37c1aaca42e..e51705c7866 100644
---
a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/DropZoneTest.java
+++
b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/DropZoneTest.java
@@ -25,13 +25,17 @@ import org.junit.jupiter.api.Test;
class DropZoneTest {
@Test
void testDropZone() {
- Query query2 = dropZone().name("zone1");
- String sql = query2.toString();
- assertThat(sql, is("DROP ZONE zone1;"));
+ Query query1 = dropZone().name("zone1");
+ String sql = query1.toString();
+ assertThat(sql, is("DROP ZONE ZONE1;"));
- Query query1 = dropZone().ifExists().name("zone1");
- sql = query1.toString();
- assertThat(sql, is("DROP ZONE IF EXISTS zone1;"));
+ Query query2 = dropZone().ifExists().name("zone1");
+ sql = query2.toString();
+ assertThat(sql, is("DROP ZONE IF EXISTS ZONE1;"));
+
+ Query query3 = dropZone().name("Zo Ne1");
+ sql = query3.toString();
+ assertThat(sql, is("DROP ZONE \"Zo Ne1\";"));
}
private static DropZoneImpl dropZone() {
diff --git
a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/QueryPartTest.java
b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/QueryPartTest.java
index f8491cc139f..9f74da0517f 100644
---
a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/QueryPartTest.java
+++
b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/QueryPartTest.java
@@ -41,6 +41,7 @@ import static
org.apache.ignite.internal.catalog.sql.ColumnTypeImpl.wrap;
import static
org.apache.ignite.internal.catalog.sql.IndexColumnImpl.parseColumn;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import java.math.BigDecimal;
import java.util.List;
@@ -51,107 +52,140 @@ import org.junit.jupiter.api.Test;
class QueryPartTest {
@Test
- void namePart() {
- Name name = new Name("a");
- assertThat(sql(name), is("a"));
+ void simpleNamePart() {
+ assertThat(sql(Name.simple("a")), is("A"));
+ assertThat(sql(Name.simple("A")), is("A"));
+ assertThat(sql(Name.simple("aBCd")), is("ABCD"));
+ assertThat(sql(Name.simple("\"aBcD\"")), is("\"aBcD\""));
+
+ assertThat(sql(Name.simple("a.b")), is("\"a.b\""));
+ assertThat(sql(Name.simple(".a.b")), is("\".a.b\""));
+
+ // whitespace
+ assertThat(sql(Name.simple("a b")), is("\"a b\""));
+ assertThat(sql(Name.simple("a ")), is("\"a \""));
+ assertThat(sql(Name.simple(" a")), is("\" a\""));
+ assertThat(sql(Name.simple("a b ")), is("\"a b \""));
+ assertThat(sql(Name.simple(" a b ")), is("\" a b \""));
+ assertThat(sql(Name.simple(" aXb ")), is("\" aXb \""));
+
+ // underscore
+ assertThat(sql(Name.simple("_a")), is("_A"));
+ assertThat(sql(Name.simple("_aB")), is("_AB"));
+ assertThat(sql(Name.simple("_a_B_c")), is("_A_B_C"));
+ assertThat(sql(Name.simple("_a B")), is("\"_a B\""));
+ assertThat(sql(Name.simple("_a b")), is("\"_a b\""));
+ }
- name = new Name("a", "b", "c");
- assertThat(sql(name), is("a.b.c"));
+ @Test
+ void compoundNamePart() {
+ assertThat(sql(Name.compound("a")), is("A"));
+ assertThat(sql(Name.compound("A")), is("A"));
+ assertThat(sql(Name.compound(null, "a")), is("A"));
+ assertThat(sql(Name.compound("", "a")), is("A"));
+ assertThat(sql(Name.compound("a", "b", "c")), is("A.B.C"));
+ assertThat(sql(Name.compound("a", "aB Cd")), is("A.\"aB Cd\""));
+
+ assertThrows(IllegalArgumentException.class, () -> Name.compound("",
"", "a"));
+ assertThrows(IllegalArgumentException.class, () -> Name.compound("a",
""));
+ assertThrows(IllegalArgumentException.class, () -> Name.compound("a",
"", "b"));
+ assertThrows(IllegalArgumentException.class, () -> Name.compound("a",
null));
+ assertThrows(IllegalArgumentException.class, () -> Name.compound("a",
null, "b"));
}
@Test
void colocatePart() {
Colocate colocate = new Colocate("a");
- assertThat(sql(colocate), is("COLOCATE BY (a)"));
+ assertThat(sql(colocate), is("COLOCATE BY (A)"));
colocate = new Colocate("a", "b");
- assertThat(sql(colocate), is("COLOCATE BY (a, b)"));
+ assertThat(sql(colocate), is("COLOCATE BY (A, B)"));
}
@Test
void columnPart() {
Column column = new Column("a", wrap(VARCHAR));
- assertThat(sql(column), is("a varchar"));
+ assertThat(sql(column), is("A VARCHAR"));
column = new Column("a", wrap(ColumnType.varchar(3)));
- assertThat(sql(column), is("a varchar(3)"));
+ assertThat(sql(column), is("A VARCHAR(3)"));
column = new Column("a", wrap(ColumnType.decimal(2, 3)));
- assertThat(sql(column), is("a decimal(2, 3)"));
+ assertThat(sql(column), is("A DECIMAL(2, 3)"));
}
@Test
void columnTypePart() {
- assertThat(sql(wrap(BOOLEAN)), is("boolean"));
- assertThat(sql(wrap(TINYINT)), is("tinyint"));
- assertThat(sql(wrap(SMALLINT)), is("smallint"));
- assertThat(sql(wrap(INT8)), is("tinyint"));
- assertThat(sql(wrap(INT16)), is("smallint"));
- assertThat(sql(wrap(INT32)), is("int"));
- assertThat(sql(wrap(INT64)), is("bigint"));
- assertThat(sql(wrap(INTEGER)), is("int"));
- assertThat(sql(wrap(BIGINT)), is("bigint"));
- assertThat(sql(wrap(REAL)), is("real"));
- assertThat(sql(wrap(FLOAT)), is("real"));
- assertThat(sql(wrap(DOUBLE)), is("double"));
- assertThat(sql(wrap(VARCHAR)), is("varchar"));
- assertThat(sql(wrap(ColumnType.varchar(1))), is("varchar(1)"));
- assertThat(sql(wrap(VARBINARY)), is("varbinary"));
- assertThat(sql(wrap(ColumnType.varbinary(1))), is("varbinary(1)"));
- assertThat(sql(wrap(TIME)), is("time"));
- assertThat(sql(wrap(ColumnType.time(1))), is("time(1)"));
- assertThat(sql(wrap(TIMESTAMP)), is("timestamp"));
- assertThat(sql(wrap(ColumnType.timestamp(1))), is("timestamp(1)"));
- assertThat(sql(wrap(DATE)), is("date"));
- assertThat(sql(wrap(DECIMAL)), is("decimal"));
- assertThat(sql(wrap(ColumnType.decimal(1, 2))), is("decimal(1, 2)"));
- assertThat(sql(wrap(UUID)), is("uuid"));
+ assertThat(sql(wrap(BOOLEAN)), is("BOOLEAN"));
+ assertThat(sql(wrap(TINYINT)), is("TINYINT"));
+ assertThat(sql(wrap(SMALLINT)), is("SMALLINT"));
+ assertThat(sql(wrap(INT8)), is("TINYINT"));
+ assertThat(sql(wrap(INT16)), is("SMALLINT"));
+ assertThat(sql(wrap(INT32)), is("INT"));
+ assertThat(sql(wrap(INT64)), is("BIGINT"));
+ assertThat(sql(wrap(INTEGER)), is("INT"));
+ assertThat(sql(wrap(BIGINT)), is("BIGINT"));
+ assertThat(sql(wrap(REAL)), is("REAL"));
+ assertThat(sql(wrap(FLOAT)), is("REAL"));
+ assertThat(sql(wrap(DOUBLE)), is("DOUBLE"));
+ assertThat(sql(wrap(VARCHAR)), is("VARCHAR"));
+ assertThat(sql(wrap(ColumnType.varchar(1))), is("VARCHAR(1)"));
+ assertThat(sql(wrap(VARBINARY)), is("VARBINARY"));
+ assertThat(sql(wrap(ColumnType.varbinary(1))), is("VARBINARY(1)"));
+ assertThat(sql(wrap(TIME)), is("TIME"));
+ assertThat(sql(wrap(ColumnType.time(1))), is("TIME(1)"));
+ assertThat(sql(wrap(TIMESTAMP)), is("TIMESTAMP"));
+ assertThat(sql(wrap(ColumnType.timestamp(1))), is("TIMESTAMP(1)"));
+ assertThat(sql(wrap(DATE)), is("DATE"));
+ assertThat(sql(wrap(DECIMAL)), is("DECIMAL"));
+ assertThat(sql(wrap(ColumnType.decimal(1, 2))), is("DECIMAL(1, 2)"));
+ assertThat(sql(wrap(UUID)), is("UUID"));
}
@Test
void columnTypeOptionsPart() {
- assertThat(sql(wrap(INTEGER)), is("int"));
- assertThat(sql(wrap(INTEGER.notNull())), is("int NOT NULL"));
- assertThat(sql(wrap(INTEGER.defaultValue(1))), is("int DEFAULT 1"));
- assertThat(sql(wrap(VARCHAR.defaultValue("s"))), is("varchar DEFAULT
's'")); // default in single quotes
- assertThat(sql(wrap(INTEGER.defaultExpression("gen_expr"))), is("int
DEFAULT gen_expr"));
- assertThat(sql(wrap(INTEGER.notNull().defaultValue(1))), is("int NOT
NULL DEFAULT 1"));
- assertThat(sql(wrap(ColumnType.decimal(2,
3).defaultValue(BigDecimal.ONE).notNull())), is("decimal(2, 3) NOT NULL DEFAULT
1"));
-
assertThat(sql(wrap(INTEGER.defaultValue(1).defaultExpression("gen_expr"))),
is("int DEFAULT 1"));
+ assertThat(sql(wrap(INTEGER)), is("INT"));
+ assertThat(sql(wrap(INTEGER.notNull())), is("INT NOT NULL"));
+ assertThat(sql(wrap(INTEGER.defaultValue(1))), is("INT DEFAULT 1"));
+ assertThat(sql(wrap(VARCHAR.defaultValue("s"))), is("VARCHAR DEFAULT
's'")); // default in single quotes
+ assertThat(sql(wrap(INTEGER.defaultExpression("gen_expr"))), is("INT
DEFAULT gen_expr"));
+ assertThat(sql(wrap(INTEGER.notNull().defaultValue(1))), is("INT NOT
NULL DEFAULT 1"));
+ assertThat(sql(wrap(ColumnType.decimal(2,
3).defaultValue(BigDecimal.ONE).notNull())), is("DECIMAL(2, 3) NOT NULL DEFAULT
1"));
+
assertThat(sql(wrap(INTEGER.defaultValue(1).defaultExpression("gen_expr"))),
is("INT DEFAULT 1"));
}
@Test
void constraintPart() {
Constraint constraint = new Constraint().primaryKey(column("a"));
- assertThat(sql(constraint), is("PRIMARY KEY (a)"));
+ assertThat(sql(constraint), is("PRIMARY KEY (A)"));
constraint = new Constraint().primaryKey(IndexType.SORTED,
List.of(column("a")));
- assertThat(sql(constraint), is("PRIMARY KEY USING SORTED (a)"));
+ assertThat(sql(constraint), is("PRIMARY KEY USING SORTED (A)"));
constraint = new Constraint().primaryKey(column("a"), column("b"));
- assertThat(sql(constraint), is("PRIMARY KEY (a, b)"));
+ assertThat(sql(constraint), is("PRIMARY KEY (A, B)"));
constraint = new Constraint().primaryKey(IndexType.SORTED,
List.of(column("a"), column("b")));
- assertThat(sql(constraint), is("PRIMARY KEY USING SORTED (a, b)"));
+ assertThat(sql(constraint), is("PRIMARY KEY USING SORTED (A, B)"));
}
@Test
void queryPartCollection() {
- QueryPartCollection<Name> collection =
QueryPartCollection.partsList(new Name("a"), new Name("b"));
+ QueryPartCollection<Name> collection =
QueryPartCollection.partsList(Name.simple("a"), Name.simple("b"));
- assertThat(sql(collection), is("a, b"));
+ assertThat(sql(collection), is("A, B"));
}
@Test
void indexColumnPart() {
IndexColumnImpl column = IndexColumnImpl.wrap(column("col1"));
- assertThat(sql(column), is("col1"));
+ assertThat(sql(column), is("COL1"));
column = IndexColumnImpl.wrap(column("col1",
SortOrder.ASC_NULLS_FIRST));
- assertThat(sql(column), is("col1 asc nulls first"));
+ assertThat(sql(column), is("COL1 ASC NULLS FIRST"));
column = IndexColumnImpl.wrap(column("col1",
SortOrder.DESC_NULLS_LAST));
- assertThat(sql(column), is("col1 desc nulls last"));
+ assertThat(sql(column), is("COL1 DESC NULLS LAST"));
}
@Test