Commits

Kirill Simonov committed 8a108b3

tweak.etl: respect `can_write` option.

Comments (0)

Files changed (13)

src/htsql/core/__init__.py

     This extension implements the HTSQL translator and HTTP service.
     It is included to every HTSQL application.
 
-    The parameter `DB` specifies parameters of the database connection;
+    The parameter `db` specifies parameters of the database connection;
     it must have the form:
 
         ENGINE://USERNAME:PASSWORD@HOST:PORT/DATABASE
       - HOST:PORT is the address of the database server.
       - DATABASE is the name of the database, or, for file-based
         backends, the path to the file containing the database.
+
+    The parameter `password` sets the database password.  It overrides
+    the password given as a part of `db` parameter.
+
+    The parameter `debug`, if set to `True`, enables debug output.
     """
 
     parameters = [

src/htsql/core/cmd/fetch.py

         data = None
         if self.statement:
             if not context.env.can_read:
-                raise PermissionError("not enough permissions"
-                                      " to execute the query")
+                raise PermissionError("No read permissions")
             stream = None
             with transaction() as connection:
                 cursor = connection.cursor()

src/htsql/tweak/etl/__init__.py

 class TweakETLAddon(Addon):
 
     name = 'tweak.etl'
-    hint = """ETL (extract-transform-load) operations"""
-    help = None
+    hint = """ETL and CRUD commands"""
+    help = """
+    The extension provides the following commands:
+
+    `insert(feed)` adds records to a table.
+
+    `update(feed)` updates table records.
+
+    `merge(feed)` adds or updates records in a table.
+
+    `delete(feed)` deletes records from a table.
+
+    `truncate(name)` truncates a table.
+
+    `do(command, ...)` performs a series of command in a single
+    transaction.
+    """
     packages = ['.', '.cmd', '.tr']
 
     @classmethod

src/htsql/tweak/etl/cmd/delete.py

 
 from ....core.util import listof
 from ....core.adapter import Utility, adapt
-from ....core.error import Error
+from ....core.error import Error, PermissionError
+from ....core.context import context
 from ....core.entity import TableEntity, ColumnEntity
 from ....core.connect import transaction, scramble
 from ....core.domain import Product
     def __call__(self, key_row):
         key_row = tuple(convert(item)
                         for item, convert in zip(key_row, self.key_converts))
+        if not context.env.can_write:
+            raise PermissionError("No write permissions")
         with transaction() as connection:
             cursor = connection.cursor()
             cursor.execute(self.sql.encode('utf-8'), key_row)

src/htsql/tweak/etl/cmd/insert.py

 
 from ....core.util import listof
 from ....core.adapter import Utility, Adapter, adapt, adapt_many
-from ....core.error import Error
+from ....core.error import Error, PermissionError
+from ....core.context import context
 from ....core.connect import transaction, scramble, unscramble
 from ....core.domain import (Domain, ListDomain, RecordDomain, BooleanDomain,
         IntegerDomain, FloatDomain, DecimalDomain, TextDomain, DateDomain,
     def __call__(self, row):
         row = tuple(convert(item)
                for item, convert in zip(row, self.input_converts))
+        if not context.env.can_write:
+            raise PermissionError("No write permissions")
         with transaction() as connection:
             cursor = connection.cursor()
             cursor.execute(self.sql.encode('utf-8'), row)

src/htsql/tweak/etl/cmd/merge.py

 
 from ....core.util import listof
 from ....core.adapter import Utility, adapt
-from ....core.error import Error
+from ....core.context import context
+from ....core.error import Error, PermissionError
 from ....core.entity import TableEntity, ColumnEntity
 from ....core.model import TableArc
 from ....core.classify import localize, relabel
                     for item, convert in zip(row, self.input_converts))
         if not row:
             return key_row
+        if not context.env.can_write:
+            raise PermissionError("No write permissions")
         with transaction() as connection:
             cursor = connection.cursor()
             cursor.execute(self.sql.encode('utf-8'), row+key_row)

src/htsql/tweak/etl/cmd/truncate.py

 
 
 from ....core.adapter import adapt
+from ....core.context import context
 from ....core.connect import transaction
+from ....core.error import PermissionError
 from ....core.cmd.act import Act, ProduceAction
 from ....core.domain import Product
 from ....core.tr.binding import VoidBinding
     adapt(TruncateCmd, ProduceAction)
 
     def __call__(self):
+        if not context.env.can_write:
+            raise PermissionError("No write permissions")
         with transaction() as connection:
             sql = serialize_truncate(self.command.table)
             sql = sql.encode('utf-8')

test/input/etl.yaml

 ifdef: pgsql
 tests:
 - load: etl
+- ctl: [ext, tweak.etl]
 - uri: /truncate(product_line)
 - uri: /truncate(manufacturer)
 - uri: /{code:='ACID', name:='Acer'} :as manufacturer

test/output/mssql.yaml

           status: 403 Forbidden
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
-          - [Set-Cookie, htsql-csrf-token=abf74627aad24b0670dd92ea48925bc2; Path=/]
-          body: |
-            not enough permissions to execute the query
+          - [Set-Cookie, htsql-csrf-token=6e2274f99f4a9a5e2946a9162a4d52e6; Path=/]
+          body: |
+            No read permissions
             While processing:
                 /school
                 ^
           status: 403 Forbidden
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
-          - [Set-Cookie, htsql-csrf-token=976ef3fa416d882655618a9faf6598d2; Path=/]
-          body: |
-            not enough permissions to execute the query
+          - [Set-Cookie, htsql-csrf-token=beaa954d9e3bf2c33620facd25b99be9; Path=/]
+          body: |
+            No read permissions
             While processing:
                 /meta(/table)
                       ^
           body: |
             {
               "type": "permissions",
-              "detail": "not enough permissions to execute the query\nWhile processing:\n    \/school:top\n    ^"
+              "detail": "No read permissions\nWhile processing:\n    \/school:top\n    ^"
             }
         - uri: /
           status: 200 OK

test/output/mysql.yaml

           status: 403 Forbidden
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
-          - [Set-Cookie, htsql-csrf-token=4780d3ab6ca5c074cc8654f4a52fe4ba; Path=/]
-          body: |
-            not enough permissions to execute the query
+          - [Set-Cookie, htsql-csrf-token=3ba579dcf9e21f2a62dd605fe8e66cfc; Path=/]
+          body: |
+            No read permissions
             While processing:
                 /school
                 ^
           status: 403 Forbidden
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
-          - [Set-Cookie, htsql-csrf-token=340fbc8056469569b31881a44510ea6a; Path=/]
-          body: |
-            not enough permissions to execute the query
+          - [Set-Cookie, htsql-csrf-token=c8c29ba9ab23e671134a8f0746094f07; Path=/]
+          body: |
+            No read permissions
             While processing:
                 /meta(/table)
                       ^
           body: |
             {
               "type": "permissions",
-              "detail": "not enough permissions to execute the query\nWhile processing:\n    \/school:top\n    ^"
+              "detail": "No read permissions\nWhile processing:\n    \/school:top\n    ^"
             }
         - uri: /
           status: 200 OK

test/output/oracle.yaml

           status: 403 Forbidden
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
-          - [Set-Cookie, htsql-csrf-token=2d2ed2827dee0595b36ecdebea8f306f; Path=/]
-          body: |
-            not enough permissions to execute the query
+          - [Set-Cookie, htsql-csrf-token=0abb5da30811596cf9626723736d850f; Path=/]
+          body: |
+            No read permissions
             While processing:
                 /school
                 ^
           status: 403 Forbidden
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
-          - [Set-Cookie, htsql-csrf-token=81748e4df4ef0587d05e38c436c91d96; Path=/]
-          body: |
-            not enough permissions to execute the query
+          - [Set-Cookie, htsql-csrf-token=83ed25b7eba183ce08eff96fda869e99; Path=/]
+          body: |
+            No read permissions
             While processing:
                 /meta(/table)
                       ^
           body: |
             {
               "type": "permissions",
-              "detail": "not enough permissions to execute the query\nWhile processing:\n    \/school:top\n    ^"
+              "detail": "No read permissions\nWhile processing:\n    \/school:top\n    ^"
             }
         - uri: /
           status: 200 OK

test/output/pgsql.yaml

           status: 403 Forbidden
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
-          - [Set-Cookie, htsql-csrf-token=b5a8aa7666b3b2b4ffd1dee5b6f336a0; Path=/]
-          body: |
-            not enough permissions to execute the query
+          - [Set-Cookie, htsql-csrf-token=ed0922cbb304ef5c76a84cb3f0f37c66; Path=/]
+          body: |
+            No read permissions
             While processing:
                 /school
                 ^
           status: 403 Forbidden
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
-          - [Set-Cookie, htsql-csrf-token=6770573d046d88b17900983d5957cd6a; Path=/]
-          body: |
-            not enough permissions to execute the query
+          - [Set-Cookie, htsql-csrf-token=23da943cab5d2cf974af7be77b02da98; Path=/]
+          body: |
+            No read permissions
             While processing:
                 /meta(/table)
                       ^
           body: |
             {
               "type": "permissions",
-              "detail": "not enough permissions to execute the query\nWhile processing:\n    \/school:top\n    ^"
+              "detail": "No read permissions\nWhile processing:\n    \/school:top\n    ^"
             }
         - uri: /
           status: 200 OK
     output:
       id: etl
       tests:
+      - ctl: [ext, tweak.etl]
+        stdout: |+
+          TWEAK.ETL - ETL and CRUD commands
+
+          The extension provides the following commands:
+
+          `insert(feed)` adds records to a table.
+
+          `update(feed)` updates table records.
+
+          `merge(feed)` adds or updates records in a table.
+
+          `delete(feed)` deletes records from a table.
+
+          `truncate(name)` truncates a table.
+
+          `do(command, ...)` performs a series of command in a single
+          transaction.
+
+        exit: 0
       - uri: /truncate(product_line)
         status: 200 OK
         headers:

test/output/sqlite.yaml

           status: 403 Forbidden
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
-          - [Set-Cookie, htsql-csrf-token=498a30e8214f4f44f623194c2031a5c2; Path=/]
-          body: |
-            not enough permissions to execute the query
+          - [Set-Cookie, htsql-csrf-token=16156576ed5fffd3a6cdc91a930500ce; Path=/]
+          body: |
+            No read permissions
             While processing:
                 /school
                 ^
           status: 403 Forbidden
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
-          - [Set-Cookie, htsql-csrf-token=2e58edb4150412b8f408cc118df2f7aa; Path=/]
-          body: |
-            not enough permissions to execute the query
+          - [Set-Cookie, htsql-csrf-token=69b93e9f439db566da72937620a915ac; Path=/]
+          body: |
+            No read permissions
             While processing:
                 /meta(/table)
                       ^
           body: |
             {
               "type": "permissions",
-              "detail": "not enough permissions to execute the query\nWhile processing:\n    \/school:top\n    ^"
+              "detail": "No read permissions\nWhile processing:\n    \/school:top\n    ^"
             }
         - uri: /
           status: 200 OK