libsql

package module
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 29, 2021 License: BSD-3-Clause Imports: 7 Imported by: 0

README

libsql

Go Report Card Build Status GoDoc NetflixOSS Lifecycle GitHub

Project Overview

Package libsql provides wrappers for the Go standard library's "sql" package that enables writing unit-testable and less error-prone SQL database code.

Getting Started

The libsql package can be installed by running:

$ go get oss.indeed.com/go/libsql

To get started, use the libsql.Wrap method and pass a *sql.DB:

import (
	"context"
	"database/sql"

	"oss.indeed.com/go/libsql"
)

func usageExample(ctx context.Context, sqldb *sql.DB) error {
	db := libsql.Wrap(sqldb)

	var column1, column2, column3 int64

	err := db.ScanOne(
		ctx,
		libsql.Into(
			&column1,
			&column2,
			&column3,
		),
		"SELECT 1, 2, 3 FROM dual WHERE 1 = ? AND 2 = ?",
		1,
		2,
	)
	if err != nil {
		return err
	}
	
	// use the values of column1, column2, column3
}

To scan multiple rows, provide a custom implementation of libsql.RowScanner:


import (
	"context"

	"oss.indeed.com/go/libsql"
)

type elephant struct {
	name string
}

type elephantRowScanner struct {
	rawElephantName string

	elephants []elephant
}

var _ libsql.RowScanner = (*elephantRowScanner)(nil)

func (e *elephantRowScanner) Into() []interface{} {
	return []interface{}{&e.rawElephantName}
}

func (e *elephantRowScanner) RowScanned() error {
	if e.rawElephantName == "" {
		return errors.New("empty elephant name in the database")
	}

	e.elephants = append(e.elephants, elephant{name: e.rawElephantName})

	return nil
}

func elephantsFrom(ctx context.Context, q libsql.Queryer) ([]elephant, error) {
	elephantRS := elephantRowScanner{}
	err := q.Scan(
		ctx,
		&elephantRS,
		`SELECT * FROM (VALUES ROW ('Dumbo'), ROW ('Horton')) AS elephants(name)`,
	)
	return elephantsRS.elephants, err
}

Asking Questions

For technical questions about libsql, just file an issue in the GitHub tracker.

For questions about Open Source in Indeed Engineering, send us an email at opensource@indeed.com

Contributing

We welcome contributions! Feel free to help make libsql better.

Process
  • Open an issue and describe the desired feature / bug fix before making changes. It's useful to get a second pair of eyes before investing development effort.
  • Make the change. If adding a new feature, remember to provide tests that demonstrate the new feature works, including any error paths. If contributing a bug fix, add tests that demonstrate the erroneous behavior is fixed.
  • Open a pull request. Automated CI tests will run. If the tests fail, please make changes to fix the behavior, and repeat until the tests pass.
  • Once everything looks good, one of the indeedeng members will review the PR and provide feedback.

Maintainers

The oss.indeed.com/go/libsql module is maintained by Indeed Engineering.

While we are always busy helping people get jobs, we will try to respond to GitHub issues, pull requests, and questions within a couple of business days.

Code of Conduct

oss.indeed.com/go/libsql is governed by theContributer Covenant v1.4.1

For more information please contact opensource@indeed.com.

License

The oss.indeed.com/go/libsql module is open source under the BSD-3-Clause license.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrNoRows = errors.New("no rows, expected 1")

ErrNoRows is returned by ScanOne when a query returns no rows

Functions

func FeedScanner

func FeedScanner(scanner RowScanner, rows ...[]interface{}) error

FeedScanner feeds the rows to scanner. NOTE: Only use this func in tests. Value conversion may differ from the one used in actual SQL execution.

Types

type Database

