xiangfu0 commented on PR #17939:
URL: https://github.com/apache/pinot/pull/17939#issuecomment-5853046653

   Rebased onto latest master (clean, no conflicts) and addressed all 16 open 
review threads:
   
   **Security / trust boundary**
   - **statementId is now server-authoritative** (`InsertRequest.java`, 
`InsertStatementResource.java`): `/insert/execute` replaces any client-supplied 
statementId with a fresh UUID via `withServerGeneratedStatementId()`. 
Idempotent retries correlate via requestId only.
   - **Strict ID validation** (`InsertRequest.ID_PATTERN` = 
`[A-Za-z0-9_-]{1,128}`): both statementId and requestId are validated on every 
construction path (JsonCreator + Builder), and `InsertStatementStore` 
re-validates ids before they become znode path components (defense in depth). A 
`/` can no longer create nested znodes or collide with another caller's subtree.
   - **payloadHash is now computed by the coordinator** from the request it 
actually received (`InsertRequest.computePayloadHash()`); a client-supplied 
hash is ignored. Reusing a requestId with different rows is now always 
detected, including for REST callers that send no hash. The broker no longer 
computes/sends a hash at all.
   - **Minion task-config allowlist** (`FileInsertExecutor.buildTaskConfigs`): 
only `inputFormat`, `includeFileNamePattern`, `excludeFileNamePattern`, and 
`recordReader.prop.*` are forwarded from caller options. `input.fs.className`, 
`recordReader.className`, `outputDirURI`, `push.*`, `authToken` etc. are 
dropped (with a log), closing the scheme-allowlist bypass.
   
   **Correctness**
   - **Negative numbers in VALUES** (`InsertIntoValues.java`): 
MINUS_PREFIX/PLUS_PREFIX around numeric literals are unwrapped (same treatment 
as CalciteSqlParser); tests added. All parse-path errors now throw 
`SqlCompilationException` instead of `IllegalArgumentException`.
   - **Lead-controller gating** 
(`InsertStatementCoordinator.cleanupAllTables`): the sweep now skips tables 
this controller does not lead (`LeadControllerManager.isLeaderForTable`), so N 
flag-enabled controllers no longer race on the same CAS transitions or all poll 
Minion state.
   - **Table-drop cleanup**: when the sweep finds a table that no longer 
exists, it deletes both `/INSERT_STATEMENTS/{table}` and 
`/INSERT_REQUEST_IDS/{table}` subtrees 
(`InsertStatementStore.deleteTableSubtrees`), so a recreated table can't serve 
the old table's idempotency results.
   - **Null partition values** (`ControllerRowInsertExecutor.partitionRows`): 
rows with a null partition column are now routed by the column's schema default 
null value — the same value the segment creator stores and computes partition 
metadata from — preserving the one-partition-per-segment invariant.
   - **BYTES / BIG_DECIMAL over the broker wire** 
(`SqlQueryExecutor.canonicalizeForWire`): byte[] is sent as HEX string (what 
the controller's STRING→BYTES coercion expects) and BigDecimal as a plain 
string (no Jackson double truncation), so the broker HTTP path and the 
in-process controller path now behave identically. New IT covers negative INT, 
BYTES, BIG_DECIMAL, negative DOUBLE end-to-end through the broker.
   
   **Resource limits (ROW inserts build segments on the controller)**
   - New configs: `controller.insert.row.max.rows.per.statement` (default 10k), 
`controller.insert.row.max.bytes.per.statement` (default 10MB) — both enforced 
pre-acceptance, before a manifest is created — and 
`controller.insert.row.max.concurrent.statements` (default 4, fail-fast 
semaphore in the executor).
   - The ROW upload path now runs the same checks as the segment-upload REST 
path at staging time: `SegmentValidationUtils.validateTimeInterval`, 
`validateUpsertSegmentPartitionMetadata`, and `checkStorageQuota` (wired to the 
controller's `StorageQuotaChecker`). An over-quota table can no longer grow 
through INSERT. If Helix registration fails after the deep-store copy, the 
orphan tar is deleted.
   
   **Docs / cleanup**
   - Removed stale comments describing PREPARED/COMMITTED transitions the v1 
enum doesn't have; remaining mentions explicitly say "reserved for v2 / not 
entered".
   - REST API docs updated: idempotency via requestId, hash computed 
server-side, statementId server-generated.
   
   **Grammar note (thread on parserImpls.ftl):** `INSERT INTO t` without 
FROM/VALUES no longer parses — `DataFileDefList()` is now a required 
alternative in the unified `SqlInsertStatement()` production. Previously it 
parsed into a `SqlInsertFromFile` with a null file list that failed later at 
execution; failing at parse time is intentional. Calling it out here since it's 
a (benign) grammar behavior change.
   
   **Not done in this pass (acknowledged):** splitting the coordinator into 
ROW-only v1 + FILE/sweep follow-up (thread on the 1.9k-line file), and the 
larger IT matrix (REALTIME upload-next-to-consuming, full upsert partition 
assignment, multi-controller, hybrid tableType) — proposing to track those as 
follow-ups; the riskiest wire-fidelity paths are now covered by the new typed 
round-trip IT.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to