cydb

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Sep 23, 2025 License: MIT Imports: 31 Imported by: 0

Documentation

Overview

Package cydb provides database operations and SQL parsing utilities.

Index

Constants

View Source
const (
	// MigrationCommentPrefix 迁移注释前缀
	MigrationCommentPrefix = "-- +migrate"
	// MigrationUp 向上迁移标记
	MigrationUp = "Up"
	// MigrationDown 向下迁移标记
	MigrationDown = "Down"
)

迁移注释标记

View Source
const (
	PreRetTypeReturn = iota
	PreRetTypeCallCallback
	PreRetTypeContinue
)
View Source
const (
	ErrCodeConnection   = "CONNECTION_FAILED"
	ErrCodeQuery        = "QUERY_FAILED"
	ErrCodeTransaction  = "TRANSACTION_FAILED"
	ErrCodeConstraint   = "CONSTRAINT_VIOLATION"
	ErrCodeNotFound     = "NOT_FOUND"
	ErrCodeDuplicate    = "DUPLICATE_KEY"
	ErrCodeTimeout      = "TIMEOUT"
	ErrCodeInvalidParam = "INVALID_PARAMETER"
	ErrCodeUnsupported  = "UNSUPPORTED_OPERATION"
)

Common database error codes

View Source
const DefaultBufferSize = 10 * 1024 * 1024

DefaultBufferSize 默认缓冲区大小 (10MB) 可以通过 ReadSQLFileOptions 进行自定义

Variables

View Source
var WithValue = WithLiteral

Functions

func DBLog

func DBLog() *cylog.Logger

func EscapeLikePattern

func EscapeLikePattern(pattern string, t LikePatternType) string

func FormatValue

func FormatValue(v interface{}, colType DBFieldType) (string, error)

Helper function to format values based on their expected type.

func GetDBAndTable

func GetDBAndTable(cli DatabaseClient, name ...string) (string, string)

func GetSupportSqlDialect

func GetSupportSqlDialect() []string

func InMapParam

func InMapParam(ids map[string]struct{}) string

func InParam

func InParam(ids []string) string

func InParam2

func InParam2(ids [][]string) string

func InternalExcute

func InternalExcute(cli DatabaseClient, sql string, arguments ...interface{}) (int64, error)

func InternalNQuery

func InternalNQuery(cli DatabaseClient, sql string, data interface{}) ([]map[string]interface{}, error)

func InternalNQueryOne

func InternalNQueryOne(cli DatabaseClient, sql string, data interface{}) (map[string]interface{}, error)

func InternalQuery

func InternalQuery(cli DatabaseClient, sql string, arguments ...interface{}) ([]map[string]interface{}, error)

func InternalQueryOne

func InternalQueryOne(cli DatabaseClient, sql string, arguments ...interface{}) (map[string]interface{}, error)

func IsMySQLKeyword

func IsMySQLKeyword(word string) bool

func LeafDirs

func LeafDirs(efs *embed.FS) ([]string, error)

func NewSQLParseError

func NewSQLParseError(errorType, message string, lineNum int, lineText string) error

NewSQLParseError 创建一个新的SQL解析错误 提供详细的上下文信息以便于调试

func NormalData

func NormalData(d interface{}) interface{}

func NormalData2

func NormalData2(d interface{}) interface{}

func ReadSQLFile

func ReadSQLFile(r io.Reader, callback FuncSQLStatementCallback, optionFuncs ...func(*ReadSQLFileOptions)) error

ReadSQLFileWithOptions 使用自定义选项从文件中读取 SQL 语句 支持配置缓冲区大小等选项,提供更灵活的控制 使用可变参数函数列表来设置选项,更符合 With 模式的设计理念

func RegisterSqlDialect

func RegisterSqlDialect(dbtype string, sql any)

func TestParseMySQL

func TestParseMySQL()

TestParseMySQL tests the SQL parsing functionality

func WithBufferSize

func WithBufferSize(size int) func(*ReadSQLFileOptions)

WithBufferSize 设置缓冲区大小的选项函数

func WithFilter

func WithFilter(filter []string) func(*ReadSQLFileOptions)

WithFilter 设置 SQL 过滤器的选项函数

func WithMigrationMode

func WithMigrationMode(mode string) func(*ReadSQLFileOptions)

WithMigrationMode 设置迁移模式的选项函数 mode 可以是 "Up"、"Down" 或空字符串(表示不过滤)

func WithPreProcessSqlLine

func WithPreProcessSqlLine(callback FuncPreProcessSqlLine) func(*ReadSQLFileOptions)

WithPreProcessSqlLine 设置预处理 SQL 行的选项函数

func WithTransaction

func WithTransaction[T IRepo](repo T, fn func(repo T) error) error

func WithWordCallback

func WithWordCallback(callback ProcessWordCallback) func(*ReadSQLFileOptions)

WithWordCallback 设置单词回调的选项函数

Types

type ArithExpr

type ArithExpr struct {
	Left  Expression // 左侧表达式
	Right Expression // 右侧表达式
	Op    string     // 运算符(+, -, *, /, %)
	Alias string     // 别名(可选)
}

ArithExpr 表示算术表达式

func (*ArithExpr) GetAlias

func (ae *ArithExpr) GetAlias() string

GetAlias 返回表达式的别名

func (*ArithExpr) GetFields

func (ae *ArithExpr) GetFields() []string

GetFields 返回表达式中涉及的字段名

func (*ArithExpr) SetAlias

func (ae *ArithExpr) SetAlias(alias string) Expression

SetAlias 设置表达式的别名

func (*ArithExpr) ToSQL

func (ae *ArithExpr) ToSQL(dt DatabaseTransformer) (string, error)

ToSQL 将算术表达式转换为SQL字符串

type BuildResult

type BuildResult struct {
	SQL        string   `json:"sql"`         // 生成的SQL语句
	ParamOrder []string `json:"param_order"` // 参数顺序列表(用于维持顺序)
}

BuildResult 查询构建结果,包含命名参数支持

type BuildSql

type BuildSql interface {
	GetFieldsString(dt DatabaseTransformer, skipAS bool) (string, error)
	GetPkFieldsString(dt DatabaseTransformer, skipAS bool) (string, error)
	GetValuesString(dt DatabaseTransformer, all bool) (string, []string, error)
	GetAssignString(dt DatabaseTransformer, all bool) (string, []string, error)
}

