Skip to content

feat(webui): Inject time range into guided UI search query; Generate timeline bucket query.#1315

Merged
hoophalab merged 6 commits into
y-scope:mainfrom
hoophalab:timestamp-sql
Sep 24, 2025
Merged

feat(webui): Inject time range into guided UI search query; Generate timeline bucket query.#1315
hoophalab merged 6 commits into
y-scope:mainfrom
hoophalab:timestamp-sql

Conversation

@hoophalab

@hoophalab hoophalab commented Sep 19, 2025

Copy link
Copy Markdown
Contributor

Description

  1. Add a function to construct timeline bucket queries.
  2. Check if the boolean expression references a timestamp column in the search query.
  3. Add a WHERE filter based on a specified timestamp range in the search query.
  4. Add a few testing input boxes.
timestampsql

Checklist

  • The PR satisfies the contribution guidelines.
  • This is a breaking change and that has been indicated in the PR title, OR this isn't a
    breaking change.
  • Necessary docs have been updated, OR no docs need to be updated.

Validation performed

  1. Referencing the timestamp column in the WHERE clause of the query is causing an error (shown in the console).
  2. The shown data in the result table is within the correct time range.
  3. The timeline buckets are stored in MongoDB in the same the format as CLP aggregation task.

Summary by CodeRabbit

  • New Features

    • Runs a timeline aggregation query alongside the main search when submitting.
    • Added inputs for database name, start/end timestamps and timestamp key.
    • Searches now include time-range filtering and timeline bucketed aggregation.
  • Improvements

    • Separate submission and logging for search and timeline queries with clearer error feedback.
    • Validation applied to both search and timeline queries to surface invalid SQL earlier.

@hoophalab hoophalab requested a review from a team as a code owner September 19, 2025 18:50
@coderabbitai

coderabbitai Bot commented Sep 19, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds 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

Cohort / File(s) Summary of Changes
Presto test UI — dual submission
components/webui/client/src/pages/SearchPage/SearchControls/Presto/BuildSqlTestingInputs.tsx
Replaced relation input with databaseName and added startTimestamp, endTimestamp, timestampKey form fields; on submit builds main search SQL (with time-range) and submits it via existing handler; also builds timeline aggregation SQL (bucketCount=10) and submits it via submitQuery; separate logging and error handling for each submission.
SQL parser core & API
components/webui/client/src/sql-parser/index.ts, components/webui/client/src/sql-parser/typings.ts
Switched parser targets to SqlLexer/SqlParser; expanded BuildSearchQueryProps with startTimestamp, endTimestamp, timestampKey; added BuildTimelineQueryProps and exported buildTimelineQuery(props): string; both builders validate final SQL and throw on invalid SQL; exports updated to include new types and function.
Grammar addition
components/webui/client/src/sql-parser/Sql.g4
New top-level grammar Sql added that imports SqlBase to serve as codegen input (wrapper grammar).
Codegen pipeline update
taskfiles/codegen.yaml
Updated webui-generate-parser job to use Sql.g4 as source and to expect generated SqlLexer.ts / SqlParser.ts; adjusted subsequent replace-text targets to new file names.

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
Title Check ✅ Passed The title clearly and concisely describes the two main features introduced—injecting a time range filter into the guided UI search query and generating a timeline bucket query—without using vague terminology or extraneous details.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b83e3cf and 1b91d32.

⛔ Files ignored due to path filters (2)
  • components/webui/client/src/sql-parser/generated/SqlBaseParser.ts is excluded by !**/generated/**
  • components/webui/client/src/sql-parser/generated/SqlBaseVisitor.ts is 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.tsx
  • 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)
🪛 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.

Comment thread components/webui/client/src/sql-parser/index.ts Outdated
Comment thread components/webui/client/src/sql-parser/index.ts Outdated
Comment thread components/webui/client/src/sql-parser/index.ts
@hoophalab hoophalab requested a review from davemarco September 19, 2025 19:32

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.index

Additional 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

📥 Commits

Reviewing files that changed from the base of the PR and between 1b91d32 and b6170ac.

📒 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.

Comment thread components/webui/client/src/sql-parser/index.ts Outdated

@davemarco davemarco left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

timestamp key checker looks good. I have some slight concerns the sql is too complex, and we can maybe just do it in javascript

Comment thread components/webui/client/src/sql-parser/index.ts Outdated
Comment thread components/webui/client/src/sql-parser/index.ts Outdated
Comment thread components/webui/client/src/sql-parser/index.ts Outdated
Comment thread components/webui/client/src/sql-parser/SqlBase.g4 Outdated
@hoophalab hoophalab requested a review from davemarco September 23, 2025 19:55
@hoophalab

hoophalab commented Sep 23, 2025

Copy link
Copy Markdown
Contributor Author

@davemarco I've made the changes we discussed. The current code doesn't work when the timestamp key contains special chars such as -, but let me confirm with the other people of what is the correct way to reference such keys in WHERE. Other than this issue, the PR should be good to be merged.

coderabbitai[bot]

This comment was marked as off-topic.

@davemarco davemarco left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. 2 small then approve

Comment thread components/webui/client/src/sql-parser/index.ts
Comment thread components/webui/client/src/sql-parser/index.ts Outdated
@hoophalab hoophalab requested a review from davemarco September 24, 2025 17:16

@davemarco davemarco left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good
feat(webui): Inject time range into guided UI search query; Generate timeline bucket query.

coderabbitai[bot]

This comment was marked as duplicate.

@hoophalab hoophalab changed the title feat(webui): Generate timeline bucket queries from guided SQL input boxes. feat(webui): Inject time range into guided UI search query; Generate timeline bucket query. Sep 24, 2025

@junhaoliao junhaoliao left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deferring to @davemarco 's review

@hoophalab hoophalab merged commit b3abc50 into y-scope:main Sep 24, 2025
27 checks passed
junhaoliao pushed a commit to junhaoliao/clp that referenced this pull request May 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants