|
| 1 | +--- |
| 2 | +title: CREATE TASK Statement — Opteryx Reference |
| 3 | +description: SQL CREATE TASK statement syntax and examples for defining a statement the platform runs for you in Opteryx |
| 4 | +--- |
| 5 | + |
| 6 | +# CREATE TASK |
| 7 | + |
| 8 | +The `CREATE TASK` statement records a statement the platform can run on your behalf, either |
| 9 | +on demand with [EXECUTE](execute) or automatically when a table changes. |
| 10 | + |
| 11 | +A task is the general form of the machinery behind a materialized view. Where a view |
| 12 | +re-runs one `SELECT` into its own backing table, a task runs any statement the engine can |
| 13 | +plan — typically an `INSERT` that appends only what changed, which is what makes it |
| 14 | +suitable for tables too large to rebuild. |
| 15 | + |
| 16 | +A task runs as its owner, so creating one is not merely registering some SQL: it creates |
| 17 | +something that executes with an identity. What you may define is therefore bounded by what |
| 18 | +you could already run yourself — see [Notes](#notes). |
| 19 | + |
| 20 | +## Syntax |
| 21 | + |
| 22 | +~~~sql |
| 23 | +CREATE [ OR REPLACE ] TASK <task_name> |
| 24 | + [ ON <table_name> ] |
| 25 | + AS <statement>; |
| 26 | +~~~ |
| 27 | + |
| 28 | +## Parameters |
| 29 | + |
| 30 | +- **`<task_name>`** — the name of the task, fully qualified as |
| 31 | + `<workspace>.<collection>.<task_name>`. A task shares its namespace with tables and |
| 32 | + views, so the name must be free. |
| 33 | +- **`<table_name>`** — a table whose commits fire this task. Supplying it creates the |
| 34 | + trigger alongside the task, so one statement leaves nothing half-wired. Omit it and the |
| 35 | + task is defined but nothing fires it, which is what a backfill or a replay wants; add |
| 36 | + triggers later with [CREATE TRIGGER](create-trigger). |
| 37 | +- **`<statement>`** — the SQL the task runs. It may contain `:name` placeholders, which are |
| 38 | + supplied when the task is executed rather than now. |
| 39 | +- `OR REPLACE` — redefine an existing task instead of refusing. The previous statement is |
| 40 | + kept as an earlier version, and the task's owner is **not** changed. |
| 41 | + |
| 42 | +## Examples |
| 43 | + |
| 44 | +### Define a Task Run on Demand |
| 45 | +~~~sql |
| 46 | +CREATE TASK my_workspace.ops.rebuild_summary AS |
| 47 | + INSERT INTO my_workspace.ops.summary |
| 48 | + SELECT category, COUNT(*) FROM my_workspace.sales.orders GROUP BY category; |
| 49 | +~~~ |
| 50 | + |
| 51 | +### Define a Task Fired by a Table |
| 52 | +~~~sql |
| 53 | +CREATE TASK my_workspace.ops.ingest_events |
| 54 | + ON my_workspace.raw.events |
| 55 | + AS INSERT INTO my_workspace.ops.event_log |
| 56 | + SELECT * FROM my_workspace.raw.events VERSION AS OF :current_version; |
| 57 | +~~~ |
| 58 | + |
| 59 | +### Parameterize the Window |
| 60 | +A task fired by a table is passed the committing snapshot and the one before it, so it can |
| 61 | +process only what that commit added: |
| 62 | + |
| 63 | +~~~sql |
| 64 | +CREATE TASK my_workspace.ops.ingest_new |
| 65 | + ON my_workspace.raw.events |
| 66 | + AS INSERT INTO my_workspace.ops.event_log |
| 67 | + SELECT c.* |
| 68 | + FROM my_workspace.raw.events VERSION AS OF :current_version AS c |
| 69 | + LEFT ANTI JOIN my_workspace.raw.events VERSION AS OF :parent_version AS p |
| 70 | + ON c.event_id = p.event_id; |
| 71 | +~~~ |
| 72 | + |
| 73 | +### Redefine an Existing Task |
| 74 | +~~~sql |
| 75 | +CREATE OR REPLACE TASK my_workspace.ops.ingest_events AS |
| 76 | + SELECT 1; |
| 77 | +~~~ |
| 78 | + |
| 79 | +## Notes |
| 80 | + |
| 81 | +- **You may only create a task you could run yourself.** Creating one requires `reader` on |
| 82 | + everything the statement reads and `writer` where it writes, checked against you at the |
| 83 | + time you create it and again every time you redefine it. Without that, a task would let |
| 84 | + anyone define work over data they cannot see and have a privileged identity run it. |
| 85 | +- **The task runs as you.** There is no syntax for naming another principal — an argument |
| 86 | + that could is the escalation above, written out. Ownership survives `OR REPLACE`, so |
| 87 | + editing a task never quietly transfers whose authority it runs with. |
| 88 | +- **Platform identities cannot own tasks.** They can read a great deal but have no billing |
| 89 | + account, so a task pinned to one would run on a schedule forever and land on nobody's |
| 90 | + bill. Own a task as a user or a service account. |
| 91 | +- The statement is parsed when the task is created, so SQL that could never run is refused |
| 92 | + now rather than discovered when it fires. It is not fully planned — a task's placeholders |
| 93 | + have no values yet, and planning would demand them. |
| 94 | +- A task cannot create, drop, or run another task. |
| 95 | +- Relations inside the statement must be **fully qualified**. A task is planned with no |
| 96 | + implicit workspace, so a two-part name cannot be resolved. |
0 commit comments