-
Notifications
You must be signed in to change notification settings - Fork 145
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#442]: Support LowCardinality series datatype
- Loading branch information
Showing
3 changed files
with
166 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
...ve-jdbc/src/main/java/com/github/housepower/data/type/complex/DataTypeLowCardinality.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package com.github.housepower.data.type.complex; | ||
|
||
import com.github.housepower.data.DataTypeFactory; | ||
import com.github.housepower.data.IDataType; | ||
import com.github.housepower.misc.SQLLexer; | ||
import com.github.housepower.misc.Validate; | ||
import com.github.housepower.serde.BinaryDeserializer; | ||
import com.github.housepower.serde.BinarySerializer; | ||
|
||
import java.io.IOException; | ||
import java.sql.SQLException; | ||
|
||
public class DataTypeLowCardinality implements IDataType { | ||
|
||
public static DataTypeCreator creator = (lexer, serverContext) -> { | ||
Validate.isTrue(lexer.character() == '('); | ||
IDataType nestedType = DataTypeFactory.get(lexer, serverContext); | ||
Validate.isTrue(lexer.character() == ')'); | ||
return new DataTypeLowCardinality( | ||
"LowCardinality(" + nestedType.name() + ")", nestedType); | ||
}; | ||
|
||
private final String name; | ||
private final IDataType nestedDataType; | ||
|
||
public DataTypeLowCardinality(String name, IDataType nestedDataType) { | ||
this.name = name; | ||
this.nestedDataType = nestedDataType; | ||
} | ||
|
||
@Override | ||
public String name() { | ||
return this.name; | ||
} | ||
|
||
@Override | ||
public int sqlTypeId() { | ||
return this.nestedDataType.sqlTypeId(); | ||
} | ||
|
||
@Override | ||
public Object defaultValue() { | ||
return this.nestedDataType.defaultValue(); | ||
} | ||
|
||
@Override | ||
public Class javaType() { | ||
return this.nestedDataType.javaType(); | ||
} | ||
|
||
@Override | ||
public Class jdbcJavaType() { | ||
return this.nestedDataType.jdbcJavaType(); | ||
} | ||
|
||
@Override | ||
public boolean nullable() { | ||
return this.nestedDataType.nullable(); | ||
} | ||
|
||
@Override | ||
public int getPrecision() { | ||
return this.nestedDataType.getPrecision(); | ||
} | ||
|
||
@Override | ||
public int getScale() { | ||
return this.nestedDataType.getScale(); | ||
} | ||
|
||
@Override | ||
public Object deserializeText(SQLLexer lexer) throws SQLException { | ||
return this.nestedDataType.deserializeText(lexer); | ||
} | ||
|
||
@Override | ||
public void serializeBinary(Object data, BinarySerializer serializer) throws SQLException, IOException { | ||
this.nestedDataType.serializeBinary(data, serializer); | ||
} | ||
|
||
@Override | ||
public void serializeBinaryBulk(Object[] data, BinarySerializer serializer) throws SQLException, IOException { | ||
this.nestedDataType.serializeBinaryBulk(data, serializer); | ||
} | ||
|
||
@Override | ||
public Object deserializeBinary(BinaryDeserializer deserializer) throws SQLException, IOException { | ||
return this.nestedDataType.deserializeBinary(deserializer); | ||
} | ||
|
||
@Override | ||
public Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer) throws SQLException, IOException { | ||
Object[] data = this.nestedDataType.deserializeBinaryBulk(rows, deserializer); | ||
return data; | ||
} | ||
|
||
@Override | ||
public boolean isSigned() { | ||
return this.nestedDataType.isSigned(); | ||
} | ||
} |
61 changes: 61 additions & 0 deletions
61
clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/LowCardinalityTypeTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package com.github.housepower.jdbc; | ||
|
||
import com.github.housepower.misc.BytesHelper; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.sql.DatabaseMetaData; | ||
import java.sql.PreparedStatement; | ||
import java.sql.ResultSet; | ||
|
||
import static org.junit.jupiter.api.Assertions.*; | ||
|
||
//Refer to [[https://github.com/housepower/ClickHouse-Native-JDBC/issues/442]] for more details. | ||
public class LowCardinalityTypeTest extends AbstractITest implements BytesHelper { | ||
@Test | ||
public void testLowCardinalityType() throws Exception { | ||
withStatement(statement -> { | ||
statement.execute("DROP TABLE IF EXISTS low_cardinality_test"); | ||
statement.execute("CREATE TABLE IF NOT EXISTS low_cardinality_test " + | ||
"(value LowCardinality(String), nullable_value LowCardinality(Nullable(String))) Engine=Memory()"); | ||
|
||
String testValue = "value"; | ||
String sql = "INSERT INTO low_cardinality_test (value, nullable_value) values(?, ?);"; | ||
try (PreparedStatement pstmt = statement.getConnection().prepareStatement(sql)) { | ||
for (int i = 0; i < 300; i++) { | ||
pstmt.setString(1, testValue); | ||
pstmt.setString(2, null); | ||
pstmt.addBatch(); | ||
} | ||
pstmt.executeBatch(); | ||
} | ||
|
||
DatabaseMetaData metaData = statement.getConnection().getMetaData(); | ||
ResultSet columns = metaData.getColumns(null, "default", "low_cardinality_test", "%value%"); | ||
while (columns.next()) { | ||
String columnName = columns.getString("COLUMN_NAME"); | ||
String columnType = columns.getString("TYPE_NAME"); | ||
boolean nullable = columns.getInt("NULLABLE") == DatabaseMetaData.columnNullable; | ||
|
||
if (columnName.equals("value")) { | ||
assertEquals(columnType, "LowCardinality(String)"); | ||
assertFalse(nullable); | ||
} else { | ||
assertEquals(columnType, "LowCardinality(Nullable(String))"); | ||
assertTrue(nullable); | ||
} | ||
} | ||
|
||
ResultSet rs = statement.executeQuery("SELECT * FROM low_cardinality_test;"); | ||
int size = 0; | ||
while (rs.next()) { | ||
String value = rs.getString(1); | ||
String nullableValue = rs.getString(2); | ||
assertEquals(testValue, value); | ||
assertNull(nullableValue); | ||
size++; | ||
} | ||
assertEquals(300, size); | ||
statement.execute("DROP TABLE IF EXISTS decimal_test"); | ||
}); | ||
} | ||
} |