type CRUDOperations

type CRUDOperations interface {
	// Insert inserts a single record
	Insert(ctx context.Context, tableName string, data map[string]any) (int64, error)
	// BatchInsert inserts multiple records
	BatchInsert(ctx context.Context, tableName string, data []map[string]any) (int64, error)
	// Update updates records matching the condition
	Update(ctx context.Context, tableName string, data map[string]any, condition map[string]any) (int64, error)
	// Delete deletes records matching the condition
	Delete(ctx context.Context, tableName string, condition map[string]any) (int64, error)
	// Replace replaces a record (upsert operation)
	Replace(ctx context.Context, tableName string, data map[string]any) (int64, error)
}

CRUDOperations provides high-level CRUD operations

type CRUDSqlFuncName

type CRUDSqlFuncName string
const (
	FuncNameGetInsertSql  CRUDSqlFuncName = "GetInsertSql"
	FuncNameGetSelectSql  CRUDSqlFuncName = "GetSelectSql"
	FuncNameGetUpdateSql  CRUDSqlFuncName = "GetUpdateSql"
	FuncNameGetDeleteSql  CRUDSqlFuncName = "GetDeleteSql"
	FuncNameGetReplaceSql CRUDSqlFuncName = "GetReplaceSql"
)

type CaseExpr

type CaseExpr struct {
	Value       Expression       // 用于简单 CASE 表达式的比较值,搜索 CASE 表达式为 nil
	WhenClauses []WhenThenClause // WHEN-THEN 子句列表
	ElseClause  Expression       // ELSE 子句(可选)
	Alias       string           // 别名(可选)
}

CaseExpr 表示 SQL CASE 表达式

func (*CaseExpr) ELSE

func (ce *CaseExpr) ELSE(elseClause Expression) Expression

ELSE 为 CASE 表达式添加 ELSE 子句

func (*CaseExpr) GetFields

func (ce *CaseExpr) GetFields() []string

GetFields 返回表达式中涉及的字段名

func (*CaseExpr) SetAlias

func (ce *CaseExpr) SetAlias(alias string) Expression

SetAlias 设置表达式的别名

func (*CaseExpr) ToSQL

func (ce *CaseExpr) ToSQL(dt DatabaseTransformer) (string, error)

ToSQL 将 CASE 表达式转换为 SQL 字符串

type Condition

type Condition struct {
	Condition string
	Fields    []string
}

type Config

type Config struct {
	Connections []DBConnection `yaml:"connections"`
}

Config is the main configuration struct, holding a list of database connections.

type DBCli

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

func NewDBCli

func NewDBCli(cli IDBOperWrapper, dbtype, key, database, un, pw string) *DBCli

NewDBCli creates a new DBCli instance. This is useful for testing purposes.

func TryConnect

func TryConnect(v *DBConnection) (*DBCli, error)

func (*DBCli) BatchInsert

func (d *DBCli) BatchInsert(tableName string, data []map[string]interface{}, cc ...FuncWithBuilder) (int64, error)

func (*DBCli) BatchReplace

func (d *DBCli) BatchReplace(tableName string, data []map[string]interface{}, cc ...FuncWithBuilder) (int64, error)

func (*DBCli) BatchUpdate

func (d *DBCli) BatchUpdate(tableName string, data []map[string]interface{}, cc ...FuncWithBuilder) (int64, error)

func (*DBCli) BeginX

func (d *DBCli) BeginX() (r *DBCli, err error)

func (*DBCli) Close

func (d *DBCli) Close() error

func (*DBCli) Commit

func (d *DBCli) Commit() error

func (*DBCli) Count

func (d *DBCli) Count(tableName any, data map[string]interface{}, cc ...FuncWithBuilder) (int64, error)

func (*DBCli) DBType

func (d *DBCli) DBType() string

func (*DBCli) Database

func (d *DBCli) Database() string

func (*DBCli) Delete

func (d *DBCli) Delete(tableName any, data map[string]interface{}, cc ...FuncWithBuilder) (int64, error)

func (*DBCli) Excute

func (d *DBCli) Excute(sql string, arguments ...interface{}) (int64, error)

func (*DBCli) Exists

func (d *DBCli) Exists(tableName string, data map[string]interface{}, cc ...FuncWithBuilder) (bool, error)

func (*DBCli) FieldExists

func (d *DBCli) FieldExists(tableName string, fieldName string) (bool, error)

func (*DBCli) First

func (d *DBCli) First(tableName any, data map[string]interface{}, cc ...FuncWithBuilder) (map[string]interface{}, error)

func (*DBCli) Get

func (d *DBCli) Get(dest interface{}, query string, args ...interface{}) error

func (*DBCli) GetDB

func (d *DBCli) GetDB() *sqlx.DB

func (*DBCli) GetDDLSql

func (d *DBCli) GetDDLSql(funcName DDLSqlFuncName, name ...string) (*SqlContent, error)

func (*DBCli) GetPK

func (d *DBCli) GetPK(tableName string) ([]string, error)

func (*DBCli) GetSortedSql

func (d *DBCli) GetSortedSql(funcName SortFuncName, database string, names []string) ([]*SqlContent, error)

func (*DBCli) GetTableColumns

func (d *DBCli) GetTableColumns(tableName string) ([]*DBColumn, error)

func (*DBCli) Insert

func (d *DBCli) Insert(tableName string, data map[string]interface{}, cc ...FuncWithBuilder) (int64, error)

func (*DBCli) IsTableExist

func (d *DBCli) IsTableExist(tableName string) (bool, error)

func (*DBCli) Key

func (d *DBCli) Key() string

func (*DBCli) List

func (d *DBCli) List(tableName any, data map[string]interface{}, cc ...FuncWithBuilder) ([]map[string]interface{}, error)

func (*DBCli) ListWithPage

func (d *DBCli) ListWithPage(tableName any, data map[string]interface{}, pageIndex int, pageSize int, cc ...FuncWithBuilder) ([]map[string]interface{}, int, error)

func (*DBCli) MakeSureDBExists

func (d *DBCli) MakeSureDBExists(dbName string) error

func (*DBCli) NExcute

func (d *DBCli) NExcute(sql string, data interface{}) (int64, error)

func (*DBCli) NQuery

func (d *DBCli) NQuery(sql string, data interface{}) ([]map[string]interface{}, error)

func (*DBCli) NQueryOne

func (d *DBCli) NQueryOne(sql string, data interface{}) (map[string]interface{}, error)

func (*DBCli) PW

func (d *DBCli) PW() string

func (*DBCli) Query

func (d *DBCli) Query(sql string, arguments ...interface{}) ([]map[string]interface{}, error)

func (*DBCli) QueryOne

func (d *DBCli) QueryOne(sql string, args ...interface{}) (map[string]interface{}, error)

func (*DBCli) ReadSQLFile

func (d *DBCli) ReadSQLFile(r io.Reader, callback FuncSQLStatementCallback, options ...func(*ReadSQLFileOptions)) error

readSQLFile reads and returns the content of an SQL file.

func (*DBCli) Replace

func (d *DBCli) Replace(tableName string, data map[string]interface{}, cc ...FuncWithBuilder) (int64, error)

func (*DBCli) Rollback

func (d *DBCli) Rollback() error

func (*DBCli) Select

func (d *DBCli) Select(dest interface{}, query string, args ...interface{}) error

func (*DBCli) TravelData

func (d *DBCli) TravelData(tableName string, data []map[string]interface{}, fn func(*DBCli, *RowData) error) error

func (*DBCli) TravelQuery

func (d *DBCli) TravelQuery(tableName string, selectSQL string, fn func(*DBCli, *RowData) error) error

func (*DBCli) Update

func (d *DBCli) Update(tableName string, data map[string]interface{}, cc ...FuncWithBuilder) (int64, error)

func (*DBCli) Upsert

func (d *DBCli) Upsert(tableName string, data map[string]interface{}, cc ...FuncWithBuilder) (int64, error)

func (*DBCli) WithTransaction

func (d *DBCli) WithTransaction(fn func(tx *DBCli) error) (err error)

type DBColumn

type DBColumn struct {
	Name        string
	DBFieldType DBFieldType
	ColumnKey   string
	OrgDataType string
	Nullable    bool
}

type DBConnection

type DBConnection struct {
	// Key is a unique identifier for the connection (e.g., "primary_db", "log_db").
	Key string `yaml:"key"`
	// Type specifies the database type, e.g., "mysql", "oracle", "sqlite", "postgresql".
	Type string `yaml:"type"`

	// Fields for MySQL, PostgreSQL and Oracle
	Host   string `yaml:"host,omitempty"`
	Port   int    `yaml:"port,omitempty"`
	Un     string `yaml:"un,omitempty"`
	Pw     string `yaml:"pw,omitempty"`
	DBName string `yaml:"dbname,omitempty"`

	// Fields for Oracle
	Service string `yaml:"service,omitempty"`
	Role    string `yaml:"role,omitempty"`

	// Field for SQLite
	Path string `yaml:"path,omitempty"`

	// Fields for PostgreSQL
	SSLMode string `yaml:"sslmode,omitempty"` // disable, require, verify-ca, verify-full
	Schema  string `yaml:"schema,omitempty"`  // default schema (search_path)
}

DBConnection is a universal struct for any database connection. It includes fields for MySQL, Oracle, PostgreSQL, and SQLite.

type DBFieldType

type DBFieldType int
const (
	DBFieldTypeString DBFieldType = iota
	DBFieldTypeInt
	DBFieldTypeFloat
	DBFieldTypeTime
	DBFieldTypeBinary
	DBFieldTypeJson
	DBFieldTypeBit
)

type DBMgr

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

func NewSqlMgr

func NewSqlMgr(conf *Config, migrateFileFunc ...MigrateFileFunc) (*DBMgr, error)

func (*DBMgr) CloseAll

func (s *DBMgr) CloseAll()

func (*DBMgr) GetCli

func (s *DBMgr) GetCli(key string) *DBCli

func (*DBMgr) GetOrCreateCli

func (s *DBMgr) GetOrCreateCli(params map[string]interface{}) (*DBCli, error)

func (*DBMgr) InitByConfig

func (s *DBMgr) InitByConfig(conf *Config) error

func (*DBMgr) SetCli

func (s *DBMgr) SetCli(key string, cli *DBCli)

type DDLSqlFunc

type DDLSqlFunc func(cli DatabaseClient, name ...string) (*SqlContent, error)

type DDLSqlFuncName

type DDLSqlFuncName string
const (
	FuncNameGetCreateTableSql     DDLSqlFuncName = "GetCreateTableSql"
	FuncNameGetCreateViewSql      DDLSqlFuncName = "GetCreateViewSql"
	FuncNameGetCreateProcedureSql DDLSqlFuncName = "GetCreateProcedureSql"
	FuncNameGetCreateFunctionSql  DDLSqlFuncName = "GetCreateFunctionSql"
	FuncNameGetTableEventSql      DDLSqlFuncName = "GetTableEventSql"
	FuncNameGetBeginSql           DDLSqlFuncName = "GetBeginSql"
	FuncNameGetEndSql             DDLSqlFuncName = "GetEndSql"
)

type DatabaseClient

type DatabaseClient interface {
	// Basic metadata
	DBType() string
	Database() string

	// Core functionality that exists in current DBCli
	Query(sql string, args ...interface{}) ([]map[string]interface{}, error)
	Select(dest interface{}, query string, args ...interface{}) error
	Get(dest interface{}, query string, args ...interface{}) error
	Excute(sql string, arguments ...interface{}) (int64, error)

	// Connection management
	Close() error

	// Legacy compatibility
	PW() string
	NQuery(sql string, data any) ([]map[string]any, error)
	NQueryOne(sql string, data any) (map[string]any, error)
}

DatabaseClient represents the main database client interface This is a minimal interface that existing DBCli can implement

type DatabaseError

type DatabaseError struct {
	Code    string `json:"code"`
	Message string `json:"message"`
	Details string `json:"details,omitempty"`
	Cause   error  `json:"-"`
}

DatabaseError represents a database-specific error with error codes

func NewDatabaseError

func NewDatabaseError(code, message string) *DatabaseError

NewDatabaseError creates a new DatabaseError

func (*DatabaseError) Error

func (e *DatabaseError) Error() string

func (*DatabaseError) Unwrap

func (e *DatabaseError) Unwrap() error

func (*DatabaseError) WithCause

func (e *DatabaseError) WithCause(cause error) *DatabaseError

WithCause adds the underlying cause

func (*DatabaseError) WithDetails

func (e *DatabaseError) WithDetails(details string) *DatabaseError

WithDetails adds details to the error

type DatabaseManager

type DatabaseManager interface {
	// GetClient returns a database client by key
	GetClient(key string) (DatabaseClient, error)
	// AddClient adds a new database client
	AddClient(key string, client DatabaseClient)
	// RemoveClient removes a database client
	RemoveClient(key string)
	// CloseAll closes all database connections
	CloseAll() error
	// ListClients returns all client keys
	ListClients() []string
}

DatabaseManager manages multiple database connections

type DatabaseMetadata

type DatabaseMetadata interface {
	// Type returns the database type (mysql, oracle, sqlite, etc.)
	Type() string
	// Name returns the database name
	Name() string
	// Version returns the database version (if available)
	Version(ctx context.Context) (string, error)
}

DatabaseMetadata provides database metadata information

type DatabaseTransformer

type DatabaseTransformer interface {
	EscapeTableName(tableName string) string
	EscapeColumnName(columnName string) string
	BuildPagination(limit, offset string) string
	SupportsBatch() bool

	BuildReplaceSQL(tableName string, buildSql BuildSql) (string, []string, error)
	BuildUpsertSQL(tableName string, buildSql BuildSql) (string, []string, error)
}

func GetSqlTransformer

func GetSqlTransformer(dbtype string) (DatabaseTransformer, bool)

type DefaultDBFieldType

type DefaultDBFieldType int
const (
	DefaultDBFieldTypeString DefaultDBFieldType = iota
	DefaultDBFieldTypeInt
	DefaultDBFieldTypeFloat
	DefaultDBFieldTypeBool
	DefaultDBFieldTypeTime
	DefaultDBFieldTypeBinary
	DefaultDBFieldTypeJson
	DefaultDBFieldTypeBit
)

type Expression

type Expression interface {
	ToSQL(dt DatabaseTransformer) (string, error)
	GetFields() []string
	SetAlias(alias string) Expression
}

Expression 表示SQL表达式接口

func ADD

func ADD(left, right Expression) Expression

ADD 创建加法表达式

func AS

func AS(v ...string) Expression

func AVG

func AVG(arg Expression) Expression

AVG 创建 AVG 函数表达式

func CASE

func CASE(value Expression, whenThenPairs ...Expression) Expression

CASE 创建简单 CASE 表达式

func CASE_WHEN

func CASE_WHEN(whenThenPairs ...Expression) Expression

CASE_WHEN 创建搜索 CASE 表达式

func COALESCE

func COALESCE(args ...Expression) Expression

COALESCE 创建 COALESCE 函数表达式

func CONCAT

func CONCAT(args ...Expression) Expression

CONCAT 创建 CONCAT 函数表达式

func CONST

func CONST(value any) Expression

CONST 创建常量表达式

func COUNT

func COUNT(arg Expression) Expression

COUNT 创建 COUNT 函数表达式

func COUNT_DISTINCT

func COUNT_DISTINCT(arg Expression) Expression

COUNT_DISTINCT 创建 COUNT(DISTINCT ...) 函数表达式

func DIV

func DIV(left, right Expression) Expression

DIV 创建除法表达式

func FIELD

func FIELD(name string) Expression

FIELD 创建字段表达式

func FUNC

func FUNC(name string, args ...Expression) Expression

FUNC 创建函数调用表达式

func FUNC_DISTINCT

func FUNC_DISTINCT(name string, args ...Expression) Expression

FUNC_DISTINCT 创建带 DISTINCT 的函数调用表达式

func IFNULL

func IFNULL(arg1, arg2 Expression) Expression

IFNULL 创建 IFNULL 函数表达式

func MAX

func MAX(arg Expression) Expression

MAX 创建 MAX 函数表达式

func MIN

func MIN(arg Expression) Expression

MIN 创建 MIN 函数表达式

func MOD

func MOD(left, right Expression) Expression

MOD 创建取模表达式

func MUL

func MUL(left, right Expression) Expression

MUL 创建乘法表达式

func SUB

func SUB(left, right Expression) Expression

SUB 创建减法表达式

func SUM

func SUM(arg Expression) Expression

SUM 创建 SUM 函数表达式

type ExtraData

type ExtraData interface {
	IsBlockEnd(string) bool
}

ExtraData 定义了额外数据的接口 用于在解析过程中存储特定于方言的额外信息

type FieldData

type FieldData struct {
	Name        string
	Type        DBFieldType
	OrgDataType string
	Data        interface{}
	IsPK        bool
	IsUQ        bool
	Nullable    bool
	Index       int
}

type FuncExpr

type FuncExpr struct {
	Name     string       // 函数名称,如 SUM, COUNT, MAX 等
	Args     []Expression // 函数参数
	Distinct bool         // 是否使用 DISTINCT
	Alias    string       // 别名(可选)
}

FuncExpr 表示函数调用表达式

func (*FuncExpr) GetAlias

func (fe *FuncExpr) GetAlias() string

GetAlias 返回表达式的别名

func (*FuncExpr) GetFields

func (fe *FuncExpr) GetFields() []string

GetFields 返回表达式中涉及的字段名

func (*FuncExpr) SetAlias

func (fe *FuncExpr) SetAlias(alias string) Expression

SetAlias 设置表达式的别名

func (*FuncExpr) ToSQL

func (fe *FuncExpr) ToSQL(dt DatabaseTransformer) (string, error)

ToSQL 将函数表达式转换为SQL字符串

type FuncPreProcessSqlLine

type FuncPreProcessSqlLine func(ctx *ParseContext, pline *string) (PreRetType, error)

type FuncSQLStatementCallback

type FuncSQLStatementCallback func(sqlStatement *SQLStatement) error

type FuncWithBuilder

type FuncWithBuilder func(SQLBuilder) SQLBuilder

func WithBetween

func WithBetween(field string, start, end any) FuncWithBuilder

func WithCount

func WithCount(field string) FuncWithBuilder

func WithDatabase

func WithDatabase(database string) FuncWithBuilder

func WithDistinct

func WithDistinct(distinct bool) FuncWithBuilder

func WithEQ

func WithEQ(field ...string) FuncWithBuilder

func WithFields

