Skip to content

Repository files navigation

go-irisnative

A Golang driver for InterSystems IRIS that implements database/sql.

Project status: alpha. API may change. Feedback and PRs welcome.

This project does not contain or distribute any proprietary source code from InterSystems. All observed behaviors or configuration techniques are derived from publicly available information, empirical testing, and independent analysis intended solely to improve interoperability within the IRIS ecosystem.


Installation

# replace the module path with the final repo path when published
go get github.com/caretdev/go-irisnative

Register the driver by importing it for side‑effects:

import (
"database/sql"
_ "github.com/caretdev/go-irisnative"// registers driver as "iris"
)

DSN formats

The driver accepts a URL-style DSN (recommended) or key=value pairs.

URL style

iris://user:password@host:1972/NAMESPACE?max_rows=200&query_timeout=30
  • host — IRIS hostname or IP
  • 1972 — superserver port (default)
  • Namespace — IRIS namespace (e.g., USER)

DSN parameters

  • max_rows — Maximum number of rows to fetch in a single request (default: 0 = no limit)
  • query_timeout — Query timeout in seconds (default: 0 = no timeout)

Quick start (database/sql)

package main
import (
"context""database/sql""fmt""log""time"
_ "github.com/caretdev/go-irisnative"
)
funcmain() {
dsn:="iris://_SYSTEM:SYS@localhost:1972/USER"db, err:=sql.Open("iris", dsn)
iferr!=nil { log.Fatal(err) }
deferdb.Close()
// Connection pool tuningdb.SetMaxOpenConns(10)
db.SetMaxIdleConns(5)
db.SetConnMaxLifetime(30*time.Minute)
ctx, cancel:=context.WithTimeout(context.Background(), 10*time.Second)
defercancel()
_, err=db.ExecContext(ctx, `DROP TABLE IF EXISTS demo_person`)
iferr!=nil { log.Fatal("drop table:", err) }
// 1) Create a table (id INT PRIMARY KEY, name VARCHAR(80))_, err=db.ExecContext(ctx, `CREATE TABLE IF NOT EXISTS demo_person ( id INT PRIMARY KEY, name VARCHAR(80) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP	)`)
iferr!=nil { log.Fatal("create table:", err) }
// 2) Insert with placeholdersres, err:=db.ExecContext(ctx, `INSERT INTO demo_person(id, name) VALUES(?, ?)`, 1, "Alice")
iferr!=nil { log.Fatal("insert:", err) }
ifn, _:=res.RowsAffected(); n>0 { fmt.Println("inserted:", n) }
// 3) Query rowsrows, err:=db.QueryContext(ctx, `SELECT id, name, created_at FROM demo_person ORDER BY id`)
iferr!=nil { log.Fatal("query:", err) }
deferrows.Close()
forrows.Next() {
var (
idintnamestringcreatedAt time.Time
)
iferr:=rows.Scan(&id, &name, &createdAt); err!=nil { log.Fatal(err) }
fmt.Printf("row: id=%d name=%s created_at=%s\n", id, name, createdAt.Format(time.RFC3339))
}
iferr:=rows.Err(); err!=nil { log.Fatal(err) }
// 4) Prepared statementstmt, err:=db.PrepareContext(ctx, `UPDATE demo_person SET name=? WHERE id=?`)
iferr!=nil { log.Fatal("prepare:", err) }
deferstmt.Close()
if_, err:=stmt.ExecContext(ctx, "Alice Updated", 1); err!=nil { log.Fatal("update:", err) }
// 5) Transaction exampletx, err:=db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelReadCommitted})
iferr!=nil { log.Fatal("begin tx:", err) }
if_, err:=tx.ExecContext(ctx, `INSERT INTO demo_person(id, name) VALUES(?, ?)`, 2, "Bob"); err!=nil {
tx.Rollback()
log.Fatal("tx insert:", err)
}
iferr:=tx.Commit(); err!=nil { log.Fatal("commit:", err) }
}

Query single value helper

varcountintiferr:=db.QueryRowContext(ctx, `SELECT COUNT(*) FROM demo_person`).Scan(&count); err!=nil {
log.Fatal(err)
}
fmt.Println("count=", count)

Using with sqlx

sqlx adds nice helpers over database/sql like struct scanning and named queries.

go get github.com/jmoiron/sqlx
package main
import (
"context""fmt""log""time"
_ "github.com/caretdev/go-irisnative"// driver"github.com/jmoiron/sqlx"
)
typePersonstruct {
IDint`db:"id"`Namestring`db:"name"`CreatedAt time.Time`db:"created_at"`
}
funccreate(ctx context.Context, db*sqlx.DB) {
drop(ctx, db)
_, err:=db.ExecContext(ctx, `CREATE TABLE IF NOT EXISTS demo_person ( id INT PRIMARY KEY, name VARCHAR(80) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP	)`)
iferr!=nil {
panic(err)
}
}
funcdrop(ctx context.Context, db*sqlx.DB) {
_, err:=db.ExecContext(ctx, `DROP TABLE IF EXISTS demo_person`)
iferr!=nil {
panic(err)
}
}
funcmain() {
ctx:=context.Background()
dsn:="iris://_SYSTEM:SYS@localhost:1972/USER"db:=sqlx.MustConnect("iris", dsn)
deferdb.Close()
create(ctx, db)
deferdrop(ctx, db)
// Struct-based insert with NamedExecp:=Person{ID: 3, Name: "Carol"}
_, err:=db.NamedExecContext(ctx,
`INSERT INTO demo_person(id, name) VALUES(:id, :name)`, p,
)
iferr!=nil {
log.Fatal("named insert:", err)
}
// Select into slice of structsvarpeople []Personiferr:=db.SelectContext(ctx, &people, `SELECT id, name, created_at FROM demo_person ORDER BY id`); err!=nil {
log.Fatal(err)
}
fmt.Printf("people: %#v\n", people)
// Get a single structvaronePersoniferr:=db.GetContext(ctx, &one, `SELECT id, name, created_at FROM demo_person WHERE id=?`, people[0].ID); err!=nil {
log.Fatal(err)
}
fmt.Printf("one: %+v\n", one)
// Named query with IN (sqlx.In)ids:= []int{1, 2, 3}
q, args, err:=sqlx.In(`SELECT id, name FROM demo_person WHERE id IN (?)`, ids)
iferr!=nil {
log.Fatal(err)
}
q=db.Rebind(q) // ensure driver-specific bindvarsrows, err:=db.QueryxContext(ctx, q, args...)
iferr!=nil {
log.Fatal(err)
}
deferrows.Close()
forrows.Next() {
varidintvarnamestringiferr:=rows.Scan(&id, &name); err!=nil {
log.Fatal(err)
}
fmt.Println(id, name)
}
}

Placeholders & rebind

  • The driver uses ? positional placeholders.
  • With sqlx, always call db.Rebind(q) after sqlx.In(...) to adapt placeholders.

Context, timeouts & cancellations

All examples use Context. Set sensible timeouts to avoid runaway queries:

ctx, cancel:=context.WithTimeout(context.Background(), 5*time.Second)
defercancel()

Error handling tips

  • Check rows.Err() after iteration.
  • Prefer ExecContext/QueryContext to ensure timeouts are respected.
  • Wrap errors with operation context (e.g., fmt.Errorf("create table: %w", err)).

Testing locally

  1. Start IRIS and ensure SQL is enabled for your namespace (e.g., USER).
  2. Create a SQL user with privileges to connect and create tables.
  3. Verify connectivity using the DSN shown above.

Compatibility

  • Go: 1.21+
  • InterSystems IRIS: 2025.1+

License

MIT


Contributing

  • Run go vet and go test ./... before submitting PRs.
  • Add tests for new behaviors.
  • Document any DSN parameters you introduce.

About

No description, website, or topics provided.

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages