Documentation
¶
Index ¶
- Variables
- func DeleteTest(t *testing.T, dialect sqldialect.Provider, connStr string, ...)
- func ErrorLogger(ctx context.Context, values LogValues)
- func InjectLogger(ctx context.Context, logFn LoggerFn) context.Context
- func InsertTest(t *testing.T, dialect sqldialect.Provider, connStr string, ...)
- func Logger(ctx context.Context, values LogValues)
- func ModifiersTest(t *testing.T, dialect sqldialect.Provider, connStr string, ...)
- func PatchTest(t *testing.T, dialect sqldialect.Provider, connStr string, ...)
- func QueryChunksTest(t *testing.T, dialect sqldialect.Provider, connStr string, ...)
- func QueryOneTest(t *testing.T, dialect sqldialect.Provider, connStr string, ...)
- func QueryTest(t *testing.T, dialect sqldialect.Provider, connStr string, ...)
- func RunTestsForAdapter(t *testing.T, adapterName string, dialect sqldialect.Provider, connStr string, ...)
- func ScanRowsTest(t *testing.T, dialect sqldialect.Provider, connStr string, ...)
- func TransactionTest(t *testing.T, dialect sqldialect.Provider, connStr string, ...)
- type ChunkParser
- type Config
- type DB
- func (c DB) Close() error
- func (c DB) Delete(ctx context.Context, table Table, idOrRecord interface{}) (err error)
- func (c DB) Exec(ctx context.Context, query string, params ...interface{}) (_ Result, err error)
- func (c DB) Insert(ctx context.Context, table Table, record interface{}) (err error)
- func (c DB) Patch(ctx context.Context, table Table, record interface{}) (err error)
- func (c DB) Query(ctx context.Context, records interface{}, query string, params ...interface{}) (err error)
- func (c DB) QueryChunks(ctx context.Context, parser ChunkParser) (err error)
- func (c DB) QueryOne(ctx context.Context, record interface{}, query string, params ...interface{}) (err error)
- func (c DB) Transaction(ctx context.Context, fn func(Provider) error) error
- type DBAdapter
- type LogValues
- type LoggerFn
- type Mock
- func (m Mock) Delete(ctx context.Context, table Table, idOrRecord interface{}) error
- func (m Mock) Exec(ctx context.Context, query string, params ...interface{}) (Result, error)
- func (m Mock) Insert(ctx context.Context, table Table, record interface{}) error
- func (m Mock) Patch(ctx context.Context, table Table, record interface{}) error
- func (m Mock) Query(ctx context.Context, records interface{}, query string, params ...interface{}) error
- func (m Mock) QueryChunks(ctx context.Context, parser ChunkParser) error
- func (m Mock) QueryOne(ctx context.Context, record interface{}, query string, params ...interface{}) error
- func (m Mock) SetFallbackDatabase(db Provider) Mock
- func (m Mock) Transaction(ctx context.Context, fn func(db Provider) error) error
- type MockResult
- type Provider
- type Result
- type Rows
- type ScanArgError
- type Table
- type Tx
- type TxBeginner
Constants ¶
This section is empty.
Variables ¶
var ErrAbortIteration error = fmt.Errorf("ksql: abort iteration, should only be used inside QueryChunks function")
ErrAbortIteration should be used inside the QueryChunks function to inform QueryChunks it should stop querying, close the connection and return with no errors.
var ErrNoValuesToUpdate error = fmt.Errorf("ksql: the input struct contains no values to update")
ErrNoValuesToUpdate informs the error of trying to make an update that would not change any attributes.
This could happen if all the non-ID attributes of the struct are being ignored or if they don't exist.
Since ID attributes are ignored by the Patch() method updating a struct that only have IDs will result in this error. And this error will also occur if the struct does have some non-ID attributes but they are all being ignored.
The reasons that can cause an attribute to be ignored in the Patch() function are: (1) If it is a nil pointer, Patch() will just ignore it. (2) If the attribute is using a modifier that contains the SkipUpdates flag.
var ErrRecordMissingIDs error = fmt.Errorf("ksql: missing required ID fields")
ErrRecordMissingIDs is returned by the Update or Delete functions if an input record does not have all of the IDs described on the input table.
var ErrRecordNotFound error = fmt.Errorf("ksql: the query returned no results: %w", sql.ErrNoRows)
ErrRecordNotFound informs that a given query failed because the record was not found. This error can be returned by the following methods: Patch(), QueryOne() and Delete().
Functions ¶
func DeleteTest ¶ added in v1.4.2
func DeleteTest( t *testing.T, dialect sqldialect.Provider, connStr string, newDBAdapter func(t *testing.T) (DBAdapter, io.Closer), )
DeleteTest runs all tests for making sure the Delete function is working for a given adapter and dialect.
func ErrorLogger ¶ added in v1.9.0
ErrorLogger is a builtin logger that can be passed to ksql.InjectLogger() to only log when an error occurs.
Note that only errors that happen after KSQL sends the query to the backend adapter will be logged. Any errors that happen before that will not be logged.
func InjectLogger ¶ added in v1.9.0
InjectLogger is a debugging tool that allows the user to force KSQL to log the query, query params and error response whenever a query is executed.
Example Usage:
// After injecting a logger into `ctx` all subsequent queries // that use this context will be logged. ctx = ksql.InjectLogger(ctx, ksql.Logger) // All the calls below will cause KSQL to log the queries: var user User db.Insert(ctx, usersTable, &user) user.Name = "NewName" db.Patch(ctx, usersTable, &user) var users []User db.Query(ctx, &users, someQuery, someParams...) db.QueryOne(ctx, &user, someQuery, someParams...) db.Delete(ctx, usersTable, user.ID)
func InsertTest ¶ added in v1.4.2
func InsertTest( t *testing.T, dialect sqldialect.Provider, connStr string, newDBAdapter func(t *testing.T) (DBAdapter, io.Closer), )
InsertTest runs all tests for making sure the Insert function is working for a given adapter and dialect.
func Logger ¶ added in v1.9.0
Logger is a builtin logger that can be passed to ksql.InjectLogger() to log every query and query errors.
Note that only errors that happen after KSQL sends the query to the backend adapter will be logged. Any errors that happen before that will not be logged.
func ModifiersTest ¶ added in v1.4.9
func PatchTest ¶ added in v1.4.8
func PatchTest( t *testing.T, dialect sqldialect.Provider, connStr string, newDBAdapter func(t *testing.T) (DBAdapter, io.Closer), )
PatchTest runs all tests for making sure the Patch function is working for a given adapter and dialect.
func QueryChunksTest ¶ added in v1.4.2
func QueryChunksTest( t *testing.T, dialect sqldialect.Provider, connStr string, newDBAdapter func(t *testing.T) (DBAdapter, io.Closer), )
QueryChunksTest runs all tests for making sure the QueryChunks function is working for a given adapter and dialect.
func QueryOneTest ¶ added in v1.4.2
func QueryOneTest( t *testing.T, dialect sqldialect.Provider, connStr string, newDBAdapter func(t *testing.T) (DBAdapter, io.Closer), )
QueryOneTest runs all tests for making sure the QueryOne function is working for a given adapter and dialect.
func QueryTest ¶ added in v1.4.2
func QueryTest( t *testing.T, dialect sqldialect.Provider, connStr string, newDBAdapter func(t *testing.T) (DBAdapter, io.Closer), )
QueryTest runs all tests for making sure the Query function is working for a given adapter and dialect.
func RunTestsForAdapter ¶ added in v1.4.2
func RunTestsForAdapter( t *testing.T, adapterName string, dialect sqldialect.Provider, connStr string, newDBAdapter func(t *testing.T) (DBAdapter, io.Closer), )
RunTestsForAdapter will run all necessary tests for making sure a given adapter is working as expected.
Optionally it is also possible to run each of these tests separatedly, which might be useful during the development of a new adapter.
Types ¶
type ChunkParser ¶
type ChunkParser struct { // The Query and Params are used together to build a query with // protection from injection, just like when using the Find function. Query string Params []interface{} ChunkSize int // This attribute must be a function with the following signature: // // `func(chunk []<Record>) error`. // // Where the actual Record type should be of a struct // representing the rows you are expecting to receive. ForEachChunk interface{} }
ChunkParser stores the arguments of the QueryChunks function
type Config ¶
type Config struct { // MaxOpenCons defaults to 1 if not set MaxOpenConns int // Used by some adapters (such as kpgx) where nil disables TLS TLSConfig *tls.Config }
Config describes the optional arguments accepted by the `ksql.New()` function.
func (*Config) SetDefaultValues ¶ added in v1.2.0
func (c *Config) SetDefaultValues()
SetDefaultValues should be called by all adapters to set the default config values if unset.
type DB ¶
type DB struct {
// contains filtered or unexported fields
}
DB represents the KSQL client responsible for interfacing with the "database/sql" package implementing the KSQL interface `ksql.Provider`.
func NewWithAdapter ¶
func NewWithAdapter( adapter DBAdapter, dialect sqldialect.Provider, ) (DB, error)
NewWithAdapter allows the user to insert a custom implementation of the DBAdapter interface
func (DB) Delete ¶
Delete deletes one record from the database using the ID or IDs defined on the `ksql.Table` passed as second argument.
For tables with a single ID column you can pass the record to be deleted as a struct, as a map or just pass the ID itself.
For tables with composite keys you must pass the record as a struct or a map so that KSQL can read all the composite keys from it.
The examples below should work for both types of tables:
err := c.Delete(ctx, UsersTable, user) err := c.Delete(ctx, UserPostsTable, map[string]interface{}{ "user_id": user.ID, "post_id": post.ID, })
The example below is shorter but will only work for tables with a single primary key:
err := c.Delete(ctx, UsersTable, user.ID)
func (DB) Insert ¶
Insert one or more instances on the database
If the original instances have been passed by reference the ID is automatically updated after insertion is completed.
func (DB) Patch ¶ added in v1.4.2
Patch applies a partial update (explained below) to the given instance on the database by id.
Partial updates will ignore any nil pointer attributes from the struct, updating only the non nil pointers and non pointer attributes.
func (DB) Query ¶
func (c DB) Query( ctx context.Context, records interface{}, query string, params ...interface{}, ) (err error)
Query queries several rows from the database, the input should be a slice of structs (or *struct) passed by reference and it will be filled with all the results.
Note: it is very important to make sure the query will return a small known number of results, otherwise you risk of overloading the available memory.
func (DB) QueryChunks ¶
func (c DB) QueryChunks( ctx context.Context, parser ChunkParser, ) (err error)
QueryChunks is meant to perform queries that returns more results than would normally fit on memory, for others cases the Query and QueryOne functions are indicated.
The ChunkParser argument has 4 attributes: (1) The Query; (2) The query args; (3) The chunk size; (4) A callback function called ForEachChunk, that will be called to process each chunk loaded from the database.
Note that the signature of the ForEachChunk callback can be any function that receives a slice of structs or a slice of pointers to struct as its only argument and that reflection will be used to instantiate this argument and to fill it with the database rows.
func (DB) QueryOne ¶
func (c DB) QueryOne( ctx context.Context, record interface{}, query string, params ...interface{}, ) (err error)
QueryOne queries one instance from the database, the input struct must be passed by reference and the query should return only one result.
QueryOne returns a ErrRecordNotFound if the query returns no results.
func (DB) Transaction ¶
Transaction encapsulates several queries into a single transaction. All these queries should be made inside the input callback `fn` and they should use the input ksql.Provider.
If the callback returns any errors the transaction will be rolled back, otherwise the transaction will me committed.
If it happens that a second transaction is started inside a transaction callback the same transaction will be reused with no errors.
type DBAdapter ¶
type DBAdapter interface { ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error) QueryContext(ctx context.Context, query string, args ...interface{}) (Rows, error) }
DBAdapter is minimalistic interface to decouple our implementation from database/sql, i.e. if any struct implements the functions below with the exact same semantic as the sql package it will work with KSQL.
To create a new client using this adapter use `ksql.NewWithAdapter()`
type LogValues ¶ added in v1.9.0
LogValues is the argument type of ksql.LoggerFn which contains the data available for logging whenever a query is executed.
func (LogValues) MarshalJSON ¶ added in v1.9.0
type LoggerFn ¶ added in v1.9.0
LoggerFn is a the type of function received as argument of the ksql.InjectLogger function.
type Mock ¶
type Mock struct { InsertFn func(ctx context.Context, table Table, record interface{}) error PatchFn func(ctx context.Context, table Table, record interface{}) error DeleteFn func(ctx context.Context, table Table, idOrRecord interface{}) error QueryFn func(ctx context.Context, records interface{}, query string, params ...interface{}) error QueryOneFn func(ctx context.Context, record interface{}, query string, params ...interface{}) error QueryChunksFn func(ctx context.Context, parser ChunkParser) error ExecFn func(ctx context.Context, query string, params ...interface{}) (Result, error) TransactionFn func(ctx context.Context, fn func(db Provider) error) error }
Mock implements the Provider interface in order to allow users to easily mock the behavior of a ksql.Provider.
To mock a particular method, e.g. Insert, you just need to overwrite the corresponding function attribute whose name is InsertFn().
NOTE: This mock should be instantiated inside each unit test not globally.
For capturing input values use a closure as in the example:
var insertRecord interface{} dbMock := Mock{ InsertFn: func(ctx context.Context, table Table, record interface{}) error { insertRecord = record }, }
NOTE: It is recommended not to make assertions inside the mocked methods, you should only check the captured values afterwards as all tests should have 3 stages: (1) setup, (2) run and finally (3) assert.
For cases where the function will be called several times you might want to capture the number of calls as well as the values passed each time for that use closures and a slice of values, e.g.:
var insertRecords []interface{} dbMock := Mock{ InsertFn: func(ctx context.Context, table Table, record interface{}) error { insertRecords = append(insertRecords, record) }, } expectedNumberOfCalls := 2 assert.Equal(t, expectedNumberOfCalls, len(insertRecords)) expectedInsertedRecords := []interface{}{ user1, user2, } assert.Equal(t, expectedInsertedRecords, insertRecords)
func (Mock) Delete ¶
Delete mocks the behavior of the Delete method. If DeleteFn is set it will just call it returning the same return values. If DeleteFn is unset it will panic with an appropriate error message.
func (Mock) Exec ¶
Exec mocks the behavior of the Exec method. If ExecFn is set it will just call it returning the same return values. If ExecFn is unset it will panic with an appropriate error message.
func (Mock) Insert ¶
Insert mocks the behavior of the Insert method. If InsertFn is set it will just call it returning the same return values. If InsertFn is unset it will panic with an appropriate error message.
func (Mock) Patch ¶ added in v1.4.2
Patch mocks the behavior of the Patch method. If PatchFn is set it will just call it returning the same return values. If PatchFn is unset it will panic with an appropriate error message.
func (Mock) Query ¶
func (m Mock) Query(ctx context.Context, records interface{}, query string, params ...interface{}) error
Query mocks the behavior of the Query method. If QueryFn is set it will just call it returning the same return values. If QueryFn is unset it will panic with an appropriate error message.
func (Mock) QueryChunks ¶
func (m Mock) QueryChunks(ctx context.Context, parser ChunkParser) error
QueryChunks mocks the behavior of the QueryChunks method. If QueryChunksFn is set it will just call it returning the same return values. If QueryChunksFn is unset it will panic with an appropriate error message.
func (Mock) QueryOne ¶
func (m Mock) QueryOne(ctx context.Context, record interface{}, query string, params ...interface{}) error
QueryOne mocks the behavior of the QueryOne method. If QueryOneFn is set it will just call it returning the same return values. If QueryOneFn is unset it will panic with an appropriate error message.
func (Mock) SetFallbackDatabase ¶
SetFallbackDatabase will set all the Fn attributes to use the function from the input database.
SetFallbackDatabase is useful when you only want to overwrite some of the operations, e.g. for testing errors or if you want to use the same setup for making unit tests and integration tests, this way instead of creating a new server with a real database and another with a mocked one you can start the server once and run both types of tests.
Example Usage:
db, err := ksql.New(...) if err != nil { t.Fatal(err.Error()) } mockdb := ksql.Mock{ PatchFn: func(_ context.Context, _ ksql.Table, record interface{}) error { return ksql.ErrRecordNotFound }, }.SetFallbackDatabase(db) // Passing the address to the service so // you can change it for each test myService := myservice.New(..., &mockdb, ...)
func (Mock) Transaction ¶
Transaction mocks the behavior of the Transaction method. If TransactionFn is set it will just call it returning the same return values. If TransactionFn is unset it will just call the input function passing the Mock itself as the database.
type MockResult ¶ added in v1.4.2
type MockResult struct { LastInsertIdFn func() (int64, error) RowsAffectedFn func() (int64, error) }
MockResult implements the Result interface returned by the Exec function
Use the constructor `NewMockResult(42, 42)` for a simpler instantiation of this mock.
But if you want one of the functions to return an error you'll need to specify the desired behavior by overwriting one of the attributes of the struct.
func (MockResult) LastInsertId ¶ added in v1.4.2
func (m MockResult) LastInsertId() (int64, error)
LastInsertId implements the Result interface
func (MockResult) RowsAffected ¶ added in v1.4.2
func (m MockResult) RowsAffected() (int64, error)
RowsAffected implements the Result interface
type Provider ¶
type Provider interface { Insert(ctx context.Context, table Table, record interface{}) error Patch(ctx context.Context, table Table, record interface{}) error Delete(ctx context.Context, table Table, idOrRecord interface{}) error Query(ctx context.Context, records interface{}, query string, params ...interface{}) error QueryOne(ctx context.Context, record interface{}, query string, params ...interface{}) error QueryChunks(ctx context.Context, parser ChunkParser) error Exec(ctx context.Context, query string, params ...interface{}) (Result, error) Transaction(ctx context.Context, fn func(Provider) error) error }
Provider describes the ksql public behavior.
The Insert, Update, Delete and QueryOne functions return ksql.ErrRecordNotFound if no record was found or no rows were changed during the operation.
type Result ¶
Result stores information about the result of an Exec query
func NewMockResult ¶ added in v1.4.2
NewMockResult returns a simple implementation of the Result interface.
type Rows ¶
type Rows interface { Scan(...interface{}) error Close() error Next() bool Err() error Columns() ([]string, error) }
Rows represents the results from a call to Query()
type ScanArgError ¶ added in v1.4.10
ScanArgError is a type of error that is expected to be returned from the Scan() method of the Rows interface.
It should be returned when there is an error scanning one of the input values.
This is necessary in order to allow KSQL to produce a better and more readable error message when this type of error occur.
func (ScanArgError) Error ¶ added in v1.4.10
func (s ScanArgError) Error() string
Error implements the error interface.
func (ScanArgError) ErrorWithStructNames ¶ added in v1.4.10
func (s ScanArgError) ErrorWithStructNames(structName string, colName string) error
type Table ¶
type Table struct {
// contains filtered or unexported fields
}
Table describes the required information for inserting, updating and deleting entities from the database by ID using the 3 helper functions created for that purpose.
func NewTable ¶
NewTable returns a Table instance that stores the tablename and the names of columns used as ID, if no column name is passed it defaults to using the `"id"` column.
This Table is required only for using the helper methods:
- Insert - Patch - Delete
Passing multiple ID columns will be interpreted as a single composite key, if you want to use the helper functions with different keys you'll need to create multiple Table instances for the same database table, each with a different set of ID columns, but this is usually not necessary.
Source Files
¶
Directories
¶
Path | Synopsis |
---|---|
adapters
|
|
kmysql
Module
|
|
kpgx
Module
|
|
kpgx5
Module
|
|
kpostgres
Module
|
|
ksqlite3
Module
|
|
ksqlserver
Module
|
|
modernc-ksqlite
Module
|
|
benchmarks
module
|
|
internal
|
|
This package exposes only the public types and functions for creating new modifiers for KSQL.
|
This package exposes only the public types and functions for creating new modifiers for KSQL. |
Package kstructs is deprecated: use ksqltest instead.
|
Package kstructs is deprecated: use ksqltest instead. |