feat(cubesql): Support COPY ... FROM STDIN - #11538
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
|
Claude finished @MazterQyou's task in 9m 44s —— View job Review: 2 high, 3 medium, 4 low — 6 inline comments postedFull review — findings, verification notes, and todo listTodos
GeneralThis is unusually careful work. The decoder mirrors Findings below; the substantive ones are also inline on the diff. High
Medium
Low / nits
Verification notesI did not build or run the test suite here (the DataFusion fork build is prohibitively long in this environment) — findings 1–5 come from reading the call graph, and the reasoning for each is spelled out in the inline comments so they can be checked quickly. Findings 1 and 2 are deterministic from the code paths shown rather than heuristic. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #11538 +/- ##
===========================================
+ Coverage 59.35% 84.28% +24.92%
===========================================
Files 223 260 +37
Lines 17989 83859 +65870
Branches 3641 0 -3641
===========================================
+ Hits 10677 70678 +60001
- Misses 6793 13181 +6388
+ Partials 519 0 -519
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Signed-off-by: Alex Qyoun-ae <4062971+MazterQyou@users.noreply.github.com>
dfb05cf to
b66ff70
Compare
|
Claude finished @MazterQyou's task in 5m 13s —— View job Re-review after force-push: all 6 prior findings fixed — 1 medium, 5 low remain (2 inline comments posted)Full review — todos, what changed, and remaining findingsTodos
Prior findings — all addressed
Six stale threads resolved. Remaining findingsMedium
Low / nits
GeneralThe rework is clean and the fixes went in at the right level rather than being patched at the edges — moving the table creation into a plan variant also got Verification notesI did not build or run the test suite (the DataFusion fork build is prohibitively long in this environment). The medium finding is traced through both |
|
|
||
| while let Some(char) = chars.next() { | ||
| if in_quote { | ||
| if char == options.escape && chars.peek() == Some(&options.quote) { |
There was a problem hiding this comment.
With a non-default ESCAPE, the escape character cannot escape itself, and the unquoting disagrees with the scan.
PostgreSQL's CopyReadAttributesCSV peeks for either character after the escape:
if (c == escapec)
{
if (cur_ptr < line_end_ptr)
{
char nextc = *cur_ptr;
if (nextc == escapec || nextc == quotec)
{
*output_ptr++ = nextc;
cur_ptr++;
continue;
}
}
}Here only options.quote is peeked for. With the default ESCAPE (which is QUOTE) the two are the same character, so nothing is lost; with WITH (FORMAT csv, ESCAPE '\') they diverge, and the divergence is not just a missing unescape — it desynchronizes this splitter from take_line.
For the row 1,"a\\" (field a followed by two backslashes, ESCAPE '\'):
take_line(line 215) sees\inside the quote, skips two bytes, then closes the quote on"— one complete row, which is right.split_csv_linesees\with peek\≠ quote → pushes\; then\with peek"== quote → pushes"and consumes it, soin_quoteis never cleared. The field comes out asa\".
PostgreSQL stores a\. So this silently loads a wrong value rather than erroring. ESCAPE isn't exercised anywhere in test_copy.rs, and the one unit test that sets options.escape = '\\' (test_the_scan_never_runs_past_the_data) only checks the unterminated-quote error.
| if char == options.escape && chars.peek() == Some(&options.quote) { | |
| if char == options.escape | |
| && chars | |
| .peek() | |
| .is_some_and(|next| *next == options.quote || *next == options.escape) | |
| { |
| } | ||
|
|
||
| /// (F) Sent by the client to signal that it has sent all the data of a `COPY ... FROM STDIN`. | ||
| #[derive(Debug, PartialEq)] |
There was a problem hiding this comment.
Nit: the doc comment describes CopyDone, not CopyFail — this message means the client is aborting the copy and carries the reason.
| #[derive(Debug, PartialEq)] | |
| /// (F) Sent by the client to abort a `COPY ... FROM STDIN`, carrying the reason. |
| } | ||
| } | ||
|
|
||
| /// (F) Sent by the client to signal that it has sent all the data of a `COPY ... FROM STDIN`. |
There was a problem hiding this comment.
Nit (this is the line my adjacent comment meant — please ignore that one's suggestion block, it anchored one line too low and would replace the #[derive]):
This doc comment describes CopyDone, not CopyFail — CopyFail means the client is aborting the copy, and the message is the reason. Suggested wording: /// (F) Sent by the client to abort a COPY ... FROM STDIN, carrying the reason.
Check List
Description of Changes Made
This PR adds support for
COPY ... FROM STDINcommand, allowing adding data to temporary tables. Related tests are included.