Skip to content
导航栏

当出现两个 hasMany 从表关系时,无法正常获取数据。

问题

当有一个模型是ddic.model定义如下。它有一些字段,并且关联了两个关联表,主表与两个子表都是一对多的关系。

json
{
  "name": "::Model",
  "table": { "name": "ddic_model", "comment": "业务模型" },
  "columns": [
    {
      "name": "id",
      "type": "ID",
      "label": "ID",
      "comment": "表名"
    },
    {
      "label": "命名空间",
      "name": "namespace",
      "type": "string",
      "length": 80,
      "default": "app",
      "nullable": false
    }
  ],
  "relations": {
    "col": {
      "label": "字段列表",
      "type": "hasMany",
      "model": "ddic.model.column",
      "key": "model_id",
      "foreign": "id"
    },
    "rel": {
      "label": "关联关系",
      "type": "hasMany",
      "model": "ddic.model.relation",
      "key": "model_id",
      "foreign": "id"
    }
  },
  "option": {}
}

模型定义了两个hasMany关联。

json
{
  "relations": {
    "col": {
      "label": "字段列表",
      "type": "hasMany",
      "model": "ddic.model.column",
      "key": "model_id",
      "foreign": "id"
    },
    "rel": {
      "label": "关联关系",
      "type": "hasMany",
      "model": "ddic.model.relation",
      "key": "model_id",
      "foreign": "id"
    }
  }
}

当调用 models.ddic.model.Find id,::{"withs":{"rel":{},"col":{}}},无法获取到预期的数据。只能读取到rel的数据。无法读取到col的数据。

查询条件::{"withs":{"rel":{},"col":{}}},按程序的处理逻辑是,把rel的结果作为col的前堤。相当于下面查询条件。本来是平行的关系,结果变成了嵌套逻辑,::{"withs":{"rel":{"col":{}}}

go
// yao-app-sources/gou/query.stack.go:124
// Run 执行查询栈
func (stack *QueryStack) Run() []maps.MapStrAny {
	res := [][]maps.MapStrAny{}
	for i, qb := range stack.Builders {
		param := stack.Params[i]
		switch param.Relation.Type {
		case "hasMany":
			stack.runHasMany(&res, qb, param)
			break
		default:
			stack.run(&res, qb, param)
		}
	}

	if len(res) < 0 {
		return nil
	}
	return res[0]
}

// yao-app-sources/gou/query.stack.go:235
func (stack *QueryStack) runHasMany(res *[][]maps.MapStrAny, builder QueryStackBuilder, param QueryStackParam) {

	// 获取上次查询结果,拼接结果集ID
	rel := stack.Relation()
	foreignIDs := []interface{}{}
	prevRows := (*res)[len(*res)-1] //以上一次的结果集作为这一次查询的条件。这里逻辑出错。
	for _, row := range prevRows {
		id := row.Get(rel.Foreign)
		foreignIDs = append(foreignIDs, id)
	}
....

结论

withs条件不支持两个同一级别的的hasMany从表。从源代码来看,如果是两个hasmany,就会出问题。

问题重现

sh

git clone git@github.com:wwsheng009/yao-admin.git

cd yao-admin/ && git checkout hasMany-bug

cp .env.sample .env

yao migrate --reset

yao studio run model.cmd.CreateFromFile

yao studio run ddic.loader.LoadModelFromFile
# 正常
yao run models.ddic.model.Find  9 '::{"withs":{"col":{}}}'
# 正常
yao run models.ddic.model.Find  9 '::{"withs":{"rel":{}}}'
# 不正常
yao run models.ddic.model.Find  9 '::{"withs":{"rel":{},"col":{}}}'
# 不正常
yao run models.ddic.model.Find  9 '::{"withs":{"col":{},"rel":{}}}'