Skip to Content
DevelopUsing Relational Databases

Using Relational Databases

Golem provides an API to integrate with popular relational database systems from any of the supported languages. The currently supported databases are:

  • PostgreSQL
  • MySQL
  • Apache Ignite 2

See selected API types and signatures

declare module 'golem:rdbms/types@1.5.0' { export type Uuid = { highBits: bigint; lowBits: bigint; }; export type Date = { year: number; month: number; day: number; }; export type Time = { hour: number; minute: number; second: number; nanosecond: number; }; export type Timestamp = { date: Date; time: Time; }; export type Timestamptz = { timestamp: Timestamp; offset: number; }; export type Timetz = { time: Time; offset: number; }; } declare module 'golem:rdbms/postgres@1.5.0' { import * as golemRdbms150Types from 'golem:rdbms/types@1.5.0'; export class LazyDbValue { constructor(value: DbValue); get(): DbValue; } export class LazyDbColumnType { constructor(value: DbColumnType); get(): DbColumnType; } export class DbResultStream { getColumns(): DbColumn[]; getNext(): DbRow[] | undefined; } export class DbConnection { /** @throws Error */ static open(address: string): DbConnection; /** @throws Error */ query(statement: string, params: DbValue[]): DbResult; /** @throws Error */ queryStream(statement: string, params: DbValue[]): DbResultStream; /** @throws Error */ execute(statement: string, params: DbValue[]): bigint; /** @throws Error */ beginTransaction(): DbTransaction; } export class DbTransaction { /** @throws Error */ query(statement: string, params: DbValue[]): DbResult; /** @throws Error */ queryStream(statement: string, params: DbValue[]): DbResultStream; /** @throws Error */ execute(statement: string, params: DbValue[]): bigint; /** @throws Error */ commit(): void; /** @throws Error */ rollback(): void; } export type Timestamp = golemRdbms150Types.Timestamp; export type Timestamptz = golemRdbms150Types.Timestamptz; export type Date = golemRdbms150Types.Date; export type Time = golemRdbms150Types.Time; export type Timetz = golemRdbms150Types.Timetz; export type Uuid = golemRdbms150Types.Uuid; export type Error = | { tag: 'connection-failure'; val: string } | { tag: 'query-parameter-failure'; val: string } | { tag: 'query-execution-failure'; val: string } | { tag: 'query-response-failure'; val: string } | { tag: 'other'; val: string }; export type SparseVec = { dim: number; indices: number[]; values: number[]; }; export type DbValue = | { tag: 'text'; val: string } | { tag: 'varchar'; val: string } | { tag: 'timestamp'; val: Timestamp } | { tag: 'timestamptz'; val: Timestamptz } | { tag: 'json'; val: string } | { tag: 'jsonb'; val: string } | { tag: 'uuid'; val: Uuid } | { tag: 'array'; val: LazyDbValue[] } | { tag: 'vector'; val: number[] } | { tag: 'halfvec'; val: number[] } | { tag: 'sparsevec'; val: SparseVec } | { tag: 'null' }; export type DbColumnType = | { tag: 'text' } | { tag: 'varchar' } | { tag: 'timestamp' } | { tag: 'timestamptz' } | { tag: 'json' } | { tag: 'jsonb' } | { tag: 'uuid' } | { tag: 'array'; val: LazyDbColumnType } | { tag: 'vector' } | { tag: 'halfvec' } | { tag: 'sparsevec' }; export type DbColumn = { ordinal: bigint; name: string; dbType: DbColumnType; dbTypeName: string; }; export type DbRow = { values: DbValue[]; }; export type DbResult = { columns: DbColumn[]; rows: DbRow[]; }; } declare module 'golem:rdbms/mysql@1.5.0' { import * as golemRdbms150Types from 'golem:rdbms/types@1.5.0'; export class DbResultStream { getColumns(): DbColumn[]; getNext(): DbRow[] | undefined; } export class DbConnection { /** @throws Error */ static open(address: string): DbConnection; /** @throws Error */ query(statement: string, params: DbValue[]): DbResult; /** @throws Error */ queryStream(statement: string, params: DbValue[]): DbResultStream; /** @throws Error */ execute(statement: string, params: DbValue[]): bigint; /** @throws Error */ beginTransaction(): DbTransaction; } export class DbTransaction { /** @throws Error */ query(statement: string, params: DbValue[]): DbResult; /** @throws Error */ queryStream(statement: string, params: DbValue[]): DbResultStream; /** @throws Error */ execute(statement: string, params: DbValue[]): bigint; /** @throws Error */ commit(): void; /** @throws Error */ rollback(): void; } export type Date = golemRdbms150Types.Date; export type Time = golemRdbms150Types.Time; export type Timestamp = golemRdbms150Types.Timestamp; export type Error = | { tag: 'connection-failure'; val: string } | { tag: 'query-parameter-failure'; val: string } | { tag: 'query-execution-failure'; val: string } | { tag: 'query-response-failure'; val: string } | { tag: 'other'; val: string }; export type DbColumnType = | { tag: 'varchar' } | { tag: 'text' } | { tag: 'timestamp' } | { tag: 'json' }; export type DbColumn = { ordinal: bigint; name: string; dbType: DbColumnType; dbTypeName: string; }; export type DbValue = | { tag: 'varchar'; val: string } | { tag: 'text'; val: string } | { tag: 'timestamp'; val: Timestamp } | { tag: 'json'; val: string } | { tag: 'null' }; export type DbRow = { values: DbValue[]; }; export type DbResult = { columns: DbColumn[]; rows: DbRow[]; }; }

Executing SQL statements

To execute an SQL statement with golem-rdbms, first create a db-connection resource and call execute on it:

The Effect examples below run inside a Golem Effect agent, whose runtime supplies the database host services. Creating an Effect does not execute it. Database failures use the SqlError error channel; handle them or map them to the agent method’s declared error type.

MySQL

import { DbConnection } from "golem:rdbms/mysql@1.5.0"; // Connecting to the database called 'test' with user 'root' const conn = DbConnection.open("mysql://root@localhost:3306/test"); conn.execute( `CREATE TABLE IF NOT EXISTS test_users ( user_id varchar(25) NOT NULL, name varchar(255) NOT NULL, created_on timestamp NOT NULL DEFAULT NOW(), PRIMARY KEY (user_id) );`, [] )

The functions in the golem:rdbms/mysql@1.5.0 module are not async. This is due to a limitation of the current Golem runtime, and are subject to change in future releases.

PostgreSQL

import { DbConnection } from "golem:rdbms/postgres@1.5.0"; // Connecting to the database called 'test' with user 'user' const conn = DbConnection.open("postgresql://user@localhost:5432/test"); conn.execute( `CREATE TABLE IF NOT EXISTS test_users ( user_id varchar(25) NOT NULL, name varchar(255) NOT NULL, created_on timestamp NOT NULL DEFAULT NOW(), PRIMARY KEY (user_id) );`, [] )

The functions in the golem:rdbms/postgres@1.5.0 module are not async. This is due to a limitation of the current Golem runtime, and are subject to change in future releases.

Apache Ignite

import { DbConnection } from "golem:rdbms/ignite2@1.5.0"; // Connecting to an Apache Ignite 2 instance const conn = DbConnection.open("ignite://localhost:10800"); conn.execute( `CREATE TABLE IF NOT EXISTS test_users ( user_id varchar(25) NOT NULL, name varchar(255) NOT NULL, PRIMARY KEY (user_id) ) WITH "CACHE_NAME=TestUsers";`, [] ) // Querying data const result = conn.query("SELECT user_id, name FROM test_users WHERE name = ?", [ { tag: "db-string", val: "hello" } ]); // Using transactions const tx = conn.beginTransaction(); tx.execute("INSERT INTO test_users (user_id, name) VALUES (?, ?)", [ { tag: "db-string", val: "1" }, { tag: "db-string", val: "Alice" } ]); tx.commit();

The functions in the golem:rdbms/ignite2@1.5.0 module are not async. This is due to a limitation of the current Golem runtime, and are subject to change in future releases.

API

Additionally you can:

  • query executes a SQL statement and returns a result
  • query-stream executes a SQL statement and returns a streaming result where the selected SDK exposes streaming
  • begin-transaction creates a transaction resource on which, in addition to the query and execute functions, there is also a commit and a rollback method.