flsql

package
v0.236.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 8, 2024 License: Apache-2.0 Imports: 16 Imported by: 3

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func JoinColumnName

func JoinColumnName(cns []ColumnName, sep string, format string) string

func MakeErrSQLRow

func MakeErrSQLRow(err error) sql.Row

func MakeSQLRowsIterator

func MakeSQLRowsIterator[T any](rows sqlRows, mapper SQLRowMapper[T]) iterators.Iterator[T]

Types

type ColumnName

type ColumnName string

func SplitArgs

func SplitArgs(cargs map[ColumnName]any) ([]ColumnName, []any)

type Connection

type Connection interface {
	comproto.OnePhaseCommitProtocol
	Queryable
	io.Closer
}

Connection represent an open connection. Connection will respect the transaction state in the received context.Context.

type ConnectionAdapter

type ConnectionAdapter[DB, TX any] struct {
	// DB is the underlying Database type to access.
	// It is ideal if ConnectionAdapter used as the Connection type implementation, but you need access to not exposed functionalities.
	//
	// 		type Connection flsql.ConnectionAdapter[*sql.DB, *sql.Tx]
	//
	DB DB
	// TxAdapter provides the mapping for a native driver specific TX type to be usable as a Queryable.
	TxAdapter func(tx TX) Queryable
	// DBAdapter provides the mapping for a native driver specific DB type to be usable as a Queryable.
	DBAdapter func(db DB) Queryable
	// BeginFunc is a function that must create a new transaction that is also a connection.
	BeginFunc func(ctx context.Context) (TX, error)
	// CommitFunc is a function that must commit a given transaction.
	CommitFunc func(ctx context.Context, tx TX) error
	// Rollback is a function that must rollback a given transaction.
	Rollback func(ctx context.Context, tx TX) error

	// OnClose [optional] is used to implement the io.Closer.
	// If The ConnectionAdapter needs to close something,
	// then this function can be used for that.
	//
	// default: DB.Close()
	OnClose func() error
	// ErrTxDone is the error returned when the transaction is already finished.
	// ErrTxDone is an optional field.
	//
	// default: sql.ErrTxDone
	ErrTxDone error
}

ConnectionAdapter is generic implementation to handle query interactions which are aware of trasnactions within the context.

Example:

type Connection = flsql.ConnectionAdapter[*sql.DB, *sql.Tx]
Example
package main

import (
	"context"
	"database/sql"
	"os"

	"go.llib.dev/frameless/pkg/flsql"
)

func main() {
	db, err := sql.Open("dbname", os.Getenv("DATABASE_URL"))
	if err != nil {
		panic(err)
	}

	_ = flsql.ConnectionAdapter[*sql.DB, *sql.Tx]{
		DB: db,

		DBAdapter: flsql.QueryableSQL[*sql.DB],
		TxAdapter: flsql.QueryableSQL[*sql.Tx],

		BeginFunc: func(ctx context.Context) (*sql.Tx, error) {
			// TODO: integrate begin tx options
			return db.BeginTx(ctx, nil)
		},

		CommitFunc: func(ctx context.Context, tx *sql.Tx) error {
			return tx.Commit()
		},

		Rollback: func(ctx context.Context, tx *sql.Tx) error {
			return tx.Rollback()
		},
	}
}

func SQLConnectionAdapter

func SQLConnectionAdapter(db *sql.DB) ConnectionAdapter[*sql.DB, *sql.Tx]

SQLConnectionAdapter is a built-in ConnectionAdapter usage for the stdlib sql.DB/sql.Tx. This can be used with any sql driver that integartes with the sql stdlib.

Example
package main

import (
	"database/sql"
	"os"

	"go.llib.dev/frameless/pkg/flsql"
)

func main() {
	db, err := sql.Open("dbname", os.Getenv("DATABASE_URL"))
	if err != nil {
		panic(err)
	}

	_ = flsql.SQLConnectionAdapter(db)
}

func (ConnectionAdapter[DB, TX]) BeginTx

func (c ConnectionAdapter[DB, TX]) BeginTx(ctx context.Context) (context.Context, error)

func (ConnectionAdapter[DB, TX]) Close

func (c ConnectionAdapter[DB, TX]) Close() error

func (ConnectionAdapter[DB, TX]) CommitTx

func (c ConnectionAdapter[DB, TX]) CommitTx(ctx context.Context) error

func (ConnectionAdapter[DB, TX]) ExecContext

func (c ConnectionAdapter[DB, TX]) ExecContext(ctx context.Context, query string, args ...any) (Result, error)

func (ConnectionAdapter[DB, TX]) QueryContext

func (c ConnectionAdapter[DB, TX]) QueryContext(ctx context.Context, query string, args ...any) (Rows, error)

func (ConnectionAdapter[DB, TX]) QueryRowContext

func (c ConnectionAdapter[DB, TX]) QueryRowContext(ctx context.Context, query string, args ...any) Row

func (ConnectionAdapter[DB, TX]) RollbackTx

func (c ConnectionAdapter[DB, TX]) RollbackTx(ctx context.Context) error

type DTO added in v0.236.0

type DTO interface {
	driver.Valuer
	sql.Scanner
}

DTO (Data Transfer Object) is an object used to transfer data between the database and your application. It acts as a bridge between the entity field types in your application and the table column types in your database, to making it easier to map data between them. This helps keep the data structure consistent when passing information between layers or systems.

func JSON added in v0.236.0

func JSON[T any](pointer *T) DTO

func Timestamp added in v0.236.0

func Timestamp(pointer *time.Time, layout string, tz *time.Location) DTO

type MapScan

type MapScan[ENT any] func(v *ENT, scan ScanFunc) error

func (MapScan[ENT]) Map

func (ms MapScan[ENT]) Map(scanner Scanner) (ENT, error)

type Mapping

type Mapping[ENT, ID any] struct {
	// TableName is the name of the table in the database.
	TableName string
	// ToQuery suppose to return back with the column names that needs to be selected from the table,
	// and the corresponding scan function that
	// ctx enables you to accept custom query instructions through the context if you require that.
	ToQuery func(ctx context.Context) ([]ColumnName, MapScan[ENT])
	// ToID will convert an ID into query components—specifically,
	// column names and their corresponding values—that represent the ID in an SQL WHERE statement.
	// If ID is nil, then
	ToID func(id ID) (map[ColumnName]any, error)
	// ToArgs converts an entity pointer into a list of query arguments for CREATE or UPDATE operations.
	// It must handle empty or zero values and still return a valid column statement.
	ToArgs func(ENT) (map[ColumnName]any, error)
	// CreatePrepare is an optional field that allows you to configure an entity prior to crud.Create call.
	// This is a good place to add support in your Repository implementation for custom ID injection or special timestamp value arrangement.
	//
	// To have this working, the user of Mapping needs to call Mapping.OnCreate method within in its crud.Create method implementation.
	CreatePrepare func(context.Context, *ENT) error

	// GetID [optional] is a function that allows the ID lookup from an entity.
	//
	// default: extid.Lookup
	GetID func(ENT) ID
}

Mapping is a table mapping

Example
package main

import (
	"context"

	"go.llib.dev/frameless/pkg/flsql"
)

func main() {
	type ExampleEntity struct {
		ID   int64
		Col1 int
		Col2 string
		Col3 bool
	}
	_ = flsql.Mapping[ExampleEntity, int64]{
		TableName: `"public"."entities"`,

		ToID: func(id int64) (map[flsql.ColumnName]any, error) {
			return map[flsql.ColumnName]any{"entity_id": id}, nil
		},

		ToArgs: func(ee ExampleEntity) (map[flsql.ColumnName]any, error) {
			return map[flsql.ColumnName]any{
				"entity_id": ee.ID,
				"col1":      ee.Col1,
				"col2":      ee.Col2,
				"col3":      ee.Col3,
			}, nil
		},

		ToQuery: func(ctx context.Context) ([]flsql.ColumnName, flsql.MapScan[ExampleEntity]) {
			return []flsql.ColumnName{"entity_id", "col1", "col2", "col3"},
				func(ent *ExampleEntity, scan flsql.ScanFunc) error {
					return scan(&ent.ID, &ent.Col1, &ent.Col2, &ent.Col3)
				}
		},
	}
}

func (Mapping[ENT, ID]) LookupID

func (m Mapping[ENT, ID]) LookupID(ent ENT) (ID, bool)

func (Mapping[ENT, ID]) OnCreate

func (m Mapping[ENT, ID]) OnCreate(ctx context.Context, ptr *ENT) error

type Queryable

type Queryable interface {
	ExecContext(ctx context.Context, query string, args ...any) (Result, error)
	QueryContext(ctx context.Context, query string, args ...any) (Rows, error)
	QueryRowContext(ctx context.Context, query string, args ...any) Row
}

func QueryableSQL

func QueryableSQL[SQLQ sqlQueryable](q SQLQ) Queryable

type QueryableAdapter

type QueryableAdapter[T any] struct {
	V T

	ExecFunc     func(ctx context.Context, query string, args ...any) (Result, error)
	QueryFunc    func(ctx context.Context, query string, args ...any) (Rows, error)
	QueryRowFunc func(ctx context.Context, query string, args ...any) Row
}

func (QueryableAdapter[T]) ExecContext

func (a QueryableAdapter[T]) ExecContext(ctx context.Context, query string, args ...any) (Result, error)

func (QueryableAdapter[T]) QueryContext

func (a QueryableAdapter[T]) QueryContext(ctx context.Context, query string, args ...any) (Rows, error)

func (QueryableAdapter[T]) QueryRowContext

func (a QueryableAdapter[T]) QueryRowContext(ctx context.Context, query string, args ...any) Row

type Result

type Result interface {
	// RowsAffected returns the number of rows affected by an
	// update, insert, or delete. Not every database or database
	// driver may support this.
	RowsAffected() (int64, error)
}

type Row

type Row interface {
	// Scan works the same as Rows. with the following exceptions. If no
	// rows were found it returns errNoRows. If multiple rows are returned it
	// ignores all but the first.
	Scan(dest ...any) error
}

type Rows

type Rows interface {
	// Closer is the interface that wraps the basic Close method.
	io.Closer
	// Err returns any error that occurred while reading.
	Err() error
	// Next prepares the next row for reading. It returns true if there is another
	// row and false if no more rows are available. It automatically closes rows
	// when all rows are read.
	Next() bool
	// Scan reads the values from the current row into dest values positionally.
	// dest can include pointers to core types, values implementing the Scanner
	// interface, and nil. nil will skip the value entirely. It is an error to
	// call Scan without first calling Next() and checking that it returned true.
	Scan(dest ...any) error
}

type SQLRowMapper

type SQLRowMapper[T any] interface {
	Map(s Scanner) (T, error)
}

type SQLRowMapperFunc

type SQLRowMapperFunc[T any] func(Scanner) (T, error)

func (SQLRowMapperFunc[T]) Map

func (fn SQLRowMapperFunc[T]) Map(s Scanner) (T, error)

type ScanFunc

type ScanFunc func(dest ...any) error

type Scanner

type Scanner interface{ Scan(dest ...any) error }

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL