gf icon indicating copy to clipboard operation
gf copied to clipboard

feature(database/gdb): Implement Row-Level Multi-Tenancy Support

Open LanceAdd opened this issue 1 month ago • 0 comments

gdb目前支持分库分表级别的多租户,补充一个行级多租户的实现

主要特性:

  1. 租户上下文管理

    • 提供WithTenantIdFieldWithTenantIdValue函数用于设置租户字段名和值到上下文中
    • 默认实现DefaultGetTenantIdFieldValue从上下文中获取租户信息
  2. 模型级租户支持

    • 在Model中添加Tenant()方法启用多租户功能
    • 支持通过UnTenant()方法禁用多租户功能
    • TenantOption可配置选项包括:
      • Enable: 控制是否启用租户功能
      • PropagateToJoins: 控制是否将租户条件应用于连接表
      • GetTenantIdFieldValueFunc: 自定义获取租户ID字段和值的函数
  3. 智能租户条件生成

    • 自动识别单表、JOIN表和逗号分隔的多表查询
    • 根据表结构检查租户字段是否存在
    • 支持多种租户值类型:
      • 基本类型(BaseType):使用等值匹配
      • 数组或切片类型(ArrayOrSliceType):使用IN条件
      • 空值类型(NullType):使用IS NULL条件
  4. 无缝集成

    • 租户条件会自动附加到所有查询语句中
    • 与现有的软删除、WHERE条件等功能协同工作
    • 不影响原有API使用方式
  5. 注意事项

    • WithTenantIdField设置的tenantIdField在构建过程中会检查对应的表字段中有没有这个字段,所以最好是多表的租户字段都相同,如果有需要我也可以加个配置让大家在不同表映射成不同的字段,看大家有没有需求

使用示例:

// 启用租户功能
ctx := WithTenantIdField(context.Background(), "tenant_id")
ctx = WithTenantIdValue(ctx, 1)

// 查询时自动添加租户条件
db.Model("user").Ctx(ctx).Tenant().All()

// 对于JOIN查询,可选择是否传播到连接表
db.Model("user u"). 
    LeftJoin("order o", "u.id=o.user_id").
    Ctx(ctx).
    Tenant(TenantOption{
        Enable: true,
        PropagateToJoins: true,
    }).
    All()

sql

SELECT * FROM user WHERE tenant_id = 1

SELECT * FROM user u LEFT JOIN order o ON u.id=o.user_id WHERE u.tenant_id = 1 AND o.tenant_id = 1

LanceAdd avatar Nov 25 '25 06:11 LanceAdd