Migration پایگاه داده

فینچ یک سیستم migration داخلی دارد که تغییرات schema را در طول زمان مدیریت می‌کند.

دستورات Migration

دستور توضیح
finch migrate --init اجرای تمام migration های در انتظار
finch migrate --create --name <name> ساخت فایل migration جدید
finch migrate --rollback برگرداندن آخرین migration
finch migrate --list نمایش وضعیت تمام migration ها
finch migrate --init --sqlite اجرا برای SQLite
finch migrate --create --name <name> --sqlite ساخت برای SQLite

ساختار فایل Migration

Migration ها در ./migrations/ (MySQL) یا ./migrations_sqlite/ (SQLite) قرار دارند:

-- NEW VERSION
CREATE TABLE articles (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(255) NOT NULL,
    body TEXT,
    published TINYINT(1) DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- ROLL BACK
DROP TABLE IF EXISTS articles;

هر فایل migration باید هر دو بخش -- NEW VERSION (برای اجرا) و -- ROLL BACK (برای rollback) را داشته باشد.

هر migration (فایلی یا مبتنی بر Dart) درون یک تراکنش پایگاه‌داده اجرا می‌شود: اگر هر یک از دستورات با خطا مواجه شود، تراکنش به‌صورت خودکار rollback می‌شود و آن migration به‌عنوان اجراشده ثبت نمی‌شود.

Migration های مبتنی بر Dart

به‌جای فایل SQL، می‌توانید migration را در Dart با extend کردن DartMigration تعریف کنید. SQL مربوط به up()/down() را با addSql() بسازید و target را برای انتخاب MigrationTarget.mysql یا MigrationTarget.sqlite تنظیم کنید:

import 'package:finch/mysql.dart';

class M1CreateUsers extends DartMigration {
  @override
  MigrationTarget get target => MigrationTarget.sqlite;

  M1CreateUsers() : super('m1_create_users');

  @override
  void up() {
    addSql('''
      CREATE TABLE users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT,
        email TEXT
      );
    ''');
  }

  @override
  void down() {
    addSql('DROP TABLE IF EXISTS users;');
  }
}

Migration ها را روی نمونه FinchApp ثبت کنید. نامی که به super(...) پاس داده می‌شود باید در میان همه‌ی migration های ثبت‌شده یکتا باشد:

final app = FinchApp(configs: configs)
  ..registerDartMigration([
    M1CreateUsers(),
    M2InsertUsers(),
  ]);

پس از ثبت، migrate --init، --rollback و --list (و معادل‌های --sqlite / migrate_sqlite آن‌ها) به‌جای خواندن فایل‌های migration، migration های Dart متناظر با آن target را اجرا می‌کنند.

نام‌گذاری فایل

فایل‌های migration با timestamp نام‌گذاری می‌شوند:

2024_01_15_143022_create_articles_table.sql

اجرای خودکار در راه‌اندازی

می‌توانید migration ها را در راه‌اندازی برنامه به صورت خودکار اجرا کنید:

FinchConfigs(
  autoMigrate: true,
)

هشدار: این گزینه را با احتیاط در production استفاده کنید.

مثال Workflow

# ساخت migration برای جدول جدید
finch migrate --create --name create_products_table

# ویرایش فایل ایجادشده در migrations/
# سپس اجرای migration
finch migrate --init

# در صورت نیاز به rollback
finch migrate --rollback