core

package
v6.0.0-beta.3 Latest Latest
Warning

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

Go to latest
Published: Apr 22, 2024 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package core 核心功能

Index

Constants

View Source
const (
	QuoteLeft  = '{'
	QuoteRight = '}'
)

作用于表名,列名等非关键字上的引号占位符。 在执行会自动替换成该数据库相应的符号。

View Source
const TimeFormatLayout = time.RFC3339

TimeFormatLayout 时间如果需要转换成字符串采用此格式

Variables

This section is empty.

Functions

func ErrColumnNotFound

func ErrColumnNotFound(s string) error

ErrColumnNotFound 返回列不存在的错误

func ErrConstraintExists

func ErrConstraintExists(c string) error

ErrConstraintExists 返回约束名已经存在的错误

func ErrInvalidColumnType

func ErrInvalidColumnType() error

ErrInvalidColumnType 无效的列类型

当一个数据无法表达为数据库中的对应的字段类型时返回此错误。

Types

type ApplyModeler

type ApplyModeler interface {
	ApplyModel(*Model) error
}

ApplyModeler 加载数据模型

当一个对象实现此接口时,那么在将对象转换成 Model 类型时, 会调用 ApplyModel 方法,给予用户修改 Model 的机会。

type Builder

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

Builder 用于构建 SQL 语句

出错时,错误信息会缓存,并在 Builder.StringBuilder.Bytes 时返回, 或是通过 Builder.Err 查看是否存在错误。

func NewBuilder

func NewBuilder(str ...string) *Builder

NewBuilder 声明一个新的 Builder 实例

func (*Builder) Append

func (b *Builder) Append(v *Builder) *Builder

Append 追加加一个 Builder 的内容

func (*Builder) Bytes

func (b *Builder) Bytes() ([]byte, error)

Bytes 获取表示的字符串

func (*Builder) Err

func (b *Builder) Err() error

Err 返回错误内容

func (*Builder) Len

func (b *Builder) Len() int

Len 获取长度

func (*Builder) Quote

func (b *Builder) Quote(str string, l, r byte) *Builder

Quote 给 str 左右添加 l 和 r 两个字符

func (*Builder) QuoteKey

func (b *Builder) QuoteKey(str string) *Builder

QuoteKey 给 str 左右添加 QuoteLeftQuoteRight 两个字符

func (*Builder) Reset

func (b *Builder) Reset() *Builder

Reset 重置内容,同时也会将 err 设置为 nil

func (*Builder) String

func (b *Builder) String() (string, error)

String 获取表示的字符串

func (*Builder) TruncateLast

func (b *Builder) TruncateLast(n int) *Builder

TruncateLast 去掉最后几个字符

func (*Builder) WBytes

func (b *Builder) WBytes(c ...byte) *Builder

WBytes 写入多个字符

func (*Builder) WRunes

func (b *Builder) WRunes(r ...rune) *Builder

WRunes 写入多个字符

func (*Builder) WString

func (b *Builder) WString(str string) *Builder

WString 写入一字符串

type Column

type Column struct {
	Name       string // 数据库的字段名
	AI         bool
	Nullable   bool
	HasDefault bool
	Default    any
	Length     []int

	PrimitiveType PrimitiveType
	GoName        string // Go 中的字段名
}

Column 列结构

func NewColumn

func NewColumn(p PrimitiveType) (*Column, error)

NewColumn 从 Go 类型中生成 Column

func (*Column) Check

func (c *Column) Check() error

Check 检测 Column 内容是否合法

func (*Column) Clone

func (c *Column) Clone() *Column

Clone 复制 Column

type Constraint

type Constraint struct {
	Name    string
	Columns []*Column
}

type ConstraintType

type ConstraintType int8
const (
	ConstraintNone   ConstraintType = iota
	ConstraintUnique                // 唯一约束
	ConstraintFK                    // 外键约束
	ConstraintCheck                 // Check 约束
	ConstraintPK                    // 主键约束
)

约束类型

以下定义了一些常用的约束类型,但是并不是所有的数据都支持这些约束类型, 比如 mysql<8.0.16 和 mariadb<10.2.1 不支持 check 约束。

type Dialect

type Dialect interface {
	// Name 当前关联实例的名称
	//
	// 一般为该数据库的官方名称。
	// 实例名称和驱动名未必相同。比如 mysql 和 mariadb 可能采用相同的驱动名;
	Name() string

	// DriverName 与当前实例关联的驱动名称
	//
	// 原则上驱动名和 Dialect 应该是一一对应的,但是也会有例外,比如:
	// github.com/lib/pq 和 github.com/jackc/pgx/v4/stdlib 功能上是相同的,
	// 仅注册的名称的不同。
	DriverName() string

	Quotes() (left, right byte)

	// SQLType 将列转换成数据支持的类型表达式
	//
	// 必须实现对所有 [PrimitiveType] 类型的转换。
	SQLType(*Column) (string, error)

	// TransactionalDDL 是否允许在事务中执行 DDL
	//
	// 比如在 postgresql 中,如果创建一个带索引的表,会采用在事务中,
	// 分多条语句创建表。
	// 而像 mysql 等不支持事务内 DDL 的数据库,则会采用普通的方式,
	// 依次提交语句。
	TransactionalDDL() bool

	// VersionSQL 查询服务器版本号的 SQL 语句
	VersionSQL() string

	// ExistsSQL 查询数据库中是否存在指定名称的表或是视图 SQL 语句
	//
	// 返回的 SQL语句中,其执行结果如果存在,则应该返回 name 字段表示表名,否则返回空。
	ExistsSQL(name string, view bool) (string, []any)

	// LimitSQL 生成 `LIMIT N OFFSET M` 或是相同的语意的语句片段
	//
	// offset 值为一个可选参数,若不指定,则表示 `LIMIT N` 语句。
	// 返回的是对应数据库的 limit 语句以及语句中占位符对应的值。
	//
	// limit 和 offset 可以是 SQL.NamedArg 类型。
	LimitSQL(limit any, offset ...any) (string, []any)

	// LastInsertIDSQL 自定义获取 LastInsertID 的获取方式
	//
	// 类似于 postgresql 等都需要额外定义。
	//
	// sql 表示额外的语句,如果为空,则执行的是标准的 SQL 插入语句;
	// append 表示在 sql 不为空的情况下,sql 与现有的插入语句的结合方式,
	// 如果为 true 表示直接添加在插入语句之后,否则为一条新的语句。
	LastInsertIDSQL(table, col string) (sql string, append bool)

	// CreateTableOptionsSQL 创建表时根据附加信息返回的部分 SQL 语句
	CreateTableOptionsSQL(sql *Builder, options map[string][]string) error

	// TruncateTableSQL 生成清空数据表并重置自增列的语句
	//
	// ai 表示自增列的名称,可以为空,表示没有自去列。
	TruncateTableSQL(table, ai string) ([]string, error)

	// CreateViewSQL 生成创建视图的 SQL 语句
	CreateViewSQL(replace, temporary bool, name, selectQuery string, cols []string) ([]string, error)

	// DropIndexSQL 生成删除索引的语句
	//
	// table 为表名,部分数据库需要;
	// index 表示索引名;
	DropIndexSQL(table, index string) (string, error)

	// Fix 对 sql 语句作调整
	//
	// 比如处理 [sql.NamedArgs],postgresql 需要将 ? 改成 $1 等形式。
	// 以及对 args 的参数作校正,比如 lib/pq 对 time.Time 处理有问题,也可以在此处作调整。
	//
	// NOTE: query 中不能同时存在 ? 和命名参数。因为如果是命名参数,则 args 的顺序可以是随意的。
	Fix(query string, args []any) (string, []any, error)

	// Prepare 对预编译的内容进行处理
	//
	// 目前大部分驱动都不支持 [sql.NamedArgs],为了支持该功能,
	// 需要在预编译之前,对语句进行如下处理:
	//  1. 将 sql 中的 @xx 替换成 ?
	//  2. 将 sql 中的 @xx 在 sql 中的位置进行记录,并通过 orders 返回。
	// query 为处理后的 SQL 语句;
	// orders 为参数名在 query 中对应的位置,第一个位置为 0,依次增加。
	//
	// NOTE: query 中不能同时存在 ? 和命名参数。因为如果是命名参数,则 Exec 等的参数顺序可以是随意的。
	Prepare(sql string) (query string, orders map[string]int, err error)
}

Dialect 用于描述与数据库和驱动相关的一些特性

Dialect 的实现者除了要实现 Dialect 之外, 还需要根据数据库的支持情况实现 sqlbuilder 下的部分 *Hooker 接口。

type Engine

type Engine interface {
	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

	Exec(query string, args ...any) (sql.Result, error)
	ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)

	Prepare(query string) (*Stmt, error)
	PrepareContext(ctx context.Context, query string) (*Stmt, error)

	Dialect() Dialect

	// Debug 启用调试输出
	//
	// 如果传递了一个非空值,那么会将生成的 SQL 输出到 l。
	Debug(l func(string))
}

Engine 数据库执行的基本接口

Engine 对查询语句作了以下处理:

  • {} 符号会被替换为 [Dialect.Quotes] 对应的符号;
  • # 会被替换为 [Engine.TablePrefix] 的返回值;

type ForeignKey

type ForeignKey struct {
	Name                     string // 约束名
	Column                   *Column
	RefTableName, RefColName string
	UpdateRule, DeleteRule   string
}

ForeignKey 外键

type IndexType

type IndexType int8
const (
	IndexDefault IndexType = iota // 普通的索引
	IndexUnique                   // 唯一索引
)

索引的类型

type Model

type Model struct {
	GoType reflect.Type

	// 模型的名称
	Name string

	// 视图的 select 语句
	//
	// 仅在 ModelType == View 时有效果,可由 [Engine.Query] 等处理。
	ViewAs string

	Type    ModelType
	Columns []*Column

	// 约束与索引
	//
	// NOTE: 如果是视图模式,理论上是不存在约束信息的,
	// 但是依然可以指定约束,这些信息主要是给 ORM 查看,以便构建搜索语句。
	Checks        map[string]string
	ForeignKeys   []*ForeignKey
	Indexes       []*Constraint // 目前不支持唯一索引,如果需要唯一索引,可以设置成唯一约束。
	Uniques       []*Constraint
	AutoIncrement *Column
	PrimaryKey    *Constraint

	OCC *Column // 乐观锁

	// 表级别的数据
	//
	// 如存储引擎,表名和字符集等,在创建表时,可能会用到这此数据。
	// 可以采用 [Dialect.Name] 限定数据库,比如 mysql_charset 限定为 mysql 下的 charset 属性。
	// 具体可参考各个 dialect 实现的介绍。
	Options map[string][]string
}

Model 表示一个数据库的表或视图模型

func NewModel

func NewModel(modelType ModelType, name string, cap int) *Model

NewModel 初始化 Model

cap 表示列的数量,如果指定了,可以提前分配 [Model.Columns] 字段的大小。

func (*Model) AddColumn

func (m *Model) AddColumn(col *Column) error

AddColumn 添加新列

按添加顺序确定位置,越早添加的越在前。

func (*Model) AddColumns

func (m *Model) AddColumns(col ...*Column) error

AddColumns 添加新列

func (*Model) AddIndex

func (m *Model) AddIndex(typ IndexType, name string, col *Column) error

AddIndex 添加索引列

如果 name 不存在,则创建新的索引

NOTE: 如果 typ == IndexUnique,则等同于调用 AddUnique。

func (*Model) AddPrimaryKey

func (m *Model) AddPrimaryKey(col *Column) error

AddPrimaryKey 指定主键约束的列

自增会自动转换为主键。 多次调用,则多列形成一个多列主键。

func (*Model) AddUnique

func (m *Model) AddUnique(name string, col *Column) error

AddUnique 添加唯一约束的列到 name

如果 name 不存在,则创建新的约束

func (*Model) FindColumn

func (m *Model) FindColumn(name string) *Column

FindColumn 查找指定名称的列

不存在该列则返回 nil

func (*Model) ForeignKey

func (m *Model) ForeignKey(name string) (*ForeignKey, bool)

func (*Model) Index

func (m *Model) Index(name string) (*Constraint, bool)

func (*Model) NewCheck

func (m *Model) NewCheck(name string, expr string) error

NewCheck 添加新的 check 约束

func (*Model) NewForeignKey

func (m *Model) NewForeignKey(fk *ForeignKey) error

NewForeignKey 添加新的外键

func (*Model) Reset

func (m *Model) Reset()

Reset 清空模型内容

func (*Model) Sanitize

func (m *Model) Sanitize() error

Sanitize 对整个对象做一次修正和检测,查看是否合法

NOTE: 必需在 Model 初始化完成之后调用。

func (*Model) SetAutoIncrement

func (m *Model) SetAutoIncrement(col *Column) error

SetAutoIncrement 将 col 列设置为自增列

如果已经存在自增列或是主键,返回错误。

func (*Model) SetOCC

func (m *Model) SetOCC(col *Column) error

SetOCC 设置该列为乐观锁

func (*Model) Unique

func (m *Model) Unique(name string) (*Constraint, bool)

type ModelType

type ModelType int8

ModelType 表示数据模型的类别

const (
	Table ModelType
	View
)

目前支持的数据模型类别

Table 表示为一张普通的数据表,默认的模型即为 Table; 如果实现了 Viewer 接口,则该模型改变视图类型,即 View

两者的创建方式稍微有点不同: Table 类型创建时,会采用列、约束和索引等信息创建表; 而 View 创建时,只使用了 Viewer 接口返回的 Select 语句作为内容生成语句,像约束等信息,仅作为查询时的依据, 当然 select 语句中的列需要和 [Columns] 中的列要相对应, 否则可能出错。

在视图类型中,唯一约束、主键约束、自增约束依然是可以定义的, 虽然不会呈现在视图中,但是在查询时,可作为 orm 的一个判断依据。

type PrimitiveType

type PrimitiveType int

PrimitiveType 表示 Go 对象在数据库中实际的存储方式

PrimitiveType 由 [Dialect.SQLType] 转换成相应数据的实际类型。

const (
	Auto PrimitiveType = iota
	Bool
	Int
	Int8
	Int16
	Int32
	Int64
	Uint
	Uint8
	Uint16
	Uint32
	Uint64
	Float32
	Float64
	String
	Bytes
	Time
	Decimal
)

当前支持的 PrimitiveType

其中的 String 被设计成可以保存部分类型为 reflect.Interface 的数据结构, 但是一个有限的集合,比如将一个 any 字段赋予 slice 类型的数,在保存时可会不被支持。 且在读取时,各个数据库略有不同,比如 mysql 返回 []byte,而其它数据一般返回 string。

func GetPrimitiveType

func GetPrimitiveType(t reflect.Type) PrimitiveType

GetPrimitiveType 获取 t 所关联的 PrimitiveType

t.Kind 不能为 reflect.Ptr 否则将返回 Auto

func (PrimitiveType) String

func (t PrimitiveType) String() string

type PrimitiveTyper

type PrimitiveTyper interface {

	// PrimitiveType 返回当前对象所表示的 [PrimitiveType] 值
	//
	// NOTE: 每个对象在任何时间返回的值应该都是固定的。
	PrimitiveType() PrimitiveType
}

type Stmt

type Stmt struct {
	*sql.Stmt
	// contains filtered or unexported fields
}

Stmt 实现自定义的 Stmt 实例

功能与 sql.Stmt 完全相同,但是实现了对 sql.NamedArgs 的支持。

func NewStmt

func NewStmt(stmt *sql.Stmt, orders map[string]int) *Stmt

NewStmt 声明 Stmt 实例

如果 orders 为空,则 Stmt 的表现和 sql.Stmt 是完全相同的, 如果不为空,则可以处理 sql.NamedArg 类型的参数。

func (*Stmt) Close

func (stmt *Stmt) Close() error

Close 关闭 Stmt 实例

func (*Stmt) Exec

func (stmt *Stmt) Exec(args ...any) (sql.Result, error)

Exec 以指定的参数执行预编译的语句

func (*Stmt) ExecContext

func (stmt *Stmt) ExecContext(ctx context.Context, args ...any) (sql.Result, error)

ExecContext 以指定的参数执行预编译的语句

func (*Stmt) Query

func (stmt *Stmt) Query(args ...any) (*sql.Rows, error)

Query 以指定的参数执行预编译的语句

func (*Stmt) QueryContext

func (stmt *Stmt) QueryContext(ctx context.Context, args ...any) (*sql.Rows, error)

QueryContext 以指定的参数执行预编译的语句

func (*Stmt) QueryRow

func (stmt *Stmt) QueryRow(args ...any) *sql.Row

QueryRow 以指定的参数执行预编译的语句

func (*Stmt) QueryRowContext

func (stmt *Stmt) QueryRowContext(ctx context.Context, args ...any) *sql.Row

QueryRowContext 以指定的参数执行预编译的语句

type TableNamer

type TableNamer interface {
	// TableName 返回表或是视图的名称
	TableName() string
}

TableNamer 表或是视图必须实现的接口

type Viewer

type Viewer interface {
	// ViewAs 返回视图所需的 SELECT 语句
	ViewAs() (string, error)
}

Viewer 视图必须要实现的接口

当一个模型实现了该接口,会被识别为视图模型,不再在数据库中创建普通的数据表。

Jump to

Keyboard shortcuts

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