Skip to content

Commit db043aa

Browse files
Backport to branch(3) : Fix handling of "null" values for non-TEXT columns in CSV imports (#3197)
Co-authored-by: inv-jishnu <[email protected]>
1 parent 2af0c7d commit db043aa

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

data-loader/core/src/main/java/com/scalar/db/dataloader/core/util/ColumnUtils.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ public static Column<?> createColumnFromValue(
8383
DataType dataType, ColumnInfo columnInfo, @Nullable String value)
8484
throws ColumnParsingException {
8585
String columnName = columnInfo.getColumnName();
86+
if (value != null && !dataType.equals(DataType.TEXT) && value.equalsIgnoreCase("null")) {
87+
value = null;
88+
}
8689
try {
8790
switch (dataType) {
8891
case BOOLEAN:

data-loader/core/src/test/java/com/scalar/db/dataloader/core/util/ColumnUtilsTest.java

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,4 +228,85 @@ void getColumnsFromResult_withResultNull_withValidData_shouldReturnColumns()
228228
null, sourceRecord, false, mockMetadata, "namespace", "table");
229229
assertEquals(8, columns.size());
230230
}
231+
232+
/**
233+
* Tests that the string "null" (lowercase) is correctly treated as null for numeric, boolean, and
234+
* date/time types.
235+
*/
236+
@Test
237+
void createColumnFromValue_valueIsLowercaseNull_shouldReturnNullColumn()
238+
throws ColumnParsingException {
239+
String columnName = "testColumn";
240+
ColumnInfo columnInfo = ColumnInfo.builder().columnName(columnName).build();
241+
242+
// Integer type
243+
Column<?> intColumn = ColumnUtils.createColumnFromValue(DataType.INT, columnInfo, "null");
244+
assertEquals(IntColumn.ofNull(columnName), intColumn);
245+
intColumn = ColumnUtils.createColumnFromValue(DataType.INT, columnInfo, "Null");
246+
assertEquals(IntColumn.ofNull(columnName), intColumn);
247+
248+
// Double type
249+
Column<?> doubleColumn = ColumnUtils.createColumnFromValue(DataType.DOUBLE, columnInfo, "null");
250+
assertEquals(DoubleColumn.ofNull(columnName), doubleColumn);
251+
doubleColumn = ColumnUtils.createColumnFromValue(DataType.DOUBLE, columnInfo, "NULL");
252+
assertEquals(DoubleColumn.ofNull(columnName), doubleColumn);
253+
254+
// Boolean type
255+
Column<?> boolColumn = ColumnUtils.createColumnFromValue(DataType.BOOLEAN, columnInfo, "null");
256+
assertEquals(BooleanColumn.ofNull(columnName), boolColumn);
257+
258+
boolColumn = ColumnUtils.createColumnFromValue(DataType.BOOLEAN, columnInfo, "nuLL");
259+
assertEquals(BooleanColumn.ofNull(columnName), boolColumn);
260+
261+
// Date type
262+
Column<?> dateColumn = ColumnUtils.createColumnFromValue(DataType.DATE, columnInfo, "null");
263+
assertEquals(DateColumn.ofNull(columnName), dateColumn);
264+
dateColumn = ColumnUtils.createColumnFromValue(DataType.DATE, columnInfo, "NULL");
265+
assertEquals(DateColumn.ofNull(columnName), dateColumn);
266+
267+
// Time type
268+
Column<?> timeColumn = ColumnUtils.createColumnFromValue(DataType.TIME, columnInfo, "null");
269+
assertEquals(TimeColumn.ofNull(columnName), timeColumn);
270+
271+
timeColumn = ColumnUtils.createColumnFromValue(DataType.TIME, columnInfo, "nuLL");
272+
assertEquals(TimeColumn.ofNull(columnName), timeColumn);
273+
274+
// Timestamp type
275+
Column<?> timestampColumn =
276+
ColumnUtils.createColumnFromValue(DataType.TIMESTAMP, columnInfo, "null");
277+
assertEquals(TimestampColumn.ofNull(columnName), timestampColumn);
278+
timestampColumn = ColumnUtils.createColumnFromValue(DataType.TIMESTAMP, columnInfo, "NULL");
279+
assertEquals(TimestampColumn.ofNull(columnName), timestampColumn);
280+
281+
// Timestamp type
282+
Column<?> timestamprtzColumn =
283+
ColumnUtils.createColumnFromValue(DataType.TIMESTAMPTZ, columnInfo, "null");
284+
assertEquals(TimestampTZColumn.ofNull(columnName), timestamprtzColumn);
285+
timestamprtzColumn =
286+
ColumnUtils.createColumnFromValue(DataType.TIMESTAMPTZ, columnInfo, "Null");
287+
assertEquals(TimestampTZColumn.ofNull(columnName), timestamprtzColumn);
288+
}
289+
290+
/**
291+
* Tests that when the string value "null" is provided for TEXT columns, it is treated as a
292+
* literal string and not converted to null.
293+
*/
294+
@Test
295+
void createColumnFromValue_valueIsNullString_shouldRemainLiteralForTextType()
296+
throws ColumnParsingException {
297+
String columnName = "textColumn";
298+
ColumnInfo columnInfo = ColumnInfo.builder().columnName(columnName).build();
299+
300+
Column<?> textCol = ColumnUtils.createColumnFromValue(DataType.TEXT, columnInfo, "null");
301+
assertEquals(TextColumn.of(columnName, "null"), textCol);
302+
303+
textCol = ColumnUtils.createColumnFromValue(DataType.TEXT, columnInfo, "NULL");
304+
assertEquals(TextColumn.of(columnName, "NULL"), textCol);
305+
306+
textCol = ColumnUtils.createColumnFromValue(DataType.TEXT, columnInfo, "Null");
307+
assertEquals(TextColumn.of(columnName, "Null"), textCol);
308+
309+
textCol = ColumnUtils.createColumnFromValue(DataType.TEXT, columnInfo, "nuLL");
310+
assertEquals(TextColumn.of(columnName, "nuLL"), textCol);
311+
}
231312
}

0 commit comments

Comments
 (0)