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 queryCapabilities unconditionally 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 typed RAW_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

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 10, 2026 5:16pm

Request Review

@os-zhuang
os-zhuang merged commit c1698df into main Jun 10, 2026
1 of 2 checks passed
@os-zhuang
os-zhuang deleted the fix/analytics-memory-driver-fallback branch June 10, 2026 17:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant