ترحيلات قاعدة البيانات
نظرة عامة
نستخدم نظام ترحيلات متسلسل لإدارة تغييرات قاعدة البيانات. جميع الترحيلات موجودة في:
infrastructure/supabase/migrations/
تسمية الملفات
00XXX_description.sql
00XXX- رقم تسلسلي (5 أرقام)description- وصف مختصر بالإنجليزية
أمثلة:
00001_complete_schema.sql
00023_create_seats_table.sql
00054_bus_templates.sql
00065_add_delayed_trip_status.sql
الترحيلات الرئيسية
| الرقم | الملف | الوصف |
|---|---|---|
| 00001 | complete_schema.sql | المخطط الكامل الأولي |
| 00010 | fix_audit_log_function.sql | إصلاح دالة سجل المراجعة |
| 00015 | add_missing_columns.sql | أعمدة مفقودة |
| 00016 | add_technical_issue_ticket_type.sql | نوع تذكرة جديد |
| 00023 | create_seats_table.sql | جدول المقاعد |
| 00028 | fix_schema_issues.sql | إصلاحات المخطط |
| 00029 | fix_passenger_rls.sql | سياسات RLS للركاب |
| 00030 | fix_bookings_rls.sql | سياسات RLS للحجوزات |
| 00035 | fix_null_seat_numbers.sql | إصلاح أرقام المقاعد |
| 00038 | maintenance_logs.sql | سجلات الصيانة |
| 00043 | email_verification.sql | التحقق من البريد |
| 00045 | atomic_booking.sql | الحجز الذري |
| 00047 | fix_critical_issues.sql | إصلاحات حرجة |
| 00048 | cascade_trip_cancellation.sql | إلغاء متسلسل |
| 00049 | fix_seat_lock_race_condition.sql | إصلاح تنافس القفل |
| 00054 | bus_templates.sql | قوالب الباصات |
| 00055 | layout_enhancements.sql | تحسينات التخطيط |
| 00056 | seat_configuration.sql | تكوين المقاعد |
| 00058 | fix_schema_mismatches.sql | إصلاح عدم التطابق |
| 00064 | fix_seat_numbers_type.sql | إصلاح نوع أرقام المقاعد |
| 00065 | add_delayed_trip_status.sql | حالة التأخير |
| 00068 | seed_bus_layouts.sql | بذر تخطيطات الباصات |
| 00116 | ensure_waitlist_table.sql | ضمان وجود جدول قائمة الانتظار وسياساته في البيئات التي بُدئت من baseline قديم |
| 00137 | restore_resource_contract_compatibility.sql | إعادة أعمدة وجداول ودوال توافقية تعتمد عليها واجهات الويب والموبايل وPostgREST |
| 00138 | fix_remaining_resource_contract_data.sql | استكمال بيانات التوافق: أسماء المدن والسائقين، أسعار المسارات، أكواد الحجز، ودالة get_booking_by_code |
| 00191 | public_trip_tracking.sql | عقد تتبع عام محدود بكود الحجز يعيد المسار والحالة وGPS ضمن نافذة زمنية من دون بيانات الراكب أو الدفع |
| 00194 | repair_seat_lock_booking_contract.sql | إصلاح قفل المقاعد المتسلسل، التحقق من ملكية جلسة القفل، الحجز الأحادي والذهاب والعودة الذري، وتسعير الخادم |
| 00195 | fix_alphanumeric_booking_cancellation.sql | إلغاء ذري آمن لأسماء المقاعد الحرفية مثل 1D مع إعادة السعة من trigger واحد |
| 00196 | atomic_company_booking_contract.sql | توحيد الأرقام الترتيبية والأسماء الفعلية وإضافة مخزون مقاعد وحجز مكتبي ذريين ومقيدين بالشركة |
| 00197 | enable_dispatcher_booking_cancellation.sql | مواءمة الإلغاء مع أدوار إدارة الحجوزات: السماح لمسؤول التشغيل مع إبقاء السائق مرفوضاً |
| 00198 | security_runtime_hardening.sql | إزالة سياسات anon التاريخية للحجوزات والركاب، جعل RPCs افتراضياً مغلقة، وإعادة تقييد دوال الإدارة والخدمة |
| 00199 | realtime_runtime_schema.sql | تثبيت مخطط Realtime التشغيلي وصلاحياته المطلوبة في بيئة الإنتاج الذاتية |
| 00200 | dashboard_analytics_snapshot.sql | تجميع تحليلات الشركة في RPC مفوض واحد ومنع روابط PostgREST الضخمة والنتائج المبتورة |
| 00201 | dashboard_advanced_analytics.sql | تجميع التحليلات المتقدمة في RPC واحد وتصحيح الإشغال والاحتفاظ ومنع تنزيل الحجوزات الخام والمكررة |
| 00202 | atomic_customer_booking_modification.sql | تعديل حجز العميل ذرياً بأسماء المقاعد الفعلية وتسعير الخادم وتحديث السعة وتدوير رموز الصعود |
| 00203 | secure_customer_trip_reviews.sql | ربط مراجعة العميل بحجزه ورحلته المكتملة ومنع تغيير الهوية أو حالة الإشراف من العميل |
| 00204 | atomic_loyalty_reward_redemption.sql | استبدال مكافآت الولاء ذرياً مع قفل الرصيد والمكافأة وحفظ لقطة شروط القسيمة |
| 00205 | apply_loyalty_rewards_to_customer_bookings.sql | معاينة قسيمة الولاء وتطبيقها مرة واحدة داخل حجز فردي أو ذهاب وعودة مع حفظ تفصيل السعر |
| 00206 | reassert_seat_capacity_ownership.sql | إعادة تثبيت trigger واحد لملكية سعة الرحلة ومصالحة السعة وتطبيع checksum لمسودة 00166 المعروفة فقط |
| 00207 | restrict_booking_price_trigger_function.sql | حجب تنفيذ دالة trigger الداخلية لتفصيل سعر الحجز عن anon وauthenticated |
| 00208 | reassert_offline_qr_token_contract.sql | إعادة تثبيت عقد رموز QR غير المتصلة وتطبيع checksum لمسودة 00181 التاريخية المعروفة فقط |
| 00209 | reassert_trip_message_driver_identity.sql | إعادة تثبيت سياسات هوية سائق محادثة الرحلة وتطبيع checksum لمسودة 00182 التاريخية المعروفة فقط |
| 00210 | unified_company_payment_ledger.sql | توحيد حقيقة دفع الحجز ودفتر تحصيل الشركة ومستخدمي قرارات التأكيد والاسترداد |
| 00211 | company_cash_reconciliation.sql | صندوق نقدي وتسلسل قرارات دفع ذرية مع إلغاء غير المكتمل واسترداد كامل وملاحظات نهائية ثابتة |
| 00212 | recurring_trip_series.sql | معاينة وإنشاء ذري لسلاسل الرحلات مع تعارضات الباص والسائق والصيانة وربط الرحلة بالسلسلة |
| 00213 | company_trip_dispatch.sql | دورة تشغيل موحدة وحضور وإلغاء ذري وانتقالات سائق أمامية وسحب الكتابة المباشرة للحجوزات والتكليفات |
| 00214 | company_operating_day_trip_list.sql | قائمة يوم تشغيل بتوقيت دمشق وسجل حديث أولاً مع حالات التشغيل وسياق الباص والسائق |
| 00215 | reassert_checked_in_reporting.sql | إعادة تثبيت احتساب الحجوزات المسجلة حضوراً ضمن قوائم الحجوزات والإيراد والتحليلات |
| 00216 | reassert_secure_customer_trip_reviews.sql | إعادة تثبيت ملكية مراجعة الرحلة واكتمالها وثبات هويتها وتطبيع checksum لمسودة 00203 المعروفة فقط |
| 00217 | enterprise_notification_delivery.sql | صندوق إرسال معاملات متعدد القنوات مع قوالب وإعادة محاولة وcallbacks قابلة للتكرار |
| 00218 | enterprise_document_registry.sql | سجل مستندات مالية immutable وأحداث تصيير مدققة للتذاكر والإيصالات والتقارير |
| 00219 | global_product_foundation.sql | أساس المعايير العامة: أنواع المقاعد، ملفات الشركات العامة، صور الرحلات، المشاهد المحفوظة، والفهارس |
| 00220 | public_company_profiles_and_trip_media.sql | عقود القراءة/التحرير الآمنة لملفات الشركات العامة ووسائط الرحلات |
| 00221 | traveler_identity_and_booking_continuity.sql | هويات دخول متعددة للمسافر وحفظ سياق الحجز عبر المصادقة |
| 00222 | global_product_api_contracts.sql | RPCs موحدة للكيانات المرتبطة والمرشحات والمشاهد وتهيئة أنواع المقاعد |
| 00223 | traveler_phone_completion.sql | استكمال رقم هاتف المسافر والتحقق منه بصيغة E.164 بعد تسجيل الدخول |
| 00224 | connected_transport_core.sql | Stops, Journey Legs, quote snapshots, and Trip-specific seat/extra inventory |
| 00225 | connected_operations_control.sql | Caller-bound telemetry, Stop Calls, check-in, disruptions, alerts, announcements, and public tracking |
| 00226 | partner_quality_settlements.sql | Versioned quality, SLA evidence, commercial terms, settlements, documents, payments, and monthly scheduling |
| 00227 | atomic_journey_booking_inventory.sql | Journey Booking, Passengers, signed Tickets, and atomic cross-leg seat/extra quote-hold-confirm flow |
| 00228 | journey_discovery.sql | بحث رحلات مترابطة مباشر/متعدد المقاطع مع نوافذ تحويل وتسعير وسعة خادمية |
| 00229 | journey_checkout_read_model.sql | نموذج قراءة checkout آمن يعيد العرض والمخزون والركاب والمقاطع من الحقيقة الأساسية |
| 00230 | atomic_journey_orders.sql | طلب Journey ذري يدعم الذهاب والعودة ويثبت كل الحجوزات أو يتراجع بالكامل |
| 00231 | journey_order_hold_lifecycle.sql | تحرير وانتهاء حجوزات موارد الطلب بأوامر idempotent وصلاحيات مرتبطة بالمالك |
| 00232 | traveler_phone_completion_privileges.sql | تضييق صلاحيات RPC استكمال الهاتف إلى الأدوار المطلوبة فقط |
| 00233 | default_city_stop_lifecycle.sql | إنشاء وصيانة محطة افتراضية لكل مدينة من دون hard-code لتطوير البحث متعدد المحطات |
| 00234 | cash_shift_null_payment_guard.sql | إصلاح شرط الصندوق النقدي كي لا يعامل provider الفارغ كتحصيل مكتبي |
| 00235 | booking_reference_trigger_order.sql | ضمان إنشاء مرجع الحجز قبل bridge الخاص بـJourney aggregate |
| 00236 | seed_bus_layout_provisioning.sql | تهيئة تخطيط مقاعد صالح لباصات QA عبر دالة مالك قاعدة البيانات غير مكشوفة للتطبيقات |
| 00237 | connected_operations_rls_predicates.sql | predicates مفوضة ضيقة لقراءة التنبيهات والتعطلات والإعلانات عبر tenant |
| 00238 | live_operations_rls_consolidation.sql | إزالة سياسات GPS الواسعة/التكرارية وتوحيد قراءة الأحداث والمحطات والموقع الحي حسب الدور والعلاقة |
| 00239 | operations_exception_priority.sql | ترتيب مركز العمليات حسب الخطر الفعلي وإعطاء الأولوية للرحلات النشطة والتأخير وGPS والتنبيهات |
| 00240 | journey_order_column_resolution.sql | إزالة التباس أسماء أعمدة/مخرجات تأكيد Journey Order داخل PL/pgSQL |
| 00241 | cash_reconciliation_rls_predicate.sql | predicate آمن وعزل tenant لقراءة ورديات وتسويات الصندوق النقدي |
| 00242 | cash_reconciliation_rpc_privileges.sql | حصر أوامر التسوية المالية بالمستخدمين المصرح لهم وwebhook مزود الدفع بـservice role |
| 00243 | traveler_journey_history.sql | سجل Journey موحّد للذهاب والعودة والرحلات المفردة، مقيّد بالمالك ومقسّم بمؤشر ثابت |
| 00244 | traveler_journey_tracking.sql | تتبع حي مقيّد بملكية المسافر يعيد المرحلة التشغيلية الصحيحة لكل Journey |
| 00245 | preserve_booked_trip_stop_calls.sql | تحديث Stop Calls المحجوزة في مكانها عند إعادة توقيت Trip بدلاً من كسر مراجع Journey |
| 00246 | traveler_journey_self_service.sql | إلغاء Journey ذاتي بسياسة شركة، quote مسبق، idempotency، وتحرير ذري للمقاعد والموارد |
| 00247 | canonical_journey_ticket_boarding.sql | تسجيل صعود ذري لكل Passenger × Journey Leg عبر Ticket موقعة مع مزامنة offline |
| 00248 | reconcile_enterprise_notification_migration_history.sql | تحقق مغلق من بنية الإشعارات قبل تسوية checksum تاريخ migration 00217 |
| 00249 | connected_journey_rls_predicates.sql | predicates غير متكررة تربط قراءة Journey بالمالك أو الشركة أو الدور التشغيلي |
| 00250 | connected_demo_tenant_lifecycle.sql | حذف وإعادة بناء عالم العرض المترابط بترتيب الاعتماديات مع حصر bypass بالـdemo فقط |
| 00251 | indexed_dashboard_trip_page.sql | حدود يوم تشغيل قابلة للفهرسة، صفحة الرحلات قبل joins، وفهارس الشركة/الحالة/وقت الانطلاق |
| 00252 | driver_trip_execution_read_model.sql | نموذج تنفيذ رحلة السائق من Journey Tickets مع manifest وحضور وأحداث تشغيل مترابطة |
| 00253 | enterprise_booking_workspace_and_documents.sql | مساحة عمل حجز شركة موحدة وسجل تأكيد/فاتورة/إلغاء immutable ومراجع وأحداث تصيير |
| 00254 | company_ticket_attendance.sql | كشف شركة موحد على Journey Ticket وحضور/غياب/تراجع ذري لكل مسافر مع fallback للحجوزات القديمة |
| 00255 | company_owned_loyalty.sql | برنامج ولاء مستقل لكل شركة مع عزل الأرصدة والمكافآت والإحالات وعقود الكسب والاستبدال الذرية |
| 00256 | connected_transport_directory_rls.sql | فصل قراءة دليل المحطات وأنماط المسار والمخزون العام عن جداول الهوية الخاصة بواسطة RLS predicates ضيقة |
| 00257 | runtime_security_posture_reassertion.sql | سحب تنفيذ trigger functions من أدوار العميل وحصر SECURITY DEFINER المجهولة بقائمة تواقيع علنية دقيقة |
| 00258 | driver_directory_rls_boundary.sql | عزل دليل السائقين حسب الشركة والدور من دون كشف سجلات شركات أخرى |
| 00259 | driver_attendance_and_incident_corrections.sql | تصحيح هوية السائق وحضور المسافر والحوادث مع دعم تراجع عدم الحضور |
| 00260 | canonical_seat_inventory_compatibility.sql | توحيد مخزون المقاعد الأساسي مع عدادات التوافق ومنع الانحراف بين قنوات البيع |
| 00261 | crypto_function_search_path.sql | تثبيت search_path لدوال التشفير داخل المعاملات لمنع فشل قفل المقاعد وعمليات الحجز |
| 00262 | retire_platform_loyalty_rpc_acl.sql | سحب تنفيذ عقود الولاء العامة المتقاعدة من كل أدوار API وservice_role |
| 00263 | canonical_booking_trip_reassignment.sql | نقل Booking Segment بين الرحلات مع مزامنة Journey Leg والمقاعد والتذاكر والإضافات والتسعير والمخزون |
| 00264 | notification_worker_acl_reassertion.sql | سحب عقود التذكير المباشر المتقاعدة وإعادة تثبيت قائمة أوامر عامل الإشعارات الدائم |
| 00265 | complete_pgcrypto_function_search_paths.sql | إكمال search_path الموثوق لدوال حجز Journey والجودة والتسويات التي تستخدم pgcrypto |
| 00266 | reconcile_converted_seat_locks_once.sql | منع احتساب قفل المقعد والحجز الناتج عنه مرتين أثناء التحويل وإعادة مصالحة مخزون المقاعد |
| 00267 | google_traveler_auth_candidate.sql | حل هوية المسافر الموثقة للخادم فقط ومنع إعادة استخدام حسابات الموظفين في دخول Google على الويب والموبايل |
| 00268 | preserve_checked_in_seat_occupancy.sql | إبقاء المقعد مشغولاً بعد تسجيل الصعود أو إكمال الرحلة وتحريره فقط عند الإلغاء أو عدم الحضور |
| 00269 | safe_google_traveler_identity_linking.sql | ربط Google بحساب المسافر الحالي ذرياً مع إثبات الملكية ومنع التعارض مع مسافر أو موظف آخر |
| 00270 | booking_confirmation_boarding_qr.sql | إضافة اعتماد صعود موقّع لكل مسافر إلى snapshot تأكيد الحجز وتوحيد رابط التذكرة في قوالب الاتصال |
| 00271 | booking_guest_access_sessions.sql | snapshot منظم لاسم العائلة وجلسة ضيف opaque محددة بالحجز مع مهلة خمول 15 دقيقة وحد مطلق 30 دقيقة |
| 00272 | legacy_booking_canonical_ticket_sync.sql | إسقاط حجوزات التوافق من قنوات العميل والمكتب إلى المقاعد وتذاكر Journey الموقّعة ذرياً وبصورة idempotent |
| 00273 | preserve_expired_legacy_booking_holds.sql | حماية حجوزات التوافق المنتهية من إعادة التفعيل وإغلاق إسقاطات مقاعدها بناءً على دليل الجلسة الدائم |
| 00274 | isolate_native_journey_from_legacy_ticket_sync.sql | عزل Journey checkout الأصلي صراحةً عن trigger التوافق ومنع تفسير source الفارغ على أنه حجز legacy |
| 00275 | service_only_identity_aware_journey_confirmation.sql | حصر أوامر تأكيد Journey التي تحفظ اسم العائلة في خدمة الخادم ومنع استدعاء SECURITY DEFINER مباشرة من anon أو authenticated |
| 00276 | traveler_booking_billing_address.sql | عنوان فوترة اختياري محفوظ ضمن حقيقة حجز المسافر |
| 00277 | card_payment_billing_details.sql | اشتراط بيانات الفوترة المهنية عند تفعيل الدفع بالبطاقة فقط |
| 00278 | online_payments_development_only.sql | إبقاء محولات الدفع الإلكتروني في وضع التطوير مع النقد كخيار إنتاج افتراضي |
| 00279 | trip_pickup_locations.sql | نقاط صعود مملوكة للشركة مع إحداثيات وتعليمات ولقطة ثابتة لكل رحلة |
| 00280 | booking_pickup_location_documents.sql | تمرير لقطة موقع الصعود إلى مستندات الحجز والتذكرة |
| 00281 | cash_only_payment_trigger_grants.sql | إعادة تثبيت صلاحيات أوامر الدفع النقدي بعد إضافة حواجز طرق الدفع |
| 00282 | notification_pickup_context.sql | إضافة سياق موقع الصعود إلى قوالب الإشعارات المعاملاتية |
| 00283 | trip_dispatch_pickup_projection.sql | إظهار موقع الصعود في نموذج قراءة التشغيل والإرسال |
| 00284 | notification_pgcrypto_search_path.sql | تثبيت مسار pgcrypto الموثوق لدوال الإشعارات |
| 00285 | booking_confirmation_ticket_copy.sql | توحيد نص رابط التذكرة ورمز الصعود في تأكيدات الحجز |
| 00286 | public_trip_pickup_projection.sql | إعادة بناء عرض الرحلات العام ليشمل لقطة موقع الصعود |
| 00287 | journey_search_stop_call_identity.sql | فصل هوية Stop عن Trip Stop Call في البحث مع توافق العملاء وربط آمن بعرض السعر |
| 00288 | trip_account_scope_isolation.sql | عزل مخزون الإنتاج وQA والعروض وقصر اكتشاف المسافر على الشركات النشطة المنشورة غير الموقوفة |
| 00289 | backfill_legacy_internal_tenant_scope.sql | تصنيف شركة QA الإنتاجية القديمة وترقية الهويات المرتبطة بها إلى نطاق داخلي موثوق |
| 00290 | journey_quote_postgres_uuid_compatibility.sql | قبول كل UUID قانوني في PostgreSQL عند إنشاء عرض Journey، بما فيه معرفات QA الحتمية القديمة |
| 00291 | authenticated_journey_confirmation_actor.sql | تمرير هوية المسافر المتحقق منها عبر جسر خدمة محدود عند تأكيد Journey |
| 00292 | legacy_booking_durable_journey_sessions.sql | إنشاء جلسة Journey دائمة للحجوزات المتوافقة كي يعيد المالك فتح التأكيد والتذاكر |
| 00293 | demo_passenger_bookable_launch.sql | اختيار مسار Demo مستقبلي قابل للبيع فعلياً حسب Stop Calls والمركبة والمخزون وتوقيت دمشق |
| 00294 | publish_isolated_demo_profiles.sql | نشر ملف شركة Demo المعزولة آلياً مع إبقاء رؤيتها محكومة بنطاق الحساب |
| 00295 | runtime_schema_client_grant_hardening.sql | إعادة تثبيت العقود النهائية لـ00292–00294 وتسوية checksums محددة وإغلاق جداول تجاوزت RLS بسبب grants قديمة |
| 00296 | security_definer_search_path_and_service_table_grants.sql | تثبيت search_path لكل SECURITY DEFINER قديمة وسحب ACL عميل متبقٍ من حالة ترحيل PII |
| 00297 | company_cash_payment_settings_provisioning.sql | ضمان سياسة دفع نقدية افتراضية لكل شركة قائمة وجديدة مع قيد uniqueness وعقد onboarding |
| 00298 | secure_document_share_grants.sql | منح مشاركة مستند واحد، جلسات recipient محدودة، وأحداث تدقيق immutable مع أسرار مخزنة كـhash فقط |
| 00299 | document_share_issuer_authorization.sql | حل مالك الحجز أو السائق المعيّن من هوية الخادم ومنع actor scope يختاره العميل |
| 00300 | two_phase_document_share_delivery.sql | فصل تفويض المستند عن تسجيل التسليم حتى لا ينشئ فشل renderer حدث عرض أو تنزيل كاذب |
| 00301 | complete_document_share_issuer_roles.sql | استكمال مصدري المشاركة بمشغلي الشركة والإدارة النشطين وإلغاء المنحة بهوية المصدر الموثقة |
| 00302 | database_authoritative_document_share_expiry.sql | حساب آجال المنحة والجلسة من ساعة PostgreSQL الموثوقة ومنع اختلاف ساعة التطبيق من تمديدها أو رفضها خطأً |
| 00303 | document_share_demo_lifecycle.sql | ربط سجلات مشاركة المستند بدورة حياة مستندات العروض التجريبية كي لا تمنع إعادة ضبط المستأجر التجريبي مع إبقاء السجل immutable خارج teardown |
| 00304 | document_share_finance_role_scope.sql | إرجاع دور مصدر المستند من الهوية الموثقة، حصر مستندات مالية الشركة بالمالك/المدير، واستبعاد دعم المنصة من قناة الإصدار |
تشغيل الترحيلات
التطوير المحلي
# التحقق من سلسلة الترحيلات أولاً
make db-validate-migrations
# تشغيل الترحيلات الجديدة فقط
make db-migrate
# تشغيل جميع عقود قاعدة البيانات داخل معاملات قابلة للتراجع
pnpm test:db-contracts
# مطابقة المخطط الحي وسجل الترحيلات وRLS والفهارس والصلاحيات
pnpm audit:db-schema
الإنتاج
# تحقق من أن الأرقام فريدة
./infrastructure/scripts/validate-migrations.sh
# طبّق الترحيلات بالتسلسل مع تسجيلها
# هذا الأمر يطبّق أيضاً seed مرجعياً دائماً من
# infrastructure/supabase/seeds/reference-data.sql
./infrastructure/scripts/run-migrations.sh
# إذا احتجت demo seed الشامل فاستخدمه فقط خارج الإنتاج
./infrastructure/scripts/run-migrations.sh --seed
# لحسابات الإنتاج الداخلية فقط
./infrastructure/scripts/run-migrations.sh --internal-seed
بعد ترحيل يضيف جدولاً أو دالةً تستخدمها PostgREST مباشرة، أعد تحميل schema cache إذا لم تفعل أداة التشغيل ذلك تلقائياً:
docker compose exec -T db psql -U postgres -d postgres -c "NOTIFY pgrst, 'reload schema';"
تعمل سكربتات الترحيل على Bash الافتراضي في macOS أيضاً، لذلك لا تتطلب Bash 4 أو mapfile.
الملف infrastructure/supabase/seeds/reference-data.sql يُطبَّق في كل تشغيل لأنه يحتوي
على بيانات مرجعية مطلوبة في جميع البيئات مثل صلاحيات الإدارة والمدن السورية.
--seed يشير إلى infrastructure/supabase/seed.sql وهو seed واسع للديمو/التطوير. لا تستخدمه في الإنتاج الحقيقي.
أما --internal-seed فيستدعي seed محدوداً وموجهاً للحسابات التشغيلية الداخلية فقط.
كتابة ترحيل جديد
1. إنشاء الملف
# الحصول على آخر رقم
ls infrastructure/supabase/migrations/ | tail -1
# إنشاء ملف جديد
touch infrastructure/supabase/migrations/00069_my_migration.sql
2. هيكل الترحيل
-- Migration: 00069_my_migration.sql
-- Description: وصف التغيير
-- Author: اسم المطور
-- Date: YYYY-MM-DD
-- ============================================
-- التغييرات
-- ============================================
-- 1. إضافة جدول جديد
CREATE TABLE IF NOT EXISTS new_table (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 2. إضافة فهرس
CREATE INDEX IF NOT EXISTS idx_new_table_name ON new_table(name);
-- 3. تفعيل RLS
ALTER TABLE new_table ENABLE ROW LEVEL SECURITY;
-- 4. إضافة سياسة
CREATE POLICY "new_table_select" ON new_table
FOR SELECT USING (true);
-- 5. منح الصلاحيات
GRANT ALL ON new_table TO authenticated;
GRANT SELECT ON new_table TO anon;
-- 6. التعليقات
COMMENT ON TABLE new_table IS 'وصف الجدول';
3. أفضل الممارسات
لا تستخدم رقماً موجوداً مسبقاً
كل ترحيل يجب أن يملك prefix رقمي فريد من 5 خانات. مثال:
00109_admin_platform_operations.sql
00110_next_change.sql
أي تكرار في الرقم سيُعتبر خطأ نشر ويمنع التطبيق.
استخدام IF NOT EXISTS / IF EXISTS
-- جيد
CREATE TABLE IF NOT EXISTS my_table (...);
DROP INDEX IF EXISTS idx_my_index;
DROP POLICY IF EXISTS "my_policy" ON my_table;
-- سيء - قد يفشل
CREATE TABLE my_table (...);
CREATE POLICY "my_policy" ON my_table FOR SELECT USING (true);
التحقق قبل التعديل
-- التحقق من وجود العمود قبل إضافته
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'my_table' AND column_name = 'new_column'
) THEN
ALTER TABLE my_table ADD COLUMN new_column TEXT;
END IF;
END $$;
استخدام المعاملات
BEGIN;
-- التغييرات هنا
ALTER TABLE my_table ADD COLUMN col1 TEXT;
ALTER TABLE my_table ADD COLUMN col2 INTEGER;
COMMIT;
أنماط شائعة
إضافة عمود جديد
-- إضافة عمود مع قيمة افتراضية
ALTER TABLE trips ADD COLUMN IF NOT EXISTS
delay_minutes INTEGER DEFAULT 0;
-- إضافة عمود JSONB
ALTER TABLE buses ADD COLUMN IF NOT EXISTS
metadata JSONB DEFAULT '{}'::JSONB;
-- تعليق على العمود
COMMENT ON COLUMN trips.delay_minutes IS 'دقائق التأخير';
إضافة نوع ENUM جديد
-- إضافة قيمة لـ ENUM موجود
ALTER TYPE trip_status ADD VALUE IF NOT EXISTS 'DELAYED';
-- إنشاء ENUM جديد
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'payment_status') THEN
CREATE TYPE payment_status AS ENUM ('PENDING', 'PAID', 'REFUNDED');
END IF;
END $$;
إنشاء دالة Trigger
-- دالة تحديث updated_at
CREATE OR REPLACE FUNCTION update_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- إنشاء الـ Trigger
DROP TRIGGER IF EXISTS my_table_updated_at ON my_table;
CREATE TRIGGER my_table_updated_at
BEFORE UPDATE ON my_table
FOR EACH ROW
EXECUTE FUNCTION update_updated_at();
تحديث البيانات الموجودة
-- تحديث بسيط
UPDATE bookings SET status = 'CONFIRMED'
WHERE status = 'PENDING' AND created_at < NOW() - INTERVAL '1 hour';
-- تحديث مع JOIN
UPDATE seats s
SET status = 'BOOKED', booking_id = b.id
FROM bookings b
WHERE s.trip_id = b.trip_id
AND s.seat_number = b.seat_number
AND b.status = 'CONFIRMED';
التراجع عن الترحيلات
إنشاء ملف تراجع
-- Rollback: 00069_my_migration.sql
-- حذف السياسات
DROP POLICY IF EXISTS "new_table_select" ON new_table;
-- إلغاء RLS
ALTER TABLE new_table DISABLE ROW LEVEL SECURITY;
-- حذف الجدول
DROP TABLE IF EXISTS new_table;
تنفيذ التراجع
psql $DATABASE_URL -f rollback/00069_rollback.sql
استكشاف الأخطاء
خطأ: "relation already exists"
-- الحل: استخدام IF NOT EXISTS
CREATE TABLE IF NOT EXISTS my_table (...);
خطأ: "column does not exist"
-- التحقق من وجود العمود
SELECT column_name FROM information_schema.columns
WHERE table_name = 'my_table';
خطأ: "cannot drop type because other objects depend on it"
-- عرض التبعيات
SELECT * FROM pg_depend WHERE refobjid = 'my_type'::regtype::oid;
-- الحذف المتسلسل (خطير!)
DROP TYPE my_type CASCADE;
خطأ: "permission denied"
-- منح الصلاحيات
GRANT ALL ON my_table TO authenticated;
GRANT USAGE ON SCHEMA public TO anon;
التحقق من الترحيل
قبل التطبيق
-- التحقق من الصياغة
\i infrastructure/supabase/migrations/00069_my_migration.sql
-- في معاملة (لا يُطبق)
BEGIN;
\i infrastructure/supabase/migrations/00069_my_migration.sql
ROLLBACK;
بعد التطبيق
-- التحقق من الجدول
\d my_table
-- التحقق من السياسات
SELECT * FROM pg_policies WHERE tablename = 'my_table';
-- التحقق من الفهارس
SELECT * FROM pg_indexes WHERE tablename = 'my_table';
سجل الترحيلات
نستخدم جدول لتتبع الترحيلات المطبقة:
CREATE TABLE IF NOT EXISTS _migrations (
id SERIAL PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
applied_at TIMESTAMPTZ DEFAULT NOW()
);
-- تسجيل ترحيل
INSERT INTO _migrations (name) VALUES ('00069_my_migration');
أوامر مفيدة
# عرض حالة الترحيلات
supabase db status
# إنشاء ترحيل من التغييرات
supabase db diff -f my_migration
# تطبيق الترحيلات
supabase db push
# إعادة تعيين قاعدة البيانات
supabase db reset
In-place migration edits & checksum drift
The runner records a sha256 checksum of every applied migration in the
applied_migrations table and compares the complete applied history in one
database query. Editing a file after it has been applied to any environment
now stops the runner before new migrations execute. The runner never re-applies
an edited migration because that could repeat production side effects.
When in-place edits are allowed
Only when the edit is a no-op against the current state of every environment the migration has already been applied to. Examples:
- Adding a comment /
RAISE NOTICE - Reordering idempotent
IF NOT EXISTS/IF EXISTSguards in a way that doesn't change which statements run - Fixing a bug in a section guarded by
IFthat was a no-op on prod
If the edit changes what the migration did on a previously-applied environment, write a new migration instead. The new migration should re-run the corrective work; the old migration's checksum stays whatever prod recorded.
Updating applied_migrations.checksum after a deliberate in-place edit
After confirming the on-prod state already reflects the new content, update the checksum so future drift checks pass:
UPDATE applied_migrations
SET checksum = '<new_sha256>'
WHERE filename = '<migration_filename>';
The new checksum can be recomputed locally with
shasum -a 256 infrastructure/supabase/migrations/<file>.sql on macOS or
sha256sum infrastructure/supabase/migrations/<file>.sql on Linux.
Tooling
infrastructure/scripts/validate-migrations.sh validates filename format and
sequencing. run-migrations.sh then validates each recorded filename and
checksum before applying anything. The single historical pre-release draft of
00166 is accepted only for its exact old and current hashes; 00206 reasserts
the intended schema/data state and normalizes that record. Every other checksum
transition fails closed and requires a corrective migration plus explicit
operational review.