Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

CREATE ROW POLICY

Создаёт ROW POLICY, то есть фильтр, который определяет, какие строки пользователь может читать из таблицы.

Синтаксис:

-- 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.

Несколько имён и таблиц

Допустимо:

-- 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;

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

-- 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

USING предложение

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

Предложение TO

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

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

Предложение AS

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

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

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.

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

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

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

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.

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

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

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.

Распределённые таблицы и таблицы с удалённым доступом к данным

ROW POLICY фильтрует строки там, где фактически читаются данные таблицы. Таблица, делегирующая чтение удалённым серверам, например таблица Distributed или обёртка над ней (например, materialized view с целью Distributed), отправляет удалённым серверам только текст запроса и не может применить фильтр политики при удалённом чтении. Чтобы фильтр не был незаметно отброшен, запросы к такой таблице от пользователей, к которым применяется политика, отклоняются с ошибкой ILLEGAL_PREWHERE.

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

-- 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;

Предложение ON CLUSTER

Позволяет создавать политики строк в кластере, см. Distributed DDL. Это также удобный способ создать политику для локальных таблиц каждого сервера кластера.

Примеры

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

Navigation