func WithFields(fields any, reset ...bool) FuncWithBuilder

func WithGT

func WithGT(field ...string) FuncWithBuilder

func WithGTE

func WithGTE(field ...string) FuncWithBuilder

func WithGroupBy

func WithGroupBy(columns any) FuncWithBuilder

func WithIn

func WithIn(field string, values []any) FuncWithBuilder

func WithInnerJoin

func WithInnerJoin(tableSrc TableSource, on ...Where) FuncWithBuilder

func WithJoin

func WithJoin(tableSrc TableSource, on ...Where) FuncWithBuilder

func WithLT

func WithLT(field ...string) FuncWithBuilder

func WithLTE

func WithLTE(field ...string) FuncWithBuilder

func WithLeftJoin

func WithLeftJoin(tableSrc TableSource, on ...Where) FuncWithBuilder

func WithLike

func WithLike(field string, value string) FuncWithBuilder

func WithLikeL

func WithLikeL(field string, value string) FuncWithBuilder

func WithLikeR

func WithLikeR(field string, value string) FuncWithBuilder

func WithLimit

func WithLimit(limit int) FuncWithBuilder

func WithNEQ

func WithNEQ(field ...string) FuncWithBuilder

func WithNotIn

func WithNotIn(field string, values []any) FuncWithBuilder

func WithOffset

func WithOffset(offset int) FuncWithBuilder

func WithOrderBy

func WithOrderBy(orderBy ...OrderBy) FuncWithBuilder

func WithRightJoin

func WithRightJoin(tableSrc TableSource, on ...Where) FuncWithBuilder

func WithSelect

func WithSelect(selects any) FuncWithBuilder

func WithSubQueryValues

func WithSubQueryValues(builder SQLBuilder) FuncWithBuilder

func WithTable

func WithTable(table any) FuncWithBuilder

func WithUpdate

func WithUpdate(columns any) FuncWithBuilder

func WithUpdateExpr

func WithUpdateExpr(updates ...Expression) FuncWithBuilder

func WithValues

func WithValues(data ...[]Expression) FuncWithBuilder

func WithValuesAppend

func WithValuesAppend(data ...[]Expression) FuncWithBuilder

func WithWhere

func WithWhere(where ...Where) FuncWithBuilder

func WithWhereAnd

func WithWhereAnd(where ...Where) FuncWithBuilder

func WithWhereOr

func WithWhereOr(where ...Where) FuncWithBuilder

type IDBOperWrapper

type IDBOperWrapper interface {
	BindNamed(query string, arg interface{}) (string, []interface{}, error)
	Exec(query string, args ...any) (sql.Result, error)
	ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
	Get(dest interface{}, query string, args ...interface{}) error
	GetContext(ctx context.Context, dest interface{}, query string, args ...interface{}) error
	MustExec(query string, args ...interface{}) sql.Result
	MustExecContext(ctx context.Context, query string, args ...interface{}) sql.Result
	NamedExec(query string, arg interface{}) (sql.Result, error)
	NamedExecContext(ctx context.Context, query string, arg interface{}) (sql.Result, error)
	NamedQuery(query string, arg interface{}) (*sqlx.Rows, error)
	Prepare(query string) (*sql.Stmt, error)
	PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
	PrepareNamed(query string) (*sqlx.NamedStmt, error)
	PrepareNamedContext(ctx context.Context, query string) (*sqlx.NamedStmt, error)
	Preparex(query string) (*sqlx.Stmt, error)
	PreparexContext(ctx context.Context, query string) (*sqlx.Stmt, error)
	Query(query string, args ...any) (*sql.Rows, error)
	QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
	QueryRow(query string, args ...any) *sql.Row
	QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
	QueryRowx(query string, args ...interface{}) *sqlx.Row
	QueryRowxContext(ctx context.Context, query string, args ...interface{}) *sqlx.Row
	Queryx(query string, args ...interface{}) (*sqlx.Rows, error)
	QueryxContext(ctx context.Context, query string, args ...interface{}) (*sqlx.Rows, error)
	Select(dest interface{}, query string, args ...interface{}) error
	SelectContext(ctx context.Context, dest interface{}, query string, args ...interface{}) error
}

type IRepo

type IRepo interface {
	GetDBCli() *DBCli
	SetDBCli(*DBCli)
}

type LikePatternType

type LikePatternType int

LikePatternType defines the type of pattern matching for a LIKE query.

const (
	// None does not add any wildcards.
	None LikePatternType = iota
	// Escape
	Escape
	// Contains matches if the pattern is anywhere in the string (e.g. %pattern%).
	Contains
	// StartsWith matches if the string starts with the pattern (e.g. pattern%).
	StartsWith
	// EndsWith matches if the string ends with the pattern (e.g. %pattern).
	EndsWith
)

type LiteralValue

type LiteralValue struct {
	Value  any  // 实际值
	Embed  bool // 是否直接嵌入
	Fields []string
}

LiteralValue 表示直接嵌入的值

func (*LiteralValue) GetFields

func (lv *LiteralValue) GetFields() []string

func (*LiteralValue) GetValue

func (lv *LiteralValue) GetValue() (string, error)

func (*LiteralValue) SetAlias

func (lv *LiteralValue) SetAlias(alias string) Expression

func (*LiteralValue) ToSQL

func (lv *LiteralValue) ToSQL(dt DatabaseTransformer) (string, error)

type MigrateFileFunc

type MigrateFileFunc func(pm *MigrateSQLParam) *MigrateSQLParam

func WithIgnoreError

func WithIgnoreError(ignoreError bool) MigrateFileFunc

func WithMigrateFileFunc

func WithMigrateFileFunc(f *embed.FS) MigrateFileFunc

func WithServiceOwner

func WithServiceOwner(serviceOwner string) MigrateFileFunc

type MigrateInfo

type MigrateInfo struct {
	Key    string
	DBType string
}

type MigrateSQLParam

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

type OP

