یک ستون نسخه خودکار با محرک های postgresql ایجاد کنید

مقدمه
هنگام ساختن طرحواره های پایگاه داده ، اغلب تمایل به ایجاد یک ستون نسخه در همه یا برخی از میزهای پایگاه داده وجود خواهد داشت. واکنش زانو یک توسعه دهنده ممکن است اجرای این امر در سطح کد باشد. این روش بسته به نحوه معماری کد شما می تواند بسیار ساده باشد. بگویید که شما یک سرویس/ماژول CRUD را در برنامه خود دارید ، فقط می توانید در آنجا منطق را برای افزایش یک ستون نسخه در حین بروزرسانی اضافه کنید. این رویکرد می تواند خوب عمل کند اما هنوز یک چیز دیگر است که باید در صورت تغییر الگوهای سطح کد شما از اصلاح مجدد ، پیگیری شود.
استفاده از یک ماشه پایگاه داده یک رویکرد ساده و کارآمدتر برای حل این مشکل است. این چیزی است که PostgreSQL (Postgres) ، در بین بیشتر بانکهای اطلاعاتی مدرن ، به عنوان یک ویژگی پشتیبانی می کند و استفاده از آن می تواند بسیار قدرتمند باشد. برای نشان دادن چگونگی انجام این کار ، ما چگونه می توانیم یک ماشه را در Postgres برای اجرای یک ستون نسخه سازی خودکار انجام دهیم.
در این پست فرض می کنم که شما حداقل دانش در مورد محرک های Postgres دارید و هر مرحله از راه را توضیح می دهید.
محرک ها چیست و چگونه کار می کنند؟
Postgres Triggers به شما امکان می دهد تا یک اعلامیه برای اجرای یک تابع در پایگاه داده ایجاد کنید که به اقدامات خاصی پیوند می یابد. برخی ممکن است از اینها به عنوان “قلاب” فکر کنند که به اقدامات پایگاه داده می شوند. اقداماتی که من در اینجا به آنها اشاره می کنم اظهارات DML است INSERT
با UPDATE
وت DELETE
بشر این اقدامات در استاندارد SQL مشخص شده است. منطق موجود در عملکردی که ایجاد می شود می تواند بیشتر برای آتش سوزی مشخص شود BEFORE
یا AFTER
عملی که در حال انجام است. علاوه بر دستورات DML که قبلاً ذکر شد ، Postgres همچنین از اضافه کردن محرک های اطراف پشتیبانی می کند TRUNCATE
عملی که همه بانکهای اطلاعاتی از آن پشتیبانی نمی کنند.
نکته دیگری که باید در نظر داشته باشید این است که محرک ها معامله ای هستند. این بدان معنی است که محرک ها بخشی از همان معامله هستند که بیانیه ای که آنها را اخراج می کند و اگر معامله به عقب برگردد ، اقدامات ماشه نیز به عقب برگردانده می شود. این مهم است که باید برای اهداف اشکال زدایی و چیزی که باید از دیدگاه مشاهده در هنگام اجرای محرک ها در نظر بگیرید ، در نظر داشته باشید. هر زمان که منطق بیشتری را به پایگاه داده خود اضافه می کنید ، البته می توان نقاط شکست بیشتری را در نظر گرفت که اکنون در خارج از سطح کد قرار دارد.
ساخت یک ماشه Postgres
برای اولین بار که هدف ما در اینجا چیست. ما یک جدول با ستونی به نام ایجاد خواهیم کرد version
این به 0 می رسد ، و هدف ما برای هر یک خواهد بود UPDATE
بیانیه ای که علیه یک ردیف در این جدول اجرا شده است ، version
ستون با 1 افزایش می یابد.
بیایید با یک عبارت DML شروع کنیم تا یک جدول برای استفاده از ماشه خود ایجاد کنیم.
CREATE TABLE table_1 (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
version INTEGER NOT NULL DEFAULT 0,
name VARCHAR NOT NULL
);
در این جمله ، من سه ستون به جدول اضافه کرده ام table_1
بشر
-
id
– این به عنوان کلید اصلی و پیش فرض ما برای استفاده از عملکرد بومی Postgres ازgen_random_uuid()
برای اینکه یک شناسه منحصر به فرد برای هر ردیف در جدول به ما بدهید. -
version
– این به عنوان ستون نسخه ای که ما با ماشه خود افزایش خواهیم داد ، خدمت می کند. تنظیم شده روی پیش فرض 0 است. -
name
– الفVARCHAR
ستون ما برای استفاده از به روزرسانی های خود استفاده خواهیم کرد.
حال برای به دست آوردن چیزی برای کار با آن ، بیایید یک ردیف را در جدول جدید خود قرار دهیم.
INSERT INTO table_1 (name) VALUES ('Nick');
اگر شما اجرا کنید SELECT
بیانیه ای که باید یک رکورد جدید در آن مشاهده کنید table_1
بشر
SELECT * FROM table_1;
اولین قدم برای ایجاد ماشه ایجاد یک تابع است. این ممکن است کمی عجیب به نظر برسد اما ایجاد ماشه یک فرآیند دو قسمتی است. ابتدا یک تابع ایجاد کنید ، سپس ماشه ای را ایجاد کنید که از عملکرد استفاده می کند. تمام جادو در داخل عملکردی اتفاق می افتد که باید به عنوان یک نوع خاص از عملکرد Postgres تنظیم شود. این تابع به روشی مشابه با هر عملکرد دیگر یا رویه ذخیره شده ایجاد می شود به جز اینکه نباید هیچ آرگومی را انجام دهد و باید یک نوع از آن را برگرداند TRIGGER
بشر در مورد ما ، عملکرد به این شکل خواهد بود.
CREATE OR REPLACE FUNCTION increment_version()
RETURNS TRIGGER AS $$
BEGIN
NEW.version = COALESCE(OLD.version, 0) + 1;
RETURN NEW;
END
$$ LANGUAGE plpgsql;
چند نکته که باید در مورد بیانیه فوق توجه داشته باشید:
- من استفاده می کنم
CREATE OR REPLACE
در اینجا که به عنوان یک عمل “upsert” برای عملکرد کار می کند. اگر این اولین بار است که فقط نوشتن یک تابع ایجاد می کندCREATE
خوب کار می کرد - این تابع اعلام شده است که یک ماشه را با
RETURNS TRIGGER
بشر - در
OLD
وتNEW
متغیرها در داخل همه محرک های Postgres در دسترس هستند و به ترتیب با سابقه جدول قدیمی و رکورد جدول جدید مطابقت دارند. مقدار ستونversion
از طریق نماد نقطه قابل دسترسی است. -
LANGUAGE plpgsql
اعلام می کند که عملکرد درPL/pgSQL
زبان رویه ای.
با داشتن عملکرد ، اکنون می توانیم ماشه را در جدول خود بمالیم.
CREATE OR REPLACE TRIGGER update_version
BEFORE UPDATE ON table_1
FOR EACH ROW
EXECUTE FUNCTION increment_version();
جمله ای برای اعمال ماشه کمی ساده تر از ایجاد عملکرد است.
- ماشه با نام ایجاد می شود
update_version
بشر -
BEFORE UPDATE
مشخص می کند که ما می خواهیم قبل از اجرای بیانیه به روزرسانی ، ماشه را آتش بزنیمtable_1
بشر -
FOR EACH ROW
مشخص می کند که این امر باید در مورد هر سطر تحت تأثیر بیانیه به روزرسانی اعمال شود. -
EXECUTE FUNCTION increment_version()
اعلام می کند که عملکرد ما از مرحله قبلی در اینجا فراخوانی خواهد شد.
ماشه اکنون اعمال شده است. اگر یک عبارت به روزرسانی را به سابقه ای که قبلاً ایجاد کردیم اجرا کنید ، باید با هر بروزرسانی ستون نسخه را با 1 مشاهده کنید.
با عملکردی که قبلاً ایجاد شده است ، می توان این ماشه را به جداول جدید گسترش داد. شما به سادگی اجرا می کنید CREATE OR REPLACE TRIGGER
بیانیه علیه جدول که می خواهید ماشه را اعمال کنید. به عنوان مثال ، اگر جدول دیگری داشتیم ، table_2
، ما می توانیم بیانیه زیر را اجرا کنیم.
CREATE OR REPLACE TRIGGER update_version
BEFORE UPDATE ON table_2
FOR EACH ROW
EXECUTE FUNCTION increment_version();
یک نکته قابل توجه این است که ما از همین نام برای ماشه استفاده کردیم ، update_version
، در این جدول جدید ، و این کاملاً خوب است! نام های ماشه باید در متن همان جدول بی نظیر باشند ، اما می توانند در جداول مختلف یکسان باشند. بنابراین ، اگر ما یک ماشه جدید ایجاد کردیم table_2
، ما باید به غیر از آن نامی بدهیم update_version
از آنجا که این اکنون گرفته شده است.
افزودن اعتبار سنجی بهتر
در این مرحله ، شما ممکن است از خود بپرسید ، “اگر جدول نداشت version
ستون؟ “. پاسخ به این امر این است که عملکردی که ما نوشتیم خطایی را ایجاد می کند ، و همانطور که قبل از ماشه گفته شد معامله ای است ، بنابراین کل معامله را ایجاد می کند که این عمل بخشی از بازگشت است. اگر بسیار مراقب باشید و داشته باشید پوشش آزمایشی خوب ممکن است چیزی نگران نباشد ، و خطاها به سرعت در حال افزایش است زیرا شما می بینید که یک تن از شکست ها از عملیات به روزرسانی ناشی می شود.
برای افزایش اعتبار سنجی ، می توانیم عملکرد خود را با یک منطق اضافی که در صورت عدم وجود عدم موفقیت برای ما ایجاد می کند ، به روز کنیم version
ستون روی جدول وجود نداشت. در اینجا عملکرد اصلاح شده است.
CREATE OR REPLACE FUNCTION increment_version()
RETURNS TRIGGER AS $$
DECLARE
table_columns TEXT[];
column_exists BOOLEAN;
BEGIN
SELECT ARRAY_AGG(column_name)
INTO table_columns
FROM information_schema.columns
WHERE table_name = TG_TABLE_NAME
AND table_schema = TG_TABLE_SCHEMA;
column_exists := 'version' = ANY(table_columns);
IF column_exists IS TRUE THEN
NEW.version = COALESCE(OLD.version, 0) + 1;
END IF;
RETURN NEW;
END
$$ LANGUAGE plpgsql;
عملکرد به روز شده دارای منطق جدیدی برای افزودن اعتبار سنجی است.
- پرس و جو برای خواندن ستون های جدول ما با پرس و جو در برابر
information_schema.columns
جدول ، که در زیر کاپوت توسط Postgres نگهداری می شود. یک فیلتر در برابر پرس و جو باTG_TABLE_NAME
وتTG_TABLE_SCHEMA
، که متغیرهایی هستند که در داخل Postgres در دسترس هستند و با نام جدول و طرحواره ای که جدول در آن قرار دارد مطابقت دارد. - چک برای دیدن اینکه آیا
version
ستون با وجود داردcolumn_exists := 'version' = ANY(table_columns);
بشر - عملیات برای افزایش
version
ستون بسته به اینکه ستون در جدول وجود داشته باشد ، مشروط است.
از آنجا که ما عملکرد را رونویسی کرده ایم CREATE OR REPLACE FUNCTION
، نام تغییر نکرده است و این بروزرسانی به طور خودکار در هر کجا که اعمال می شود وارد می شود!
پایان
ما توانستیم یک ماشه اصلی Postgres ایجاد کنیم تا نسخه ای را به سوابق پایگاه داده خود اضافه کنیم. این یک مورد بسیار ساده است و کاربردهای محرک های Postgres بی پایان است. امیدوارم این بینش در مورد چگونگی اجرای یک ماشه Postgres آسان باشد و شما را به این فکر می کند که چه منطق سطح کد می تواند به لایه پایگاه داده شما منتقل شود.
برای مطالعه بیشتر در مورد محرک های Postgres ، می توانید اسناد را در اینجا بررسی کنید
با تشکر از خواندن!