برنامه نویسی

یک ستون نسخه خودکار با محرک های 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 ، می توانید اسناد را در اینجا بررسی کنید

با تشکر از خواندن!

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا