npawar commented on a change in pull request #7237: URL: https://github.com/apache/pinot/pull/7237#discussion_r690810134
########## File path: pinot-plugins/pinot-input-format/pinot-csv/src/main/java/org/apache/pinot/plugin/inputformat/csv/CSVRecordReader.java ########## @@ -103,6 +105,23 @@ public void init(File dataFile, @Nullable Set<String> fieldsToRead, @Nullable Re _recordExtractor.init(fieldsToRead, recordExtractorConfig); } + private void validateHeaderForDelimiter(char delimiter, String csvHeader, CSVFormat format) + throws IOException { + CSVParser parser = format.parse(RecordReaderUtils.getBufferedReader(_dataFile)); Review comment: we're creating a parser again in `init()` line 125. Can we avoid the duplication? Maybe move the init call to the top since it needs only the dataFile anyway? ########## File path: pinot-plugins/pinot-input-format/pinot-csv/src/test/java/org/apache/pinot/plugin/inputformat/csv/CSVRecordReaderTest.java ########## @@ -103,4 +105,74 @@ protected void checkValue(RecordReader recordReader, List<Map<String, Object>> e } Assert.assertFalse(recordReader.hasNext()); } + + @Test + public void testInvalidDelimiterInHeader() { + //setup + CSVRecordReaderConfig csvRecordReaderConfig = new CSVRecordReaderConfig(); + csvRecordReaderConfig.setMultiValueDelimiter(CSV_MULTI_VALUE_DELIMITER); + csvRecordReaderConfig.setHeader("col1;col2;col3;col4;col5;col6;col7;col8;col9;col10"); + csvRecordReaderConfig.setDelimiter(','); + CSVRecordReader csvRecordReader = new CSVRecordReader(); + + //execute and assert + Assert.assertThrows(IllegalArgumentException.class, + () -> csvRecordReader.init(_dataFile, null, csvRecordReaderConfig)); + } + + @Test + public void testValidDelimiterInHeader() + throws IOException { + //setup + CSVRecordReaderConfig csvRecordReaderConfig = new CSVRecordReaderConfig(); + csvRecordReaderConfig.setMultiValueDelimiter(CSV_MULTI_VALUE_DELIMITER); + csvRecordReaderConfig.setHeader("col1,col2,col3,col4,col5,col6,col7,col8,col9,col10"); + csvRecordReaderConfig.setDelimiter(','); + CSVRecordReader csvRecordReader = new CSVRecordReader(); + + //read all fields + //execute and assert + csvRecordReader.init(_dataFile, null, csvRecordReaderConfig); + Assert.assertTrue(csvRecordReader.hasNext()); + } + + /** + * When CSV records contain a single value, then no exception should be throw while initialising. + * This test requires a different setup from the rest of the tests as it requires a single-column + * CSV. Therefore, we re-write already generated records into a new file, but only the first + * column. + * + * @throws IOException + */ + @Test + public void testHeaderDelimiterSingleColumn() + throws IOException { + //setup + + //create a single value CSV + Schema pinotSchema = getPinotSchema(); + //write only the first column in the schema + String column = pinotSchema.getColumnNames().toArray(new String[0])[0]; + //use a different file name so that other tests aren't affected + File file = new File(_tempDir, "data1.csv"); + try (FileWriter fileWriter = new FileWriter(file); + CSVPrinter csvPrinter = new CSVPrinter(fileWriter, CSVFormat.DEFAULT.withHeader(column))) { + for (Map<String, Object> r : _records) { + Object[] record = new Object[1]; + for (int i = 0; i < 1; i++) { Review comment: remove loop ########## File path: pinot-plugins/pinot-input-format/pinot-csv/src/main/java/org/apache/pinot/plugin/inputformat/csv/CSVRecordReader.java ########## @@ -103,6 +105,23 @@ public void init(File dataFile, @Nullable Set<String> fieldsToRead, @Nullable Re _recordExtractor.init(fieldsToRead, recordExtractorConfig); } + private void validateHeaderForDelimiter(char delimiter, String csvHeader, CSVFormat format) + throws IOException { + CSVParser parser = format.parse(RecordReaderUtils.getBufferedReader(_dataFile)); + CSVRecord firstRecord = parser.getRecords().get(0); + if (recordHasMultipleValues(firstRecord) && delimiterNotPresentInHeader(delimiter, csvHeader)) { Review comment: lets stick to using `parser.Iterator()` (preferrably the one already created in the `init`). `getRecords` is internally creating an arraylist with all the records from the file. firstRecord = iterator.hasNext() ? iterator.next() : null; ########## File path: pinot-plugins/pinot-input-format/pinot-csv/src/main/java/org/apache/pinot/plugin/inputformat/csv/CSVRecordReader.java ########## @@ -103,6 +105,23 @@ public void init(File dataFile, @Nullable Set<String> fieldsToRead, @Nullable Re _recordExtractor.init(fieldsToRead, recordExtractorConfig); } + private void validateHeaderForDelimiter(char delimiter, String csvHeader, CSVFormat format) + throws IOException { + CSVParser parser = format.parse(RecordReaderUtils.getBufferedReader(_dataFile)); + CSVRecord firstRecord = parser.getRecords().get(0); + if (recordHasMultipleValues(firstRecord) && delimiterNotPresentInHeader(delimiter, csvHeader)) { Review comment: using the iterator will also protect us from case where file has no records -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For additional commands, e-mail: commits-h...@pinot.apache.org