Domanda

Is it possible to extract parts of a Boost.Proto expression tree, evaluate them individually (externally), and then mutate the expression tree, replacing the extracted parts with a result?

In my specific case, I'm trying to evaluate if I could rewrite some legacy code that repeatedly:

  1. generates sql
  2. queries a database
  3. uses the result to generate a new sql query
  4. queries the database again ... (and so on)

What I was hoping to do, was to: 1. Generate a single, large expression tree 2. Get the SQL from the expression tree. This consists of: b. visit the tree and check for sub-queries that must be evaluated before the resulting, single sql can be generated c. if there are sub-queries, create the sql and return as a string, evaluate the sql externally, and mutate the tree, replacing the sub-queries with the results

(also, I'd like to identify identical sub-queries, and evaluate them only once if it is possible)

Is this possible to do? Will it require code that is hard to understand/learn?

I've skimmed the Boost.Proto documentation, but I'm not sure if it is intended for this scenario where I need to externally evaluate subtrees, and replace it with a result until the whole tree is reduced to a single query.

EDIT:

Lets say I have the following tables:

objects id | name

attribute_link objectid | attributeid

attributes id | parentid | name | value

My queries come in as a custom "query" object -- a (binary) tree with multiple AND,OR clauses.

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

This translates to: get the attribute(s) for object 10 where the attribute's name is "name". Notice the parentid field, which means that the attribute.name we are looking for can be nested, and not directly linked to our object.

What I need to do is: 1. Translate this into an expression tree with enough information 2. Send this tree to the db layer 3. Process the tree (sometimes in multiple stages) as explained above

Perhaps the expression tree would look something like:

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

There are multiple databases where the SQL syntax differs, which is why I want to do it this way. Therefore, I need to be able to override some of the processing steps based on the database.

For e.g. PostgreSQL :

  1. the processing would first recognize the find_attributes node, and know that we are searching for attributes

  2. looking further, the attribute needs to be linked to object.id = 10, we generate and run a query right away to get all attributes with object.id = 10, and replace the object_id = 10 node in the expression tree with the actual attribute ids (object_id = 10) => (attribute_id = (20 OR 21)).

  3. then, we find the attribute_name node and since attributes are nested, we need to find all the attribute rows that have name = "name" or "name2"

  4. as an (optional) optimization step, since there are millions of attributes, we need to merge the attribute_id and attribute_name nodes into a single query

The resulting queries could look something like:

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

  2. (final query) ---

    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

(assuming the attributes are only three levels deep here, it might be rewritten as a recursive CTE)

I guess it might be possible, but would it be too much work? There are a limited set of queries, and the one presented here is the most complicated.

È stato utile?

Soluzione

Proto tree structure is set at compile-time and thus non mutable. Usually what you do is regenerate a new tree with the elements you need. This can be trivially done as a proto transform takign a tree and returning a new tree.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top