是否可以在Boost.Proto中构建和增量评估/突变表达树

Is it possible to build and incrementally evaluate/mutate expression trees in Boost.Proto?

本文关键字:评估 突变 Boost Proto 构建 是否      更新时间:2023-10-16

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

在我的具体案例中,我试图评估是否可以重复重写一些遗留代码:

  1. 生成sql
  2. 查询数据库
  3. 使用结果生成新的sql查询
  4. 再次查询数据库。。。(依此类推)

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

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

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

我已经浏览了Boost.Proto文档,但我不确定它是否适用于这种情况,在这种情况下,我需要从外部评估子树,并用结果替换它,直到整个树被简化为一个查询。

编辑:

假设我有以下表格:

对象id |名称

属性链接对象|属性

属性id | parentid | name | value

我的查询是作为一个自定义的"查询"对象来的——一个包含多个AND、OR子句的(二进制)树。

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

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

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

也许表达式树看起来像:

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

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

例如PostgreSQL:

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

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

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

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

由此产生的查询可能看起来像:

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

  2. (最终查询)---


    get_roots AS(SELECT*FROM属性WHERE(id=20或id=21)),
    get_childs AS(SELECT*FROM get_roots,attributes WHERE attributes.parentid=get_roots.id),
    get_grandchilds AS(选择*FROM get_childs,属性WHERE attributes.parentid=get_childs.id)

    从get_roots选择*UNION
    从get_childs选择*UNION
    从get_grandchilds 中选择*

(假设这里的属性只有三个级别,它可能会被重写为递归CTE)

我想这可能是可能的,但工作量会不会太大?有一组有限的查询,这里给出的查询是最复杂的。

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