Commits

Kirill Simonov committed dea4088

Added support for macro definitions.

Comments (0)

Files changed (9)

src/htsql/tr/bind.py

                       LiteralBinding, SieveBinding, CastBinding,
                       WrapperBinding, FreeTableBinding, AttachedTableBinding,
                       ColumnBinding, ComplementBinding, KernelBinding,
-                      DefinitionBinding, RedirectBinding)
-from .lookup import lookup, itemize, get_kernel, get_complement
+                      DefinitionBinding, RedirectBinding, AliasBinding)
+from .lookup import lookup, itemize, get_kernel, get_complement, get_function
 from .coerce import coerce
 
 
         # If passed, set the new lookup context.
         if base is not None:
             self.push_base(base)
+        # First, try to find the function in the local context.
+        recipe = get_function
+        # Otherwise, look for the global function.
         # Realize and apply `BindByName` protocol.
         bind = BindByName(syntax, self)
         bindings = list(bind())
         #   <lop> <identifier> <rop>
 
         # Find and bind the function.
-        return self.state.call(self.syntax)
+        recipe = get_function(self.state.base, self.syntax.identifier,
+                              len(self.syntax.arguments))
+        if recipe is not None:
+            bind = BindByRecipe(recipe, self.syntax, self.state)
+            bindings = [bind()]
+        else:
+            bindings = self.state.call(self.syntax)
+        return bindings
 
 
 class BindFunctionCall(Bind):
         if self.syntax.base is not None:
             base = self.state.bind(self.syntax.base)
         # Find and bind the function.
-        return self.state.call(self.syntax, base)
+        self.state.push_base(base)
+        recipe = get_function(base, self.syntax.identifier,
+                              len(self.syntax.arguments))
+        if recipe is not None:
+            bind = BindByRecipe(recipe, self.syntax, self.state)
+            bindings = [bind()]
+        else:
+            bindings = self.state.call(self.syntax, base)
+        self.state.pop_base()
+        return bindings
 
 
 class BindByName(Protocol):
 
     def __call__(self):
         if self.recipe.subnames:
+            assert isinstance(self.syntax, IdentifierSyntax)
             recipe = lookup(self.recipe.base, self.syntax)
             if recipe is None:
                 raise BindError("unable to resolve an identifier",
                                         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)
+        if self.recipe.arguments is not None:
+            assert isinstance(self.syntax, CallSyntax)
+            assert len(self.syntax.arguments) == len(self.recipe.arguments)
+            for name, syntax in zip(self.recipe.arguments,
+                                    self.syntax.arguments):
+                binding = self.state.bind(syntax)
+                base = AliasBinding(base, name, binding, base.syntax)
         binding = self.state.bind(self.recipe.body, base=base)
         binding = WrapperBinding(binding, self.syntax)
         return binding

src/htsql/tr/fn/bind.py

         arguments = []
         syntax = lop
         if isinstance(syntax, FunctionCallSyntax):
-            names.append(syntax.identifier)
+            identifiers.append(syntax.identifier)
             for argument in syntax.arguments:
                 if not isinstance(argument, IdentifierSyntax):
                     raise BindError("an identifier expected", argument.mark)

src/htsql/tr/lookup.py

     adapts(Binding)
 
     def __init__(self, binding, identifier, arity):
-        assert isinstance(identifier, IdentifierBinding)
+        assert isinstance(identifier, IdentifierSyntax)
         assert isinstance(arity, int) and arity >= 0
-        super(GetFunction, self).__init__(binding, identifier, arity)
+        super(GetFunction, self).__init__(binding)
+        self.identifier = identifier
+        self.key = normalize(identifier.value)
+        self.arity = arity
 
 
 class LookupRoot(Lookup):
                 AliasBinding)
 
     def __call__(self):
-        return get_function(self.binding.base)
+        return get_function(self.binding.base, self.identifier, self.arity)
 
 
 class ItemizeQuotient(Itemize):
                                           self.binding.subnames,
                                           self.binding.arguments,
                                           self.binding.body)
-        return super(LookupDefinition, self).__call__()
+        return super(GetFunctionFromDefinition, self).__call__()
 
 
 class LookupRedirect(Lookup):
     return bindings
 
 
-def get_function(binding):
-    get_function = GetFunction(binding)
+def get_function(binding, identifier, arity):
+    get_function = GetFunction(binding, identifier, arity)
     binding = get_function()
     return binding
 

test/regress/input/translation.yaml

                    school.department.course:=course?credits<5,
                    school.department:=department?code='acc')
             .school.department.course{department,no,title,credits}
+    - uri: /define(double(x):=x*2){double(1),double(2),double(3)}
+    - uri: /define(student.age(date):=(date(date)-dob)/365:round(1),
+                   student.age():=age('2011-01-01'),
+                   inactive_student:=student?!is_active)
+            .inactive_student{name,dob,start_date,age(start_date),age()}
 
   - title: Projections
     tests:

test/regress/output/mssql.yaml

                      AND ([course].[credits] > 2)
                      AND ([department].[code] = 'acc')
                ORDER BY [school].[code] ASC, [department].[code] ASC, 1 ASC, 2 ASC
+          - uri: /define(double(x):=x*2){double(1),double(2),double(3)}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | define(double(x):=x*2)            |
+              -+-----------------------------------+-
+               | double(1) | double(2) | double(3) |
+              -+-----------+-----------+-----------+-
+               |         2 |         4 |         6 |
+                                             (1 row)
+
+               ----
+               /define(double(x):=x*2){double(1),double(2),double(3)}
+               SELECT (1 * 2),
+                      (2 * 2),
+                      (3 * 2)
+          - uri: /define(student.age(date):=(date(date)-dob)/365:round(1), student.age():=age('2011-01-01'),
+              inactive_student:=student?!is_active) .inactive_student{name,dob,start_date,age(start_date),age()}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | define(student.age(date):=(date(date)-dob)/365:round(1),student.age():=age('2011-01-01'),inactive_student:=student?!is_active).inactive_student |
+              -+-------------------------------------------------------------------------------------------------------------------------------------------------+-
+               | name                               | dob                       | start_date               | age(start_date)               | age()               |
+              -+------------------------------------+---------------------------+--------------------------+-------------------------------+---------------------+-
+               | Narissa Maya                       | 1992-04-30                | 2007-11-21               |                          15.6 |                18.7 |
+               | Valeria Rinaldi                    | 1985-09-02                | 2004-09-01               |                          19.0 |                25.3 |
+               | Mahesh Basa                        | 1995-08-21                | 2008-04-15               |                          12.7 |                15.4 |
+               | Khadija Hamad Azzan                | 1992-11-26                | 2008-09-21               |                          15.8 |                18.1 |
+               | Raisa Antonova                     | 1992-12-09                | 2008-09-15               |                          15.8 |                18.1 |
+               | Amy Yang                           | 1992-12-17                | 2002-08-10               |                           9.7 |                18.1 |
+               | Ming Wang                          | 1988-03-15                | 2002-11-27               |                          14.7 |                22.8 |
+                                                                                                                                                          (7 rows)
+
+               ----
+               /define(student.age(date):=(date(date)-dob)/365:round(1),student.age():=age('2011-01-01'),inactive_student:=student?!is_active).inactive_student{name,dob,start_date,age(start_date),age()}
+               SELECT [student].[name],
+                      [student].[dob],
+                      [student].[start_date],
+                      CAST(ROUND((CAST(DATEDIFF(DAY, [student].[dob], [student].[start_date]) AS DECIMAL(38)) / 365.), 1) AS DECIMAL(38,1)),
+                      CAST(ROUND((CAST(DATEDIFF(DAY, [student].[dob], CAST('2011-01-01' AS DATETIME)) AS DECIMAL(38)) / 365.), 1) AS DECIMAL(38,1))
+               FROM [ed].[student] AS [student]
+               WHERE (NOT ([student].[is_active] <> 0))
+               ORDER BY [student].[id] ASC
         - id: projections
           tests:
           - uri: /quotient(program, degree)

test/regress/output/mysql.yaml

                      AND (`course`.`credits` > 2)
                      AND (`department`.`code` = 'acc')
                ORDER BY `school`.`code` ASC, `department`.`code` ASC, 1 ASC, 2 ASC
+          - uri: /define(double(x):=x*2){double(1),double(2),double(3)}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | define(double(x):=x*2)            |
+              -+-----------------------------------+-
+               | double(1) | double(2) | double(3) |
+              -+-----------+-----------+-----------+-
+               |         2 |         4 |         6 |
+                                             (1 row)
+
+               ----
+               /define(double(x):=x*2){double(1),double(2),double(3)}
+               SELECT (1 * 2),
+                      (2 * 2),
+                      (3 * 2)
+          - uri: /define(student.age(date):=(date(date)-dob)/365:round(1), student.age():=age('2011-01-01'),
+              inactive_student:=student?!is_active) .inactive_student{name,dob,start_date,age(start_date),age()}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | define(student.age(date):=(date(date)-dob)/365:round(1),student.age():=age('2011-01-01'),inactive_student:=student?!is_active).inactive_student |
+              -+-------------------------------------------------------------------------------------------------------------------------------------------------+-
+               | name                               | dob                       | start_date               | age(start_date)               | age()               |
+              -+------------------------------------+---------------------------+--------------------------+-------------------------------+---------------------+-
+               | Narissa Maya                       | 1992-04-30                | 2007-11-21               |                          15.6 |                18.7 |
+               | Valeria Rinaldi                    | 1985-09-02                | 2004-09-01               |                          19.0 |                25.3 |
+               | Mahesh Basa                        | 1995-08-21                | 2008-04-15               |                          12.7 |                15.4 |
+               | Khadija Hamad Azzan                | 1992-11-26                | 2008-09-21               |                          15.8 |                18.1 |
+               | Raisa Antonova                     | 1992-12-09                | 2008-09-15               |                          15.8 |                18.1 |
+               | Amy Yang                           | 1992-12-17                | 2002-08-10               |                           9.7 |                18.1 |
+               | Ming Wang                          | 1988-03-15                | 2002-11-27               |                          14.7 |                22.8 |
+                                                                                                                                                          (7 rows)
+
+               ----
+               /define(student.age(date):=(date(date)-dob)/365:round(1),student.age():=age('2011-01-01'),inactive_student:=student?!is_active).inactive_student{name,dob,start_date,age(start_date),age()}
+               SELECT `student`.`name`,
+                      `student`.`dob`,
+                      `student`.`start_date`,
+                      ROUND((CAST(DATEDIFF(`student`.`start_date`, `student`.`dob`) AS DECIMAL(65,30)) / 365.), 1),
+                      ROUND((CAST(DATEDIFF(DATE('2011-01-01'), `student`.`dob`) AS DECIMAL(65,30)) / 365.), 1)
+               FROM `htsql_regress`.`student` AS `student`
+               WHERE (NOT `student`.`is_active`)
+               ORDER BY `student`.`id` ASC
         - id: projections
           tests:
           - uri: /quotient(program, degree)

test/regress/output/oracle.yaml

                      AND ("COURSE"."CREDITS" > 2)
                      AND ("DEPARTMENT"."CODE" = 'acc')
                ORDER BY "SCHOOL"."CODE" ASC, "DEPARTMENT"."CODE" ASC, 1 ASC, 2 ASC
