Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public final class ClickHouseColumn implements Serializable {
private static ClickHouseColumn update(ClickHouseColumn column) {
column.enumConstants = ClickHouseEnum.EMPTY;
int size = column.parameters.size();
column.precision = column.dataType.getMaxPrecision();
switch (column.dataType) {
case Array:
column.arrayLevel = 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ public enum ClickHouseDataType {
UInt32(Long.class, false, true, false, 4, 10, 0, 0, 0, "INT UNSIGNED", "INTEGER UNSIGNED", "MEDIUMINT UNSIGNED"),
UInt64(Long.class, false, true, false, 8, 20, 0, 0, 0, "BIGINT UNSIGNED"),
UInt128(BigInteger.class, false, true, false, 16, 39, 0, 0, 0),
UInt256(BigInteger.class, false, true, false, 32, 78, 0, 0, 0), Int8(Byte.class, false, true, true, 1, 3, 0, 0, 0,
"BYTE", "INT1", "INT1 SIGNED", "TINYINT", "TINYINT SIGNED"),
UInt256(BigInteger.class, false, true, false, 32, 78, 0, 0, 0),
Int8(Byte.class, false, true, true, 1, 3, 0, 0, 0, "BYTE", "INT1", "INT1 SIGNED", "TINYINT", "TINYINT SIGNED"),
Int16(Short.class, false, true, true, 2, 5, 0, 0, 0, "SMALLINT", "SMALLINT SIGNED"),
Int32(Integer.class, false, true, true, 4, 10, 0, 0, 0, "INT", "INTEGER", "MEDIUMINT", "INT SIGNED",
"INTEGER SIGNED", "MEDIUMINT SIGNED"),
Int64(Long.class, false, true, true, 8, 19, 0, 0, 0, "BIGINT", "BIGINT SIGNED"),
Int128(BigInteger.class, false, true, true, 16, 39, 0, 0, 0),
Int256(BigInteger.class, false, true, true, 32, 77, 0, 0, 0),
Bool(Boolean.class, false, false, true, 1, 3, 0, 0, 0, "BOOLEAN"),
Bool(Boolean.class, false, false, true, 1, 1, 0, 0, 0, "BOOLEAN"),
Date(LocalDate.class, false, false, false, 2, 10, 0, 0, 0),
Date32(LocalDate.class, false, false, false, 4, 10, 0, 0, 0),
DateTime(LocalDateTime.class, true, false, false, 0, 29, 0, 0, 9, "TIMESTAMP"),
Expand All @@ -63,12 +63,15 @@ public enum ClickHouseDataType {
Decimal64(BigDecimal.class, true, false, true, 8, 18, 18, 0, 18),
Decimal128(BigDecimal.class, true, false, true, 16, 38, 38, 0, 38),
Decimal256(BigDecimal.class, true, false, true, 32, 76, 20, 0, 76),
UUID(UUID.class, false, true, false, 16, 69, 0, 0, 0), Enum(String.class, true, true, false, 1, 0, 0, 0, 0),
Enum8(String.class, true, true, false, 1, 0, 0, 0, 0), Enum16(String.class, true, true, false, 2, 0, 0, 0, 0),
UUID(UUID.class, false, true, false, 16, 69, 0, 0, 0),
@Deprecated
Enum(String.class, true, true, false, 1, 0, 0, 0, 0),
Enum8(String.class, true, true, false, 1, 0, 0, 0, 0), // "ENUM"),
Enum16(String.class, true, true, false, 2, 0, 0, 0, 0),
Float32(Float.class, false, true, true, 4, 12, 0, 0, 38, "FLOAT", "REAL", "SINGLE"),
Float64(Double.class, false, true, true, 16, 22, 0, 0, 308, "DOUBLE", "DOUBLE PRECISION"),
IPv4(Inet4Address.class, false, true, false, 4, 0, 0, 0, 0, "INET4"),
IPv6(Inet6Address.class, false, true, false, 16, 0, 0, 0, 0, "INET6"),
IPv4(Inet4Address.class, false, true, false, 4, 10, 0, 0, 0, "INET4"),
IPv6(Inet6Address.class, false, true, false, 16, 39, 0, 0, 0, "INET6"),
FixedString(String.class, true, true, false, 0, 0, 0, 0, 0, "BINARY"),
String(String.class, false, true, false, 0, 0, 0, 0, 0, "BINARY LARGE OBJECT", "BINARY VARYING", "BLOB", "BYTEA",
"CHAR", "CHAR LARGE OBJECT", "CHAR VARYING", "CHARACTER", "CHARACTER LARGE OBJECT", "CHARACTER VARYING",
Expand All @@ -77,8 +80,10 @@ public enum ClickHouseDataType {
"NCHAR LARGE OBJECT", "NCHAR VARYING", "NVARCHAR", "TEXT", "TINYBLOB", "TINYTEXT", "VARCHAR", "VARCHAR2"),
AggregateFunction(String.class, true, true, false, 0, 0, 0, 0, 0), // implementation-defined intermediate state
SimpleAggregateFunction(String.class, true, true, false, 0, 0, 0, 0, 0),
Array(Object.class, true, true, false, 0, 0, 0, 0, 0), Map(Map.class, true, true, false, 0, 0, 0, 0, 0),
Nested(Object.class, true, true, false, 0, 0, 0, 0, 0), Tuple(List.class, true, true, false, 0, 0, 0, 0, 0),
Array(Object.class, true, true, false, 0, 0, 0, 0, 0),
Map(Map.class, true, true, false, 0, 0, 0, 0, 0),
Nested(Object.class, true, true, false, 0, 0, 0, 0, 0),
Tuple(List.class, true, true, false, 0, 0, 0, 0, 0),
Point(Object.class, false, true, true, 33, 0, 0, 0, 0), // same as Tuple(Float64, Float64)
Polygon(Object.class, false, true, true, 0, 0, 0, 0, 0), // same as Array(Ring)
MultiPolygon(Object.class, false, true, true, 0, 0, 0, 0, 0), // same as Array(Polygon)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.clickhouse.client.ClickHouseResponse;
import com.clickhouse.client.ClickHouseResponseSummary;
import com.clickhouse.client.ClickHouseUtils;
import com.clickhouse.client.ClickHouseVersion;
import com.clickhouse.client.config.ClickHouseClientOption;
import com.clickhouse.client.data.ClickHouseExternalTable;
import com.clickhouse.client.data.ClickHouseStringValue;
Expand Down Expand Up @@ -143,6 +144,12 @@ public void testLogComment() throws Exception {
String uuid = UUID.randomUUID().toString();
try (ClickHouseClient client = ClickHouseClient.newInstance()) {
ClickHouseRequest<?> request = client.connect(server).format(ClickHouseFormat.RowBinaryWithNamesAndTypes);
try (ClickHouseResponse resp = request
.query("select version()").execute().get()) {
if (!ClickHouseVersion.of(resp.firstRecord().getValue(0).asString()).check("[21.2,)")) {
return;
}
}
try (ClickHouseResponse resp = request
.option(ClickHouseClientOption.LOG_LEADING_COMMENT, true)
.query("-- select something\r\nselect 1", uuid).execute().get()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -814,9 +814,9 @@ public ResultSet getColumns(String catalog, String schemaPattern, String tableNa
String sql = ClickHouseParameterizedQuery
.apply("select null as TABLE_CAT, database as TABLE_SCHEM, table as TABLE_NAME, "
+ "name as COLUMN_NAME, toInt32(:defaultType) as DATA_TYPE, type as TYPE_NAME, toInt32(0) as COLUMN_SIZE, "
+ "0 as BUFFER_LENGTH, toInt32(null) as DECIMAL_DIGITS, 10 as NUM_PREC_RADIX, "
+ "0 as BUFFER_LENGTH, cast(null as Nullable(Int32)) as DECIMAL_DIGITS, 10 as NUM_PREC_RADIX, "
+ "toInt32(position(type, 'Nullable(') >= 1 ? :defaultNullable : :defaultNonNull) as NULLABLE, :comment as REMARKS, default_expression as COLUMN_DEF, "
+ "0 as SQL_DATA_TYPE, 0 as SQL_DATETIME_SUB, toInt32(null) as CHAR_OCTET_LENGTH, position as ORDINAL_POSITION, "
+ "0 as SQL_DATA_TYPE, 0 as SQL_DATETIME_SUB, cast(null as Nullable(Int32)) as CHAR_OCTET_LENGTH, position as ORDINAL_POSITION, "
+ "position(type, 'Nullable(') >= 1 ? 'YES' : 'NO' as IS_NULLABLE, null as SCOPE_CATALOG, null as SCOPE_SCHEMA, null as SCOPE_TABLE, "
+ "null as SOURCE_DATA_TYPE, 'NO' as IS_AUTOINCREMENT, 'NO' as IS_GENERATEDCOLUMN from system.columns\n"
+ "where database like :database and table like :table and name like :column", params);
Expand All @@ -825,7 +825,8 @@ public ResultSet getColumns(String catalog, String schemaPattern, String tableNa
try {
ClickHouseColumn column = ClickHouseColumn.of("", typeName);
r.getValue("DATA_TYPE").update(JdbcTypeMapping.toJdbcType(typeMaps, column));
r.getValue("COLUMN_SIZE").update(column.getDataType().getByteLength());
r.getValue("COLUMN_SIZE").update(
column.getPrecision() > 0 ? column.getPrecision() : column.getDataType().getByteLength());
if (column.isNullable()) {
r.getValue("NULLABLE").update(DatabaseMetaData.typeNullable);
r.getValue("IS_NULLABLE").update("YES");
Expand All @@ -838,7 +839,16 @@ public ResultSet getColumns(String catalog, String schemaPattern, String tableNa
r.getValue("CHAR_OCTET_LENGTH").update(column.getPrecision());
}

if (column.getScale() > 0) {
if (column.getScale() > 0
|| column.getDataType() == ClickHouseDataType.Float32
|| column.getDataType() == ClickHouseDataType.Float64
|| column.getDataType() == ClickHouseDataType.Decimal
|| column.getDataType() == ClickHouseDataType.Decimal32
|| column.getDataType() == ClickHouseDataType.Decimal64
|| column.getDataType() == ClickHouseDataType.Decimal128
|| column.getDataType() == ClickHouseDataType.Decimal256
|| column.getDataType() == ClickHouseDataType.DateTime
|| column.getDataType() == ClickHouseDataType.DateTime64) {
r.getValue("DECIMAL_DIGITS").update(column.getScale());
} else {
r.getValue("DECIMAL_DIGITS").resetToNullOrEmpty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ public void setBytes(int parameterIndex, byte[] x) throws SQLException {
ensureOpen();

int idx = toArrayIndex(parameterIndex);
values[idx].update(new String(x, StandardCharsets.UTF_8));
values[idx].update(ClickHouseValues.convertToQuotedString(new String(x, StandardCharsets.UTF_8)));
flags[idx] = true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ public void setBytes(int parameterIndex, byte[] x) throws SQLException {
value.update(x);
values[idx] = value.toSqlExpression();
} else {
values[idx] = new String(x, StandardCharsets.UTF_8);
values[idx] = ClickHouseValues.convertToQuotedString(new String(x, StandardCharsets.UTF_8));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,29 @@
import java.util.Locale;
import java.util.Properties;

import com.clickhouse.client.ClickHouseColumn;

import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class ClickHouseDatabaseMetaDataTest extends JdbcIntegrationTest {
@DataProvider(name = "selectedColumns")
private Object[][] getSelectedColumns() {
return new Object[][] {
// COLUMN_SIZE, DECIMAL_DIGITS, CHAR_OCTET_LENGTH
// new Object[] { "Bool", 1, null, null }, // Bool was an alias before 21.12
new Object[] { "Int8", 3, null, null },
new Object[] { "UInt8", 3, null, null },
new Object[] { "FixedString(3)", 3, null, 3 },
new Object[] { "String", 0, null, null },
new Object[] { "Decimal64(10)", 18, 10, null },
new Object[] { "Decimal(10,2)", 10, 2, null },
new Object[] { "Decimal(10,0)", 10, 0, null },
new Object[] { "Float32", 12, 0, null },
new Object[] { "Float64", 22, 0, null } };
}

@Test(groups = "integration")
public void testGetTypeInfo() throws SQLException {
Properties props = new Properties();
Expand All @@ -21,6 +40,26 @@ public void testGetTypeInfo() throws SQLException {
}
}

@Test(dataProvider = "selectedColumns", groups = "integration")
public void testGetColumns(String columnType, Integer columnSize, Integer decimalDigits, Integer octectLength)
throws SQLException {
ClickHouseColumn c = ClickHouseColumn.of("x", columnType);
String tableName = "test_get_column_" + c.getDataType().name().toLowerCase();
try (ClickHouseConnection conn = newConnection(new Properties());
Statement s = conn.createStatement()) {
s.execute("drop table if exists " + tableName + "; "
+ "create table " + tableName + "(x " + columnType + ") engine=Memory");
try (ResultSet rs = conn.getMetaData().getColumns(conn.getCatalog(), conn.getSchema(), tableName, "%")) {
Assert.assertTrue(rs.next(), "Should have one record");
Assert.assertEquals(rs.getString("COLUMN_NAME"), "x");
Assert.assertEquals(rs.getObject("COLUMN_SIZE"), columnSize);
Assert.assertEquals(rs.getObject("DECIMAL_DIGITS"), decimalDigits);
Assert.assertEquals(rs.getObject("CHAR_OCTET_LENGTH"), octectLength);
Assert.assertFalse(rs.next(), "Should have only one record");
}
}
}

@Test(groups = "integration")
public void testTableComment() throws SQLException {
String tableName = "test_table_comment";
Expand All @@ -35,7 +74,7 @@ public void testTableComment() throws SQLException {
s.execute(String.format(Locale.ROOT,
"drop table if exists %1$s; create table %1$s(s String) engine=Memory comment '%2$s'",
tableName, tableComment));
try (ResultSet rs = conn.getMetaData().getTables(null, "%", tableName, null)) {
try (ResultSet rs = conn.getMetaData().getTables(conn.getCatalog(), conn.getSchema(), tableName, null)) {
Assert.assertTrue(rs.next());
Assert.assertEquals(rs.getString("remarks"), tableComment);
Assert.assertFalse(rs.next());
Expand Down