Commits

Kirill Simonov  committed 5afd353

`do()`: support for assignments and passing references.

  • Participants
  • Parent commits 8b247a6

Comments (0)

Files changed (5)

File src/htsql/tweak/etl/cmd/command.py

 
 class DoCmd(ProducerCmd):
 
-    def __init__(self, commands):
-        assert isinstance(commands, listof(Command))
-        self.commands = commands
+    def __init__(self, scope, ops):
+        self.scope = scope
+        self.ops = ops
 
 

File src/htsql/tweak/etl/cmd/do.py

 
 from ....core.adapter import Adapter, adapt
 from ....core.connect import transaction
-from ....core.domain import RecordDomain
+from ....core.cmd.command import DefaultCmd
 from ....core.cmd.act import Act, ProduceAction, produce
 from ....core.cmd.fetch import Product
-from ....core.tr.binding import VoidBinding
+from ....core.tr.syntax import (WeakSegmentSyntax, AssignmentSyntax,
+        ReferenceSyntax)
+from ....core.tr.bind import BindingState
+from ....core.tr.binding import (VoidBinding, QueryBinding, SegmentBinding,
+        LiteralBinding, DefinitionBinding, BindingRecipe, ClosedRecipe)
 from ....core.tr.decorate import decorate
+from ....core.tr.lookup import lookup_command
+from ....core.tr.error import BindError
 from .command import DoCmd
 
 
     adapt(DoCmd, ProduceAction)
 
     def __call__(self):
+        scope = self.command.scope
+        root = scope
+        while root.base is not None:
+            root = root.base
+        reference = None
+        recipe = None
         product = None
         with transaction():
-            for command in self.command.commands:
+            for op in self.command.ops:
+                state = BindingState()
+                state.set_root(root)
+                state.push_scope(scope)
+                if reference is not None:
+                    seed = state.use(recipe, reference)
+                    scope = DefinitionBinding(scope, reference.identifier.value,
+                                              True, None, recipe, reference)
+                    state.push_scope(scope)
+                    reference = None
+                    recipe = None
+                if isinstance(op, AssignmentSyntax):
+                    if not isinstance(op.lbranch, ReferenceSyntax):
+                        raise BindError("a reference is expected",
+                                        op.lbranch.mark)
+                    reference = op.lbranch
+                    op = op.rbranch
+                op = WeakSegmentSyntax(op, op.mark)
+                op = state.bind(op)
+                command = lookup_command(op)
+                if command is None:
+                    if not isinstance(op, SegmentBinding):
+                        raise BindError("a segment is expected", op.mark)
+                    profile = decorate(op)
+                    binding = QueryBinding(state.root, op, profile, op.syntax)
+                    command = DefaultCmd(binding)
                 product = produce(command)
+                if reference is not None:
+                    literal = LiteralBinding(state.scope, product.data,
+                                             product.meta.domain, reference)
+                    recipe = ClosedRecipe(BindingRecipe(literal))
         return product
 
 

File src/htsql/tweak/etl/tr/bind.py

     signature = ConnectiveSig
 
     def expand(self, ops):
-        commands = []
-        for op in ops:
-            op = WeakSegmentSyntax(op, op.mark)
-            op = self.state.bind(op)
-            command = lookup_command(op)
-            if command is None:
-                if not isinstance(op, SegmentBinding):
-                    raise BindError("a segment is expected", op.mark)
-                profile = decorate(op)
-                binding = QueryBinding(self.state.root, op, profile, op.syntax)
-                command = DefaultCmd(binding)
-            commands.append(command)
-        command = DoCmd(commands)
+        command = DoCmd(self.state.scope, ops)
         return CommandBinding(self.state.scope, command, self.syntax)
 
 

File test/input/etl.yaml

 - uri: /merge({'A0000004' :as sku,
                'Sony Vaio SVE1711X1EB' :as title} :as product)/:json
 - uri: /update(product[A0000004]{id(), list_price:=1279})/:json
+- uri: /do($new_list_price:=product[A0000004].list_price*0.8:round(2),
+           update(product[A0000004]{id(), list_price:=$new_list_price}),
+           product[A0000004])
 - uri: /product
 

File test/output/pgsql.yaml

           {
             "product": "A0000004"
           }
+      - uri: /do($new_list_price:=product[A0000004].list_price*0.8:round(2), update(product[A0000004]{id(),
+          list_price:=$new_list_price}), product[A0000004])
+        status: 200 OK
+        headers:
+        - [Content-Type, text/plain; charset=UTF-8]
+        - [Vary, Accept]
+        body: |2
+           | product                                                                                                            |
+           +----------+-------------------+-------------------+-----------------------+--------------+-------------+------------+
+           | sku      | manufacturer_code | product_line_code | title                 | is_available | description | list_price |
+          -+----------+-------------------+-------------------+-----------------------+--------------+-------------+------------+-
+           | A0000004 | SNY               |                   | Sony Vaio SVE1711X1EB | true         |             |    1023.20 |
+
+           ----
+           product[A0000004]
+           SELECT "product"."sku",
+                  "product"."manufacturer_code",
+                  "product"."product_line_code",
+                  "product"."title",
+                  "product"."is_available",
+                  "product"."description",
+                  "product"."list_price"
+           FROM "product"
+           WHERE ("product"."sku" = 'A0000004')
+           ORDER BY 1 ASC
       - uri: /product
         status: 200 OK
         headers:
           ThinkPad T430        | true         |                                  |
           \           |\n | A0000004 | SNY               |                   | Sony
           Vaio SVE1711X1EB       | true         |                                  |
-          \   1279.00 |\n\n ----\n /product\n SELECT \"product\".\"sku\",\n        \"product\".\"manufacturer_code\",\n
+          \   1023.20 |\n\n ----\n /product\n SELECT \"product\".\"sku\",\n        \"product\".\"manufacturer_code\",\n
           \       \"product\".\"product_line_code\",\n        \"product\".\"title\",\n
           \       \"product\".\"is_available\",\n        \"product\".\"description\",\n
           \       \"product\".\"list_price\"\n FROM \"product\"\n ORDER BY 1 ASC\n"