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

> تُعدِّد تنسيقات التأطير إرسال البيانات والإجماليات والقيم المتطرفة والتقدّم وأحداث ملف التعريف وسجلات الخادم ضمن دفق استجابة واحد عبر HTTP

# تنسيقات التأطير

يُعدِّد تنسيق التأطير إرسال أجزاء مختلفة من استجابة الاستعلام ضمن دفق واحد: أجزاء البيانات، والإجماليات والقيم المتطرفة، وحزم التقدّم، وأحداث ملف التعريف (المقاييس)، وسجلات الخادم — أي كل ما يدعمه البروتوكول الأصلي. ويتيح ذلك تبادل بيانات غنيًا عبر بروتوكول HTTP.

تنسيقات التأطير مستقلة عن [تنسيقات الإخراج](/docs/ar/reference/formats): إذ تغلف البايتات التي ينتجها أي تنسيق إخراج، بفصل أجزاء البايتات هذه وترميزها عند الحاجة. إن ربط حمولات جميع حزم `data` و`totals` و`extremes` ينتج بالضبط ما كان سينتجه تنسيق الإخراج من دون تأطير. وتُمثَّل الحزم المساعدة (التقدّم والسجلات وأحداث ملف التعريف والاستثناءات) بصيغة JSON.

يمكن للتأطير أيضًا أن يجعل تنسيق الإخراج أكثر قدرةً على التعبير — وهذا هو الاستثناء المقصود الوحيد للقاعدة أعلاه. تحذف عائلة تنسيقات `JSONCompactEachRow` الإجماليات والقيم المتطرفة من مخرجاتها العادية، لأن صفوفها لا يمكن تمييزها عن صفوف البيانات العادية. وفي تنسيق مؤطَّر، يميّز نوع الحزمة بينها، لذا تُصدر هذه التنسيقات صفوف الإجماليات والقيم المتطرفة (بصياغة الصفوف المعتادة) في حزم `totals` و`extremes`. بالنسبة إلى هذه التنسيقات، ينتج ربط حمولات حزم `data` وحدها بالضبط ما كان سينتجه تنسيق الإخراج من دون تأطير، بينما تحمل حزم `totals` و`extremes` صفوفًا إضافية لا تتضمنها المخرجات غير المؤطَّرة — لذا ينبغي للعميل الذي يعيد إنشاء المخرجات غير المؤطَّرة من هذا الدفق أن يربط حمولات `data` فقط.

يُختار تنسيق التأطير من خلال الإعداد على مستوى الاستعلام `framing_output_format`. وينطبق حاليًا على بروتوكول HTTP ويُتجاهل في الواجهات الأخرى.

تُضمَّن سجلات الخادم كحزم إذا تم تعيين الإعداد `send_logs_level`. وتُضمَّن أحداث ملف التعريف إذا كان الإعداد `send_profile_events` مفعّلًا (وهو مفعّل افتراضيًا). وتُرسل حزم التقدّم وأحداث ملف التعريف مرة واحدة على الأكثر كل `interactive_delay` ميكروثانية.

ينتهي الدفق الناجح بحزمة `progress` نهائية تحمل العدادات النهائية (`result_rows` و`result_bytes` و`memory_usage`)، على غرار حزمة التقدّم النهائية في البروتوكول الأصلي. لا تُعرف هذه العدادات إلا بعد انتهاء الاستعلام، لذلك لا تحملها أي حزمة `progress` سابقة. وتُكتب حزمة `progress` النهائية بعد حزم `log` و`profile_events` الختامية التي يصدرها تسجيل انتهاء الاستعلام (مثل إدخال السجل "ذروة استخدام الذاكرة")، لذا فهي بالفعل الحزمة الأخيرة في الدفق. وعند الفشل، تكون حزمة `exception` هي الحزمة الأخيرة بدلًا منها، ولا تُكتب حزمة `progress` ذات العدادات النهائية إطلاقًا — إذ إنها مؤشر انتهاء الدفق بنجاح — حتى إذا حدث الفشل بعد انتهاء الاستعلام نفسه ومعرفة العدادات النهائية بالفعل (مثلًا، عند حدوث فشل أثناء كتابة سجل الاستعلام).

لأن هذا الجزء الختامي من الدفق يُكتب بعد تسجيل إدخال `QueryFinish` في `system.query_log`، فإن أحداث ملف التعريف الخاصة بإرسال الشبكة للاستعلام (`NetworkSendBytes` و`NetworkSendElapsedMicroseconds`) لا تشمل إرسال الحزم الختامية وإغلاق الاستجابة — ولا تشمل، عندما تكون الاستجابة مخزنة مؤقتًا (`http_response_buffer_size` أو `wait_end_of_query`)، إرسال جسم الاستجابة المخزن مؤقتًا، الذي لا يُنقل إلا بعد انتهاء الاستعلام. ويتوافق هذا مع البروتوكول الأصلي، الذي يرسل أيضًا سجلاته الختامية وأحداث ملف التعريف بعد إدخال سجل الاستعلام.

أي شيء لا يفعّله الاستعلام إلا عبر عبارة `SETTINGS` الخاصة به — سواء كان تنسيق تأطير أو `send_logs_level` أو `send_profile_events` — لا يُعرف إلا بعد تحليل الاستعلام، لذا لا تُلتقط السجلات وأحداث ملف التعريف المقابلة إلا بدءًا من تنفيذ الاستعلام. ولا تُلتقط السجلات وأحداث ملف التعريف الخاصة بمرحلة التحليل والتخطيط والاستدلال إلا عندما يأتي الإعداد من الجلسة أو URL. وبوجه خاص، فإن الاستعلام الذي يفشل أثناء التحليل (قبل تنفيذ المسار) — مثل الإشارة إلى جدول غير معروف — ويُفعّل `send_logs_level` فقط في عبارة `SETTINGS` الخاصة به، لا يرسل سوى حزمة `exception`، وليس سجلات مرحلة التحليل. عيّن `send_logs_level` في الجلسة أو URL لالتقاط تلك السجلات.

ينطبق التحذير نفسه بشأن الاكتشاف المتأخر على `send_logs_source_regexp`: إذ ترشّح قائمة انتظار السجل الإدخالات حسب المصدر لحظة التقاط كل إدخال، لذا لا يصبح التعبير النمطي المضبوط في عبارة `SETTINGS` الخاصة بالاستعلام نافذًا إلا من وقت تنفيذ الاستعلام فصاعدًا. تُرشّح حزم `log` الخاصة بمراحل التحليل والتخطيط والمعالجة وفقًا لقيمة الإعداد في الجلسة أو URL — وتبقى غير مرشحة إذا لم يُضبط الإعداد هناك — لذا قد تتضمن مصادر لا تطابق التعبير النمطي على مستوى الاستعلام. وعلى العكس، فإن الإدخالات التي يستبعدها تعبير نمطي أضيق في الجلسة أو URL تُفقد ولا يستعيدها تعبير أوسع على مستوى الاستعلام. اضبط `send_logs_source_regexp` في الجلسة أو URL لترشيح دورة حياة الاستعلام بأكملها.

إذا حدث استثناء أثناء تنفيذ الاستعلام، يُرسل في حزمة `exception` (وهي آخر حزمة في الدفق)، بغض النظر عن إعداد `http_write_exception_in_output_format`، لكي يتمكن العميل دائمًا من تحليل الاستجابة كدفق من الحزم. بعد تسجيل الاستثناء، لا يضيف تنسيق الإخراج أي بايتات أخرى إلى الحمولة: فالاستعلام الذي يفشل قبل إنتاج أي مخرجات لا يرسل أي حزمة `data` على الإطلاق (ولا حتى البنية الفارغة للمستند الخاصة بالتنسيق)، أما الاستعلام الذي يفشل في منتصف الدفق فيترك الحمولة المتسلسلة مقتطعة عند نقطة الفشل، من دون لاحقة التنسيق — إذ يجب ألا تبدو حمولة الاستعلام الفاشل كمستند مكتمل.

