Kirill Simonov avatar Kirill Simonov committed 2f13dd7

Refactored embedding/correlation terms to permit outer references in arbitrary expressions.

Comments (0)

Files changed (10)

src/htsql/core/tr/assemble.py

 from ..domain import BooleanDomain
 from .coerce import coerce
 from .flow import (Code, SegmentCode, LiteralCode, FormulaCode, CastCode,
-                   RecordCode, AnnihilatorCode, Unit, ColumnUnit, CompoundUnit)
+                   RecordCode, AnnihilatorCode, Unit, ColumnUnit, CompoundUnit,
+                   CorrelationCode)
 from .term import (PreTerm, Term, UnaryTerm, BinaryTerm, TableTerm,
                    ScalarTerm, FilterTerm, JoinTerm, CorrelationTerm,
                    EmbeddingTerm, ProjectionTerm, OrderTerm, SegmentTerm,
         self.name = None
         self.segment_stack = []
         self.segment = None
+        self.correlations_stack = []
+        self.correlations = {}
+
+    def push_correlations(self, correlations):
+        self.correlations_stack.append(self.correlations)
+        self.correlations = correlations
+
+    def pop_correlations(self):
+        self.correlations = self.correlations_stack.pop()
 
     def push_name(self, name):
         assert isinstance(name, maybe(unicode))
         self.claims_by_broker = None
         self.phrases_by_claim = None
         self.segment_indexes = None
+        self.correlations_stack = []
+        self.correlations = {}
 
     def push_gate(self, is_nullable=None, dispatcher=None, router=None):
         """
         # Call the super `delegate()` to review and forward claims.
         super(AssembleEmbedding, self).delegate()
 
-        # An embedding term adds an embedded term (i.e. a term whose frame
-        # is not attached to the `FROM` list of its parent) to the regular
-        # term tree.  Here, `lkid` belongs to the regular tree and `rkid`
-        # is the embedded (correlation) term.  An embedded term (`rkid`)
-        # contains a join condition connecting it to its regular counterpart
-        # (`lkid`).  Now the tricky part is that `rkid` cannot assign claims
-        # to `lkid` since the latter does not belong to its subtree, and by
-        # the time the embedded frame is assembled, `lkid` is already
-        # translated, so it is too late to request any claims.  Therefore,
-        # it's the parent term which is going to request the claims on
-        # behalf of the correlation term.
-
-        # The embedded term.
-        correlation = self.term.rkid
-        # The join condition is a sequence of equalities: `lop = rop`,
-        # where `lop` is exported from `lkid` and `rop` is exported
-        # from (the child of) `rkid`.
-        for joint in correlation.joints:
-            # Assign the claims from th embedded term to its sibling term;
-            # here `correlation.link` coincides with `lkid`.
-            self.state.schedule(joint.lop, router=correlation.link)
-            # While we are on it, we also assign claims to `rkid` (or rather
-            # the child of `rkid`), although that is something `rkid` could
-            # do for itself.
-            self.state.schedule(joint.rop, dispatcher=correlation)
+        for code in self.term.correlations:
+            self.state.schedule(code, router=self.term.lkid)
 
     def assemble_include(self):
         # Assemble the `FROM` list.
     def assemble_embed(self):
         # Assemble the list of embedded frames.
 
+        correlations = {}
+        for code in self.term.correlations:
+            phrase = self.state.evaluate(code, router=self.term.lkid)
+            correlations[code] = phrase
+        self.state.push_correlations(correlations)
+
         # Set up the dispatch context for the embedded term.  An embedded
         # frame is always considered nullable, although it may not be true
         # in some cases.  In practice, nullability of an embedded frame does
         frame = self.state.assemble(self.term.rkid)
         # Restore the original dispatch context.
         self.state.pop_gate()
+        self.state.pop_correlations()
         # Return a list of subframes embedded to the assembled frame.
         return [frame]
 
 
 class AssembleCorrelation(Assemble):
-    """
-    Assembles a frame for a correlation term.
-    """
 
     adapt(CorrelationTerm)
 
         # Return the `SELECT` list.
         return [phrase]
 
-    def assemble_where(self):
-        # Assemble a `WHERE` clause.
-        # The `WHERE` clause of a correlated frame is a conjunction of
-        # equalities: `lop = rop`, where `rop` belongs to the child of the
-        # correlated frame and `lop` belongs to the sibling frame.
-        # It is tricky to evaluate `lop` because the sibling frame is
-        # not a descendant of the correlated frame.
-        # List of equality phrases.
-        equalities = []
-        # Iterate over `lop = rop` expressions:
-        for joint in self.term.joints:
-            # We cannot dispatch `lop` directly because `link` is not
-            # our descendant and thus, it is not in the dispatch table.
-            # So we temporarily pop the current gate making the parent
-            # gate current -- that puts `link` to the dispatching table.
-            self.state.pop_gate()
-            # Evaluate the left operand against our sibling (`link` coincides
-            # with `lkid` of our parent term).
-            lop = self.state.evaluate(joint.lop, router=self.term.link)
-            # Restore the original dispatching context.
-            self.state.push_gate(is_nullable=True, dispatcher=self.term)
-            # Evaluate the right operand against the child frame.
-            rop = self.state.evaluate(joint.rop, router=self.term.kid)
-            # An individual condition.
-            is_nullable = (lop.is_nullable or rop.is_nullable)
-            signature = IsEqualSig(+1)
-            equality = FormulaPhrase(signature, coerce(BooleanDomain()),
-                                     is_nullable, self.term.expression,
-                                     lop=lop, rop=rop)
-            equalities.append(equality)
-        # Generate and return the clause.
-        condition = None
-        if equalities:
-            is_nullable = any(equality.is_nullable for equality in equalities)
-            condition = FormulaPhrase(AndSig(), coerce(BooleanDomain()),
-                                      is_nullable, self.term.expression,
-                                      ops=equalities)
-        return condition
-
 
 class AssembleSegment(Assemble):
     """
             yield phrase
 
 
+class EvaluateCorrelation(Evaluate):
+
+    adapt(CorrelationCode)
+
+    def __call__(self):
+        assert self.code.code in self.state.correlations
+        # FIXME: is this correct in case of nested correlated subqueries?
+        # FIXME: implement decompose?
+        yield self.state.correlations[self.code.code]
+
+
 class EvaluateFormula(Evaluate):
     """
     Evaluates a formula node.

src/htsql/core/tr/compile.py

 from ..domain import BooleanDomain, IntegerDomain
 from .error import CompileError
 from .coerce import coerce
-from .signature import (IsNullSig, AndSig, CompareSig,
+from .signature import (IsNullSig, IsEqualSig, AndSig, CompareSig,
                         SortDirectionSig, RowNumberSig)
 from .flow import (Expression, QueryExpr, SegmentCode, Code, LiteralCode,
                    FormulaCode, Flow, RootFlow, ScalarFlow, TableFlow,
                    QuotientFlow, ComplementFlow, MonikerFlow, ForkedFlow,
                    LinkedFlow, ClippedFlow, FilteredFlow, OrderedFlow,
                    Unit, ScalarUnit, ColumnUnit, AggregateUnit, CorrelatedUnit,
-                   KernelUnit, CoveringUnit)
+                   KernelUnit, CoveringUnit, CorrelationCode)
 from .term import (Term, ScalarTerm, TableTerm, FilterTerm, JoinTerm,
                    EmbeddingTerm, CorrelationTerm, ProjectionTerm, OrderTerm,
                    WrapperTerm, PermanentTerm, SegmentTerm, QueryTerm, Joint)
         # Make sure that the unit term could export tie conditions.
         unit_term = self.inject_joints(unit_term, joints)
         # Connect the plural term to the unit term.
+        correlations = []
+        filters = []
+        for lop, rop in joints:
+            correlations.append(lop)
+            lop = CorrelationCode(lop)
+            filter = FormulaCode(IsEqualSig(+1), coerce(BooleanDomain()),
+                                 self.flow.binding, lop=lop, rop=rop)
+            filters.append(filter)
+        if len(filters) == 0:
+            filter = None
+        elif len(filters) == 1:
+            [filter] = filters
+        else:
+            filter = FormulaCode(AndSig(), coerce(BooleanDomain()),
+                                 self.flow.binding, ops=filters)
+        if filter is not None:
+            plural_term = FilterTerm(self.state.tag(), plural_term, filter,
+                                     plural_term.flow, plural_term.baseline,
+                                     plural_term.routes.copy())
         plural_term = CorrelationTerm(self.state.tag(), plural_term,
-                                      unit_term, joints, plural_term.flow,
-                                      plural_term.baseline, plural_term.routes)
+                                      plural_term.flow, plural_term.baseline,
+                                      plural_term.routes.copy())
         # Implant the correlation term into the term tree.
         routes = unit_term.routes.copy()
         routes[self.unit] = plural_term.tag
         unit_term = EmbeddingTerm(self.state.tag(), unit_term, plural_term,
+                                  correlations,
                                   unit_term.flow, unit_term.baseline, routes)
         # If we attached the unit directly to the main term, we are done.
         if is_native:

src/htsql/core/tr/flow.py

         return (self.code, self.flow)
 
 
+class CorrelationCode(Code):
+
+    def __init__(self, code):
+        super(CorrelationCode, self).__init__(code.domain, code.binding)
+        self.code = code
+
+    def __basis__(self):
+        return (self.code,)
+
+

src/htsql/core/tr/term.py

 
     """
 
-    def __init__(self, tag, lkid, rkid, flow, baseline, routes):
+    def __init__(self, tag, lkid, rkid, correlations, flow, baseline, routes):
         # Verify that the right child is a correlation term and the left
         # child is its link term.
-        assert isinstance(rkid, CorrelationTerm) and rkid.link is lkid
+        assert isinstance(correlations, listof(Code))
         super(EmbeddingTerm, self).__init__(tag, lkid, rkid,
                                             flow, baseline, routes)
+        self.correlations = correlations
 
     def __str__(self):
         # Display:
 class CorrelationTerm(UnaryTerm):
     """
     Represents a correlation term.
-
-    A correlation term connects the child term with a *link* term using
-    the given joint condition.  Note that the link term is not a part
-    of the sub-tree under the correlation term.
-
-    A correlation term must always be embedded into the term tree with
-    a :class:`EmbeddingTerm` instance.  The left child of the embedding
-    term must coincide with the link term.
-
-    `kid` (:class:`Term`)
-        The operand of the correlation condition.
-
-    `link` (:class:`Term`)
-        The term to link to.
-
-    `joints` (a list of pairs of :class:`htsql.core.tr.flow.Code`)
-        A list of pairs `(lop, rop)` that establish join conditions
-        of the form `lop = rop`.
     """
 
-    def __init__(self, tag, kid, link, joints, flow, baseline, routes):
-        assert isinstance(link, Term)
-        assert isinstance(joints, listof(Joint))
+    def __init__(self, tag, kid, flow, baseline, routes):
         super(CorrelationTerm, self).__init__(tag, kid,
                                               flow, baseline, routes)
-        self.link = link
-        self.joints = joints
-
-    def __str__(self):
-        # Display:
-        #   (<kid> | <lop>=<rop>, ...)
-        conditions = ", ".join("%s=%s" % (joint.lop, joint.rop)
-                               for joint in self.joints)
-        if conditions:
-            conditions = " | %s" % conditions
-        return "(%s%s)" % (self.kid, conditions)
 
 
 class ProjectionTerm(UnaryTerm):

test/input/translation.yaml

     - uri: /{count(department),count(department?exists(course))}
       ifndef: mssql # MSSQL does not allow an aggregate to contain
                     # an EXISTS subquery.
+    - uri: /school{code, campus, exists(department?count(course)>20),
+                                 exists(program?count(student)>10)}
+    - uri: /school?exists({campus, exists(department?count(course)>20)}
+                          -> school{campus, exists(program?count(student)>10)})
     - uri: /department{code,count(course{credits=3})}
     - uri: /department{code,count(course?credits=3)}
     - uri: /school{code,count(department.course{credits=3})}

test/output/mssql.yaml

                                              FROM [ad].[course] AS [course]
                                              WHERE ([department].[code] = [course].[department_code])
                                                    AND (1 <> 0))) AS [department_2]
+          - uri: /school{code, campus, exists(department?count(course)>20), exists(program?count(student)>10)}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            - [Vary, Accept]
+            body: |2
+               | school                                                                                  |
+               +------+--------+-------------------------------------+-----------------------------------+
+               | code | campus | exists(department?count(course)>20) | exists(program?count(student)>10) |
+              -+------+--------+-------------------------------------+-----------------------------------+-
+               | art  | old    | false                               | true                              |
+               | bus  | south  | false                               | true                              |
+               | edu  | old    | false                               | true                              |
+               | eng  | north  | true                                | true                              |
+               | la   | old    | true                                | true                              |
+               | mus  | south  | false                               | false                             |
+               | ns   | old    | true                                | true                              |
+               | ph   |        | false                               | true                              |
+               | sc   |        | false                               | false                             |
+
+               ----
+               /school{code,campus,exists(department?count(course)>20),exists(program?count(student)>10)}
+               SELECT [school].[code],
+                      [school].[campus],
+                      (CASE WHEN EXISTS(SELECT 1
+                                        FROM [ad].[department]
+                                             LEFT OUTER JOIN (SELECT COUNT(1) AS [count],
+                                                                     [course].[department_code]
+                                                              FROM [ad].[course]
+                                                              GROUP BY [course].[department_code]) AS [course]
+                                                             ON ([department].[code] = [course].[department_code])
+                                        WHERE ([school].[code] = [department].[school_code])
+                                              AND (1 <> 0)
+                                              AND (COALESCE([course].[count], 0) > 20)) THEN 1 ELSE 0 END),
+                      (CASE WHEN EXISTS(SELECT 1
+                                        FROM [ad].[program]
+                                             LEFT OUTER JOIN (SELECT COUNT(1) AS [count],
+                                                                     [student].[school_code],
+                                                                     [student].[program_code]
+                                                              FROM [ed].[student]
+                                                              GROUP BY [student].[school_code], [student].[program_code]) AS [student]
+                                                             ON (([program].[school_code] = [student].[school_code]) AND ([program].[code] = [student].[program_code]))
+                                        WHERE ([school].[code] = [program].[school_code])
+                                              AND (1 <> 0)
+                                              AND (COALESCE([student].[count], 0) > 10)) THEN 1 ELSE 0 END)
+               FROM [ad].[school]
+               ORDER BY 1 ASC
+          - uri: /school?exists({campus, exists(department?count(course)>20)} -> school{campus,
+              exists(program?count(student)>10)})
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            - [Vary, Accept]
+            body: |2
+               | school                                        |
+               +------+-------------------------------+--------+
+               | code | name                          | campus |
+              -+------+-------------------------------+--------+-
+               | bus  | School of Business            | south  |
+               | eng  | School of Engineering         | north  |
+               | la   | School of Arts and Humanities | old    |
+               | mus  | School of Music & Dance       | south  |
+               | ns   | School of Natural Sciences    | old    |
+
+               ----
+               /school?exists({campus,exists(department?count(course)>20)}->school{campus,exists(program?count(student)>10)})
+               SELECT [school].[code],
+                      [school].[name],
+                      [school].[campus]
+               FROM [ad].[school]
+               WHERE EXISTS(SELECT 1
+                            FROM [ad].[school] AS [school_1]
+                            WHERE ([school].[campus] = [school_1].[campus])
+                                  AND ((CASE WHEN EXISTS(SELECT 1
+                                                         FROM [ad].[department]
+                                                              LEFT OUTER JOIN (SELECT COUNT(1) AS [count],
+                                                                                      [course].[department_code]
+                                                                               FROM [ad].[course]
+                                                                               GROUP BY [course].[department_code]) AS [course]
+                                                                              ON ([department].[code] = [course].[department_code])
+                                                         WHERE ([school].[code] = [department].[school_code])
+                                                               AND (1 <> 0)
+                                                               AND (COALESCE([course].[count], 0) > 20)) THEN 1 ELSE 0 END) = (CASE WHEN EXISTS(SELECT 1
+                                                                                                                                                FROM [ad].[program]
+                                                                                                                                                     LEFT OUTER JOIN (SELECT COUNT(1) AS [count],
+                                                                                                                                                                             [student].[school_code],
+                                                                                                                                                                             [student].[program_code]
+                                                                                                                                                                      FROM [ed].[student]
+                                                                                                                                                                      GROUP BY [student].[school_code], [student].[program_code]) AS [student]
+                                                                                                                                                                     ON (([program].[school_code] = [student].[school_code]) AND ([program].[code] = [student].[program_code]))
+                                                                                                                                                WHERE ([school_1].[code] = [program].[school_code])
+                                                                                                                                                      AND (1 <> 0)
+                                                                                                                                                      AND (COALESCE([student].[count], 0) > 10)) THEN 1 ELSE 0 END))
+                                  AND (1 <> 0))
+               ORDER BY 1 ASC
           - uri: /department{code,count(course{credits=3})}
             status: 200 OK
             headers:

test/output/mysql.yaml

                                               FROM `course`
                                               WHERE (`department`.`code` = `course`.`department_code`)) THEN TRUE END))
                FROM `department`
+          - uri: /school{code, campus, exists(department?count(course)>20), exists(program?count(student)>10)}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            - [Vary, Accept]
+            body: |2
+               | school                                                                                  |
+               +------+--------+-------------------------------------+-----------------------------------+
+               | code | campus | exists(department?count(course)>20) | exists(program?count(student)>10) |
+              -+------+--------+-------------------------------------+-----------------------------------+-
+               | art  | old    | false                               | true                              |
+               | bus  | south  | false                               | true                              |
+               | edu  | old    | false                               | true                              |
+               | eng  | north  | true                                | true                              |
+               | la   | old    | true                                | true                              |
+               | mus  | south  | false                               | false                             |
+               | ns   | old    | true                                | true                              |
+               | ph   |        | false                               | true                              |
+               | sc   |        | false                               | false                             |
+
+               ----
+               /school{code,campus,exists(department?count(course)>20),exists(program?count(student)>10)}
+               SELECT `school`.`code`,
+                      `school`.`campus`,
+                      EXISTS(SELECT TRUE
+                             FROM `department`
+                                  LEFT OUTER JOIN (SELECT COUNT(TRUE) AS `count`,
+                                                          `course`.`department_code`
+                                                   FROM `course`
+                                                   GROUP BY 2) AS `course`
+                                                  ON (`department`.`code` = `course`.`department_code`)
+                             WHERE (`school`.`code` = `department`.`school_code`)
+                                   AND (COALESCE(`course`.`count`, 0) > 20)),
+                      EXISTS(SELECT TRUE
+                             FROM `program`
+                                  LEFT OUTER JOIN (SELECT COUNT(TRUE) AS `count`,
+                                                          `student`.`school_code`,
+                                                          `student`.`program_code`
+                                                   FROM `student`
+                                                   GROUP BY 2, 3) AS `student`
+                                                  ON ((`program`.`school_code` = `student`.`school_code`) AND (`program`.`code` = `student`.`program_code`))
+                             WHERE (`school`.`code` = `program`.`school_code`)
+                                   AND (COALESCE(`student`.`count`, 0) > 10))
+               FROM `school`
+               ORDER BY 1 ASC
+          - uri: /school?exists({campus, exists(department?count(course)>20)} -> school{campus,
+              exists(program?count(student)>10)})
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            - [Vary, Accept]
+            body: |2
+               | school                                        |
+               +------+-------------------------------+--------+
+               | code | name                          | campus |
+              -+------+-------------------------------+--------+-
+               | bus  | School of Business            | south  |
+               | eng  | School of Engineering         | north  |
+               | la   | School of Arts and Humanities | old    |
+               | mus  | School of Music & Dance       | south  |
+               | ns   | School of Natural Sciences    | old    |
+
+               ----
+               /school?exists({campus,exists(department?count(course)>20)}->school{campus,exists(program?count(student)>10)})
+               SELECT `school`.`code`,
+                      `school`.`name`,
+                      `school`.`campus`
+               FROM `school`
+               WHERE EXISTS(SELECT TRUE
+                            FROM `school` AS `school_1`
+                            WHERE (`school`.`campus` = `school_1`.`campus`)
+                                  AND (EXISTS(SELECT TRUE
+                                              FROM `department`
+                                                   LEFT OUTER JOIN (SELECT COUNT(TRUE) AS `count`,
+                                                                           `course`.`department_code`
+                                                                    FROM `course`
+                                                                    GROUP BY 2) AS `course`
+                                                                   ON (`department`.`code` = `course`.`department_code`)
+                                              WHERE (`school`.`code` = `department`.`school_code`)
+                                                    AND (COALESCE(`course`.`count`, 0) > 20)) = EXISTS(SELECT TRUE
+                                                                                                       FROM `program`
+                                                                                                            LEFT OUTER JOIN (SELECT COUNT(TRUE) AS `count`,
+                                                                                                                                    `student`.`school_code`,
+                                                                                                                                    `student`.`program_code`
+                                                                                                                             FROM `student`
+                                                                                                                             GROUP BY 2, 3) AS `student`
+                                                                                                                            ON ((`program`.`school_code` = `student`.`school_code`) AND (`program`.`code` = `student`.`program_code`))
+                                                                                                       WHERE (`school_1`.`code` = `program`.`school_code`)
+                                                                                                             AND (COALESCE(`student`.`count`, 0) > 10))))
+               ORDER BY 1 ASC
           - uri: /department{code,count(course{credits=3})}
             status: 200 OK
             headers:

test/output/oracle.yaml

                                               WHERE ("DEPARTMENT"."CODE" = "COURSE"."DEPARTMENT_CODE")
                                                     AND (1 <> 0)) THEN 1 END))
                FROM "DEPARTMENT"
+          - uri: /school{code, campus, exists(department?count(course)>20), exists(program?count(student)>10)}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            - [Vary, Accept]
+            body: |2
+               | school                                                                                  |
+               +------+--------+-------------------------------------+-----------------------------------+
+               | code | campus | exists(department?count(course)>20) | exists(program?count(student)>10) |
+              -+------+--------+-------------------------------------+-----------------------------------+-
+               | art  | old    | false                               | true                              |
+               | bus  | south  | false                               | true                              |
+               | edu  | old    | false                               | true                              |
+               | eng  | north  | true                                | true                              |
+               | la   | old    | true                                | true                              |
+               | mus  | south  | false                               | false                             |
+               | ns   | old    | true                                | true                              |
+               | ph   |        | false                               | true                              |
+               | sc   |        | false                               | false                             |
+
+               ----
+               /school{code,campus,exists(department?count(course)>20),exists(program?count(student)>10)}
+               SELECT "SCHOOL"."CODE",
+                      "SCHOOL"."CAMPUS",
+                      (CASE WHEN EXISTS(SELECT 1
+                                        FROM "DEPARTMENT"
+                                             LEFT OUTER JOIN (SELECT COUNT(1) AS "count",
+                                                                     "COURSE"."DEPARTMENT_CODE"
+                                                              FROM "COURSE"
+                                                              GROUP BY "COURSE"."DEPARTMENT_CODE") "COURSE"
+                                                             ON ("DEPARTMENT"."CODE" = "COURSE"."DEPARTMENT_CODE")
+                                        WHERE ("SCHOOL"."CODE" = "DEPARTMENT"."SCHOOL_CODE")
+                                              AND (1 <> 0)
+                                              AND (COALESCE("COURSE"."count", 0) > 20)) THEN 1 ELSE 0 END),
+                      (CASE WHEN EXISTS(SELECT 1
+                                        FROM "PROGRAM"
+                                             LEFT OUTER JOIN (SELECT COUNT(1) AS "count",
+                                                                     "STUDENT"."SCHOOL_CODE",
+                                                                     "STUDENT"."PROGRAM_CODE"
+                                                              FROM "STUDENT"
+                                                              GROUP BY "STUDENT"."SCHOOL_CODE", "STUDENT"."PROGRAM_CODE") "STUDENT"
+                                                             ON (("PROGRAM"."SCHOOL_CODE" = "STUDENT"."SCHOOL_CODE") AND ("PROGRAM"."CODE" = "STUDENT"."PROGRAM_CODE"))
+                                        WHERE ("SCHOOL"."CODE" = "PROGRAM"."SCHOOL_CODE")
+                                              AND (1 <> 0)
+                                              AND (COALESCE("STUDENT"."count", 0) > 10)) THEN 1 ELSE 0 END)
+               FROM "SCHOOL"
+               ORDER BY 1 ASC
+          - uri: /school?exists({campus, exists(department?count(course)>20)} -> school{campus,
+              exists(program?count(student)>10)})
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            - [Vary, Accept]
+            body: |2
+               | school                                        |
+               +------+-------------------------------+--------+
+               | code | name                          | campus |
+              -+------+-------------------------------+--------+-
+               | bus  | School of Business            | south  |
+               | eng  | School of Engineering         | north  |
+               | la   | School of Arts and Humanities | old    |
+               | mus  | School of Music & Dance       | south  |
+               | ns   | School of Natural Sciences    | old    |
+
+               ----
+               /school?exists({campus,exists(department?count(course)>20)}->school{campus,exists(program?count(student)>10)})
+               SELECT "SCHOOL"."CODE",
+                      "SCHOOL"."NAME",
+                      "SCHOOL"."CAMPUS"
+               FROM "SCHOOL"
+               WHERE EXISTS(SELECT 1
+                            FROM "SCHOOL" "SCHOOL_1"
+                            WHERE ("SCHOOL"."CAMPUS" = "SCHOOL_1"."CAMPUS")
+                                  AND ((CASE WHEN EXISTS(SELECT 1
+                                                         FROM "DEPARTMENT"
+                                                              LEFT OUTER JOIN (SELECT COUNT(1) AS "count",
+                                                                                      "COURSE"."DEPARTMENT_CODE"
+                                                                               FROM "COURSE"
+                                                                               GROUP BY "COURSE"."DEPARTMENT_CODE") "COURSE"
+                                                                              ON ("DEPARTMENT"."CODE" = "COURSE"."DEPARTMENT_CODE")
+                                                         WHERE ("SCHOOL"."CODE" = "DEPARTMENT"."SCHOOL_CODE")
+                                                               AND (1 <> 0)
+                                                               AND (COALESCE("COURSE"."count", 0) > 20)) THEN 1 ELSE 0 END) = (CASE WHEN EXISTS(SELECT 1
+                                                                                                                                                FROM "PROGRAM"
+                                                                                                                                                     LEFT OUTER JOIN (SELECT COUNT(1) AS "count",
+                                                                                                                                                                             "STUDENT"."SCHOOL_CODE",
+                                                                                                                                                                             "STUDENT"."PROGRAM_CODE"
+                                                                                                                                                                      FROM "STUDENT"
+                                                                                                                                                                      GROUP BY "STUDENT"."SCHOOL_CODE", "STUDENT"."PROGRAM_CODE") "STUDENT"
+                                                                                                                                                                     ON (("PROGRAM"."SCHOOL_CODE" = "STUDENT"."SCHOOL_CODE") AND ("PROGRAM"."CODE" = "STUDENT"."PROGRAM_CODE"))
+                                                                                                                                                WHERE ("SCHOOL_1"."CODE" = "PROGRAM"."SCHOOL_CODE")
+                                                                                                                                                      AND (1 <> 0)
+                                                                                                                                                      AND (COALESCE("STUDENT"."count", 0) > 10)) THEN 1 ELSE 0 END))
+                                  AND (1 <> 0))
+               ORDER BY 1 ASC
           - uri: /department{code,count(course{credits=3})}
             status: 200 OK
             headers:

test/output/pgsql.yaml

                                               FROM "ad"."course"
                                               WHERE ("department"."code" = "course"."department_code")) THEN TRUE END))
                FROM "ad"."department"
+          - uri: /school{code, campus, exists(department?count(course)>20), exists(program?count(student)>10)}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            - [Vary, Accept]
+            body: |2
+               | school                                                                                  |
+               +------+--------+-------------------------------------+-----------------------------------+
+               | code | campus | exists(department?count(course)>20) | exists(program?count(student)>10) |
+              -+------+--------+-------------------------------------+-----------------------------------+-
+               | art  | old    | false                               | true                              |
+               | bus  | south  | false                               | true                              |
+               | edu  | old    | false                               | true                              |
+               | eng  | north  | true                                | true                              |
+               | la   | old    | true                                | true                              |
+               | mus  | south  | false                               | false                             |
+               | ns   | old    | true                                | true                              |
+               | ph   |        | false                               | true                              |
+               | sc   |        | false                               | false                             |
+
+               ----
+               /school{code,campus,exists(department?count(course)>20),exists(program?count(student)>10)}
+               SELECT "school"."code",
+                      "school"."campus",
+                      EXISTS(SELECT TRUE
+                             FROM "ad"."department"
+                                  LEFT OUTER JOIN (SELECT COUNT(TRUE) AS "count",
+                                                          "course"."department_code"
+                                                   FROM "ad"."course"
+                                                   GROUP BY 2) AS "course"
+                                                  ON ("department"."code" = "course"."department_code")
+                             WHERE ("school"."code" = "department"."school_code")
+                                   AND (COALESCE("course"."count", 0) > 20)),
+                      EXISTS(SELECT TRUE
+                             FROM "ad"."program"
+                                  LEFT OUTER JOIN (SELECT COUNT(TRUE) AS "count",
+                                                          "student"."school_code",
+                                                          "student"."program_code"
+                                                   FROM "ed"."student"
+                                                   GROUP BY 2, 3) AS "student"
+                                                  ON (("program"."school_code" = "student"."school_code") AND ("program"."code" = "student"."program_code"))
+                             WHERE ("school"."code" = "program"."school_code")
+                                   AND (COALESCE("student"."count", 0) > 10))
+               FROM "ad"."school"
+               ORDER BY 1 ASC
+          - uri: /school?exists({campus, exists(department?count(course)>20)} -> school{campus,
+              exists(program?count(student)>10)})
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            - [Vary, Accept]
+            body: |2
+               | school                                        |
+               +------+-------------------------------+--------+
+               | code | name                          | campus |
+              -+------+-------------------------------+--------+-
+               | bus  | School of Business            | south  |
+               | eng  | School of Engineering         | north  |
+               | la   | School of Arts and Humanities | old    |
+               | mus  | School of Music & Dance       | south  |
+               | ns   | School of Natural Sciences    | old    |
+
+               ----
+               /school?exists({campus,exists(department?count(course)>20)}->school{campus,exists(program?count(student)>10)})
+               SELECT "school"."code",
+                      "school"."name",
+                      "school"."campus"
+               FROM "ad"."school"
+               WHERE EXISTS(SELECT TRUE
+                            FROM "ad"."school" AS "school_1"
+                            WHERE ("school"."campus" = "school_1"."campus")
+                                  AND (EXISTS(SELECT TRUE
+                                              FROM "ad"."department"
+                                                   LEFT OUTER JOIN (SELECT COUNT(TRUE) AS "count",
+                                                                           "course"."department_code"
+                                                                    FROM "ad"."course"
+                                                                    GROUP BY 2) AS "course"
+                                                                   ON ("department"."code" = "course"."department_code")
+                                              WHERE ("school"."code" = "department"."school_code")
+                                                    AND (COALESCE("course"."count", 0) > 20)) = EXISTS(SELECT TRUE
+                                                                                                       FROM "ad"."program"
+                                                                                                            LEFT OUTER JOIN (SELECT COUNT(TRUE) AS "count",
+                                                                                                                                    "student"."school_code",
+                                                                                                                                    "student"."program_code"
+                                                                                                                             FROM "ed"."student"
+                                                                                                                             GROUP BY 2, 3) AS "student"
+                                                                                                                            ON (("program"."school_code" = "student"."school_code") AND ("program"."code" = "student"."program_code"))
+                                                                                                       WHERE ("school_1"."code" = "program"."school_code")
+                                                                                                             AND (COALESCE("student"."count", 0) > 10))))
+               ORDER BY 1 ASC
           - uri: /department{code,count(course{credits=3})}
             status: 200 OK
             headers:

test/output/sqlite.yaml

                                               FROM "course"
                                               WHERE ("department"."code" = "course"."department_code")) THEN 1 END))
                FROM "department"
+          - uri: /school{code, campus, exists(department?count(course)>20), exists(program?count(student)>10)}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            - [Vary, Accept]
+            body: |2
+               | school                                                                                  |
+               +------+--------+-------------------------------------+-----------------------------------+
+               | code | campus | exists(department?count(course)>20) | exists(program?count(student)>10) |
+              -+------+--------+-------------------------------------+-----------------------------------+-
+               | art  | old    | false                               | true                              |
+               | bus  | south  | false                               | true                              |
+               | edu  | old    | false                               | true                              |
+               | eng  | north  | true                                | true                              |
+               | la   | old    | true                                | true                              |
+               | mus  | south  | false                               | false                             |
+               | ns   | old    | true                                | true                              |
+               | ph   |        | false                               | true                              |
+               | sc   |        | false                               | false                             |
+
+               ----
+               /school{code,campus,exists(department?count(course)>20),exists(program?count(student)>10)}
+               SELECT "school"."code",
+                      "school"."campus",
+                      EXISTS(SELECT 1
+                             FROM "department"
+                                  LEFT OUTER JOIN (SELECT COUNT(1) AS "count",
+                                                          "course"."department_code"
+                                                   FROM "course"
+                                                   GROUP BY 2) AS "course"
+                                                  ON ("department"."code" = "course"."department_code")
+                             WHERE ("school"."code" = "department"."school_code")
+                                   AND (COALESCE("course"."count", 0) > 20)),
+                      EXISTS(SELECT 1
+                             FROM "program"
+                                  LEFT OUTER JOIN (SELECT COUNT(1) AS "count",
+                                                          "student"."school_code",
+                                                          "student"."program_code"
+                                                   FROM "student"
+                                                   GROUP BY 2, 3) AS "student"
+                                                  ON (("program"."school_code" = "student"."school_code") AND ("program"."code" = "student"."program_code"))
+                             WHERE ("school"."code" = "program"."school_code")
+                                   AND (COALESCE("student"."count", 0) > 10))
+               FROM "school"
+               ORDER BY 1 ASC
+          - uri: /school?exists({campus, exists(department?count(course)>20)} -> school{campus,
+              exists(program?count(student)>10)})
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            - [Vary, Accept]
+            body: |2
+               | school                                        |
+               +------+-------------------------------+--------+
+               | code | name                          | campus |
+              -+------+-------------------------------+--------+-
+               | bus  | School of Business            | south  |
+               | eng  | School of Engineering         | north  |
+               | la   | School of Arts and Humanities | old    |
+               | mus  | School of Music & Dance       | south  |
+               | ns   | School of Natural Sciences    | old    |
+
+               ----
+               /school?exists({campus,exists(department?count(course)>20)}->school{campus,exists(program?count(student)>10)})
+               SELECT "school"."code",
+                      "school"."name",
+                      "school"."campus"
+               FROM "school"
+               WHERE EXISTS(SELECT 1
+                            FROM "school" AS "school_1"
+                            WHERE ("school"."campus" = "school_1"."campus")
+                                  AND (EXISTS(SELECT 1
+                                              FROM "department"
+                                                   LEFT OUTER JOIN (SELECT COUNT(1) AS "count",
+                                                                           "course"."department_code"
+                                                                    FROM "course"
+                                                                    GROUP BY 2) AS "course"
+                                                                   ON ("department"."code" = "course"."department_code")
+                                              WHERE ("school"."code" = "department"."school_code")
+                                                    AND (COALESCE("course"."count", 0) > 20)) = EXISTS(SELECT 1
+                                                                                                       FROM "program"
+                                                                                                            LEFT OUTER JOIN (SELECT COUNT(1) AS "count",
+                                                                                                                                    "student"."school_code",
+                                                                                                                                    "student"."program_code"
+                                                                                                                             FROM "student"
+                                                                                                                             GROUP BY 2, 3) AS "student"
+                                                                                                                            ON (("program"."school_code" = "student"."school_code") AND ("program"."code" = "student"."program_code"))
+                                                                                                       WHERE ("school_1"."code" = "program"."school_code")
+                                                                                                             AND (COALESCE("student"."count", 0) > 10))))
+               ORDER BY 1 ASC
           - uri: /department{code,count(course{credits=3})}
             status: 200 OK
             headers:
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.