Skip to content

Commit 6304a9b

Browse files
hbarthelsclaude
andcommitted
Add CSV table mode: single-relation loading without row ID
Introduces a `table` form for `csv_data` that loads all selected columns into one output relation with schema `key=[T1..TN], value=[]`, dropping the per-column row-ID keying of the existing `columns` form. Proto: - Add `CsvTarget` message (target_id, column_names, types) - Add `optional CsvTarget target = 5` to `CSVData` Grammar: - Add `csv_table` rule: `(table <rel_id> ["col"...] [Type...])` - Rewrite `csv_data` to accept either `gnf_columns?` or `csv_table?` in a single alternative (avoids LL(3) conflict on the shared prefix) - Add construct/deconstruct helpers for the two modes Regenerate parsers, pretty-printers, and proto stubs for Python, Julia, and Go. Add `tests/lqp/csv_table.lqp` with four table-mode variants and corresponding binary/snapshot artifacts. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 88009c6 commit 6304a9b

21 files changed

Lines changed: 14906 additions & 14161 deletions

File tree

meta/src/meta/grammar.y

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
%nonterm csv_data logic.CSVData
9292
%nonterm csv_locator_inline_data String
9393
%nonterm csv_locator_paths Sequence[String]
94+
%nonterm csv_table logic.CSVTarget
9495
%nonterm csvlocator logic.CSVLocator
9596
%nonterm data logic.Data
9697
%nonterm date logic.DateValue
@@ -1104,14 +1105,23 @@ gnf_columns
11041105
csv_asof
11051106
: "(" "asof" STRING ")"
11061107

1108+
csv_table
1109+
: "(" "table" relation_id "[" STRING* "]" "[" type* "]" ")"
1110+
construct: $$ = logic.CSVTarget(target_id=$3, column_names=$5, types=$8)
1111+
deconstruct:
1112+
$3: logic.RelationId = $$.target_id
1113+
$5: Sequence[String] = $$.column_names
1114+
$8: Sequence[logic.Type] = $$.types
1115+
11071116
csv_data
1108-
: "(" "csv_data" csvlocator csv_config gnf_columns csv_asof ")"
1109-
construct: $$ = logic.CSVData(locator=$3, config=$4, columns=$5, asof=$6)
1117+
: "(" "csv_data" csvlocator csv_config gnf_columns? csv_table? csv_asof ")"
1118+
construct: $$ = construct_csv_data($3, $4, $5, $6, $7)
11101119
deconstruct:
11111120
$3: logic.CSVLocator = $$.locator
11121121
$4: logic.CSVConfig = $$.config
1113-
$5: Sequence[logic.GNFColumn] = $$.columns
1114-
$6: String = $$.asof
1122+
$5: Optional[Sequence[logic.GNFColumn]] = deconstruct_csv_data_columns_optional($$)
1123+
$6: Optional[logic.CSVTarget] = deconstruct_csv_data_target_optional($$)
1124+
$7: String = $$.asof
11151125

11161126
csv_locator_paths
11171127
: "(" "paths" STRING* ")"
@@ -1751,6 +1761,34 @@ def deconstruct_iceberg_data_to_snapshot_optional(msg: logic.IcebergData) -> Opt
17511761
return builtin.none()
17521762

17531763

1764+
def construct_csv_data(
1765+
locator: logic.CSVLocator,
1766+
config: logic.CSVConfig,
1767+
columns_opt: Optional[Sequence[logic.GNFColumn]],
1768+
target_opt: Optional[logic.CSVTarget],
1769+
asof: String,
1770+
) -> logic.CSVData:
1771+
return logic.CSVData(
1772+
locator=locator,
1773+
config=config,
1774+
columns=builtin.unwrap_option_or(columns_opt, list[logic.GNFColumn]()),
1775+
asof=asof,
1776+
target=target_opt,
1777+
)
1778+
1779+
1780+
def deconstruct_csv_data_columns_optional(msg: logic.CSVData) -> Optional[Sequence[logic.GNFColumn]]:
1781+
if not builtin.has_proto_field(msg, "target"):
1782+
return builtin.some(msg.columns)
1783+
return builtin.none()
1784+
1785+
1786+
def deconstruct_csv_data_target_optional(msg: logic.CSVData) -> Optional[logic.CSVTarget]:
1787+
if builtin.has_proto_field(msg, "target"):
1788+
return builtin.some(builtin.unwrap_option(msg.target))
1789+
return builtin.none()
1790+
1791+
17541792
def construct_export_iceberg_config_full(
17551793
locator: logic.IcebergLocator,
17561794
config: logic.IcebergCatalogConfig,

proto/relationalai/lqp/v1/logic.proto

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,11 +276,18 @@ message BeTreeLocator {
276276
int64 tree_height = 3;
277277
}
278278

279+
message CSVTarget {
280+
RelationId target_id = 1; // Output relation path
281+
repeated string column_names = 2; // CSV column names in order (no METADATA$ columns)
282+
repeated Type types = 3; // Column types in order (same length as column_names)
283+
}
284+
279285
message CSVData {
280286
CSVLocator locator = 1;
281287
CSVConfig config = 2;
282288
repeated GNFColumn columns = 3;
283289
string asof = 4; // Blob storage timestamp for freshness requirements
290+
optional CSVTarget target = 5; // If present, single-relation (table) mode; mutually exclusive with columns
284291
}
285292

286293
message CSVLocator {

0 commit comments

Comments
 (0)