يوجد استثناء واحد لهذه القاعدة: إذا فشلت كتابة الحزمة نفسها في منتصفها (مثلًا عند انقطاع الاتصال بعد أن تكون بعض بايتات الحزمة قد وصلت إلى العميل)، يفشل التأطير بصورة مغلقة ويُنهي الدفق من دون حزمة `exception` نهائية. ولا يعيد محاولة إرسال حزمة كُتبت جزئيًا مطلقًا، لأن إعادة إرسالها ستلحق نسخة مكررة بعد البايتات المقتطعة وتفسد الدفق. في هذه الحالة، يلاحظ العميل استجابة مقتطعة واتصال HTTP مُجهضًا بدلًا من حزمة نهائية سليمة البنية. وتنطبق القاعدة نفسها على الفشل أثناء إغلاق دفق الاستجابة ذاته (تفريغ النتائج المخزنة مؤقتًا، وإنهاء ضغط HTTP، وإغلاق المقبس): إذ يكون جزء من دفق النجاح أو كله قد أصبح بالفعل في تنسيق النقل، لذلك لا يُلحق به شيء — لا حزمة `exception` ولا كتلة خطأ HTTP العامة — ويلاحظ العميل استجابة مقتطعة واتصالًا مُجهضًا. وتنطبق أيضًا عند فشل تسليم الاستثناء نفسه: فإذا فشلت كتابة حزمة `exception` النهائية (مثلًا أثناء تصريف السجلات الختامية) بعد إنتاج أي جزء من دفق الحزم — سواء أُرسل بالفعل أو ما زال في مخازن الاستجابة المؤقتة من جانب الخادم (`http_response_buffer_size`) — يُنهى الدفق كذلك من دون إلحاق أي شيء، لذلك لا يُمزج نص خطأ HTTP عادي مطلقًا ضمن دفق حزم جزئي. ويُعد الفشل أثناء كتابة حقول السلاسل النصية للحزم المساعدة `log` و`profile_events` و`exception` حزمة مكتوبة جزئيًا أيضًا، بما في ذلك الفشل في كتابة البايتات الأخيرة من مثل هذا الحقل: ينتهي الدفق حينها بهذه الحزمة المقتطعة ولا يحمل أي مُنهٍ على الإطلاق — لا حزمة `exception` ولا حزمة `progress` ذات العدادات النهائية — وبذلك يكتشف العميل الذي يتطلب مُنهِيًا الفشل حتى عندما ينجح الاستعلام نفسه.

يُطبّق تنسيق تأطير أيضًا على الاستعلامات التي لا تنتج دفق نتائج — مثل `INSERT` ناجح، أو استعلام DDL، أو أي استعلام آخر بلا مخرجات. لا تحمل هذه الاستجابة حزم `data`، لكنها تبدّل `Content-Type` الخاص بالاستجابة إلى تنسيق التأطير وتبث حزم `progress` و`log` و`profile_events`، بما يتوافق مع البروتوكول الأصلي. ينتهي الدفق بحزمة `progress` نهائية تحمل العدادات النهائية (مثلًا `result_rows` و`result_bytes` مع عدد الصفوف المكتوبة لعملية `INSERT`). وبما أنه لا تُنسّق أي حمولة، فإن تنسيق الإخراج غير ذي صلة بهذه الاستعلامات ولا يؤثر في الدفق المؤطّر.

<div id="available-framing-formats">
  ## تنسيقات التأطير المتاحة
</div>

