From cc1e9f04000a87256c2fb8a1dbc9049ff905882b Mon Sep 17 00:00:00 2001 From: inv-jishnu <31100916+inv-jishnu@users.noreply.github.com> Date: Fri, 17 Oct 2025 08:01:14 +0530 Subject: [PATCH] Fix `--no-header` option not working for CSV exports (#2924) --- .../core/dataexport/CsvExportManager.java | 8 ++- .../core/dataexport/CsvExportManagerTest.java | 69 +++++++++++++++++++ 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/data-loader/core/src/main/java/com/scalar/db/dataloader/core/dataexport/CsvExportManager.java b/data-loader/core/src/main/java/com/scalar/db/dataloader/core/dataexport/CsvExportManager.java index 64f059852e..bccf691adc 100644 --- a/data-loader/core/src/main/java/com/scalar/db/dataloader/core/dataexport/CsvExportManager.java +++ b/data-loader/core/src/main/java/com/scalar/db/dataloader/core/dataexport/CsvExportManager.java @@ -38,9 +38,11 @@ public CsvExportManager( @Override void processHeader(ExportOptions exportOptions, TableMetadata tableMetadata, Writer writer) throws IOException { - String header = createCsvHeaderRow(exportOptions, tableMetadata); - writer.append(header); - writer.flush(); + if (!exportOptions.isExcludeHeaderRow()) { + String header = createCsvHeaderRow(exportOptions, tableMetadata); + writer.append(header); + writer.flush(); + } } /** diff --git a/data-loader/core/src/test/java/com/scalar/db/dataloader/core/dataexport/CsvExportManagerTest.java b/data-loader/core/src/test/java/com/scalar/db/dataloader/core/dataexport/CsvExportManagerTest.java index ca65c10010..c61aa6f989 100644 --- a/data-loader/core/src/test/java/com/scalar/db/dataloader/core/dataexport/CsvExportManagerTest.java +++ b/data-loader/core/src/test/java/com/scalar/db/dataloader/core/dataexport/CsvExportManagerTest.java @@ -14,6 +14,7 @@ import com.scalar.db.io.Column; import com.scalar.db.io.IntColumn; import com.scalar.db.io.Key; +import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; @@ -129,4 +130,72 @@ void startExport_givenPartitionKey_shouldGenerateOutputFile() Assertions.assertTrue(file.exists()); Assertions.assertTrue(file.delete()); } + + @Test + void startExport_givenNoHeaderRequired_shouldGenerateOutputFileWithoutHeader() throws Exception { + String expectedFirstLine = + "9007199254740992,2147483647,true,0.000000000000000000000000000000000000000000001401298464324817,0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000049,test value,YmxvYiB0ZXN0IHZhbHVl,2000-01-01,01:01:01,2000-01-01T01:01,1970-01-21T03:20:41.740Z"; + + runExportAndAssertFirstLine(true, expectedFirstLine); + } + + @Test + void startExport_givenHeaderRequired_shouldGenerateOutputFileWithHeader() throws Exception { + String expectedFirstLine = "col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11"; + + runExportAndAssertFirstLine(false, expectedFirstLine); + } + + private void runExportAndAssertFirstLine(boolean excludeHeader, String expectedFirstLine) + throws Exception { + // Arrange + producerTaskFactory = new ProducerTaskFactory(",", false, false); + exportManager = new CsvExportManager(storage, dao, producerTaskFactory); + Scanner scanner = Mockito.mock(Scanner.class); + String filePath = Paths.get("").toAbsolutePath() + "/output.csv"; + Map> values = UnitTestUtils.createTestValues(); + Result result = new ResultImpl(values, mockData); + List results = Collections.singletonList(result); + + ExportOptions exportOptions = + ExportOptions.builder( + "namespace", + "table", + Key.newBuilder().add(IntColumn.of("col1", 1)).build(), + FileFormat.CSV) + .sortOrders(Collections.emptyList()) + .scanRange(new ScanRange(null, null, false, false)) + .delimiter(",") + .excludeHeaderRow(excludeHeader) + .build(); + + Mockito.when( + dao.createScanner( + exportOptions.getNamespace(), + exportOptions.getTableName(), + exportOptions.getScanPartitionKey(), + exportOptions.getScanRange(), + exportOptions.getSortOrders(), + exportOptions.getProjectionColumns(), + exportOptions.getLimit(), + storage)) + .thenReturn(scanner); + Mockito.when(scanner.iterator()).thenReturn(results.iterator()); + try (BufferedWriter writer = + Files.newBufferedWriter( + Paths.get(filePath), + Charset.defaultCharset(), + StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING)) { + exportManager.startExport(exportOptions, mockData, writer); + } + File file = new File(filePath); + Assertions.assertTrue(file.exists()); + try (BufferedReader br = Files.newBufferedReader(file.toPath(), Charset.defaultCharset())) { + String firstLine = br.readLine(); + Assertions.assertEquals(expectedFirstLine, firstLine); + } finally { + Assertions.assertTrue(file.delete()); + } + } }