From e7c4ea85915d525c738ae0da5494da57926b07ca Mon Sep 17 00:00:00 2001 From: Stefan Majewsky Date: Wed, 29 Jul 2026 21:42:32 +0200 Subject: add package gsql --- gsql/gsql.go | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 gsql/gsql.go (limited to 'gsql/gsql.go') diff --git a/gsql/gsql.go b/gsql/gsql.go new file mode 100644 index 0000000..939194b --- /dev/null +++ b/gsql/gsql.go @@ -0,0 +1,77 @@ +// SPDX-FileCopyrightText: 2026 Stefan Majewsky +// SPDX-License-Identifier: Apache-2.0 + +// Package gsql abstracts over database libraries, supporting both database/sql drivers and non-standard drivers like [pgx]. +// The main abstractions are [Handle] and [ConnectionHandle]. +// +// This package only provides [Handle] implementations for use with database/sql. +// A [Handle] implementation for use with [pgx] is provided in [gg-pgx]. +// +// [pgx]: https://github.com/jackc/pgx +// [gg-pgx]: https://git.xyrillian.de/go-gg-pgx/ +package gsql + +import ( + "context" + "database/sql" +) + +// ConnectionHandle extends [Handle] with methods that make sense for handles referring to entire connections or connection pools, but not e.g. to transactions. +// The standard-library types [*sql.DB] and [*sql.Conn] can satisfy this interface through the wrappers [NewDB] and [NewConn]. +// +// Like for [Handle], the method names are deliberately clunky to avoid name clashes with well-known methods. +type ConnectionHandle interface { + Handle + + // GSQLClose closes the connection represented by this handle. + GSQLClose() error + + // GSQLTransact executes an action within a database transaction. + // The callback will be provided with a [Handle] referring to the transaction. + // The transaction will be committed if the callback returns successfully, or rolled back otherwise. + GSQLTransact(ctx context.Context, action func(tx Handle) error) error +} + +// Handle can be implemented by objects that allow executing SQL queries. +// The standard-library types [*sql.DB], [*sql.Conn] and [*sql.Tx] can satisfy this interface through the wrappers [NewDB], [NewConn] and [NewTx]. +// Custom implementations of this interface can be used to connect non-std database drivers to functions accepting this interface. +// +// The method names are deliberately clunky to avoid name clashes with well-known methods like [sql.DB.Prepare] or [sql.DB.Query]. +type Handle interface { + // GSQLPrepare prepares to execute a certain SQL query one or multiple times. + // + // The "repeated" flag is a hint to the implementation whether the same statement is going to be run many times. + // If false, the implementation shall choose to forego the additional effort of a full statement preparation if possible, + // and execute one-off queries instead. + GSQLPrepare(ctx context.Context, query string, repeated bool) (Statement, error) + + // GSQLQuery works like db.QueryContext(ctx, query, args...). + GSQLQuery(ctx context.Context, query string, args []any) (Rows, error) +} + +// Statement represents a prepared statement returned from the GSQLPrepare() method of [Handle]. +// The Exec and QueryRow methods shall work similarly to the respective functions on [*sql.Tx], as indicated in the comments. +// +// You will not need to interact with this type except when implementing your own [Handle]. +type Statement interface { + Close() error + + // Exec works like stmt.ExecContext(ctx, args...). + // The returned Result object must remain usable after Close() is called on this Statement instance. + Exec(ctx context.Context, args []any) (sql.Result, error) + + // QueryRow works like stmt.QueryRow(ctx, args...).Scan(slots...). + QueryRow(ctx context.Context, args []any, slots []any) error +} + +// Rows represents a set of rows returned from the GSQLQuery() method of [Handle]. +// All methods shall behave like on the [*sql.Rows] type from std. +// +// You will not need to interact with this type except when implementing your own [Handle]. +type Rows interface { + Columns() ([]string, error) + Close() error + Err() error + Next() bool + Scan(slots ...any) error +} -- cgit v1.3.1