129 lines
2.7 KiB
Go
129 lines
2.7 KiB
Go
|
package schema
|
||
|
|
||
|
import (
|
||
|
"github.com/samber/lo"
|
||
|
|
||
|
"git.fsdpf.net/go/db"
|
||
|
)
|
||
|
|
||
|
type Builder struct {
|
||
|
Connection *db.Connection // The database connection instance
|
||
|
Grammar IGrammar // The schema grammar instance
|
||
|
}
|
||
|
|
||
|
func NewSchema(conn *db.Connection) *Builder {
|
||
|
var grammar IGrammar
|
||
|
|
||
|
switch conn.GetConfig().Driver {
|
||
|
case "mysql":
|
||
|
grammar = &MysqlGrammar{}
|
||
|
case "sqlite3":
|
||
|
grammar = &Sqlite3Grammar{}
|
||
|
}
|
||
|
|
||
|
return &Builder{
|
||
|
Connection: conn,
|
||
|
Grammar: grammar,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 判断数据表是否存在
|
||
|
func (this *Builder) HasTable(table string) (bool, error) {
|
||
|
query := this.Grammar.CompileTableExists()
|
||
|
dbName := this.Connection.GetConfig().Database
|
||
|
|
||
|
count := 0
|
||
|
|
||
|
if _, err := this.Connection.Select(query, []any{table, dbName}, &count); err != nil || count == 0 {
|
||
|
return false, err
|
||
|
}
|
||
|
|
||
|
return true, nil
|
||
|
}
|
||
|
|
||
|
// 判断表字段是个存在
|
||
|
func (this *Builder) HasColumns(table string, columns ...string) (bool, error) {
|
||
|
if tColumns, err := this.GetColumnListing(table); err != nil {
|
||
|
return false, err
|
||
|
} else {
|
||
|
for _, col := range columns {
|
||
|
if !lo.Contains(tColumns, col) {
|
||
|
return false, nil
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return true, nil
|
||
|
}
|
||
|
|
||
|
// 判断数据库列是否存在
|
||
|
func (this *Builder) GetColumnListing(table string) (columns []string, err error) {
|
||
|
query := this.Grammar.CompileColumnListing(table)
|
||
|
dbName := this.Connection.GetConfig().Database
|
||
|
|
||
|
items := []struct {
|
||
|
ID int `db:"id"`
|
||
|
Name string `db:"name"`
|
||
|
}{}
|
||
|
|
||
|
bindings := []any{table, dbName}
|
||
|
|
||
|
if this.Connection.GetConfig().Driver == "sqlite3" {
|
||
|
bindings = nil
|
||
|
}
|
||
|
|
||
|
if _, err := this.Connection.Select(query, bindings, &items); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
for _, item := range items {
|
||
|
columns = append(columns, item.Name)
|
||
|
}
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// 修改表
|
||
|
func (this *Builder) Table(table string, cb func(*Blueprint)) error {
|
||
|
bp := this.createBlueprint(table)
|
||
|
cb(bp)
|
||
|
return this.Build(bp)
|
||
|
}
|
||
|
|
||
|
// 创建表
|
||
|
func (this *Builder) Create(table string, cb func(*Blueprint)) error {
|
||
|
bp := this.createBlueprint(table)
|
||
|
bp.Create()
|
||
|
cb(bp)
|
||
|
return this.Build(bp)
|
||
|
}
|
||
|
|
||
|
// 修改表名
|
||
|
func (this *Builder) Rename(from, to string) error {
|
||
|
bp := this.createBlueprint(from)
|
||
|
bp.Rename(to)
|
||
|
return this.Build(bp)
|
||
|
}
|
||
|
|
||
|
// 删除表
|
||
|
func (this *Builder) Drop(table string) error {
|
||
|
bp := this.createBlueprint(table)
|
||
|
bp.Drop()
|
||
|
return this.Build(bp)
|
||
|
}
|
||
|
|
||
|
// 删除表, 先判断再删除
|
||
|
func (this *Builder) DropIfExists(table string) error {
|
||
|
bp := this.createBlueprint(table)
|
||
|
bp.DropIfExists()
|
||
|
return this.Build(bp)
|
||
|
}
|
||
|
|
||
|
func (b *Builder) createBlueprint(table string) *Blueprint {
|
||
|
return NewBlueprint(table)
|
||
|
}
|
||
|
|
||
|
// Build execute the blueprint to build / modify the table
|
||
|
func (this *Builder) Build(bp *Blueprint) error {
|
||
|
return bp.Build(this.Connection, this.Grammar)
|
||
|
}
|