You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
pxf.bind_row promises (pxf.default) and (pxf.required) but applies neither #24
The bind_row docstring promises something the code does not do. It says an absent cell takes (pxf.default) and that (pxf.required) errors. Neither happens, so a dataset row can silently lose its default or skip a required field.
Evidence
Measured with a one-field schema on protowire-cpp main (8d0867a):
Call
(pxf.required), field absent
(pxf.default) = "x", field absent
pxf.unmarshal
accepted
not tested
pxf.bind_row
accepted
f == ""
pxf.unmarshal_full
required field "f" is absent
f == "x"
The cause is upstream. protowire-cpp applies both options only in UnmarshalFull (src/pxf/decode_fast.cc), and bind_row and cpp's BindRow both go through plain Unmarshal. cpp's comment in BindRow makes the same promise.
Open question
Should bind_row apply the options, or should the docstring change? Going through unmarshal_full would make it match the text but would change what existing rows decode to. That choice belongs to the owner, and I have not made it.
Done when
bind_row's behavior and its docstring agree, with a test for an absent required field and an absent default.
This adds to what this issue decides. protowire-go is changing DatasetReader.Scan (trendvidia/protowire-go#280, PR trendvidia/protowire-go#281; decided in trendvidia/protowire-cpp#166). A streamed row will be bound under all the caller's options except MaxMessageSize, as the options-taking BindRow binds it. Only a decode error gets the row's position. A schema violation and a validator's error come back with no position. protowire-cpp's Scan and BindRow already do this (PR trendvidia/protowire-cpp#174).
From reading this port's code at df004ec (not run):
scan and bind_row have no discard_unknown, so it is always False for a streamed row.
skip_validate defaults to True. Go validates by default.
Errors are not moved to the row, so a decode error carries a position in the generated body rather than the row's position in the input.
If this issue settles on calling cpp's BindRow, all three come with it once the cpp pin moves past #174. The test cases to copy are in protowire-go's encoding/pxf/dataset_scan_options_test.go on #281.
Unblocked: trendvidia/protowire-go#281 merged (8894b7b), which closed #280. The reference tests are in encoding/pxf/dataset_scan_options_test.go on protowire-go main.
Activity
bfrancojr commentedon Nov 7, 2026
This adds to what this issue decides. protowire-go is changing
DatasetReader.Scan(trendvidia/protowire-go#280, PR trendvidia/protowire-go#281; decided in trendvidia/protowire-cpp#166). A streamed row will be bound under all the caller's options exceptMaxMessageSize, as the options-takingBindRowbinds it. Only a decode error gets the row's position. A schema violation and a validator's error come back with no position. protowire-cpp'sScanandBindRowalready do this (PR trendvidia/protowire-cpp#174).From reading this port's code at df004ec (not run):
scanandbind_rowhave nodiscard_unknown, so it is always False for a streamed row.skip_validatedefaults to True. Go validates by default.If this issue settles on calling cpp's
BindRow, all three come with it once the cpp pin moves past #174. The test cases to copy are in protowire-go'sencoding/pxf/dataset_scan_options_test.goon #281.bfrancojr commentedon Nov 7, 2026
Unblocked: trendvidia/protowire-go#281 merged (8894b7b), which closed #280. The reference tests are in
encoding/pxf/dataset_scan_options_test.goon protowire-go main.