Supported Dialects
Supported Dialects: PostgreSQL & Google Spanner
spanner-orm
is uniquely designed to work with both PostgreSQL (including its lightweight variant PGLite) and Google Spanner, allowing you to use a single object model for your schema and queries across these distinct database systems.
Core Philosophy: Single Object Model
The primary goal is to define your data structures and write your application logic once. spanner-orm
then handles the translation to dialect-specific SQL for schema manipulation (DDL) and data querying (DML).
- Schema Definition: You define tables, columns, and relationships using
spanner-orm
’s Drizzle-inspired syntax. This definition is abstract and not tied to a specific SQL dialect at the point of definition. - Migration Generation: When you create migrations,
spanner-orm
generates SQL appropriate for both PostgreSQL and Spanner, storing them in dialect-specific functions within the migration file (e.g.,migratePostgresUp
,migrateSpannerUp
). - Query Execution: When you build queries using the fluent API (
db
object) or theQueryBuilder
, the ORM constructs an internal representation of the query. This is then translated into dialect-specific SQL by the appropriate adapter just before execution.
PostgreSQL & PGLite
For PostgreSQL and PGLite, spanner-orm
generates standard, highly compatible SQL.
- Dialect Name: When configuring the
OrmClient
or using CLI commands for PostgreSQL or PGLite, the dialect is specified as"postgres"
. - PGLite: PGLite is a WebAssembly build of PostgreSQL that runs directly in Node.js or the browser.
spanner-orm
treats PGLite as a PostgreSQL-compatible environment. ThePgliteAdapter
handles the specifics of interacting with a PGLite instance. - Features: Most standard PostgreSQL features that can be expressed through the ORM’s schema definition and query builder are supported. This includes common data types, constraints, indexes, and query operations.
- SQL Generation: The SQL generated aims for broad compatibility with common PostgreSQL versions.
Example OrmClient
Initialization for PGLite:
import { OrmClient, PgliteAdapter } from "spanner-orm";
import { PGlite } from "@electric-sql/pglite";
const pglite = new PGlite(); // In-memory or file-based
const adapter = new PgliteAdapter(pglite);
await adapter.connect();
const db = new OrmClient(adapter, "postgres");
Google Spanner
Google Spanner uses a dialect of SQL known as “Google Standard SQL”. While it shares many similarities with ANSI SQL, it has unique features, data types, and DDL syntax, particularly concerning schema design (e.g., interleaved tables, primary key constraints).
- Dialect Name: When configuring the
OrmClient
or using CLI commands for Spanner, the dialect is specified as"spanner"
. - SQL Generation:
spanner-orm
generates Google Standard SQL when targeting Spanner. This includes:- Correct DDL for
CREATE TABLE
, including Spanner-specific primary key definitions and options. - DML (SELECT, INSERT, UPDATE, DELETE) that adheres to Google Standard SQL syntax and conventions.
- Correct DDL for
- Spanner-Specific Features:
- Interleaved Tables: While the core schema definition aims for common ground,
spanner-orm
intends to provide mechanisms or conventions to define and utilize Spanner’s interleaved tables for co-location of parent-child data. (See Advanced Topics). - Data Types: The ORM maps its abstract types to appropriate Spanner data types (e.g.,
STRING
,INT64
,FLOAT64
,BOOL
,TIMESTAMP
,DATE
,JSON
,BYTES
,ARRAY
). - Transactions: Spanner’s transaction model (especially read-write transactions) is respected by the
SpannerAdapter
.
- Interleaved Tables: While the core schema definition aims for common ground,
Example OrmClient
Initialization for Spanner:
import { OrmClient, SpannerAdapter } from "spanner-orm";
import { Spanner } from "@google-cloud/spanner";
// const spannerClient = new Spanner({ projectId: "your-gcp-project" });
// const instance = spannerClient.instance("your-spanner-instance");
// const database = instance.database("your-spanner-database");
// const adapter = new SpannerAdapter(database);
// await adapter.connect(); // May involve specific Spanner setup/checks
// const db = new OrmClient(adapter, "spanner");
Bridging the Differences
spanner-orm
abstracts many common database operations. However, some features are unique to one dialect:
jsonb
type: This is primarily a PostgreSQL feature. When targeting Spanner,spanner-orm
will map this to Spanner’sJSON
type. Functionality and indexing capabilities for JSON might differ between the two.- Advanced Spanner Features: Features like interleaved tables or specific Spanner query hints might require special handling or syntax extensions within the ORM, or might be addressed through raw SQL escape hatches if direct ORM support is not yet mature.
The goal is to maximize code reusability while still allowing developers to leverage the unique strengths of each database system when necessary. Always refer to the specific documentation for adapters and advanced features for the most up-to-date information on how dialect differences are handled.