Expand description
v7.22 (mailrs round-13 / T2) — shared COPY text-format helpers.
PG’s COPY is not an engine statement in SPG: both consumers
lower it to per-row INSERTs. The wire path (spg-server pgwire)
has done this since v7.15 for COPY … FROM stdin CopyData
frames; the embed path (Database::execute_script /
spg import) gained it in v7.22 because default-format
pg_dump emits COPY blocks, and the zero-change import promise
covers the default format, not just --column-inserts.
This module is the single home for the pure pieces: text-row
decoding (tab-separated, \N nulls, backslash escapes) and
INSERT synthesis. The wire path delegates here; wire-specific
concerns (CopyData framing, SKIP/ON_ERROR/JSON options) stay in
pgwire.
Structs§
- Copy
From File Spec - v7.39 (round 249) — a parsed
COPY <table> [(cols)] FROM '<path>'. The engine is no_std: the HOST readspathand hands the bytes tocopy_buffer_inserts/Engine::copy_from_buffer. - Copy
From Spec - The head of an embed-path
COPY … FROM stdin;statement. - Copy
ToFile Spec - v7.39 (round 252) — a parsed
COPY … TO '<file>'(table or query form). The HOST renders viaEngine::copy_to_bufferand writespathitself.
Functions§
- build_
copy_ insert - Build
INSERT INTO <table> [(cols)] VALUES (…)from a decoded row. Numeric-looking and boolean cells go in bare so the engine sees typed literals; everything else is single-quoted with SQL escaping. - copy_
buffer_ inserts - v7.39 (round 249) — decode a whole
COPY … FROM '<file>'buffer (the HOST read the file; the engine is no_std and performs no I/O) into the per-row INSERT statements both hosts drive. Text and CSV formats honour DELIMITER / NULL / HEADER / QUOTE; the text-format\.terminator ends the data early, as in PG. - csv_
record_ end - Byte length of the first complete CSV record in
buf— including its terminating\n— orNoneif the buffer does not yet hold a full record (an unterminated quoted field, or no record-ending newline yet). Quote-aware: a newline inside a quoted field is part of the record. The quote character only opens a quoted field at the start of a field (buffer start or right after a delimiter), sodelimiteris needed to track field boundaries. Scanning raw bytes is UTF-8-safe because the ASCII delimiter / quote / newline never collide with a multi-byte continuation byte (which is always ≥ 0x80). - decode_
copy_ csv_ record - Decode one CSV data record (
COPY … FROM stdin WITH (FORMAT csv)) into its fields. A field that starts with the quote character is a quoted field: its content runs to the matching close quote, a doubled quote ("") is one literal quote, and it is never NULL — a quoted empty string staysSome(""). An unquoted field runs to the next delimiter; if its text equalsnull_strit decodes to NULL, so with the default empty null string an empty unquoted field is NULL while""is the empty string (PG’s exact CSV distinction). Embedded delimiters and newlines are only meaningful inside quotes. - decode_
copy_ text_ row - Decode one COPY text-format data row: tab-separated cells,
\N= NULL, C-style backslash escapes. - encode_
copy_ csv_ cells - Encode one row’s cells as a CSV line (PG
COPY … WITH (FORMAT csv)). A non-NULL field is quoted when it contains the delimiter, the quote character, a CR or LF, or when its text equalsnull_str— so an empty string under the default empty NULL, or any value that collides with the NULL marker, reads back as itself rather than as NULL. The quote character is doubled inside a quoted field. NULL is emitted asnull_str, unquoted. - encode_
copy_ csv_ cells_ opts - v7.39 (round 247) — the full CSV cell encoder:
escapeis the character that precedes a quote (or itself) inside a quoted cell (PG’s default is the quote itself — doubling), andforce_quotemarks per-column forced quoting (NULLs stay bare, as PG’s FORCE_QUOTE does). - encode_
copy_ text_ cells - Encode one row’s selected cells as a COPY text-format line —
the inverse of
decode_copy_text_row: tab-separated,\Nfor NULL, C-style backslash escapes for the control characters the decoder understands. - encode_
copy_ text_ cells_ opts - Encode one row’s cells as a COPY text-format line with a custom
delimiter and NULL marker (PG
COPY … WITH (FORMAT text, DELIMITER 'c', NULL 'str')). The named C-escapes (\t \n \r \b \f \v \\) are always applied; a delimiter character that is not itself one of those gets a literal\<char>escape so it round-trips. - parse_
copy_ from_ file - Parse
sqland return its parts when it is aCOPY … FROM '<file>'statement — the host-side sniff for the file endpoint (any other statement, or a parse error, returnsNoneand the caller executes normally). - parse_
copy_ from_ stdin_ head - Parse the head of a
COPY <table> [(cols)] FROM stdinstatement (text format). ReturnsNonewhen the statement is not that shape — includingCOPY … TO stdoutand file endpoints. A trailingWITH (…)options tail is accepted and ignored except that a non-textFORMATmakes this returnNone(the embed path only lowers the text format; callers surface a clear error). - parse_
copy_ to_ file - Parse
sqland return its parts when it is aCOPY … TO '<file>'statement (any other statement, or a parse error, returnsNone). - validate_
copy_ option_ direction - v7.39 (round 265) — the COPY option rules that depend on DIRECTION, probed against live PG18.4: