داده، SQL، قراردادها و ماشین حالت · فصل ۳ — Migration، ORM و Backup/Restore · 65
Drizzle ORM: Typed Schema و Migration Review
داده را ذخیره یا query میکند اما constraint، consistency، compatibility و recovery را به یک contract مهندسی تبدیل نمیکند. موضوع جاری: «Drizzle ORM: Typed Schema و Migration Review». میتواند «Drizzle ORM: Typed Schema و Migration Review» را برای یک domain محدود مدل کند و constraint، compatibility یا recovery evidence لازم را مشخص کند.
خلاصهٔ درس
داده را ذخیره یا query میکند اما constraint، consistency، compatibility و recovery را به یک contract مهندسی تبدیل نمیکند. موضوع جاری: «Drizzle ORM: Typed Schema و Migration Review».
میتواند «Drizzle ORM: Typed Schema و Migration Review» را برای یک domain محدود مدل کند و constraint، compatibility یا recovery evidence لازم را مشخص کند.
خروجی این درس
میتواند «Drizzle ORM: Typed Schema و Migration Review» را برای یک domain محدود مدل کند و constraint، compatibility یا recovery evidence لازم را مشخص کند.
پیشنیازها
1) مسئله قبل از ابزار
یک schema تایپشده در TypeScript بهتنهایی نمیگوید دیتابیس واقعی دقیقاً همان شکل را دارد. حتی وقتی drizzle-kit generate فایل SQL تولید میکند، هنوز سه پرسش باز است: source of truth کجاست، SQL تولیدشده چه اثری روی داده و compatibility دارد، و آیا تغییر روی یک دیتابیس تمیز واقعاً اعمال و مشاهده شده است؟ این درس فقط یک تغییر محدود را دنبال میکند: افزودن handle نرمالشده و یکتا به customer_profile. هدف، ساخت Drizzle Typed Schema & Migration Review Record v1 است؛ نه اثبات ایمنی production و نه آموزش کل Drizzle.
2) جهت مسیر
پیشنیاز این درس DAT-005 است: باید بتوانی migration را یک contract تغییر schema/data ببینی. در این درس آن منطق را داخل workflow Drizzle قرار میدهیم. مسیر اصلی codebase-first است چون schema تایپشده را source of truth اعلام میکنیم؛ اما همین انتخاب باید در artifact نوشته شود. Drizzle همچنین database-first را پشتیبانی میکند. انتخاب route یک تصمیم پروژه است، نه نتیجهای که ابزار بهجای ما میگیرد.
3) مدل ذهنی
زنجیرهٔ تصمیم را اینطور نگه دار:
Source of Truth → Typed Schema / DB State → Previous Snapshot & Migration History → Generated Diff/SQL → Human Review → Clean Apply → Direct DB Observation → Decision + Residual Risk
generate پایان کار نیست. فایل SQL و snapshot، evidence برای review هستند. migrate یا اجرای مستقیم migration نیز فقط apply را نشان میدهد. برای بستهشدن claim باید state دیتابیس مشاهده شود. push هم یک workflow جداست: تغییر schema را مستقیمتر روی database اعمال میکند و در این درس جای مسیر reviewed migration-file را نمیگیرد مگر اینکه governance صریحاً چنین تصمیمی ثبت کند.
4) لایهٔ پایه: source of truth
اول artifact را با یک جملهٔ بدون ابهام شروع کن: «در این تمرین، codebase schema منبع اعلامشدهٔ intent است و database state منبع observation است.» این دو را یکی نکن. اگر code تغییر کرده ولی migration اعمال نشده، intent جدید است اما deployed state قدیمی است. اگر database خارج از migration history تغییر کرده باشد، deployed state ممکن است از code و snapshot فاصله گرفته باشد. بنابراین سه سطح را جدا ثبت میکنیم: declared schema، migration history/snapshot، actual database state.
5) توضیح عمیق: generate چه چیزی را ثابت میکند؟
طبق مستندات فعلی Drizzle، drizzle-kit generate schema فعلی را میخواند، snapshot آن را با snapshot قبلی مقایسه میکند و بر اساس diff، SQL migration و snapshot جدید ذخیره میکند. این رفتار برای traceability مهم است، اما safety proof نیست. خروجی SQL باید خوانده شود: آیا DROP یا rename مبهم وجود دارد؟ آیا constraint جدید روی دادهٔ موجود قابل اعمال است؟ آیا NOT NULL یا uniqueness قبل از data transition وارد شده؟ آیا تغییر با نسخهٔ قدیمی برنامه سازگار است؟
در fixture دو failure class عمداً از هم جدا نگه داشته میشوند. اول، generated review fixture معقولی که میخواهد handle NOT NULL را مستقیم به جدولِ دارای داده اضافه کند باید روی precondition ستون اجباری با SQLSTATE 23502 شکست بخورد؛ این خروجی فقط evidence برای review است و SQL پذیرفتهشده نیست. دوم، یک data-transition probe جدا و عمداً ساده، ابتدا handle را nullable اضافه میکند، آن را از display_name backfill میکند و سپس به uniqueness میرسد؛ دو ردیف Sara به یک handle نرمال میشوند و مرحله uniqueness باید با 23505 شکست بخورد. نکتهٔ آموزشی این نیست که Drizzle «اشتباه» میکند؛ schema intent و DDL تولیدشده خودبهخود data precondition و collision policy را حل نمیکنند.
6) مثال کارشدهٔ محدود
Baseline شامل customer_profile(id, email, display_name) است. target schema ستون handle را اضافه میکند. review record باید این سطرها را داشته باشد:
- Schema Intent:
handleنرمالشده و یکتا. - Source of Truth: codebase-first.
- Prior Snapshot/Migration: baseline migration history موجود.
- Generated SQL: artifact تولیدشده را با hash یا path ثبت کن.
- Data Risk: collision و null transition.
- Compatibility: آیا reader/writer قدیمی بدون
handleهنوز کار میکند؟ - Clean Apply: نتیجه apply روی schema disposable.
- DB Observation: ستون، constraint و دادهٔ واقعی را query کن.
- Decision: accept / repair / defer.
- Residual Risk: این fixture production workload را مدل نمیکند.
7) Failure modes که باید عمداً ببینی
Failure A — required-column precondition: generated review fixture میخواهد handle NOT NULL را روی جدول دارای داده اضافه کند. در fixture disposable باید با 23502 شکست بخورد؛ این را بهعنوان mismatch میان generated SQL و data transition ثبت کن، نه collision uniqueness.
Failure B — duplicate normalization precondition: data-transition probe جدا، handleهای نرمالشده را backfill میکند و سپس uniqueness را enforce میکند. دو رکورد seed به یک handle میرسند و مرحله uniqueness باید با 23505 شکست بخورد.
Failure C — schema changed, migration not applied: TypeScript target وجود دارد اما information_schema.columns هنوز handle را نشان نمیدهد. این drift بین intent و deployed state است.
Failure D — generated SQL بدون review: اگر artifact فقط بگوید «generate succeeded»، evidence ناقص است. باید destructive/data-risk scan و human decision ثبت شود.
Failure E — push بدون governance record: push ذاتاً ممنوع نیست؛ اما اگر lesson contract مسیر reviewed migration-file را انتخاب کرده، جایگزینی silent آن با push باید flag شود چون audit trail تصمیم تغییر کرده است.
8) پل برای برنامهنویس باتجربه
اگر قبلاً ORM یا migration framework استفاده کردهای، syntax را سریع رد کن و روی چهار separation تمرکز کن: type model ≠ deployed schema، generated diff ≠ accepted change، apply success ≠ invariant proof، tool convenience ≠ governance decision. در review حرفهای باید بتوانی دقیقاً بگویی کدام observation از خود database آمده و کدام conclusion هنوز inference است.
9) Alternatives و trade-offها
Database-first وقتی مناسب است که database schema authority اصلی باشد و code از آن pull شود. Codebase-first با migration files وقتی مفید است که schema declaration و migration history در version control باشند و SQL review لازم باشد. Codebase-first با push میتواند iteration را سریع کند، اما traceability و approval workflow متفاوتی دارد. این درس هیچکدام را مطلقاً «بهترین» اعلام نمیکند؛ فقط برای fixture خودش migration-file review را انتخاب و boundary آن را ثبت میکند.
10) تمرین هدایتشده و مستقل
در مسیر هدایتشده، baseline را inspect کن، source of truth را ثبت کن، target schema را ببین، generate را فقط در toolchain publisher-pinned اجرا کن و SQL/snapshot را قبل از apply review کن. failure ستون اجباری generated fixture با 23502 را جدا از failure collision نرمالسازی با 23505 پیشبینی و ثبت کن. drift probe را قبل از هر migration اجرا کن. سپس apply را فقط روی PostgreSQL disposable انجام بده و database state را مستقیم query کن.
تمرین مستقل: یک subscription service میخواهد external_id nullable را constrained کند و قبلاً migration folder دارد. بدون کپیکردن راهحل fixture، تعیین کن source of truth چیست، prior snapshot چه نقشی دارد، generated SQL را با چه risk checklist میخوانی، clean-apply evidence چیست و کدام residual risk باقی میماند.
11) Verification و evidence
Artifact کامل باید observationهای مثبت و منفی را کنار هم نگه دارد. حداقل evidence: baseline database observation، generate artifact identity، human SQL review، deliberate duplicate failure، repair/recovery result، clean apply، direct DB observation، drift probe، push-boundary decision و residual limitation. اگر PostgreSQL یا Drizzle واقعی اجرا نشده، status باید صریحاً NOT_RUN بماند؛ هیچ خروجی شبیه runtime evidence نباید ساخته شود.
12) Assessment و transfer
برای قبولی، learner باید بتواند: contract محدود را بیان کند؛ مسیر codebase-first را از database-first تفکیک کند؛ یک generated migration را برای data/destructive risk review کند؛ تفاوت schema intent و deployed state را با observation نشان دهد؛ failure duplicate را تشخیص دهد؛ و در changed-context case بدون scaffold تصمیم مشابهی بسازد. پاسخ صرفاً «TypeScript build موفق شد» یا «generate فایل ساخت» کافی نیست.
13) منابع و freshness
Source boundary این درس فقط دو منبع رسمی frozen است: DRIZZLE-MIGRATIONS و DRIZZLE-GENERATE. تاریخ review_due هر دو 2026-10-17 است. در 2026-09-15 هنوز recheck اجباری بهعلت موعد فرا نرسیده است؛ same-source verification انجام شده و scope توسعه نیافته است. اگر رفتار generate, migrate, push, snapshot یا migration folder تغییر کند، claimهای TOOL_VOLATILE باید دوباره بررسی شوند.
ارزیابی
پاسخنامهی این درس در بستهی آموزش وجود ندارد؛ خودت جواب بده و صادقانه علامت بزن. «نیاز به مرور» درس را به صف تکرار میفرستد.
DAT-007-S1 retrieval
DAT-007-S2 application
DAT-007-S3 diagnosis
DAT-007-S4 decision
DAT-007-S5 transfer
ملاکهای ارزیابی (rubric)
Critical dimensions: contract/recovery correctness; evidence quality; scope discipline; transfer independence. Blocking failures include artifact-presence-only proof, fabricated runtime evidence, missing deliberate failure, or treating typed schema as deployed-state proof.
منابع و تازگی
مطالعهٔ موارد (case studies)
فایلهای آزمایشگاه
رسانه و اسلایدهای درس
فایلهای آموزشی (دانلود)