orm API reference
A minimal relational mapper over the sql library. It is Data Mapper, not Active Record - Jennifer structs are value-semantic and carry no methods, and a module holds no state, so a row cannot save() itself. Instead you pass a record and a Schema to repository functions: orm.insert / find / update / delete, and orm.all over a query.
There is no reflection, so you declare the table mapping once as an orm.Schema (built with orm.schema + orm.column), which also carries the SQL dialect (orm.Dialect.Mysql or orm.Dialect.Postgres) - a backend selector on one module, not parallel modules. The query builder is functional (like the json write surface): each step returns a fresh orm.Query, rendered to parameterized SQL by orm.toSql. The surface covers ordinary queries: column projection (select) and aggregates (count / aggregate), where / orWhere / whereIn (AND / OR / IN conditions), join / leftJoin / rightJoin, groupBy + having, orderBy / limit / offset.
Values bind only through placeholders (injection safety inherited from sql); the tokens that cannot be parameterized - table / column identifiers, comparison operators, aggregate functions, join kinds, sort directions - are validated against fixed allowlists (identifiers must be bare SQL names). They are checked both at build time (for an early, friendly error) and again at render time inside toSql / createTable / the CRUD builders, so even a hand-built orm.Query / orm.Schema struct literal that skipped the builder cannot inject SQL.
A record - both the input to insert / update and the result of find / all - is a map of string to string keyed by column name (the row form that needs no map-to-struct conversion; a typed-struct form waits on that language feature). The database coerces the string values to the column types.
Needs sql, so the default jennifer binary.
Import with import "orm.j" as orm;. See the orm guide for prose and examples.
Functions
orm.addColumn(table as string, name as string, kind as ColumnKind, dialect as Dialect)
The ALTER TABLE ... ADD COLUMN DDL for a new column (name + type, no attributes; express attribute-rich columns in a createTable schema).
Parameters
table{string}- the table namename{string}- the new column namekind{ColumnKind}- the column value kinddialect{Dialect}- the SQL dialect (for the type spelling)
Returns {string} - the ALTER TABLE ADD COLUMN statement
orm.addForeignKey(table as string, name as string, column as string, refTable as string, refColumn as string)
The ALTER TABLE ... ADD CONSTRAINT ... FOREIGN KEY DDL.
Parameters
table{string}- the table carrying the foreign keyname{string}- the constraint namecolumn{string}- the local foreign-key columnrefTable{string}- the referenced tablerefColumn{string}- the referenced column
Returns {string} - the ALTER TABLE ADD CONSTRAINT statement
orm.aggregate(q as Query, fn as string, col as string, alias as string)
A copy of q adding func(col) AS alias to the projection. func is one of COUNT / SUM / AVG / MIN / MAX; col may be "*" (for COUNT).
Parameters
q{Query}- the source queryfn{string}- the aggregate functioncol{string}- the column (or"*")alias{string}- the result-column alias
Returns {Query} - the extended query
orm.all(session as Session, q as Query)
Run a query and return every matching row.
Parameters
session{Session}- the session (orm.sessionororm.transaction)q{Query}- the query (from the builder)
Returns {list of map of string to string} - the rows
orm.autoIncrement(s as Schema)
A copy of s marking its most-recently-added column auto-incrementing (SERIAL on Postgres, AUTO_INCREMENT on MySQL).
Parameters
s{Schema}- the source schema
Returns {Schema} - the schema with the last column auto-incrementing
orm.belongsTo(s as Schema, name as string, target as string, foreignKey as string)
Declare a belongs-to relation: this table holds foreignKey, which references the target's primary key (id by convention). E.g. a post belongs to an author via posts.authorId -> authors.id.
Parameters
s{Schema}- the source schemaname{string}- the relation nametarget{string}- the target tableforeignKey{string}- the foreign-key column on this table
Returns {Schema} - the schema with the relation added
orm.column(s as Schema, name as string, kind as ColumnKind)
A copy of s with a column appended.
Parameters
s{Schema}- the source schemaname{string}- the column namekind{ColumnKind}- the value kind (orm.ColumnKind.Int/String/Float/Bool/Bytes)
Returns {Schema} - the extended schema
orm.count(q as Query, alias as string)
A copy of q adding COUNT(*) AS alias to the projection.
Parameters
q{Query}- the source queryalias{string}- the result-column alias
Returns {Query} - the extended query
orm.createIndex(name as string, table as string, columns as list of string, isUnique as bool)
The CREATE [UNIQUE] INDEX DDL over one or more columns.
Parameters
name{string}- the index nametable{string}- the table namecolumns{list of string}- the indexed columns (non-empty)isUnique{bool}- whether the index is UNIQUE
Returns {string} - the CREATE INDEX statement
orm.createTable(s as Schema)
The CREATE TABLE DDL for a schema, in its dialect - including each column's NOT NULL / DEFAULT / UNIQUE / auto-increment attributes and the primary key. Pair it with the migration runner (orm.migrate) or run it directly.
Parameters
s{Schema}- the schema
Returns {string} - the CREATE TABLE statement
orm.delete(session as Session, s as Schema, id as string)
Delete a row by primary-key value.
Parameters
session{Session}- the session (orm.sessionororm.transaction)s{Schema}- the schemaid{string}- the primary-key value
Returns {sql.Result} - the affected-rows result
orm.deleteWhere(session as Session, s as Schema, q as Query)
Bulk-delete every row matching a query's WHERE. Refuses a query with no WHERE (use a raw sql.exec to truncate deliberately).
Parameters
session{Session}- the session (orm.sessionororm.transaction)s{Schema}- the schemaq{Query}- the query whoseWHEREselects the rows
Returns {sql.Result} - the affected-rows result
orm.distinct(q as Query)
A copy of q rendered as SELECT DISTINCT ....
Parameters
q{Query}- the source query
Returns {Query} - the query with DISTINCT set
orm.dropColumn(table as string, name as string)
The ALTER TABLE ... DROP COLUMN DDL.
Parameters
table{string}- the table namename{string}- the column to drop
Returns {string} - the ALTER TABLE DROP COLUMN statement
orm.dropForeignKey(table as string, name as string, dialect as Dialect)
The ALTER TABLE ... DROP foreign-key DDL (Postgres DROP CONSTRAINT; MySQL DROP FOREIGN KEY).
Parameters
table{string}- the table namename{string}- the constraint namedialect{Dialect}- the SQL dialect
Returns {string} - the ALTER TABLE DROP statement
orm.dropIndex(name as string, table as string, dialect as Dialect)
The DROP INDEX DDL (Postgres drops by index name; MySQL needs the table).
Parameters
name{string}- the index nametable{string}- the table the index is ondialect{Dialect}- the SQL dialect
Returns {string} - the DROP INDEX statement
orm.dropTable(table as string)
The DROP TABLE DDL for a table.
Parameters
table{string}- the table name
Returns {string} - the DROP TABLE statement
orm.exists(session as Session, q as Query)
Whether a query matches any row (adds LIMIT 1).
Parameters
session{Session}- the session (orm.sessionororm.transaction)q{Query}- the query
Returns {bool} - true if at least one row matches
orm.find(session as Session, s as Schema, id as string)
Find a single row by primary-key value.
Parameters
session{Session}- the session (orm.sessionororm.transaction)s{Schema}- the schemaid{string}- the primary-key value
Returns {map of string to string} - the row (column name -> value)
Throws
{Error}- when no row has that key
orm.findBy(session as Session, s as Schema, col as string, value as string)
The first row of the schema's table where col = value, or {} if none.
Parameters
session{Session}- the session (orm.sessionororm.transaction)s{Schema}- the schemacol{string}- the column to matchvalue{string}- the value to match
Returns {map of string to string} - the matching row, or {} if none
orm.first(session as Session, q as Query)
The first row a query matches (adds LIMIT 1), or an empty map when there is none.
Parameters
session{Session}- the session (orm.sessionororm.transaction)q{Query}- the query
Returns {map of string to string} - the first row, or {} if none
orm.from(s as Schema)
A base query selecting all rows of the schema's table.
Parameters
s{Schema}- the schema
Returns {Query} - the base query
orm.groupBy(q as Query, cols as list of string)
A copy of q grouping by the named columns.
Parameters
q{Query}- the source querycols{list of string}- the GROUP BY columns
Returns {Query} - the extended query
orm.hasMany(s as Schema, name as string, target as string, foreignKey as string)
Declare a has-many relation: the target table holds foreignKey, which references this table's primary key. E.g. an author has many posts via posts.authorId -> authors.id.
Parameters
s{Schema}- the source schemaname{string}- the relation nametarget{string}- the target tableforeignKey{string}- the foreign-key column on the target table
Returns {Schema} - the schema with the relation added
orm.hasOne(s as Schema, name as string, target as string, foreignKey as string)
Declare a has-one relation: the target table holds foreignKey, which references this table's primary key. E.g. a user has one profile via profiles.userId -> users.id.
Parameters
s{Schema}- the source schemaname{string}- the relation nametarget{string}- the target tableforeignKey{string}- the foreign-key column on the target table
Returns {Schema} - the schema with the relation added
orm.having(q as Query, fn as string, col as string, op as string, value as string)
A copy of q with a HAVING condition over an aggregate (func(col) op value), AND-joined. HAVING filters groups, so it is used with groupBy / aggregate.
Parameters
q{Query}- the source queryfn{string}- the aggregate function (COUNT / SUM / AVG / MIN / MAX)col{string}- the aggregated column (or"*")op{string}- the operatorvalue{string}- the value to bind
Returns {Query} - the extended query
orm.insert(session as Session, s as Schema, record as map of string to string)
Insert a record. Only the columns present in record are written (so an auto-generated primary key is simply omitted).
Parameters
session{Session}- the session (orm.sessionororm.transaction)s{Schema}- the schemarecord{map of string to string}- column name -> value
Returns {sql.Result} - the affected-rows / last-insert-id result
orm.insertMany(session as Session, s as Schema, records as list of map of string to string)
Insert many records in one multi-row INSERT. Every record must set the same columns (those present in the first). A batch whose placeholder count would exceed the per-statement limit is split across several INSERTs (never silently capped); wrap the call in orm.transaction for all-or-nothing.
Parameters
session{Session}- the session (orm.sessionororm.transaction)s{Schema}- the schemarecords{list of map of string to string}- the rows to insert
Returns {int} - the number of records inserted
orm.insertReturning(session as Session, s as Schema, record as map of string to string)
Insert record and return the generated primary-key value (Postgres RETURNING pk; MySQL LAST_INSERT_ID via the result's lastId).
Parameters
session{Session}- the session (orm.sessionororm.transaction)s{Schema}- the schemarecord{map of string to string}- the row to insert
Returns {string} - the generated primary-key value
orm.join(q as Query, table as string, leftCol as string, rightCol as string)
A copy of q with an INNER JOIN.
Parameters
q{Query}- the source querytable{string}- the table to joinleftCol{string}- the left join column (table.col)rightCol{string}- the right join column
Returns {Query} - the extended query
orm.joinRelation(q as Query, s as Schema, relationName as string)
A copy of q with the JOIN(s) that a declared relation implies - an INNER JOIN on the correct key columns (two joins for a many-to-many, through its join table). Built over the join primitive.
Parameters
q{Query}- the source querys{Schema}- the schema declaring the relationrelationName{string}- the relation to join
Returns {Query} - the extended query
orm.leftJoin(q as Query, table as string, leftCol as string, rightCol as string)
A copy of q with a LEFT JOIN.
Parameters
q{Query}- the source querytable{string}- the table to joinleftCol{string}- the left join column (table.col)rightCol{string}- the right join column
Returns {Query} - the extended query
orm.limit(q as Query, n as int)
A copy of q with a LIMIT.
Parameters
q{Query}- the source queryn{int}- the row limit
Returns {Query} - the extended query
orm.load(session as Session, schema as Schema, q as Query)
Run a query and eager-load its orm.with-marked relations in a fixed 1 + R queries (R = relations requested): the base query once, then one batched WHERE fk IN (...) per relation - never one query per row. Returns a Result walked by orm.rows / related / relatedOne.
Parameters
session{Session}- the session (orm.sessionororm.transaction)schema{Schema}- the base schema (declares the relations)q{Query}- the query, with relations marked byorm.with
Returns {Result} - the base rows plus the eager-loaded relations
orm.manyToMany(s as Schema, name as string, target as string, joinTable as string, localFk as string, targetFk as string)
Declare a many-to-many relation through a join table. E.g. a post has many tags via post_tags(postId, tagId): manyToMany(s, "tags", "tags", "post_tags", "postId", "tagId"). The target's primary key is id by convention, and this table's key is its primary key.
Parameters
s{Schema}- the source schemaname{string}- the relation nametarget{string}- the target tablejoinTable{string}- the join (through) tablelocalFk{string}- the join-table column referencing this tabletargetFk{string}- the join-table column referencing the target
Returns {Schema} - the schema with the relation added
orm.notNull(s as Schema)
A copy of s marking its most-recently-added column NOT NULL.
Parameters
s{Schema}- the source schema
Returns {Schema} - the schema with the last column made non-nullable
orm.offset(q as Query, n as int)
A copy of q with an OFFSET.
Parameters
q{Query}- the source queryn{int}- the row offset
Returns {Query} - the extended query
orm.orHaving(q as Query, fn as string, col as string, op as string, value as string)
Like having, but OR-joined to the previous HAVING condition.
Parameters
q{Query}- the source queryfn{string}- the aggregate functioncol{string}- the aggregated column (or"*")op{string}- the operatorvalue{string}- the value to bind
Returns {Query} - the extended query
orm.orWhere(q as Query, col as string, op as string, value as string)
Like where, but OR-joined to the previous condition. SQL binds AND tighter than OR, so where(...).orWhere(...) reads a AND b OR c = (a AND b) OR c.
Parameters
q{Query}- the source querycol{string}- the columnop{string}- the operatorvalue{string}- the value to bind
Returns {Query} - the extended query
orm.orWhereIn(q as Query, col as string, values as list of string)
Like whereIn, but OR-joined to the previous condition.
Parameters
q{Query}- the source querycol{string}- the columnvalues{list of string}- the values (must be non-empty)
Returns {Query} - the extended query
orm.orderBy(q as Query, col as string, dir as string)
A copy of q with an ORDER BY term added.
Parameters
q{Query}- the source querycol{string}- the columndir{string}-"asc"or"desc"
Returns {Query} - the extended query
orm.page(q as Query, pageNum as int, pageSize as int)
A copy of q with LIMIT / OFFSET set for a 1-based page: page pageNum of pageSize rows (page 1 starts at offset 0).
Parameters
q{Query}- the source querypageNum{int}- the 1-based page numberpageSize{int}- the rows per page
Returns {Query} - the paginated query
orm.pluck(session as Session, q as Query, col as string)
The values of one column across every row a query matches (the column must be in the projection; the default SELECT * includes it).
Parameters
session{Session}- the session (orm.sessionororm.transaction)q{Query}- the querycol{string}- the column to pluck
Returns {list of string} - the column's value for each matching row
orm.related(result as Result, row as map of string to string, name as string)
The eager-loaded child rows of row for a has-many / many-to-many relation (an empty list if the row has none). No query - a lookup into the Result.
Parameters
result{Result}- the load resultrow{map of string to string}- one base row (fromorm.rows)name{string}- the relation name
Returns {list of map of string to string} - the related child rows
orm.relatedOne(result as Result, row as map of string to string, name as string)
The single eager-loaded row of row for a belongs-to / has-one relation, or an empty map when there is none (a null / unmatched foreign key). No query.
Parameters
result{Result}- the load resultrow{map of string to string}- one base row (fromorm.rows)name{string}- the relation name
Returns {map of string to string} - the related row, or {} if none
orm.renameColumn(table as string, fromName as string, toName as string)
The ALTER TABLE ... RENAME COLUMN DDL (modern MySQL 8+ / MariaDB / Postgres syntax).
Parameters
table{string}- the table namefromName{string}- the current column nametoName{string}- the new column name
Returns {string} - the ALTER TABLE RENAME COLUMN statement
orm.rightJoin(q as Query, table as string, leftCol as string, rightCol as string)
A copy of q with a RIGHT JOIN.
Parameters
q{Query}- the source querytable{string}- the table to joinleftCol{string}- the left join column (table.col)rightCol{string}- the right join column
Returns {Query} - the extended query
orm.rows(result as Result)
The base rows of a Result (the same rows orm.all would return).
Parameters
result{Result}- the load result
Returns {list of map of string to string} - the base rows
orm.save(session as Session, s as Schema, record as map of string to string)
Insert record when it carries no primary key, else update it (matched by the primary key). A Data-Mapper convenience - still no per-row method. (A new row with an explicitly-assigned primary key should use orm.insert.)
Parameters
session{Session}- the session (orm.sessionororm.transaction)s{Schema}- the schemarecord{map of string to string}- the row
Returns {sql.Result} - the affected-rows result
orm.schema(table as string, primaryKey as string, dialect as Dialect)
Start a schema for a table with its primary-key column and dialect. Add columns with orm.column.
Parameters
table{string}- the table nameprimaryKey{string}- the primary-key columndialect{Dialect}-orm.Dialect.Mysqlororm.Dialect.Postgres
Returns {Schema} - the schema (no columns yet)
orm.select(q as Query, cols as list of string)
A copy of q projecting only the named columns (instead of SELECT *). Additive: call again, or combine with count / aggregate.
Parameters
q{Query}- the source querycols{list of string}- the columns to project
Returns {Query} - the extended query
orm.session(conn as sql.Connection)
A session that runs each statement directly on a connection (auto-commit).
Parameters
conn{sql.Connection}- the open connection
Returns {Session} - an auto-committing session
orm.toSql(q as Query)
Render a query to parameterized SQL for its dialect. Pure - the whole query-builder surface is testable without a database. Every identifier and operator is re-validated here (validateQuery), so a hand-built Query literal that skipped the builder guards still cannot inject.
Parameters
q{Query}- the query
Returns {Rendered} - the SQL text and ordered bind values
orm.transaction(tx as sql.Tx)
A session that runs its statements inside a caller-managed transaction. The caller owns sql.begin / commit / rollback; orm just executes through the Tx. The idiom is sql.begin + errdefer sql.rollback + orm.transaction + sql.commit.
Parameters
tx{sql.Tx}- the open transaction
Returns {Session} - a transaction-bound session
orm.unique(s as Schema)
A copy of s adding a UNIQUE constraint to its most-recently-added column.
Parameters
s{Schema}- the source schema
Returns {Schema} - the schema with the last column made unique
orm.update(session as Session, s as Schema, record as map of string to string)
Update a record, matched by its primary-key value (which the record must carry). Every other present column is written.
Parameters
session{Session}- the session (orm.sessionororm.transaction)s{Schema}- the schemarecord{map of string to string}- the row, including the primary key
Returns {sql.Result} - the affected-rows result
Throws
{Error}- when the record has no primary-key value
orm.updateWhere(session as Session, s as Schema, assignments as map of string to string, q as Query)
Bulk-update every row matching a query's WHERE, setting assignments (column -> value, bound as parameters). Refuses a query with no WHERE.
Parameters
session{Session}- the session (orm.sessionororm.transaction)s{Schema}- the schemaassignments{map of string to string}- the columns to setq{Query}- the query whoseWHEREselects the rows
Returns {sql.Result} - the affected-rows result
orm.upsert(session as Session, s as Schema, record as map of string to string, conflictCols as list of string)
Insert record, or update the conflicting row if a unique / primary-key conflict on conflictCols occurs (Postgres ON CONFLICT ... DO UPDATE, MySQL ON DUPLICATE KEY UPDATE). The non-conflict present columns are updated.
Parameters
session{Session}- the session (orm.sessionororm.transaction)s{Schema}- the schemarecord{map of string to string}- the row to insert / updateconflictCols{list of string}- the conflict-target columns (unique / PK; non-empty)
Returns {sql.Result} - the affected-rows result
orm.where(q as Query, col as string, op as string, value as string)
A copy of q with a column op value condition AND-joined to the rest. The value binds as a parameter.
Parameters
q{Query}- the source querycol{string}- the columnop{string}- the operator (=,>,<,>=,<=,!=,<>,LIKE,NOT LIKE)value{string}- the value to bind
Returns {Query} - the extended query
orm.whereBetween(q as Query, col as string, lo as string, hi as string)
A copy of q with a column BETWEEN lo AND hi condition, AND-joined. Both bounds bind as parameters.
Parameters
q{Query}- the source querycol{string}- the columnlo{string}- the lower bound (inclusive)hi{string}- the upper bound (inclusive)
Returns {Query} - the extended query
orm.whereIn(q as Query, col as string, values as list of string)
A copy of q with a column IN (...) condition AND-joined, one placeholder bound per value.
Parameters
q{Query}- the source querycol{string}- the columnvalues{list of string}- the values (must be non-empty)
Returns {Query} - the extended query
orm.whereNotIn(q as Query, col as string, values as list of string)
A copy of q with a column NOT IN (...) condition AND-joined.
Parameters
q{Query}- the source querycol{string}- the columnvalues{list of string}- the values (must be non-empty)
Returns {Query} - the extended query
orm.whereNotNull(q as Query, col as string)
A copy of q with a column IS NOT NULL condition, AND-joined.
Parameters
q{Query}- the source querycol{string}- the column
Returns {Query} - the extended query
orm.whereNull(q as Query, col as string)
A copy of q with a column IS NULL condition, AND-joined.
Parameters
q{Query}- the source querycol{string}- the column
Returns {Query} - the extended query
orm.with(q as Query, relationName as string)
A copy of q marking a declared relation to eager-load with orm.load. Additive: call again for more relations. Does not change the base SQL (toSql ignores it); load runs one extra batched query per marked relation.
Parameters
q{Query}- the source queryrelationName{string}- the relation to eager-load
Returns {Query} - the extended query
orm.withDefault(s as Schema, value as string)
A copy of s giving its most-recently-added column a DEFAULT. The value is rendered by the column kind: an Int / Float default is validated numeric and rendered bare; a Bool default accepts true/false/1/0; a String / Bytes default is rendered as a quoted, escaped SQL string literal (backslashes and control characters are rejected). So no default value can inject DDL.
Parameters
s{Schema}- the source schemavalue{string}- the default value (interpreted per the column kind)
Returns {Schema} - the schema with the last column defaulted
Structs
orm.Column
One column in a schema: its name, value kind, and DDL attributes. The attributes drive createTable / addColumn DDL; set them with the fluent setters (notNull / unique / withDefault / autoIncrement), which decorate the most-recently-added column. A column is nullable by default (SQL's own default); notNull opts into NOT NULL.
| Field | Type | Description |
|---|---|---|
name | string | the column name |
kind | ColumnKind | the value kind |
nullable | bool | whether the column allows NULL (true = no NOT NULL clause) |
unique | bool | whether the column carries a UNIQUE constraint |
hasDefault | bool | whether a DEFAULT is set (guards default) |
default | string | the DEFAULT value (rendered by kind: numeric/bool bare, string quoted+escaped) |
autoIncrement | bool | whether the column auto-increments (SERIAL / AUTO_INCREMENT) |
orm.Condition
A single WHERE condition within a Query; its bound value(s) live in the query's params list (positionally). Built by orm.where / orWhere / whereIn, not directly.
| Field | Type | Description |
|---|---|---|
column | string | the column |
op | string | the comparison operator (or IN / NOT IN) |
connector | string | "AND" or "OR" - how this joins the previous condition |
valueCount | int | the number of placeholders this condition consumes (1, or N for IN) |
orm.Having
A single HAVING condition over an aggregate, its value in havingParams. Built by orm.having, not directly.
| Field | Type | Description |
|---|---|---|
func | string | the aggregate function (COUNT / SUM / AVG / MIN / MAX) |
column | string | the aggregated column (or "" for COUNT()) |
op | string | the comparison operator |
connector | string | "AND" or "OR" - how this joins the previous HAVING condition |
orm.Join
One JOIN clause: its kind and the left = right equality. Built by orm.join / orm.leftJoin / orm.rightJoin, not directly.
| Field | Type | Description |
|---|---|---|
kind | string | "INNER", "LEFT", or "RIGHT" |
table | string | the joined table |
leftCol | string | the left join column (table.col) |
rightCol | string | the right join column |
orm.Order
One ORDER BY term. Built by orm.orderBy, not directly.
| Field | Type | Description |
|---|---|---|
column | string | the column |
dir | string | "ASC" or "DESC" |
orm.Query
A composable, non-mutating SELECT query. Build it with from / select / count / aggregate / where / orWhere / whereIn / join / leftJoin / groupBy / having / orderBy / limit / offset, then render with toSql. Every identifier is re-validated at render time, so a hand-built Query literal cannot bypass the injection guards.
| Field | Type | Description |
|---|---|---|
table | string | the base table |
dialect | Dialect | the SQL dialect |
selects | list of SelectItem | the projection (empty = SELECT *) |
wheres | list of Condition | the WHERE conditions |
params | list of string | the bind values for the WHERE conditions |
joins | list of Join | the JOIN clauses |
groups | list of string | the GROUP BY columns |
havings | list of Having | the HAVING conditions |
havingParams | list of string | the bind values for the HAVING conditions |
orders | list of Order | the ORDER BY terms |
hasLimit | bool | whether a LIMIT is set |
limitN | int | the LIMIT value |
hasOffset | bool | whether an OFFSET is set |
offsetN | int | the OFFSET value |
withRelations | list of string | relation names to eager-load (consumed by load, ignored by toSql) |
distinctSelect | bool | whether to render SELECT DISTINCT |
orm.Relation
A declared association from a schema to another table. Metadata only - built by orm.belongsTo / hasOne / hasMany / manyToMany, read by orm.joinRelation (and, later, eager loading). For a BelongsTo, foreignKey is on this table and localKey is the target's key; for HasOne / HasMany, foreignKey is on the target table and localKey is this table's key. ManyToMany links through through (a join table) via its two keys.
| Field | Type | Description |
|---|---|---|
name | string | the relation's name (the lookup key for joinRelation / eager loading) |
kind | RelationKind | the association kind |
target | string | the target table |
foreignKey | string | the foreign-key column (side depends on kind) |
localKey | string | the referenced key column (the "one" side's key) |
through | string | the join table for ManyToMany (else "") |
throughLocalKey | string | the join-table column referencing this table (else "") |
throughTargetKey | string | the join-table column referencing the target (else "") |
orm.RelationData
The loaded child rows for one eager-loaded relation: a parent-key -> child-rows lookup, built once from a single batched query. Internal to a Result; read it through orm.related / orm.relatedOne, not directly.
| Field | Type | Description |
|---|---|---|
name | string | the relation name |
parentKeyColumn | string | the base-row column whose value indexes the lookup |
byParentKey | map of string to list of map of string to string | parent-key value -> its child rows |
orm.Rendered
A rendered, parameterized statement: the SQL text and the ordered bind values.
| Field | Type | Description |
|---|---|---|
sql | string | the SQL with dialect placeholders |
params | list of string | the bind values, in placeholder order |
orm.Result
The result of orm.load: the base query's rows plus the eager-loaded relations. Read the base rows with orm.rows and a row's related rows with orm.related (has-many / many-to-many) or orm.relatedOne (belongs-to / has-one).
| Field | Type | Description |
|---|---|---|
rows | list of map of string to string | the base query's rows |
relations | list of RelationData | one entry per eager-loaded relation |
orm.Schema
A table mapping: the table name, its columns, the primary-key column, the SQL dialect, and any declared relations. Value-semantic; column returns a fresh schema.
| Field | Type | Description |
|---|---|---|
table | string | the table name |
columns | list of Column | the columns |
primaryKey | string | the primary-key column name |
dialect | Dialect | the SQL dialect (placeholder + DDL spelling) |
relations | list of Relation | the declared associations |
orm.SelectItem
One item in a SELECT projection: a plain column (func "") or an aggregate (func one of COUNT / SUM / AVG / MIN / MAX, rendered func(column) AS alias). Built by orm.select / orm.count / orm.aggregate, not directly.
| Field | Type | Description |
|---|---|---|
func | string | the aggregate function, or "" for a plain column |
column | string | the column (or "" for COUNT()) |
alias | string | the AS alias for an aggregate, or "" for a plain column |
orm.Session
A unit of work wrapping either a sql.Connection (auto-committing) or a sql.Tx (inside a caller's transaction). Every persistence / query-executing function takes a Session as its first argument, so the same call runs standalone or inside a transaction. Value-semantic; build it with orm.session or orm.transaction, not directly (only the handle selected by inTx is ever touched).
| Field | Type | Description |
|---|---|---|
conn | sql.Connection | the connection (used when inTx is false) |
tx | sql.Tx | the transaction (used when inTx is true) |
inTx | bool | which handle is live |
Enums
orm.ColumnKind
A column's value kind: the SQL type family createTable renders. One of orm.ColumnKind.Int / String / Float / Bool / Bytes.
orm.Dialect
The SQL dialect: the backend selector that governs placeholder syntax and DDL spelling. orm.Dialect.Mysql or orm.Dialect.Postgres.
orm.RelationKind
The kind of an association between two tables: orm.RelationKind.BelongsTo (this table holds the foreign key), HasOne / HasMany (the target table holds it), or ManyToMany (a join table links the two).