Implement substitute methods of atoms
Querybuilder objects are immutable and lack helpers to easily obtain variants of them. One such helper would be the substitute
method, that take an Atom-to-Atom mapping as unique argument and returns a variant of the given object in which the sub-elements that are key of the mapping have been replaced by the corresponding value.
For instance:
from querybuilder.queries.dql import Select
from querybuilder.queries.algebra.columns import make_column
c1 = make_column(1)
c2 = make_column(2)
q_orig = Select([c1, c2])
print(str(q_orig))
q_subst = q_orig.substitute({c1: make_column(1.0), c2: make_column(2.0)})
print(str(q_subst))
would give
SELECT 1, 2
SELECT 1.0, 2.0
The substitution is non-recursive, e.g.,
q_swap = q_orig.substitute({c1: c2, c2: c1})
print(str(q_swap))
would give
SELECT 2, 1
This non-recursivity could be use to protect some parts of the objects.
qo = Select([c1, c2], aliases={0: "a", 1: "b"})
qs = qo.alias("s")
qt = qo.alias("t")
qu = qs.select().union_all(qt.select())
qv = qu.substitute({qs: qs, c1: c2, c2: c1})
print(str(qv))
would give
SELECT a, b FROM (SELECT 1 AS a, 2 AS b) AS s UNION ALL SELECT a, b FROM (SELECT 2 AS a, 1 AS b) AS t