Joorgem opened a new pull request, #57671:
URL: https://github.com/apache/spark/pull/57671

   ### What changes were proposed in this pull request?
   
   Adds a test to `CSVSuite` pinning what the CSV reader does with a line break 
inside a
   quoted value when `multiLine` is left at its default of `false`: the record 
is cut at
   the break into a NULL-tailed head plus a fragment, and the row count rises 
by one.
   
   The test also pins the three consequences that follow from it — the 
`multiLine=true`
   contrast, `DROPMALFORMED` discarding both halves, and the raw text captured 
when
   `columnNameOfCorruptRecord` is declared.
   
   ### Why are the changes needed?
   
   The behaviour is not covered today. `CSVSuite` contains exactly one input 
literal with
   a newline inside quotes, in the `lineSep with 2 chars when multiLine set to 
...` test,
   and it is confined to the `multiLine = true` branch:
   
   ```scala
   val inputData = if (multiLine) {
     s"""name,"i am the${newLine} column1"${newLine}jack,30${newLine}tom,18"""
   } else {
     s"name,age${newLine}jack,30${newLine}tom,18"
   }
   ```
   
   The `multiLine = false` branch deliberately drops the quoted break, so the 
default
   path is never exercised with the input that distinguishes it. 
`UnivocityParserSuite`
   does not cover it either.
   
   That leaves an untested behaviour that users do meet: a line break inside a 
quoted
   value is valid CSV (RFC 4180 §2.6) and appears in published datasets, so 
reading such
   a file with default options is an ordinary thing to do. The split is a 
consequence of
   the non-multiLine read path being line-oriented by design — 
`HadoopFileLinesReader`
   splits the input on the line separator before the tokenizer sees it, and
   `UnivocityParser.parseLine` then receives one physical line at a time — 
which is what
   makes the file splittable. This PR does not propose changing that; it pins 
what the
   current design produces, so a future change to that path cannot alter it 
silently.
   
   `DROPMALFORMED` losing the whole source record rather than the damaged half 
is the
   part most worth having locked down, since it is the opposite of what the 
mode's name
   suggests for one bad line.
   
   ### Does this PR introduce _any_ user-facing change?
   
   No. Test-only.
   
   ### How was this patch tested?
   
   This PR *is* the test. It was run in CI against this base before the PR was 
opened:
   `Build modules: sql - slow tests`, `sql - extended tests` and `sql - other 
tests` all
   passed, so the test holds in `CSVv1Suite`, `CSVv2Suite` and 
`CSVLegacyTimeParserSuite`
   alike.
   
   The expected rows were derived before the Scala was written, from `pyspark` 
3.5.9 with
   the same three-record input and the same explicit three-column schema. 3.5.9 
is two
   majors behind this base, so those values were treated as a hypothesis to be 
confirmed
   by that CI run rather than as evidence in themselves:
   
   | read | rows |
   |---|---|
   | default (`multiLine=false`) | 4 — `("1","ACME LTDA","SP")`, `("2","EMPRESA 
COM",null)`, `("QUEBRA DE LINHA\"","RJ",null)`, `("3","OUTRA EMPRESA","MG")` |
   | `multiLine=true` | 3, with the break preserved inside the value |
   | `mode=DROPMALFORMED` | 2 — records 1 and 3; record 2 lost entirely |
   | `columnNameOfCorruptRecord` declared | 4, both halves carrying raw text 
`2,"EMPRESA COM` and `QUEBRA DE LINHA",RJ` |
   
   Reproduction script: `docs/evidence/c5_expected_rows.py` in the authoring 
repo (not
   part of this patch).
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   Generated-by: Claude Code (Opus 5)
   
   ### Related
   
   This is the third of three separate concerns in the same area, filed in 
order:
   
   1. [#57608](https://github.com/apache/spark/pull/57608) — documents what 
`multiLine=false`
      does to a line break inside a quoted value (open, reviewed, revision 
applied).
   2. [#57658](https://github.com/apache/spark/pull/57658) — corrects the 
`PERMISSIVE`
      "drops corrupt records" sentence in the CSV and JSON docs.
   3. This PR — pins the behaviour #57608 documents, so it cannot change 
silently.
   
   Flagging the overlap explicitly since all three touch CSV: this one adds a 
test and
   changes no docs and no `main` code.
   


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to