پستگرس db/postgres
کارخواه PostgreSQL نوشتهشده با خود سلام: رشتهی اتصال و نشانی، TLS، پرسمان، تراکنش، استخر اتصال و مهاجرت.
واردسازی دیتابیس.پستگرس
- آموزش: کتابفروشی در یازده گام
- ۱. اتصال
- ۲. رشتهی اتصال، نشانی و TLS
- ۳. ساختن جدولها
- ۴. افزودن ردیف و گرفتن شناسهی تازه
- ۵. خواندن ردیفها درون ساختارهای خودتان
- ۶. مقدارهای کاربر، به شکل امن
- ۷. مقدار NULL
- ۸. تراکنش
- ۹. خطاها
- ۱۰. استخر اتصال، و یک اتصال برای هر نخ
- ۱۱. امکانات PostgreSQL
- بیشتر
- راهنما: مهاجرت طرحواره
- راهنما: تنظیمها از متغیرهای محیطی
- راهنما: نتیجهی تودرتو به شکل JSON
- راهنما: کدام تابع برای کدام کار
- گونهها
- تابعها
این بسته مستقیم با PostgreSQL حرف میزند: پروتکل شبکهی پستگرس را در خود سلام پیاده میکند، با ورود به روش گذرواژهی ساده، MD5 و SCRAM-SHA-256 و TLS اختیاری، پس به libpq یا هیچ کتابخانهی بیرونی دیگری نیاز ندارد. همهی ردیفهای نتیجه یکجا از سرور گرفته میشوند، پس تعداد ردیف پیش از خواندن هم معلوم است. هر پایگاه داده در رابط مشترک اتصال از بستهی دیتابیس هم مینشیند و با آن به تابعهای مستقل از موتور، استخر اتصال و مهاجرت طرحواره دسترسی دارید. این صفحه با یک آموزش شروع میشود و مرجع کامل همهی تابعها و گونهها پس از آن میآید.
آموزش: کتابفروشی در یازده گام
گامهای زیر پایگاه دادهی یک کتابفروشی کوچک را میسازند: کتابها، موجودی انبار و سفارشها. هر گام یک برنامهی کامل است و خروجی زیر آن همان چیزی است که در برابر یک PostgreSQL 17 واقعی چاپ کرد. گامها را به ترتیب اجرا کنید، چون هر گام از دادههایی که گامهای قبل گذاشتهاند استفاده میکند. دادهها فارسیاند و پستگرس متن فارسی را بی هیچ تنظیم اضافهای نگه میدارد و جستجو میکند.
اول یک سرور راه بیندازید. با داکر یک فرمان کافی است؛ این فرمان پایگاه دادهی bookshop و کاربر postgres را با گذرواژهی secret میسازد:
docker run -d --name bookshop-db -p 5432:5432 -e POSTGRES_PASSWORD=secret -e POSTGRES_DB=bookshop postgres:17-alpine
بدون داکر، PostgreSQL را از بستههای سیستمعامل نصب کنید، فرمان createdb bookshop را بزنید و همین گذرواژه را به کاربر postgres بدهید. برنامهها به 127.0.0.1 روی درگاه ۵۴۳۲ وصل میشوند. برنامهی واقعی به جای postgres با کاربر خودش وارد میشود، همانطور که گام ۲ نشان میدهد.
۱. اتصال
بازکردن یک رشتهی اتصال از جفتهای key=value میگیرد، همان قالبی که psql و libpq به کار میبرند. این تابع همیشه یک پایگاه داده برمیگرداند، حتی وقتی ورود شکست خورده باشد، پس پیش از هر کاری معتبر را بپرسید؛ در آن صورت خطا پیام سرور را دارد. پینگ یک پرسمان بسیار کوچک میفرستد تا مطمئن شود اتصال هنوز کار میکند، و برای وارسی سلامت یک سرویس همیشهروشن مناسب است.
واردسازی دیتابیس.پستگرس
تابع ریشه:
پ := پستگرس.بازکردن("host=127.0.0.1 port=5432 user=postgres password=secret dbname=bookshop")
دیرکن پستگرس.بستن(پ)
اگر وارونه پستگرس.معتبر(پ):
چاپ "اتصال برقرار نشد: " + پستگرس.خطا(پ)
برگشت ۱
پایان
سرچاپ "وصل شد به"، پستگرس.نام پایگاه داده(پ)، "با کاربر"، پستگرس.نام کاربر(پ)
سرچاپ "سرور"، پستگرس.نام میزبان(پ) + ":" + پستگرس.درگاه(پ)، "نسخه"، پستگرس.نسخه سرور(پ)
سرچاپ پستگرس.پرسمان متن(پ، "SELECT split_part(version(), ' on ', 1)")
سرچاپ "زنده است:"، پستگرس.پینگ(پ)
اشتباه := پستگرس.بازکردن("host=127.0.0.1 user=postgres password=wrong dbname=bookshop")
دیرکن پستگرس.بستن(اشتباه)
سرچاپ "با گذرواژهی نادرست:"، پستگرس.معتبر(اشتباه)
چاپ پستگرس.خطا(اشتباه)
خاموش := پستگرس.بازکردن("host=127.0.0.1 port=5499 user=postgres password=secret connect_timeout=3")
دیرکن پستگرس.بستن(خاموش)
سرچاپ "وقتی سروری روی درگاه نیست:"، پستگرس.معتبر(خاموش)
چاپ پستگرس.خطا(خاموش)
پایانپیامهای خود سرور به همان زبان PostgreSQL میمانند و با شدت خطا شروع میشوند: FATAL برای ورود ردشده و ERROR برای دستوری که شکست خورده. پیام خطا با یک خط تازه تمام میشود و برای همین نمونهها آن را با چاپ مینویسند نه سرچاپ. اگر چیزی روی درگاه گوش ندهد، بازکردن بیدرنگ شکست میخورد. connect_timeout بر حسب ثانیه است و تعیین میکند ورود برای هر پاسخ سرور چقدر صبر کند؛ اگر ننویسید ۳۰ ثانیه است.
۲. رشتهی اتصال، نشانی و TLS
همین تنظیمها را به سه شکل میتوان نوشت: جفتهای key=value، نشانی postgresql://user:password@host:port/dbname?key=value، یا پنج آرگومان بازکردن کامل. این گام یک نقش ورود برای فروشگاه هم میسازد، با گذرواژهای که فاصله و @ دارد، تا نشان دهد چنین مقداری در هر شکل چطور نوشته میشود.
واردسازی دیتابیس.پستگرس
تابع ریشه:
مدیر := پستگرس.بازکردن کامل("127.0.0.1"، ۵۴۳۲، "postgres"، "secret"، "bookshop")
دیرکن پستگرس.بستن(مدیر)
سرچاپ "بازکردن کامل:"، پستگرس.معتبر(مدیر)
_ := پستگرس.اجرا(مدیر، "DROP ROLE IF EXISTS clerk")
_ := پستگرس.اجرا(مدیر، "CREATE ROLE clerk LOGIN PASSWORD 'p@ss word'")
الف := پستگرس.بازکردن("host=127.0.0.1 user=clerk password='p@ss word' dbname=bookshop")
دیرکن پستگرس.بستن(الف)
سرچاپ "مقدار در نقل قول:"، پستگرس.معتبر(الف)، پستگرس.نام کاربر(الف)
ب := پستگرس.بازکردن("postgresql://clerk:p%40ss%[email protected]:5432/bookshop?connect_timeout=5")
دیرکن پستگرس.بستن(ب)
سرچاپ "نشانی:"، پستگرس.معتبر(ب)، پستگرس.نام کاربر(ب)، پستگرس.نام پایگاه داده(ب)
ج := پستگرس.بازکردن("host=127.0.0.1 user=clerk password='p@ss word' dbname=bookshop sslmode=disable")
دیرکن پستگرس.بستن(ج)
سرچاپ "sslmode=disable:"، پستگرس.معتبر(ج)، پستگرس.پرسمان متن(ج، "SHOW ssl")
ت := پستگرس.بازکردن("host=127.0.0.1 user=clerk password='p@ss word' dbname=bookshop sslmode=require")
دیرکن پستگرس.بستن(ت)
سرچاپ "sslmode=require:"، پستگرس.معتبر(ت)
چاپ پستگرس.خطا(ت)
پایاندر شکل key=value مقداری که فاصله دارد میان نقلقول تکی میآید. در نشانی، نویسههایی که معنای خاص دارند درصدی کد میشوند: %40 برای @ و %20 برای فاصله. بازکردن کامل آرگومانهایش را بی نقلقول کنار هم میگذارد، پس فقط برای مقدارهای بیفاصله مناسب است.
کلیدهایی که این بسته میخواند اینها هستند: host (یا hostaddr)، port، user، password، dbname، sslmode، sslrootcert و connect_timeout؛ کلیدهای دیگر نادیده گرفته میشوند. sslmode مثل libpq رفتار میکند: prefer (پیشفرض) اگر سرور TLS داشته باشد آن را به کار میبرد، require بدون TLS ادامه نمیدهد، verify-ca و verify-full گواهی سرور را هم وارسی میکنند (اگر sslrootcert بدهید، با همان فایل CA)، و disable و allow اصلا TLS نمیخواهند. بدون یکی از حالتهای verify گواهی وارسی نمیشود. سرور آزمایشی اینجا TLS را خاموش دارد، برای همین require شکست میخورد. سوکت یونیکس پشتیبانی نمیشود؛ حتی روی همان ماشین هم با TCP وصل شوید.
۳. ساختن جدولها
اجرا دستوری را اجرا میکند که ردیفی برنمیگرداند و در صورت موفقیت ۰ و در صورت شکست ۱- میدهد. چند دستور جداشده با نقطهویرگول را هم یکجا میپذیرد که برای تعریف طرحواره مناسب است. گونههای PostgreSQL را متناسب با داده انتخاب کنید: bigint GENERATED ALWAYS AS IDENTITY برای شناسه، numeric برای پول، text[] برای فهرست برچسبها و jsonb برای جزئیات بیقالب.
واردسازی دیتابیس.پستگرس
تابع ریشه:
پ := پستگرس.بازکردن("host=127.0.0.1 user=postgres password=secret dbname=bookshop")
دیرکن پستگرس.بستن(پ)
طرح := `
DROP TABLE IF EXISTS orders, books;
CREATE TABLE books (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
title text NOT NULL UNIQUE,
author text NOT NULL,
year int CHECK (year > 0),
price numeric(6, 2) NOT NULL CHECK (price >= 0),
stock int NOT NULL DEFAULT 0 CHECK (stock >= 0),
isbn text,
tags text[] NOT NULL DEFAULT '{}',
info jsonb NOT NULL DEFAULT '{}'
);
CREATE TABLE orders (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
customer text NOT NULL,
book_id bigint NOT NULL REFERENCES books (id),
qty int NOT NULL CHECK (qty > 0),
total numeric(8, 2) NOT NULL
);`
اگر پستگرس.اجرا(پ، طرح) نابرابر ۰:
چاپ پستگرس.خطا(پ)
برگشت ۱
پایان
ر := پستگرس.پرسمان(پ، `SELECT table_name, column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_name IN ('books', 'orders') ORDER BY table_name, ordinal_position`)
دیرکن ر.بستن()
تا ر.بعدی():
سرچاپ ر.متن(۰) + "." + ر.متن(۱)، ر.متن(۲)، "خالیپذیر:"، ر.متن(۳)
پایان
پایانقیدهایی مثل UNIQUE، CHECK (stock >= 0) و REFERENCES باعث میشوند پایگاه داده دادهی نادرست را رد کند، حتی وقتی اشکالی در برنامه بخواهد آن را بنویسد. گام ۹ نشان میدهد این رد شدن چه شکلی دارد.
۴. افزودن ردیف و گرفتن شناسهی تازه
دستور INSERT ... RETURNING id یک پرسمان است که شناسهی ساختهشده را برمیگرداند، پس آن را با پرسمان اجرا کنید و تنها ردیفش را بخوانید. متنی که از بیرون برنامه میآید از نقل قول میگذرد که آن را به شکل یک رشتهی SQL نقلقولدار و گریزخورده برمیگرداند: نقلقول درون متن دوتایی میشود و نمیتواند رشته را زودتر ببندد. اجرا با شمارش یک دستور را اجرا میکند و میگوید چند ردیف افزوده، بهروز یا حذف شد.
واردسازی دیتابیس.پستگرس
واردسازی رشته
تابع افزودن کتاب(پ: پستگرس.پایگاه داده، عنوان: رشته، نویسنده: رشته، سال: صحیح، قیمت: رشته، موجودی: صحیح): صحیح۶۴:
دستور := "INSERT INTO books (title, author, year, price, stock) VALUES (" + پستگرس.نقل قول(پ، عنوان) + ", " + پستگرس.نقل قول(پ، نویسنده) + ", " + رشته.از عدد(سال) + ", " + قیمت + ", " + رشته.از عدد(موجودی) + ") RETURNING id"
ر := پستگرس.پرسمان(پ، دستور)
دیرکن ر.بستن()
اگر وارونه ر.بعدی():
چاپ پستگرس.خطا(پ)
برگشت ۰
پایان
برگشت ر.عدد صحیح۶۴(۰)
پایان
تابع ریشه:
پ := پستگرس.بازکردن("host=127.0.0.1 user=postgres password=secret dbname=bookshop")
دیرکن پستگرس.بستن(پ)
سرچاپ پستگرس.نقل قول(پ، "کتاب 'سووشون' از سیمین دانشور")
سرچاپ "بوف کور شناسهی"، افزودن کتاب(پ، "بوف کور"، "صادق هدایت"، ۱۳۱۵، "12.50"، ۴)، "گرفت"
سرچاپ "سووشون شناسهی"، افزودن کتاب(پ، "سووشون"، "سیمین دانشور"، ۱۳۴۸، "9.99"، ۲)، "گرفت"
تعداد := پستگرس.اجرا با شمارش(پ، `INSERT INTO books (title, author, year, price, stock, isbn, tags) VALUES
('گلستان', 'سعدی', 656, 7.25, 3, '978-9643510011', '{شعر,کلاسیک}'),
('شازده کوچولو', 'آنتوان دو سنتاگزوپری', 1322, 6.00, 10, '978-9643620475', '{افسانه,کلاسیک}'),
('سمفونی مردگان', 'عباس معروفی', 1368, 11.00, 1, NULL, '{رمان}')`)
سرچاپ تعداد، "کتاب دیگر افزوده شد، آخرین شناسه"، پ.شناسه آخرین درج()
ر := پستگرس.پرسمان(پ، "UPDATE books SET tags = '{رمان,کلاسیک}' WHERE title = 'بوف کور' RETURNING id, title, tags")
تا ر.بعدی():
سرچاپ "بهروز شد"، ر.عدد صحیح(۰)، ر.متن(۱)، ر.متن(۲)
پایان
ر.بستن()
سرچاپ "افزایش قیمت روی"، پستگرس.اجرا با شمارش(پ، "UPDATE books SET price = price + 1 WHERE year < 1300")، "کتاب کهن"
پایانشناسه آخرین درج مقدار lastval() را از سرور میپرسد، یعنی آخرین مقداری که یک دنباله یا ستون شناسه در این نشست ساخته است. پس از درج سهردیفی، این شناسهی ردیف آخر است؛ اگر همهی شناسهها را بخواهید RETURNING روشنتر است. RETURNING روی UPDATE و DELETE هم کار میکند، همانطور که تغییر برچسب نشان میدهد.
پ.تعداد تغییرات() شمار ردیفهایی است که آخرین پ.اجرا(...) تغییر داد. این عدد فقط وقتی نگه داشته میشود که متد را روی خود مقدار صدا بزنید؛ تابع بستهای پستگرس.اجرا(پ، ...) روی یک رونوشت کار میکند و پس از آن پ.تعداد تغییرات() صفر میماند. اجرا با شمارش این پرسش را از میان برمیدارد.
۵. خواندن ردیفها درون ساختارهای خودتان
پرسمان یک ردیف ها برمیگرداند. بعدی به ردیف بعد میرود و اگر ردیفی نماند نادرست برمیگرداند، پس تا ر.بعدی(): از همهی ردیفها میگذرد؛ درون حلقه متن، عدد صحیح، عدد صحیح۶۴ و عدد اعشار یک ستون را با شمارهاش، از ۰، میخوانند. حلقه را در تابعی بگذارید که یک وکتور از ساختار خودتان پر کند تا بقیهی برنامه هیچوقت ردیف SQL نبیند.
واردسازی دیتابیس
واردسازی دیتابیس.پستگرس
واردسازی رشته
ساختار کتاب:
همگانی شناسه: صحیح۶۴ = ۰
همگانی عنوان: رشته = ""
همگانی نویسنده: رشته = ""
همگانی سال: صحیح = ۰
همگانی سنت: صحیح = ۰
همگانی موجودی: صحیح = ۰
پایان
تابع پول(سنت: صحیح): رشته:
خرده := سنت % ۱۰۰
اگر خرده کوچکتر ۱۰:
برگشت رشته.از عدد(سنت / ۱۰۰) + ".0" + رشته.از عدد(خرده)
پایان
برگشت رشته.از عدد(سنت / ۱۰۰) + "." + رشته.از عدد(خرده)
پایان
تابع خواندن کتاب ها(پ: پستگرس.پایگاه داده، شرط: رشته): وکتور<کتاب>:
ناپایا خروجی := وکتور {} برگردان وکتور<کتاب>
ر := پستگرس.پرسمان(پ، "SELECT id, title, author, year, (price * 100)::int AS cents, stock FROM books " + شرط)
دیرکن ر.بستن()
تا ر.بعدی():
خروجی.بیفزا(کتاب { شناسه = ر.عدد صحیح۶۴(۰)، عنوان = ر.متن(۱)، نویسنده = ر.متن(۲)، سال = ر.عدد صحیح(۳)، سنت = ر.عدد صحیح(۴)، موجودی = ر.عدد صحیح(۵) })
پایان
برگشت خروجی
پایان
تابع ریشه:
پ := پستگرس.بازکردن("host=127.0.0.1 user=postgres password=secret dbname=bookshop")
دیرکن پستگرس.بستن(پ)
کتاب ها := خواندن کتاب ها(پ، "ORDER BY year")
سرچاپ کتاب ها.طول()، "کتاب"
هر ک در کتاب ها:
سرچاپ ک.شناسه، ک.عنوان، "از"، ک.نویسنده، ک.سال، پول(ک.سنت)، "موجودی"، ک.موجودی
پایان
ارزان ها := خواندن کتاب ها(پ، "WHERE price < 10 ORDER BY price")
سرچاپ "زیر ۱۰:"، ارزان ها.طول()
ر := پستگرس.پرسمان(پ، "SELECT title, price, stock, isbn FROM books WHERE id = 3")
دیرکن ر.بستن()
ر.بعدی()
تکرار ر.تعداد ستون() در ستون:
نوع داده := ر.نوع ستون(ستون)
ناپایا نام := "متن"
اگر نوع داده برابر دیتابیس.نوع صحیح: نام = "صحیح" پایان
اگر نوع داده برابر دیتابیس.نوع اعشاری: نام = "اعشاری" پایان
سرچاپ ر.نام ستون(ستون)، "="، ر.متن(ستون)، "از نوع"، نام
پایان
پایانقیمتها به شکل سنت درست ((price * 100)::int در SQL) خوانده میشوند نه با عدد اعشار، چون عدد اعشاری دودویی بیشتر مبلغهای دهدهی را دقیق نگه نمیدارد. متن مقدار دقیق numeric را همانطور که سرور نوشته میدهد، مثل 8.25، و این هم راه امن دیگری است. نام ستون و نوع ستون ستونها را توصیف میکنند: عددهای صحیح و منطقیها دیتابیس.نوع صحیح، real و double precision و numeric دیتابیس.نوع اعشاری، bytea دیتابیس.نوع دودویی و بقیه، از جمله تاریخ، آرایه و jsonb، دیتابیس.نوع متن هستند. کار با هر ردیف ها که تمام شد آن را ببندید؛ سادهترین راه دیرکن ر.بستن() درست پس از پرسمان است.
۶. مقدارهای کاربر، به شکل امن
این بسته SQL را به شکل متن میفرستد و جاینگهدار ندارد، پس هر مقداری که از کاربر میآید باید پیش از چسبیدن به دستور از نقل قول بگذرد. مقدار نقلقولشده هر چیزی میتواند داشته باشد، از نقلقول تا نقطهویرگول، و باز هم یک رشته میماند. عددها نقلقول نمیخواهند ولی باید واقعا عدد باشند: ورودی را به عدد صحیح تبدیل و وارسی کنید.
واردسازی دیتابیس.پستگرس
واردسازی تبدیل
واردسازی رشته
تابع الگوی شبیه(متن: رشته): رشته:
برگشت "%" + رشته.جایگزینی(رشته.جایگزینی(رشته.جایگزینی(متن، "\\"، "\\\\")، "%"، "\\%")، "_"، "\\_") + "%"
پایان
تابع جستجو(پ: پستگرس.پایگاه داده، واژه ها: رشته): صحیح:
دستور := "SELECT title FROM books WHERE title ILIKE " + پستگرس.نقل قول(پ، الگوی شبیه(واژه ها)) + " ORDER BY title"
ر := پستگرس.پرسمان(پ، دستور)
دیرکن ر.بستن()
سرچاپ "جستجوی"، پستگرس.نقل قول(پ، واژه ها)، "یافت:"، ر.تعداد ردیف()
تا ر.بعدی():
سرچاپ " " + ر.متن(۰)
پایان
برگشت ر.تعداد ردیف()
پایان
تابع ریشه:
پ := پستگرس.بازکردن("host=127.0.0.1 user=postgres password=secret dbname=bookshop")
دیرکن پستگرس.بستن(پ)
_ := جستجو(پ، "کو")
_ := جستجو(پ، "x' OR '1'='1")
_ := جستجو(پ، "'; DROP TABLE books; --")
_ := جستجو(پ، "100%")
سرچاپ "کتابها هنوز سر جایشاناند:"، پستگرس.پرسمان عدد(پ، "SELECT count(*) FROM books")
نوشته := "3 OR 1=1"
شناسه := تبدیل.تجزیه عدد(نوشته)
اگر تبدیل.قالب عدد(شناسه) نابرابر نوشته:
سرچاپ "شناسهی کتاب نیست:"، نوشته
پایان
سرچاپ پستگرس.نقل قول(پ، `C:\books\new`)
پایانهر دو حمله فقط دنبال عنوانهای عجیب گشتند و جدول سر جایش است. درون الگوی LIKE یا ILIKE نویسههای % و _ نویسهی عاماند، برای همین جستجو اول آنها را با بکاسلش گریز میدهد؛ وگرنه جستجوی 100% هر عنوانی را که با 100 شروع شود پیدا میکرد. اگر متن بکاسلش داشته باشد، نقل قول آن را به شکل E'...' پستگرس با یک فاصله در آغاز مینویسد که باز هم یک رشتهی واحد است.
ورودی خام را هرگز به نام جدول یا ستون نچسبانید. اگر کاربر ستون مرتبسازی را انتخاب میکند، انتخابش را با فهرست ثابتی از نامها در برنامه مقایسه کنید و نسخهی خودتان از آن نام را به کار ببرید.
۷. مقدار NULL
یک ستون میتواند اصلا مقدار نداشته باشد: همان NULL در SQL. متن برای آن رشتهی خالی و عدد صحیح صفر برمیگرداند که از یک رشتهی خالی یا صفر واقعی قابل تشخیص نیست، پس هر جا این تفاوت مهم است خالی است را صدا بزنید. برای نوشتن NULL، به جای مقدار نقلقولدار خود واژهی NULL را در SQL بگذارید؛ یک تابع کمکی کوچک کار را مرتب نگه میدارد.
واردسازی دیتابیس.پستگرس
تابع مقدار اس کیو ال(پ: پستگرس.پایگاه داده، متن: رشته): رشته:
اگر متن برابر "":
برگشت "NULL"
پایان
برگشت پستگرس.نقل قول(پ، متن)
پایان
تابع ریشه:
پ := پستگرس.بازکردن("host=127.0.0.1 user=postgres password=secret dbname=bookshop")
دیرکن پستگرس.بستن(پ)
_ := پستگرس.اجرا(پ، "UPDATE books SET isbn = " + مقدار اس کیو ال(پ، "978-9645595597") + " WHERE title = 'بوف کور'")
_ := پستگرس.اجرا(پ، "UPDATE books SET isbn = " + مقدار اس کیو ال(پ، "") + " WHERE title LIKE 'سووش%'")
ر := پستگرس.پرسمان(پ، "SELECT title, isbn FROM books ORDER BY id")
دیرکن ر.بستن()
تا ر.بعدی():
اگر ر.خالی است(۱):
سرچاپ ر.متن(۰)، "شابک ندارد، متن میدهد"، "[" + ر.متن(۱) + "]"
وگرنه:
سرچاپ ر.متن(۰)، ر.متن(۱)
پایان
پایان
سرچاپ "بی شابک:"، پستگرس.پرسمان عدد(پ، "SELECT count(*) FROM books WHERE isbn IS NULL")
سرچاپ "= NULL مییابد"، پستگرس.پرسمان عدد(پ، "SELECT count(*) FROM books WHERE isbn = NULL")
تازه ترین := پستگرس.پرسمان(پ، "SELECT max(year) FROM books WHERE year > 2100")
دیرکن تازه ترین.بستن()
تازه ترین.بعدی()
سرچاپ "بیشینه روی هیچ ردیف:"، تازه ترین.عدد صحیح(۰)، تازه ترین.خالی است(۰)
سرچاپ پستگرس.پرسمان متن(پ، "SELECT string_agg(coalesce(isbn, 'ندارد'), '، ' ORDER BY id) FROM books")
پایانبا IS NULL مقایسه کنید، نه با = NULL که هیچوقت درست نیست. تابعهای تجمعی مثل max و sum روی هیچ ردیفی NULL برمیگردانند نه صفر؛ coalesce(x, جایگزین) همانجا در SQL به جای NULL مقدار دیگری میگذارد.
۸. تراکنش
یک سفارش دو جدول را تغییر میدهد: موجودی کتاب کم میشود و ردیفی به orders افزوده میشود. یا هر دو باید انجام شوند یا هیچکدام. شروع تراکنش تراکنشی آغاز میکند و یک تراکنش برمیگرداند که اجرا و پرسمان آن درون تراکنش اجرا میشوند؛ ثبت تراکنش تغییرها را نگه میدارد و بازگردانی دورشان میریزد.
واردسازی دیتابیس.پستگرس
واردسازی رشته
تابع ثبت سفارش(پ: پستگرس.پایگاه داده، مشتری: رشته، کتاب: صحیح، تعداد: صحیح): منطقی:
ت := پ.شروع تراکنش()
اگر وارونه ت.معتبر():
برگشت نادرست
پایان
ر := ت.پرسمان("UPDATE books SET stock = stock - " + رشته.از عدد(تعداد) + " WHERE id = " + رشته.از عدد(کتاب) + " AND stock >= " + رشته.از عدد(تعداد) + " RETURNING price * " + رشته.از عدد(تعداد))
دیرکن ر.بستن()
اگر وارونه ر.بعدی():
ت.بازگردانی()
سرچاپ مشتری، تعداد، "نسخه از کتاب " + رشته.از عدد(کتاب) + " میخواهد: موجودی کافی نیست، بازگردانده شد"
برگشت نادرست
پایان
جمع := ر.متن(۰)
اگر ت.اجرا("INSERT INTO orders (customer, book_id, qty, total) VALUES (" + پستگرس.نقل قول(پ، مشتری) + ", " + رشته.از عدد(کتاب) + ", " + رشته.از عدد(تعداد) + ", " + جمع + ")") نابرابر ۰:
ت.بازگردانی()
برگشت نادرست
پایان
اگر ت.ثبت تراکنش() نابرابر ۰:
برگشت نادرست
پایان
سرچاپ مشتری، تعداد، "نسخه از کتاب"، کتاب، "خرید به مبلغ"، جمع
برگشت درست
پایان
تابع ریشه:
پ := پستگرس.بازکردن("host=127.0.0.1 user=postgres password=secret dbname=bookshop")
دیرکن پستگرس.بستن(پ)
_ := ثبت سفارش(پ، "سارا"، ۱، ۲)
_ := ثبت سفارش(پ، "امید"، ۵، ۱)
_ := ثبت سفارش(پ، "لیلا"، ۵، ۱)
_ := ثبت سفارش(پ، "سارا"، ۴، ۳)
سرچاپ "سفارشها:"، پستگرس.پرسمان عدد(پ، "SELECT count(*) FROM orders")، "فروش:"، پستگرس.پرسمان متن(پ، "SELECT sum(total) FROM orders")
سرچاپ "ماندهی بوف کور:"، پستگرس.پرسمان عدد(پ، "SELECT stock FROM books WHERE id = 1")، "ماندهی سمفونی مردگان:"، پستگرس.پرسمان عدد(پ، "SELECT stock FROM books WHERE id = 5")
پایاندستور UPDATE ... WHERE stock >= qty RETURNING ... وارسی موجودی و برداشتن آن را در یک دستور انجام میدهد، پس دو مشتری که همزمان آخرین نسخه را سفارش میدهند نمیتوانند هر دو آن را بگیرند: دومی منتظر پایان تراکنش اولی میماند و بعد میبیند موجودی صفر است.
همهی دستورهای درون تراکنش را وارسی کنید. پس از یک دستور ناموفق، PostgreSQL بقیهی تراکنش را نادیده میگیرد و ثبت تراکنش بعدی به جای ثبت، همهچیز را بازمیگرداند. در این حالت ثبت تراکنش مقدار ۱- برمیگرداند، پس ۰ از آن یعنی تغییرها واقعا ذخیره شدهاند.
۹. خطاها
همهی فراخوانیها شکست را یکجور گزارش میدهند. اجرا و اجرا با شمارش ۱- برمیگردانند و پرسمان یک ردیف ها میدهد که معتبر آن نادرست است و بعدی آن بیدرنگ نادرست برمیگرداند. آنگاه خطا پیام سرور را دارد، همراه خط DETAIL اگر باشد؛ این پیام با شروع دستور بعدی پاک میشود.
واردسازی دیتابیس.پستگرس
واردسازی رشته
تابع آزمودن(پ: پستگرس.پایگاه داده، دستور: رشته):
اگر پستگرس.اجرا(پ، دستور) نابرابر ۰:
چاپ پستگرس.خطا(پ)
پایان
پایان
تابع ریشه:
پ := پستگرس.بازکردن("host=127.0.0.1 user=postgres password=secret dbname=bookshop")
دیرکن پستگرس.بستن(پ)
آزمودن(پ، "INSERT INTO books (title, author, price) VALUES ('بوف کور', 'کسی دیگر', 5)")
آزمودن(پ، "UPDATE books SET stock = stock - 50 WHERE id = 1")
آزمودن(پ، "INSERT INTO orders (customer, book_id, qty, total) VALUES ('امید', 99, 1, 1)")
آزمودن(پ، "SELEC title FROM books")
ر := پستگرس.پرسمان(پ، "SELECT nope FROM books")
سرچاپ "پرسمان معتبر:"، ر.معتبر()، "ردیف:"، ر.تعداد ردیف()، "بعدی:"، ر.بعدی()
سرچاپ "اجرا با شمارش هنگام خطا:"، پستگرس.اجرا با شمارش(پ، "DELETE FROM nowhere")
چاپ پستگرس.خطا(پ)
ت := پ.شروع تراکنش()
_ := ت.اجرا("UPDATE books SET price = 0 WHERE id = 1")
_ := ت.اجرا("INSERT INTO books (title) VALUES ('بینام')")
چاپ پستگرس.خطا(پ)
_ := ت.اجرا("UPDATE books SET price = 1 WHERE id = 2")
چاپ پستگرس.خطا(پ)
ت.بازگردانی()
سرچاپ "قیمت بوف کور هنوز"، پستگرس.پرسمان متن(پ، "SELECT price FROM books WHERE id = 1")
قطع کننده := پستگرس.بازکردن("host=127.0.0.1 user=postgres password=secret dbname=bookshop")
دیرکن پستگرس.بستن(قطع کننده)
فرایند := پستگرس.پرسمان عدد(پ، "SELECT pg_backend_pid()")
_ := پستگرس.اجرا(قطع کننده، "SELECT pg_terminate_backend(" + رشته.از عدد(فرایند) + ")")
سرچاپ "پس از قطع شدن از سوی سرور، پینگ:"، پستگرس.پینگ(پ)
پستگرس.بازنشانی(پ)
سرچاپ "پس از بازنشانی، پینگ:"، پستگرس.پینگ(پ)، پستگرس.پرسمان عدد(پ، "SELECT count(*) FROM books")
پایانبخش دوم قاعدهی تراکنش گام ۸ را در عمل نشان میدهد: پس از درج ناموفق، دستور بعدی با پیام current transaction is aborted رد میشود تا بازگردانی صدا زده شود. بخش آخر یک اتصال قطعشده را نشان میدهد که اینجا سرور با pg_terminate_backend قطعش کرده، همان چیزی که با راهاندازی دوبارهی سرور هم پیش میآید. پینگ آن را میفهمد و بازنشانی با همان تنظیمها دوباره وصل میشود.
پرسمان باید ردیف برگرداند. یک UPDATE یا DELETE بدون RETURNING که با پرسمان اجرا شود کارش را میکند، ولی ردیف های برگشتی معتبر نیست؛ برای اینها اجرا یا اجرا با شمارش را به کار ببرید.
۱۰. استخر اتصال، و یک اتصال برای هر نخ
هر اتصال در هر لحظه یک دستور را پیش میبرد. سروری که به درخواستهای زیادی پاسخ میدهد چند اتصال را باز نگه میدارد و به هر درخواست یکی را قرض میدهد. استخر از بستهی دیتابیس این حسابوکتاب را نگه میدارد: افزودن اتصالها را در استخر میگذارد، گرفتن یکی را با یک شمارهی اجاره قرض میدهد، اتصال اجارهای اتصال آن اجاره را میدهد و رهاکردن آن را پس میدهد. پستگرس.اتصال یک پایگاه داده را به اتصال مشترکی تبدیل میکند که استخر نگه میدارد.
واردسازی دیتابیس
واردسازی دیتابیس.پستگرس
واردسازی حافظه
واردسازی نخ
پایا نشانیپایگاه := "host=127.0.0.1 user=postgres password=secret dbname=bookshop"
ساختار کار:
همگانی نویسنده: رشته = ""
همگانی فروش: صحیح = ۰
پایان
تابع شمارش فروش(ک: کار*):
پ := پستگرس.بازکردن(نشانیپایگاه)
دیرکن پستگرس.بستن(پ)
ک[۰].فروش = پستگرس.پرسمان عدد(پ، "SELECT coalesce(sum(o.qty), 0) FROM orders o JOIN books b ON b.id = o.book_id WHERE b.author = " + پستگرس.نقل قول(پ، ک[۰].نویسنده))
پایان
تابع ریشه:
ناپایا استخر := دیتابیس.استخر جدید(۳)
دیرکن دیتابیس.آزادکردن(استخر)
تکرار ۳:
_ := دیتابیس.افزودن(استخر، پستگرس.اتصال(پستگرس.بازکردن(نشانیپایگاه)))
پایان
سرچاپ "استخر:"، دیتابیس.اندازه(استخر)، "اتصال،"، دیتابیس.بیکار(استخر)، "بیکار"
الف := دیتابیس.گرفتن(استخر)
ب := دیتابیس.گرفتن(استخر)
سرچاپ "دو درخواست در جریان:"، دیتابیس.در استفاده(استخر)، "در استفاده"
سرچاپ "کتابها:"، دیتابیس.پرسمان عدد(دیتابیس.اتصال اجارهای(استخر، الف)، "SELECT count(*) FROM books")، "سفارشها:"، دیتابیس.پرسمان عدد(دیتابیس.اتصال اجارهای(استخر، ب)، "SELECT count(*) FROM orders")
دیتابیس.رهاکردن(استخر، الف)
دیتابیس.رهاکردن(استخر، ب)
ناپایا کارها := وکتور {} برگردان وکتور<کار*>
دیرکن کارها.آزادکن()
ناپایا گروه := وکتور {} برگردان وکتور<نخ.نخ>
دیرکن گروه.آزادکن()
هر نام در ["صادق هدایت"، "عباس معروفی"، "آنتوان دو سنتاگزوپری"، "سعدی"]:
ک := حافظه.تخصیص(اندازهگونه(کار)) برگردان کار*
ک[۰] = کار { نویسنده = نام }
کارها.بیفزا(ک)
گروه = نخ.جمع آوری(گروه، نخساز(شمارش فروش، ک))
پایان
نخ.پیوستن به همه(گروه)
هر ک در کارها:
سرچاپ ک[۰].نویسنده، "فروش"، ک[۰].فروش
حافظه.آزادسازی(ک برگردان تهی*)
پایان
پایانخود استخر قفل ندارد، پس گرفتن و رهاکردن را از یک نخ انجام دهید. برای کاری که میان نخها پخش شده، سادهترین قاعدهی امن همانی است که نیمهی دوم برنامه رعایت میکند: هر نخ اتصال خودش را باز میکند، به کار میبرد و میبندد. هرگز یک پایگاه داده را همزمان از دو نخ به کار نبرید.
۱۱. امکانات PostgreSQL
هر کاری که PostgreSQL میتواند، فقط یک رشتهی SQL فاصله دارد. این گام چند امکان را به کار میبرد که کد زیادی را از برنامه حذف میکنند: ON CONFLICT ... DO UPDATE ردیفی را میافزاید یا اگر از قبل باشد بهروزش میکند، عملگرهای jsonb درون سند JSON را میخوانند و میگردند، unnest ستون آرایهای را به ردیف تبدیل میکند، جستجوی متنی واژهها را پیدا میکند و یک تابع پنجرهای نویسندهها را بر پایهی فروش رتبه میدهد.
واردسازی دیتابیس.پستگرس
تابع نمایش(پ: پستگرس.پایگاه داده، سرتیتر: رشته، دستور: رشته):
ر := پستگرس.پرسمان(پ، دستور)
دیرکن ر.بستن()
سرچاپ سرتیتر
تا ر.بعدی():
ناپایا سطر := " "
تکرار ر.تعداد ستون() در ستون:
سطر = سطر + " " + ر.متن(ستون)
پایان
سرچاپ سطر
پایان
پایان
تابع ریشه:
پ := پستگرس.بازکردن("host=127.0.0.1 user=postgres password=secret dbname=bookshop")
دیرکن پستگرس.بستن(پ)
_ := پستگرس.اجرا(پ، `INSERT INTO books (title, author, year, price, stock) VALUES
('بوف کور', 'صادق هدایت', 1315, 12.50, 5),
('شاهنامه', 'فردوسی', 384, 8.75, 4)
ON CONFLICT (title) DO UPDATE SET stock = books.stock + EXCLUDED.stock`)
نمایش(پ، "انبار، افزودن یا اضافه کردن:"، "SELECT title, stock FROM books WHERE title IN ('بوف کور', 'شاهنامه') ORDER BY title")
_ := پستگرس.اجرا(پ، `UPDATE books SET info = '{"pages": 128, "publisher": "امیرکبیر", "translations": ["فرانسوی", "انگلیسی"]}' WHERE title = 'بوف کور';
UPDATE books SET info = '{"pages": 1200, "publisher": "قطره"}', tags = '{شعر,کلاسیک}' WHERE title = 'شاهنامه'`)
نمایش(پ، "فیلدهای jsonb:"، "SELECT title, info->>'publisher', (info->>'pages')::int FROM books WHERE info ? 'publisher' ORDER BY title")
نمایش(پ، "ترجمه به فرانسوی:"، `SELECT title FROM books WHERE info->'translations' @> '["فرانسوی"]'`)
نمایش(پ، "آرایهها:"، "SELECT tag, count(*) FROM books, unnest(tags) AS tag GROUP BY tag ORDER BY count(*) DESC, tag")
نمایش(پ، "جستجوی متنی:"، "SELECT title FROM books WHERE to_tsvector('simple', title) @@ plainto_tsquery('simple', 'مردگان')")
نمایش(پ، "پرفروشها:"، `SELECT b.author, sum(o.total), rank() OVER (ORDER BY sum(o.total) DESC)
FROM orders o JOIN books b ON b.id = o.book_id GROUP BY b.author`)
پایانپیکربندی simple جستجوی متنی واژهها را همانطور که نوشته شدهاند مقایسه میکند و برای متن فارسی مناسب است؛ پیکربندی english ریشهی واژههای انگلیسی را هم میشناسد. هر مقدار به شکل متن و در قالب خود PostgreSQL میرسد: آرایه به شکل {رمان,کلاسیک}، jsonb به شکل متن JSON و منطقی به شکل t یا f (که عدد صحیح آنها را ۱ و ۰ میخواند). وقتی نتیجه ساختار دارد، بگذارید SQL آن را به JSON بسازد و در سلام بازش کنید، همانطور که راهنمای JSON پایین نشان میدهد.
بیشتر
- ورود انبوه:
COPY FROM STDINپشتیبانی نمیشود. ردیفهای زیاد را با یکINSERTچندردیفی برای هر چند صد ردیف و درون یک تراکنش بیفزایید. پرسمان عددوپرسمان متننخستین ستون نخستین ردیف را با یک فراخوانی میخوانند، برای شمارش، جمع و تنظیمها.- کدی که روی
دیتابیس.اتصالنوشته شود بدون تغییر روی اس کیو لایت و مای اس کیو ال هم اجرا میشود؛دیتابیس.پرسمان عدد،دیتابیس.اجرای همهودیتابیس.در تراکنشروی همهی آنها کار میکنند. نسخه سرورنسخهی اصلی ضرب در ۱۰۰۰۰ بهعلاوهی نسخهی فرعی را برمیگرداند، پس 170011 یعنی 17.11؛ برای امکانات سرورهای تازهتر آن را با یک عدد مقایسه کنید.- نتیجهها کامل در حافظه نگه داشته میشوند. جدول خیلی بزرگ را صفحهبهصفحه با
ORDER BY id LIMIT 1000وWHERE id > آخرینبخوانید.
راهنما: مهاجرت طرحواره
طرحوارهی یک برنامهی واقعی با گذشت زمان تغییر میکند و همهی نسخههای پایگاه داده باید همراهش بروند. مهاجرت گر از بستهی دیتابیس گامهای شمارهدار نگه میدارد که هر کدام SQL اعمال و SQL برگرداندن دارند، و گامهای اعمالشده را در جدول schema_migrations ثبت میکند. هر گام در تراکنش خودش اجرا میشود و در PostgreSQL این شامل CREATE TABLE و CREATE INDEX هم میشود، پس گام ناموفق هیچ تغییر نیمهکارهای به جا نمیگذارد.
واردسازی دیتابیس
واردسازی دیتابیس.پستگرس
تابع ریشه:
پ := پستگرس.بازکردن("host=127.0.0.1 user=postgres password=secret dbname=bookshop")
دیرکن پستگرس.بستن(پ)
ا := پستگرس.اتصال(پ)
ناپایا م := دیتابیس.مهاجرت گر جدید()
دیرکن دیتابیس.آزادکردن مهاجرت گر(م)
دیتابیس.افزودن مهاجرت(م، ۱، "نقدها"، `CREATE TABLE reviews (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
book_id bigint NOT NULL REFERENCES books (id),
stars int NOT NULL CHECK (stars BETWEEN 1 AND 5),
body text)`، "DROP TABLE reviews")
دیتابیس.افزودن مهاجرت(م، ۲، "نمایهی مشتری سفارشها"، "CREATE INDEX orders_customer ON orders (customer)"، "DROP INDEX orders_customer")
سرچاپ "نسخهی طرحواره"، دیتابیس.نسخه طرحواره(م، ا)، "در انتظار"، دیتابیس.تعداد در انتظار(م، ا)
سرچاپ "اعمال شد:"، دیتابیس.مهاجرت به بالا(م، ا)
سرچاپ "نسخهی طرحواره"، دیتابیس.نسخه طرحواره(م، ا)، "در انتظار"، دیتابیس.تعداد در انتظار(م، ا)
سرچاپ "اعمال شد:"، دیتابیس.مهاجرت به بالا(م، ا)، "در اجرای دوم"
سرچاپ "بازگردانی:"، دیتابیس.بازگردانی(م، ا)، "اکنون در"، دیتابیس.نسخه طرحواره(م، ا)
سرچاپ "نمایه هست:"، پستگرس.پرسمان عدد(پ، "SELECT count(*) FROM pg_indexes WHERE indexname = 'orders_customer'")
سرچاپ "مهاجرت تا ۲:"، دیتابیس.مهاجرت به(م، ا، ۲)
سرچاپ پستگرس.پرسمان متن(پ، "SELECT string_agg(version || ' ' || name, '، ' ORDER BY version) FROM schema_migrations")
پایانمهاجرت به بالا را هنگام شروع برنامه اجرا کنید: فقط گامهایی را اعمال میکند که پایگاه داده هنوز ندیده، پس اجرای دوبارهاش بیخطر است. بازگردانی تازهترین گام را برمیگرداند و مهاجرت به به نسخهی دلخواه میرود.
راهنما: تنظیمها از متغیرهای محیطی
جای گذرواژه در کد نیست. بازکردن مثل libpq از متغیرهای محیطی PGHOST، PGPORT، PGUSER، PGPASSWORD، PGDATABASE، PGSSLMODE و PGSSLROOTCERT شروع میکند و بعد هر چه رشتهی اتصال تعیین کند روی آنها میگذارد. پس بازکردن("") فقط با محیط وصل میشود و برنامهی زیر هم با یک DATABASE_URL تنها کار میکند و هم با متغیرهای PG....
واردسازی دیتابیس.پستگرس
واردسازی سیستم عامل
تابع ریشه:
پ := پستگرس.بازکردن(سیستم عامل.متغیر محیطی("DATABASE_URL"))
دیرکن پستگرس.بستن(پ)
اگر وارونه پستگرس.معتبر(پ):
چاپ "پایگاه داده: " + پستگرس.خطا(پ)
برگشت ۱
پایان
سرچاپ "پایگاه دادهی"، پستگرس.نام پایگاه داده(پ)، "روی"، پستگرس.نام میزبان(پ)، "با کاربر"، پستگرس.نام کاربر(پ)
سرچاپ پستگرس.پرسمان عدد(پ، "SELECT count(*) FROM books")، "کتاب"
پایانخروجی بالا از اجرای برنامه با متغیرهای PG... به دست آمد:
PGHOST=127.0.0.1 PGUSER=postgres PGPASSWORD=secret PGDATABASE=bookshop salam run app.salam
DATABASE_URL=postgresql://postgres:[email protected]:5432/bookshop salam run app.salam
اگر هیچجا کاربری تعیین نشود، متغیر محیطی USER به کار میرود، و اگر پایگاه دادهای تعیین نشود، پایگاه دادهای همنام کاربر.
راهنما: نتیجهی تودرتو به شکل JSON
فهرست کتابها، هر کدام با سفارشهایش، یا برای هر کتاب یک پرسمان میخواهد یا یک پیوند (join) که ردیفهایش را باید با دست دوباره گروه کنید. PostgreSQL میتواند کل سند تودرتو را با json_agg و json_build_object در یک پرسمان بسازد و جیسون آن را مستقیم درون ساختارهای سلامی میخواند که نام فیلدهایشان با کلیدهای JSON یکی است. نام فیلدهای فارسی هم کار میکنند، به شرط آنکه نیمفاصله نداشته باشند.
واردسازی دیتابیس.پستگرس
واردسازی کدگذاری.جیسون
واردسازی کدگذاری.خطای کدگذاری
ساختار سفارش:
همگانی مشتری: رشته = ""
همگانی تعداد: صحیح = ۰
پایان
ساختار کتاب:
همگانی عنوان: رشته = ""
همگانی قیمت: اعشار۶۴ = ۰.۰
همگانی خریدها: وکتور<سفارش> = وکتور {}
پایان
ساختار قفسه:
همگانی فهرست: وکتور<کتاب> = وکتور {}
پایان
تابع ریشه:
پ := پستگرس.بازکردن("host=127.0.0.1 user=postgres password=secret dbname=bookshop")
دیرکن پستگرس.بستن(پ)
متن := پستگرس.پرسمان متن(پ، `SELECT json_build_object('فهرست', coalesce(json_agg(b ORDER BY b."عنوان"), '[]'))
FROM (SELECT bk.title AS "عنوان", bk.price AS "قیمت",
coalesce((SELECT json_agg(json_build_object('مشتری', o.customer, 'تعداد', o.qty) ORDER BY o.id)
FROM orders o WHERE o.book_id = bk.id), '[]') AS "خریدها"
FROM books bk WHERE bk.id IN (SELECT book_id FROM orders)) b`)
ناپایا قفسه کتاب := قفسه {}
ناپایا اشکال := خطای کدگذاری.بدون خطا()
اگر وارونه جیسون.واسریال سازی آسان گیر(متن، قفسه کتاب، اشکال):
سرچاپ "جیسون نادرست:"، اشکال.پیام
برگشت ۱
پایان
هر ک در قفسه کتاب.فهرست:
سرچاپ ک.عنوان، ک.قیمت، "سفارش:"، ک.خریدها.طول()
هر س در ک.خریدها:
سرچاپ " " + س.مشتری، "×"، س.تعداد
پایان
پایان
پایانcoalesce(..., '[]') «بدون سفارش» را به فهرست خالی تبدیل میکند نه NULL. همین الگو در جهت عکس هم کار میکند: یک سند JSON را به شکل یک رشتهی نقلقولشده بفرستید و روی سرور با jsonb_to_recordset بازش کنید.
راهنما: کدام تابع برای کدام کار
| میخواهید | به کار ببرید |
|---|---|
| وصل شوید | بازکردن با جفتهای key=value یا نشانی postgresql://، سپس معتبر |
| DDL یا نوشتنی را اجرا کنید که شمارش آن را لازم ندارید | اجرا (۰ یعنی موفق) |
| بدانید یک نوشتن چند ردیف را تغییر داد | اجرا با شمارش |
| شناسههای ساختهشده یا ردیفهای تغییرکرده را پس بگیرید | پرسمان با INSERT/UPDATE/DELETE ... RETURNING |
| ردیفهای زیادی بخوانید | پرسمان، سپس تا ر.بعدی(): و ر.بستن() |
| یک عدد یا یک رشته بخوانید | پرسمان عدد، پرسمان متن |
| متن کاربر را در SQL بگذارید | همیشه نقل قول |
| NULL را از خالی تشخیص دهید | ر.خالی است(ستون) |
| چند تغییر را با هم یا هیچکدام انجام دهید | پ.شروع تراکنش()، سپس ثبت تراکنش یا بازگردانی |
| پس از قطع اتصال از سوی سرور ادامه دهید | پینگ، سپس بازنشانی |
| کدی بنویسید که روی چند موتور کار کند | اتصال و تابعهای کمکی دیتابیس |
گونهها
پایگاه داده Database
ساختار پایگاه داده| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| دسته | handle | تهی* | دستگیرهی اتصال؛ اگر اتصالی نباشد تهی است. |
| تاثیرپذیرفته | affected | صحیح۶۴ = 0 | شمار ردیفهای تغییرکرده در آخرین دستور. |
واردسازی دیتابیس
واردسازی دیتابیس.پستگرس
تابع ریشه:
اگر وارونه پستگرس.در دسترس():
سرچاپ "کلاینت پستگرس در دسترس نیست"
برگشت
پایان
سرچاپ پستگرس.نسخه کلاینت()
پ := پستگرس.بازکردن("host=127.0.0.1 port=5432 dbname=shop user=app password=s3cret")
اگر وارونه پستگرس.معتبر(پ):
سرچاپ پستگرس.خطا(پ)
برگشت
پایان
سرچاپ پستگرس.نسخه سرور(پ)، پستگرس.نام پایگاه داده(پ)، پستگرس.نام کاربر(پ)، پستگرس.نام میزبان(پ)، پستگرس.درگاه(پ)
سرچاپ پستگرس.پینگ(پ)
_ := پستگرس.اجرا(پ، "CREATE TABLE IF NOT EXISTS items (id SERIAL PRIMARY KEY, name TEXT, price NUMERIC)")
_ := پستگرس.اجرا(پ، "INSERT INTO items (name, price) VALUES (" + پستگرس.نقل قول(پ، "چای") + ", 12.5)")
سرچاپ پستگرس.اجرا با شمارش(پ، "UPDATE items SET price = price * 1.1")
ر := پستگرس.پرسمان(پ، "SELECT id, name, price FROM items ORDER BY id")
سرچاپ ر.معتبر()، ر.تعداد ستون()، ر.تعداد ردیف()، ر.نام ستون(۱)
تا ر.بعدی():
سرچاپ ر.عدد صحیح(۰)، ر.متن(۱)، ر.عدد اعشار(۲)، ر.عدد صحیح۶۴(۰)، ر.خالی است(۲)، ر.نوع ستون(۱)
پایان
_ := ر.بستن()
سرچاپ پستگرس.پرسمان عدد(پ، "SELECT COUNT(*) FROM items")، پستگرس.پرسمان متن(پ، "SELECT version()")
ا := پستگرس.اتصال(پ)
ت := ا.شروع تراکنش()
_ := ت.اجرا("DELETE FROM items")
_ := ت.بازگردانی()
سرچاپ دیتابیس.پرسمان عدد(ا، "SELECT COUNT(*) FROM items")، پ.نوع()
پستگرس.بازنشانی(پ)
_ := پستگرس.بستن(پ)
_ := پستگرس.بازکردن کامل("db.example.com"، ۵۴۳۲، "app"، "s3cret"، "shop")
پایاننوع Kind
تابع نوع(): رشتهنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
معتبر Ok
تابع معتبر(): منطقینمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
پینگ Ping
تابع پینگ(): منطقینمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
اجرا Exec
تابع اجرا(sql: رشته): صحیحتعداد تغییرات نگه میدارد.نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
پرسمان Query
تابع پرسمان(sql: رشته): dyn db.ردیف هامعتبر نتیجه نادرست است.نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
شروع تراکنش Begin
تابع شروع تراکنش(): dyn db.TxBEGIN تراکنشی آغاز میکند؛ اگر این کار شکست بخورد، تراکنش معتبر نیست.نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
شناسه آخرین درج LastInsertId
تابع شناسه آخرین درج(): صحیح۶۴SELECT lastval())؛ اگر نباشد ۰.نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
تعداد تغییرات Changes
تابع تعداد تغییرات(): صحیح۶۴اجرای صدازده روی همین مقدار تغییر داد.نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
خطا Error
تابع خطا(): رشتهنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
نقل قول Quote
تابع نقل قول(s: رشته): رشتهE'...'.نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
بستن Close
تابع بستن(): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
ردیف ها Rows
ساختار ردیف ها| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| دسته | handle | تهی* | دستگیرهی نتیجه؛ اگر پرسمان شکست خورده باشد تهی است. |
| ردیف | row | صحیح = -1 | شمارهی ردیف جاری؛ پیش از نخستین بعدی برابر ۱-. |
| تعداد | count | صحیح = 0 | شمار ردیفها. |
نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
معتبر Ok
تابع معتبر(): منطقینمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
بعدی Next
تابع بعدی(): منطقینمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
تعداد ستون ColumnCount
تابع تعداد ستون(): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
تعداد ردیف RowCount
تابع تعداد ردیف(): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
نام ستون ColumnName
تابع نام ستون(col: صحیح): رشتهنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
نوع ستون ColumnType
تابع نوع ستون(col: صحیح): صحیحنوع ... در دیتابیس: عدد صحیح و منطقی نوع صحیح، real و double precision و numeric نوع اعشاری، bytea نوع دودویی، NULL نوع خالی و بقیه نوع متن.نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
خالی است IsNull
تابع خالی است(col: صحیح): منطقینمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
متن Text
تابع متن(col: صحیح): رشتهنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
عدد صحیح Int
تابع عدد صحیح(col: صحیح): صحیحt و f به شکل ۱ و ۰ و NULL به شکل ۰ خوانده میشوند.نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
عدد صحیح۶۴ Int64
تابع عدد صحیح۶۴(col: صحیح): صحیح۶۴t و f به شکل ۱ و ۰ و NULL به شکل ۰ خوانده میشوند.نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
عدد اعشار Float
تابع عدد اعشار(col: صحیح): اعشار۶۴نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
بستن Close
تابع بستن(): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
تراکنش Txn
ساختار تراکنش| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| دسته | handle | تهی* | اشارهگر اتصال. |
نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
معتبر Ok
تابع معتبر(): منطقیBEGIN موفق بود.نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
اجرا Exec
تابع اجرا(sql: رشته): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
پرسمان Query
تابع پرسمان(sql: رشته): dyn db.ردیف هانمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
ثبت تراکنش Commit
تابع ثبت تراکنش(): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
بازگردانی Rollback
تابع بازگردانی(): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
تابعها
در دسترس Available
تابع در دسترس(): منطقینمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
نسخه کلاینت ClientVersion
تابع نسخه کلاینت(): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
نسخه سرور ServerVersion
تابع نسخه سرور(d: پایگاه داده): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
بازکردن Open
تابع بازکردن(conninfo: رشته): پایگاه دادهhost=... port=... user=... password=... dbname=...، یا نشانی postgresql:// وصل میشود. مقدارهای تعییننشده از PGHOST، PGPORT، PGUSER، PGPASSWORD، PGDATABASE و PGSSLMODE میآیند. همیشه یک پایگاه داده برمیگرداند؛ معتبر را بپرسید.نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
بازکردن کامل OpenFull
تابع بازکردن کامل(host: رشته، port: صحیح، user: رشته، pass: رشته، dbname: رشته): پایگاه دادهبازکردن را به کار ببرید.نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
معتبر Ok
تابع معتبر(d: پایگاه داده): منطقینمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
پینگ Ping
تابع پینگ(d: پایگاه داده): منطقینمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
بازنشانی Reset
تابع بازنشانی(d: پایگاه داده)نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
بستن Close
تابع بستن(d: پایگاه داده): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
خطا Error
تابع خطا(d: پایگاه داده): رشتهنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
اجرا Exec
تابع اجرا(d: پایگاه داده، sql: رشته): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
اجرا با شمارش ExecCount
تابع اجرا با شمارش(d: پایگاه داده، sql: رشته): صحیح۶۴نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
پرسمان Query
تابع پرسمان(d: پایگاه داده، sql: رشته): ردیف هامعتبر نتیجه نادرست است.نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
نقل قول Quote
تابع نقل قول(d: پایگاه داده، s: رشته): رشتهنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
نام پایگاه داده DatabaseName
تابع نام پایگاه داده(d: پایگاه داده): رشتهنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
نام کاربر UserName
تابع نام کاربر(d: پایگاه داده): رشتهنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
نام میزبان HostName
تابع نام میزبان(d: پایگاه داده): رشتهنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
درگاه Port
تابع درگاه(d: پایگاه داده): رشتهنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
پرسمان عدد QueryInt
تابع پرسمان عدد(d: پایگاه داده، sql: رشته): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
پرسمان متن QueryText
تابع پرسمان متن(d: پایگاه داده، sql: رشته): رشتهنمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam
اتصال Conn
تابع اتصال(d: پایگاه داده): dyn db.Connectionاتصال مشترک برمیگرداند.نمونهی این مورد همراه با موارد بالاتر آمده است: db-postgres-Client.salam