type OP string
const (
	// 比较运算符
	OP_EQ          OP = "="
	OP_NEQ         OP = "!="
	OP_GT          OP = ">"
	OP_GTE         OP = ">="
	OP_LT          OP = "<"
	OP_LTE         OP = "<="
	OP_LIKE        OP = "LIKE"
	OP_IN          OP = "IN"
	OP_NOT_IN      OP = "NOT IN"
	OP_IS_NULL     OP = "IS NULL"
	OP_IS_NOT_NULL OP = "IS NOT NULL"
	OP_BETWEEN     OP = "BETWEEN"
	OP_EXISTS      OP = "EXISTS"
	OP_NOT_EXISTS  OP = "NOT EXISTS"

	// 算术运算符
	OP_ADD      OP = "+"
	OP_SUBTRACT OP = "-"
	OP_MULTIPLY OP = "*"
	OP_DIVIDE   OP = "/"
	OP_MOD      OP = "%"
)

type OrderBy

type OrderBy struct {
	Column    []Expression
	Direction string // ASC, DESC
}

func ASC

func ASC(field any) OrderBy

func DESC

func DESC(field any) OrderBy

type PARAMS

type PARAMS = map[string]interface{}

type ParameterValue

type ParameterValue struct {
	Name string // 参数名
}

func (*ParameterValue) GetFields

func (pv *ParameterValue) GetFields() []string

func (*ParameterValue) GetValue

func (pv *ParameterValue) GetValue() (string, error)

func (*ParameterValue) SetAlias

func (pv *ParameterValue) SetAlias(alias string) Expression

func (*ParameterValue) ToSQL

type ParseContext

type ParseContext struct {
	// CurrentStmt 当前正在构建的 SQL 语句
	CurrentStmt strings.Builder
	// StartLineNum 当前语句的起始行号
	StartLineNum int
	// CurrentLineNum 当前处理的行号
	CurrentLineNum int
	// LineContent 当前行的内容
	LineContent string
	// HasContent 标记当前是否有内容正在处理
	HasContent bool
	// BlockIndex 块索引,用于标识 SQL 语句块
	BlockIndex int
	// CurrentType 当前 SQL 语句的类型
	CurrentType SQLType
	// TypeWord 类型关键字
	TypeWord string
	// TraceWord 用于跟踪关键字
	TraceWord *TraceWord
	// ExpectedStringEnd 期望的字符串结束标记
	ExpectedStringEnd string
	// IsMultiLineComment 是否在多行注释中
	IsMultiLineComment bool
	// Filter SQL 过滤器
	Filter []string
	// Extra 额外的特定于方言的数据
	Extra ExtraData
	// WordCallback 处理单词的回调函数
	WordCallback ProcessWordCallback
	// PreProcessSqlLine 预处理 SQL 行的回调函数
	PreProcessSqlLine FuncPreProcessSqlLine
}

ParseContext 用于解析 SQL 文件的上下文结构体 存储解析过程中的状态和中间结果

func (*ParseContext) IsBlockEnd

func (pc *ParseContext) IsBlockEnd(line string) bool

func (*ParseContext) IsCurrentTypeNull

func (pc *ParseContext) IsCurrentTypeNull() bool

func (*ParseContext) ReadSQLCallback

func (ctx *ParseContext) ReadSQLCallback(callback FuncSQLStatementCallback) error

ReadSQLCallback 用于处理完整的 SQL 语句 当一个 SQL 语句解析完成后调用此函数处理结果

func (*ParseContext) Reset

func (pc *ParseContext) Reset()

Reset 重置 ParseContext 的所有字段到初始状态 在处理完一个 SQL 语句后调用,准备处理下一个语句

type ParseMysqlContext

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

func (*ParseMysqlContext) GetParamExpr

func (ctx *ParseMysqlContext) GetParamExpr(index int) *ParameterValue

func (*ParseMysqlContext) GetParamValue

func (ctx *ParseMysqlContext) GetParamValue(index int) string

type PreRetType

type PreRetType int

FuncPreProcessSqlLine 用于预处理 SQL 行的回调函数类型 返回 true 则跳过该行

type ProcessWordCallback

type ProcessWordCallback func(ctx *ParseContext, word *cyutil.WordInfo) (bool, error)

ProcessWordCallback 用于处理单词的回调函数类型 在遍历 SQL 语句中的单词时调用

type QueryExecutor

type QueryExecutor interface {
	// Query executes a query and returns raw results
	Query(ctx context.Context, sql string, args ...any) ([]map[string]any, error)
	// QueryRow executes a query that is expected to return at most one row
	QueryRow(ctx context.Context, sql string, args ...any) (map[string]any, error)
	// Exec executes a statement that doesn't return rows
	Exec(ctx context.Context, sql string, args ...any) (sql.Result, error)
}

QueryExecutor handles query execution

type QueryMetadata

type QueryMetadata struct {
	ExecutionTime time.Duration `json:"execution_time"`
	RowsAffected  int64         `json:"rows_affected"`
	QueryHash     string        `json:"query_hash,omitempty"`
}

QueryMetadata contains additional information about the query execution

type ReadSQLFileOptions

type ReadSQLFileOptions struct {
	// BufferSize 扫描器的缓冲区大小
	BufferSize int
	// MigrationMode 迁移模式过滤器 ("Up", "Down" 或空字符串表示不过滤)
	MigrationMode string
	// Filter SQL 过滤器,用于过滤特定类型的 SQL 语句
	Filter []string

	// WordCallback 单词回调函数,用于处理 SQL 语句中的单词
	WordCallback ProcessWordCallback

	// PreProcessSqlLine 预处理 SQL 行的回调函数
	PreProcessSqlLine FuncPreProcessSqlLine
}

ReadSQLFileOptions 定义了读取 SQL 文件的选项

func NewReadSQLFileOptions

func NewReadSQLFileOptions(options ...func(*ReadSQLFileOptions)) ReadSQLFileOptions

NewReadSQLFileOptions 创建一个新的 ReadSQLFileOptions 实例并应用选项函数

type ResultSet

type ResultSet[T any] struct {
	Data       []T           `json:"data"`
	TotalCount int64         `json:"total_count,omitempty"`
	Page       int           `json:"page,omitempty"`
	PageSize   int           `json:"page_size,omitempty"`
	Metadata   QueryMetadata `json:"metadata,omitempty"`
}

ResultSet represents query results with better type safety

type RowData

type RowData struct {
	Data []*FieldData
}

func (*RowData) GetData

func (r *RowData) GetData() map[string]interface{}

func (*RowData) GetReplaceSql

func (r *RowData) GetReplaceSql(cli DatabaseClient, table string) (string, error)

type SQLBuilder

type SQLBuilder interface {
	Type(t SQLOperationType) SQLBuilder
	Database(db string) SQLBuilder
	Table(table any) SQLBuilder
	Fields(columns any, reset ...bool) SQLBuilder
	// PrimaryKeys 指定主键字段,用于REPLACE和UPSERT操作
	PrimaryKeys(keys ...string) SQLBuilder
	Distinct(distinct bool) SQLBuilder
	Values(data ...[]Expression) SQLBuilder
	ValuesAppend(data ...[]Expression) SQLBuilder
	SubQueryValues(builder SQLBuilder) SQLBuilder
	Update(columns any) SQLBuilder
	UpdateExpr(updates ...Expression) SQLBuilder
	Count(fields string) SQLBuilder
	Select(fields any) SQLBuilder
	From(tableSrc any) SQLBuilder
	Where(fv Where, reset ...bool) SQLBuilder
	WhereAnd(fvs ...Where) SQLBuilder
	WhereOr(fvs ...Where) SQLBuilder
	Join(tableSrc TableSource, condition ...Where) SQLBuilder
	LeftJoin(tableSrc TableSource, condition ...Where) SQLBuilder
	RightJoin(tableSrc TableSource, condition ...Where) SQLBuilder
	InnerJoin(tableSrc TableSource, condition ...Where) SQLBuilder
	GroupBy(columns any) SQLBuilder
	Having(fv Where) SQLBuilder
	HavingAnd(fvs ...Where) SQLBuilder
	HavingOr(fvs ...Where) SQLBuilder
	OrderBy(orderBy ...OrderBy) SQLBuilder
	Limit(limit int) SQLBuilder
	LimitPlaceholder(limit string) SQLBuilder
	Offset(offset int) SQLBuilder
	OffsetPlaceholder(offset string) SQLBuilder

	// 统一的构建方法,通过选项控制不同的构建方式
	Build(dt DatabaseTransformer) (*BuildResult, error)
}

SQLBuilder provides a fluent interface for building queries

func Builder

func Builder() SQLBuilder

func ParseMySQL

func ParseMySQL(sql string) (SQLBuilder, error)

ParseMySQL parses a SQL statement and returns a SQLBuilder

type SQLDialect

type SQLDialect interface {
	// DDL operations
	GetDDLSqlFunc(funcName DDLSqlFuncName) (DDLSqlFunc, error)
	GetSortedSqlFunc(funcName SortFuncName) (SortedSqlFunc, error)

	// Schema operations - using DatabaseClient instead of specific type
	GetTableColumns(cli DatabaseClient, database, tableName string) ([]*DBColumn, error)
	IsTableExist(cli DatabaseClient, tableName string) (bool, error)

	// SQL preprocessing and utilities
	PreProcess(sql string, param ...int) string
	GetReplaceSql(cli DatabaseClient, table string, rd *RowData) (string, error)
	MakeSureDBExists(cli DatabaseClient, dbName string) error
	ReadSQLFile(r io.Reader, callback FuncSQLStatementCallback, options ...func(*ReadSQLFileOptions)) error
	GetConnectStr(dbConn *DBConnection) (string, string)
	GetDefaultTypeName(tp DefaultDBFieldType) string
}

SQLDialect handles database-specific SQL generation This matches the existing ISql interface for compatibility

func GetSqlDialect

func GetSqlDialect(dbtype string) (SQLDialect, bool)

type SQLOperationType

type SQLOperationType string
const (
	SQLOperationUnknown SQLOperationType = ""
	SQLOperationSelect  SQLOperationType = "SELECT"
	SQLOperationCount   SQLOperationType = "COUNT"
	SQLOperationInsert  SQLOperationType = "INSERT"
	SQLOperationUpdate  SQLOperationType = "UPDATE"
	SQLOperationDelete  SQLOperationType = "DELETE"
	SQLOperationReplace SQLOperationType = "REPLACE"
	SQLOperationUpsert  SQLOperationType = "UPSERT"
)

type SQLParseError

type SQLParseError struct {
	// Message 错误消息
	Message string
	// LineNum 发生错误的行号
	LineNum int
	// LineText 发生错误的行文本
	LineText string
	// ErrorType 错误类型
	ErrorType string
}

SQLParseError 定义了SQL解析过程中的错误 提供详细的错误信息,包括行号和错误类型

func (*SQLParseError) Error

func (e *SQLParseError) Error() string

Error 实现 error 接口,返回格式化的错误信息

type SQLStatement

type SQLStatement struct {
	Index     int
	StartLine int
	EndLine   int
	Type      string
	Content   string
}

type SQLType

type SQLType interface {
	// AsInt 返回 SQL 类型的整数表示
	AsInt() int
	// String 返回 SQL 类型的字符串表示
	String() string
	// IsBlock 判断该 SQL 类型是否为块级语句(如存储过程、函数等)
	IsBlock() bool

	// IsNull 判断该 SQL 类型是否为空
	IsNull() bool
}

SQLType 定义了 SQL 类型的接口 实现此接口的类型可以表示不同的 SQL 语句类型(如 SELECT, INSERT 等)

type SchemaInspector

type SchemaInspector interface {
	// GetTableColumns returns column information for a table
	GetTableColumns(ctx context.Context, database, tableName string) ([]*DBColumn, error)
	// IsTableExist checks if a table exists
	IsTableExist(ctx context.Context, tableName string) (bool, error)
	// GetTableNames returns all table names in the database
	GetTableNames(ctx context.Context, database string) ([]string, error)
}

SchemaInspector provides database schema information

type SimpleExpr

type SimpleExpr struct {
	Field  string     // 字段名
	Table  string     // 表名(可选)
	Schema string     // 模式名(可选)
	Alias  string     // 别名(可选)
	Value  Expression // 值(可选)
}

SimpleExpr 表示简单字段表达式

func (*SimpleExpr) GetFields

func (se *SimpleExpr) GetFields() []string

GetFields 返回表达式中涉及的字段名

func (*SimpleExpr) SetAlias

func (se *SimpleExpr) SetAlias(alias string) Expression

func (*SimpleExpr) ToSQL

func (se *SimpleExpr) ToSQL(dt DatabaseTransformer) (string, error)

ToSQL 将简单表达式转换为SQL字符串

type SortFuncName

