Docs
View as markdown

Go API

The exported identifiers of the relate Go package, the Cypher and Go value mapping in both directions, result metadata, errors and cgo linking.

go

The Go client A language package that runs the relate engine inside a program's process: the Python, Node.js, Rust, Java, Go and Swift clients. Read more in the glossary is the module github.com/relatedb/relate/clients/go, package relate, for Go 1.22 or later. It is cgo code over the relate C library, librelate_ffi, whose C application binary interface (C ABI) is version 2: values cross through the library's typed value walker and parameter builder, with no JSON. Every call is synchronous. This page lists the package's exported identifiers as go doc reports them for relate 0.1.2.

Synopsis

import relate "github.com/relatedb/relate/clients/go"

func Open(uri string) (*Database, error)
func OpenReadOnly(uri string) (*Database, error)

func (d *Database) Connect() (*Connection, error)
func (d *Database) ConnectNamespace(name string) (*Connection, error)
func (d *Database) Checkpoint() error
func (d *Database) Close()

func (c *Connection) Query(cypher string) (*Result, error)
func (c *Connection) QueryParams(cypher string, params map[string]any) (*Result, error)
func (c *Connection) SetNamespace(name string) error
func (c *Connection) Begin() error
func (c *Connection) Commit() (string, error)
func (c *Connection) Rollback() error
func (c *Connection) Close()

Exported identifiers

IdentifierKindHolds
Databasestruct, unexported fieldsAn open store
Connectionstruct, unexported fieldsOne session on a store
ResultstructColumns, Rows, QueryType, Namespace, Bookmark, Stats, Notifications, Plan
StatsstructThe 11 mutation counters
QueryTypestring typeQueryTypeRead "r", QueryTypeWrite "w", QueryTypeReadWrite "rw", QueryTypeSchema "s"
Namespacestring typeNamespaceNeo4j "neo4j", NamespaceSystem "system", NamespaceSystemOntologies "system_ontologies"
ErrorstructCode, GQLStatus, Stage, Retryable, Message; Error() returns Message
Stagestring typeStageCompile "compile", StageRuntime "runtime", StageInternal "internal"
Node, Relationship, Pathstruct, struct, []anyGraph values
Point, VectorstructSpatial and vector values
Date, Time, LocalTime, DateTime, LocalDateTime, DurationstructTemporal values as their components
NotificationstructOne planner notification
PlanDocument, PlanNode, PlanActual, PlanStartstructThe structured plan

Database

Function or methodBehavior
Open(uri)Opens :memory:, a directory store or a .rl store for writing; creates a missing store
OpenReadOnly(uri)Loads an existing store once; refuses writes and checkpoints; a missing store is an error
Connect()A connection in the neo4j namespace
ConnectNamespace(name)A connection in neo4j, system or system_ontologies, matched case-insensitively
Checkpoint()Writes a checkpoint, folding the write-ahead log into a fresh snapshot of committed state; refused on a read-only database
Close()Frees the native handle

A failed Open or OpenReadOnly returns a *Error with message internal error, code Neo.DatabaseError.General.UnknownError, GQLSTATUS 42000 and stage internal, whether the store is locked by another writer or missing. An unknown namespace returns semantic error: DatabaseNotFound: Graph not found: <name>.

Close on a *Database or a *Connection frees the native handle and keeps no closed state: a second Close, or any later call on the value, uses freed memory. The package sets no finalizers, so a handle never closed keeps its store open, and a .rl store locked, until the process exits.

Connection

MethodBehavior
Query(cypher)QueryParams with a nil map
QueryParams(cypher, params)Runs one statement; auto-commits outside an explicit transaction; a nil map binds no parameters
SetNamespace(name)Changes the session namespace; refused inside a transaction
Begin()Opens an explicit transaction; transactions do not nest
Commit()Commits; returns the bookmark "relate:<n>", or "" when the transaction wrote nothing; a failure returns "" and the error and ends the transaction
Rollback()Discards the explicit transaction
Close()Disconnects; an open transaction rolls back

A statement failure returns a nil *Result and the *Error. A connection's own refusals, each with code Neo.ClientError.Statement.SemanticError and GQLSTATUS 42000:

CallMessage
Begin() inside a transactionsemantic error: already in a transaction
Commit() or Rollback() with no transactionsemantic error: no transaction
SetNamespace(…) inside a transactionsemantic error: TransactionError: Cannot change the namespace while a transaction is open.

The package holds no lock. A *Database may be shared between goroutines; calls that share a *Connection are serialized by the caller, one at a time, and distinct connections may run concurrently.

Result

FieldTypeHolds
Columns[]stringThe column names, in RETURN order
Rows[][]anyOne slice per row, cells typed as in Values
QueryTypeQueryTypeThe plan-time classification; EXPLAIN and PROFILE report the wrapped statement's type
NamespaceNamespaceThe statement's USE target, else the session namespace
BookmarkstringAn auto-commit write's bookmark, relate:<n>; "" for a read, an EXPLAIN, a write whose counters are all zero (it changed nothing), and any statement inside an explicit transaction
StatsStatsThe mutation counters; all zero for a read, an EXPLAIN or a write that matched no rows
Notifications[]NotificationFilled by EXPLAIN and PROFILE; an empty, non-nil slice on a plain run
Plan*PlanDocumentThe relate.plan/v1 plan document under EXPLAIN or PROFILE; nil on a plain run

A Result has no column types or timings. A bookmark's <n> grows across every connection of the store and orders as a number: as strings, "relate:10" sorts before "relate:9".

Stats has 11 int64 fields, always present: NodesCreated, NodesDeleted, RelationshipsCreated, RelationshipsDeleted, PropertiesSet, LabelsAdded, LabelsRemoved, IndexesAdded, IndexesRemoved, ConstraintsAdded, ConstraintsRemoved. The counting follows Neo4j: one label per node it is added to, one property per write, and schema statements in the index and constraint counters.

Values

Each result cell decodes to one Go type per Cypher kind:

Cypher kindGo type
NULLnil
BOOLEANbool
INTEGERint64, lossless
FLOATfloat64, NaN and infinities included
STRINGstring, an interior NUL kept
LIST[]any
MAPmap[string]any; Go maps keep no order
nodeNode{ElementID string, ID int64, Labels []string, Properties map[string]any}
relationshipRelationship{ElementID, StartElementID, EndElementID string, ID, StartID, EndID int64, Type string, Properties map[string]any}
pathPath, a []any alternating Node and Relationship
POINTPoint{SRID, Dimension int32, X, Y, Z float64}; Z set only when Dimension is 3
DATEDate{Year, Month, Day int64}
ZONED TIMETime{Hour, Minute, Second, Nanosecond, OffsetSeconds int64}
LOCAL TIMELocalTime{Hour, Minute, Second, Nanosecond int64}
ZONED DATETIMEDateTime{Year, Month, Day, Hour, Minute, Second, Nanosecond, OffsetSeconds int64, Zone string}; Zone is the zone id, or "" for an offset-only value
LOCAL DATETIMELocalDateTime{Year, Month, Day, Hour, Minute, Second, Nanosecond int64}
DURATIONDuration{Months, Days, Seconds, Nanos int64}
VECTORVector{DType string, Ints []int64, Floats []float64}; the slice of the other family is nil
byte array[]any of int64

A zoned value reports its local wall clock. An element id The string elementId() returns for a node or relationship, such as 4:relate-neo4j:n0; it stays the same when the store is closed and opened again. Read more in the glossary is the string elementId() returns, such as 4:relate-neo4j:n0, and is "" in the system namespace. The ID fields are the deprecated numeric ids id() returns. A value kind the client does not know is an error, never nil.

Parameters

QueryParams binds each map entry as one Cypher value:

Go valueBinds as
nil, or a nil pointer, interface, slice, or mapNULL
boolBOOLEAN
any signed or unsigned integerINTEGER; an unsigned value greater than math.MaxInt64 is refused
float32, float64FLOAT
stringSTRING
slice or array, []byte includedLIST
map[string]TMAP
structMAP of its exported fields, keyed by json tag name; json:"-" is skipped and omitempty drops a zero value

The package's own value types are structs, so they bind as maps of their fields; a temporal, point or vector parameter is built in the statement from its parts, as date($day) or vector($v, 3, FLOAT32). A value the builder refuses fails before the statement runs, as a plain error prefixed parameter "<name>": :

CaseMessage after the prefix
Unsigned integer greater than math.MaxInt64unsigned value <n> exceeds the INT range
Map with a non-string key typemap key type <type> is not a string
Struct with no exported fields, time.Time among themstruct type <type> has no exported fields to bind
Any other type: a channel, a function, a complex numberunsupported parameter type <type>

A nested value adds its position (item <n>, field "<name>", key "<name>"). A name holding a NUL byte fails with parameter "<name>" holds an interior NUL and cannot cross the C boundary, and a statement holding one with statement holds an interior NUL and cannot cross the C boundary.

Errors

FieldHolds
CodeThe Neo4j status code, such as Neo.ClientError.Statement.ArithmeticError
GQLStatusThe five-character GQLSTATUS, such as 22G03
StageStageCompile (parse or plan), StageRuntime (execution) or StageInternal (the C boundary: a poisoned handle, a caught panic, a refused argument)
Retryabletrue exactly when running the same work again can succeed: a write-write conflict (Neo.TransientError.Transaction.Outdated, message write-write conflict) or a retryable memory cap
MessageThe engine's message

Every failure the engine or the C boundary reports is a *Error, from a statement's result or from the call's own error channel; errors.As(err, &e) with var e *relate.Error matches it. The client's own refusals are plain error values: the parameter refusals, ABI contract violated: … for a result that breaks the C contract, and unsupported value kind <n>. A write on a read-only database returns code Neo.ClientError.Statement.SemanticError and GQLSTATUS 42N18. The errors reference lists the engine's messages.

Notifications and plans

Notification has the fields Code, GQLStatus, Severity (INFORMATION or WARNING), Category (PERFORMANCE, UNRECOGNIZED, DEPRECATION, SCHEMA or HINT), Title, Description, Remedy and OperatorID, an *int64 that is nil on a statement-scoped notification.

StructFields
PlanDocumentSchema (relate.plan/v1), Profiled, Statement *string, Root PlanNode
PlanNodeOperator, Details, Identifiers, EstimatedRows *int64, Actual *PlanActual, Children, Warnings []Notification
PlanActualRows, TimeMs, DbHits, MemoryBytes, Hops, NeighborWalks, NodeReads, Start *PlanStart; nil on an EXPLAIN plan
PlanStartElement, Backward, Reason

Linking

The package's cgo directives include relate.h and link -lrelate_ffi, searching the surfaces/relate-ffi/include, target/debug and target/release directories of the relate source repository. Outside that repository the build reads cgo's environment:

VariableValueWithout it
CGO_ENABLED1The package's files are excluded: undefined: relate.Open
CGO_CFLAGS-I<directory holding relate.h>fatal error: 'relate.h' file not found
CGO_LDFLAGS-L<directory holding librelate_ffi> -lrelate_ffi; for a static link on macOS, add -framework CoreFoundationld: library 'relate_ffi' not found
DYLD_LIBRARY_PATH (macOS), LD_LIBRARY_PATH (Linux)The shared library's directory, at run time. On Linux an rpath at link time does the same; on macOS the library's install name is the absolute path it was built at, so an rpath does not helpThe binary does not start: on macOS, dyld[<pid>]: Library not loaded: <absolute build path>/librelate_ffi.dylib

Each release attaches relate-ffi-<target>.tar.gz, holding the shared library, the static library, and the header. On Windows, cgo links with MinGW, which needs an import library generated from relate_ffi.dll with gendef and dlltool.

Limits

The limits come from the engine and are the same on every surface: a statement's text is at most 4194304 bytes (syntax error: query text of <n> bytes exceeds the maximum query size of 4194304 bytes), one value a statement builds is bounded by the expression memory cap, and a file-backed store has one writing open across every process. Limits and sizing lists each limit with its default and the setting that changes it.

Capabilities

FeatureGo
In-memory storeA store that lives only in the process.yesrelate.Open(":memory:")
Directory storeA store in a directory on disk.yesrelate.Open(path)
Single-file .rl storeA store in one .rl file.yesrelate.Open("graph.rl")
Read-only openAn open that loads the store once and refuses every write.yesrelate.OpenReadOnly(uri)
Explicit transactionsSeveral statements committed or rolled back together.yesBegin(), Commit(), Rollback()
Parameters$name values passed beside the statement.yesQueryParams(statement, map)
Column types, counters and timingsMetadata returned with each result.partialStats, QueryType, Plan; no column types or timings
NotificationsThe engine's query notifications (for example a Cartesian product), each with a remedy.yesNotifications
Arrow outputResults as Apache Arrow.nono Arrow call in the client
Change data captureReading committed changes from a slot.nono change-data-capture call in the client
Full-text searchFull-text indexes and their queries.yesCREATE FULLTEXT INDEX and full-text SEARCH through the C ABI
LOAD CSV from local filesLocal LOAD CSV under a configured directory (denied unless one is set).yesRELATE_LOAD_CSV_DIR, read by the C ABI's open
Load a store from a URLOpening a .rl store fetched over https.nono open from a URL in the client
Agent modeThe CLI's agent defaults: the 100-row cap and the piped toon output.noA CLI setting

Each cell is yes, no, partial or unknown, with the call, flag or reason. Checked on 2026-11-09 against relate 0.1.2: runs of the CLI binary and relate serve (Bolt, HTTP and MCP), the WebAssembly build this site ships, and the Python, Node.js, C, Java, Go, Swift and Rust clients, and each surface's upstream reference. The C, Java, Go and Swift clients load the same C ABI library as the Node.js client.

Example

This program writes two Person nodes and a KNOWS relationship to an in-memory store and prints the Go type of each returned value:

package main

import (
	"fmt"
	"log"

	relate "github.com/relatedb/relate/clients/go"
)

func main() {
	db, err := relate.Open(":memory:")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
	conn, err := db.Connect()
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
	res, err := conn.Query(`
		CREATE (ada:Person {name: 'Ada'})-[k:KNOWS {since: 2024}]->(grace:Person {name: 'Grace'})
		RETURN ada, k, 9007199254740993 AS big, 1.5 AS ratio, date('2024-05-06') AS day,
		       datetime('2024-05-06T09:30:00[Europe/Berlin]') AS meeting, duration('P1Y2M') AS term,
		       point({x: 1, y: 2}) AS spot, vector([1, 2, 3], 3, INT8) AS counts`)
	if err != nil {
		log.Fatal(err)
	}
	for i, col := range res.Columns {
		fmt.Printf("%s: %T %+v\n", col, res.Rows[0][i], res.Rows[0][i])
	}
}
ada: relate.Node {ElementID:4:relate-neo4j:n0 ID:0 Labels:[Person] Properties:map[name:Ada]}
k: relate.Relationship {ElementID:5:relate-neo4j:r0 StartElementID:4:relate-neo4j:n0 EndElementID:4:relate-neo4j:n1 ID:0 StartID:0 EndID:1 Type:KNOWS Properties:map[since:2024]}
big: int64 9007199254740993
ratio: float64 1.5
day: relate.Date {Year:2024 Month:5 Day:6}
meeting: relate.DateTime {Year:2024 Month:5 Day:6 Hour:9 Minute:30 Second:0 Nanosecond:0 OffsetSeconds:7200 Zone:Europe/Berlin}
term: relate.Duration {Months:14 Days:0 Seconds:0 Nanos:0}
spot: relate.Point {SRID:7203 Dimension:2 X:1 Y:2 Z:0}
counts: relate.Vector {DType:INTEGER8 Ints:[1 2 3] Floats:[]}

See also