fix(load): adjust non-strict LOAD DATA values#25459
Conversation
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
XuPeng-SH
left a comment
There was a problem hiding this comment.
Requesting changes.
I verified the external package tests locally (with the MO CGo/rpath setup) and CI is green, but I do not think this PR has a closed semantic contract yet.
-
#25366 is still
needs-triage, and the issue discussion explicitly says LOAD DATA invalid adjusted-value handling needs a product/R&D decision before implementation. This PR directly changes that contract. Before merging, please document/confirm the intended contract: strict vs non-strict, LOCAL vs non-LOCAL, accepted rows, adjusted values, warning/count reporting, and which LOAD formats are included. -
The adjustment gate is broader than the reported CSV LOCAL case.
shouldApplyLoadDataNonStrictAdjustmentsonly checksExternType_LOAD && !checkLineStrict(external.go:900-904), thengetColDataapplies numeric/date/string rewrites to any matching LOAD path (external.go:1071-1110). That also changes JSONLINE and other non-strict LOAD surfaces, not just the issue sample. Please either narrow the gate to the intended surface or add explicit coverage/documentation that the broader behavior is intended. -
The behavior is only a partial MySQL-style adjusted-value implementation. It handles numeric prefix/no-prefix, invalid DATE, and CHAR/VARCHAR truncation for the sample, but warning reporting is missing; numeric range/unsigned overflow still aborts through the existing
ErrRangepaths; empty temporal fields still go through the NULL path; invalid BOOL and quoted numeric cases can still abort. Please either define these as intentionally out of scope in the contract/tests/PR body, or complete the semantic matrix. -
The test coverage is not sufficient for a compatibility semantic change. The new tests call
getOneRowData/getColDatadirectly, but there is no BVT/e2e coverage for the actualLOAD DATA LOCAL INFILESQL from the issue. Please add coverage for the real SQL path and unhappy cases: non-strict LOCAL success, strict/non-LOCAL rejection, explicit\\Nvs empty fields, JSONLINE unchanged or intentionally adjusted, range/unsigned/bool/quoted numeric/date cases according to the chosen contract.
4b53458 to
92405e8
Compare
92405e8 to
ef71d37
Compare
XuPeng-SH
left a comment
There was a problem hiding this comment.
Requesting changes on the current head (ef71d37). The revised scope is much better than the previous version: the adjustment gate is now limited to LOAD DATA LOCAL + CSV + non-strict mode, CI is green, and the new BVT covers the real SQL path. I still found one semantic leak that should be closed before merge.
Confirmed issue: quoted invalid numeric fields are now adjusted even though the PR declares quoted numeric edge cases out of scope.
getColData applies the non-strict numeric-prefix rewrite before the typed parser:
pkg/sql/colexec/external/external.go:1102-1105rewrites every scoped numeric value withloadDataNonStrictNumericPrefix.- The existing integer parser only rejects quoted numeric conversion when parsing fails and then sees
field.HasStringQuote(external.go:1209-1211, and the same pattern for other integer widths). - After this PR, a quoted invalid value like
"abc"is rewritten to"0";strconv.ParseInt("0")succeeds, so theHasStringQuoterejection path is never reached.
I verified this locally with a temporary UT against the current PR head:
err := getColData(
bat,
[]csvparser.Field{{Val: "abc", HasStringQuote: true}},
0,
param, // LOAD DATA LOCAL, CSV, StrictSqlMode=false
proc.Mp(),
plan.ExternAttr{ColName: "i", ColIndex: 0, ColFieldIndex: 0},
proc,
)
require.Error(t, err) // fails: err is nil, value is loaded as 0This is not just missing coverage; it changes an existing quoted-field contract while the PR body says quoted numeric edge cases are intentionally not part of this compatibility patch.
Suggested fix: if quoted numeric behavior is truly out of scope, skip the numeric-prefix adjustment when field.HasStringQuote is true and add UT/BVT coverage for quoted "abc" / "10x" with FIELDS ... ENCLOSED BY '"' or OPTIONALLY ENCLOSED BY '"', plus strict/non-LOCAL rejection coverage. If the intended behavior is to adjust quoted invalid numeric values too, then please update the semantic contract and add explicit SQL coverage for that expanded behavior.
Validation I ran:
go test -ldflags="-extldflags '-L$(pwd)/cgo -lmo -L$(pwd)/thirdparties/install/lib -Wl,-rpath,@executable_path/lib'" \
-v -count=1 -timeout 120s ./pkg/sql/colexec/external \
-run 'Test(GetOneRowDataLoadDataNonStrictAdjustedValues|GetColDataLoadDataStrictRejectsInvalidInteger|GetColDataLoadDataAdjustmentsOnlyLocalCSVNonStrict|GetColDataLoadDataNonStrictAdjustmentLeavesEmptyBoolNull|GetColDataParallelLoadEmptyNumericAsZero|GetColDataParallelLoadNullNumericRemainsNull|GetColDataLoadDataYear)|Test_getColData_StringWidthStrict'
PASS
Temporary quoted-invalid-numeric repro test: FAIL, err is nil.
aunjgr
left a comment
There was a problem hiding this comment.
Carefully scoped. The gate shouldApplyLoadDataNonStrictAdjustments correctly restricts to LOCAL + CSV + non-strict. Minor suggestions:
-
T_date gets zero-value adjustment but T_datetime/T_timestamp don't. The PR body says this is out of scope. Add a comment near the temporal handling noting the intentional gap so future maintainers don't think it's an oversight.
-
shouldLoadEmptyNumericAsZerousesisLoadNumericAdjustedValueType(excludes T_bool) vsisLoadNumericZeroFillType(includes T_bool). The PR body says empty BOOL remains NULL — this is correct but deserves a comment at the call site explaining why the two paths diverge.
What type of PR is this?
Which issue(s) this PR fixes:
Fixes #25366
What this PR does / why we need it:
LOAD DATA LOCAL INFILEwith non-strict SQL mode should accept the adjusted values from the reported MySQL-compatible CSV case instead of aborting the whole load on invalid field conversions.Semantic contract for this PR:
LOAD DATA LOCAL INFILE, CSV format, non-strict SQL mode (StrictSqlMode=false).sql_modeis non-strict.\Nand mapped null fields remainNULL; empty numeric CSV fields in the scoped path load as zero.NULLand invalid BOOL is not adjusted.Adjusted values implemented in scope:
0when no numeric prefix existsDATEfields load as MO's internal zero-date value (types.Date(0)); BVT/JDBC result rendering shows it as0001-01-01CHAR/VARCHARvalues truncate by rune widthIntentionally out of scope for this focused compatibility patch:
SHOW WARNINGSreportingChanges:
LOAD DATA LOCAL INFILESQL path, including the issue sample,\Nvs empty numeric fields, strict LOCAL rejection, non-LOCAL non-strict rejection, and quoted invalid numeric rejectionValidation: