Kirill Simonov avatar Kirill Simonov committed 64d1ace

Added support for qualified definitions.

Comments (0)

Files changed (12)

src/htsql/tr/bind.py

                      ComplementSyntax, StringSyntax, NumberSyntax)
 from .recipe import (Recipe, FreeTableRecipe, AttachedTableRecipe,
                      ColumnRecipe, ComplementRecipe, KernelRecipe,
-                     SubstitutionRecipe)
+                     SubstitutionRecipe, BindingRecipe)
 from .binding import (Binding, RootBinding, QueryBinding, SegmentBinding,
                       LiteralBinding, SieveBinding, CastBinding,
                       WrapperBinding, FreeTableBinding, AttachedTableBinding,
                       ColumnBinding, ComplementBinding, KernelBinding,
-                      RedirectBinding)
+                      DefinitionBinding, RedirectBinding)
 from .lookup import lookup, itemize, get_kernel, get_complement
 from .coerce import coerce
 
             # FIXME: Will fail if `binding.syntax` is not an identifier
             # or a wildcard node.  Currently, `binding.syntax` is always
             # an identifier node, but that might change in the future.
-            binding_syntax = SpecifierSyntax(base.syntax, binding.syntax,
-                                             binding.mark)
-            binding = WrapperBinding(binding, binding_syntax)
+            binding_syntax = binding.syntax
+            if isinstance(binding_syntax, IdentifierSyntax):
+                binding_syntax = SpecifierSyntax(base.syntax, binding_syntax,
+                                                 binding.mark)
+                binding = WrapperBinding(binding, binding_syntax)
             yield binding
 
 
     adapts(SubstitutionRecipe)
 
     def __call__(self):
+        if self.recipe.subnames:
+            recipe = lookup(self.recipe.base, self.syntax)
+            if recipe is None:
+                raise BindError("unable to resolve an identifier",
+                                self.syntax.mark)
+            bind = BindByRecipe(recipe, self.syntax, self.state)
+            binding = bind()
+            binding = DefinitionBinding(binding, self.recipe.subnames[0],
+                                        self.recipe.subnames[1:],
+                                        self.recipe.arguments,
+                                        self.recipe.body,
+                                        binding.syntax)
+            return binding
+        if self.recipe.arguments is not None:
+            assert False
         base = RedirectBinding(self.state.base, self.recipe.base,
                                self.state.base.syntax)
         binding = self.state.bind(self.recipe.body, base=base)
         return binding
 
 
+class BindByBinding(BindByRecipe):
+
+    adapts(BindingRecipe)
+
+    def __call__(self):
+        return self.recipe.binding
+
+
 def bind_all(syntax, state=None, base=None):
     """
     Binds the given syntax node.

src/htsql/tr/binding.py

 from ..util import maybe, listof, Clonable, Printable
 from ..entity import TableEntity, ColumnEntity, Join
 from ..domain import Domain, VoidDomain, BooleanDomain, TupleDomain
-from .syntax import Syntax
+from .syntax import Syntax, IdentifierSyntax
 from .signature import Signature, Bag, Formula
 
 
 
 class AliasBinding(ChainBinding):
 
-    def __init__(self, base, binding, syntax):
+    def __init__(self, base, name, binding, syntax):
+        assert isinstance(name, str)
         assert isinstance(binding, Binding)
-        super(AliasBinding, self).__init__(base, binding.domain, syntax)
+        super(AliasBinding, self).__init__(base, base.domain, syntax)
+        self.name = name
         self.binding = binding
 
 
 class AssignmentBinding(Binding):
 
-    def __init__(self, name, body, syntax):
-        assert isinstance(name, str)
+    def __init__(self, identifiers, arguments, body, syntax):
+        assert isinstance(identifiers, listof(IdentifierSyntax))
+        assert len(identifiers) > 0
+        assert isinstance(arguments, maybe(listof(IdentifierSyntax)))
         assert isinstance(body, Syntax)
         super(AssignmentBinding, self).__init__(VoidDomain(), syntax)
-        self.name = name
+        self.identifiers = identifiers
+        self.arguments = arguments
         self.body = body
 
 
 class DefinitionBinding(ChainBinding):
 
-    def __init__(self, base, assignment, syntax):
-        assert isinstance(assignment, AssignmentBinding)
+    def __init__(self, base, name, subnames, arguments, body, syntax):
+        assert isinstance(name, str)
+        assert isinstance(subnames, listof(str))
+        assert isinstance(arguments, maybe(listof(str)))
+        assert isinstance(body, Syntax)
         super(DefinitionBinding, self).__init__(base, base.domain, syntax)
-        self.assignment = assignment
+        self.name = name
+        self.subnames = subnames
+        self.arguments = arguments
+        self.body = body
 
 
 class LiteralBinding(Binding):

src/htsql/tr/encode.py

     adapts(AliasBinding)
 
     def __call__(self):
-        return self.state.encode(self.binding.binding)
+        return self.state.encode(self.binding.base)
 
 
 class RelateAlias(Relate):
     adapts(AliasBinding)
 
     def __call__(self):
-        return self.state.relate(self.binding.binding)
+        return self.state.relate(self.binding.base)
 
 
 class DirectAlias(Direct):
     adapts(AliasBinding)
 
     def __call__(self):
-        return self.state.direct(self.binding.binding)
+        return self.state.direct(self.binding.base)
 
 
 class DirectDirection(Direct):

src/htsql/tr/fn/bind.py

 from ...domain import (Domain, UntypedDomain, BooleanDomain, StringDomain,
                        IntegerDomain, DecimalDomain, FloatDomain,
                        DateDomain, EnumDomain)
-from ..syntax import NumberSyntax, StringSyntax, IdentifierSyntax
+from ..syntax import (NumberSyntax, StringSyntax, IdentifierSyntax,
+                      SpecifierSyntax, FunctionCallSyntax)
 from ..binding import (LiteralBinding, SortBinding, SieveBinding,
                        FormulaBinding, CastBinding, WrapperBinding,
                        TitleBinding, DirectionBinding, QuotientBinding,
-                       AssignmentBinding, DefinitionBinding, Binding)
+                       AssignmentBinding, DefinitionBinding, AliasBinding,
+                       Binding)
 from ..bind import BindByName, BindByRecipe, BindingState
 from ..error import BindError
 from ..coerce import coerce
     signature = AssignmentSig
 
     def expand(self, lop, rop):
-        if not isinstance(lop, IdentifierSyntax):
-            raise BindError("an identifier expected", lop.mark)
-        name = lop.value
-        yield AssignmentBinding(name, rop, self.syntax)
+        identifiers = []
+        arguments = []
+        syntax = lop
+        if isinstance(syntax, FunctionCallSyntax):
+            names.append(syntax.identifier)
+            for argument in syntax.arguments:
+                if not isinstance(argument, IdentifierSyntax):
+                    raise BindError("an identifier expected", argument.mark)
+                arguments.append(argument)
+            syntax = syntax.base
+        else:
+            arguments = None
+        while syntax is not None:
+            if isinstance(syntax, SpecifierSyntax):
+                if not isinstance(syntax.identifier, IdentifierSyntax):
+                    raise BindError("an identifier expected",
+                                    syntax.identifier.mark)
+                identifiers.append(syntax.identifier)
+                syntax = syntax.base
+            elif isinstance(syntax, IdentifierSyntax):
+                identifiers.append(syntax)
+                syntax = None
+            else:
+                raise BindError("an identifier expected", syntax.mark)
+        identifiers.reverse()
+        yield AssignmentBinding(identifiers, arguments, rop, self.syntax)
 
 
 class BindDefine(BindMacro):
             assignment = self.state.bind(op)
             if not isinstance(assignment, AssignmentBinding):
                 raise BindError("an assignment expected", op.mark)
-            body = self.state.bind(assignment.body, base=binding)
-            binding = DefinitionBinding(binding, assignment, self.syntax)
+            name = assignment.identifiers[0].value
+            subnames = [identifier.value
+                        for identifier in assignment.identifiers[1:]]
+            arguments = None
+            if assignment.arguments is not None:
+                arguments = [argument.value
+                             for argument in assignment.arguments]
+            binding = DefinitionBinding(binding, name, subnames, arguments,
+                                        assignment.body, self.syntax)
         yield binding
 
 

src/htsql/tr/lookup.py

                       TableBinding, FreeTableBinding, AttachedTableBinding,
                       ColumnBinding, SieveBinding, WrapperBinding, SortBinding,
                       QuotientBinding, ComplementBinding, KernelBinding,
-                      DefinitionBinding, RedirectBinding)
+                      DefinitionBinding, RedirectBinding, AliasBinding)
 from .recipe import (FreeTableRecipe, AttachedTableRecipe, ColumnRecipe,
-                     ComplementRecipe, KernelRecipe, SubstitutionRecipe)
+                     ComplementRecipe, KernelRecipe, SubstitutionRecipe,
+                     BindingRecipe)
 import re
 import unicodedata
 
     return name
 
 
+class Thing(object):
+    pass
+
+
+class AttributeThing(Thing):
+
+    def __init__(self, name):
+        name = name
+
+
+class FunctionThing(Thing):
+
+    def __init__(self, name, arity):
+        self.name = name
+        self.arity = arity
+
+
+class KernelThing(Thing):
+
+    def __init__(self, index=None):
+        self.index = index
+
+
+class ComplementThing(Thing):
+    pass
+
+
+class WildThing(Thing):
+
+    def __init__(self, index=None):
+        pass
+
+
+class DeepAttributeThing(AttributeThing):
+    pass
+
+
+class DeepFunctionThing(FunctionThing):
+    pass
+
+
+class _Lookup(Adapter):
+
+    adapts(Binding, Thing)
+
+    def __init__(self, binding, thing):
+        self.binding = binding
+        self.thing = thing
+
+    def __call__(self):
+        return None
+
+
 class LookupItemizeMixin(object):
     """
     Encapsulates common methods and attributes of the :class:`Lookup`
         return None
 
 
+class GetFunction(Adapter, LookupItemizeMixin):
+
+    adapts(Binding)
+
+    def __init__(self, binding, identifier, arity):
+        assert isinstance(identifier, IdentifierBinding)
+        assert isinstance(arity, int) and arity >= 0
+        super(GetFunction, self).__init__(binding, identifier, arity)
+
+
 class LookupRoot(Lookup):
     """
     Finds a member with the given name in the root context.
     adapts_many(WrapperBinding,
                 SieveBinding,
                 SortBinding,
+                AliasBinding,
                 DefinitionBinding)
 
     def __call__(self):
     adapts_many(WrapperBinding,
                 SieveBinding,
                 SortBinding,
+                AliasBinding,
                 DefinitionBinding)
 
     def __call__(self):
     adapts_many(WrapperBinding,
                 SieveBinding,
                 SortBinding,
+                AliasBinding,
                 DefinitionBinding)
 
     def __call__(self):
         return get_kernel(self.binding.base)
 
 
+class GetFunctionFromWrapper(GetFunction):
+
+    adapts_many(WrapperBinding,
+                SieveBinding,
+                SortBinding,
+                AliasBinding)
+
+    def __call__(self):
+        return get_function(self.binding.base)
+
+
 class ItemizeQuotient(Itemize):
 
     adapts(QuotientBinding)
         return get_complement(self.binding.seed)
 
 
+class GetFunctionFromComplement(GetKernel):
+
+    adapts(ComplementBinding)
+
+    def __call__(self):
+        return get_function(self.binding.seed)
+
+
+class LookupAlias(LookupWrapper):
+
+    adapts(AliasBinding)
+
+    def __call__(self):
+        if self.key == normalize(self.binding.name):
+            return BindingRecipe(self.binding.binding)
+        return super(LookupAlias, self).__call__()
+
+
 class LookupDefinition(LookupWrapper):
 
     adapts(DefinitionBinding)
 
     def __call__(self):
-        if self.key == normalize(self.binding.assignment.name):
-            return SubstitutionRecipe(self.binding.base,
-                                      self.binding.assignment.body)
+        if self.key == normalize(self.binding.name):
+            if (self.binding.arguments is None or
+                    len(self.binding.subnames) > 0):
+                return SubstitutionRecipe(self.binding.base,
+                                          self.binding.subnames,
+                                          self.binding.arguments,
+                                          self.binding.body)
+        return super(LookupDefinition, self).__call__()
+
+
+class GetFunctionFromDefinition(GetFunctionFromWrapper):
+
+    adapts(DefinitionBinding)
+
+    def __call__(self):
+        if self.key == normalize(self.binding.name):
+            if (not self.binding.subnames and
+                    self.binding.arguments is not None and
+                    len(self.binding.arguments) == self.arity):
+                return SubstitutionRecipe(self.binding.base,
+                                          self.binding.subnames,
+                                          self.binding.arguments,
+                                          self.binding.body)
         return super(LookupDefinition, self).__call__()
 
 
         return get_kernel(self.binding.pointer)
 
 
+class GetFunctionFromRedirect(GetKernel):
+
+    adapts(RedirectBinding)
+
+    def __call__(self):
+        return get_function(self.binding.pointer)
+
+
 def lookup(binding, identifier):
     """
     Looks for a member of the specified binding that matches
     return bindings
 
 
+def get_function(binding):
+    get_function = GetFunction(binding)
+    binding = get_function()
+    return binding
+
+

src/htsql/tr/recipe.py

 
 class SubstitutionRecipe(Recipe):
 
-    def __init__(self, base, body):
+    def __init__(self, base, subnames, arguments, body):
         assert isinstance(base, Binding)
+        assert isinstance(subnames, listof(str))
+        assert isinstance(arguments, maybe(listof(str)))
         assert isinstance(body, Syntax)
         self.base = base
+        self.subnames = subnames
         self.body = body
+        self.arguments = arguments
 
 
+class BindingRecipe(Recipe):
+
+    def __init__(self, binding):
+        assert isinstance(binding, Binding)
+        self.binding = binding
+
+

test/regress/input/translation.yaml

     - uri: /school.define(program:=(program?degree='bs')
                                 .define(student:=student?is_active))
                 {code,count(program),count(program.student)}?code='eng'
-    # FIXME?
     - uri: /school{code,count(program.student),
                    count((program.define(s:=student)?degree='bs').s),
                    count((program?degree='bs').define(s:=student).s)}?code='eng'
     - uri: /define(x:=2,y:=3,z:=x*y){x,y,z}
     - uri: /define(x:=2,x:=x+x,x:=x*x){x}
+    - uri: /define(program.student:=student?is_active)
+            .program{code,count(student)}?school='bus'
+    - uri: /define(school.program.student:=student?is_active)
+            .count((school?code='bus').program.student)
+    - uri: /define(school.department.course:=course?credits>2,
+                   school.department.course:=course?credits<5,
+                   school.department:=department?code='acc')
+            .school.department.course{department,no,title,credits}
 
   - title: Projections
     tests:

test/regress/output/mssql.yaml

                ----
                /define(x:=2,x:=x+x,x:=x*x){x}
                SELECT ((2 + 2) * (2 + 2))
+          - uri: /define(program.student:=student?is_active) .program{code,count(student)}?school='bus'
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | (define(program.student:=student?is_active).program?school='bus') |
+              -+-------------------------------------------------------------------+-
+               | code                         | count(student)                     |
+              -+------------------------------+------------------------------------+-
+               | pacc                         |                                  2 |
+               | pcap                         |                                  1 |
+               | uacct                        |                                  2 |
+               | ubusad                       |                                  0 |
+               | ucorpfi                      |                                  2 |
+                                                                            (5 rows)
+
+               ----
+               /define(program.student:=student?is_active).program{code,count(student)}?school='bus'
+               SELECT [program].[code],
+                      COALESCE([student].[count], 0)
+               FROM [ad].[program] AS [program]
+                    LEFT OUTER JOIN (SELECT COUNT(1) AS [count],
+                                            [student].[school],
+                                            [student].[program]
+                                     FROM [ed].[student] AS [student]
+                                     WHERE ([student].[is_active] <> 0)
+                                     GROUP BY [student].[school], [student].[program]) AS [student]
+                                    ON (([program].[school] = [student].[school]) AND ([program].[code] = [student].[program]))
+               WHERE ([program].[school] = 'bus')
+               ORDER BY [program].[school] ASC, 1 ASC
+          - uri: /define(school.program.student:=student?is_active) .count((school?code='bus').program.student)
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               |                                                                                              |
+              -+----------------------------------------------------------------------------------------------+-
+               | define(school.program.student:=student?is_active).count((school?code='bus').program.student) |
+              -+----------------------------------------------------------------------------------------------+-
+               |                                                                                            7 |
+                                                                                                        (1 row)
+
+               ----
+               /define(school.program.student:=student?is_active).count((school?code='bus').program.student)
+               SELECT COUNT(1)
+               FROM [ad].[school] AS [school]
+                    INNER JOIN [ad].[program] AS [program]
+                               ON ([school].[code] = [program].[school])
+                    INNER JOIN [ed].[student] AS [student]
+                               ON (([program].[school] = [student].[school]) AND ([program].[code] = [student].[program]))
+               WHERE ([student].[is_active] <> 0)
+                     AND ([school].[code] = 'bus')
+          - uri: /define(school.department.course:=course?credits>2, school.department.course:=course?credits<5,
+              school.department:=department?code='acc') .school.department.course{department,no,title,credits}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | define(school.department.course:=course?credits>2,school.department.course:=course?credits<5,school.department:=department?code='acc').school.department.course |
+              -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+-
+               | department                           | no                            | title                                                | credits                           |
+              -+--------------------------------------+-------------------------------+------------------------------------------------------+-----------------------------------+-
+               | acc                                  |                           200 | Principles of Accounting I                           |                                 3 |
+               | acc                                  |                           426 | Corporate Taxation                                   |                                 3 |
+               | acc                                  |                           527 | Advanced Accounting                                  |                                 3 |
+               | acc                                  |                           606 | Corporate Financial Law                              |                                 3 |
+                                                                                                                                                                          (4 rows)
+
+               ----
+               /define(school.department.course:=course?credits>2,school.department.course:=course?credits<5,school.department:=department?code='acc').school.department.course{department,no,title,credits}
+               SELECT [course].[department],
+                      [course].[no],
+                      [course].[title],
+                      [course].[credits]
+               FROM [ad].[school] AS [school]
+                    INNER JOIN [ad].[department] AS [department]
+                               ON ([school].[code] = [department].[school])
+                    INNER JOIN [ad].[course] AS [course]
+                               ON ([department].[code] = [course].[department])
+               WHERE ([course].[credits] < 5)
+                     AND ([course].[credits] > 2)
+                     AND ([department].[code] = 'acc')
+               ORDER BY [school].[code] ASC, [department].[code] ASC, 1 ASC, 2 ASC
         - id: projections
           tests:
           - uri: /quotient(program, degree)

test/regress/output/mysql.yaml

                ----
                /define(x:=2,x:=x+x,x:=x*x){x}
                SELECT ((2 + 2) * (2 + 2))
+          - uri: /define(program.student:=student?is_active) .program{code,count(student)}?school='bus'
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | (define(program.student:=student?is_active).program?school='bus') |
+              -+-------------------------------------------------------------------+-
+               | code                         | count(student)                     |
+              -+------------------------------+------------------------------------+-
+               | pacc                         |                                  2 |
+               | pcap                         |                                  1 |
+               | uacct                        |                                  2 |
+               | ubusad                       |                                  0 |
+               | ucorpfi                      |                                  2 |
+                                                                            (5 rows)
+
+               ----
+               /define(program.student:=student?is_active).program{code,count(student)}?school='bus'
+               SELECT `program`.`code`,
+                      COALESCE(`student`.`count`, 0)
+               FROM `htsql_regress`.`program` AS `program`
+                    LEFT OUTER JOIN (SELECT COUNT(TRUE) AS `count`,
+                                            `student`.`school`,
+                                            `student`.`program`
+                                     FROM `htsql_regress`.`student` AS `student`
+                                     WHERE `student`.`is_active`
+                                     GROUP BY 2, 3) AS `student`
+                                    ON ((`program`.`school` = `student`.`school`) AND (`program`.`code` = `student`.`program`))
+               WHERE (`program`.`school` = 'bus')
+               ORDER BY `program`.`school` ASC, 1 ASC
+          - uri: /define(school.program.student:=student?is_active) .count((school?code='bus').program.student)
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               |                                                                                              |
+              -+----------------------------------------------------------------------------------------------+-
+               | define(school.program.student:=student?is_active).count((school?code='bus').program.student) |
+              -+----------------------------------------------------------------------------------------------+-
+               |                                                                                            7 |
+                                                                                                        (1 row)
+
+               ----
+               /define(school.program.student:=student?is_active).count((school?code='bus').program.student)
+               SELECT COUNT(TRUE)
+               FROM `htsql_regress`.`school` AS `school`
+                    INNER JOIN `htsql_regress`.`program` AS `program`
+                               ON (`school`.`code` = `program`.`school`)
+                    INNER JOIN `htsql_regress`.`student` AS `student`
+                               ON ((`program`.`school` = `student`.`school`) AND (`program`.`code` = `student`.`program`))
+               WHERE `student`.`is_active`
+                     AND (`school`.`code` = 'bus')
+          - uri: /define(school.department.course:=course?credits>2, school.department.course:=course?credits<5,
+              school.department:=department?code='acc') .school.department.course{department,no,title,credits}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | define(school.department.course:=course?credits>2,school.department.course:=course?credits<5,school.department:=department?code='acc').school.department.course |
+              -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+-
+               | department                           | no                            | title                                                | credits                           |
+              -+--------------------------------------+-------------------------------+------------------------------------------------------+-----------------------------------+-
+               | acc                                  |                           200 | Principles of Accounting I                           |                                 3 |
+               | acc                                  |                           426 | Corporate Taxation                                   |                                 3 |
+               | acc                                  |                           527 | Advanced Accounting                                  |                                 3 |
+               | acc                                  |                           606 | Corporate Financial Law                              |                                 3 |
+                                                                                                                                                                          (4 rows)
+
+               ----
+               /define(school.department.course:=course?credits>2,school.department.course:=course?credits<5,school.department:=department?code='acc').school.department.course{department,no,title,credits}
+               SELECT `course`.`department`,
+                      `course`.`no`,
+                      `course`.`title`,
+                      `course`.`credits`
+               FROM `htsql_regress`.`school` AS `school`
+                    INNER JOIN `htsql_regress`.`department` AS `department`
+                               ON (`school`.`code` = `department`.`school`)
+                    INNER JOIN `htsql_regress`.`course` AS `course`
+                               ON (`department`.`code` = `course`.`department`)
+               WHERE (`course`.`credits` < 5)
+                     AND (`course`.`credits` > 2)
+                     AND (`department`.`code` = 'acc')
+               ORDER BY `school`.`code` ASC, `department`.`code` ASC, 1 ASC, 2 ASC
         - id: projections
           tests:
           - uri: /quotient(program, degree)

test/regress/output/oracle.yaml

                /define(x:=2,x:=x+x,x:=x*x){x}
                SELECT ((2 + 2) * (2 + 2))
                FROM DUAL "!"
+          - uri: /define(program.student:=student?is_active) .program{code,count(student)}?school='bus'
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | (define(program.student:=student?is_active).program?school='bus') |
+              -+-------------------------------------------------------------------+-
+               | code                         | count(student)                     |
+              -+------------------------------+------------------------------------+-
+               | pacc                         |                                  2 |
+               | pcap                         |                                  1 |
+               | uacct                        |                                  2 |
+               | ubusad                       |                                  0 |
+               | ucorpfi                      |                                  2 |
+                                                                            (5 rows)
+
+               ----
+               /define(program.student:=student?is_active).program{code,count(student)}?school='bus'
+               SELECT "PROGRAM"."CODE",
+                      COALESCE("STUDENT"."count", 0)
+               FROM "HTSQL_REGRESS"."PROGRAM" "PROGRAM"
+                    LEFT OUTER JOIN (SELECT COUNT(1) AS "count",
+                                            "STUDENT"."SCHOOL",
+                                            "STUDENT"."PROGRAM"
+                                     FROM "HTSQL_REGRESS"."STUDENT" "STUDENT"
+                                     WHERE ("STUDENT"."IS_ACTIVE" <> 0)
+                                     GROUP BY "STUDENT"."SCHOOL", "STUDENT"."PROGRAM") "STUDENT"
+                                    ON (("PROGRAM"."SCHOOL" = "STUDENT"."SCHOOL") AND ("PROGRAM"."CODE" = "STUDENT"."PROGRAM"))
+               WHERE ("PROGRAM"."SCHOOL" = 'bus')
+               ORDER BY "PROGRAM"."SCHOOL" ASC, 1 ASC
+          - uri: /define(school.program.student:=student?is_active) .count((school?code='bus').program.student)
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               |                                                                                              |
+              -+----------------------------------------------------------------------------------------------+-
+               | define(school.program.student:=student?is_active).count((school?code='bus').program.student) |
+              -+----------------------------------------------------------------------------------------------+-
+               |                                                                                            7 |
+                                                                                                        (1 row)
+
+               ----
+               /define(school.program.student:=student?is_active).count((school?code='bus').program.student)
+               SELECT COUNT(1)
+               FROM "HTSQL_REGRESS"."SCHOOL" "SCHOOL"
+                    INNER JOIN "HTSQL_REGRESS"."PROGRAM" "PROGRAM"
+                               ON ("SCHOOL"."CODE" = "PROGRAM"."SCHOOL")
+                    INNER JOIN "HTSQL_REGRESS"."STUDENT" "STUDENT"
+                               ON (("PROGRAM"."SCHOOL" = "STUDENT"."SCHOOL") AND ("PROGRAM"."CODE" = "STUDENT"."PROGRAM"))
+               WHERE ("STUDENT"."IS_ACTIVE" <> 0)
+                     AND ("SCHOOL"."CODE" = 'bus')
+          - uri: /define(school.department.course:=course?credits>2, school.department.course:=course?credits<5,
+              school.department:=department?code='acc') .school.department.course{department,no,title,credits}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | define(school.department.course:=course?credits>2,school.department.course:=course?credits<5,school.department:=department?code='acc').school.department.course |
+              -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+-
+               | department                           | no                            | title                                                | credits                           |
+              -+--------------------------------------+-------------------------------+------------------------------------------------------+-----------------------------------+-
+               | acc                                  |                           200 | Principles of Accounting I                           |                                 3 |
+               | acc                                  |                           426 | Corporate Taxation                                   |                                 3 |
+               | acc                                  |                           527 | Advanced Accounting                                  |                                 3 |
+               | acc                                  |                           606 | Corporate Financial Law                              |                                 3 |
+                                                                                                                                                                          (4 rows)
+
+               ----
+               /define(school.department.course:=course?credits>2,school.department.course:=course?credits<5,school.department:=department?code='acc').school.department.course{department,no,title,credits}
+               SELECT "COURSE"."DEPARTMENT",
+                      "COURSE"."NO",
+                      "COURSE"."TITLE",
+                      "COURSE"."CREDITS"
+               FROM "HTSQL_REGRESS"."SCHOOL" "SCHOOL"
+                    INNER JOIN "HTSQL_REGRESS"."DEPARTMENT" "DEPARTMENT"
+                               ON ("SCHOOL"."CODE" = "DEPARTMENT"."SCHOOL")
+                    INNER JOIN "HTSQL_REGRESS"."COURSE" "COURSE"
+                               ON ("DEPARTMENT"."CODE" = "COURSE"."DEPARTMENT")
+               WHERE ("COURSE"."CREDITS" < 5)
+                     AND ("COURSE"."CREDITS" > 2)
+                     AND ("DEPARTMENT"."CODE" = 'acc')
+               ORDER BY "SCHOOL"."CODE" ASC, "DEPARTMENT"."CODE" ASC, 1 ASC, 2 ASC
         - id: projections
           tests:
           - uri: /quotient(program, degree)

test/regress/output/pgsql.yaml

                ----
                /define(x:=2,x:=x+x,x:=x*x){x}
                SELECT ((2 + 2) * (2 + 2))
+          - uri: /define(program.student:=student?is_active) .program{code,count(student)}?school='bus'
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | (define(program.student:=student?is_active).program?school='bus') |
+              -+-------------------------------------------------------------------+-
+               | code                         | count(student)                     |
+              -+------------------------------+------------------------------------+-
+               | pacc                         |                                  2 |
+               | pcap                         |                                  1 |
+               | uacct                        |                                  2 |
+               | ubusad                       |                                  0 |
+               | ucorpfi                      |                                  2 |
+                                                                            (5 rows)
+
+               ----
+               /define(program.student:=student?is_active).program{code,count(student)}?school='bus'
+               SELECT "program"."code",
+                      COALESCE("student"."count", 0)
+               FROM "ad"."program" AS "program"
+                    LEFT OUTER JOIN (SELECT COUNT(TRUE) AS "count",
+                                            "student"."school",
+                                            "student"."program"
+                                     FROM "ed"."student" AS "student"
+                                     WHERE "student"."is_active"
+                                     GROUP BY 2, 3) AS "student"
+                                    ON (("program"."school" = "student"."school") AND ("program"."code" = "student"."program"))
+               WHERE ("program"."school" = 'bus')
+               ORDER BY "program"."school" ASC, 1 ASC
+          - uri: /define(school.program.student:=student?is_active) .count((school?code='bus').program.student)
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               |                                                                                              |
+              -+----------------------------------------------------------------------------------------------+-
+               | define(school.program.student:=student?is_active).count((school?code='bus').program.student) |
+              -+----------------------------------------------------------------------------------------------+-
+               |                                                                                            7 |
+                                                                                                        (1 row)
+
+               ----
+               /define(school.program.student:=student?is_active).count((school?code='bus').program.student)
+               SELECT COUNT(TRUE)
+               FROM "ad"."school" AS "school"
+                    INNER JOIN "ad"."program" AS "program"
+                               ON ("school"."code" = "program"."school")
+                    INNER JOIN "ed"."student" AS "student"
+                               ON (("program"."school" = "student"."school") AND ("program"."code" = "student"."program"))
+               WHERE "student"."is_active"
+                     AND ("school"."code" = 'bus')
+          - uri: /define(school.department.course:=course?credits>2, school.department.course:=course?credits<5,
+              school.department:=department?code='acc') .school.department.course{department,no,title,credits}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | define(school.department.course:=course?credits>2,school.department.course:=course?credits<5,school.department:=department?code='acc').school.department.course |
+              -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+-
+               | department                           | no                            | title                                                | credits                           |
+              -+--------------------------------------+-------------------------------+------------------------------------------------------+-----------------------------------+-
+               | acc                                  |                           200 | Principles of Accounting I                           |                                 3 |
+               | acc                                  |                           426 | Corporate Taxation                                   |                                 3 |
+               | acc                                  |                           527 | Advanced Accounting                                  |                                 3 |
+               | acc                                  |                           606 | Corporate Financial Law                              |                                 3 |
+                                                                                                                                                                          (4 rows)
+
+               ----
+               /define(school.department.course:=course?credits>2,school.department.course:=course?credits<5,school.department:=department?code='acc').school.department.course{department,no,title,credits}
+               SELECT "course"."department",
+                      "course"."no",
+                      "course"."title",
+                      "course"."credits"
+               FROM "ad"."school" AS "school"
+                    INNER JOIN "ad"."department" AS "department"
+                               ON ("school"."code" = "department"."school")
+                    INNER JOIN "ad"."course" AS "course"
+                               ON ("department"."code" = "course"."department")
+               WHERE ("course"."credits" < 5)
+                     AND ("course"."credits" > 2)
+                     AND ("department"."code" = 'acc')
+               ORDER BY "school"."code" ASC, "department"."code" ASC, 1 ASC, 2 ASC
         - id: projections
           tests:
           - uri: /quotient(program, degree)

test/regress/output/sqlite.yaml

                ----
                /define(x:=2,x:=x+x,x:=x*x){x}
                SELECT ((2 + 2) * (2 + 2))
+          - uri: /define(program.student:=student?is_active) .program{code,count(student)}?school='bus'
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | (define(program.student:=student?is_active).program?school='bus') |
+              -+-------------------------------------------------------------------+-
+               | code                         | count(student)                     |
+              -+------------------------------+------------------------------------+-
+               | pacc                         |                                  2 |
+               | pcap                         |                                  1 |
+               | uacct                        |                                  2 |
+               | ubusad                       |                                  0 |
+               | ucorpfi                      |                                  2 |
+                                                                            (5 rows)
+
+               ----
+               /define(program.student:=student?is_active).program{code,count(student)}?school='bus'
+               SELECT "program"."code",
+                      COALESCE("student"."count", 0)
+               FROM "program" AS "program"
+                    LEFT OUTER JOIN (SELECT COUNT(1) AS "count",
+                                            "student"."school",
+                                            "student"."program"
+                                     FROM "student" AS "student"
+                                     WHERE "student"."is_active"
+                                     GROUP BY 2, 3) AS "student"
+                                    ON (("program"."school" = "student"."school") AND ("program"."code" = "student"."program"))
+               WHERE ("program"."school" = 'bus')
+               ORDER BY "program"."school" ASC, 1 ASC
+          - uri: /define(school.program.student:=student?is_active) .count((school?code='bus').program.student)
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               |                                                                                              |
+              -+----------------------------------------------------------------------------------------------+-
+               | define(school.program.student:=student?is_active).count((school?code='bus').program.student) |
+              -+----------------------------------------------------------------------------------------------+-
+               |                                                                                            7 |
+                                                                                                        (1 row)
+
+               ----
+               /define(school.program.student:=student?is_active).count((school?code='bus').program.student)
+               SELECT COUNT(1)
+               FROM "school" AS "school"
+                    INNER JOIN "program" AS "program"
+                               ON ("school"."code" = "program"."school")
+                    INNER JOIN "student" AS "student"
+                               ON (("program"."school" = "student"."school") AND ("program"."code" = "student"."program"))
+               WHERE "student"."is_active"
+                     AND ("school"."code" = 'bus')
+          - uri: /define(school.department.course:=course?credits>2, school.department.course:=course?credits<5,
+              school.department:=department?code='acc') .school.department.course{department,no,title,credits}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | define(school.department.course:=course?credits>2,school.department.course:=course?credits<5,school.department:=department?code='acc').school.department.course |
+              -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+-
+               | department                           | no                            | title                                                | credits                           |
+              -+--------------------------------------+-------------------------------+------------------------------------------------------+-----------------------------------+-
+               | acc                                  |                           200 | Principles of Accounting I                           |                                 3 |
+               | acc                                  |                           426 | Corporate Taxation                                   |                                 3 |
+               | acc                                  |                           527 | Advanced Accounting                                  |                                 3 |
+               | acc                                  |                           606 | Corporate Financial Law                              |                                 3 |
+                                                                                                                                                                          (4 rows)
+
+               ----
+               /define(school.department.course:=course?credits>2,school.department.course:=course?credits<5,school.department:=department?code='acc').school.department.course{department,no,title,credits}
+               SELECT "course"."department",
+                      "course"."no",
+                      "course"."title",
+                      "course"."credits"
+               FROM "school" AS "school"
+                    INNER JOIN "department" AS "department"
+                               ON ("school"."code" = "department"."school")
+                    INNER JOIN "course" AS "course"
+                               ON ("department"."code" = "course"."department")
+               WHERE ("course"."credits" < 5)
+                     AND ("course"."credits" > 2)
+                     AND ("department"."code" = 'acc')
+               ORDER BY "school"."code" ASC, "department"."code" ASC, 1 ASC, 2 ASC
         - id: projections
           tests:
           - uri: /quotient(program, degree)
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.