type Database interface {
	io.Closer

	Queryer
	Preparer

	// Transaction performs work in transaction.
	// Transaction is committed if work returns nil, and rolled back otherwise.
	Transaction(ctx context.Context, work func(Transaction) error) error

	// PrepareStatement prepares a statement for later queries.
	//
	// In addition to preparing a statement on a single connection, the returned
	// PreparedStatement can use other connections from the Database's connection
	// pool re-preparing the statement as needed.
	// PreparedStatement is safe for concurrent use.
	// Refer to sql.Stmt's godoc for details.
	//
	// It is best to use this API for queries that are executed frequently from
	// different contexts. For example, using a PreparedStatement to fetch data
	// served via a service's HTTP API endpoint by many goroutines can reduce
	// the latency considerably.
	// In other scenarios, prefer using the Prepared method: it takes care of
	// closing the Statement and is thus less error-prone.
	//
	// The provided context is used for the preparation of the statement, not
	// for its execution.
	// The caller must call Close on the returned PreparedStatement when it is
	// no longer needed.
	PrepareStatement(ctx context.Context, sql string) (PreparedStatement, error)
}

Database provides fluent database API.

func Wrap

func Wrap(db *sql.DB) Database

Wrap returns a Database wrapping a given *sql.DB.

type PreparedStatement added in v1.1.0

type PreparedStatement interface {
	io.Closer
	Statement
}

PreparedStatement is a Statement that must be closed by the caller

type Preparer

type Preparer interface {
	// Prepared prepares a sql statement and runs work.
	// The prepared statement is always closed when this method returns.
	Prepared(ctx context.Context, sql string, work func(Statement) error) error
}

Preparer prepares a sql statement

type Queryer

type Queryer interface {
	// Scan executes sql and scans result rows with RowScanner
	Scan(ctx context.Context, scanner RowScanner, sql string, args ...interface{}) error

	// ScanOne executes sql and scans the first result row with RowScanner.
	// Returns ErrNoRows if no rows were returned. Remaining rows are discarded
	ScanOne(ctx context.Context, scanner RowScanner, sql string, args ...interface{}) error

	// Update executes sql insert, update, or delete
	Update(ctx context.Context, sql string, args ...interface{}) (sql.Result, error)

	// UpdateAndGetRowsAffected sql insert, update, or delete and returns affected row count
	// Shorthand for Update(...) followed by UpdateResult.RowsAffected
	UpdateAndGetRowsAffected(ctx context.Context, sql string, args ...interface{}) (int64, error)

	// UpdateAndGetLastInsertID sql insert, update, or delete and returns last generated row id.
	// Shorthand for Update(...) followed by UpdateResult.LastInsertId
	UpdateAndGetLastInsertID(ctx context.Context, sql string, args ...interface{}) (int64, error)
}

Queryer performs scans and updates

type RowScanner

type RowScanner interface {
	// Into returns a slice of pointers to scan into.
	// Should always return a slice of same pointers.
	Into() []interface{}

	// RowScanned notifies scanner that a row has been scanned into slice returned by Into()
	RowScanned() error
}

RowScanner scans database rows into arbitrary data structures

func Into

func Into(valuePointers ...interface{}) RowScanner

Into creates a RowScanner that scans values into the passed pointers. Only suitable for scanning single or last row.

type Statement

type Statement interface {
	// Scan executes the prepared statement and scans result rows with RowScanner
	Scan(ctx context.Context, scanner RowScanner, args ...interface{}) error

	// ScanOne executes the prepared statement and scans the first result row with RowScanner.
	// Returns ErrNoRows if no rows were returned. Remaining rows are discarded
	ScanOne(ctx context.Context, scanner RowScanner, args ...interface{}) error

	// Update executes the prepared insert, update, or delete
	Update(ctx context.Context, args ...interface{}) (sql.Result, error)

	// UpdateAndGetRowsAffected the prepared insert, update, or delete and returns affected row count
	// Shorthand for Update(...) followed by UpdateResult.RowsAffected
	UpdateAndGetRowsAffected(ctx context.Context, args ...interface{}) (int64, error)

	// UpdateAndGetLastInsertID the prepared insert, update, or delete and returns last generated row id.
	// Shorthand for Update(...) followed by UpdateResult.LastInsertId
	UpdateAndGetLastInsertID(ctx context.Context, args ...interface{}) (int64, error)
}

Statement is a prepared statement

type Transaction

type Transaction interface {
	Queryer
	Preparer
}

Transaction represents an open transaction

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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