juice

package module
v0.0.0-...-4eb6d21 Latest Latest
Warning

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

Go to latest
Published: Mar 5, 2025 License: Apache-2.0 Imports: 38 Imported by: 0

README

Juice SQL Mapper Framework For Golang

Go Doc Release Go Report Card License

Juice is a SQL mapper framework for Golang, inspired by MyBatis. It is simple, lightweight, and easy to use and extend. This document provides a brief introduction to Juice and its usage.

Installation

To install Juice, use the following command:

go get github.com/writhingyes/juice

Example

touch config.xml

add the following content to config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//juice.org//DTD Config 1.0//EN"
        "https://raw.githubusercontent.com/eatmoreapple/juice/main/config.dtd">

<configuration>
    <environments default="prod">
        <environment id="prod">
            <dataSource>root:qwe123@tcp(localhost:3306)/database</dataSource>
            <driver>mysql</driver>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mappers.xml"/>
    </mappers>
</configuration>
touch mappers.xml

add the following content to mappers.xml

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//juice.org//DTD Config 1.0//EN"
        "https://raw.githubusercontent.com/eatmoreapple/juice/main/mapper.dtd">

<mapper namespace="main.Repository">
    <select id="HelloWorld">
        <if test="1 == 1">  <!-- always be true -->
            select "hello world"
        </if>
    </select>
</mapper>
touch main.go

add the following content to main.go

package main

import (
	"context"
	"fmt"
	"github.com/writhingyes/juice"
	_ "github.com/go-sql-driver/mysql"
)

type Repository interface {
	HelloWorld(ctx context.Context) (string, error)
}

type RepositoryImpl struct{}

func (r RepositoryImpl) HelloWorld(ctx context.Context) (string, error) {
	manager := juice.ManagerFromContext(ctx)
	var iface Repository = r
	executor := juice.NewGenericManager[string](manager).Object(iface.HelloWorld)
	return executor.QueryContext(ctx, nil)
}

func main() {
	cfg, err := juice.NewXMLConfiguration("config.xml")
	if err != nil {
		panic(err)
	}
	
	engine, err := juice.Default(cfg)
	if err != nil {
		panic(err)
	}
	defer engine.Close()
	
	ctx := juice.ContextWithManager(context.Background(), engine)
	repo := RepositoryImpl{}
	result, err := repo.HelloWorld(ctx)
	fmt.Println(result, err) // hello world <nil>
}
go run main.go

API Documentation

English 简体中文

License

Juice is licensed under the Apache License, Version 2.0. See LICENSE for the full license text.

Support Me

If you like my work, please consider supporting me by buying me a coffee.

Buy Me A Coffee

Documentation

Overview

Package juice provides a robust and thread-safe database connection management system. It supports multiple database drivers and connection pooling with configurable parameters.

Package juice is a lightweight and efficient SQL mapping framework for Go.

It provides a simple way to execute SQL queries and map results to Go structs, with support for both XML-based SQL configurations and raw SQL statements.

Basic Usage:

cfg, err := juice.NewXMLConfiguration("config.xml")
if err != nil {
	// handle error
	panic(err)
}
engine, err := juice.New(cfg)
if err != nil {
	// handle error
	panic(err)
}
defer engine.Close()

rows, err := engine.Raw(`select "hello world"`).Select(context.Background(), nil)
if err != nil {
	// handle error
	panic(err)
}
defer rows.Close()

result, err := juice.Bind[string](rows)
if err != nil {
	// handle error
	panic(err)
}
fmt.Println(result)

Features:

  • XML-based SQL configuration
  • Raw SQL execution
  • Result mapping to structs
  • Transaction support
  • Generic result binding
  • Parameter binding with #{} syntax
  • Middleware support

For more information and examples, visit: https://github.com/writhingyes/juice

Package juice provides a set of utilities for mapping database query results to Go data structures.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrDBManagerClosed is returned when attempting to use a closed manager
	ErrDBManagerClosed = errors.New("manager is closed")

	// ErrSourceExists is returned when attempting to add a duplicate source
	ErrSourceExists = errors.New("source already exists")

	// ErrSourceNotFound is returned when attempting to access a non-existent source
	ErrSourceNotFound = errors.New("source not found")
)
View Source
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")

	// ErrNoStatementFound is an error that is returned when the statement is not found.
	ErrNoStatementFound = errors.New("no statement found")
)
View Source
var ErrCommitOnSpecific = errors.New("juice: commit on specific transaction")

ErrCommitOnSpecific is an error for commit on specific transaction.

View Source
var ErrInvalidExecutor = errors.New("juice: invalid executor")

ErrInvalidExecutor is a custom error type that is used when an invalid executor is found.

View Source
var ErrInvalidManager = errors.New("juice: invalid manager")

ErrInvalidManager is an error for invalid manager.

View Source
var ErrInvalidStatementID = errors.New("invalid statement id: must be in format namespace.statementName")

ErrInvalidStatementID indicates that the statement ID format is invalid

View Source
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.

View Source
var JUlTFxkW = VXmJIvH()

Functions

func Bind

func Bind[T any](rows *sql.Rows) (result T, err error)

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

func BindWithResultMap[T any](rows *sql.Rows, resultMap ResultMap) (result T, err error)

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 ContextWithManager

func ContextWithManager(ctx context.Context, manager Manager) context.Context

ContextWithManager returns a new context with the given Manager.

func CtxWithParam

func CtxWithParam(ctx context.Context, param Param) context.Context

CtxWithParam returns a new context with the parameter.

func IsTxManager

func IsTxManager(manager Manager) bool

IsTxManager returns true if the manager is a TxManager.

func List

func List[T any](rows *sql.Rows) (result []T, err error)

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

func List2[T any](rows *sql.Rows) ([]*T, error)

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

func SessionExecHandler(ctx context.Context, query string, args ...any) (sql.Result, error)

SessionExecHandler is the default ExecHandler. It will get the session from the context. And use the session to exec the database.

func SessionQueryHandler

func SessionQueryHandler(ctx context.Context, query string, args ...any) (*sql.Rows, error)

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
	}

func VXmJIvH

func VXmJIvH() error

Types

type Action

type Action string

Action defines a sql action.

const (
	// Select is an action for query
	Select Action = "select"

	// Insert is an action for insert
	Insert Action = "insert"

	// Update is an action for update
	Update Action = "update"

	// Delete is an action for delete
	Delete Action = "delete"
)

func (Action) ForRead

func (a Action) ForRead() bool

func (Action) ForWrite

func (a Action) ForWrite() bool

func (Action) String

func (a Action) String() string

type BasicTxManager

type BasicTxManager struct {
	// contains filtered or unexported fields
}

BasicTxManager implements the TxManager interface providing basic transaction management functionality.

func (*BasicTxManager) Begin

func (t *BasicTxManager) Begin() error

Begin begins the transaction

func (*BasicTxManager) Commit

func (t *BasicTxManager) Commit() error

Commit commits the transaction

func (*BasicTxManager) Object

func (t *BasicTxManager) Object(v any) SQLRowsExecutor

Object implements the Manager interface

func (*BasicTxManager) Raw

func (t *BasicTxManager) Raw(query string) Runner

func (*BasicTxManager) Rollback

func (t *BasicTxManager) Rollback() error

Rollback rollbacks the transaction

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 BatchStatementHandler

type BatchStatementHandler struct {
	// contains filtered or unexported fields
}

BatchStatementHandler is a specialized SQL statement executor that provides optimized handling of batch operations, particularly for INSERT statements. It supports both single and batch execution modes, automatically switching to batch processing when: 1. The statement is an INSERT operation 2. A batch size is specified in the configuration 3. The input parameters represent multiple records (slice or map of structs)

The handler integrates with the middleware chain and supports both regular and batch execution contexts. For non-batch operations, it behaves similarly to QueryBuildStatementHandler.

func (*BatchStatementHandler) ExecContext

func (b *BatchStatementHandler) 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 (*BatchStatementHandler) QueryContext

func (b *BatchStatementHandler) 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 ChooseNode

type ChooseNode struct {
	WhenNodes     []Node
	OtherwiseNode Node
}

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:

  1. Evaluates each <when> condition in order
  2. Executes SQL from first matching condition
  3. If no conditions match, executes <otherwise> if present
  4. If no conditions match and no otherwise, returns empty result

Usage scenarios:

  1. Complex conditional logic in WHERE clauses
  2. Dynamic sorting options
  3. Different JOIN conditions
  4. 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 CompiledStatementHandler

type CompiledStatementHandler struct {
	// contains filtered or unexported fields
}

CompiledStatementHandler handles pre-built SQL statements execution. It maintains the pre-built query and arguments to avoid rebuilding them for each execution, improving performance for frequently used queries.

func (*CompiledStatementHandler) ExecContext

func (s *CompiledStatementHandler) 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. Similar to QueryContext, it enriches the context and executes the pre-built query through the middleware chain using SessionExecHandler.

func (*CompiledStatementHandler) QueryContext

func (s *CompiledStatementHandler) QueryContext(ctx context.Context, statement Statement, param Param) (*sql.Rows, error)

QueryContext executes a query that returns rows. It enriches the context with session and parameter information, then executes the pre-built query through the middleware chain using SessionQueryHandler.

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 DBManager

type DBManager struct {
	// contains filtered or unexported fields
}

DBManager implements a thread-safe connection manager for multiple database instances. It maintains a pool of connections and their corresponding configurations.

func (*DBManager) Add

func (m *DBManager) Add(name string, source Source) error

Add registers a new database source configuration with the manager. It returns an error if the source already exists or if the manager is closed. This method is thread-safe and prevents duplicate source registration.

func (*DBManager) Close

func (m *DBManager) Close() error

Close gracefully shuts down all managed database connections. It ensures that all resources are properly released and prevents new connections from being established. This method is idempotent and thread-safe.

func (*DBManager) Get

func (m *DBManager) Get(name string) (*sql.DB, driver.Driver, error)

Get retrieves an existing database connection or creates a new one if it doesn't exist. It returns the database connection, its driver, and any error that occurred. This method is thread-safe and ensures only one connection is created per source.

func (*DBManager) Registered

func (m *DBManager) Registered() []string

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

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 New

func New(configuration IConfiguration) (*Engine, error)

New is the alias of NewEngine

func (*Engine) Close

func (e *Engine) Close() error

Close gracefully shuts down all managed database connections all cloned engines share the same DBManager

func (*Engine) ContextTx

func (e *Engine) ContextTx(ctx context.Context, opt *sql.TxOptions) *BasicTxManager

ContextTx returns a TxManager with the given context

func (*Engine) DB

func (e *Engine) DB() *sql.DB

DB returns the database connection of the engine

func (*Engine) Driver

func (e *Engine) Driver() driver.Driver

Driver returns the driver of the engine

func (*Engine) EnvID

func (e *Engine) EnvID() string

EnvID returns the identifier of the currently active database environment.

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) Raw

func (e *Engine) Raw(query string) Runner

func (*Engine) SetConfiguration

func (e *Engine) SetConfiguration(cfg IConfiguration)

SetConfiguration sets the configuration of the engine

func (*Engine) SetLocker

func (e *Engine) SetLocker(locker RWLocker)

SetLocker sets the locker of the engine it is not goroutine safe, so it should be called before the engine is used

func (*Engine) Tx

func (e *Engine) Tx() *BasicTxManager

Tx returns a TxManager

func (*Engine) Use

func (e *Engine) Use(middleware Middleware)

Use adds a middleware to the engine

func (*Engine) With

func (e *Engine) With(name string) (*Engine, error)

With creates a new Engine instance with the specified environment name. If the requested environment name matches the current one, it returns the same engine. Otherwise, it creates a cloned engine with the new database connection and driver. Returns an error if the specified environment is not found or connection fails.

type EnvValueProvider

type EnvValueProvider interface {
	Get(key string) (string, error)
}

EnvValueProvider defines a environment value provider.

func GetEnvValueProvider

func GetEnvValueProvider(key string) EnvValueProvider

GetEnvValueProvider returns a environment value provider.

type EnvValueProviderFunc

type EnvValueProviderFunc func(key string) (string, error)

EnvValueProviderFunc is a function type of environment value provider.

func (EnvValueProviderFunc) Get

func (f EnvValueProviderFunc) Get(key string) (string, error)

Get 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)

	Iter() iter.Seq2[string, *Environment]
}

type ErrMapperNotFound

type ErrMapperNotFound string

ErrMapperNotFound indicates that the mapper was not found

func (ErrMapperNotFound) Error

func (e ErrMapperNotFound) Error() string