type SortFuncName string
const (
	FuncNameSortTables     SortFuncName = "SortTables"
	FuncNameSortFunctions  SortFuncName = "SortFunctions"
	FuncNameSortProcedures SortFuncName = "SortProcedures"
)

type SortedSqlFunc

type SortedSqlFunc func(cli DatabaseClient, names []string) ([]*SqlContent, error)

type SqlContent

type SqlContent struct {
	Name    string
	Content string
}

type SubQuery

type SubQuery struct {
	Builder SQLBuilder
	Alias   string
	// contains filtered or unexported fields
}

func (*SubQuery) GetAlias

func (s *SubQuery) GetAlias() string

func (*SubQuery) GetFields

func (s *SubQuery) GetFields() []string

func (*SubQuery) SetAlias

func (s *SubQuery) SetAlias(alias string) Expression

func (*SubQuery) ToCondition

func (s *SubQuery) ToCondition(dt DatabaseTransformer) (*Condition, error)

func (*SubQuery) ToSQL

func (s *SubQuery) ToSQL(dt DatabaseTransformer) (string, error)

type Table

type Table struct {
	Schema string // 数据库/schema名称
	Name   string // 表名
	Alias  string // 表别名
}

func (*Table) GetAlias

func (t *Table) GetAlias() string

func (*Table) ToSQL

func (t *Table) ToSQL(dt DatabaseTransformer) (string, error)

type TableSource

type TableSource interface {
	GetAlias() string
	ToSQL(dt DatabaseTransformer) (string, error)
}

func ALIAS

func ALIAS(table string, alias string) TableSource

func SUBQUERY

func SUBQUERY(builder SQLBuilder, alias ...string) TableSource

func TABLE

func TABLE(param ...string) TableSource

type TraceWord

type TraceWord struct {
	// Key 表示当前关键字
	Key string
	// Skip 表示跳过的字符数
	Skip int
	// NextKeys 表示可能的下一个关键字及其对应的 SQL 类型
	NextKeys map[string]SQLType
}

TraceWord 用于跟踪关键字的结构体 在解析 SQL 语句时用于识别和处理特定的关键字

type Transaction

type Transaction interface {
	QueryExecutor
	TypedQueryExecutor
	// Commit commits the transaction
	Commit() error
	// Rollback rolls back the transaction
	Rollback() error
}

Transaction represents a database transaction

type TransactionManager

type TransactionManager interface {
	// Begin starts a new transaction
	Begin(ctx context.Context) (Transaction, error)
	// BeginTx starts a new transaction with options
	BeginTx(ctx context.Context, opts *sql.TxOptions) (Transaction, error)
}

TransactionManager handles transaction lifecycle

type TypedQueryExecutor

type TypedQueryExecutor interface {
	// Select scans query results into a slice
	Select(ctx context.Context, dest any, query string, args ...any) error
	// Get scans a single row into dest
	Get(ctx context.Context, dest any, query string, args ...any) error
}

TypedQueryExecutor provides type-safe query execution

type Value

type Value interface {
	GetValue() (string, error)
	// contains filtered or unexported methods
}

type WhenThenClause

type WhenThenClause struct {
	When Expression // WHEN 条件
	Then Expression // THEN 结果
}

WhenThenClause 表示 CASE 表达式中的 WHEN-THEN 子句

type Where

type Where interface {
	ToCondition(dt DatabaseTransformer) (*Condition, error)
}

func AND

func AND(conditions ...Where) Where

AND 创建AND条件组合的WhereClause 注意:这些是条件组合函数,不是OP操作符

func BETWEEN

func BETWEEN(field string, start, end any, f ...WhereOptionFunc) Where

func COMBINE

func COMBINE(andConditions []Where, orConditions []Where) Where

Combine 组合AND和OR条件

func EQ

func EQ(field string, f ...WhereOptionFunc) Where

func EXISTS

func EXISTS(subquery Expression, f ...WhereOptionFunc) Where

EXISTS 创建 EXISTS 条件,用于检查子查询是否返回结果 subquery 可以是 SQLBuilder 或者已经格式化的 SQL 字符串

func GT

func GT(field string, f ...WhereOptionFunc) Where

func GTE

func GTE(field string, f ...WhereOptionFunc) Where

func IN

func IN(field string, values []any, f ...WhereOptionFunc) Where

func IS_NOT_NULL

func IS_NOT_NULL(field string, f ...WhereOptionFunc) Where

func IS_NULL

func IS_NULL(field string, f ...WhereOptionFunc) Where

func LIKE

func LIKE(field string, value string, pt LikePatternType, f ...WhereOptionFunc) Where

func LIKEC

func LIKEC(field string, value string, f ...WhereOptionFunc) Where

func LIKEL

func LIKEL(field string, value string, f ...WhereOptionFunc) Where

func LIKER

func LIKER(field string, value string, f ...WhereOptionFunc) Where

func LT

func LT(field string, f ...WhereOptionFunc) Where

func LTE

func LTE(field string, f ...WhereOptionFunc) Where

func MergeWhere

func MergeWhere(w1 Where, w2 Where) Where

func NEQ

func NEQ(field string, f ...WhereOptionFunc) Where

func NOT_EXISTS

func NOT_EXISTS(subquery Expression, f ...WhereOptionFunc) Where

NOT_EXISTS 创建 NOT EXISTS 条件,用于检查子查询是否不返回结果 subquery 可以是 SQLBuilder 或者已经格式化的 SQL 字符串

func NOT_IN

func NOT_IN(field string, values []any, f ...WhereOptionFunc) Where

func ON

func ON(leftField any, rightField any, op ...string) Where

func OR

func OR(conditions ...Where) Where

OR 创建OR条件组合的WhereClause

func WHERE

func WHERE(field string, value any, ops ...OP) Where

RawFieldCondition 创建原始字段条件(字段名不转义)

type WhereOP

type WhereOP string
const (
	WhereOPAnd WhereOP = "AND"
	WhereOPOr  WhereOP = "OR"
)

type WhereOptionFunc

type WhereOptionFunc func(*whereItem) *whereItem

func WithLiteral

func WithLiteral(v any) WhereOptionFunc

WithLiteral 创建直接嵌入的值

func WithNativeValue

func WithNativeValue(v any) WhereOptionFunc

func WithParameter

func WithParameter(name string) WhereOptionFunc

WithParameter 创建参数值

Directories

Path Synopsis
sql

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL