Skip to content

fix(analytics): fall back to aggregate strategy when the driver can't run SQL - #1701

Merged
os-zhuang merged 1 commit into
mainfrom
fix/analytics-memory-driver-fallback
Jun 10, 2026
Merged

fix(analytics): fall back to aggregate strategy when the driver can't run SQL#1701
os-zhuang merged 1 commit into
mainfrom
fix/analytics-memory-driver-fallback

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

The bug (live on staging)

Every dataset query on staging tenant environments returned rows: [] with HTTP 200 and the compiled SQL attached — all dashboards read "No rows" forever while looking healthy. Even COUNT(*) FROM sys_user and queries against nonexistent tables came back empty (the discriminating probe).

Root cause chain

  1. Staging env kernels run on the in-memory driver, whose execute() logs a warning and returns null for raw SQL (memory-driver.ts:250).
  2. The analytics plugin's raw-SQL auto-bridge silently mapped null[].
  3. The default queryCapabilitiesunconditionally advertise nativeSql: true (the bridge closure always exists), so NativeSQLStrategy was selected on a driver that cannot execute SQL — compiled SQL attached, never executed.

Fix (both layers)

  • Bridge: null/undefined from engine.execute now throws a typedRAW_SQL_UNSUPPORTED error — an empty result is never fabricated.
  • Orchestrator: AnalyticsService.query treats that error as a runtime capability miss and falls back to the next capable strategyObjectQLStrategy over the aggregate bridge (the in-memory driver implements aggregate()), so memory-backed environments now return real numbers. Any other error propagates untouched; with no fallback available the failure is loud and names the skipped strategies.

Test

service-analytics 109 green — 3 new: fallback returns the aggregate rows; non-typed errors propagate without fallback masking; no-fallback case fails loudly (never silent []).

Staging validation follows via the cloud .framework-sha bump.

🤖 Generated with Claude Code

… run SQL
Every dataset query on an in-memory-driver environment returned rows:[] with
HTTP 200 and the compiled SQL attached — dashboards read "No rows" forever
while looking healthy (live staging incident: even COUNT(*) FROM sys_user and
queries against nonexistent tables came back empty).
Root cause chain: InMemoryDriver.execute() returns null for raw SQL; the
analytics plugin's auto-bridge mapped null to [] silently; and the default
queryCapabilities unconditionally advertise nativeSql, so NativeSQLStrategy
was always selected even on drivers that cannot execute SQL.
Fix at both layers:
- the raw-SQL bridge now throws a TYPED error (code RAW_SQL_UNSUPPORTED) when
the engine returns null/undefined — an empty result is never fabricated;
- AnalyticsService.query treats that error as a runtime capability miss and
falls back to the next capable strategy (ObjectQLStrategy over the
aggregate bridge — the in-memory driver implements aggregate()), skipping
the proven-incapable one. Any other error propagates untouched, and when no
fallback exists the failure is loud and names the skipped strategies.
service-analytics: 109 tests green (3 new covering fallback, error
passthrough, and the no-fallback loud failure).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercelBot commented Jun 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJun 10, 2026 5:16pm

Request Review

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@os-zhuang