Data · The database, wired

Invercargill-Sql-Inversion

The Inversion integrations for Invercargill-Sql. Three classes — DatabaseConfigurator, MigrationStartupService and InversionTypeProvider — turn the database layer from something you wire by hand into something the container hands you.

Version
0.1
Licence
LGPL-3.0-or-later
Package
usm install invercargill-sql-inversion
Language
Vala

Overview

Integration glue, honestly scoped

This repository ships no README — its three source files are the whole story, and this page summarises what they actually do. Invercargill-Sql-Inversion is glue in the good sense: the connective tissue that lets an application declare its database, entities, projections and migrations once, and have the Inversion container resolve Invercargill-Sql's connections, dialects, runners, mappers and sessions ever after.

Without it, every application repeats the same wiring — open a connection from a connection string, create a dialect, build a migration runner, register a type registry, construct sessions. With it, that wiring is one configurator object and a handful of registrations.

Features

The three classes

  • DatabaseConfigurator. Registers a connection from a connection string, plus the dialect factory, migration runner, type provider and ORM session — with an auto-detected lifecycle.
  • add_entity, add_migration, add_projection. Fluent registration of mappers, migrations and projection definitions, each tagged with typed metadata.
  • MigrationStartupService. A startup-lifecycle service that gathers every registered migration and runs the schema to latest when the container initialises.
  • InversionTypeProvider. Answers "which mapper or projection belongs to this Vala type?" by querying registration metadata — the bridge the ORM's registry needs.
  • Lifecycle detection. In-memory databases register as singletons, file databases as scoped — the sensible default, overridable per registration.

Installation

Getting the library

usm install invercargill
usm install invercargill-sql
usm install inversion
usm install invercargill-sql-inversion
USM resolves the dependency chain; the explicit steps are for reading order.

From source:

git clone <the Invercargill-Sql-Inversion repository>
cd Invercargill-Sql-Inversion
meson setup build
ninja -C build
ninja -C build install
Requires the three libraries above installed first.
valac --pkg invercargill-sql-inversion my-program.vala
The binding pulls in its .deps chain automatically.

Usage & documentation

Wiring a database in one place

The configurator injects the container it lives in, so configuration reads as plain registrations:

var db = new DatabaseConfigurator();
db.register_connection("sqlite::memory:");
The entry point, from src/DatabaseConfigurator.vala. In-memory databases default to the singleton lifecycle; file databases to scoped — pass a lifecycle to override.

That one call registers the connection itself, a transient SqlDialect from the connection string's scheme, a transient MigrationRunner, the TypeProvider, and an OrmSession sharing the connection's lifecycle. Then entities, projections and migrations join the container with their own fluent calls:

db.add_entity<User>(b => b
    .table("users")
    .column<int64?>("id", u => u.id, (u, v) => u.id = v)
    .column<string>("name", u => u.name, (u, v) => u.name = v));

db.add_projection<UserSummary>(b => { /* projection columns */ });

db.add_migration<V001_CreateUsers>();
Shape from src/DatabaseConfigurator.vala — each registration tags the container entry with typed MapperTypeInfo metadata.

To have the schema ready before the application serves anything, one more line:

db.migrate_on_startup();
container.initialise();
migrate_on_startup() registers the MigrationStartupService on the STARTUP lifecycle; when the container initialises, it creates a scope, resolves every registered Migration, hands them to the runner, and migrates to latest.

Downstream, the ORM asks for mappers through the type provider rather than a hand-built registry:

public class InversionTypeProvider : Object, TypeProvider {

    private Scope scope = inject<Scope>();

    public EntityMapper? get_mapper_for_type(GLib.Type type) throws Error {
        var reg = scope.get_registrations(typeof(EntityMapper))
            .where(r => r.get_metadata<MapperTypeInfo>()
                        .any(i => i.mapper_type == type))
            .first_or_default();
        return reg == null ? null
            : (EntityMapper)scope.resolve_registration(reg);
    }
    // get_projection_for_type, has_mapper_for_type likewise
}
Condensed from src/InversionTypeProvider.vala — the metadata written at registration time is what answers the type question here.

Package & source

The ledger

Version
0.1 (from MANIFEST.usm)
Licence
LGPL-3.0-or-later — free to run, study, share and improve; the LGPL keeps it free to link from any program.
Package
usm install invercargill-sql-inversion
Provides
libinvercargill-sql-inversion.so, invercargill-sql-inversion.h, invercargill-sql-inversion.vapi + .deps, invercargill_sql_inversion-0.1.gir, invercargill_sql_inversion-0.1.typelib, invercargill-sql-inversion.pc
Needs at runtime
GLib, GObject, libinvercargill-1.so, libinvercargill-sql.so and libinversion-0.1.so.
Source
The repository Tilo15/Invercargill-Sql-Inversion on the Astrologue forge (git over ssh, port 222). Free software: the licence guarantees your right to the source.