Skip to content

drivers(turso): 聚合函数名的大小写归一化 local/remote 不一致 —— COUNT 在 remote 编得出、在 local 被拒(同一个 TursoDriver,取决于 url) #6203

Closed

Description

@os-zhuang

从 #5907(聚合函数拒收信封,两面同改)的落点实测中带出。不在该单的信封面内(该单只改拒收的 code/status 与措辞,不动「什么能编译」),按 Prime Directive #10 单独记一笔。

观察类:仓内没有活体发送方,协议门也表达不出这个输入 —— 严重度请分诊时判定。

事实

两个面对聚合函数名的归一化不一样:

  • packages/drivers/driver-turso/src/remote-transport.ts — aggregate() 先 .toLowerCase() 再查自己的编译表;
  • packages/drivers/driver-sql/src/sql-driver.ts — mapAggregateFunc() 拿到什么查什么,不归一化。

TursoDriver 按 url 选面(本地/副本继承 SqlDriver,远程委派 RemoteTransport),于是同一个驱动、同一条查询,答案取决于连接串。在 origin/main @ 80f7dc6a3 实测(一条 aggregations: [{ function, field: 'stage', alias: 'n' }]):

COUNT           REMOTE -> RESOLVED  "SELECT count(\"stage\") AS \"n\" FROM \"deal\""
COUNT           LOCAL  -> THREW     "Unsupported aggregate function: COUNT"

COUNT_DISTINCT  REMOTE -> THREW     "Unsupported aggregate function: count_distinct"   (注意:回显的是归一化后的名字)
COUNT_DISTINCT  LOCAL  -> THREW     "Unsupported aggregate function: COUNT_DISTINCT"

Median          REMOTE -> THREW     "Unsupported aggregate function: median"
Median          LOCAL  -> THREW     "Unsupported aggregate function: Median"

第一行是分叉本身:一个面返回行,另一个面抛错。后两行是同一归一化的影子 —— 拒收消息回显的名字不是调用方写的那个。

为什么记一笔

为什么今天没人撞上(=> 观察类)

  • 全仓搜 function: 'COUNT' / 'SUM' / 'AVG' / 'MIN' / 'MAX'(大写)零命中,没有活体发送方;
  • 经 REST/协议门进来的查询过 AggregationNodeSchema,大写拼写在到达任何驱动之前就被拒;
  • 只有绕过 spec 校验的进程内调用方才够得着。

修法(供分诊,两个方向相反)

  1. 收紧 remote(契约优先,倾向这个):删掉 .toLowerCase(),两面都只认协议声明的小写拼写,COUNT 在两面都落 drivers(sql,turso): Unsupported aggregate function 两面都是裸 Error(code/status 皆 undefined),且三个 spec 已声明的聚合函数无任何 SQL 后端编译 #5907 的第 1 类拒收(INVALID_QUERY / 400,「不是已声明的聚合函数」)。与本仓两次同形先例一致(RemoteTransport.findOne 的未声明 string-id 分支、FilterArray 的第二套编译器,都是删掉后收敛到一种拼写)。代价:任何今天靠大写拼写工作的进程外调用方会开始拿到 400 —— 但那本来就不是协议表达得出的输入。
  2. 放宽 local:给 mapAggregateFunc 也加 .toLowerCase()。两面同样收敛,但方向是把方言固化成第二套事实上的契约,PD#12 明确反对。

已经钉住的部分

#5907 的 PR 在 remote-transport-aggregate-function-refusal.test.ts 里留了一条如实记录现状的用例([filed, not fixed] COUNT still compiles HERE while the local driver refuses it),这样下一个读者是读到它、而不是重新踩一遍;同一 PR 也把两面的拒收分类改为按调用方写的原始拼写判定,免得归一化差异顺着信封扩散(否则 COUNT_DISTINCT 会在 remote 拿 501、在 local 拿 400)。所以本单剩下的只有「什么能编译」这一半。

相关:#5907(带出本单)、#5769(同族 local/remote 叉)、#6188(那三个已声明未实现的函数按 ADR-0049 的去留)。

Activity

  1. added
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    bugSomething isn't working
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Aug 7, 2026
  2. self-assigned this
    on Aug 7, 2026
  3. os-zhuang commented on Aug 7, 2026

    @os-zhuang
    ContributorAuthor

    车道裁决(第三档,带否决窗口)+ 认领

    裁定:方向 1 —— 收紧 remote,删掉 .toLowerCase(),两面只认协议声明的小写拼写;COUNT 在两面统一落 #5907 已落地的第 1 类拒收(INVALID_QUERY / 400,「不是已声明的聚合函数」)。

    这不是新裁决,是三条既有规矩的应用,故不占维护者决策位(可否决):

    • AggregationFunction 是大小写敏感的 z.enum,COUNT 是协议从未声明的拼写——remote 今天多认的是一种方言,PD#12 明确反对在消费端偷偷放宽;
    • 仓内两处同形先例都是删掉宽容侧收敛到一种拼写(RemoteTransport.findOne 的未声明 string-id 分支、FilterArray 的第二套编译器);
    • 方向 2(给 local 也加 .toLowerCase())会把方言固化成第二套事实上的契约,与上一条相反。

    风险已由本单自证可接受:全仓大写拼写零活体发送方,经协议门的查询在到达驱动前就被 AggregationNodeSchema 拒,只有绕过 spec 校验的进程内调用方够得着。


    认领:PM 循环第 11 轮续批(drivers 车道)
    会话:session_01WyvqvKMG6asi9aXjKE6xtx
    分支:claude/issue-6203-aggregate-case-normalization
    Worktree:objectstack-issue-6203
    文件面:driver-turso/src/remote-transport.ts(aggregate 归一化处)+ remote-transport-aggregate-function-refusal.test.ts(把 #5907 留的 [filed, not fixed] 现状用例翻面)+ changeset
    前置已清:#6204(#5907 信封)与 #6210(#6075 签名)均已 MERGED。并行:#5234 在飞(driver-sql applyLike 区 + service-analytics),零重叠。


    Generated by Claude Code

  4. os-zhuang commented on Aug 7, 2026

    @os-zhuang
    ContributorAuthor

    复核:ACCEPT → PR #6312(PM 实测复核):

    已转 ready + auto-merge,CI 绿即入队。


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingpm:dispatchedDispatched to a dev agent by /pm-dispatch

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions