feat(webui): Inject time range into guided UI search query; Generate timeline bucket query.#1315
Conversation
WalkthroughAdds a timeline aggregation flow to the Presto test UI: the form now builds and submits both a main search SQL and a bucketed timeline SQL. Extends the SQL parser/types with time-range fields and a new buildTimelineQuery, adds a Sql.g4 wrapper grammar, and updates codegen targets to SqlLexer/SqlParser. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Dev as Developer (UI)
participant UI as BuildSqlTestingInputs.tsx
participant Parser as sql-parser (buildSearchQuery / buildTimelineQuery)
participant Presto as Presto submit (handlePrestoQuerySubmit)
participant Agg as Aggregation submit (submitQuery)
Dev->>UI: Submit form
UI->>Parser: buildSearchQuery(props with start/end/timestampKey)
alt search SQL valid
Parser-->>UI: searchQuery
UI->>Presto: handlePrestoQuerySubmit(searchQuery)
Presto-->>UI: Search submission result
else search SQL invalid
Parser-->>UI: Error
UI-->>Dev: Log/display search build error
end
UI->>Parser: buildTimelineQuery({databaseName, start/end, bucketCount, timestampKey})
alt timeline SQL valid
Parser-->>UI: timelineQuery
UI->>Agg: submitQuery(timelineQuery)
alt submit success
Agg-->>UI: { aggregationJobId }
UI-->>Dev: Log aggregationJobId
else submit error
Agg-->>UI: Error
UI-->>Dev: Log timeline submit error
end
else timeline SQL invalid
Parser-->>UI: Error
UI-->>Dev: Log/display timeline build error
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (2)
components/webui/client/src/sql-parser/generated/SqlBaseParser.tsis excluded by!**/generated/**components/webui/client/src/sql-parser/generated/SqlBaseVisitor.tsis excluded by!**/generated/**
📒 Files selected for processing (4)
components/webui/client/src/pages/SearchPage/SearchControls/Presto/BuildSqlTestingInputs.tsx(4 hunks)components/webui/client/src/sql-parser/SqlBase.g4(2 hunks)components/webui/client/src/sql-parser/index.ts(4 hunks)taskfiles/codegen.yaml(2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}
⚙️ CodeRabbit configuration file
- Prefer
false == <expression>rather than!<expression>.
Files:
components/webui/client/src/pages/SearchPage/SearchControls/Presto/BuildSqlTestingInputs.tsxcomponents/webui/client/src/sql-parser/index.ts
🧬 Code graph analysis (1)
components/webui/client/src/sql-parser/index.ts (2)
components/webui/client/src/sql-parser/generated/SqlBaseVisitor.ts (1)
SqlBaseVisitor(245-1783)components/webui/client/src/sql-parser/generated/SqlBaseParser.ts (1)
ColumnReferenceContext(15687-15703)
🪛 Biome (2.1.2)
components/webui/client/src/pages/SearchPage/SearchControls/Presto/BuildSqlTestingInputs.tsx
[error] 104-104: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 106-106: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 108-108: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
[error] 110-110: A form label must be associated with an input.
Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.
(lint/a11y/noLabelWithoutControl)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
- GitHub Check: ubuntu-jammy-dynamic-linked-bins
- GitHub Check: centos-stream-9-dynamic-linked-bins
- GitHub Check: ubuntu-jammy-static-linked-bins
- GitHub Check: package-image
- GitHub Check: ubuntu-jammy-lint
- GitHub Check: musllinux_1_2-x86_64-static-linked-bins
- GitHub Check: musllinux_1_2-x86_64-dynamic-linked-bins
- GitHub Check: centos-stream-9-static-linked-bins
- GitHub Check: manylinux_2_28-x86_64-dynamic-linked-bins
- GitHub Check: manylinux_2_28-x86_64-static-linked-bins
- GitHub Check: build-macos (macos-15, false)
- GitHub Check: build-macos (macos-14, true)
- GitHub Check: build-macos (macos-14, false)
🔇 Additional comments (5)
components/webui/client/src/sql-parser/SqlBase.g4 (2)
15-17: Provenance header: good addition.Clear attribution; no issues.
36-38: New entry rule enables boolean-only parsing.The rule is well‑placed and unambiguous relative to existing top‑level rules. Ensure parsers are regenerated wherever this grammar is consumed.
Run the webui parser codegen task and commit the updated artifacts if any diffs appear.
taskfiles/codegen.yaml (1)
69-71: Enable visitor generation and propagate header injection to the Visitor.
- Adding -visitor is correct and required for the new visitor-based flow.
- Including generated/SqlBaseVisitor.ts in the header injection loop keeps linters quiet.
Please run the task locally to confirm the visitor file is produced and the checksum updates as expected.
Also applies to: 77-80
components/webui/client/src/pages/SearchPage/SearchControls/Presto/BuildSqlTestingInputs.tsx (1)
83-90: Verify response shape for timeline submission.Confirm result.data.searchJobId is the correct property for timeline queries; APIs often differ (e.g., jobId vs searchJobId).
components/webui/client/src/sql-parser/index.ts (1)
145-148: Consider quoting identifiers when needed.If timestampKey may include special characters, ensure callers pass quoted/back‑quoted forms or add a safe identifier wrapper. Current usage relies on raw insertion.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (4)
components/webui/client/src/sql-parser/index.ts (4)
50-75: Fix timestamp key detection: normalise case and strip quotes to match UpperCaseCharStream.UpperCaseCharStream upper-cases everything (including quoted/back‑quoted identifiers), so direct string comparisons miss matches. Normalise once and compare upper‑cased text.
Apply this diff:
class TimestampKeyChecker extends SqlBaseVisitor<void> { hasTimestamp: boolean; constructor (timestampKey: string) { super(); this.hasTimestamp = false; - // Three possible terminal nodes of the `identifer` context - const timestampIdentifiers = new Set([ - // unquotedIdentifier - timestampKey, - - // quotedIdentifier - `"${timestampKey}"`, - - // backQuotedIdentifier - `\`${timestampKey}\``, - ]); + // Normalise: strip one layer of quotes/backquotes and upper-case + const base = timestampKey.replace(/^["`]|["`]$/g, ""); + const TK = base.toUpperCase(); + const timestampIdentifiers = new Set<string>([TK, `"${TK}"`, `\`${TK}\``]); - this.visitColumnReference = (ctx: ColumnReferenceContext) => { - if (timestampIdentifiers.has(ctx.identifier().getText())) { + this.visitColumnReference = (ctx: ColumnReferenceContext) => { + const idText = ctx.identifier().getText().toUpperCase(); + if (timestampIdentifiers.has(idText)) { this.hasTimestamp = true; } }; } }
105-106: Make InvalidBooleanExpressionError carry context (message + name).Provide a useful message and set the error name.
Apply this diff:
-class InvalidBooleanExpressionError extends Error { -} +class InvalidBooleanExpressionError extends Error { + constructor (message?: string) { + super(message ?? "The WHERE boolean expression must not reference the timestamp column."); + this.name = "InvalidBooleanExpressionError"; + } +}
148-159: Trim/ignore empty booleanExpression and include a descriptive error on violation.Avoid parsing empty strings; include the key in the thrown message.
Apply this diff:
- if ("undefined" !== typeof booleanExpression) { - const booleanExpressionTree = buildParser(booleanExpression).standaloneBooleanExpression() + if ("undefined" !== typeof booleanExpression) { + const expr = booleanExpression.trim(); + if (expr.length === 0) { + // no-op + } else { + const booleanExpressionTree = buildParser(expr).standaloneBooleanExpression() .booleanExpression(); - const checker = new TimestampKeyChecker(timestampKey); + const checker = new TimestampKeyChecker(timestampKey); checker.visit(booleanExpressionTree); - if (checker.hasTimestamp) { - throw new InvalidBooleanExpressionError(); - } + if (checker.hasTimestamp) { + throw new InvalidBooleanExpressionError( + `The WHERE boolean expression must not reference the timestamp column '${timestampKey}'.` + ); + } - queryString += ` AND (${booleanExpression})`; + queryString += ` AND (${expr})`; + } }
206-241: Fix ordering: ORDER BY should use the always-present label table, not the LEFT side’s nullable join key.Ordering by bucket_count.index yields NULLs for empty buckets and unstable ordering. Order by bucket_timestamp.index.
Apply this diff:
-ORDER BY bucket_count.index +ORDER BY bucket_timestamp.indexAdditional recommended improvements:
- Use centre-of-bin timestamps for clearer charting.
- Use strict bounds (> start AND <= end) so width_bucket yields only 1..bucketCount and you can drop the extra WHERE filter.
Apply this diff to centre the timestamps and tighten bounds:
- WHERE to_unixtime(${timestampKey}) BETWEEN ${startTimestampFixed} AND ${endTimestampFixed} + WHERE to_unixtime(${timestampKey}) > ${startTimestampFixed} AND to_unixtime(${timestampKey}) <= ${endTimestampFixed} @@ bucket_timestamp AS ( SELECT index + 1 AS index, - ${startTimestampFixed} - + (index*(${endTimestampFixed}-${startTimestampFixed})/${bucketCount}) AS timestamp + ${startTimestampFixed} + + ((index + 0.5) * ((${endTimestampFixed}-${startTimestampFixed})/${bucketCount})) AS timestamp FROM UNNEST(sequence(0, ${bucketCount - 1}, 1)) AS t(index) )Optional tidy-up (naming): consider renaming “index”→“bucket” throughout to avoid confusion with SQL “INDEX”.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
components/webui/client/src/sql-parser/index.ts(4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}
⚙️ CodeRabbit configuration file
- Prefer
false == <expression>rather than!<expression>.
Files:
components/webui/client/src/sql-parser/index.ts
🧬 Code graph analysis (1)
components/webui/client/src/sql-parser/index.ts (2)
components/webui/client/src/sql-parser/generated/SqlBaseVisitor.ts (1)
SqlBaseVisitor(245-1783)components/webui/client/src/sql-parser/generated/SqlBaseParser.ts (1)
ColumnReferenceContext(15687-15703)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
- GitHub Check: build-macos (macos-14, true)
- GitHub Check: build-macos (macos-15, false)
- GitHub Check: build-macos (macos-15, true)
- GitHub Check: build-macos (macos-14, false)
- GitHub Check: package-image
- GitHub Check: musllinux_1_2-x86_64-dynamic-linked-bins
- GitHub Check: ubuntu-jammy-dynamic-linked-bins
- GitHub Check: ubuntu-jammy-lint
- GitHub Check: musllinux_1_2-x86_64-static-linked-bins
- GitHub Check: ubuntu-jammy-static-linked-bins
- GitHub Check: manylinux_2_28-x86_64-dynamic-linked-bins
- GitHub Check: centos-stream-9-static-linked-bins
- GitHub Check: manylinux_2_28-x86_64-static-linked-bins
- GitHub Check: centos-stream-9-dynamic-linked-bins
🔇 Additional comments (5)
components/webui/client/src/sql-parser/index.ts (5)
10-11: LGTM on new imports.Importing ColumnReferenceContext and SqlBaseVisitor is appropriate for the visitor pattern usage.
167-174: LGTM on validation and error chaining.Catching syntax errors and rethrowing with the full SQL aids debugging.
242-246: LGTM on final validation and error chaining.Consistent with buildSearchQuery.
253-255: LGTM on exports.Public API surface looks coherent.
259-262: LGTM on type exports.Types are correctly exposed.
davemarco
left a comment
There was a problem hiding this comment.
timestamp key checker looks good. I have some slight concerns the sql is too complex, and we can maybe just do it in javascript
|
@davemarco I've made the changes we discussed. The current code doesn't work when the timestamp key contains special chars such as |
davemarco
left a comment
There was a problem hiding this comment.
Looks good. 2 small then approve
junhaoliao
left a comment
There was a problem hiding this comment.
deferring to @davemarco 's review
…timeline bucket query. (y-scope#1315)
Description
Checklist
breaking change.
Validation performed
Summary by CodeRabbit
New Features
Improvements