RPC (Postgres funksiyalar)
Postgres funksiyalarini chaqirish orqali custom biznes logikasini bajarish. RLS va autentifikatsiya bilan ishlaydi, skalyar yoki SETOF qaytaruvchi funksiyalarni qo'llaydi.
RPC asoslari
RPC (Remote Procedure Call) — bu Postgres funksiyalarini HTTP orqali chaqirish imkoniyati. storagedb SQL Editor'da yaratgan funksiyani POST /v1/<REF>/rest/v1/rpc/<fn_name> orqali chaqirish mumkin.
HTTP so'rov bajarilganda:
1. SET LOCAL ROLE <anon|authenticated|service_role> — foydalanuvchining roli o'rnatiladi (RLS qoidalari ushbu rol ostida ishlaydi).
2. set_config('request.jwt.claims', <jwt>, true) — JWT claim'lari session'ga o'rnatiladi, shuning uchun auth.uid() va boshqa auth funksiyalari ishlaydi.
3. Postgres funksiyasi bajariladi. Skalyar qaytaruvchi (bitta qiymat) to'g'ridan-to'g'ri qaytariladi; SETOF yoki table qaytaruvchi funksiya massiv qaytaradi.
Funksiyani avval SQL Editor'da CREATE FUNCTION yoki meta/query bilan yaratish kerak.
Postgres funksiyasi yaratish
storagedb'dagi SQL Editor orqali funksiya yarating. Quyida o'z schema'sida simple qoshish funksiyasi:
Bu funksiya public schema'sida bo'ladi va uning parametrlar nomasi o'zgaruvchining nomi bilan mos kelib turadi (RPC POST body'dagi key'lar).
CREATE FUNCTION public.qoshish(a int, b int) RETURNS int AS $$ BEGIN RETURN a + b; END; $$ LANGUAGE plpgsql; -- Yoki immutable (pure function): CREATE FUNCTION public.ko_payti(x int, y int) RETURNS int IMMUTABLE AS $$ SELECT x * y; $$ LANGUAGE sql;
RPC: curl orqali chaqirish
POST so'rovni /rest/v1/rpc/<fn_name> ga yuboring. JSON body'dagi kalitlar funksiyaning parameter nomlari bo'lishi kerak.
Header'ga apikey: <ANON_KEY> yoki apikey: <SERVICE_KEY> qo'shing.
Skalyar funksiyalar (1 qiymat qaytaruvchi) qiymatni to'g'ridan-to'g'ri qaytaradi. SETOF funksiyalar massiv qaytaradi.
curl -X POST \
https://storage.identify.uz/v1/<REF>/rest/v1/rpc/qoshish \
-H "apikey: <ANON_KEY>" \
-H "content-type: application/json" \
-d '{"a": 5, "b": 7}'
# Natija (skalyar):
# 12curl -X POST \
https://storage.identify.uz/v1/<REF>/rest/v1/rpc/ko_payti \
-H "apikey: <SERVICE_KEY>" \
-H "content-type: application/json" \
-d '{"x": 3, "y": 4}'
# Natija:
# 12RPC: Client SDK bilan chaqirish
storagedb Client SDK'sida db.rpc(fnName, args) metodini ishlating. U Promise qaytaradi { data, error } strukturi bilan.
TypeScript'da generik T bilan qaytaruvchi tip belgilang.
import { createClient } from '@storagedb/client';
const db = createClient(
'https://storage.identify.uz/v1/<REF>',
'<ANON_KEY>'
);
// Skalyar qaytar (number)
const { data, error } = await db.rpc<number>('qoshish', { a: 5, b: 7 });
if (error) {
console.error('RPC xatosi:', error.message);
} else {
console.log('Natija:', data); // 12
}// Postgres funksiya JSON parametrni qabul qiladi:
// CREATE FUNCTION public.save_metadata(user_id text, meta jsonb) RETURNS text ...
const { data, error } = await db.rpc<string>('save_metadata', {
user_id: 'abc123',
meta: { color: 'blue', size: 'large' } // JSON
});
if (!error) console.log('Saqlandi:', data);RLC va autentifikatsiya
RPC chaqiruvi RLS (Row-Level Security) qoidalariga bo'ysinadi. Rol o'rnatiladi (anon_key uchun anon, service_key uchun service_role), JWT claim'lari session'ga o'rnatiladi.
service_key RLS ni chetlab o'tadi; barcha jadval va ustunlarga kirish mumkin.
anon_key foydalanuvchi identity'si bilan ishlaydi — JWT claim'lardagi auth.uid() mavjud bo'ladi va RLS qoidalari nazorat qiladi.
Funksiya ichida auth.uid() funksiyasini ishlating: SELECT auth.uid() — hozirgi foydalanuvchining UUID'sini qaytaradi.
-- Shaxsiy ma'lumotlar jadvali (RLS bilan himoyalangan) CREATE TABLE public.user_profile ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid REFERENCES auth.users(id), name text, bio text, UNIQUE(user_id) ); ALTER TABLE public.user_profile ENABLE ROW LEVEL SECURITY; CREATE POLICY "Foydalanuvchilar o'z profilini o'qishi" ON public.user_profile FOR SELECT USING (user_id = auth.uid()); -- RPC funksiyasi: foydalanuvchi o'z profilini yangilashi CREATE FUNCTION public.update_my_profile(new_name text, new_bio text) RETURNS jsonb AS $$ DECLARE updated_row jsonb; BEGIN UPDATE public.user_profile SET name = new_name, bio = new_bio WHERE user_id = auth.uid() RETURNING row_to_json(user_profile.*) INTO updated_row; RETURN updated_row; END; $$ LANGUAGE plpgsql SECURITY DEFINER;
// anon_key ishlatib (autentifikatsiyalangan foydalanuvchi)
const { data, error } = await db.rpc<any>('update_my_profile', {
new_name: 'Shohjahon',
new_bio: 'O'zbek dasturchisi'
});
if (error) {
// RLS ni polatka qilgan bo'lsa (masalan, bu profil o'zimning emas)
console.error('Kirishga taqiq:', error.message);
} else {
console.log('Profil yangilandi:', data);
}SETOF va massiv qaytarish
Agar funksiya SETOF <type> yoki TABLE(...) qaytarsa, RPC natija massiv bo'ladi.
SETOF scalar tiplar (masalan SETOF text) massivga aylanadi.
SETOF composite tiplar (masalan SETOF user_profile) nesnalar massiviga aylanadi.
-- Barcha blog postlarini tag bo'yicha filtrlash CREATE FUNCTION public.posts_by_tag(tag_name text) RETURNS TABLE(id uuid, title text, body text) AS $$ BEGIN RETURN QUERY SELECT p.id, p.title, p.body FROM public.blog_posts p JOIN public.post_tags pt ON p.id = pt.post_id WHERE pt.tag = tag_name; END; $$ LANGUAGE plpgsql;
interface BlogPost {
id: string;
title: string;
body: string;
}
const { data, error } = await db.rpc<BlogPost[]>('posts_by_tag', {
tag_name: 'o\'zbek'
});
if (!error && Array.isArray(data)) {
data.forEach(post => {
console.log(post.title); // "O'zbekcha IT faqtlari", ...
});
}