1

是否可以提取 Boost.Proto 表达式树的部分,单独(外部)评估它们,然后改变表达式树,用结果替换提取的部分?

在我的具体情况下,我正在尝试评估是否可以重复重写一些遗留代码:

  1. 生成sql
  2. 查询数据库
  3. 使用结果生成新的 sql 查询
  4. 再次查询数据库...(等等)

我希望做的是: 1. 生成单个大型表达式树 2. 从表达式树中获取 SQL。这包括: b. 访问树并检查在生成单个 sql 之前必须评估的子查询 c.如果有子查询,则创建 sql 并以字符串形式返回,在外部评估 sql,然后改变树,用结果替换子查询

(另外,我想识别相同的子查询,如果可能的话,只评估一次)

这可能吗?它是否需要难以理解/学习的代码?

我浏览了 Boost.Proto 文档,但我不确定它是否适用于我需要从外部评估子树并用结果替换它的场景,直到整个树减少为单个查询。

编辑:

可以说我有以下表格:

对象 ID | 姓名

属性链接对象ID | 属性id

属性 ID | 父母身份 | 姓名 | 价值

我的查询以自定义“查询”对象的形式出现——具有多个 AND、OR 子句的(二进制)树。

示例:query1 = object.id=10 OR (attribute.name = "name" OR attribute.name = "name2")

这转换为:获取对象 10 的属性,其中属性的名称是“名称”。注意 parentid 字段,这意味着我们要查找的 attribute.name可以嵌套,而不是直接链接到我们的 object

我需要做的是: 1. 将其转换为具有足够信息的表达式树 2. 将此树发送到 db 层 3. 如上所述处理树(有时分多个阶段)

也许表达式树看起来像:

find_attributes(object_id = 10 AND attribute_name = ("name" OR "name2"))

有多个数据库的 SQL 语法不同,这就是我想这样做的原因。因此,我需要能够覆盖一些基于数据库的处理步骤。

例如 PostgreSQL:

  1. 处理将首先识别 find_attributes 节点,并知道我们正在搜索属性

  2. 进一步看,属性需要链接到object.id = 10,我们立即生成并运行查询以获取object.id = 10的所有属性,并将表达式树中的object_id = 10节点替换为实际属性ids (object_id = 10) => (attribute_id = (20 OR 21))。

  3. 然后,我们找到attribute_name节点,由于属性是嵌套的,我们需要找到所有具有name =“name”或“name2”的属性行

  4. 作为一个(可选的)优化步骤,由于有数百万个属性,我们需要将 attribute_id 和 attribute_name 节点合并到一个查询中

生成的查询可能类似于:

  1. (find attributeids) SELECT id FROM attributes WHERE objectid = 10)

  2. (最终查询)---

    WITH
    get_roots AS (SELECT * FROM attributes WHERE (id=20 OR id=21)),
    get_childs AS (SELECT * FROM get_roots, attributes WHERE attributes.parentid = get_roots.id),
    get_grandchilds AS (SELECT * FROM get_childs, attributes WHERE attributes .parentid = get_childs.id)

    SELECT * FROM get_roots UNION
    SELECT * FROM get_childs UNION
    SELECT * FROM get_grandchilds

(假设这里的属性只有三层深,可能会被重写为递归CTE)

我想这可能是可能的,但它会不会工作太多?有一组有限的查询,这里介绍的查询是最复杂的。

4

1 回答 1

1

原型树结构是在编译时设置的,因此是不可变的。通常你所做的是用你需要的元素重新生成一棵新树。这可以简单地作为一个原型转换来完成一棵树并返回一棵新树。

于 2013-08-22T17:58:01.997 回答