core

package
v3.2.0 Latest Latest
Warning

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

Go to latest
Published: Apr 7, 2021 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package core 核心功能

Index

Constants

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

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

View Source
const TimeFormatLayout = time.RFC3339

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

Variables

View Source
var (
	// ErrColumnMustNumber 列的类型错误
	//
	// 部分列对其类型有要求,比如自增列和被定义为乐观锁的锁,
	// 其类型必须为数值类型,否则将返回此错误。
	ErrColumnMustNumber = errors.New("类型必须为数值")

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

ErrInvalidColumnType 无效的列类型

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

Functions

func AIName

func AIName(table string) string

AIName 生成 AI 约束名称

自增约束的实现,各个数据库并不相同,诸如 mysql 直接加在列信息上, 而 postgres 会创建 sequence,需要指定 sequence 名称。

参数 table 必须是完整的表名,如果有表名前缀,也需要带上。

func ErrConstraintExists

func ErrConstraintExists(c string) error

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

func PKName

func PKName(table string) string

PKName 生成主键约束的名称

各个数据库对主键约束的规定并不统一,mysql 会忽略约束名, 为了统一,主键约束的名称统一由此函数生成,用户不能另外指定。

参数 table 必须是完整的表名,如果有表名前缀,也需要带上。

Types

type Builder

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

Builder 用于构建 SQL 语句

出错时,错误信息会缓存,并在 String 和 Bytes 时返回, 或是通过 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    interface{}
	Length     []int

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

Column 列结构

func NewColumn added in v3.2.0

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 int8

Constraint 表示约束类型

const (
	ConstraintNone   Constraint = iota
	ConstraintUnique            // 唯一约束
	ConstraintFK                // 外键约束
	ConstraintCheck             // Check 约束
	ConstraintPK                // 主键约束
	ConstraintAI                // 自增
)

约束类型

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

type DefaultParser

type DefaultParser interface {
	// 将默认值从字符串解析成 t 类型的值
	ParseDefault(v string) error
}

DefaultParser 提供了 ParseDefault 函数

在 struct tag 中可以通过 default 指定默认值, 该值的表示可能与数据库中的表示不尽相同, 所以自定义的数据类型,需要实现该接口,以便能正确转换成该类型的值。

如果用户不提供该接口实现,那么默认情况下, 系统会采用 github.com/issue9/conv.Value() 函数作默认转换。

type Dialect

type Dialect interface {
	// 当前关联的数据库名称
	//
	// 数据库名称和驱动名未必相同。比如 mysql 和 mariadb 可能采用相同的驱动名;
	DBName() string

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

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

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

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

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

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

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

	// 对 sql 语句作调整
	//
	// 比如替换 {} 符号;处理 sql.NamedArgs;
	// postgresql 需要将 ? 改成 $1 等形式。
	// 以及对 args 的参数作校正,比如 lib/pq 对 time.Time 处理有问题,也可以在此处作调整。
	Fix(query string, args []interface{}) (string, []interface{}, error)

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

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

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

type Engine

type Engine interface {
	TablePrefix() string

	Dialect() Dialect

	Query(query string, args ...interface{}) (*sql.Rows, error)

	QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)

	QueryRow(query string, args ...interface{}) *sql.Row

	QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row

	Exec(query string, args ...interface{}) (sql.Result, error)

	ExecContext(ctx context.Context, query string, args ...interface{}) (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 {
	Column                   *Column
	RefTableName, RefColName string
	UpdateRule, DeleteRule   string
}

ForeignKey 外键

type Index

type Index int8

Index 索引的类型

const (
	IndexDefault Index = iota // 普通的索引
	IndexUnique               // 唯一索引
)

索引的类型

type Metaer

type Metaer interface {
	Meta() string
}

Metaer 用于指定数据模型的元数据

不同的数据库可以有各自的属性内容,具体的由 Dialect 的实现者定义。 但是 name、check 是通用的,分别表示名称和 check 约束。

"name(tbl_name);mysql_engine(myISAM);mysql_charset(utf8)"

type Model

type Model struct {
	GoType reflect.Type

	// 模型的名称,可以以 # 符号开头,表示该表名带有一个表名前缀。
	// 在生成 SQL 语句时,该符号会被转换成 Engine.TablePrefix()
	// 返回的值。
	Name string

	// 如果当前模型是视图,那么此值表示的是视图的 select 语句,
	// 其它类型下,ViewAs 不启作用。
	ViewAs string

	Type    ModelType
	Columns []*Column
	OCC     *Column             // 乐观锁
	Meta    map[string][]string // 表级别的数据,如存储引擎,表名和字符集等。

	// 索引内容
	//
	// 目前不支持唯一索引,如果需要唯一索引,可以设置成唯一约束。
	Indexes map[string][]*Column

	// 约束
	Uniques       map[string][]*Column
	Checks        map[string]string
	ForeignKeys   map[string]*ForeignKey
	AutoIncrement *Column
	PrimaryKey    []*Column
}

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

func NewModel

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

NewModel 初始化 Model,分其所有变量分配内存。 但是变量的内容依然要手动初始化。

cap 表示列的数量,如果指定了,可以提交分配内存。

func (*Model) AIName

func (m *Model) AIName() string

AIName 当前模型中自增列的名称

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 Index, name string, col *Column) error

AddIndex 添加索引列

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

NOTE: 如果是唯一索引,则改为唯一约束

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

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

NewCheck 添加新的 check 约束

func (*Model) NewForeignKey

func (m *Model) NewForeignKey(name string, fk *ForeignKey) error

NewForeignKey 添加新的外键

func (*Model) PKName

func (m *Model) PKName() string

PKName 当前模型中主键约束的名称

func (*Model) Reset

func (m *Model) Reset()

Reset 清空模型内容

func (*Model) Sanitize

func (m *Model) Sanitize() error

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

必须要在 Model 初始化完成之后调用。

func (*Model) SetAutoIncrement

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

SetAutoIncrement 将 col 列设置为自增列

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

func (*Model) SetOCC

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

SetOCC 设置该列为乐观锁

type ModelType

type ModelType int8

ModelType 表示数据模型的类别

const (
	Table ModelType
	View
)

目前支持的数据模型类别

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

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

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

type PrimitiveType added in v3.2.0

type PrimitiveType int

PrimitiveType 表示支持转换成数据库类型的 Go 类型信息

const (
	Auto PrimitiveType = iota
	Bool
	Int
	Int8
	Int16
	Int32
	Int64
	Uint
	Uint8
	Uint16
	Uint32
	Uint64
	Float32
	Float64
	String
	NullString
	NullInt64
	NullInt32
	NullBool
	NullFloat64
	Bytes
	RawBytes
	Time
	NullTime
)

所有的 PrimitiveType

func GetPrimitiveType added in v3.2.0

func GetPrimitiveType(t reflect.Type) PrimitiveType

GetPrimitiveType 获取 t 所关联的 PrimitiveType 值

如果 t.Kind == Ptr,则需要用户自行处理获取其对象的类型,否则返回 Auto。

type PrimitiveTyper added in v3.2.0

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

PrimitiveTyper 提供了 PrimitiveType 方法

如果用户需要将自定义类型写入数据,需要提供该类型所表示的 PrimitiveType 值, 最终会以该类型的值写入数据库。

NOTE: 最简单的方法是复用 driver.Valuer 接口,从其返回值中获取类型信息, 但是该接口有可能返回 nil 值,无法确定类型。

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 ...interface{}) (sql.Result, error)

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

func (*Stmt) ExecContext

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

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

func (*Stmt) Query

func (stmt *Stmt) Query(args ...interface{}) (*sql.Rows, error)

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

func (*Stmt) QueryContext

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

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

func (*Stmt) QueryRow

func (stmt *Stmt) QueryRow(args ...interface{}) *sql.Row

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

func (*Stmt) QueryRowContext

func (stmt *Stmt) QueryRowContext(ctx context.Context, args ...interface{}) *sql.Row

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

type Unix added in v3.1.0

type Unix struct {
	time.Time
	IsNull bool
}

Unix 以 unix 时间戳保存的 time.Time 数据格式

func (*Unix) FromTime added in v3.2.0

func (n *Unix) FromTime(t time.Time)

FromTime 从 time.Time 转换而来

func (Unix) MarshalBinary added in v3.2.0

func (n Unix) MarshalBinary() ([]byte, error)

MarshalBinary implements encoding.BinaryMarshaler

func (Unix) MarshalJSON added in v3.2.0

func (n Unix) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler

func (Unix) MarshalText added in v3.2.0

func (n Unix) MarshalText() ([]byte, error)

MarshalText encoding.TextMarshaler

func (*Unix) ParseDefault added in v3.2.0

func (n *Unix) ParseDefault(v string) error

ParseDefault 实现 DefaultParser 接口

func (Unix) PrimitiveType added in v3.2.0

func (n Unix) PrimitiveType() PrimitiveType

PrimitiveType 实现 PrimitiveTyper 接口

func (*Unix) Scan added in v3.1.0

func (n *Unix) Scan(src interface{}) (err error)

Scan implements the Scanner.Scan

func (*Unix) UnmarshalBinary added in v3.2.0

func (n *Unix) UnmarshalBinary(data []byte) error

UnmarshalBinary implements encoding.BinaryUnmarshaler

func (*Unix) UnmarshalJSON added in v3.2.0

func (n *Unix) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler

func (*Unix) UnmarshalText added in v3.2.0

func (n *Unix) UnmarshalText(data []byte) error

UnmarshalText encoding.TextUnmarshaler

func (Unix) Value added in v3.1.0

func (n Unix) Value() (driver.Value, error)

Value implements the driver.Valuer

type Viewer

type Viewer interface {
	// 返回视图所需的 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