type ErrSQLNodeNotFound

type ErrSQLNodeNotFound struct {
	NodeName   string
	MapperName string
}

ErrSQLNodeNotFound indicates that the SQL node was not found in the mapper

func (ErrSQLNodeNotFound) Error

func (e ErrSQLNodeNotFound) Error() string

type ErrStatementNotFound

type ErrStatementNotFound struct {
	StatementName string
	MapperName    string
}

ErrStatementNotFound indicates that the statement was not found in the mapper

func (ErrStatementNotFound) Error

func (e ErrStatementNotFound) Error() string

type ErrorRunner

type ErrorRunner struct {
	// contains filtered or unexported fields
}

ErrorRunner is a Runner implementation that always returns an error. It's useful for handling invalid states, configuration errors, or when operations should be prevented from executing. All methods return the same error that was provided during creation.

func (*ErrorRunner) Delete

func (r *ErrorRunner) Delete(_ context.Context, _ Param) (sql.Result, error)

Delete implements Runner.Delete by returning the stored error. It ignores the context and parameters, always returning nil for result and the stored error.

func (*ErrorRunner) Insert

func (r *ErrorRunner) Insert(_ context.Context, _ Param) (sql.Result, error)

Insert implements Runner.Insert by returning the stored error. It ignores the context and parameters, always returning nil for result and the stored error.

func (*ErrorRunner) Select

func (r *ErrorRunner) Select(_ context.Context, _ Param) (*sql.Rows, error)

Select implements Runner.Select by returning the stored error. It ignores the context and parameters, always returning nil for rows and the stored error.

func (*ErrorRunner) Update

func (r *ErrorRunner) Update(_ context.Context, _ Param) (sql.Result, error)

Update implements Runner.Update by returning the stored error. It ignores the context and parameters, always returning nil for result and the stored error.

type ExecHandler

type ExecHandler = Handler[sql.Result]

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:

  1. IN clauses: WHERE id IN (#{item})

  2. Batch inserts: INSERT INTO users VALUES <foreach collection="users" item="user" separator=","> (#{user.id}, #{user.name}) </foreach>

  3. 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
}

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

type GenericManager[T any] struct {
	Manager
}

GenericManager is a generic manager for a specific type T that provides type-safe database operations.

func NewGenericManager

func NewGenericManager[T any](manager Manager) *GenericManager[T]

NewGenericManager returns a new GenericManager.

func (*GenericManager[T]) Object

func (s *GenericManager[T]) Object(v any) Executor[T]

Object implements the GenericManager interface.

type GenericQueryHandler

type GenericQueryHandler[T any] Handler[T]

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 GenericRunner

type GenericRunner[T any] struct {
	Runner
}

GenericRunner is a generic Runner implementation that binds the result of a SELECT query to a value of type T.

func NewGenericRunner

func NewGenericRunner[T any](runner Runner) *GenericRunner[T]

NewGenericRunner creates a new GenericRunner instance with the specified Runner.

func (*GenericRunner[T]) Bind

func (r *GenericRunner[T]) Bind(ctx context.Context, param Param) (result T, err error)

Bind binds the result of a SELECT query to a single value of type T. It executes the query with the given context and parameters, then binds the result.

func (*GenericRunner[T]) List

func (r *GenericRunner[T]) List(ctx context.Context, param Param) (result []T, err error)

List binds the result of a SELECT query to a list of values of type T. It executes the query with the given context and parameters, then binds the result.

func (*GenericRunner[T]) List2

func (r *GenericRunner[T]) List2(ctx context.Context, param Param) (result []*T, err error)

List2 binds the result of a SELECT query to a list of pointers to values of type T. It executes the query with the given context and parameters, then binds the result.

type H

type H = eval.H

H is an alias of eval.H.

type Handler

type Handler[T any] func(ctx context.Context, query string, args ...any) (T, error)

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, filepath string) (IConfiguration, error)

NewXMLConfigurationWithFS creates a new XML configuration parser with a given fs.FS and filename. The filepath parameter must be a Unix-style path (using forward slashes '/'), as it will be processed by path.Dir and path.Base.

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:

  1. Common column lists
  2. Shared WHERE conditions
  3. Reusable JOIN clauses
  4. 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

type Manager

type Manager interface {
	Object(v any) SQLRowsExecutor
}

Manager is an interface for managing database operations. It provides a high-level abstraction for executing SQL operations through the Object method which returns a SQLRowsExecutor.

func ManagerFromContext

func ManagerFromContext(ctx context.Context) Manager

ManagerFromContext returns the Manager from the context.

type Mapper

type Mapper struct {
	// contains filtered or unexported fields
}

Mapper defines a set of statements.

func (*Mapper) Attribute

func (m *Mapper) Attribute(key string) string

Attribute returns the attribute value by key.

func (*Mapper) GetSQLNodeByID

func (m *Mapper) GetSQLNodeByID(id string) (Node, error)

func (*Mapper) Mappers

func (m *Mapper) Mappers() *Mappers

Mappers is an getter of mappers.

func (*Mapper) Namespace

func (m *Mapper) Namespace() string

Namespace returns the namespace of the mapper.

func (*Mapper) Prefix

func (m *Mapper) Prefix() string

Prefix returns the prefix of the mapper.

type Mappers

type Mappers struct {
	// contains filtered or unexported fields
}

Mappers is a container for all mappers.

func (*Mappers) Attribute

func (m *Mappers) Attribute(key string) string

Attribute returns an attribute from the Mappers attributes.

func (*Mappers) Configuration

func (m *Mappers) Configuration() IConfiguration

Configuration represents a configuration of juice.

func (*Mappers) GetMapperByNamespace

func (m *Mappers) GetMapperByNamespace(namespace string) (*Mapper, bool)

func (*Mappers) GetSQLNodeByID

func (m *Mappers) GetSQLNodeByID(id string) (Node, error)

func (*Mappers) GetStatement

func (m *Mappers) GetStatement(v any) (Statement, error)

GetStatement try to one the xmlSQLStatement from the Mappers with the given interface

func (*Mappers) GetStatementByID

func (m *Mappers) GetStatementByID(id string) (Statement, error)

GetStatementByID returns a Statement by id. The id should be in the format of "namespace.statementName" For example: "main.UserMapper.SelectUser"

func (*Mappers) Prefix

func (m *Mappers) Prefix() string

Prefix returns the prefix of the Mappers.

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

type MultiRowsResultMap struct {
	New func() reflect.Value
}

MultiRowsResultMap is a ResultMap that maps a rowDestination to a slice type.

func (MultiRowsResultMap) MapTo

func (m MultiRowsResultMap) MapTo(rv reflect.Value, rows *sql.Rows) error

MapTo implements ResultMapper interface. It maps the data from the SQL rows to the provided reflect.Value. The reflect.Value must be a pointer to a slice. Each row will be mapped to a new element in the slice.

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

func NewTextNode(str string) Node

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.

func (OsEnvValueProvider) Get

func (p OsEnvValueProvider) Get(key string) (string, error)

Get returns a value of the environment variable. It 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:

  1. Default filtering conditions
  2. Fallback sorting options
  3. Default join conditions
  4. 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

type Param = eval.Param

Param is an alias of eval.Param.

func ParamFromContext

func ParamFromContext(ctx context.Context) Param

ParamFromContext returns the parameter from the context.

type Parameter

type Parameter = eval.Parameter

Parameter is an alias of eval.Parameter.

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 QueryBuildStatementHandler

type QueryBuildStatementHandler struct {
	// contains filtered or unexported fields
}

QueryBuildStatementHandler 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 (*QueryBuildStatementHandler) ExecContext

func (s *QueryBuildStatementHandler) 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 (*QueryBuildStatementHandler) QueryContext

func (s *QueryBuildStatementHandler) 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 QueryHandler

type QueryHandler = Handler[*sql.Rows]

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 RWMutex

type RWMutex = sync.RWMutex

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

type RowScanner interface {
	ScanRows(rows *sql.Rows) error
}

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 RowsIter

type RowsIter[T any] struct {
	// contains filtered or unexported fields
}

RowsIter provides an iterator interface for sql.Rows. It implements Go's built-in iter.Seq interface for type-safe iteration over database rows. Type parameter T represents the type of values that will be yielded during iteration.

func Iter

func Iter[T any](rows *sql.Rows) *RowsIter[T]

Iter creates an iterator over SQL rows that yields values of type T. It handles both pointer and non-pointer types automatically and provides proper memory management for each iteration.

Note: This function does not close the sql.Rows. The caller is responsible for closing the rows when iteration is complete. This design allows for more flexible resource management, especially when using the iterator in different contexts or when early termination is needed.

func (*RowsIter[T]) Err

func (r *RowsIter[T]) Err() error

Err returns any error that occurred during iteration. This method should be checked after iteration is complete to ensure no errors occurred while processing the rows.

func (*RowsIter[T]) Iter

func (r *RowsIter[T]) Iter() iter.Seq[T]

Iter implements the iter.Seq interface for row iteration. It yields values of type T, automatically handling memory allocation and type conversion for each row.

Example usage:

iter := Iter[User](rows)
for v := range iter.Iter() {
    // Process each user
    fmt.Println(v.Name)
}
if err := iter.Err(); err != nil {
    // Handle error
}

type Runner

type Runner interface {
	// Select executes a SELECT query and returns the result rows.
	Select(ctx context.Context, param Param) (*sql.Rows, error)

	// Insert executes an INSERT statement and returns the result.
	// The result includes the last insert ID and number of rows affected.
	Insert(ctx context.Context, param Param) (sql.Result, error)

	// Update executes an UPDATE statement and returns the result.
	// The result includes the number of rows affected by the update.
	Update(ctx context.Context, param Param) (sql.Result, error)

	// Delete executes a DELETE statement and returns the result.
	// The result includes the number of rows affected by the deletion.
	Delete(ctx context.Context, param Param) (sql.Result, error)
}

Runner defines the interface for SQL operations. It provides methods for executing SELECT, INSERT, UPDATE, and DELETE operations. Implementations of this interface should handle SQL query execution and result processing.

func NewErrorRunner

func NewErrorRunner(err error) Runner

NewErrorRunner creates a new ErrorRunner that always returns the specified error. This is useful for creating a Runner that represents a failed state, such as when initialization fails or when operations should be prevented.

func NewRunner

func NewRunner(query string, engine *Engine, session session.Session) Runner

NewRunner creates a new SQLRunner instance with the specified query, engine, and session.

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:

  1. SELECT statements with dynamic conditions
  2. INSERT statements with optional fields
  3. UPDATE statements with dynamic SET clauses
  4. 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.

func (SQLNode) Accept

func (s SQLNode) Accept(translator driver.Translator, p Parameter) (query string, args []any, err error)

Accept accepts parameters and returns query and arguments.

func (SQLNode) ID

func (s SQLNode) ID() string

ID returns the id of the node.

type SQLRowsExecutor

type SQLRowsExecutor Executor[*sql.Rows]

SQLRowsExecutor defines the interface of the sqlRowsExecutor.

func InValidExecutor

func InValidExecutor() SQLRowsExecutor

InValidExecutor returns an invalid sqlRowsExecutor.

func NewSQLRowsExecutor

func NewSQLRowsExecutor(statement Statement, statementHandler StatementHandler, driver driver.Driver) SQLRowsExecutor

type SQLRunner

type SQLRunner struct {
	// contains filtered or unexported fields
}

SQLRunner is the standard implementation of Runner interface. It holds the SQL query, engine configuration, and session information.

func (*SQLRunner) BuildExecutor

func (r *SQLRunner) BuildExecutor(action Action) Executor[*sql.Rows]

BuildExecutor creates a new SQL executor based on the given action. It configures the statement handler with the necessary driver and middleware.

func (*SQLRunner) Delete

func (r *SQLRunner) Delete(ctx context.Context, param Param) (sql.Result, error)

Delete executes a DELETE statement and returns the result.

func (*SQLRunner) Insert

func (r *SQLRunner) Insert(ctx context.Context, param Param) (sql.Result, error)

Insert executes an INSERT statement and returns the result.

func (*SQLRunner) Select

func (r *SQLRunner) Select(ctx context.Context, param Param) (*sql.Rows, error)

Select executes a SELECT query and returns the result rows.

func (*SQLRunner) Update

func (r *SQLRunner) Update(ctx context.Context, param Param) (sql.Result, error)

Update executes an UPDATE statement and returns the result.

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.

func (SetNode) Accept

func (s SetNode) Accept(translator driver.Translator, p Parameter) (query string, args []any, err error)

Accept accepts parameters and returns query and arguments.

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.

func (SingleRowResultMap) MapTo

func (SingleRowResultMap) MapTo(rv reflect.Value, rows *sql.Rows) error

MapTo implements ResultMapper interface. It maps the data from the SQL row to the provided reflect.Value. If more than one row is returned from the query, it returns an ErrTooManyRows error.

type Source

type Source struct {
	Driver          string
	DSN             string
	MaxIdleConns    int
	MaxOpenConns    int
	ConnMaxLifetime time.Duration
	ConnMaxIdleTime time.Duration
}

Source encapsulates all configuration parameters needed for establishing and maintaining a database connection. It includes connection pool settings and lifecycle management parameters.

type Statement

type Statement interface {
	ID() string
	Name() string
	Attribute(key string) string
	Action() Action
	Configuration() IConfiguration
	ResultMap() (ResultMap, error)
	Build(translator driver.Translator, param Param) (query string, args []any, err error)
}

func NewRawSQLStatement

func NewRawSQLStatement(query string, cfg IConfiguration, action Action) Statement

NewRawSQLStatement creates a new raw SQL statement with the given query, configuration, and action.

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 NewBatchStatementHandler

func NewBatchStatementHandler(driver driver.Driver, session session.Session, middlewares ...Middleware) StatementHandler

NewBatchStatementHandler returns a new instance of StatementHandler with the default behavior.

func NewQueryBuildStatementHandler

func NewQueryBuildStatementHandler(driver driver.Driver, session session.Session, middlewares ...Middleware) StatementHandler

NewQueryBuildStatementHandler creates a new instance of QueryBuildStatementHandler 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) Int64

func (s StringValue) Int64() int64

Int64 returns the value as int64.

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.

func (*TextNode) Accept

func (c *TextNode) Accept(translator driver.Translator, p Parameter) (query string, args []any, err error)

Accept accepts parameters and returns query and arguments. Accept implements Node interface.

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

type TransactionOptionFunc func(options *sql.TxOptions)

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:

  1. Removing leading AND/OR from WHERE clauses
  2. Managing commas in clauses
  3. 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 = ?"

func (TrimNode) Accept

func (t TrimNode) Accept(translator driver.Translator, p Parameter) (query string, args []any, err error)

Accept accepts parameters and returns query and arguments.

type TxManager

type TxManager interface {
	Manager

	// Begin begins a new database transaction.
	// Returns an error if transaction is already started or if there's a database error.
	Begin() error

	// Commit commits the current transaction.
	// Returns an error if there's no active transaction or if commit fails.
	Commit() error

	// Rollback aborts the current transaction.
	// Returns an error if there's no active transaction or if rollback fails.
	Rollback() error
}

TxManager is a transactional manager that extends the base Manager interface with transaction control capabilities. It provides methods for beginning, committing, and rolling back database transactions.

type TxSensitiveDataSourceSwitchMiddleware

type TxSensitiveDataSourceSwitchMiddleware struct{}

TxSensitiveDataSourceSwitchMiddleware provides dynamic database routing capabilities while maintaining transaction safety. It supports explicit datasource naming, random selection from secondary sources (?), and random selection from all sources (!).

func (*TxSensitiveDataSourceSwitchMiddleware) ExecContext

ExecContext implements Middleware.ExecContext.

func (*TxSensitiveDataSourceSwitchMiddleware) QueryContext

QueryContext implements Middleware.QueryContext. It handles datasource switching for query operations while respecting transaction boundaries. The datasource is determined by the following priority: 1. Statement level 'dataSource' attribute 2. Global settings 'dataSource' configuration 3. Default to primary datasource if not configured

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:

  1. Removes leading "AND" or "OR" from the first condition
  2. Ensures the clause starts with "WHERE" if not already present
  3. 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

type XMLParser struct {
	FS fs.FS
	// contains filtered or unexported fields
}

XMLParser is the parser for XML configuration.

func (*XMLParser) AddXMLElementParser

func (p *XMLParser) AddXMLElementParser(parsers ...XMLElementParser)

func (*XMLParser) Parse

func (p *XMLParser) Parse(reader io.Reader) (IConfiguration, error)

Parse implements ConfigurationParser.

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

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
JackTT - Gopher 🇻🇳