+          - uri: /define(double(x):=x*2){double(1),double(2),double(3)}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | define(double(x):=x*2)            |
+              -+-----------------------------------+-
+               | double(1) | double(2) | double(3) |
+              -+-----------+-----------+-----------+-
+               |         2 |         4 |         6 |
+                                             (1 row)
+
+               ----
+               /define(double(x):=x*2){double(1),double(2),double(3)}
+               SELECT (1 * 2),
+                      (2 * 2),
+                      (3 * 2)
+               FROM DUAL "!"
+          - uri: /define(student.age(date):=(date(date)-dob)/365:round(1), student.age():=age('2011-01-01'),
+              inactive_student:=student?!is_active) .inactive_student{name,dob,start_date,age(start_date),age()}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | define(student.age(date):=(date(date)-dob)/365:round(1),student.age():=age('2011-01-01'),inactive_student:=student?!is_active).inactive_student |
+              -+-------------------------------------------------------------------------------------------------------------------------------------------------+-
+               | name                               | dob                       | start_date               | age(start_date)               | age()               |
+              -+------------------------------------+---------------------------+--------------------------+-------------------------------+---------------------+-
+               | Narissa Maya                       | 1992-04-30                | 2007-11-21               |                          15.6 |                18.7 |
+               | Valeria Rinaldi                    | 1985-09-02                | 2004-09-01               |                            19 |                25.3 |
+               | Mahesh Basa                        | 1995-08-21                | 2008-04-15               |                          12.7 |                15.4 |
+               | Khadija Hamad Azzan                | 1992-11-26                | 2008-09-21               |                          15.8 |                18.1 |
+               | Raisa Antonova                     | 1992-12-09                | 2008-09-15               |                          15.8 |                18.1 |
+               | Amy Yang                           | 1992-12-17                | 2002-08-10               |                           9.7 |                18.1 |
+               | Ming Wang                          | 1988-03-15                | 2002-11-27               |                          14.7 |                22.8 |
+                                                                                                                                                          (7 rows)
+
+               ----
+               /define(student.age(date):=(date(date)-dob)/365:round(1),student.age():=age('2011-01-01'),inactive_student:=student?!is_active).inactive_student{name,dob,start_date,age(start_date),age()}
+               SELECT "STUDENT"."NAME",
+                      "STUDENT"."DOB",
+                      "STUDENT"."START_DATE",
+                      ROUND((CAST(("STUDENT"."START_DATE" - "STUDENT"."DOB") AS NUMBER) / 365), 1),
+                      ROUND((CAST((DATE '2011-01-01' - "STUDENT"."DOB") AS NUMBER) / 365), 1)
+               FROM "HTSQL_REGRESS"."STUDENT" "STUDENT"
+               WHERE (NOT ("STUDENT"."IS_ACTIVE" <> 0))
+               ORDER BY "STUDENT"."ID" ASC
         - id: projections
           tests:
           - uri: /quotient(program, degree)

test/regress/output/pgsql.yaml

                      AND ("course"."credits" > 2)
                      AND ("department"."code" = 'acc')
                ORDER BY "school"."code" ASC, "department"."code" ASC, 1 ASC, 2 ASC
+          - uri: /define(double(x):=x*2){double(1),double(2),double(3)}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | define(double(x):=x*2)            |
+              -+-----------------------------------+-
+               | double(1) | double(2) | double(3) |
+              -+-----------+-----------+-----------+-
+               |         2 |         4 |         6 |
+                                             (1 row)
+
+               ----
+               /define(double(x):=x*2){double(1),double(2),double(3)}
+               SELECT (1 * 2),
+                      (2 * 2),
+                      (3 * 2)
+          - uri: /define(student.age(date):=(date(date)-dob)/365:round(1), student.age():=age('2011-01-01'),
+              inactive_student:=student?!is_active) .inactive_student{name,dob,start_date,age(start_date),age()}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | define(student.age(date):=(date(date)-dob)/365:round(1),student.age():=age('2011-01-01'),inactive_student:=student?!is_active).inactive_student |
+              -+-------------------------------------------------------------------------------------------------------------------------------------------------+-
+               | name                               | dob                       | start_date               | age(start_date)               | age()               |
+              -+------------------------------------+---------------------------+--------------------------+-------------------------------+---------------------+-
+               | Narissa Maya                       | 1992-04-30                | 2007-11-21               |                          15.6 |                18.7 |
+               | Valeria Rinaldi                    | 1985-09-02                | 2004-09-01               |                          19.0 |                25.3 |
+               | Mahesh Basa                        | 1995-08-21                | 2008-04-15               |                          12.7 |                15.4 |
+               | Khadija Hamad Azzan                | 1992-11-26                | 2008-09-21               |                          15.8 |                18.1 |
+               | Raisa Antonova                     | 1992-12-09                | 2008-09-15               |                          15.8 |                18.1 |
+               | Amy Yang                           | 1992-12-17                | 2002-08-10               |                           9.7 |                18.1 |
+               | Ming Wang                          | 1988-03-15                | 2002-11-27               |                          14.7 |                22.8 |
+                                                                                                                                                          (7 rows)
+
+               ----
+               /define(student.age(date):=(date(date)-dob)/365:round(1),student.age():=age('2011-01-01'),inactive_student:=student?!is_active).inactive_student{name,dob,start_date,age(start_date),age()}
+               SELECT "student"."name",
+                      "student"."dob",
+                      "student"."start_date",
+                      ROUND((CAST(("student"."start_date" - "student"."dob") AS NUMERIC) / 365::NUMERIC), 1),
+                      ROUND((CAST(('2011-01-01'::DATE - "student"."dob") AS NUMERIC) / 365::NUMERIC), 1)
+               FROM "ed"."student" AS "student"
+               WHERE (NOT "student"."is_active")
+               ORDER BY "student"."id" ASC
         - id: projections
           tests:
           - uri: /quotient(program, degree)

test/regress/output/sqlite.yaml

                      AND ("course"."credits" > 2)
                      AND ("department"."code" = 'acc')
                ORDER BY "school"."code" ASC, "department"."code" ASC, 1 ASC, 2 ASC
+          - uri: /define(double(x):=x*2){double(1),double(2),double(3)}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | define(double(x):=x*2)            |
+              -+-----------------------------------+-
+               | double(1) | double(2) | double(3) |
+              -+-----------+-----------+-----------+-
+               |         2 |         4 |         6 |
+                                             (1 row)
+
+               ----
+               /define(double(x):=x*2){double(1),double(2),double(3)}
+               SELECT (1 * 2),
+                      (2 * 2),
+                      (3 * 2)
+          - uri: /define(student.age(date):=(date(date)-dob)/365:round(1), student.age():=age('2011-01-01'),
+              inactive_student:=student?!is_active) .inactive_student{name,dob,start_date,age(start_date),age()}
+            status: 200 OK
+            headers:
+            - [Content-Type, text/plain; charset=UTF-8]
+            body: |2
+               | define(student.age(date):=(date(date)-dob)/365:round(1),student.age():=age('2011-01-01'),inactive_student:=student?!is_active).inactive_student |
+              -+-------------------------------------------------------------------------------------------------------------------------------------------------+-
+               | name                               | dob                       | start_date               | age(start_date)               | age()               |
+              -+------------------------------------+---------------------------+--------------------------+-------------------------------+---------------------+-
+               | Narissa Maya                       | 1992-04-30                | 2007-11-21               |                          15.6 |                18.7 |
+               | Valeria Rinaldi                    | 1985-09-02                | 2004-09-01               |                          19.0 |                25.3 |
+               | Mahesh Basa                        | 1995-08-21                | 2008-04-15               |                          12.7 |                15.4 |
+               | Khadija Hamad Azzan                | 1992-11-26                | 2008-09-21               |                          15.8 |                18.1 |
+               | Raisa Antonova                     | 1992-12-09                | 2008-09-15               |                          15.8 |                18.1 |
+               | Amy Yang                           | 1992-12-17                | 2002-08-10               |                           9.7 |                18.1 |
+               | Ming Wang                          | 1988-03-15                | 2002-11-27               |                          14.7 |                22.8 |
+                                                                                                                                                          (7 rows)
+
+               ----
+               /define(student.age(date):=(date(date)-dob)/365:round(1),student.age():=age('2011-01-01'),inactive_student:=student?!is_active).inactive_student{name,dob,start_date,age(start_date),age()}
+               SELECT "student"."name",
+                      "student"."dob",
+                      "student"."start_date",
+                      ROUND((CAST(CAST(JULIANDAY("student"."start_date") - JULIANDAY("student"."dob") AS INTEGER) AS REAL) / 365.0), 1),
+                      ROUND((CAST(CAST(JULIANDAY('2011-01-01') - JULIANDAY("student"."dob") AS INTEGER) AS REAL) / 365.0), 1)
+               FROM "student" AS "student"
+               WHERE (NOT "student"."is_active")
+               ORDER BY "student"."id" ASC
         - id: projections
           tests:
           - uri: /quotient(program, degree)