#4842·gf

database/gdb: 类型自动探测用 "int" 子串匹配,把 point/interval 等非整数类型判成整数

Author: lingcoderCreated Aug 11, 2026Updated Aug 11, 2026

问题

database/gdb/gdb_core_structure.go:360,驱动未显式列举的类型会落到 Core 的 自动探测分支,那里用子串匹配猜类型:

go
case strings.Contains(typeName, "int"):
    if gstr.ContainsI(fieldType, "unsigned") {
        return LocalTypeUint, nil
    }
    return LocalTypeInt, nil

凡是类型名里含 int 的都被当成整数。PostgreSQL / openGauss 上至少这些不是 整数却会命中:

point(p-o-int)、intervaltintervalint4rangeint8rangeint4multirangeint8multirange,以及它们的数组形式。

后果是值被转成 0:

point    存 (1.5,2.5)   读回 0
interval 存 '2 days'    读回 0

数据本身没问题,是读取时的类型判定错了。

佐证

  • 该分支的匹配顺序是 text/char → float/double/numeric → bool → binary/blob → int → time → date,所以 point 会先命中 int,走不到后面。
  • 目前各驱动是靠在自己的 CheckLocalTypeForField逐个列举来绕过它的。 pgsql 那份清单的 13 条 case 全是被报了 bug 之后才补的: bytea 见 #4231 / #4677(由 #4678 修)、numeric[] / decimal[] 见 #4457 (由 #4511 修)。
  • #4840 又补进了 point / interval / range 系列。

影响

清单式绕过只能挡住已经被发现的类型:任何未列举、名字里含 int 的类型仍会被 静默转成 0,而且每个驱动都要各自补一遍。

可能的修法

  • 在 Core 里加一份「已知非整数」的排除清单;
  • 或把子串匹配收紧(按词边界匹配,或改为精确类型名表)。

任一改法都会影响所有驱动,需要评估 dm / oracle / mssql / clickhouse 等本地 难以验证的驱动,所以先开 issue 记录,不直接改。

环境

  • master (41baf1e28)
  • 实测数据库:openGauss 7.0.0-RC1、PostgreSQL 17