Skip to content

fix(flexible-csv): Skip the CSV header once per file instead of once per split - #417

Merged
ferenc-csaky merged 1 commit into
mainfrom
fix/flexible-csv-split-header
Oct 16, 2026
Merged

ferenc-csaky merged 1 commit into
mainfrom
fix/flexible-csv-split-header

Conversation

@ferenc-csaky

@ferenc-csaky ferenc-csaky commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

What does this change?

The filesystem connector now skips a flexible-csv file's header once per file, instead of once per split. Before, a file read in several splits lost the first data row of every later split. Follow-up to DataSQRL/sqrl#2476.

  • New FlexibleCsvFileFormat: a BulkReaderFormatFactory with the flexible-csv identifier. The filesystem connector prefers it over FlexibleCsv, and Kafka keeps using FlexibleCsv unchanged.
  • New FlexibleCsvBulkFormat: reads each split through a DeserializationSchemaAdapter, as before, so parsing and options are unchanged. Only the split at offset 0 skips the header, and restored splits stay consistent.
  • README.md: documents the skip-header default, that it applies per file, the Kafka caveat, and the flexible-csv. option prefix.

Only files read in several splits were affected: uncompressed files on a filesystem that reports several blocks, such as HDFS. Local files, compressed files and S3 objects are always read in one split. skip-header still defaults to true, so Kafka still drops the first record of each reader. Changing that is a separate decision.

Area

  • Runner CLI and Docker image (flink-sql-runner)
  • Connectors (connectors)
  • Formats (formats)
  • Function libraries (stdlib)
  • Environment utilities (env-utils)
  • Tests and samples (testing)
  • Build / CI / dependencies
  • Docs (README.md, stdlib-docs)

How did you test it?

  • FlexibleCsvFileFormatTest covers factory lookup, a file read in two splits at every split point, skip-header = false, and restoring the first and a later split. 20 of its 28 tests fail with the old behavior.
  • FlexibleCsvFileFormatIT runs SQL on a MiniCluster: plain and gzipped files with headers, a single-column query, and ignore-parse-errors.
  • mvn verify on the module, mvn test on flink-sql-runner, and mvn spotless:check all pass.

Checklist

  • The PR title starts with a type such as feat:, fix: or docs:, optionally with a scope (e.g. fix(flexible-json):)
  • mvn clean install passes locally and the code is formatted with mvn spotless:apply (formatted; ran only the builds above, with -Dlicense.skip=true because the license plugin can't read a git worktree)
  • New or changed behavior is covered by tests (given_when_then naming, AssertJ assertions)
  • New dependency and plugin versions are defined as properties in the root pom.xml
  • Commits are signed off and signed (git commit -s -S)
  • README.md and stdlib-docs are updated if user-facing behavior or functions changed

🤖 Generated with Claude Code

…per split

The filesystem connector decoded flexible-csv files with a line
deserializer that drops the first record it sees, cloned for every file
split. A file read in several splits therefore lost the first data row
of every split after the first. A new BulkReaderFormatFactory reads each
split the same way, but skips the header only in the split that starts
at offset 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Ferenc Csaky <ferenc@datasqrl.com>
@ferenc-csaky
ferenc-csaky merged commit 75ad937 into main Oct 16, 2026
13 checks passed
@ferenc-csaky
ferenc-csaky deleted the fix/flexible-csv-split-header branch October 16, 2026 15:40
ferenc-csaky added a commit that referenced this pull request Oct 21, 2026
…per split (#417)

Signed-off-by: Ferenc Csaky <ferenc@datasqrl.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants