Documentation ¶
Overview ¶
Example (TagOverride) ¶
You can override how values are serialized via struct tags. The following tags are available:
string (encoding.TextMarshaler, encoding.TextUnmarshaler), binary (encoding.BinaryMarshaler, encoding.BinaryUnmarshaler, gogoproto.Marshaler, gogoproto.Unmarshaler), json (json.Marshaler, json.Unmarshaler).
package main import ( "context" "fmt" "net" "reflect" "github.com/samsarahq/thunder/internal/testfixtures" "github.com/samsarahq/thunder/sqlgen" uuid "github.com/satori/go.uuid" ) type UUID uuid.UUID func (u UUID) MarshalBinary() ([]byte, error) { return u[:], nil } func (u *UUID) UnmarshalBinary(b []byte) error { copy(u[:], b) return nil } // You can override how values are serialized via struct tags. The following tags are available: // // string (encoding.TextMarshaler, encoding.TextUnmarshaler), binary (encoding.BinaryMarshaler, // encoding.BinaryUnmarshaler, gogoproto.Marshaler, gogoproto.Unmarshaler), json (json.Marshaler, // json.Unmarshaler). func main() { testDb, _ := testfixtures.NewTestDatabase() defer testDb.Close() _, err := testDb.Exec(` CREATE TABLE users ( uuid BINARY(16) PRIMARY KEY, name VARCHAR(255), ip VARCHAR(255), configuration BLOB ) `) if err != nil { panic(err) } ctx := context.TODO() type User struct { UUID UUID `sql:"uuid,primary,binary"` Name string IP net.IP `sql:"ip,string"` Configuration map[string]interface{} `sql:"configuration,json"` } schema := sqlgen.NewSchema() schema.MustRegisterType("users", sqlgen.UniqueId, User{}) db := sqlgen.NewDB(testDb.DB, schema) uuid := uuid.NewV4() initialUser := &User{ UUID: UUID(uuid), // => BINARY (via uuid.MarshalBinary()) Name: "Jean", // => VARCHAR IP: net.IPv4(127, 0, 0, 1), // => VARCHAR (via ip.MarshalText()) Configuration: map[string]interface{}{ // => JSON (via json.Marshal(configuration)) "darkmode": true, }, } _, err = db.InsertRow(ctx, initialUser) if err != nil { panic(err) } user := &User{UUID: UUID(uuid)} err = db.QueryRow(ctx, &user, nil, nil) if err != nil { panic(err) } if reflect.DeepEqual(*user, *initialUser) { fmt.Println("They match!") } }
Output: They match!
Index ¶
- func CopySingletonSlice(result interface{}, rows []interface{}) error
- func CopySlice(result interface{}, rows []interface{}) error
- type BaseSelectQuery
- type Column
- type DB
- func (db *DB) BaseQuery(ctx context.Context, query *BaseSelectQuery) ([]interface{}, error)
- func (db *DB) Count(ctx context.Context, model interface{}, filter Filter) (int64, error)
- func (db *DB) DeleteRow(ctx context.Context, row interface{}) error
- func (db *DB) HasTx(ctx context.Context) bool
- func (db *DB) InsertRow(ctx context.Context, row interface{}) (sql.Result, error)
- func (db *DB) Query(ctx context.Context, result interface{}, filter Filter, options *SelectOptions) error
- func (db *DB) QueryExecer(ctx context.Context) QueryExecer
- func (db *DB) QueryRow(ctx context.Context, result interface{}, filter Filter, options *SelectOptions) error
- func (db *DB) UpdateRow(ctx context.Context, row interface{}) error
- func (db *DB) UpsertRow(ctx context.Context, row interface{}) (sql.Result, error)
- func (db *DB) WithDynamicLimit(dynamicLimit DynamicLimit) (*DB, error)
- func (db *DB) WithExistingTx(ctx context.Context, tx *sql.Tx) (context.Context, error)
- func (db *DB) WithShardLimit(shardLimit Filter) (*DB, error)
- func (db *DB) WithTx(ctx context.Context) (context.Context, *sql.Tx, error)
- type DeleteQuery
- type DynamicLimit
- type DynamicLimitErrorCallback
- type DynamicLimitFilterCallback
- type ErrorWithQuery
- type Filter
- type InsertQuery
- type NullBytes
- type PrimaryKeyType
- type QueryExecer
- type SQLQuery
- type Schema
- func (s *Schema) BuildStruct(tableName string, row []driver.Value) (interface{}, error)
- func (s *Schema) MakeDeleteRow(row interface{}) (*DeleteQuery, error)
- func (s *Schema) MakeInsertRow(row interface{}) (*InsertQuery, error)
- func (s *Schema) MakeSelect(result interface{}, filter Filter, options *SelectOptions) (*BaseSelectQuery, error)
- func (s *Schema) MakeSelectRow(result interface{}, filter Filter, options *SelectOptions) (*BaseSelectQuery, error)
- func (s *Schema) MakeTester(table string, filter Filter) (Tester, error)
- func (s *Schema) MakeUpdateRow(row interface{}) (*UpdateQuery, error)
- func (s *Schema) MakeUpsertRow(row interface{}) (*UpsertQuery, error)
- func (s *Schema) MustRegisterType(table string, primaryKeyType PrimaryKeyType, value interface{})
- func (s *Schema) ParseRows(query *SelectQuery, res *sql.Rows) ([]interface{}, error)
- func (s *Schema) RegisterType(table string, primaryKeyType PrimaryKeyType, value interface{}) error
- func (s *Schema) UnbuildStruct(tableName string, strct interface{}) ([]interface{}, error)
- type SelectOptions
- type SelectQuery
- type SimpleWhere
- type Table
- type Tester
- type UpdateQuery
- type UpsertQuery
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CopySingletonSlice ¶
func CopySingletonSlice(result interface{}, rows []interface{}) error
Types ¶
type BaseSelectQuery ¶
type BaseSelectQuery struct { Table *Table Filter Filter Options *SelectOptions }
func (*BaseSelectQuery) MakeSelectQuery ¶
func (b *BaseSelectQuery) MakeSelectQuery() (*SelectQuery, error)
type DB ¶
DB uses a *sql.DB connection that is established by its owner. DB assumes the database connection exists and is alive at all times during the lifecycle of the object.
func (*DB) BaseQuery ¶
func (db *DB) BaseQuery(ctx context.Context, query *BaseSelectQuery) ([]interface{}, error)
func (*DB) Count ¶ added in v0.5.1
Count counts the number of relevant rows in a database, matching options in filter
model should be a pointer to a struct, for example:
count, err := db.Count(ctx, &User{}, &res, Filter{}) if err != nil { ... }
func (*DB) DeleteRow ¶
DeleteRow deletes a single row from the database, identified by the row's primary key
row should be a pointer to a struct, for example:
user := &User{Id; 10} if err := db.DeleteRow(ctx, user); err != nil {
func (*DB) InsertRow ¶
InsertRow inserts a single row into the database
row should be a pointer to a struct, for example:
user := &User{Name: "foo"} if err := db.InsertRow(ctx, user); err != nil {
func (*DB) Query ¶
func (db *DB) Query(ctx context.Context, result interface{}, filter Filter, options *SelectOptions) error
Query fetches a collection of rows from the database
result should be a pointer to a slice of pointers to structs, for example:
var users []*User if err := db.Query(ctx, &users, nil, nil); err != nil {
func (*DB) QueryExecer ¶
func (db *DB) QueryExecer(ctx context.Context) QueryExecer
func (*DB) QueryRow ¶
func (db *DB) QueryRow(ctx context.Context, result interface{}, filter Filter, options *SelectOptions) error
QueryRow fetches a single row from the database
result should be a pointer to a pointer to a struct, for example:
var user *User if err := db.Query(ctx, &user, Filter{"id": 10}, nil); err != nil {
func (*DB) UpdateRow ¶
UpdateRow updates a single row in the database, identified by the row's primary key
row should be a pointer to a struct, for example:
user := &User{Id; 10, Name: "bar"} if err := db.UpdateRow(ctx, user); err != nil {
func (*DB) UpsertRow ¶
UpsertRow inserts a single row into the database
row should be a pointer to a struct, for example:
user := &User{Name: "foo"} if err := db.UpsertRow(ctx, user); err != nil {
func (*DB) WithDynamicLimit ¶ added in v0.5.1
func (db *DB) WithDynamicLimit(dynamicLimit DynamicLimit) (*DB, error)
WithDynamicLimit is similar to WithShardLimit except that it supports dynamically computing what filter to enforce as a limit, based on a user- provide callback. It may be used together with a shard limit.
func (*DB) WithExistingTx ¶
WithExistingTx returns a derived Context that contains the provided Tx. It is an error to invoke this method on a Context that already contains a transaction for this DB. On error WithExistingTx returns a non-nil Context, so that the caller can still easily use its Context (e.g., to log the error).
func (*DB) WithShardLimit ¶ added in v0.5.1
WithShardLimit scopes the DB to only allow queries with the given key-value pairs. This means any query must include a filter for the key-value pairs in the limit, and any write must have columns including the specified key-value pairs.
func (*DB) WithTx ¶
WithTx begins a transaction and returns a derived Context that contains that transaction. It also returns the transaction value itself, for the caller to manipulate (e.g., Commit). It is an error to invoke this method on a Context that already contains a transaction for this DB. On error WithTx returns a non-nil Context, so that the caller can still easily use its Context (e.g., to log the error).
type DeleteQuery ¶
type DeleteQuery struct { Table string Where *SimpleWhere }
DeleteQuery represents a DELETE query
func (*DeleteQuery) ToSQL ¶
func (q *DeleteQuery) ToSQL() (string, []interface{})
ToSQL builds a parameterized DELETE FROM x WHERE a = ? AND b = ? statement
type DynamicLimit ¶ added in v0.5.1
type DynamicLimit struct { GetLimitFilter DynamicLimitFilterCallback ShouldContinueOnError DynamicLimitErrorCallback }
DynamicLimit is used with WithDynamicLimit to register a dynamic limit on a Thunder DB.
A `DynamicLimit` consists of two callbacks, `GetLimitFilter`, and `ShouldContinueOnError`, both user-defined.
Before making an SQL query, a Thunder DB with a dynamic limit will call `GetLimitFilter` with the request context and the name of the table being queried. It will use the sqlgen filter returned by the function as the limit to check for against the current query. The underlying limit check is the same as that used in `WithShardLimit`.
If the limit check fails, Thunder will call `ShouldContinueOnError` with the resulting error object and the table name. If `ShouldContinueOnError` returns false, the query will fail. Otherwise, if the return value is true Thunder will still execute the query.
type DynamicLimitErrorCallback ¶ added in v0.5.1
type DynamicLimitFilterCallback ¶ added in v0.5.1
type ErrorWithQuery ¶ added in v0.5.1
type ErrorWithQuery struct {
// contains filtered or unexported fields
}
ErrorWithQuery is an error wrapper that includes the clause and arguments of a sqlgen query.
func (*ErrorWithQuery) Error ¶ added in v0.5.1
func (e *ErrorWithQuery) Error() string
func (*ErrorWithQuery) Reason ¶ added in v0.5.1
func (e *ErrorWithQuery) Reason() string
Reason returns a human-readable error message of the clause and args
func (*ErrorWithQuery) Unwrap ¶ added in v0.5.1
func (e *ErrorWithQuery) Unwrap() error
Unwrap returns the error without the clause or arguments.
type InsertQuery ¶
InsertQuery represents a INSERT query
func (*InsertQuery) ToSQL ¶
func (q *InsertQuery) ToSQL() (string, []interface{})
ToSQL builds a parameterized INSERT INTO x (a, b) VALUES (?, ?) statement
type PrimaryKeyType ¶
type PrimaryKeyType int
const ( AutoIncrement PrimaryKeyType = iota UniqueId )
type QueryExecer ¶
type QueryExecer interface { Query(query string, args ...interface{}) (*sql.Rows, error) QueryRow(query string, args ...interface{}) *sql.Row Exec(query string, args ...interface{}) (sql.Result, error) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) }
A QueryExecer is either a *sql.Tx or a *sql.DB.
type Schema ¶
func (*Schema) BuildStruct ¶ added in v0.5.0
BuildStruct scans a row in struct's column order into a struct pointer.
func (*Schema) MakeDeleteRow ¶
func (s *Schema) MakeDeleteRow(row interface{}) (*DeleteQuery, error)
MakeDeleteRow builds a new DeleteQuery to delete row
func (*Schema) MakeInsertRow ¶
func (s *Schema) MakeInsertRow(row interface{}) (*InsertQuery, error)
MakeInsertRow builds a new InsertQuery to insert row
func (*Schema) MakeSelect ¶
func (s *Schema) MakeSelect(result interface{}, filter Filter, options *SelectOptions) (*BaseSelectQuery, error)
func (*Schema) MakeSelectRow ¶
func (s *Schema) MakeSelectRow(result interface{}, filter Filter, options *SelectOptions) (*BaseSelectQuery, error)
func (*Schema) MakeTester ¶
func (*Schema) MakeUpdateRow ¶
func (s *Schema) MakeUpdateRow(row interface{}) (*UpdateQuery, error)
MakeUpdateRow builds a new UpdateQuery to update row
func (*Schema) MakeUpsertRow ¶
func (s *Schema) MakeUpsertRow(row interface{}) (*UpsertQuery, error)
MakeUpsertRow builds a new UpsertQuery to upsqrt row
func (*Schema) MustRegisterType ¶
func (s *Schema) MustRegisterType(table string, primaryKeyType PrimaryKeyType, value interface{})
func (*Schema) ParseRows ¶
func (s *Schema) ParseRows(query *SelectQuery, res *sql.Rows) ([]interface{}, error)
func (*Schema) RegisterType ¶
func (s *Schema) RegisterType(table string, primaryKeyType PrimaryKeyType, value interface{}) error
func (*Schema) UnbuildStruct ¶ added in v0.5.0
UnbuildStruct extracts SQL values from a struct.
type SelectOptions ¶
func (*SelectOptions) IncludeFilter ¶
func (s *SelectOptions) IncludeFilter(table *Table, filter Filter) error
type SelectQuery ¶
type SelectQuery struct { Table string Columns []string Options *SelectOptions }
SelectQuery represents a SELECT query
func (*SelectQuery) ToSQL ¶
func (q *SelectQuery) ToSQL() (string, []interface{})
ToSQL builds a parameterized SELECT a, b, c FROM x ... statement
type SimpleWhere ¶
type SimpleWhere struct { Columns []string Values []interface{} }
SimpleWhere represents a simple WHERE clause
func (*SimpleWhere) ToSQL ¶
func (w *SimpleWhere) ToSQL() (string, []interface{})
ToSQL builds a `a = ? AND b = ?` clause
type UpdateQuery ¶
type UpdateQuery struct { Table string Columns []string Values []interface{} Where *SimpleWhere }
UpdateQuery represents a UPDATE query
func (*UpdateQuery) ToSQL ¶
func (q *UpdateQuery) ToSQL() (string, []interface{})
ToSQL builds a parameterized UPDATE x SET a = ?, b = ? WHERE c = ? statement
type UpsertQuery ¶
UpsertQuery represents a INSERT ... ON DUPLICATE KEY UPDATE query
func (*UpsertQuery) ToSQL ¶
func (q *UpsertQuery) ToSQL() (string, []interface{})
ToSQL builds a parameterized INSERT INTO x (a, b) VALUES (?, ?) statement