SQL Connect — SQL a Firebase-ben
- sql-connectBevezető
01 — Bevezetés
Mi az SQL Connect?
Honnan jött?
Az alapfilozófia: query-defined infrastructure
- A séma alapján elkészíti a PostgreSQL táblákat (DDL automatikusan).
- Ad egy biztonságos GraphQL végpontot, ami csak az általad előre definiált queryket és mutationöket fogadja.
- Generál egy típusbiztos kliens SDK-t — webre, iOS-re, Androidra, Flutterre —, amiben minden lekérdezés egy tipizált függvény.
- Kezeli a séma-migrációkat — ha módosítod a típusokat, az SQL Connect tudja, mit kell a PostgreSQL-en is megváltoztatni.
- postgresqlBevezető
- cloud-sqlBevezető
02 — PostgreSQL
A háttérben: Cloud SQL PostgreSQL
Mit kapsz a Postgres-ből?
- Erős konzisztencia — ACID tranzakciók, foreign key megszorítások, unique indexek. Pénzügyi adatra vagy üzleti adatra alkalmasabb, mint a Firestore.
- Bonyolult lekérdezések — joinok, subqueryk, window functionök, CTE-k, aggregációk. Mind, ami SQL-ben szokásos.
- PostgreSQL-kiterjesztések — PostGIS földrajzi adatokhoz, pgvector embedding kereséshez, full-text keresés (tsvector/tsquery), és bármi, amit a Cloud SQL támogat.
- Adatmodell-portolhatóság — ha valaha el akarsz költözni a Firebase-ből, a Postgres adatbázis exportálható és bárhova áttehető. Ez sokkal könnyebb, mint egy Firestore-export.
Két séma-üzemmód
Strict mode vs. compatible mode
Az SQL Connect séma vezeti a PostgreSQL sémát. Te csak a GraphQL típusokat módosítod, a Postgres séma magától követi. Új projektekhez ideális — egy hely, egy igazság.
A PostgreSQL séma az igazság forrása, az SQL Connect csak egy részét teszi elérhetővé. Akkor jó, ha már van meglévő Cloud SQL adatbázisod, amit a klienseknek elérhetővé teszel.
- sql-connectKözéphaladó
- graphqlKözéphaladó
03 — A séma
A séma — relációs gondolkodás újra
@table direktívát teszel. A típusok lesznek a táblák, a mezők lesznek az oszlopok, és a más típusra mutató mezők lesznek a foreign key-ek. Mintha egy SQL DDL-t írnál — csak sokkal olvashatóbban.Egy egyszerű séma
type User @table {
id: UUID! @default(expr: "uuidV4()")
uid: String! @col(name: "firebase_uid") @unique
displayName: String!
email: String! @unique
createdAt: Timestamp! @default(expr: "request.time")
}
type Post @table {
id: UUID! @default(expr: "uuidV4()")
title: String!
content: String!
author: User! # foreign key to User
publishedAt: Timestamp
tags: [String!]! # text[] PostgreSQL array
}
type Comment @table {
id: UUID! @default(expr: "uuidV4()")
text: String!
post: Post! # M-1 relation
author: User!
createdAt: Timestamp! @default(expr: "request.time")
}
users, posts és comments táblát Postgres-ben, foreign key megszorításokkal. A @default direktíva azt mondja, hogy a createdAt magától a kérés idejét veszi fel, az id pedig egy UUID lesz. A @col egy másik oszlopnévre térképez (ha SQL oldali konvenciót akarsz tartani: snake_case).Many-to-many kapcsolatok
type Tag @table {
id: UUID! @default(expr: "uuidV4()")
name: String! @unique
}
# Junction table with composite key
type PostTag @table(key: ["post", "tag"]) {
post: Post!
tag: Tag!
addedAt: Timestamp! @default(expr: "request.time")
}
posts_via_PostTag mezőt a Tag típusra, és egy tags_via_PostTag-et a Post típusra. A klienskódban így ezek explicit join nélkül elérhetők.- sql-connectKözéphaladó
04 — Queries és mutations
Előre definiált queryk és mutationök
Egy egyszerű query
query GetRecentPosts($limit: Int! = 20) @auth(level: PUBLIC) {
posts(
orderBy: [{ publishedAt: DESC }],
where: { publishedAt: { ne: null } },
limit: $limit
) {
id
title
publishedAt
author { # automatic join
displayName
}
comments_count # auto-generated aggregate
}
}
where egy SQL-szerű szűrés, ami GraphQL-ben kifejezve. A 10-12. sor egy implicit join — kéred a szerző nevét, és az SQL Connect mögötte lefuttat egy JOIN users-t. A 13. sor egy aggregátum: az SQL Connect minden kapcsolatra automatikusan generál egy _count mezőt, és számoszlopokra _sum, _avg, _min, _max mezőket is. SQL-ben ez egy JOIN ... GROUP BY lenne, itt egy szó.Mutationök
mutation CreatePost(
$title: String!,
$content: String!,
$tags: [String!]!
) @auth(level: USER) {
post_insert(data: {
title: $title,
content: $content,
tags: $tags,
author: { uid_expr: "auth.uid" } # from the JWT
})
}
auth.uid-ra hivatkozhatsz közvetlenül. A szerző ID-jét nem a kliens küldi (mert hamisítható lenne), hanem az SQL Connect szerver olvassa ki a JWT-ből. Ez egészen más, mint egy klasszikus REST API-ban, ahol az ilyen ellenőrzést neked kell elvégezned a backend kódban.Aggregate fields — beépített statisztikák
| Mező típusa | Generált aggregátumok |
|---|---|
| Bármi | <field>_count — non-null sorok száma |
| Számok (Int, Float, Int64) | _min, _max, _sum, _avg |
| Kapcsolat (1-N) | <rel>_count, <rel>_aggregate { ... } |
count(), sum() hívásként érhetők el, és külön költségen. Az SQL Connect-ben egy lekérdezésen belül tetszőlegesen variálhatod őket, plusz költség nélkül.- sql-connectHaladó
05 — Native SQL
Native SQL — ha tényleg kell
query TopAuthorsByPostCount($limit: Int!) @auth(level: PUBLIC) {
authors: _select(
sql: """
SELECT
u.id, u.display_name,
COUNT(p.id) AS post_count,
RANK() OVER (ORDER BY COUNT(p.id) DESC) AS rank
FROM users u
LEFT JOIN posts p ON p.author = u.id
GROUP BY u.id, u.display_name
ORDER BY post_count DESC
LIMIT $1
""",
params: [$limit]
)
}
Mire való és mire nem?
- Jó használati esetek: komplex riportok ablak-függvényekkel, PostGIS földrajzi keresések, full-text keresés tsvector-rel, stored procedure-ök hívása, performance-kritikus, kézzel optimalizált lekérdezések.
- Kevésbé jó: egyszerű CRUD műveletek (a sima GraphQL kényelmesebb), bármi, ami típusbiztos eredményt igényelne (a native SQL lazább típusokkal tér vissza).
-- sor-komment (csak /* ... */ blokk-komment), és a paramétereket $1, $2 stílusban kell megadni — ez biztonsági ellenőrzés a SQL-injection ellen. Ha kommentbe rakott egy paramétert is, az operation hibázni fog, mert a params tömbben még szerepel.- realtimeKözéphaladó
06 — Valós idejű lekérdezések
Valós idejű lekérdezések — a GA újdonsága
Hogy néz ki egy valós idejű query?
import { subscribeGetRecentPosts } from '@my-app/dataconnect';
// A traditional query: runs once, result comes back
const { data } = await getRecentPosts({ limit: 20 });
// A realtime query: subscribe, every change is pushed
const unsub = subscribeGetRecentPosts(
{ limit: 20 },
({ data }) => {
setPosts(data.posts); // React state update
}
);
// Cleanup when the component unmounts
unsub();
onSnapshot-ja — feliratkozol, callback érkezik minden változásnál, és van egy unsubscribe függvény. A háttérben az SQL Connect figyeli a Postgres változásait (CDC, change data capture), és csak azokat a változásokat pusholja, amik a query eredményét tényleg érintik.Mire való?
- Live leaderboard — egy játék pontszámlistája, ami változik közben.
- News feed — új posztok, amik magától megjelennek.
- Kollaborációs felület — több felhasználó együtt szerkeszt valamit, és látják egymás módosításait.
- Adminisztrációs dashboard — rendelési statisztikák, amik élőben frissülnek.
where szűrésekkel), ne pedig „minden poszt" stílusúak.- sql-connectKözéphaladó
07 — Jogosultság
@auth — jogosultság a séma szintjén
@auth direktívával. Mindegyik művelet mellé odaírod, kinek szabad lefuttatnia. Ez egészen más szemlélet — szorosabb integráció, kevesebb párhuzamosan karbantartott szabály.A jogosultsági szintek
| @auth(level) | Mit jelent |
|---|---|
PUBLIC | Bárki, akár nem hitelesített is |
USER_ANON | Hitelesített (akár anonim) felhasználó |
USER | Email-megerősített, nem anonim felhasználó |
USER_EMAIL_VERIFIED | Csak email-verifikált |
NO_ACCESS | Csak admin-credenciálok (server-side) |
Finomabb feltételek
where kifejezést is hozzátehetsz, ami a JWT-ből kiolvasott adatokra hivatkozhat:# A user can only see their own orders
query MyOrders @auth(level: USER) {
orders(where: { user: { uid: { eq_expr: "auth.uid" } } }) {
id, total, createdAt
}
}
# Only admin can delete a post (custom claim)
mutation DeletePost($id: UUID!)
@auth(level: USER, expr: "auth.token.role == 'admin'") {
post_delete(id: $id)
}
auth.uid a JWT subject (a felhasználó UID-je), az auth.token a teljes token tartalom, beleértve a custom claimeket (mint a role). Ez ugyanaz a mechanizmus, amit a Firestore Security Rules-ban használsz — csak itt nem külön fájlban van, hanem közvetlenül a művelet mellett.@auth direktíva előnye, hogy a query és a hozzá tartozó jogosultság egymás mellett van. Ha valaki olvassa a kódot, azonnal látja, hogy ez a query kinek elérhető — nem kell egy másik fájlban keresgélnie. Ez sokkal könnyebben karbantartható lehet, mint egy 500 soros firestore.rules fájl.- type-safe-sdkKözéphaladó
08 — SDK-k
Generált típusbiztos SDK-k
Hogy néz ki a generált kód?
import {
getRecentPosts,
createPost,
type GetRecentPostsResponse,
} from '@my-app/dataconnect';
// Typed query — auto-completion, type-checking
const { data, error } = await getRecentPosts({ limit: 10 });
// data.posts has exactly the type the query returns —
// no <any>, no "I hope it looks like this" assumption
data.posts.forEach(post => {
console.log(post.title, post.author.displayName);
});
// Mutation — also typed
await createPost({
title: 'New article',
content: '...',
tags: ['firebase', 'sql'],
});
Mit ad ez a klasszikus REST API-hoz képest?
- Backend kód (Express, NestJS, Laravel...).
- OpenAPI vagy Swagger spec, amit kézzel kell karbantartani.
- Külön kliens SDK, amit vagy generálsz az OpenAPI-ból, vagy kézzel írsz.
- Külön validáció backenden és frontenden.
Frameworkenkénti integráció
- React — TanStack Query alapú hook-ok minden queryhez (
useGetRecentPosts). - Angular — RxJS Observable-ök, Signal-ok, vagy egyszerű Promise.
- Flutter — natív Stream-ek a realtime feliratkozásokhoz.
- iOS / Android — coroutines, async/await, vagy callback alapú API-k.
- sql-connectKözéphaladó
09 — Firestore vs. SQL Connect
Firestore vagy SQL Connect?
| Szempont | Firestore | SQL Connect |
|---|---|---|
| Adatmodell | NoSQL dokumentum | Relációs (PostgreSQL) |
| Lekérdezés-erő | Korlátozott (nincs join, korlátos OR) | Teljes SQL erő (joinok, aggregációk, ablakfüggvények) |
| Tranzakciók | Korlátozott | Teljes ACID |
| Klienselérés | Közvetlen — Security Rules véd | Csak előre definiált műveletek — @auth véd |
| Realtime | Klasszikus erőssége | Új funkció (GA óta) |
| Skálázódás | Gyakorlatilag korlátlan | Cloud SQL skálázódás (vertikális, replikák) |
| Belépési pont (induló költség) | $0 (Spark plan) | ~$9.37/hó (db-f1-micro) |
| Pricing modell | Műveletek alapján | Cloud SQL instance + operations |
| Migráció | Lock-in (export bonyolult) | Standard PostgreSQL — könnyebb átköltözni |
Mikor melyik?
Firestore vagy SQL Connect?
Mobile-first appok, valós idejű kollaboráció, kis-közepes adatmennyiség, sok user, dokumentum-orientált adat (chat, jegyzetek, profilok). Ahol a séma rugalmas és gyorsan változik.
Üzleti rendszerek bonyolult relációkkal, riportok, analitikai lekérdezések, pénzügyi adat erős konzisztenciával, klasszikus admin-felületek. Ahol az SQL ereje hiányzik a Firestore-ból.
- sql-connectHaladó
10 — Hibrid
Hibrid — együtt használat
Egy jellemző hibrid felosztás
| Adat típusa | Hol legyen |
|---|---|
| Felhasználói profilok, beállítások | Firestore (kis adat, gyakran változó) |
| Chat üzenetek, presence | Realtime Database vagy Firestore |
| Jegyzetek, dokumentumok, sablonok | Firestore (rugalmas séma) |
| Rendelések, számlák, tranzakciók | SQL Connect (erős konzisztencia) |
| Termékkatalógus, készlet | SQL Connect (relációs, sok join) |
| Riportok, dashboardok | SQL Connect (aggregációk) |
| Audit log, történeti rekordok | SQL Connect (tartós, analizálható) |
Az integráció
users kollekciójában is, és az SQL Connect users táblájában is jelen van — egyik sem „mester", csak két nézet ugyanarra a felhasználóra.notifications kollekcióba), akkor erre Cloud Function jön — egy onCreate trigger az SQL Connect oldalon, ami létrehozza a Firestore-rekordot.- sql-connectKözéphaladó
11 — Pricing
Pricing — Cloud SQL költség és műveletek
SQL Connect szolgáltatás-díj
| Tétel | Ingyenes | Felette |
|---|---|---|
| Műveletek (queryk, mutationök) | 250 000 / hó | $4.00 / 1 millió művelet |
| Hálózati kimenő forgalom | 10 GiB / hó | Google Cloud Premium Tier díjszabás |
Cloud SQL PostgreSQL költség
db-f1-micro instance:- 3 hónap ingyenes próba a GA-óta — ez lényegében Spark-szerű limitek nélkül.
- Utána ~$9.37 / hó a legkisebb (db-f1-micro) instance-ért. Ez 600 MB RAM, 1 megosztott vCPU.
- Felfelé skálázható tetszőleges méretű instance-ig — nagy alkalmazáshoz $50-500 / hó között mozog jellemzően.
Hogy különbözik ez a Firestore-tól?
| Pricing dimenzió | Firestore | SQL Connect |
|---|---|---|
| Induló költség | $0 (Spark) | ~$9.37/hó (Cloud SQL) |
| Skálázási karakter | Lineáris (per művelet) | Lépcsős (instance-méret) |
| Olcsó alacsony forgalomnál | Igen | Nem (kell az instance) |
| Olcsó nagy forgalomnál | Nem (sok művelet drága) | Igen (nagyobb instance, lineáris hatás) |
Tehát: kis vagy szezonális forgalmú appra a Firestore olcsóbb, mert nem kell mindig fizetni egy instance-ért. Nagy, állandóan magas terhelésű appra az SQL Connect olcsóbbá válik — egy 1 millió művelet/nap forgalom Firestore-ban súlyos összeg, SQL Connect-ben pedig egy közepes Cloud SQL instance kérdése.
- sql-connectKözéphaladó
12 — Konklúzió
Mikor érdemes választani?
Tervezési checklist SQL Connect indulás előtt
- ☐Az adatmodellem tényleg relációs (sok join, sok aggregáció), vagy csak megszokásból tervezem így?
- ☐Eldöntöttem, hogy strict mode-ban (SQL Connect vezet) vagy compatible mode-ban (Postgres vezet) dolgozom?
- ☐A queryket előre felírtam — minden képernyőhöz tudom, milyen lekérdezésre lesz szükség?
- ☐Mindegyik queryhez és mutationhöz hozzárendeltem a megfelelő
@auth(level: ...)direktívát? - ☐Cloud SQL régiója közel van a felhasználóimhoz (pl.
europe-west1EU-s usereknek)? - ☐A séma migrációt CI-ből futtatom, és tesztkörnyezetben valós SQL-en kipróbálom, mielőtt élesíteném?
- ☐Költség-kerete van a projektnek a Cloud SQL instance-ra (legalább db-f1-micro a minimum)?
- ☐Ha hibrid (Firestore + SQL Connect): tisztán definiáltam, melyik adat hova kerül, és hogy szinkronizálódnak?
- ☐Vannak olyan komplex lekérdezések, amik native SQL-t igényelnek? Ha igen, ezeket külön kommenteltem és tesztelem?
- ☐A generált SDK CI-ben magától újra-generálódik a séma változása után, és committolódik a kliens repóba?
Az SQL Connect nem váltja le a Firestore-t — kiegészíti azt. A Firebase végre teljes platform: dokumentum, fa és relációs adatmodell, mind ugyanazon Auth és Hosting alatt.