# Row-policy statements (/docs/reference/sql/statements/row-policy)



Row-policy statements [#row-policy-statements]

This page describes statements accepted by the Query API in RawTree Cloud
and RawTree BYOC. Its restrictions apply to the API, not to all RawTree SQL.
See [ClickHouse compatibility and API scope](/docs/reference/clickhouse-compatibility).

Syntax [#syntax]

```sql
CREATE ROW POLICY [IF NOT EXISTS | OR REPLACE] <name>
  [ON CLUSTER 'default'] ON [<database>.]<table>
  [AS PERMISSIVE | AS RESTRICTIVE] [FOR SELECT]
  USING <expression> TO <existing role>, ...
DROP ROW POLICY [IF EXISTS] <name>
  [ON CLUSTER 'default'] ON [<database>.]<table>
```

Clauses [#clauses]

| Clause           | Meaning                             |
| ---------------- | ----------------------------------- |
| `OR REPLACE`     | Replace the named policy.           |
| `AS PERMISSIVE`  | Combine matching policies with OR.  |
| `AS RESTRICTIVE` | Combine matching policies with AND. |
| `FOR SELECT`     | Apply the policy to reads.          |
| `USING`          | The row predicate.                  |

<a id="rawtree-behavior" />

Query API behavior [#query-api-behavior]

* **Supported:** One policy on one table per request, assigned to existing
  roles; omit `ON CLUSTER` for replicated access storage.
* **Not exposed by the Query API:** `ALTER ROW POLICY`, subqueries, user targets, `USING
  NONE`, and statements for other clusters.
* **Query API scope:** The selected database is mandatory for an
  unqualified table, and `ON CLUSTER` requires a qualified table.

Errors [#errors]

Error: `Unsupported row policy statement.`

Hint:

```text
Use CREATE ROW POLICY [IF NOT EXISTS | OR REPLACE] <name> [ON CLUSTER 'default'] ON [database.]<table> [AS PERMISSIVE | AS RESTRICTIVE] [FOR SELECT] USING <expression> TO <existing roles>, or DROP ROW POLICY [IF EXISTS] <name> [ON CLUSTER 'default'] ON [database.]<table>. Select the target database with the database parameter; ON CLUSTER requires database.table. Submit one policy on one table; subqueries and user targets are not supported.
```

Examples [#examples]

Create a role for the policy.

```sql test
CREATE ROLE acme_statement_reader
```

Grant access to the event table.

```sql test
GRANT SELECT ON analytics.events TO acme_statement_reader
```

Create a permissive policy.

```sql test
CREATE ROW POLICY acme_statement_only ON events FOR SELECT USING __raw_data.tenant::String = 'acme' TO acme_statement_reader
```

Replace the policy with a narrower condition.

```sql test
CREATE ROW POLICY OR REPLACE acme_statement_only ON events FOR SELECT USING __raw_data.tenant::String = 'acme' AND __raw_data.environment::String = 'prod' TO acme_statement_reader
```

Drop the policy.

```sql
DROP ROW POLICY IF EXISTS acme_statement_only ON events
```

Drop the role after the policy.

```sql
DROP ROLE IF EXISTS acme_statement_reader
```

The parser rejects `ALTER ROW POLICY`.

```sql test expect-error="Unsupported ALTER statement."
ALTER ROW POLICY acme_statement_only ON events USING 1
```

The parser rejects subqueries.

```sql test expect-error="Unsupported row policy statement."
CREATE ROW POLICY tenant_filter ON events USING (SELECT 1) TO acme_statement_reader
```

The parser rejects user targets.

```sql test expect-error="Unsupported row policy statement."
CREATE ROW POLICY tenant_filter ON events USING 1 TO USER analytics_user
```

The parser rejects `USING NONE`.

```sql test expect-error="Unsupported row policy statement."
CREATE ROW POLICY tenant_filter ON events USING NONE TO acme_statement_reader
```

The parser rejects other clusters.

```sql test expect-error="Unsupported row policy statement."
CREATE ROW POLICY tenant_filter ON CLUSTER 'other' ON analytics.events USING 1 TO acme_statement_reader
```

Related [#related]

* [Access control](/docs/concepts/access-control)
* [Apply row-level security](/docs/guides/secure/row-level-security)
