core

package
v5.2.0 Latest Latest
Warning

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

Go to latest
Published: Mar 14, 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

View Source
var (
	// ErrAutoIncrementPrimaryKeyConflict 自增和主键不能同时存在
	//
	// 当添加自增时,会自动将其转换为主键,如果此时已经已经存在主键,则会报此错误。
	ErrAutoIncrementPrimaryKeyConflict = errors.New("自增和主键不能同时存在")
)
View Source
var ErrInvalidColumnType = errors.New("无效的列类型")

ErrInvalidColumnType 无效的列类型

作为列类型,该数据类型必须是可序列化的。 像 reflect.Funcreflect.Chan 等类型的数据都将返回该错误。

Functions

func ErrConstraintExists

func ErrConstraintExists(c string) error

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

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 左右添加 QuoteLeft 和 QuoteRight 两个字符

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 {
	// DBName 当前关联的数据库名称
	//
	// 数据库名称和驱动名未必相同。比如 mysql 和 mariadb 可能采用相同的驱动名;
	DBName() 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 {
	Dialect() Dialect

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

Engine 数据库执行的基本接口

orm.DB 和 orm.Tx 应该实现此接口。

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 语句,
	// 其它类型下,ViewAs 不启作用。
	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.DBName 限定数据库,比如 mysql_charset 限定为 mysql 下的 charset 属性。
	// 具体可参考各个 dialect 实现的介绍。
	Options map[string][]string
}

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

func NewModel

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

NewModel 初始化 Model

cap 表示列的数量,如果指定了,可以提前分配 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(e Engine) (string, error)
}

Viewer 视图必须要实现的接口

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

Jump to

Keyboard shortcuts

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