| الاسم                                                    | الوصف                                                        |
| -------------------------------------------------------- | ------------------------------------------------------------ |
| [`None`](#framing-format-none)                           | بدون تأطير: يعمل كل شيء كما هو افتراضيًا.                    |
| [`EventStream`](#framing-format-eventstream)             | أحداث يرسلها خادم HTTP (`text/event-stream`).                |
| [`JSONEachPacketBase64`](#framing-format-jsoneachpacket) | كائن JSON لكل حزمة؛ البيانات المنسقة مُرمَّزة بترميز Base64. |
| [`JSONEachPacketString`](#framing-format-jsoneachpacket) | كائن JSON لكل حزمة؛ تُوضع البيانات المنسقة في سلسلة JSON.    |

<div id="framing-format-none">
  ## None
</div>

الخيار الافتراضي. يمرّر بشفافية كل ما ينطبق (البيانات، الإجماليات، القيم القصوى، التقدم) إلى تنسيق الإخراج، ويتجاهل كل ما لا ينطبق (المقاييس، السجلات). وبذلك يعمل كل شيء كما هو افتراضيًا، بما في ذلك التنسيقات التي تمثل التقدم بنفسها، مثل `JSONEachRowWithProgress`.

<div id="framing-format-eventstream">
  ## EventStream
</div>

يؤطّر الحزم على هيئة [أحداث يرسلها خادم HTTP](https://html.spec.whatwg.org/multipage/server-sent-events.html)، ويضبط `Content-Type` للاستجابة على `text/event-stream; charset=UTF-8; payload=base64`. تُرسل كل حزمة كحدث يحمل اسم نوع الحزمة: `data`، `totals`، `extremes`، `progress`، `log`، `profile_events`، `exception`. وتُرسل حزم التقدم وغيرها من الحزم المساعدة بصيغة JSON.

الأحداث التي يرسلها الخادم بروتوكول نصي يتعامل مع فواصل الأسطر، بما في ذلك محارف إرجاع العربة (`\r`)، بوصفها فواصل للحقول؛ لذا لا تُضمَّن البايتات التي ينتجها تنسيق الإخراج حرفيًا. بل تُرمَّز كتلة من البيانات المنسّقة بترميز base64 في حقل `data:` واحد، ويُفك ترميزها إلى الحمولة المنسّقة بالكامل، بما فيها جميع أسطرها الجديدة. وهذا ما يوضحه المَعْلَم `payload=base64` في `Content-Type`. إن تسلسل الحمولات المفككة الترميز لحزم `data` و`totals` و`extremes` يطابق تمامًا، بايتًا ببايت، ما كان سينتجه تنسيق الإخراج دون تأطير، لأي تنسيق إخراج، سواء كان نصيًا أو ثنائيًا (`Native`، `RowBinary`) أو تمريرًا خامًا (`RawBLOB`، `TSVRaw`).

لا تُرمَّز حزم JSON المساعدة (`progress`، `log`، `profile_events`، `exception`) مطلقًا؛ إذ تُكتب في حقل `data:` واحد يحتوي على JSON بلا فواصل أسطر.

تكتب تنسيقات الإخراج `*WithProgress` (`JSONEachRowWithProgress`، `JSONCompactEachRowWithProgress`) التقدم كصفوف مضمّنة تشكل جزءًا من مخرجاتها. أما تنسيق التأطير فيرسل التقدم كحزم `progress` منفصلة، لذا فهو غير متوافق مع تنسيقات الإخراج هذه ويرفضها. استخدم تنسيق الإخراج الأساسي، مثل `JSONEachRow`، مع التأطير، أو التأطير `None` مع تنسيق `*WithProgress`.

```bash theme={null}
curl "http://localhost:8123/?framing_output_format=EventStream" -d "SELECT number FROM numbers(3) FORMAT JSONEachRow"
```

```text theme={null}
event: data
data: eyJudW1iZXIiOiIwIn0KeyJudW1iZXIiOiIxIn0KeyJudW1iZXIiOiIyIn0K

event: profile_events
data: [{"host_name":"localhost","current_time":"2026-07-11 00:00:00","thread_id":"0","type":"increment","name":"SelectedRows","value":"3"},{"host_name":"localhost","current_time":"2026-07-11 00:00:00","thread_id":"0","type":"increment","name":"SelectedBytes","value":"24"}]

event: progress
data: {"read_rows":"3","read_bytes":"24","total_rows_to_read":"3","result_rows":"3","result_bytes":"24","elapsed_ns":"1174415"}

```

يتكامل `EventStream` مع بروتوكول HTTP ويُطلق استثناءً عندما لا يكون منطبقًا.

<div id="framing-format-jsoneachpacket">
  ## JSONEachPacketBase64 وJSONEachPacketString
</div>

كل حزمة هي كائن JSON في سطر منفصل (JSON محدد بأسطر جديدة، `application/x-ndjson`) وتحتوي على معلومات عن الحزمة. توضع البايتات التي ينتجها تنسيق الإخراج في الحقل `data`: بترميز base64 في `JSONEachPacketBase64` (وهو مناسب لتنسيقات الإخراج الثنائية)، أو كسلسلة JSON في `JSONEachPacketString`.

يُرمِّز البديلان الحقل `data` بطرائق مختلفة، لذا يميّز `Content-Type` الخاص بالاستجابة بينهما، كما في `EventStream`: يضبط `JSONEachPacketBase64` القيمة `application/x-ndjson; charset=UTF-8; payload=base64`، بينما يضبط `JSONEachPacketString` القيمة `application/x-ndjson; payload=string`. لذلك، يمكن للعميل أن يعرف من البيانات الوصفية للاستجابة وحدها ما إذا كان الحقل `data` يحتاج إلى فك ترميز base64. ولا يضمن `charset=UTF-8` سوى `JSONEachPacketBase64`، لأن ترميز base64 وحده يجعل الدفق بأكمله UTF-8 صالحًا، بغض النظر عن بايتات الحمولة — انظر أدناه.

بما أن `JSONEachPacketString` يضع بايتات الحمولة في سلسلة JSON، فهو مخصص لتنسيقات الإخراج التي تنتج نص UTF-8 صالحًا. يمكن للأعمدة `String` و`FixedString` أن تحتوي على بايتات عشوائية، لذا قد تُنتج تنسيقات الإخراج النصية، مثل `JSONEachRow` أو `TSV` أو `CSV`، UTF-8 غير صالح لهذه القيم — تمامًا كما يفعل `JSONEachRow` الخاص بـ ClickHouse عند استخدام الإعداد الافتراضي `output_format_json_validate_utf8 = 0` — وعندئذٍ لا يُضمن أن تكون سلسلة JSON الناتجة، وبالتالي دفق NDJSON بأكمله، صالحة بتشفير UTF-8. لا يتحقق `JSONEachPacketString` من الحمولة ولا يعيد ترميزها؛ استخدم `JSONEachPacketBase64` لنقل البايتات العشوائية بدقة تامة.

يرفض `JSONEachPacketString` مسبقًا، مع ظهور خطأ قبل تنفيذ الاستعلام، تنسيقات الإخراج المعروفة بإنتاج بايتات غير UTF-8: التنسيقات الثنائية (`Native`، `RowBinary`)، وتنسيقات التمرير الخام (`RawBLOB`، `TSVRaw`)، والتنسيقات التي تكتب في مخرجاتها اسم عمود أو اسم نوع بيانات أو اسم عنصر `Tuple` غير UTF-8 من رأس الاستعلام، والتهيئات التي تُكتب فيها القيم الحرفية المستمدة من الإعدادات كما هي بواسطة عمليات التسلسل ولا تكون صالحة بتشفير UTF-8 — الإعدادات `format_csv_delimiter` و`format_tsv_null_representation` / `format_csv_null_representation` و`bool_true_representation` / `bool_false_representation`.

```bash theme={null}
curl "http://localhost:8123/?framing_output_format=JSONEachPacketString" -d "SELECT number FROM numbers(3) FORMAT JSONEachRow"
```

```text theme={null}
{"packet":"data","data":"{\"number\":\"0\"}\n{\"number\":\"1\"}\n{\"number\":\"2\"}\n"}
{"packet":"profile_events","profile_events":[{"host_name":"localhost","current_time":"2026-07-11 00:00:00","thread_id":"0","type":"increment","name":"SelectedRows","value":"3"}]}
{"packet":"progress","progress":{"read_rows":"3","read_bytes":"24","total_rows_to_read":"3","result_rows":"3","result_bytes":"24","elapsed_ns":"1265958"}}
```

باستخدام `JSONEachPacketBase64`، تكون حزمة `data` نفسها كما يلي:

```text theme={null}
{"packet":"data","data":"eyJudW1iZXIiOiIwIn0KeyJudW1iZXIiOiIxIn0KeyJudW1iZXIiOiIyIn0K"}
```

<div id="framing-format-packet-kinds">
  ## أنواع الحزم
</div>

| الحزمة           | المحتويات                                                                                                                                                               |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data`           | البايتات التي ينتجها تنسيق الإخراج للنتيجة الرئيسية، بما في ذلك بادئة التنسيق ولاحقته.                                                                                  |
| `totals`         | البايتات التي ينتجها تنسيق الإخراج لصف الإجماليات (`WITH TOTALS`).                                                                                                      |
| `extremes`       | البايتات التي ينتجها تنسيق الإخراج للقيم القصوى (إعداد `extremes`).                                                                                                     |
| `progress`       | تقدّم الاستعلام بصيغة JSON: `read_rows`، `read_bytes`، `total_rows_to_read`، `result_rows`، `result_bytes`، `elapsed_ns`، `memory_usage` (تُحذف الحقول ذات القيمة صفر). |
| `log`            | مُدخل في سجل الخادم بصيغة JSON: `event_time`، `host_name`، `query_id`، `thread_id`، `priority`، `source`، `text`.                                                       |
| `profile_events` | مصفوفة من أحداث ملف التعريف بصيغة JSON: `host_name`، `current_time`، `thread_id`، `type` (`increment` أو `gauge`)، `name`، `value`.                                     |
| `exception`      | رسالة الاستثناء بصيغة JSON.                                                                                                                                             |

على خلاف حمولات `data` و`totals` و`extremes` (راجع ملاحظات المطابقة التامة للبايتات أعلاه)، لا تتوفر لحقول السلاسل النصية في الحزم المساعدة (`query_id` و`text` و`source` في `log`، و`name` في `profile_events`، ورسالة `exception`) آلية إفلات باستخدام base64، ويمكن لبعضها، مثل `query_id` المأخوذ من الاستعلام، أن يحتوي على بايتات عشوائية. تُنقّى هذه الحقول دائمًا لتصبح UTF-8 صالحة، مع استبدال التسلسلات غير الصالحة بمحرف الاستبدال (`U+FFFD`)، وبذلك تكون الحزم المساعدة دائمًا JSON صالحًا.

لم تُنفَّذ بعد معالجة عدة استعلامات في وقت واحد، لكن التصميم يتيح ذلك: يمكن توسيع كل حزمة بمعلومات عن فهرس الاستعلام عند معالجة عدة استعلامات.
