> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> Документация по ROW POLICY

# CREATE ROW POLICY

Создаёт [ROW POLICY](/docs/ru/concepts/features/security/access-rights#row-policy-management), то есть фильтр, который определяет, какие строки пользователь может читать из таблицы.

<Tip>
  ROW POLICY имеют смысл только для пользователей с доступом только на чтение. Если пользователь может изменять таблицу или копировать партиции между таблицами, это сводит на нет ограничения, задаваемые ROW POLICY.
</Tip>

Синтаксис:

```sql theme={null}
-- Multiple names on one table target
CREATE [ROW] POLICY [IF NOT EXISTS | OR REPLACE] policy_name [, ...]
    [ON CLUSTER cluster_name]
    ON { [db.]table | db.* }
    [IN access_storage_type]
    [FOR SELECT] USING condition
    [AS {PERMISSIVE | RESTRICTIVE}]
    [TO {role1 [, role2 ...] | ALL | ALL EXCEPT role1 [, role2 ...]}]

-- One name on multiple table targets
CREATE [ROW] POLICY [IF NOT EXISTS | OR REPLACE] policy_name
    [ON CLUSTER cluster_name]
    ON { [db.]table | db.* } [, ...]
    [IN access_storage_type]
    [FOR SELECT] USING condition
    [AS {PERMISSIVE | RESTRICTIVE}]
    [TO {role1 [, role2 ...] | ALL | ALL EXCEPT role1 [, role2 ...]}]

-- Mixed packing: each name paired with its own table target
CREATE [ROW] POLICY [IF NOT EXISTS | OR REPLACE]
    policy_name ON { [db.]table | db.* } [, policy_name ON { [db.]table | db.* } ...]
    [ON CLUSTER cluster_name]
    [IN access_storage_type]
    [FOR SELECT] USING condition
    [AS {PERMISSIVE | RESTRICTIVE}]
    [TO {role1 [, role2 ...] | ALL | ALL EXCEPT role1 [, role2 ...]}]
```

`ParserRowPolicyNames` поддерживает **три** формы группировки (не полный декартов продукт):

1. **Несколько имён, одна цель** — `pol1, pol2 ON table1` создаёт каждую указанную политику для одной таблицы (или `db.*`).
2. **Одно имя, несколько целей** — `pol1 ON table1, table2` создаёт одну и ту же политику с кратким именем для каждой указанной цели.
3. **Смешанные пары** — `p1 ON t1, p2 ON t2` создаёт каждую политику только для соответствующей ей цели.

Список из нескольких имён **нельзя** объединить со списком из нескольких таблиц после `ON` в одной группе: `p1, p2 ON t1, t2` не принимается. После группы с несколькими именами также нельзя добавить другую разделённую запятыми группу `name ON target` в том же операторе.

Необязательное предложение `ON CLUSTER` применяется ко всему оператору (одно имя кластера). ClickHouse **не** поддерживает отдельное `ON CLUSTER` для каждого имени политики, сгруппированного в одном операторе создания — если политики необходимо создать в разных кластерах, выполните отдельные операторы `CREATE ROW POLICY`.

<div id="multiple-names-and-tables">
  ## Несколько имён и таблиц
</div>

Допустимо:

```sql theme={null}
-- Several policy names, one table
CREATE ROW POLICY pol1, pol2, pol3 ON table1
    FOR SELECT USING id = 1
    TO accountant;

-- One policy name, several tables
CREATE ROW POLICY IF NOT EXISTS pol1 ON table1, table2, table3
    FOR SELECT USING id = 1
    TO accountant;

-- Mixed packing: different name per table
CREATE ROW POLICY p4 ON db.table, p5 ON db2.table2
    USING a = b;

-- Same policy on several tables, on a cluster
CREATE ROW POLICY IF NOT EXISTS pol1 ON CLUSTER replicated_cluster ON table1, table2
    FOR SELECT USING id = 1
    TO accountant;
```

Недопустимо:

```sql theme={null}
-- Multi-name × multi-table in one ON-group (not a Cartesian product)
CREATE ROW POLICY p1, p2 ON t1, t2
    FOR SELECT USING id = 1
    TO accountant;

-- Different clusters per name in one statement
CREATE ROW POLICY pol1 ON CLUSTER cluster1 ON table1, pol2 ON CLUSTER cluster2 ON table2
```

<div id="using-clause">
  ## USING предложение
</div>

Позволяет задать условие для фильтрации строк. Пользователь увидит строку, если значение условия для этой строки не равно нулю.

<div id="to-clause">
  ## Предложение TO
</div>

В секции `TO` можно указать список пользователей и ролей, для которых должна действовать эта политика. Например, `CREATE ROW POLICY ... TO accountant, john@localhost`.

Ключевое слово `ALL` означает всех пользователей ClickHouse, включая текущего пользователя. Ключевое слово `ALL EXCEPT` позволяет исключить отдельных пользователей из списка всех пользователей, например: `CREATE ROW POLICY ... TO ALL EXCEPT accountant, john@localhost`

<div id="as-clause">
  ## Предложение AS
</div>

Допускается, чтобы для одной и той же таблицы и одного и того же пользователя одновременно было включено несколько политик. Поэтому нужен способ объединять условия из нескольких политик.

По умолчанию политики объединяются с помощью булева оператора `OR`. Например, следующие политики:

```sql theme={null}
CREATE ROW POLICY pol1 ON mydb.table1 USING b=1 TO mira, peter
CREATE ROW POLICY pol2 ON mydb.table1 USING c=2 TO peter, antonio
```

разрешить пользователю `peter` видеть строки, где либо `b=1`, либо `c=2`.

Предложение `AS` указывает, как политики должны сочетаться с другими политиками. Политики могут быть либо разрешающими, либо ограничивающими. По умолчанию политики являются разрешающими, то есть они объединяются с помощью булева оператора `OR`.

В качестве альтернативы политику можно задать как ограничивающую. Ограничивающие политики объединяются с помощью булева оператора `AND`.

Вот общая формула:

```text theme={null}
row_is_visible = (одно или несколько состояний разрешающих политик не равны нулю) AND
                 (все состояния ограничивающих политик не равны нулю)
```

Например, следующие политики:

```sql theme={null}
CREATE ROW POLICY pol1 ON mydb.table1 USING b=1 TO mira, peter
CREATE ROW POLICY pol2 ON mydb.table1 USING c=2 AS RESTRICTIVE TO peter, antonio
```

разрешить пользователю `peter` видеть строки только при одновременном выполнении условий `b=1` AND `c=2`.

Политики на уровне базы данных объединяются с политиками на уровне таблицы.

Например, следующие политики:

```sql theme={null}
CREATE ROW POLICY pol1 ON mydb.* USING b=1 TO mira, peter
CREATE ROW POLICY pol2 ON mydb.table1 USING c=2 AS RESTRICTIVE TO peter, antonio
```

разрешить пользователю `peter` видеть строки таблицы table1 только при одновременном выполнении условий `b=1` И `c=2`, хотя
для любой другой таблицы в mydb к пользователю применялась бы только политика `b=1`.

<div id="distributed-and-remote-backed-tables">
  ## Распределённые таблицы и таблицы с удалённым доступом к данным
</div>

ROW POLICY фильтрует строки там, где фактически читаются данные таблицы. Таблица, делегирующая чтение удалённым серверам, например таблица [Distributed](/docs/ru/reference/engines/table-engines/special/distributed) или обёртка над ней (например, materialized view с целью `Distributed`), отправляет удалённым серверам только текст запроса и не может применить фильтр политики при удалённом чтении. Чтобы фильтр не был незаметно отброшен, запросы к такой таблице от пользователей, к которым применяется политика, отклоняются с ошибкой `ILLEGAL_PREWHERE`.

Вместо этого определите политику для базовых локальных таблиц на каждом удалённом сервере: она будет применяться там, когда переданный запрос читает эти таблицы:

```sql theme={null}
-- Filters reads of local_table on this server, including reads shipped by a Distributed table over it.
CREATE ROW POLICY filter ON mydb.local_table USING a < 1000 TO john;
```

<Warning>
  Это работает, пока запрос передаётся в виде текста, что используется по умолчанию. При [`serialize_query_plan = 1`](/docs/ru/reference/settings/session-settings/serialize#serialize_query_plan) инициатор вместо этого передаёт уже сформированный план чтения, а удалённый сервер, выполняющий такой план, не применяет собственные ROW POLICY. Поэтому чтение таблицы `Distributed` через `local_table` возвращает неотфильтрованные строки. Для пользователей, к которым должны применяться ROW POLICY, сохраняйте значение `serialize_query_plan = 0`. См. [issue #112891](https://github.com/ClickHouse/ClickHouse/issues/112891).
</Warning>

<div id="on-cluster-clause">
  ## Предложение ON CLUSTER
</div>

Позволяет создавать политики строк в кластере, см. [Distributed DDL](/docs/ru/reference/statements/distributed-ddl). Это также удобный способ создать политику для локальных таблиц каждого сервера кластера.

<div id="examples">
  ## Примеры
</div>

`CREATE ROW POLICY filter1 ON mydb.mytable USING a<1000 TO accountant, john@localhost`

`CREATE ROW POLICY filter2 ON mydb.mytable USING a<1000 AND b=5 TO ALL EXCEPT mira`

`CREATE ROW POLICY filter3 ON mydb.mytable USING 1 TO admin`

`CREATE ROW POLICY filter4 ON mydb.* USING 1 TO admin`
