> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-parallel-read-in-order-multi-part.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> توثيق سياسة الصفوف

# CREATE ROW POLICY

ينشئ [سياسة الصفوف](/ar/concepts/features/security/access-rights#row-policy-management)، أي عامل تصفية يُستخدم لتحديد الصفوف التي يمكن للمستخدم قراءتها من جدول.

<Tip>
  لا تكون سياسات الصفوف مجدية إلا للمستخدمين الذين لديهم وصول readonly. إذا كان بإمكان المستخدم تعديل جدول أو نسخ partition بين الجداول، فإن ذلك يُلغي قيود سياسات الصفوف.
</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 | NONE}]
    [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 | NONE}]
    [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 | NONE}]
    [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` منفصلة عندما يلزم إنشاء سياسات على عناقيد مختلفة.

تتطلب `CREATE ROW POLICY` صلاحية [CREATE ROW POLICY](/ar/reference/statements/grant#access-management) على الجدول الذي تُنشأ عليه السياسة. أما `OR REPLACE` فتتخلص من سياسة قائمة تحمل الاسم نفسه، بما في ذلك الأدوار التي تنطبق عليها، ولذلك تتطلب أيضًا صلاحية [DROP ROW POLICY](/ar/reference/statements/grant#access-management) على ذلك الجدول. وصلاحية `DROP ROW POLICY` مطلوبة سواء أكانت السياسة موجودة مسبقًا أم لا، لذا لا يمكن استخدام العبارة لمعرفة السياسات الموجودة.

## أسماء وجداول متعددة

صحيح:

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

## عبارة USING

تتيح تحديد شرط لتصفية الصفوف. يرى المستخدم صفًا إذا كانت قيمة الشرط المحسوبة لهذا الصف غير صفرية.

## عبارة TO

في قسم `TO`، يمكنك تحديد قائمة بالمستخدمين والأدوار التي تنطبق عليها هذه السياسة. على سبيل المثال، `CREATE ROW POLICY ... TO accountant, john@localhost`.

تعني الكلمة المفتاحية `ALL` جميع مستخدمي ClickHouse، بما في ذلك المستخدم الحالي. وتتيح الكلمة المفتاحية `ALL EXCEPT` استبعاد بعض المستخدمين من قائمة جميع المستخدمين، على سبيل المثال، `CREATE ROW POLICY ... TO ALL EXCEPT accountant, john@localhost`

تتم مطابقة الأدوار المذكورة في قسم `TO`، بما في ذلك تلك الواردة بعد `ALL EXCEPT`، مع الأدوار المفعّلة للمستخدم الحالي ([`system.enabled_roles`](/ar/reference/system-tables/enabled_roles))، وليس مع كل دور مُمنَح للمستخدم، لذا يمكن أن يغيّر [`SET ROLE`](/ar/reference/statements/set-role) السياسات التي تنطبق.

## عبارة AS

يُسمح بتفعيل أكثر من سياسة واحدة على الجدول نفسه للمستخدم نفسه في الوقت ذاته. لذلك نحتاج إلى طريقة لدمج الشروط الواردة من سياسات متعددة.

افتراضيًا، تُدمَج السياسات باستخدام العامل المنطقي `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 = (one or more of the conditions from the permissive policies that apply to the current user and their enabled roles are non-zero) AND
                 (all of the conditions from the restrictive policies that apply to the current user and their enabled roles are non-zero)
```

إذا لم ينطبق أي شرط متساهل، فلن يكون للشرط الأول أي تأثير وتتولى السياسات المقيِّدة وحدها تحديد النتيجة، لأن `access_control_improvements.users_without_row_policies_can_read_rows` مفعَّل افتراضيًا. وبالتالي فإن المستخدم الذي لا ينطبق عليه أي شرط يرى كل صف، أما `access_control_improvements.throw_on_unmatched_row_policies`، المعطَّل افتراضيًا، فيثير استثناءً بدلاً من ذلك عندما تكون للجدول شروط ولا ينطبق أي منها.

على سبيل المثال، السياسات التالية:

```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` AND `c=2` معًا، رغم أن أي جدول آخر في mydb لن تُطبَّق عليه للمستخدم سوى سياسة `b=1`.

## جداول Distributed والجداول المعتمدة على خوادم بعيدة

تُصفّي سياسة الصفوف الصفوف في الموضع الذي تُقرأ فيه بيانات الجدول فعليًا. فالجدول الذي يفوّض القراءة إلى خوادم بعيدة، مثل جدول [Distributed](/ar/reference/engines/table-engines/special/distributed) أو طبقة تغليف فوقه (مثل عرض مادي له هدف `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>
  يعمل هذا ما دام query تُرسَل كنص، وهو السلوك الافتراضي. عند استخدام [`serialize_query_plan = 1`](/ar/reference/settings/session-settings/serialize#serialize_query_plan)، يرسل initiator بدلاً من ذلك plan قراءة مُعدّة مسبقاً، ولا يطبّق remote server الذي ينفّذ هذه plan سياسات الصفوف الخاصة به. لذلك، تُرجع قراءة table من نوع `Distributed` عبر `local_table` صفوفاً غير مُرشّحة. أبقِ `serialize_query_plan = 0` للمستخدمين الذين يجب فرض سياسات الصفوف عليهم. راجع [issue #112891](https://github.com/ClickHouse/ClickHouse/issues/112891).
</Warning>

## عبارة ON CLUSTER

تسمح بإنشاء سياسات الصفوف على مستوى العنقود، راجع [DDL الموزع](/ar/reference/statements/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`
