Documentation ¶
Overview ¶
Package juice provides a set of utilities for mapping database query results to Go data structures.
Index ¶
- Variables
- func Bind[T any](rows *sql.Rows) (result T, err error)
- func BindWithResultMap[T any](rows *sql.Rows, resultMap ResultMap) (result T, err error)
- func ConnectFromEnv(env *Environment) (*sql.DB, error)
- func ContextWithManager(ctx context.Context, manager Manager) context.Context
- func CtxWithParam(ctx context.Context, param Param) context.Context
- func IsTxManager(manager Manager) bool
- func List[T any](rows *sql.Rows) (result []T, err error)
- func List2[T any](rows *sql.Rows) ([]*T, error)
- func NestedTransaction(ctx context.Context, handler func(ctx context.Context) error, ...) (err error)
- func RegisterEnvValueProvider(name string, provider EnvValueProvider)
- func SessionExecHandler(ctx context.Context, query string, args ...any) (sql.Result, error)
- func SessionQueryHandler(ctx context.Context, query string, args ...any) (*sql.Rows, error)
- func Transaction(ctx context.Context, handler func(ctx context.Context) error, ...) (err error)
- type Action
- type BatchInsertIDGenerateStrategy
- type ChooseNode
- type ColumnDestination
- type ConditionNode
- type Configuration
- type ConfigurationParser
- type DebugMiddleware
- type DecrementalBatchInsertIDStrategy
- type DefaultStatementHandler
- type Engine
- func (e *Engine) CacheTx() TxCacheManager
- func (e *Engine) Close() error
- func (e *Engine) ContextCacheTx(ctx context.Context, opt *sql.TxOptions) TxCacheManager
- func (e *Engine) ContextTx(ctx context.Context, opt *sql.TxOptions) TxManager
- func (e *Engine) DB() *sql.DB
- func (e *Engine) Driver() driver.Driver
- func (e *Engine) GetConfiguration() IConfiguration
- func (e *Engine) Object(v any) SQLRowsExecutor
- func (e *Engine) SetConfiguration(cfg IConfiguration)
- func (e *Engine) SetLocker(locker RWLocker)
- func (e *Engine) Tx() TxManager
- func (e *Engine) Use(middleware Middleware)
- type EnvValueProvider
- type EnvValueProviderFunc
- type Environment
- type EnvironmentProvider
- type ErrMapperNotFound
- type ErrSQLNodeNotFound
- type ErrStatementNotFound
- type ExecHandler
- type Executor
- type ForeachNode
- type GenericExecutor
- type GenericManager
- type GenericQueryHandler
- type H
- type Handler
- type IConfiguration
- type IfNode
- type IncludeNode
- type IncrementalBatchInsertIDStrategy
- type Manager
- type Mapper
- type Mappers
- func (m *Mappers) Attribute(key string) string
- func (m *Mappers) Configuration() IConfiguration
- func (m *Mappers) GetMapperByNamespace(namespace string) (*Mapper, bool)
- func (m *Mappers) GetSQLNodeByID(id string) (Node, error)
- func (m *Mappers) GetStatement(v any) (Statement, error)
- func (m *Mappers) GetStatementByID(id string) (Statement, error)
- func (m *Mappers) Prefix() string
- type Middleware
- type MiddlewareGroup
- type MultiRowsResultMap
- type NoOpRWMutex
- type Node
- type NodeGroup
- type OsEnvValueProvider
- type OtherwiseNode
- type Param
- type Parameter
- type PreparedStatementHandler
- func (s *PreparedStatementHandler) Close() error
- func (s *PreparedStatementHandler) ExecContext(ctx context.Context, statement Statement, param Param) (result sql.Result, err error)
- func (s *PreparedStatementHandler) QueryContext(ctx context.Context, statement Statement, param Param) (*sql.Rows, error)
- type QueryHandler
- type RWLocker
- type RWMutex
- type ResultMap
- type RowScanner
- type SQLNode
- type SQLRowsExecutor
- type SQLRowsStatementHandler
- type SelectFieldAliasNode
- type SetNode
- type SettingProvider
- type SingleRowResultMap
- type Statement
- type StatementHandler
- type StringValue
- type TextNode
- type TimeoutMiddleware
- type TransactionOptionFunc
- type TrimNode
- type TxCacheManager
- type TxManager
- type ValuesNode
- type WhenNode
- type WhereNode
- type XMLElementParser
- type XMLElementParserChain
- type XMLEnvironmentsElementParser
- type XMLMappersElementParser
- type XMLParser
- type XMLSettingsElementParser
Constants ¶
This section is empty.
Variables ¶
var ( // ErrEmptyQuery is an error that is returned when the query is empty. ErrEmptyQuery = errors.New("empty query") // ErrResultMapNotSet is an error that is returned when the result map is not set. ErrResultMapNotSet = errors.New("resultMap not set") // ErrSqlNodeNotFound is an error that is returned when the sql node is not found. // nolint:unused ErrSqlNodeNotFound = errors.New("sql node not found") // ErrNilDestination is an error that is returned when the destination is nil. ErrNilDestination = errors.New("destination can not be nil") // ErrNilRows is an error that is returned when the rows is nil. ErrNilRows = errors.New("rows can not be nil") // ErrPointerRequired is an error that is returned when the destination is not a pointer. ErrPointerRequired = errors.New("destination must be a pointer") )
var CacheKeyFunc cacheKeyFunc = func(stmt Statement, query string, args []any) (string, error) { writer := md5.New() writer.Write([]byte(stmt.ID() + query)) if len(args) > 0 { if err := gob.NewEncoder(writer).Encode(args); err != nil { return "", err } } return hex.EncodeToString(writer.Sum(nil)), nil }
CacheKeyFunc is the function which is used to generate the scopeCache key. default is the md5 of the query and args. reset the CacheKeyFunc variable to change the default behavior.
var ErrCommitOnSpecific = errors.New("juice: commit on specific transaction")
ErrCommitOnSpecific is an error for commit on specific transaction.
var ErrInvalidExecutor = errors.New("juice: invalid executor")
ErrInvalidExecutor is a custom error type that is used when an invalid executor is found.
var ErrInvalidManager = errors.New("juice: invalid manager")
ErrInvalidManager is an error for invalid manager.
var ErrInvalidStatementID = errors.New("invalid statement id: must be in format namespace.statementName")
ErrInvalidStatementID indicates that the statement ID format is invalid
var ErrTooManyRows = errors.New("juice: too many rows in result set")
ErrTooManyRows is returned when the result set has too many rows but excepted only one row.
Functions ¶
func Bind ¶
Bind sql.Rows to given entity with default mapper Example usage of the binder package
Example_bind shows how to use the Bind function:
type User struct { ID int `column:"id"` Name string `column:"name"` } rows, err := db.Query("SELECT id, name FROM users") if err != nil { log.Fatal(err) } defer rows.Close() user, err := Bind[[]User](rows) if err != nil { log.Fatal(err) }
func BindWithResultMap ¶
BindWithResultMap bind sql.Rows to given entity with given ResultMap bind cover sql.Rows to given entity dest can be a pointer to a struct, a pointer to a slice of struct, or a pointer to a slice of any type. rows won't be closed when the function returns.
func ConnectFromEnv ¶
func ConnectFromEnv(env *Environment) (*sql.DB, error)
ConnectFromEnv connects to the database using the environment configuration.
func ContextWithManager ¶
ContextWithManager returns a new context with the given Manager.
func CtxWithParam ¶
CtxWithParam returns a new context with the parameter.
func IsTxManager ¶
IsTxManager returns true if the manager is a TxManager.
func List ¶
List converts sql.Rows to a slice of the given entity type. If there are no rows, it will return an empty slice.
Differences between List and Bind: - List always returns a slice, even if there is only one row. - Bind always returns the entity of the given type.
Bind is more flexible; you can use it to bind a single row to a struct, a slice of structs, or a slice of any type. However, if you are sure that the result will be a slice, you can use List. It could be faster than Bind.
Example_list shows how to use the List function:
type User struct { ID int `column:"id"` Name string `column:"name"` } rows, err := db.Query("SELECT id, name FROM users") if err != nil { log.Fatal(err) } defer rows.Close() users, err := List[User](rows) if err != nil { log.Fatal(err) }
func List2 ¶ added in v1.6.6
List2 converts database query results into a slice of pointers. Unlike List function, List2 returns a slice of pointers []*T instead of a slice of values []T. This is particularly useful when you need to modify slice elements or handle large structs.
func NestedTransaction ¶
func NestedTransaction(ctx context.Context, handler func(ctx context.Context) error, opts ...TransactionOptionFunc) (err error)
NestedTransaction executes a handler function with transaction support. If the manager is a TxManager, it will execute the handler within the existing transaction. Otherwise, it will create a new transaction and execute the handler within the new transaction.
func RegisterEnvValueProvider ¶
func RegisterEnvValueProvider(name string, provider EnvValueProvider)
RegisterEnvValueProvider registers an environment value provider. The key is a name of the provider. The value is a provider. It allows to override the default provider.
func SessionExecHandler ¶
SessionExecHandler is the default ExecHandler. It will get the session from the context. And use the session to exec the database.
func SessionQueryHandler ¶
SessionQueryHandler is the default QueryHandler. It will get the session from the context. And use the session to query the database.
func Transaction ¶
func Transaction(ctx context.Context, handler func(ctx context.Context) error, opts ...TransactionOptionFunc) (err error)
Transaction executes a transaction with the given handler. If the manager is not an instance of Engine, it will return ErrInvalidManager. If the handler returns an error, the transaction will be rolled back. Otherwise, the transaction will be committed. The ctx must should be created by ContextWithManager. For example:
var engine *juice.Engine // ... initialize engine ctx := juice.ContextWithManager(context.Background(), engine) if err := juice.Transaction(ctx, func(ctx context.Context) error { // ... do something return nil }); err != nil { // handle error }
Types ¶
type BatchInsertIDGenerateStrategy ¶
type BatchInsertIDGenerateStrategy interface { // BatchInsertID generates batch insert IDs for the given reflect.Value slice. BatchInsertID(sliceReflectValue reflect.Value) error }
BatchInsertIDGenerateStrategy is an interface that defines a method for generating batch insert IDs.
type ChooseNode ¶
ChooseNode implements a switch-like conditional structure for SQL generation. It evaluates multiple conditions in order and executes the first matching case, with an optional default case (otherwise).
Fields:
- WhenNodes: Ordered list of conditional branches to evaluate
- OtherwiseNode: Default branch if no when conditions match
Example XML:
<choose> <when test="id != 0"> AND id = #{id} </when> <when test='name != ""'> AND name LIKE CONCAT('%', #{name}, '%') </when> <otherwise> AND status = 'ACTIVE' </otherwise> </choose>
Behavior:
- Evaluates each <when> condition in order
- Executes SQL from first matching condition
- If no conditions match, executes <otherwise> if present
- If no conditions match and no otherwise, returns empty result
Usage scenarios:
- Complex conditional logic in WHERE clauses
- Dynamic sorting options
- Different JOIN conditions
- Status-based queries
Example results:
Case 1 (id present): AND id = ? Case 2 (only name present): AND name LIKE ? Case 3 (neither present): AND status = 'ACTIVE'
Note: Similar to a switch statement in programming languages, only the first matching condition is executed.
func (ChooseNode) Accept ¶
func (c ChooseNode) Accept(translator driver.Translator, p Parameter) (query string, args []any, err error)
Accept accepts parameters and returns query and arguments.
type ColumnDestination ¶
type ColumnDestination interface { // Destination returns the destination for the given reflect value and column. Destination(rv reflect.Value, column []string) ([]any, error) }
ColumnDestination is a column destination which can be used to scan a row.
type ConditionNode ¶
type ConditionNode struct { Nodes NodeGroup // contains filtered or unexported fields }
ConditionNode represents a conditional SQL fragment with its evaluation expression and child nodes. It is used to conditionally include or exclude SQL fragments based on runtime parameters.
func (*ConditionNode) Accept ¶
func (c *ConditionNode) Accept(translator driver.Translator, p Parameter) (query string, args []any, err error)
Accept accepts parameters and returns query and arguments. Accept implements Node interface.
func (*ConditionNode) Match ¶
func (c *ConditionNode) Match(p Parameter) (bool, error)
Match evaluates if the condition is true based on the provided parameter. It handles different types of values and converts them to boolean results:
- Bool: returns the boolean value directly
- Integers (signed/unsigned): returns true if non-zero
- Floats: returns true if non-zero
- String: returns true if non-empty
func (*ConditionNode) Parse ¶
func (c *ConditionNode) Parse(test string) (err error)
Parse compiles the given expression string into an evaluable expression. The expression syntax supports various operations like:
- Comparison: ==, !=, >, <, >=, <=
- Logical: &&, ||, !
- Null checks: != null, == null
- Property access: user.age, order.status
Examples:
"id != nil" // Check for non-null "age >= 18" // Numeric comparison "status == "ACTIVE"" // String comparison "user.role == "ADMIN"" // Property access
type Configuration ¶
type Configuration struct {
// contains filtered or unexported fields
}
Configuration is a configuration of juice.
func (Configuration) Environments ¶
func (c Configuration) Environments() EnvironmentProvider
Environments returns the environments.
func (Configuration) GetStatement ¶
func (c Configuration) GetStatement(v any) (Statement, error)
GetStatement returns the xmlSQLStatement of the given value.
func (Configuration) Settings ¶
func (c Configuration) Settings() SettingProvider
Settings returns the settings.
type ConfigurationParser ¶
type ConfigurationParser interface { // Parse parses the configuration from the reader. Parse(reader io.Reader) (IConfiguration, error) }
ConfigurationParser is the interface for parsing configuration.
type DebugMiddleware ¶
type DebugMiddleware struct{}
DebugMiddleware is a middleware that prints the sql xmlSQLStatement and the execution time.
func (*DebugMiddleware) ExecContext ¶
func (m *DebugMiddleware) ExecContext(stmt Statement, next ExecHandler) ExecHandler
ExecContext implements Middleware. ExecContext will print the sql xmlSQLStatement and the execution time.
func (*DebugMiddleware) QueryContext ¶
func (m *DebugMiddleware) QueryContext(stmt Statement, next QueryHandler) QueryHandler
QueryContext implements Middleware. QueryContext will print the sql xmlSQLStatement and the execution time.
type DecrementalBatchInsertIDStrategy ¶
type DecrementalBatchInsertIDStrategy struct { ID int64 // contains filtered or unexported fields }
func (DecrementalBatchInsertIDStrategy) BatchInsertID ¶
func (in DecrementalBatchInsertIDStrategy) BatchInsertID(v reflect.Value) error
type DefaultStatementHandler ¶
type DefaultStatementHandler struct {
// contains filtered or unexported fields
}
DefaultStatementHandler handles the execution of SQL statements in batches. It integrates a driver, middlewares, and a session to manage the execution flow.
func (*DefaultStatementHandler) ExecContext ¶
func (b *DefaultStatementHandler) ExecContext(ctx context.Context, statement Statement, param Param) (result sql.Result, err error)
ExecContext executes a batch of SQL statements within a context. It handles the execution of SQL statements in batches if the action is an Insert and a batch size is specified. If the action is not an Insert or no batch size is specified, it delegates to the execContext method.
func (*DefaultStatementHandler) QueryContext ¶
func (b *DefaultStatementHandler) QueryContext(ctx context.Context, statement Statement, param Param) (*sql.Rows, error)
QueryContext executes a query represented by the Statement object within a context, and returns the resulting rows. It builds the query using the provided Param values, processes the query through any configured middlewares, and then executes it using the associated driver.
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine is the implementation of Manager interface and the core of juice.
func Default ¶
func Default(configuration IConfiguration) (*Engine, error)
Default creates a new Engine with the default middlewares It adds an interceptor to log the statements
func (*Engine) CacheTx ¶
func (e *Engine) CacheTx() TxCacheManager
CacheTx returns a TxCacheManager.
func (*Engine) ContextCacheTx ¶
ContextCacheTx returns a TxCacheManager with the given context.
func (*Engine) GetConfiguration ¶
func (e *Engine) GetConfiguration() IConfiguration
GetConfiguration returns the configuration of the engine
func (*Engine) Object ¶
func (e *Engine) Object(v any) SQLRowsExecutor
Object implements the Manager interface
func (*Engine) SetConfiguration ¶
func (e *Engine) SetConfiguration(cfg IConfiguration)
SetConfiguration sets the configuration of the engine
func (*Engine) SetLocker ¶
SetLocker sets the locker of the engine it is not goroutine safe, so it should be called before the engine is used
func (*Engine) Use ¶
func (e *Engine) Use(middleware Middleware)
Use adds a middleware to the engine
type EnvValueProvider ¶
EnvValueProvider defines a environment value provider.
func GetEnvValueProvider ¶
func GetEnvValueProvider(key string) EnvValueProvider
GetEnvValueProvider returns a environment value provider.
type EnvValueProviderFunc ¶
EnvValueProviderFunc is a function type of environment value provider.
type Environment ¶
type Environment struct { // DataSource is a string in a driver-specific format. DataSource string // Driver is a driver for Driver string // MaxIdleConnNum is a maximum number of idle connections. MaxIdleConnNum int // MaxOpenConnNum is a maximum number of open connections. MaxOpenConnNum int // MaxConnLifetime is a maximum lifetime of a connection. MaxConnLifetime int // MaxIdleConnLifetime is a maximum lifetime of an idle connection. MaxIdleConnLifetime int // contains filtered or unexported fields }
Environment defines a environment. It contains a database connection configuration.
func (*Environment) Attr ¶
func (e *Environment) Attr(key string) string
Attr returns a value of the attribute.
func (*Environment) ID ¶
func (e *Environment) ID() string
ID returns an identifier of the environment.
type EnvironmentProvider ¶
type EnvironmentProvider interface { // Attribute returns a value of the attribute. Attribute(key string) string // Use returns the environment specified by the identifier. Use(id string) (*Environment, error) }
type ErrMapperNotFound ¶
type ErrMapperNotFound string
ErrMapperNotFound indicates that the mapper was not found
func (ErrMapperNotFound) Error ¶
func (e ErrMapperNotFound) Error() string
type ErrSQLNodeNotFound ¶
ErrSQLNodeNotFound indicates that the SQL node was not found in the mapper
func (ErrSQLNodeNotFound) Error ¶
func (e ErrSQLNodeNotFound) Error() string
type ErrStatementNotFound ¶
ErrStatementNotFound indicates that the statement was not found in the mapper
func (ErrStatementNotFound) Error ¶
func (e ErrStatementNotFound) Error() string
type ExecHandler ¶
ExecHandler is a specialized Handler type for execution operations. It is specifically typed to return sql.Result, making it suitable for INSERT, UPDATE, DELETE, or any other operation that modifies data.
type Executor ¶
type Executor[T any] interface { // QueryContext executes the query and returns the direct result. // The args are for any placeholder parameters in the query. QueryContext(ctx context.Context, param Param) (T, error) // ExecContext executes a query without returning any rows. // The args are for any placeholder parameters in the query. ExecContext(ctx context.Context, param Param) (sql.Result, error) // Statement returns the Statement of the current Executor. Statement() Statement // Driver returns the driver of the current Executor. Driver() driver.Driver }
Executor is a generic sqlRowsExecutor.
type ForeachNode ¶
type ForeachNode struct { Collection string Nodes []Node Item string Index string Open string Close string Separator string }
ForeachNode represents a dynamic SQL fragment that iterates over a collection. It's commonly used for IN clauses, batch inserts, or any scenario requiring iteration over a collection of values in SQL generation.
Fields:
- Collection: Expression to get the collection to iterate over
- Nodes: SQL fragments to be repeated for each item
- Item: Variable name for the current item in iteration
- Index: Variable name for the current index (optional)
- Open: String to prepend before the iteration results
- Close: String to append after the iteration results
- Separator: String to insert between iterations
Example XML:
<foreach collection="list" item="item" index="i" open="(" separator="," close=")"> #{item} </foreach>
Usage scenarios:
IN clauses: WHERE id IN (#{item})
Batch inserts: INSERT INTO users VALUES <foreach collection="users" item="user" separator=","> (#{user.id}, #{user.name}) </foreach>
Multiple conditions: <foreach collection="ids" item="id" separator="OR"> id = #{id} </foreach>
Example results:
Input collection: [1, 2, 3] Configuration: open="(", separator=",", close=")" Output: "(1,2,3)"
func (ForeachNode) Accept ¶
func (f ForeachNode) Accept(translator driver.Translator, p Parameter) (query string, args []any, err error)
Accept accepts parameters and returns query and arguments.
type GenericExecutor ¶
type GenericExecutor[T any] struct { SQLRowsExecutor // contains filtered or unexported fields }
GenericExecutor is a generic sqlRowsExecutor.
func (*GenericExecutor[_]) ExecContext ¶
func (e *GenericExecutor[_]) ExecContext(ctx context.Context, p Param) (result sql.Result, err error)
ExecContext executes the query and returns the result.
func (*GenericExecutor[T]) QueryContext ¶
func (e *GenericExecutor[T]) QueryContext(ctx context.Context, p Param) (result T, err error)
QueryContext executes the query and returns the scanner.
type GenericManager ¶
GenericManager is an interface for managing database operations.
func NewGenericManager ¶
func NewGenericManager[T any](manager Manager) GenericManager[T]
NewGenericManager returns a new GenericManager.
type GenericQueryHandler ¶
GenericQueryHandler is a flexible query handler that can return custom result types. It allows for implementing custom result processing logic by specifying the desired return type through the generic parameter T.
Type Parameters:
- T: The custom return type that the handler will produce.
type Handler ¶
Handler defines a generic query handler function that executes database operations. It is a generic type that can handle different types of query results.
Type Parameters:
- T: The return type of the handler function. Can be any type that represents the result of a database operation (e.g., *sql.Rows, sql.Result).
Parameters:
- ctx: Context for handling timeouts, cancellation, and passing values.
- query: The SQL query string to be executed.
- args: Variable number of arguments to be used in the query for parameter binding.
Returns:
- T: The result of the query execution, type depends on the generic parameter T.
- error: Any error that occurred during query execution.
type IConfiguration ¶
type IConfiguration interface { // Environments returns the environments. Environments() EnvironmentProvider // Settings returns the settings. Settings() SettingProvider // GetStatement returns the xmlSQLStatement of the given value. GetStatement(v any) (Statement, error) }
IConfiguration is the interface of configuration.
func NewXMLConfiguration ¶
func NewXMLConfiguration(filename string) (IConfiguration, error)
func NewXMLConfigurationWithFS ¶
func NewXMLConfigurationWithFS(fs fs.FS, filename string) (IConfiguration, error)
NewXMLConfigurationWithFS creates a new Configuration from an XML file.
type IfNode ¶
type IfNode = ConditionNode
IfNode is an alias for ConditionNode, representing a conditional SQL fragment. It evaluates a condition and determines whether its content should be included in the final SQL.
The condition can be based on various types:
- Boolean: direct condition
- Numbers: non-zero values are true
- Strings: non-empty strings are true
Example usage:
<if test="id > 0"> AND id = #{id} </if>
See ConditionNode for detailed behavior of condition evaluation.
type IncludeNode ¶
type IncludeNode struct {
// contains filtered or unexported fields
}
IncludeNode represents a reference to another SQL fragment, enabling SQL reuse. It allows common SQL fragments to be defined once and included in multiple places, promoting code reuse and maintainability.
Fields:
- sqlNode: The referenced SQL fragment node
- mapper: Reference to the parent Mapper for context
- refId: ID of the SQL fragment to include
Example XML:
<!-- Common WHERE clause --> <sql id="userFields"> id, name, age, status </sql> <!-- Using the include --> <select id="getUsers"> SELECT <include refid="userFields"/> FROM users WHERE status = #{status} </select>
Features:
- Enables SQL fragment reuse
- Supports cross-mapper references
- Maintains consistent SQL patterns
- Reduces code duplication
Usage scenarios:
- Common column lists
- Shared WHERE conditions
- Reusable JOIN clauses
- Standard filtering conditions
Note: The refId must reference an existing SQL fragment defined with the <sql> tag. The reference can be within the same mapper or from another mapper if properly configured.
func (*IncludeNode) Accept ¶
func (i *IncludeNode) Accept(translator driver.Translator, p Parameter) (query string, args []any, err error)
Accept accepts parameters and returns query and arguments.
type IncrementalBatchInsertIDStrategy ¶
type IncrementalBatchInsertIDStrategy struct { ID int64 // contains filtered or unexported fields }
func (IncrementalBatchInsertIDStrategy) BatchInsertID ¶
func (in IncrementalBatchInsertIDStrategy) BatchInsertID(v reflect.Value) error
type Manager ¶
type Manager interface {
Object(v any) SQLRowsExecutor
}
Manager is an interface for managing database operations.
func ManagerFromContext ¶
ManagerFromContext returns the Manager from the context.
type Mapper ¶
type Mapper struct {
// contains filtered or unexported fields
}
Mapper defines a set of statements.
type Mappers ¶
type Mappers struct {
// contains filtered or unexported fields
}
Mappers is a container for all mappers.
func (*Mappers) Configuration ¶
func (m *Mappers) Configuration() IConfiguration
Configuration represents a configuration of juice.
func (*Mappers) GetMapperByNamespace ¶
func (*Mappers) GetStatement ¶
GetStatement try to one the xmlSQLStatement from the Mappers with the given interface
func (*Mappers) GetStatementByID ¶
GetStatementByID returns a Statement by id. The id should be in the format of "namespace.statementName" For example: "main.UserMapper.SelectUser"
type Middleware ¶
type Middleware interface { // QueryContext wraps the QueryHandler. QueryContext(stmt Statement, next QueryHandler) QueryHandler // ExecContext wraps the ExecHandler. ExecContext(stmt Statement, next ExecHandler) ExecHandler }
Middleware is a wrapper of QueryHandler and ExecHandler.
type MiddlewareGroup ¶
type MiddlewareGroup []Middleware
MiddlewareGroup is a group of Middleware.
func (MiddlewareGroup) ExecContext ¶
func (m MiddlewareGroup) ExecContext(stmt Statement, next ExecHandler) ExecHandler
ExecContext implements Middleware. Call ExecContext will call all the ExecContext of the middlewares in the group.
func (MiddlewareGroup) QueryContext ¶
func (m MiddlewareGroup) QueryContext(stmt Statement, next QueryHandler) QueryHandler
QueryContext implements Middleware. Call QueryContext will call all the QueryContext of the middlewares in the group.
type MultiRowsResultMap ¶
MultiRowsResultMap is a ResultMap that maps a rowDestination to a slice type.
type NoOpRWMutex ¶
type NoOpRWMutex struct{}
NoOpRWMutex is a no-op implementation of RWLocker.
func (*NoOpRWMutex) Lock ¶
func (l *NoOpRWMutex) Lock()
func (*NoOpRWMutex) RLock ¶
func (l *NoOpRWMutex) RLock()
func (*NoOpRWMutex) RUnlock ¶
func (l *NoOpRWMutex) RUnlock()
func (*NoOpRWMutex) Unlock ¶
func (l *NoOpRWMutex) Unlock()
type Node ¶
type Node interface { // Accept processes the node with given translator and parameters // to produce a SQL fragment and its arguments. Accept(translator driver.Translator, p Parameter) (query string, args []any, err error) }
Node is the fundamental interface for all SQL generation components. It defines the contract for converting dynamic SQL structures into concrete SQL queries with their corresponding parameters.
The Accept method follows the Visitor pattern, allowing different SQL dialects to be supported through the translator parameter.
Parameters:
- translator: Handles dialect-specific SQL translations
- p: Contains parameter values for SQL generation
Returns:
- query: The generated SQL fragment
- args: Slice of arguments for prepared statement
- err: Any error during SQL generation
Implementing types include:
- SQLNode: Complete SQL statements
- WhereNode: WHERE clause handling
- SetNode: SET clause for updates
- IfNode: Conditional inclusion
- ChooseNode: Switch-like conditionals
- ForeachNode: Collection iteration
- TrimNode: String manipulation
- IncludeNode: SQL fragment reuse
Example usage:
query, args, err := node.Accept(mysqlTranslator, params) if err != nil { // handle error } // use query and args with database
Note: Implementations should handle their specific SQL generation logic while maintaining consistency with the overall SQL structure.
func NewTextNode ¶
NewTextNode creates a new text node based on the input string. It returns either a lightweight pureTextNode for static SQL, or a full TextNode for dynamic SQL with placeholders/substitutions.
type NodeGroup ¶
type NodeGroup []Node
NodeGroup wraps multiple nodes into a single node.
func (NodeGroup) Accept ¶
func (g NodeGroup) Accept(translator driver.Translator, p Parameter) (query string, args []any, err error)
Accept processes all nodes in the group and combines their results. The method ensures proper spacing between node outputs and trims any extra whitespace. If the group is empty or no nodes produce output, it returns empty results.
type OsEnvValueProvider ¶
type OsEnvValueProvider struct{}
OsEnvValueProvider is a environment value provider that uses os.Getenv.
type OtherwiseNode ¶
type OtherwiseNode struct {
Nodes NodeGroup
}
OtherwiseNode represents the default branch in a <choose> statement, which executes when none of the <when> conditions are met. It's similar to the 'default' case in a switch statement.
Fields:
- Nodes: Group of nodes containing the default SQL fragments
Example XML:
<choose> <when test="status != nil"> AND status = #{status} </when> <when test="type != nil"> AND type = #{type} </when> <otherwise> AND is_deleted = 0 AND status = 'ACTIVE' </otherwise> </choose>
Behavior:
- Executes only if all <when> conditions are false
- No condition evaluation needed
- Can contain multiple SQL fragments
- Optional within <choose> block
Usage scenarios:
- Default filtering conditions
- Fallback sorting options
- Default join conditions
- Error prevention (ensuring non-empty WHERE clauses)
Example results:
When no conditions match: AND is_deleted = 0 AND status = 'ACTIVE'
Note: Unlike WhenNode, OtherwiseNode doesn't evaluate any conditions. It simply provides default SQL fragments when needed.
func (OtherwiseNode) Accept ¶
func (o OtherwiseNode) Accept(translator driver.Translator, p Parameter) (query string, args []any, err error)
Accept accepts parameters and returns query and arguments.
type Param ¶
Param is an alias of eval.Param.
func ParamFromContext ¶
ParamFromContext returns the parameter from the context.
type PreparedStatementHandler ¶
type PreparedStatementHandler struct {
// contains filtered or unexported fields
}
PreparedStatementHandler implements the StatementHandler interface. It maintains a single prepared statement that can be reused if the query is the same. When a different query is encountered, it closes the existing statement and creates a new one.
func (*PreparedStatementHandler) Close ¶
func (s *PreparedStatementHandler) Close() error
Close closes all prepared statements in the pool and returns any error that occurred during the process. Multiple errors are joined together.
func (*PreparedStatementHandler) ExecContext ¶
func (s *PreparedStatementHandler) ExecContext(ctx context.Context, statement Statement, param Param) (result sql.Result, err error)
ExecContext executes a query that doesn't return rows. It builds the query using the provided Statement and Param, applies middlewares, and executes the prepared statement with the given context.
func (*PreparedStatementHandler) QueryContext ¶
func (s *PreparedStatementHandler) QueryContext(ctx context.Context, statement Statement, param Param) (*sql.Rows, error)
QueryContext executes a query that returns rows. It builds the query using the provided Statement and Param, applies middlewares, and executes the prepared statement with the given context.
type QueryHandler ¶
QueryHandler is a specialized Handler type for query operations that return rows. It is specifically typed to return *sql.Rows, making it suitable for SELECT queries or any operation that returns a result set.
type RWLocker ¶
type RWLocker interface { RLock() RUnlock() Lock() Unlock() }
RWLocker is a interface that can be used to lock、unlock and read lock、read unlock.
type ResultMap ¶
type ResultMap interface { // MapTo maps the data from the SQL row to the provided reflect.Value. MapTo(rv reflect.Value, row *sql.Rows) error }
ResultMap is an interface that defines a method for mapping database query results to Go data structures.
type RowScanner ¶
RowScanner is an interface that provides a custom mechanism for mapping database rows to Go structures. It serves as an extension point in the data binding system, allowing implementers to override the default reflection-based mapping behavior.
When a type implements this interface, the binding system will detect it during the mapping process and delegate the row scanning responsibility to the implementation. This gives complete control over how database values are mapped to the target structure.
Use cases: - Custom mapping logic for complex database schemas or legacy systems - Performance optimization by eliminating reflection overhead - Special data type handling (e.g., JSON, XML, custom database types) - Complex data transformations during the mapping process - Implementation of caching or lazy loading strategies
Example implementation:
func (u *User) ScanRows(rows *sql.Rows) error { return rows.Scan(&u.ID, &u.Name, &u.Email) }
The implementation must ensure proper handling of NULL values and return appropriate errors if the scanning process fails.
type SQLNode ¶
type SQLNode struct {
// contains filtered or unexported fields
}
SQLNode represents a complete SQL statement with its metadata and child nodes. It serves as the root node for a single SQL operation (SELECT, INSERT, UPDATE, DELETE) and manages the entire SQL generation process.
Fields:
- id: Unique identifier for the SQL statement within the mapper
- nodes: Collection of child nodes that form the complete SQL
- mapper: Reference to the parent Mapper for context and configuration
Example XML:
<select id="getUserById"> SELECT * FROM users <where> <if test="id != 0"> id = #{id} </if> </where> </select>
Usage scenarios:
- SELECT statements with dynamic conditions
- INSERT statements with optional fields
- UPDATE statements with dynamic SET clauses
- DELETE statements with complex WHERE conditions
Features:
- Manages complete SQL statement generation
- Handles parameter binding
- Supports dynamic SQL through child nodes
- Maintains connection to mapper context
- Enables statement reuse through ID reference
Note: The id must be unique within its mapper context to allow proper statement lookup and execution.
type SQLRowsExecutor ¶
SQLRowsExecutor defines the interface of the sqlRowsExecutor.
func InValidExecutor ¶
func InValidExecutor() SQLRowsExecutor
InValidExecutor returns an invalid sqlRowsExecutor.
type SQLRowsStatementHandler ¶
type SQLRowsStatementHandler struct {
// contains filtered or unexported fields
}
SQLRowsStatementHandler handles the execution of SQL statements and returns the results in a sql.Rows structure. It integrates a driver, middlewares, and a session to manage the execution flow.
func (*SQLRowsStatementHandler) ExecContext ¶
func (s *SQLRowsStatementHandler) ExecContext(ctx context.Context, statement Statement, param Param) (sql.Result, error)
ExecContext executes a non-query SQL statement (such as INSERT, UPDATE, DELETE) within a context, and returns the result. Similar to QueryContext, it constructs the SQL command, applies middlewares, and executes the command using the driver.
func (*SQLRowsStatementHandler) QueryContext ¶
func (s *SQLRowsStatementHandler) QueryContext(ctx context.Context, statement Statement, param Param) (*sql.Rows, error)
QueryContext executes a query represented by the Statement object within a context, and returns the resulting rows. It builds the query using the provided Param values, processes the query through any configured middlewares, and then executes it using the associated driver.
type SelectFieldAliasNode ¶
type SelectFieldAliasNode []*selectFieldAliasItem
SelectFieldAliasNode is a node of select field alias.
func (SelectFieldAliasNode) Accept ¶
func (s SelectFieldAliasNode) Accept(_ driver.Translator, _ Parameter) (query string, args []any, err error)
Accept accepts parameters and returns query and arguments.
type SetNode ¶
type SetNode struct {
Nodes NodeGroup
}
SetNode represents an SQL SET clause for UPDATE statements. It manages a group of assignment expressions and automatically handles the comma separators and SET prefix.
Features:
- Automatically adds "SET" prefix
- Manages comma separators between assignments
- Handles dynamic assignments based on conditions
Example XML:
<update id="updateUser"> UPDATE users <set> <if test='name != ""'> name = #{name}, </if> <if test="age > 0"> age = #{age}, </if> <if test="status != 0"> status = #{status} </if> </set> WHERE id = #{id} </update>
Example results:
Case 1 (name and age set): UPDATE users SET name = ?, age = ? WHERE id = ? Case 2 (only status set): UPDATE users SET status = ? WHERE id = ?
Note: The node automatically handles trailing commas and ensures proper formatting of the SET clause regardless of which fields are included dynamically.
type SettingProvider ¶
type SettingProvider interface {
Get(name string) StringValue
}
type SingleRowResultMap ¶
type SingleRowResultMap struct{}
SingleRowResultMap is a ResultMap that maps a rowDestination to a non-slice type.
type StatementHandler ¶
type StatementHandler interface { // ExecContext executes a non-query SQL statement (such as INSERT, UPDATE, DELETE) // within a context, and returns the result. It takes a context, a Statement object, // and a Param object as parameters. ExecContext(ctx context.Context, statement Statement, param Param) (sql.Result, error) // QueryContext executes a query SQL statement (such as SELECT) within a context, // and returns the resulting rows. It takes a context, a Statement object, and a // Param object as parameters. QueryContext(ctx context.Context, statement Statement, param Param) (*sql.Rows, error) }
StatementHandler is an interface that defines methods for executing SQL statements. It provides two methods: ExecContext and QueryContext, which are used to execute non-query and query SQL statements respectively.
func NewDefaultStatementHandler ¶
func NewDefaultStatementHandler(driver driver.Driver, session session.Session, middlewares ...Middleware) StatementHandler
NewDefaultStatementHandler returns a new instance of StatementHandler with the default behavior.
func NewSQLRowsStatementHandler ¶
func NewSQLRowsStatementHandler(driver driver.Driver, session session.Session, middlewares ...Middleware) StatementHandler
NewSQLRowsStatementHandler creates a new instance of SQLRowsStatementHandler with the provided driver, session, and an optional list of middlewares. This function is typically used to initialize the handler before executing SQL statements.
type StringValue ¶
type StringValue string
StringValue is a string value which can be converted to other types.
func (StringValue) Bool ¶
func (s StringValue) Bool() bool
Bool returns true if the value is "true".
func (StringValue) Float64 ¶
func (s StringValue) Float64() float64
Float64 returns the value as float64.
func (StringValue) String ¶
func (s StringValue) String() string
String returns the value as string.
func (StringValue) Uint64 ¶
func (s StringValue) Uint64() uint64
Uint64 returns the value as uint64.
func (StringValue) Unmarshaler ¶
func (s StringValue) Unmarshaler(marshaller encoding.TextUnmarshaler) error
Unmarshaler unmarshals the value to given marshaller.
type TextNode ¶
type TextNode struct {
// contains filtered or unexported fields
}
TextNode is a node of text. What is the difference between TextNode and pureTextNode? TextNode is used to replace parameters with placeholders. pureTextNode is used to avoid unnecessary parameter replacement.
type TimeoutMiddleware ¶
type TimeoutMiddleware struct{}
TimeoutMiddleware is a middleware that sets the timeout for the sql xmlSQLStatement.
func (TimeoutMiddleware) ExecContext ¶
func (t TimeoutMiddleware) ExecContext(stmt Statement, next ExecHandler) ExecHandler
ExecContext implements Middleware. ExecContext will set the timeout for the sql xmlSQLStatement.
func (TimeoutMiddleware) QueryContext ¶
func (t TimeoutMiddleware) QueryContext(stmt Statement, next QueryHandler) QueryHandler
QueryContext implements Middleware. QueryContext will set the timeout for the sql xmlSQLStatement.
type TransactionOptionFunc ¶
TransactionOptionFunc is a function to set the transaction options. It is used to set the transaction options for the transaction.
func WithIsolationLevel ¶
func WithIsolationLevel(level sql.IsolationLevel) TransactionOptionFunc
WithIsolationLevel sets the isolation level for the transaction.
func WithReadOnly ¶
func WithReadOnly(readOnly bool) TransactionOptionFunc
WithReadOnly sets the read-only flag for the transaction.
type TrimNode ¶
type TrimNode struct { Nodes NodeGroup Prefix string PrefixOverrides []string Suffix string SuffixOverrides []string }
TrimNode handles SQL fragment cleanup by managing prefixes, suffixes, and their overrides. It's particularly useful for dynamically generated SQL where certain prefixes or suffixes might need to be added or removed based on the context.
Fields:
- Nodes: Group of child nodes containing the SQL fragments
- Prefix: String to prepend to the result if content exists
- PrefixOverrides: Strings to remove if found at the start
- Suffix: String to append to the result if content exists
- SuffixOverrides: Strings to remove if found at the end
Common use cases:
- Removing leading AND/OR from WHERE clauses
- Managing commas in clauses
- Handling dynamic UPDATE SET statements
Example XML:
<trim prefix="WHERE" prefixOverrides="AND|OR"> <if test="id > 0"> AND id = #{id} </if> <if test='name != ""'> AND name = #{name} </if> </trim>
Example Result:
Input: "AND id = ? AND name = ?" Output: "WHERE id = ? AND name = ?"
type TxCacheManager ¶
type TxCacheManager interface { TxManager Cache() cache.ScopeCache }
TxCacheManager defines a transactional scopeCache manager whose scopeCache can be accessed. All queries in the transaction will be cached. scopeCache.Flush() will be called after Commit() or Rollback().
func NewTxCacheManager ¶
func NewTxCacheManager(manager TxManager, cache cache.ScopeCache) TxCacheManager
NewTxCacheManager returns a new TxCacheManager.
type TxManager ¶
type TxManager interface { Manager // Begin begins the transaction. Begin() error // Commit commits the transaction. Commit() error // Rollback rollbacks the transaction. Rollback() error }
TxManager is a transactional mapper sqlRowsExecutor
type ValuesNode ¶
type ValuesNode []*valueItem
ValuesNode is a node of values. only support for insert.
func (ValuesNode) Accept ¶
func (v ValuesNode) Accept(translator driver.Translator, param Parameter) (query string, args []any, err error)
Accept accepts parameters and returns query and arguments.
type WhenNode ¶
type WhenNode = ConditionNode
WhenNode is an alias for ConditionNode, representing a conditional branch within a <choose> statement. It evaluates a condition and executes its content if the condition is true and it's the first matching condition in the choose block.
Behavior:
- Evaluates condition using same rules as ConditionNode
- Only executes if it's the first true condition in choose
- Subsequent true conditions are ignored
Example XML:
<choose> <when test='type == "PREMIUM"'> AND membership_level = 'PREMIUM' </when> <when test='type == "BASIC"'> AND membership_level IN ('BASIC', 'STANDARD') </when> </choose>
Supported conditions:
- Boolean expressions
- Numeric comparisons
- String comparisons
- Null checks
- Property access
Note: Unlike a standalone ConditionNode, WhenNode's execution is controlled by its parent ChooseNode and follows choose-when semantics similar to switch-case statements.
See ConditionNode for detailed condition evaluation rules.
type WhereNode ¶
type WhereNode struct {
Nodes NodeGroup
}
WhereNode represents a SQL WHERE clause and its conditions. It manages a group of condition nodes that form the complete WHERE clause.
func (WhereNode) Accept ¶
func (w WhereNode) Accept(translator driver.Translator, p Parameter) (query string, args []any, err error)
Accept processes the WHERE clause and its conditions. It handles several special cases:
- Removes leading "AND" or "OR" from the first condition
- Ensures the clause starts with "WHERE" if not already present
- Properly handles spacing between conditions
Examples:
Input: "AND id = ?" -> Output: "WHERE id = ?" Input: "OR name = ?" -> Output: "WHERE name = ?" Input: "WHERE age > ?" -> Output: "WHERE age > ?" Input: "status = ?" -> Output: "WHERE status = ?"
type XMLElementParser ¶
type XMLElementParser interface { ParseElement(parser *XMLParser, decoder *xml.Decoder, token xml.StartElement) error MatchElement(token xml.StartElement) bool }
type XMLElementParserChain ¶
type XMLElementParserChain []XMLElementParser
func (XMLElementParserChain) ParseElement ¶
func (xs XMLElementParserChain) ParseElement(parser *XMLParser, decoder *xml.Decoder, token xml.StartElement) error
type XMLEnvironmentsElementParser ¶
type XMLEnvironmentsElementParser struct{}
func (*XMLEnvironmentsElementParser) MatchElement ¶
func (p *XMLEnvironmentsElementParser) MatchElement(token xml.StartElement) bool
func (*XMLEnvironmentsElementParser) ParseElement ¶
func (p *XMLEnvironmentsElementParser) ParseElement(parser *XMLParser, decoder *xml.Decoder, token xml.StartElement) error
type XMLMappersElementParser ¶
type XMLMappersElementParser struct {
// contains filtered or unexported fields
}
func (*XMLMappersElementParser) MatchElement ¶
func (p *XMLMappersElementParser) MatchElement(token xml.StartElement) bool
func (*XMLMappersElementParser) ParseElement ¶
func (p *XMLMappersElementParser) ParseElement(parser *XMLParser, decoder *xml.Decoder, token xml.StartElement) error
type XMLParser ¶
XMLParser is the parser for XML configuration.
func (*XMLParser) AddXMLElementParser ¶
func (p *XMLParser) AddXMLElementParser(parsers ...XMLElementParser)
type XMLSettingsElementParser ¶
type XMLSettingsElementParser struct{}
func (*XMLSettingsElementParser) MatchElement ¶
func (p *XMLSettingsElementParser) MatchElement(token xml.StartElement) bool
func (*XMLSettingsElementParser) ParseElement ¶
func (p *XMLSettingsElementParser) ParseElement(parser *XMLParser, decoder *xml.Decoder, token xml.StartElement) error
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package eval provides a simple lexical analyzer for processing logical expressions.
|
Package eval provides a simple lexical analyzer for processing logical expressions. |
internal
|
|