Documentation
¶
Overview ¶
Package sql contains helper functions that connect a standard Go database/sql object to the GoRADD system.
Most of the functionality in this package is used by database implementations. GoRADD users would not normally directly call functions in this package.
Index ¶
- func GenerateDelete(db DbI, table string, where map[string]any, useOr bool) (sql string, args []any)
- func GenerateInsert(db DbI, table string, fields map[string]any) (sql string, args []any)
- func GenerateSelect(db DbI, table string, fieldNames []string, where map[string]any, ...) (sql string, args []any)
- func GenerateUpdate(db DbI, table string, fields map[string]any, where map[string]any, useOr bool) (sql string, args []any)
- func GenerateVersionLock(db DbI, table string, pkName string, pkValue any, versionName string, ...) (sql string, args []any)
- func GetDataDefLength(description string) (l int, subLen int)
- func NewSqlCursor(rows *sql.Rows, columnTypes []query.ReceiverType, columnNames []string, ...) query.CursorI
- func ReceiveRows(rows *sql.Rows, columnTypes []query.ReceiverType, columnNames []string, ...) (values []map[string]any, err error)
- func RowClose(c io.Closer)
- type Base
- func (h *Base) BuilderQuery(ctx context.Context, builder *Builder) (ret any, err error)
- func (h *Base) CheckLock(ctx context.Context, table string, pkName string, pkValue any, ...) (newLock int64, err error)
- func (h *Base) CreateSchema(ctx context.Context, s schema2.Database) error
- func (h *Base) DbKey() string
- func (h *Base) Delete(ctx context.Context, table string, primaryKey map[string]any, ...) error
- func (h *Base) DeleteWhere(ctx context.Context, table string, where map[string]any) error
- func (h *Base) DestroySchema(ctx context.Context, s schema2.Database) error
- func (h *Base) IsInTransaction(ctx context.Context) (inTx bool)
- func (h *Base) Query(ctx context.Context, table string, fields map[string]ReceiverType, ...) (CursorI, error)
- func (h *Base) SqlDb() *sql.DB
- func (h *Base) SqlExec(ctx context.Context, sql string, args ...interface{}) (r sql.Result, err error)
- func (h *Base) SqlQuery(ctx context.Context, sql string, args ...interface{}) (r *sql.Rows, err error)
- func (h *Base) StartProfiling()
- func (h *Base) StopProfiling()
- func (h *Base) WithSameConnection(ctx context.Context, f func(ctx context.Context) error) (err error)
- func (h *Base) WithTransaction(ctx context.Context, f func(ctx context.Context) error) (err error)
- type DbI
- type SqlReceiver
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GenerateDelete ¶
func GenerateDelete(db DbI, table string, where map[string]any, useOr bool) (sql string, args []any)
GenerateDelete is a helper function for database implementations to generate a delete statement. useOr will determine if the where items are initially ANDed or ORed
func GenerateInsert ¶
GenerateInsert is a helper function for database implementations to generate an insert statement. Pass the quoted table name to quotedTable. Include the schema name here if applicaable.
func GenerateSelect ¶
func GenerateSelect(db DbI, table string, fieldNames []string, where map[string]any, orderBy []string) (sql string, args []any)
GenerateSelect is a helper function for database implementations to generate a select statement.
func GenerateUpdate ¶
func GenerateUpdate(db DbI, table string, fields map[string]any, where map[string]any, useOr bool) (sql string, args []any)
GenerateUpdate is a helper function for database implementations to generate an update statement. useOr will indicate whether to OR or AND the items in the where group. If where has a map[string]any object in it, the items in that map will be OR'd or AND'd opposite to userOr. This is recursive.
func GenerateVersionLock ¶
func GenerateVersionLock(db DbI, table string, pkName string, pkValue any, versionName string, inTransaction bool) (sql string, args []any)
GenerateVersionLock is a helper function for database implementations to implement optimistic locking. It generates the sql that will return the version number of the record, while also doing an exclusive write lock on the row, if a transaction is active. If a transaction is not active, it will simply do a read of the version number.
func GetDataDefLength ¶
GetDataDefLength will extract the length from the definition given a data definition description of the table. Example:
bigint(21) -> 21
varchar(50) -> 50 decimal(10,2) -> 10
func NewSqlCursor ¶
func NewSqlCursor(rows *sql.Rows, columnTypes []query.ReceiverType, columnNames []string, joinTree *jointree.JoinTree, sql string, args []any, ) query.CursorI
NewSqlCursor is a new cursor created from the result of a sql query. columnTypes are the receiver types in the order of the query. columnNames are optional, and if left off, will be taken from the rows value as described in the database. builder is optional, and is used for unpacking joined tables.
func ReceiveRows ¶
func ReceiveRows(rows *sql.Rows, columnTypes []query.ReceiverType, columnNames []string, joinTree *jointree.JoinTree, sql string, args []any, ) (values []map[string]any, err error)
ReceiveRows gets data from a sql result set and returns it as a slice of maps.
Each column is mapped to its column name. If you provide columnNames, those will be used in the map. Otherwise, it will get the column names out of the result set provided.
If joinTree is provided, it will be used to unpack the result into a hierarchy.
Types ¶
type Base ¶
type Base struct {
// contains filtered or unexported fields
}
Base is a mixin for SQL database drivers that implement the standard Go database/sql interface.
func (*Base) BuilderQuery ¶
BuilderQuery performs a complex query using a query builder. The data returned will depend on the command inside the builder. Be sure when using BuilderCommandLoadCursor you close the returned cursor, probably with a defer.
func (*Base) CreateSchema ¶
func (*Base) Delete ¶
func (h *Base) Delete(ctx context.Context, table string, primaryKey map[string]any, optLockFieldName string, optLockFieldValue int64) error
Delete deletes a single record from the database. Care should be exercised when calling this directly, since linked records are not modified in any way. If this record has linked records, the database structure may be corrupted.
func (*Base) DeleteWhere ¶
DeleteWhere deletes the records from the table indicated by the fields in where. If where is empty, all the records will be deleted.
func (*Base) DestroySchema ¶
DestroySchema removes all tables and data from the tables found in the given schema s. Some databases automatically commit transactions during the process, so do not do this inside of a transaction. This operation is not reversible. Circular references on certain databases may fail if the data is not destroyed first.
func (*Base) IsInTransaction ¶
IsInTransaction returns true if the database is in the middle of a transaction.
func (*Base) Query ¶
func (h *Base) Query(ctx context.Context, table string, fields map[string]ReceiverType, where map[string]any, orderBy []string) (CursorI, error)
Query queries table for fields and returns a cursor that can be used to scan the result set. If where is provided, it will limit the result set to rows with fields that match the where values. If orderBy is provided, the result set will be sorted in ascending order by the fields indicated there. The returned cursor must eventually be closed.
func (*Base) SqlExec ¶
func (h *Base) SqlExec(ctx context.Context, sql string, args ...interface{}) (r sql.Result, err error)
SqlExec executes the given SQL code, without returning any result rows.
func (*Base) SqlQuery ¶
func (h *Base) SqlQuery(ctx context.Context, sql string, args ...interface{}) (r *sql.Rows, err error)
SqlQuery executes the given sql, and returns a row result set.
func (*Base) StartProfiling ¶
func (h *Base) StartProfiling()
StartProfiling will start the database profiling process.
func (*Base) StopProfiling ¶
func (h *Base) StopProfiling()
StopProfiling will stop the database profiling process.
func (*Base) WithSameConnection ¶
func (h *Base) WithSameConnection(ctx context.Context, f func(ctx context.Context) error) (err error)
WithSameConnection ensures that all database operations that happen inside the handler use the same database connection session.
The Go SQL driver uses connection pooling. Each separate database operation may happen on a different connection in the pool, even if inside a transaction. However, this breaks some processes on particular databases. For example, in MySQL and SQLite, the process of turning off and on foreign key checks only works within the same connection, so trying to bracket that with some separate calls to the database will not work. The solution is here, to call WithSameConnection, which will pin a connection to the context within f. It is important to not have too many of these calls happening at the same time, or the connection pool may run out, causing subsequent database calls to block until one is freed.
Nested calls will operate on the same connection.
func (*Base) WithTransaction ¶
WithTransaction wraps the function f in a database transaction. While the ORM by default will wrap individual database calls with a timeout, it will not apply this timeout to a transaction. It is up to you to pass a context that has a timeout to prevent the overall transaction from hanging. Nested calls will operate within the same transaction, and the outermost call will determine when the transaction is finally committed.
type DbI ¶
type DbI interface {
// SqlExec executes a query that does not expect to return values.
// It will time out the query if contextTimeout is exceeded
SqlExec(ctx context.Context, sql string, args ...interface{}) (r sql.Result, err error)
// SqlQuery executes a SQL query that returns values.
// It will time out the query if contextTimeout is exceeded
SqlQuery(ctx context.Context, sql string, args ...interface{}) (r *sql.Rows, err error)
// QuoteIdentifier will put quotes around an identifier in a database specific way.
QuoteIdentifier(string) string
// FormatArgument will return the placeholder string for the n'th argument
// in a sql string. Some sqls just use "?" while others identify an argument
// by location, like Postgres's $1, $2, etc.
FormatArgument(n int) string
// SupportsForUpdate will return true if it supports SELECT ... FOR UPDATE clauses for row level locking in a transaction
SupportsForUpdate() bool
// TableDefinitionSql returns the sql that will create table.
TableDefinitionSql(d *schema2.Database, table *schema2.Table) (tableSql string, extraSql []string)
}
The DbI interface describes the interface that a sql database needs to implement so that it will work with the Builder object. If you know a DatabaseI object is a standard Go database/sql database, you can cast it to this type to gain access to the low level SQL driver and send it raw SQL commands.
type SqlReceiver ¶
type SqlReceiver struct {
R interface{}
}
SqlReceiver is an encapsulation of a way of receiving data from sql queries as interface{} pointers. This allows you to get data without knowing the type of data you are asking for ahead of time, and is easier for dealing with NULL fields. Some database drivers (MySql for one) return different results in fields depending on how you call the query (using a prepared statement can return different results than without one), or if the data does not quite fit (UInt64 in particular will return a string if the returned value is bigger than MaxInt64, but smaller than MaxUint64.)
Pass the address of the R member to the sql.Scan method when using an object of this type, because there are some idiosyncrasies with how Go treats return values that prevents returning an address of R from a function
func (SqlReceiver) Unpack ¶
func (r SqlReceiver) Unpack(typ ReceiverType) interface{}
Unpack converts a SqlReceiver to a type corresponding to the given ReceiverType
func (SqlReceiver) UnpackDefaultValue ¶
func (r SqlReceiver) UnpackDefaultValue(typ schema.ColumnType, size int) interface{}
UnpackDefaultValue converts a SqlReceiver used to get the default value to a type corresponding to typ.