Skip to content

HIVE-29805: Write header/footer lines in HiveIgnoreKeyTextOutputForma… - #6684

Open
dengziming wants to merge 1 commit into
apache:masterfrom
dengziming:HIVE-29805
Open

HIVE-29805: Write header/footer lines in HiveIgnoreKeyTextOutputForma…#6684
dengziming wants to merge 1 commit into
apache:masterfrom
dengziming:HIVE-29805

Conversation

@dengziming

@dengziming dengziming commented Aug 7, 2026

Copy link
Copy Markdown
Member

<!--
Thanks for sending a pull request! Here are some tips for you:

  1. If this is your first time, please read our contributor guidelines: https://cwiki.apache.org/confluence/display/Hive/HowToContribute
  2. Ensure that you have created an issue on the Hive project JIRA: https://issues.apache.org/jira/projects/HIVE/summary
  3. Ensure you have added or run the appropriate tests for your PR:
  4. If the PR is unfinished, add '[WIP]' in your PR title, e.g., '[WIP]HIVE-XXXXX: Your PR title ...'.
  5. Be sure to keep the PR description updated to reflect all changes.
  6. Please write your PR title to summarize what this PR proposes.
  7. If possible, provide a concise example to reproduce the issue for a faster review.

-->

What changes were proposed in this pull request?

For a text table with skip.header.line.count=N (and/or skip.footer.line.count=M), INSERT / INSERT OVERWRITE writes data files that do not contain N header lines or M footer lines. On read, SkippingTextInputFormat skips the first N lines of each file and the last M lines of each file. When new files are appended, the first N data lines of each appended file are skipped as if they were headers, causing data loss.

Reproduce with:


CREATE TABLE t (a string, b string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS TEXTFILE
TBLPROPERTIES ('skip.header.line.count'='1');

INSERT into TABLE t VALUES ('x','y'),('a','b'),('c','d'); 

SELECT * FROM t; -- returned only ('a','b'), ('c','d') before the fix

This mirrors how Spark native CSV handles header=true: the writer emits a header line before the data rows (see Spark's CsvOutputWriter). Hive already has the reader-side skip (SkippingTextInputFormat, RecordReaderWrapper); this change adds the writer-side header/footer emission to HiveIgnoreKeyTextOutputFormat.

Spark writer reference:
https://github.com/apache/spark/blob/751f29f12933ef3626518e8ed7a13a225c37d326/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/csv/CsvOutputWriter.scala#L42-L44

Why are the changes needed?

This is a bug that would lead to data loss

Does this PR introduce any user-facing change?

Yes, fix

How was this patch tested?

Update the skip_header_footer_proj.q golden output to reflect that all inserted rows are now returned, and add TestHiveIgnoreKeyTextOutputFormat to verify the round-trip.

…t for skip.header/footer.line.count

For a text table with `skip.header.line.count=N` (and/or
`skip.footer.line.count=M`), `INSERT` / `INSERT OVERWRITE` writes data files
that do not contain N header lines or M footer lines. On read,
`SkippingTextInputFormat` skips the first N lines of each file and the last M
lines of each file. When new files are appended, the first N data lines of each
appended file are skipped as if they were headers, causing data loss.

Reproduce with:

CREATE TABLE t (a string, b string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS TEXTFILE
TBLPROPERTIES ('skip.header.line.count'='1');

INSERT OVERWRITE TABLE t VALUES ('x','y'),('a','b'),('c','d');
SELECT * FROM t; -- returned only ('a','b'), ('c','d') before the fix

This mirrors how Spark native CSV handles `header=true`: the writer emits a
header line before the data rows (see Spark's CsvOutputWriter). Hive already
has the reader-side skip (`SkippingTextInputFormat`, `RecordReaderWrapper`);
this change adds the writer-side header/footer emission to
`HiveIgnoreKeyTextOutputFormat`.

Spark writer reference:
https://github.com/apache/spark/blob/751f29f12933ef3626518e8ed7a13a225c37d326/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/csv/CsvOutputWriter.scala#L42-L44

The header line is built from the table column names using the table's delimiter
and quote properties; OpenCSVSerde tables quote all header fields by default,
other text SerDes quote only when required. Footer lines are emitted before the
file is closed.

Also updates the `skip_header_footer_proj.q` golden output to reflect that all
inserted rows are now returned, and adds `TestHiveIgnoreKeyTextOutputFormat` to
verify the round-trip.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@sonarqubecloud

sonarqubecloud Bot commented Aug 7, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants