clickhouse-java icon indicating copy to clipboard operation
clickhouse-java copied to clipboard

Cannot set null to non-nullable column but column set default value in DDL

Open ShortFinger opened this issue 3 years ago • 1 comments

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

ShortFinger avatar Sep 01 '22 09:09 ShortFinger

Thanks @ShortFinger for the report. This is a known issue due to limitation of RowBinary data format - see comments at here.

zhicwu avatar Sep 01 '22 10:09 zhicwu