# FINISH {bdg-primary-line}`GQL clause` {bdg-secondary-line}`Added in 2.18` Ends a query without projecting anything: the work runs, and the query returns an empty result. ## Synopsis
FINISH

bold keywords · italic placeholders you supply · [ ] optional · ... repeatable. See Syntax conventions.

## Description Every query has to end with `RETURN`, `FINISH` or a write clause. `FINISH` is the ending that says "produce no result": it takes no arguments, projects no columns and closes the statement. - `FINISH` must be the **last** clause. Anything after it raises `FINISH must be at the end of the query`. - After a read, `FINISH` discards the rows. The planner applies it as `LIMIT 0`, so the scan is opened but no row is fetched. - After a write, the write still happens. `FINISH` only suppresses the projection. - A query ending in `FINISH` returns an **empty result**: no columns and no rows. `psql` prints it as a `--` header followed by `(0 rows)`, and `\gdesc` reports `The command has no result, or the result has no columns.` - A write that ends in `FINISH` reports its ordinary command tag instead of a result, such as `UPDATE 1` for one created vertex. ## Examples Every example runs against [the example dataset](../../get_started/example-dataset.md). Run a read for its plan and nothing else. There is no Cypher spelling of this. A Cypher query with no `RETURN` and no write clause is rejected: ```cypher MATCH (m:movie) FINISH; ``` ``` -- (0 rows) ``` ### Perform a write without reading the result back `CREATE … FINISH` is the form to reach for when you do not want the created elements shipped to the client: ```cypher CREATE (:movie {title: 'Tenet', year: 2020, genre: 'Action'}) FINISH; ``` ``` UPDATE 1 ``` The vertex is there: ```cypher MATCH (m:movie {title: 'Tenet'}) RETURN m.title AS film, m.year AS year; ``` ``` film | year ---------+------ "Tenet" | 2020 (1 row) ``` ### Confirm that a read costs nothing after FINISH The plan shows the `LIMIT 0` the clause compiles to, above the scan it never draws from: ```cypher EXPLAIN (COSTS OFF) MATCH (m:movie) FINISH; ``` ``` QUERY PLAN --------------------------- Limit -> Seq Scan on movie m (2 rows) ``` A write plan keeps its write node, because the write is not optional: ```cypher EXPLAIN (COSTS OFF) CREATE (:movie {title: 'Tenet'}) FINISH; ``` ``` QUERY PLAN -------------- Graph Create -> Result (2 rows) ``` ### End a sorted query that projects nothing `ORDER BY`, `SKIP`, `OFFSET` and `LIMIT` are clauses in their own right, but none of them can end a query. `FINISH` closes a pipeline that ends on one: ```cypher MATCH (m:movie) ORDER BY m.year LIMIT 3 FINISH; ``` ``` -- (0 rows) ``` Without the `FINISH` the same query raises `Cypher query must end with RETURN, FINISH or update clause`. ## Notes `FINISH` is not accepted where a result is required. A `CALL { }` body must project something, so a body ending in `FINISH` raises `CALL subquery must RETURN at least one variable`. A query ending in `FINISH` cannot be the left operand of [`NEXT`](next.md) either. That raises `FINISH cannot be followed by NEXT`. ```{note} `finish` became a reserved keyword in 2.18. It is still accepted unquoted as a label name in a pattern, `MATCH (n:finish)`, which is what an upgraded database needs. It is not accepted as a variable name, a `CREATE VLABEL` name or a SQL identifier; write `"finish"` there, or rename. Property keys and `RETURN` aliases are unaffected. ``` ## Compatibility ```{admonition} GQL conformance :class: gql-conformance Implements `FINISH` of the GQL *primitive result statement* (ISO/IEC 39075:2024 §14.10). The standard specifies that `FINISH` has "the empty type" and sets the execution outcome to "a successful outcome with an omitted result", which is what the empty, column-less result above represents. - **Supported** — `FINISH` as the terminal statement of a read query and of a data-modifying query, in which case the standard makes it implicit anyway (§13.1). - **Not supported** — `FINISH` as a branch of a set operation, which the standard also forbids (§14.2, Syntax Rule 5). AgensGraph rejects it as a column-count mismatch: `each UNION query must have the same number of columns`. Track status in the [GQL conformance matrix](../../appendix/gql-conformance.md). ``` ### openCypher openCypher has no `FINISH`. There, a read query must end with `RETURN`, and a write query may end with its write clause. AgensGraph accepts that second form too, so `FINISH` adds the read case rather than replacing anything. ## See also - [`RETURN`](return.md) — the other way to end a query - [`ORDER BY`](order-by.md) and [`SKIP` and `LIMIT`](skip-and-limit.md) — clauses that need a terminator - [`NEXT`](next.md) {bdg-secondary-line}`GQL` — the one clause `FINISH` may not precede - [`INSERT`](insert.md) {bdg-secondary-line}`GQL` — a write worth ending with `FINISH` - [GQL conformance matrix](../../appendix/gql-conformance.md)