diff --git a/public/app/features/expressions/components/SqlExpr.test.tsx b/public/app/features/expressions/components/SqlExpr.test.tsx
new file mode 100644
index 00000000000..20cd0b8d85f
--- /dev/null
+++ b/public/app/features/expressions/components/SqlExpr.test.tsx
@@ -0,0 +1,50 @@
+import { render } from '@testing-library/react';
+
+import { ExpressionQuery } from '../types';
+
+import { SqlExpr } from './SqlExpr';
+
+jest.mock('@grafana/ui', () => ({
+ ...jest.requireActual('@grafana/ui'),
+ useStyles2: jest.fn().mockImplementation(() => ({})),
+}));
+
+jest.mock('@grafana/plugin-ui', () => ({
+ SQLEditor: () =>
SQL Editor Mock
,
+}));
+
+describe('SqlExpr', () => {
+ it('initializes new expressions with default query', () => {
+ const onChange = jest.fn();
+ const refIds = [{ value: 'A' }];
+ const query = { refId: 'expr1', type: 'sql', expression: '' } as ExpressionQuery;
+
+ render();
+
+ // Verify onChange was called
+ expect(onChange).toHaveBeenCalled();
+
+ // Verify essential SQL structure without exact string matching
+ const updatedQuery = onChange.mock.calls[0][0];
+ expect(updatedQuery.expression.toUpperCase()).toContain('SELECT');
+ });
+
+ it('preserves existing expressions when mounted', () => {
+ const onChange = jest.fn();
+ const refIds = [{ value: 'A' }];
+ const existingExpression = 'SELECT 1 AS foo';
+ const query = { refId: 'expr1', type: 'sql', expression: existingExpression } as ExpressionQuery;
+
+ render();
+
+ // Check if onChange was called
+ if (onChange.mock.calls.length > 0) {
+ // If called, ensure it didn't change the expression value
+ const updatedQuery = onChange.mock.calls[0][0];
+ expect(updatedQuery.expression).toBe(existingExpression);
+ }
+
+ // The SQLEditor should receive the existing expression
+ expect(query.expression).toBe(existingExpression);
+ });
+});
diff --git a/public/app/features/expressions/components/SqlExpr.tsx b/public/app/features/expressions/components/SqlExpr.tsx
index 2d7747c8d17..a9a8d9a45cc 100644
--- a/public/app/features/expressions/components/SqlExpr.tsx
+++ b/public/app/features/expressions/components/SqlExpr.tsx
@@ -60,6 +60,15 @@ LIMIT 10`;
return () => resizeObserver.disconnect();
}, []);
+ useEffect(() => {
+ // Call the onChange method once so we have access to the initial query in consuming components
+ // But only if expression is empty
+ if (!query.expression) {
+ onEditorChange(initialQuery);
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
return (