clickhouse-java
clickhouse-java copied to clipboard
Cannot set null to non-nullable column but column set default value in DDL
version v.0.3.2-patch11
DDL
create tabel test(
test_int Int64 default 10,
test_string String default 'n'
)
// com.clickhouse.jdbc.internal.InputBasedPreparedStatement
@Override
public void addBatch() throws SQLException {
ensureOpen();
ClickHouseConfig config = getConfig();
int nullAsDefault = getNullAsDefault();
for (int i = 0, len = values.length; i < len; i++) {
if (!flags[i]) {
throw SqlExceptionUtils
.clientError(ClickHouseUtils.format("Missing value for parameter #%d [%s]", i + 1, columns[i]));
}
ClickHouseColumn col = columns[i];
ClickHouseValue val = values[i];
if (!col.isNestedType() && !col.isNullable() && (val == null || val.isNullOrEmpty())) {
if (nullAsDefault > 1 && val != null) {
val.resetToDefault();
} else if (nullAsDefault < 1) {
throw SqlExceptionUtils.clientError(ClickHouseUtils.format(
"Cannot set null to non-nullable column #%d [%s]", i + 1, col));
}
}
try {
serializer.serialize(val, config, col, stream);
} catch (IOException e) {
// should not happen
throw SqlExceptionUtils.handle(e);
}
}
counter++;
clearParameters();
}
when do batch insert if insert null into test_int,test_string and not set nullAsDefault then will throw
java.sql.SQLException: Cannot set null to non-nullable column #1 [test_int Int64]
at com.clickhouse.jdbc.SqlExceptionUtils.clientError(SqlExceptionUtils.java:73) ~[clickhouse-jdbc-0.3.2-patch11.jar:clickhouse-jdbc 0.3.2-patch11 (revision: 27f8951)]
because code in com.clickhouse.client.data.ClickHouseRowBinaryProcessor
public void serialize(ClickHouseValue value, ClickHouseConfig config, ClickHouseColumn column, ClickHouseOutputStream output) throws IOException {
if (column.isNullable()) { //column is not nullable,but column has default value
if (value.isNullOrEmpty()) {
BinaryStreamUtils.writeNull(output);
return;
}
BinaryStreamUtils.writeNonNull(output);
}
ClickHouseSerializer<ClickHouseValue> func = (ClickHouseSerializer)this.serializers.get(column.getDataType());
if (func == null) {
throw new IllegalArgumentException("Unsupported data type: " + column.getDataType().name());
} else {
func.serialize(value, config, column, output); //then code in here will throw NullpointExection
}
}
in this case, column can be null and jdbc should get default, When column is null InputBasedPreparedStatement will set default value or allow column be null
Thanks @ShortFinger for the report. This is a known issue due to limitation of RowBinary data format - see comments at here.