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

JackieTien97 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb-extras.git


The following commit(s) were added to refs/heads/master by this push:
     new ca2d615  support object-form template variable queries (#128)
ca2d615 is described below

commit ca2d615f767cd619bfa6e3f8ce326a9a89dd72fd
Author: Zhao Xinqi <[email protected]>
AuthorDate: Tue Aug 25 17:06:11 2026 +0800

    support object-form template variable queries (#128)
---
 connectors/grafana-plugin/src/datasource.test.ts | 39 ++++++++++++++++++++++++
 connectors/grafana-plugin/src/datasource.ts      | 24 +++++++++++++--
 2 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/connectors/grafana-plugin/src/datasource.test.ts 
b/connectors/grafana-plugin/src/datasource.test.ts
index 61ee77d..6d32cfa 100644
--- a/connectors/grafana-plugin/src/datasource.test.ts
+++ b/connectors/grafana-plugin/src/datasource.test.ts
@@ -237,4 +237,43 @@ describe('DataSource', () => {
       expect(result.groupBy?.step).toBe('1h');
     });
   });
+
+  describe('metricFindQuery', () => {
+    it('extracts and expands a standard variable query object', async () => {
+      const scopedVars: ScopedVars = { cluster: { text: 'cluster-a', value: 
'cluster-a' } };
+      const sql =
+        "table:metrics_validation:SELECT DISTINCT instance FROM sys_cpu_cores 
WHERE cluster IN (${cluster:sqlstring})";
+      const expandedSql =
+        "table:metrics_validation:SELECT DISTINCT instance FROM sys_cpu_cores 
WHERE cluster IN ('cluster-a')";
+      const getVariablesResult = jest.spyOn(ds, 
'getVariablesResult').mockResolvedValue([]);
+      mockReplace.mockReturnValue(expandedSql);
+
+      await ds.metricFindQuery({ query: sql, refId: 'StandardVariableQuery' }, 
{ scopedVars });
+
+      expect(mockReplace).toHaveBeenCalledWith(sql, scopedVars);
+      expect(getVariablesResult).toHaveBeenCalledWith(expandedSql);
+    });
+
+    it('keeps legacy string variable queries compatible', async () => {
+      const sql = 'show child paths root.sg';
+      const getVariablesResult = jest.spyOn(ds, 
'getVariablesResult').mockResolvedValue([]);
+      mockReplace.mockReturnValue(sql);
+
+      await ds.metricFindQuery(sql);
+
+      expect(mockReplace).toHaveBeenCalledWith(sql, undefined);
+      expect(getVariablesResult).toHaveBeenCalledWith(sql);
+    });
+
+    it('rejects variable query objects without a string query field', async () 
=> {
+      const getVariablesResult = jest.spyOn(ds, 
'getVariablesResult').mockResolvedValue([]);
+
+      await expect(ds.metricFindQuery({ refId: 'StandardVariableQuery' 
})).rejects.toThrow(
+        'Variable query must be a string or an object with a string query 
field'
+      );
+
+      expect(mockReplace).not.toHaveBeenCalled();
+      expect(getVariablesResult).not.toHaveBeenCalled();
+    });
+  });
 });
diff --git a/connectors/grafana-plugin/src/datasource.ts 
b/connectors/grafana-plugin/src/datasource.ts
index 319f804..0e27c05 100644
--- a/connectors/grafana-plugin/src/datasource.ts
+++ b/connectors/grafana-plugin/src/datasource.ts
@@ -20,6 +20,21 @@ import { IoTDBOptions, IoTDBQuery } from './types';
 import { toMetricFindValue } from './functions';
 import { DataSourceWithBackend, getTemplateSrv } from '@grafana/runtime';
 
+function variableQueryText(query: unknown): string | undefined {
+  if (typeof query === 'string') {
+    return query;
+  }
+
+  if (query && typeof query === 'object' && 'query' in query) {
+    const queryText = (query as { query?: unknown }).query;
+    if (typeof queryText === 'string') {
+      return queryText;
+    }
+  }
+
+  return undefined;
+}
+
 export class DataSource extends DataSourceWithBackend<IoTDBQuery, 
IoTDBOptions> {
   username: string;
   url: string;
@@ -138,8 +153,13 @@ export class DataSource extends 
DataSourceWithBackend<IoTDBQuery, IoTDBOptions>
   }
 
   metricFindQuery(query: any, options?: any): Promise<MetricFindValue[]> {
-    query = getTemplateSrv().replace(query, options.scopedVars);
-    return this.getVariablesResult(query);
+    const queryText = variableQueryText(query);
+    if (queryText === undefined) {
+      return Promise.reject(new Error('Variable query must be a string or an 
object with a string query field'));
+    }
+
+    const expandedQuery = getTemplateSrv().replace(queryText, 
options?.scopedVars);
+    return this.getVariablesResult(expandedQuery);
   }
 
   nodeQuery(query: any, options?: any): Promise<MetricFindValue[]> {

Reply via email to