Definitions
- Changelog
ไฟล์ที่รวบรวมการเปลี่ยนแปลงไว้ สำหรับบทความนี้เราใช้วิธีการเก็บไว้ในไฟล์
liquibase.changelog.xml
และใส่ config ให้ใช้ทุกไฟล์ในmigrations
ดังนั้นในบทความนี้ changelog หมายถึงไฟล์ sql ทุกไฟล์ในโฟรเดอร์migrations
- Changeset รายละเอียดของการเปลี่ยนแปลงที่เราสามารถเอา database migration script หลายๆตัวมารวมกันได้ภายใน changeset เดียว
- Migrate การรัน migration script เพื่ออัพเดทโครงสร้าง database
- Rollback การรัน rollback เพื่อ undo การ migrate
Project Structure
project-root/
- migrations/
- YYYYMMDD-sprint-01.sql
- YYYYMMDD-sprint-02.sql
- ...
- liquibase.properties
- liquibase.changelog.xml
อธิบาย
-
liquibase.changelog.xml
-- ไฟล์ changelog หลัก ที่จะ config ให้ไปใช้ไฟล์ในmigrations
ในการรัน database migration -
liquibase.properties
-- ไฟล์ที่เก็บ variable ของ Liquibase -
migrations/
-- โฟลเดอร์ที่จะเก็บ migration script ทั้งหมด -
migrations/YYYYMMDD-sprint-01.sql
-- ไฟล์ Liquibase changelog ในรูปแบบ SQL ซึ่งภายในไฟล์จะมี database migration script ที่สามารถ grouping เป็น change set ได้
คำแนะนำ
โดยแต่ละไฟล์ควรจะนำหน้าด้วย YYYYMMDD เพื่อเรียงลำดับของการ migration และควรใส่เลข sprint เพื่อที่จะสามารถ track กลับมาได้ว่าเป็น changelog ของ sprint ไหน
Migration Script
-- liquibase formatted sql
-- changeset lumin:1721661329831-1 labels:pbi-1234,sprint-10
-- comment: create products table
CREATE TABLE "products" ("id" INTEGER NOT NULL, "name" VARCHAR(50) NOT NULL, "description" TEXT NOT NULL, "price" numeric(5, 2) NOT NULL, "stock" INTEGER NOT NULL, "updated_at" TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL, CONSTRAINT "products_pkey" PRIMARY KEY ("id"));
-- rollback DROP TABLE "products";
-- changeset lumin:1721661329831-2 labels:pbi-1235,sprint-10
-- comment: create customers table
CREATE TABLE "customers" ("id" INTEGER NOT NULL, "name" VARCHAR(100) NOT NULL, "registered_at" TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL, CONSTRAINT "customers_pkey" PRIMARY KEY ("id"));
-- rollback DROP TABLE "customers";
อธิบาย
- บรรทัดแรก
-- liquibase formatted sql
เพื่อบอกว่านี่คือไฟล์ Liquibase changelog -
-- changeset author:unique-number labels:label-1,label-2
เป็นการกำหนดว่าหลังจากบรรทัดนี้เป็นต้นไปจะเป็น migration script ภายใต้ changeset นี้ ซึ่งจะใช้เลขunique-number
และใช้ labellabel-1
และlabel-2
(สามารถเอาไปใช้ filter ได้) -
-- comment: ...
เป็น comment เพื่อใส่รายละเอียดอธิบาย ไม่มีผลในการรัน -
-- rollback ...
กำหนด roll back script
Step
0) Prepare Example Project
ด้วยการจำลอง database ด้วย Docker
# Use postgres/example user/password credentials
services:
db:
image: postgres:alpine
restart: always
shm_size: 128mb
ports:
- 5432:5432
environment:
POSTGRES_PASSWORD: example
adminer:
image: adminer
restart: always
ports:
- 8080:8080
และสร้าง container ด้วย
docker compose up -d
และเข้าไปสร้าง database จำลอง เพื่อจำลองว่าในโปรเจคของเรามี database ที่ยังไม่ได้ migrate อยู่ โดยใช้ script นี้
CREATE DATABASE "app-local";
CREATE TABLE products
(
id INTEGER PRIMARY KEY NOT NULL,
name VARCHAR(50) NOT NULL,
description TEXT NOT NULL,
price DECIMAL(5,2) NOT NULL,
stock INTEGER NOT NULL,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
);
CREATE TABLE customers
(
id INTEGER PRIMARY KEY NOT NULL,
name VARCHAR(100) NOT NULL,
registered_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
);
1) Init Liquibase Project
สร้าง liquibase.changelog.yml
databaseChangeLog:
- includeAll:
path: migrations/
- เรากำหนดให้ liquibase ใช้ไฟล์ทั้งหมดภายในโฟลเดอร์
migrations/
- change log format สามารถดูได้ที่
สร้าง liquibase.properties
# Liquibase setting
liquibase.hub.mode: off
liquibase.showBanner: false
changelogFile: liquibase.changelog.yml
# LOCAL ENVIRONMENT
url: jdbc:postgresql://localhost:5432/app-local
username: postgres
password: example
liquibase.command.defaultSchemaName: public
- variable ที่จำเป็นในการรัน Liquibase จะมี 4 ตัวดังนี้
-
changelogFile
บอกว่าให้ไปหยิบ changelog จากไหน -
url
คือ database connection string แบบjdbc
-
username
คือ database username -
password
คือ database password
-
- variable อื่นๆ ที่ไม่มีก็รันได้ แต่ถ้าใส่ก็จะดีกว่า
-
liquibase.hub.mode: off
เพื่อไม่ส่งข้อมูลการใช้งานของเราให้ Liquibase -
liquibase.showBanner: false
เพื่อไม่แสดง Liquibase banner ตอนรัน CLI -
liquibase.command.defaultSchemaName: public
เพื่อบอกว่า default database schema คือ public ซึ่งเราอาจจะได้ใช้ในกรณีที่เรามีหลาย schema
-
- ถ้าไม่มีไฟล์
liquibase.properties
เราสามารถใส่ข้อมูลเหล่านี้ได้ 2 แบบ- ใส่เป็น option เช่น
liquibase status --changelog-file ? --url ? --username ? --password ?
(ไม่แนะนำให้ทำใน local environment จะลำบากทำไม) - ใส่เป็น environment variables โดยใช้ format
LIQUIBASE_<option-name>
เช่นLIQUIBASE_URL
LIQUIBASE_USERNAME
LIQUIBASE_PASSWORD
- ซึ่งท่านี้ เราจะใช้ในกรณีที่เอาไปรันใน CI เพราะเราจะไม่ใส่
liquibase.properties
ตอน build package
- ใส่เป็น option เช่น
ทดสอบว่าสามารถใช้งานได้ไหม
$ liquibase status
> ERROR: Exception Details
> ERROR: Exception Primary Class: SetupException
> ERROR: Exception Primary Reason: Could not find directory, directory was empty, or no changelogs matched the provided search criteria for includeAll 'migrations/'
> ERROR: Exception Primary Source: 4.28.0
ซึ่งเป็น error ที่บอกว่าไม่มีไฟล์ใน migrations/
เลย แต่สามารถ connect database ได้เรียบร้อย
2) Capture Database Structure
เราสามารถดึงโครงสร้างของ database ณ ปัจจุบัน โดยใช้คำสั่ง generate-changelog
$ liquibase generate-changelog \
--changelog-file ./migrations/00000000-init.sql
Generated changelog written to ./migrations/00000000-init.sql
เกิดไฟล์ migrations/00000000-init.sql
ซึ่งมีข้อมูล
-- liquibase formatted sql
-- changeset lumin:1721661329831-1
CREATE TABLE "products" ("id" INTEGER NOT NULL, "name" VARCHAR(50) NOT NULL, "description" TEXT NOT NULL, "price" numeric(5, 2) NOT NULL, "stock" INTEGER NOT NULL, "updated_at" TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL, CONSTRAINT "products_pkey" PRIMARY KEY ("id"));
-- changeset lumin:1721661329831-2
CREATE TABLE "customers" ("id" INTEGER NOT NULL, "name" VARCHAR(100) NOT NULL, "registered_at" TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL, CONSTRAINT "customers_pkey" PRIMARY KEY ("id"));
เราควรเพิ่ม label ลงไปเพื่อให้เราสามารถทำ filter label ได้ โดยเพิ่ม labels:init
-- liquibase formatted sql
-- changeset lumin:1721661329831-1 labels:init
CREATE TABLE "products" ("id" INTEGER NOT NULL, "name" VARCHAR(50) NOT NULL, "description" TEXT NOT NULL, "price" numeric(5, 2) NOT NULL, "stock" INTEGER NOT NULL, "updated_at" TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL, CONSTRAINT "products_pkey" PRIMARY KEY ("id"));
-- changeset lumin:1721661329831-2 labels:init
CREATE TABLE "customers" ("id" INTEGER NOT NULL, "name" VARCHAR(100) NOT NULL, "registered_at" TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL, CONSTRAINT "customers_pkey" PRIMARY KEY ("id"));
ทดสอบ ด้วยคำสั่ง status
$ liquibase status
changesets have not been applied to postgres@jdbc:postgresql://localhost:5432/app-local
migrations/000000-init-structure.sql::1721906361520-1::teerasak.vichadee
migrations/000000-init-structure.sql::1721906361520-2::teerasak.vichadee
ตอนนี้เรามี changeset 2 ตัวที่ยังไม่ได้รัน migrate (แน่ล่ะ ก็เราเพิ่ง generate มันใหม่จาก database structure เดิมที่มีอยู่แล้ว)
แต่อันที่จริง เราไม่จำเป็นต้อง migrate ก็เพราะว่ามันมี table ครบอยู่แล้ว ดังนั้นสิ่งที่เราควรทำคือ sync ข้อมูล changeset เหล่านี้ขึ้นไปเก็บและให้สถานะมันเป็น EXECUTED
หรือ รัน migrate ไปแล้ว
# check sync SQL
$ liquibase changelog-sync-sql --label-filter init --output-file dump.sql
Output saved to dump.sql
# updated undeployed changelog with label=init to EXECUTED
$ liquibase changelog-sync --label-filter init
เมื่อเข้าไปดูใน database จะพบว่าในตาราง databasechangelog
(เป็นตารางที่ liquibase สร้างมาเก็บ changelog record) มี 2 record ที่มี
- filename =
migrations/000000-init-structure.sql
- exectype =
EXECUTED
- labels =
init
ทดสอบอีกครั้ง
# ตรวจสอบว่ามี changelog ที่ยังไม่ได้ execute ไหม (ไม่ควรมี เพราะเพิ่งเปลี่ยนสถานะเป็น EXECUTED ไป)
$ liquibase status
postgres@jdbc:postgresql://localhost:5432/app-local is up to date
# ตรวจสอบว่า changelog ตัวไหนที่ execute ไปแล้ว
$ liquibase history
Liquibase History for jdbc:postgresql://localhost:5432/app-local
- Database updated at 7/25/24, 6:40 PM. Applied 2 changeset(s) in 0.009s, DeploymentId: 1907624549
migrations/000000-init-structure.sql::1721906361520-1::teerasak.vichadee
migrations/000000-init-structure.sql::1721906361520-2::teerasak.vichadee
ณ ตอนนี้ เรามี migration script ที่สามารถเอาไป execute ใน environment ใหม่ได้แล้ว
3) Test Migrate in New Environment
เราจะจำลองการเอาไปรันใน environment ใหม่โดยการ terminate docker container แล้วรัน migrate script
# terminate docker container ของโปรเจคปัจจุบัน
$ docker compose down
# start docker container อีกครั้ง (ซึ่ง database structure ทั้งหมดจะหายไปแล้ว)
$ docker compose up -d
ก่อนอื่น เราต้องสร้าง database app-local
ขึ้นมาก่อน
CREATE DATABASE "app-local";
หลังจากนั้นรัน migration script ด้วยคำสั่ง
$ liquibase update
Running Changeset: migrations/000000-init-structure.sql::1721906361520-1::teerasak.vichadee
Running Changeset: migrations/000000-init-structure.sql::1721906361520-2::teerasak.vichadee
UPDATE SUMMARY
Run: 2
Previously run: 0
Filtered out: 0
-------------------------------
Total change sets: 2
Liquibase: Update has been successful. Rows affected: 2
เมื่อไปเช็คใน database จะพบว่ามีตาราง products และ customers เกิดขึ้น ตามรายละเอียดของไฟล์ migrations/000000-init-structure.sql
4) Create New Migration Script
สมมุติเราต้องเพิ่ม feature ใหม่ให้ระบบ ซึ่งจะต้องมีการเปลี่ยนแปลงโครงสร้างตารางด้วย
เราควรสร้างไฟล์ changelog ใหม่ในโฟลเดอร์ migrations/
โดยกำหนดชื่อไฟล์ตาม pattern คือ migrations/20240725-sprint-11.sql
-- liquibase formatted sql
-- changeset teerasak.vichadee:pbi-111 labels:pbi-111,sprint-11
-- comment: pbi-111 implement orders aggregate
-- สร้างตาราง orders
CREATE TABLE "orders" (
"id" serial NOT NULL,
PRIMARY KEY ("id"),
"customer_id" integer NOT NULL,
"updated_at" timestamp NOT NULL,
"created_at" timestamp NOT NULL
);
-- สร้าง index สำหรับ orders.customer_id
CREATE INDEX "orders_customer_id" ON "orders" ("customer_id");
-- สร้างตาราง order_items
CREATE TABLE "order_items" (
"id" serial NOT NULL,
PRIMARY KEY ("id"),
"order_id" integer NOT NULL,
"product_id" integer NOT NULL,
"quantity" integer NOT NULL DEFAULT '0',
"updated_at" timestamp NOT NULL,
"created_at" timestamp NOT NULL
);
-- สร้าง index สำหรับ order_items.order_id และ order_items.product_id
CREATE INDEX "order_items_order_id" ON "order_items" ("order_id");
CREATE INDEX "order_items_product_id" ON "order_items" ("product_id");
-- rollback DROP TABLE orders;
-- rollback DROP TABLE order_items;
รายละเอียดภายในไฟล์ changelog ที่ควรสนใจและถกเถียงในทีมเวลาสร้าง
- เราควรสร้าง changeset ให้มีหลายๆ SQL command โดยขึ้นอยู่กับว่า มันเป็น change ที่เกี่ยวข้องกันไหม
- ซึ่งมันจะแลกมากับความยืดหยุ่นในการ migrate และ rollback เพราะถ้ามี change เยอะเกินไป หรือไม่เกี่ยวข้องการ การที่จะทำ rollback อาจจะส่งผลกระทบให้ต้อง rollback ทั้งหมด
- ด้วยมาตรฐานที่เราวางไว้ว่า เราจะสร้าง PBI ที่มี value และสามารถ deploy ได้ด้วยตัวมันเอง และไม่ dependency กับ PBI อื่นๆ ดังนั้นโดยปกติ 1 PBI ควรมีแค่ 1 changeset
- SQL command ในแต่ละ changset ควรใช้ command ที่ได้ performance เพื่อเสียเวลาในการรัน migrate น้อยที่สุด เช่น ถ้าจะ insert เพื่อทำ seeding ควรใช้ batch insert ไม่ควร insert 1 record per row
- ทุก changeset ควรมี rollback
- rollback script สามารถใส่หลายๆตัวภายใน changeset ดังนั้นเราสามารถใส่ควบคู่ไปกับ SQL command แต่ละตัวได้เลย
จากนั้นทดสอบ migration script ด้วย
# เช็คสถานะของ changeset ที่เราสร้าง
$ liquibase status
1 changeset has not been applied to postgres@jdbc:postgresql://localhost:5432/app-local
migrations/20240725-sprint-11.sql::pbi-111::teerasak.vichadee
# สร้าง migration script เพื่อเอามารีวิว
$ liquibase update-sql --output-file migration-sprint-11.review.sql
Output saved to migration-sprint-11.review.sql
# สร้าง rollback script เพื่อเอามารีวิว
$ liquibase future-rollback-sql --output-file migration-sprint-11-rollback.review.sql
Output saved to migration-sprint-11-rollback.review.sql
ในการทำงานเราควรเอาไฟล์ migration-sprint-11.review.sql
มีรีวิวว่ามีรายละเอียดตรงกับที่เราต้องการหรือไม่ (ข้อเสียของ Liquibase คือ ไม่แสดง SQL comment ที่เราใส่ไปใน changelog)
...
-- *********************************************************************
-- Update Database Script
-- *********************************************************************
-- Change Log: liquibase.changelog.yml
-- Ran at: 7/26/24, 9:32 AM
-- Against: postgres@jdbc:postgresql://localhost:5432/app-local
-- Liquibase version: 4.28.0
-- *********************************************************************
...
CREATE TABLE "orders" (
"id" serial NOT NULL,
PRIMARY KEY ("id"),
"customer_id" integer NOT NULL,
"updated_at" timestamp NOT NULL,
"created_at" timestamp NOT NULL
);
CREATE INDEX "orders_customer_id" ON "orders" ("customer_id");
CREATE TABLE "order_items" (
"id" serial NOT NULL,
PRIMARY KEY ("id"),
"order_id" integer NOT NULL,
"product_id" integer NOT NULL,
"quantity" integer NOT NULL DEFAULT '0',
"updated_at" timestamp NOT NULL,
"created_at" timestamp NOT NULL
);
CREATE INDEX "order_items_order_id" ON "order_items" ("order_id");
CREATE INDEX "order_items_product_id" ON "order_items" ("product_id");
...
และก็ควรรีวิว rollback script จากไฟล์ migration-sprint-11-rollback.review.sql
...
-- *********************************************************************
-- SQL to roll back currently unexecuted changes
-- *********************************************************************
-- Change Log: liquibase.changelog.yml
-- Ran at: 7/26/24, 9:43 AM
-- Against: postgres@jdbc:postgresql://localhost:5432/app-local
-- Liquibase version: 4.28.0
-- *********************************************************************
...
-- Rolling Back ChangeSet: migrations/20240725-sprint-11.sql::pbi-111::teerasak.vichadee
DROP TABLE orders;
DROP TABLE order_items;
...
เมื่อรีวิวตรวจสอบความถูกต้องดีแล้ว จึงรัน migrate
# สั่งรัน migration script
$ liquibase update
Running Changeset: migrations/20240725-sprint-11.sql::pbi-111::teerasak.vichadee
UPDATE SUMMARY
Run: 1
Previously run: 2
Filtered out: 0
-------------------------------
Total change sets: 3
Liquibase: Update has been successful. Rows affected: 1
# ตรวจสอบ history การรัน migration
$ liquibase history --format text
Liquibase History for jdbc:postgresql://localhost:5432/app-local
- Database updated at 7/25/24, 6:53 PM. Applied 2 changeset(s) in 0.013s, DeploymentId: 1908401506
migrations/000000-init-structure.sql::1721906361520-1::teerasak.vichadee
migrations/000000-init-structure.sql::1721906361520-2::teerasak.vichadee
- Database updated at 7/26/24, 9:20 AM. Applied 1 changeset(s), DeploymentId: 1960449791
migrations/20240725-sprint-11.sql::pbi-111::teerasak.vichadee
ซึ่งใน history จะเห็นว่า changelog ของเราเป็น update ล่าสุดที่เกิดขึ้น
5) Rollback!
เมื่อเกิดปัญหา เราสามารถสั่ง rollback ดังนี้
$ liquibase rollback-sql --label-filter sprint-11 --output-file migration-sprint-11-rollback.preview.sql
Output saved to migration-sprint-11-rollback.preview.sql
$ liquibase rollback --label-filter sprint-11
Rolling Back Changeset: migrations/20240725-sprint-11.sql::pbi-111::teerasak.vichadee
$ liquibase history --format text
Liquibase History for jdbc:postgresql://localhost:5432/app-local
- Database updated at 7/25/24, 6:53 PM. Applied 2 changeset(s) in 0.013s, DeploymentId: 1908401506
migrations/000000-init-structure.sql::1721906361520-1::teerasak.vichadee
migrations/000000-init-structure.sql::1721906361520-2::teerasak.vichadee
การ rollback เราสามารถทำได้ 2 แบบ
- ใช้
rollback-count 1
เพื่อบอกว่าให้ rollback migration ล่าสุด แต่เราจะแน่ใจได้อย่างว่า นั่นคือ rollback ที่ถูกต้อง และถ้าไม่ถูกต้องจะต้องทำอย่างไร - ใช้
rollback --label-filter sprint-11
เพื่อทำ rollback สำหรับ migrate ที่มี label =sprint-11
จะมีความ specific มากขึ้น โดยกำหนดว่าจะต้อง rollback migration ที่มี label ตามที่กำหนด
ดังนั้น ถ้าหากว่าเราใส่ label กำกับทุกครั้ง เราควรใช้ท่า rollback --label-filter
Summary
- สร้าง pattern ของไฟล์ changelog ให้สามารถ filter ได้ เช่น
20240725-sprint-11.sql
- สร้าง pattern ของ changeset
- ใช้ unqiue-numer เป็นเลข pbi
- ใส่ label เพื่อให้สามารถ filter เพื่อ migrate หรือ rollback ได้
-
migration workflow
- สร้าง changelog ไปเก็บใน
migrations/
และต้องใส่ rollback ในทุกๆ changeset ที่มีการเปลี่ยนแปลง และอย่าลืมกำหนด label ตาม pattern - run migrate
# ตรวจสอบก่อนว่ามี pending changelog อยู่ไหม และใช่ของเราหรือปล่าว liquibase status # ตรวจสอบ migration script (ไม่ควรจะมีของเรา) liquibase update-sql --output-file migration-sprint-11.review.sql # ตรวจสอบ rollback script (ควรจะมี comment บอกว่ามาจากไฟล์ changelog ของเรา) liquibase future-rollback-sql --label-filter "sprint-11" --output-file migration-sprint-11.review.sql # สั่งรัน migration script liquibase update # ตรวจสอบ pending อีกครั้งว่ารันไปแล้วหรือยัง (มันควรจะหายไป) liquibase status # ตรวจสอบ migration script ที่รันไปแล้ว (ควรมีของเราเป็นอันสุดท้าย) liquibase history
- run rollback
# ตรวจสอบ rollback script (ควรจะมี comment บอกว่ามาจากไฟล์ changelog ของเรา) liquibase rollback-sql --label-filter "sprint-11" --output-file rollback-sprint-11.review.sql # สั่ง rollback ด้วย label ของ changeset liquibase rollback --label-filter "sprint-11" # ตรวจสอบ pending (ควรจะแสดง changeset ที่ถูก rollback) liquibase status # ตรวจสอบ migration script ที่รันไปแล้ว (ไม่ควรมี changeset ที่ถูก rollback) liquibase history
- สร้าง changelog ไปเก็บใน
Improvement
Makefile
เพื่อซ่อนความซับซ้อนและเพิ่มความเข้าใจในการรัน เราควรสร้าง Makefile ดังนี้
help: ## Shows the available commands.
@printf "Available Commands:\n"
@grep -E '^[a-zA-Z0-9_/\-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
@printf "\nExample:\n"
@printf " - make migration/status\n"
@printf " - make migration/status OPTIONS=\"--label-filter init\"\n"
@printf "\n"
migration/pending: ## ตรวจสอบ migration script ที่ยังไม่ได้รัน
liquibase status $(OPTIONS)
migration/check-migrate: ## เตรียม SQL สำหรับรัน migration
liquibase update-sql --output-file migration.review.sql $(OPTIONS)
migration/check-future-rollback: ## เตรียม SQL สำหรับรัน rollback
liquibase future-rollback-sql --output-file rollback.review.sql $(OPTIONS)
migration/check-rollback: ## เตรียม SQL สำหรับรัน rollback
ifndef labels
$(error ระบุ labels โดยใช้คำสั่ง 'make migration/prepare-rollback labels=<label ที่เราต้องการ>')
endif
liquibase rollback-sql --output-file prepare-rollback.review.sql --label-filter=$(labels) $(OPTIONS)
migration/migrate: ## รัน migration script
liquibase update $(OPTIONS)
migration/rollback: ## รัน rollback script
ifndef labels
$(error ระบุ labels โดยใช้คำสั่ง 'make migration/rollback labels=<label ที่เราต้องการ>')
endif
liquibase rollback --label-filter=$(labels) $(OPTIONS)
migration/history: ## ตรวจสอบ migration script ที่รันไปแล้ว
liquibase history --format text $(OPTIONS)
-
make migration/pending
-- ตรวจสอบ migration script ที่ยังไม่ได้รัน -
make migration/check-migrate
-- เตรียม SQL สำหรับรัน migration เพื่อเอามารีวิว -
make migration/check-future-rollback
-- เตรียม SQL สำหรับรัน rollback ทุกอย่างที่อยู่ใน pending เพื่อเอามารีวิว -
make migration/migrate
-- รัน migration script -
make migration/check-rollback labels=<label>
-- เตรียม SQL สำหรับรัน rollback เฉพาะ changeset ที่มีlabels=<label>
เพื่อเอามารีวิว -
make migration/rollback labels=<label>
-- รัน rollback script เฉพาะ changeset ที่มีlabels=<label>
-
make migration/history
-- ตรวจสอบ migration script ที่รันไปแล้ว
Top comments (0)