gisila_orm
gisila_orm is a PostgreSQL ORM for Dart. You describe your tables in a YAML
file. The generator turns it into Dart models with typed columns plus SQL
migrations, and the runtime gives you a query builder, transactions and
batched eager loading on top of package:postgres.
Install
Section titled “Install”dart pub add gisila_ormRequires Dart 3.3 or newer and PostgreSQL. The package provides two commands:
dart run gisila_orm:generate and dart run gisila_orm:migrate.
30-second example
Section titled “30-second example”Author: columns: name: { type: varchar, is_null: false } email: { type: varchar, is_null: false, is_unique: true }
Post: columns: title: { type: varchar, is_null: false } published_at: { type: timestamp } author: { type: Author, is_null: false, reverse_name: posts }dart run gisila_orm:generate # models + migrationdart run gisila_orm:migrate up # apply it (DATABASE_URL or database.yaml)import 'package:blog/models/blog.gisila.g.dart';import 'package:gisila_orm/gisila.dart';
Future<void> main() async { final db = await Database.connect(await DatabaseConfig.fromEnvironment()); final ctx = db.context();
final ada = await authors().insert({'name': 'Ada', 'email': 'ada@example.com'}).one(ctx); await posts().insert({'title': 'Hello', 'author_id': ada.id}).run(ctx);
final list = await authors() .where(AuthorTable.email.ilike('%@example.com')) .orderBy(AuthorTable.name) .preload([Author.posts]) .all(ctx); for (final a in list) { print('${a.name}: ${a.postsList.map((p) => p.title).toList()}'); }
await db.close();}What you get
Section titled “What you get”| Feature | In short |
|---|---|
| Schema YAML | Models, columns, relations, enums, arrays, pgvector, geometric types, indexes and checks in one file, validated with precise error messages. |
| Generated code | Immutable models, typed ColumnRefs, relation objects and query accessors. No reflection. |
| Query builder | where, orderBy, limit, keyset pagination, joins, count, exists, streaming, all with bound parameters. |
| Writes | Single and bulk inserts, upserts, updates and deletes with RETURNING, and a guard against forgetting WHERE. |
| Eager loading | preload([Author.posts.then(Post.comments)]): one query per relation, not per row. |
| Transactions | db.transaction, savepoints, nested transactions, isolation levels. |
| Migrations | Generated from schema diffs, refused when they’d lose data, applied under an advisory lock with checksums. |
| Errors | Postgres errors as typed exceptions (PostgresUniqueViolationException, …), and an HTTP mapper for gisila apps. |
When to use it
Section titled “When to use it”- A Dart backend that owns its PostgreSQL database and evolves the schema with the code.
- You want column names and value types checked at compile time.
- You want migrations generated for you, with guardrails, but still as plain SQL you can review.
- You build on the gisila framework;
package:gisila_orm/web.dartplugs straight in.
When not to use it
Section titled “When not to use it”- Other databases. Only PostgreSQL is supported.
- A database you don’t own (legacy systems, shared reporting databases). The schema-first workflow assumes you control migrations; use
package:postgresdirectly, or gisila_orm’s raw SQL with hand-writtenTableMeta. - Mostly analytical SQL (reports, window functions, CTEs). The builder targets single-table reads and writes; you’d mostly be using raw SQL.
- Schemas that rely on composite primary keys, partial or expression indexes, or PostGIS. The schema can’t describe them yet; you’d hand-write that DDL.
Map of this section
Section titled “Map of this section”ConceptsSchema-first design, the codegen pipeline, query building, relations and N+1, migrations, transactions, raw SQL.
GuidesSet up a project, define a schema, run migrations, CRUD, filtering, relations, eager loading, testing, production changes.
ReferenceEvery public symbol, the schema format, CLI commands and errors.
gisila frameworkUse gisila_orm from a gisila web app.
Concepts
Section titled “Concepts”- Schema-first design
- The codegen pipeline
- Query building
- Relations and the N+1 problem
- Migrations
- Transactions
- When to drop to raw SQL