This is an automated email from the ASF dual-hosted git repository.

ankitsultana pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 4935e417f3a [timeseries] Adding error banner for timeseries error 
handling in Controller UI (#16406)
4935e417f3a is described below

commit 4935e417f3a8bcb5731d428d82fb8aceda6132ec
Author: Shaurya Chaturvedi <[email protected]>
AuthorDate: Thu Jul 24 09:53:50 2025 -0700

    [timeseries] Adding error banner for timeseries error handling in 
Controller UI (#16406)
    
    Co-authored-by: Shaurya Chaturvedi <[email protected]>
---
 .../app/components/Query/TimeseriesQueryPage.tsx   | 21 +++++++++++-----
 .../apache/pinot/tsdb/m3ql/parser/Tokenizer.java   | 29 ++++++++++++++++++++++
 2 files changed, 44 insertions(+), 6 deletions(-)

diff --git 
a/pinot-controller/src/main/resources/app/components/Query/TimeseriesQueryPage.tsx
 
b/pinot-controller/src/main/resources/app/components/Query/TimeseriesQueryPage.tsx
index 03922a0bc2e..964945813be 100644
--- 
a/pinot-controller/src/main/resources/app/components/Query/TimeseriesQueryPage.tsx
+++ 
b/pinot-controller/src/main/resources/app/components/Query/TimeseriesQueryPage.tsx
@@ -51,6 +51,7 @@ import { MAX_SERIES_LIMIT } from '../../utils/ChartConstants';
 
 // Define proper types
 interface TimeseriesQueryResponse {
+  error: string;
   data: {
     resultType: string;
     result: Array<{
@@ -335,6 +336,14 @@ const TimeseriesQueryPage = () => {
     setRawData(parsedData);
     setRawOutput(JSON.stringify(parsedData, null, 2));
 
+    // Check if this is an error response
+    if (parsedData.error != null && parsedData.error !== '') {
+      setError(parsedData.error);
+      setChartSeries([]);
+      setTruncatedChartSeries([]);
+      return;
+    }
+
     // Parse timeseries data for chart and stats
     if (isPrometheusFormat(parsedData)) {
       const series = parseTimeseriesResponse(parsedData);
@@ -498,12 +507,6 @@ const TimeseriesQueryPage = () => {
           </Grid>
         </Grid>
 
-        {error && (
-          <Alert severity="error" className={classes.sqlError}>
-            {error}
-          </Alert>
-        )}
-
         {rawOutput && (
           <Grid item xs style={{ backgroundColor: 'white' }}>
                          <ViewToggle
@@ -515,6 +518,12 @@ const TimeseriesQueryPage = () => {
                classes={classes}
              />
 
+              {error && (
+                <Alert severity="error" className={classes.sqlError}>
+                  {error}
+                </Alert>
+              )}
+
                                     {viewType === 'chart' && (
               <SimpleAccordion
                 headerTitle="Timeseries Chart & Statistics"
diff --git 
a/pinot-plugins/pinot-timeseries-lang/pinot-timeseries-m3ql/src/main/java/org/apache/pinot/tsdb/m3ql/parser/Tokenizer.java
 
b/pinot-plugins/pinot-timeseries-lang/pinot-timeseries-m3ql/src/main/java/org/apache/pinot/tsdb/m3ql/parser/Tokenizer.java
index fec5db4e1fc..75ec610a771 100644
--- 
a/pinot-plugins/pinot-timeseries-lang/pinot-timeseries-m3ql/src/main/java/org/apache/pinot/tsdb/m3ql/parser/Tokenizer.java
+++ 
b/pinot-plugins/pinot-timeseries-lang/pinot-timeseries-m3ql/src/main/java/org/apache/pinot/tsdb/m3ql/parser/Tokenizer.java
@@ -37,6 +37,7 @@ public class Tokenizer {
     String[] pipelines = _query.split("\\|");
     List<List<String>> result = new ArrayList<>();
     for (String pipeline : pipelines) {
+      Preconditions.checkState(isValidToken(pipeline), String.format("Invalid 
token: %s", pipeline));
       String command = pipeline.trim().substring(0, pipeline.indexOf("{"));
       if (command.equals("fetch")) {
         result.add(consumeFetch(pipeline.trim()));
@@ -87,4 +88,32 @@ public class Tokenizer {
     }
     return result;
   }
+
+  public static boolean isValidToken(String input) {
+    if (input == null || input.length() < 2) {
+      return false;
+    }
+    int openIndex = -1;
+    int closeIndex = -1;
+    // Find first '{' from the front
+    for (int i = 0; i < input.length(); i++) {
+      if (input.charAt(i) == '{') {
+        openIndex = i;
+        break;
+      }
+    }
+    // If no '{' found
+    if (openIndex == -1) {
+      return false;
+    }
+    // Find first '}' from the back
+    for (int i = input.length() - 1; i > openIndex; i--) {
+      if (input.charAt(i) == '}') {
+        closeIndex = i;
+        break;
+      }
+    }
+    // Valid only if '}' found after '{'
+    return closeIndex != -1;
+  }
 }


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

Reply via email to