Skip to content

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.

Terminal window
dart pub add gisila_orm

Requires Dart 3.3 or newer and PostgreSQL. The package provides two commands: dart run gisila_orm:generate and dart run gisila_orm:migrate.

lib/models/blog.gisila.yaml
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 }
Terminal window
dart run gisila_orm:generate # models + migration
dart 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();
}
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.
  • 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.dart plugs straight in.
  • 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:postgres directly, or gisila_orm’s raw SQL with hand-written TableMeta.
  • 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.