diff --git a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseColumn.java b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseColumn.java index 340116063..aac9dc41c 100644 --- a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseColumn.java +++ b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseColumn.java @@ -321,16 +321,18 @@ protected static int readColumn(String args, int startIndex, int len, String nam StringBuilder sb = new StringBuilder(); i = ClickHouseUtils.readNameOrQuotedString(args, i, len, sb); String modifier = sb.toString(); + String normalizedModifier = modifier.toUpperCase(); sb.setLength(0); boolean startsWithNot = false; - if ("not".equalsIgnoreCase(modifier)) { + if ("NOT".equals(normalizedModifier)) { startsWithNot = true; i = ClickHouseUtils.readNameOrQuotedString(args, i, len, sb); modifier = sb.toString(); + normalizedModifier = modifier.toUpperCase(); sb.setLength(0); } - if ("null".equalsIgnoreCase(modifier)) { + if ("NULL".equals(normalizedModifier)) { if (nullable) { throw new IllegalArgumentException("Nullable and NULL cannot be used together"); } @@ -339,14 +341,14 @@ protected static int readColumn(String args, int startIndex, int len, String nam break; } else if (startsWithNot) { throw new IllegalArgumentException("Expect keyword NULL after NOT"); - } else if ("alias".equalsIgnoreCase(modifier) || "codec".equalsIgnoreCase(modifier) - || "default".equalsIgnoreCase(modifier) || "materialized".equalsIgnoreCase(modifier) - || "ttl".equalsIgnoreCase(modifier)) { // stop words + } else if ("ALIAS".equals(normalizedModifier) || "CODEC".equals(normalizedModifier) + || "DEFAULT".equals(normalizedModifier) || "MATERIALIZED".equals(normalizedModifier) + || "TTL".equals(normalizedModifier)) { // stop words i = ClickHouseUtils.skipContentsUntil(args, i, len, ',') - 1; break; } else { if ((name == null || name.isEmpty()) - && !ClickHouseDataType.mayStartWith(builder.toString())) { + && !ClickHouseDataType.mayStartWith(builder.toString(), normalizedModifier)) { return readColumn(args, i - modifier.length(), len, builder.toString(), list); } else { builder.append(' '); diff --git a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseDataType.java b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseDataType.java index bf17c0713..38de08718 100644 --- a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseDataType.java +++ b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseDataType.java @@ -181,19 +181,25 @@ public static List match(String part) { } /** - * Checks if any alias uses the given prefix. + * Checks if any alias uses the given prefixes. * - * @param prefix prefix to check - * @return true if any alias using the given prefix; false otherwise + * @param prefixes prefixes to check + * @return true if any alias using the given prefixes; false otherwise */ - public static boolean mayStartWith(String prefix) { - if (prefix == null || prefix.isEmpty()) { + public static boolean mayStartWith(String... prefixes) { + if (prefixes == null || prefixes.length == 0) { return false; } - prefix = prefix.toUpperCase(); + StringBuilder builder = new StringBuilder(); + for (int i = 0, len = prefixes.length; i < len; i++) { + builder.append(prefixes[i].toUpperCase()).append(' '); + } + String prefix = builder.toString(); + builder.setLength(builder.length() - 1); + String typeName = builder.toString(); for (String alias : allAliases) { - if (alias.startsWith(prefix)) { + if (alias.startsWith(prefix) || alias.equals(typeName)) { return true; } } diff --git a/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseColumnTest.java b/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseColumnTest.java index 1e041d4ec..ecdea0727 100644 --- a/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseColumnTest.java +++ b/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseColumnTest.java @@ -17,6 +17,14 @@ private Object[][] getEnumTypes() { @DataProvider(name = "objectTypesProvider") private Object[][] getObjectTypes() { return new Object[][] { + { "Tuple(not NChar Large Object)" }, + { "nchar Large Object" }, + { "Tuple(int Int32)" }, + { "a Tuple(i Int32)" }, + { "b Tuple(i1 Int32)" }, + { "Tuple(i Int32)" }, + { "Tuple(i1 Int32)" }, + { "Tuple(i Int32, a Array(Int32), m Map(LowCardinality(String), Int32))" }, { "Int8" }, { "TINYINT SIGNED" }, { "k1 Int8" }, { "k1 TINYINT SIGNED" }, { "k1 Nullable(Int8)" }, { "k1 Nullable( Int8 )" }, { "k1 TINYINT SIGNED null" },