Documentation
¶
Index ¶
- func AddColumn(ctx context.Context, db wrapper.Querier, col Column) error
- func ChangeColumn(ctx context.Context, db wrapper.Querier, col Column) error
- func CheckAutoSet(defaultVal string) bool
- func CheckAutoincrement(extra string) bool
- func CheckNull(null nullenum.Null) bool
- func CheckPk(key keyenum.Key) bool
- func CheckUnsigned(dbColType string) bool
- func CreateTable(ctx context.Context, db wrapper.Querier, t Table) error
- func NewFieldFromColumn(col Column) astutils.FieldMeta
- func Setup() (func(), *sqlx.DB, error)
- type Column
- type DbAction
- type DbColumn
- type DbForeignKey
- type DbIndex
- type ForeignKey
- type Index
- type IndexItem
- type IndexItems
- type Table
- func NewTableFromStruct(structMeta astutils.StructMeta, prefix ...string) Table
- func Struct2Table(ctx context.Context, dir, pre string, existTables []string, db *sqlx.DB, ...) (tables []Table)
- func Table2struct(ctx context.Context, pre, schema string, existTables []string, db *sqlx.DB) (tables []Table)
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ChangeColumn ¶
ChangeColumn change a column definition by Column
func CheckAutoSet ¶
CheckAutoSet check a column is auto generated by database or not
func CheckAutoincrement ¶
CheckAutoincrement check a column is auto increment or not
func CheckUnsigned ¶
CheckUnsigned check a column is unsigned or not
func CreateTable ¶
CreateTable create table from Table
Example ¶
terminator, db, err := Setup()
if err != nil {
panic(err)
}
defer terminator()
defer db.Close()
expectjson := `{"Name":"user_createtable","Columns":[{"Table":"user","Name":"id","Type":"INT","Default":null,"Pk":true,"Nullable":false,"Unsigned":false,"Autoincrement":true,"Extra":"","Meta":{"Name":"ID","Type":"int","Tag":"dd:\"pk;auto\"","Comments":null},"AutoSet":false,"Indexes":null},{"Table":"user","Name":"name","Type":"VARCHAR(255)","Default":"'jack'","Pk":false,"Nullable":false,"Unsigned":false,"Autoincrement":false,"Extra":"","Meta":{"Name":"Name","Type":"string","Tag":"dd:\"index:name_phone_idx,2;default:'jack'\"","Comments":null},"AutoSet":false,"Indexes":null},{"Table":"user","Name":"phone","Type":"VARCHAR(255)","Default":"'13552053960'","Pk":false,"Nullable":false,"Unsigned":false,"Autoincrement":false,"Extra":"comment '手机号'","Meta":{"Name":"Phone","Type":"string","Tag":"dd:\"index:name_phone_idx,1;default:'13552053960';extra:comment '手机号'\"","Comments":null},"AutoSet":false,"Indexes":null},{"Table":"user","Name":"age","Type":"INT","Default":null,"Pk":false,"Nullable":false,"Unsigned":false,"Autoincrement":false,"Extra":"","Meta":{"Name":"Age","Type":"int","Tag":"dd:\"index\"","Comments":null},"AutoSet":false,"Indexes":null},{"Table":"user","Name":"no","Type":"INT","Default":null,"Pk":false,"Nullable":false,"Unsigned":false,"Autoincrement":false,"Extra":"","Meta":{"Name":"No","Type":"int","Tag":"dd:\"unique\"","Comments":null},"AutoSet":false,"Indexes":null},{"Table":"user","Name":"school","Type":"VARCHAR(255)","Default":"'harvard'","Pk":false,"Nullable":true,"Unsigned":false,"Autoincrement":false,"Extra":"comment '学校'","Meta":{"Name":"School","Type":"string","Tag":"dd:\"null;default:'harvard';extra:comment '学校'\"","Comments":null},"AutoSet":false,"Indexes":null},{"Table":"user","Name":"is_student","Type":"TINYINT","Default":null,"Pk":false,"Nullable":false,"Unsigned":false,"Autoincrement":false,"Extra":"","Meta":{"Name":"IsStudent","Type":"bool","Tag":"","Comments":null},"AutoSet":false,"Indexes":null},{"Table":"user","Name":"delete_at","Type":"DATETIME","Default":null,"Pk":false,"Nullable":true,"Unsigned":false,"Autoincrement":false,"Extra":"","Meta":{"Name":"DeleteAt","Type":"*time.Time","Tag":"","Comments":null},"AutoSet":false,"Indexes":null},{"Table":"user","Name":"create_at","Type":"DATETIME","Default":"CURRENT_TIMESTAMP","Pk":false,"Nullable":true,"Unsigned":false,"Autoincrement":false,"Extra":"","Meta":{"Name":"CreateAt","Type":"*time.Time","Tag":"dd:\"default:CURRENT_TIMESTAMP\"","Comments":null},"AutoSet":true,"Indexes":null},{"Table":"user","Name":"update_at","Type":"DATETIME","Default":"CURRENT_TIMESTAMP","Pk":false,"Nullable":true,"Unsigned":false,"Autoincrement":false,"Extra":"ON UPDATE CURRENT_TIMESTAMP","Meta":{"Name":"UpdateAt","Type":"*time.Time","Tag":"dd:\"default:CURRENT_TIMESTAMP;extra:ON UPDATE CURRENT_TIMESTAMP\"","Comments":null},"AutoSet":true,"Indexes":null}],"Pk":"id","Indexes":[{"Unique":false,"Name":"name_phone_idx","Items":[{"Unique":false,"Name":"","Column":"phone","Order":1,"Sort":"asc"},{"Unique":false,"Name":"","Column":"name","Order":2,"Sort":"asc"}]},{"Unique":false,"Name":"age_idx","Items":[{"Unique":false,"Name":"","Column":"age","Order":1,"Sort":"asc"}]},{"Unique":true,"Name":"no_idx","Items":[{"Unique":false,"Name":"","Column":"no","Order":1,"Sort":"asc"}]}],"Meta":{"Name":"User","Fields":[{"Name":"ID","Type":"int","Tag":"dd:\"pk;auto\"","Comments":null},{"Name":"Name","Type":"string","Tag":"dd:\"index:name_phone_idx,2;default:'jack'\"","Comments":null},{"Name":"Phone","Type":"string","Tag":"dd:\"index:name_phone_idx,1;default:'13552053960';extra:comment '手机号'\"","Comments":null},{"Name":"Age","Type":"int","Tag":"dd:\"index\"","Comments":null},{"Name":"No","Type":"int","Tag":"dd:\"unique\"","Comments":null},{"Name":"School","Type":"string","Tag":"dd:\"null;default:'harvard';extra:comment '学校'\"","Comments":null},{"Name":"IsStudent","Type":"bool","Tag":"","Comments":null},{"Name":"DeleteAt","Type":"*time.Time","Tag":"","Comments":null},{"Name":"CreateAt","Type":"*time.Time","Tag":"dd:\"default:CURRENT_TIMESTAMP\"","Comments":null},{"Name":"UpdateAt","Type":"*time.Time","Tag":"dd:\"default:CURRENT_TIMESTAMP;extra:ON UPDATE CURRENT_TIMESTAMP\"","Comments":null}],"Comments":["dd:table"],"Methods":null}}`
var table Table
if err = json.Unmarshal([]byte(expectjson), &table); err != nil {
panic(err)
}
if err := CreateTable(context.Background(), db, table); (err != nil) != false {
panic(fmt.Sprintf("CreateTable() error = %v, wantErr %v", err, false))
}
Output: CREATE TABLE `user_createtable` ( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) NOT NULL DEFAULT 'jack', `phone` VARCHAR(255) NOT NULL DEFAULT '13552053960' comment '手机号', `age` INT NOT NULL, `no` INT NOT NULL, `school` VARCHAR(255) NULL DEFAULT 'harvard' comment '学校', `is_student` TINYINT NOT NULL, `delete_at` DATETIME NULL, `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP, `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), INDEX `name_phone_idx` (`phone` asc,`name` asc), INDEX `age_idx` (`age` asc), UNIQUE INDEX `no_idx` (`no` asc))
func NewFieldFromColumn ¶
NewFieldFromColumn creates an astutils.FieldMeta instance from col
Types ¶
type Column ¶
type Column struct {
Table string
Name string
Type columnenum.ColumnType
Default string
Pk bool
Nullable bool
Unsigned bool
Autoincrement bool
Extra extraenum.Extra
Meta astutils.FieldMeta
AutoSet bool
Indexes []IndexItem
Fk ForeignKey
}
Column define a column
func (*Column) AddColumnSql ¶
AddColumnSql return add column sql
func (*Column) ChangeColumnSql ¶
ChangeColumnSql return change column sql
type DbAction ¶
type DbAction struct {
TableName string `db:"TABLE_NAME"`
ConstraintName string `db:"CONSTRAINT_NAME"`
ReferencedTableName string `db:"REFERENCED_TABLE_NAME"`
UpdateRule string `db:"UPDATE_RULE"`
DeleteRule string `db:"DELETE_RULE"`
}
DbAction from information_schema.REFERENTIAL_CONSTRAINTS
type DbColumn ¶
type DbColumn struct {
Field string `db:"Field"`
Type string `db:"Type"`
Null nullenum.Null `db:"Null"`
Key keyenum.Key `db:"Key"`
Default *string `db:"Default"`
Extra string `db:"Extra"`
Comment string `db:"Comment"`
}
DbColumn defines a column
type DbForeignKey ¶
type DbForeignKey struct {
TableName string `db:"TABLE_NAME"`
ColumnName string `db:"COLUMN_NAME"`
ConstraintName string `db:"CONSTRAINT_NAME"`
ReferencedTableName string `db:"REFERENCED_TABLE_NAME"`
ReferencedColumnName string `db:"REFERENCED_COLUMN_NAME"`
}
DbForeignKey from INFORMATION_SCHEMA.KEY_COLUMN_USAGE
type DbIndex ¶
type DbIndex struct {
Table string `db:"Table"` // The name of the table
NonUnique bool `db:"Non_unique"` // 1 if the index can contain duplicates, 0 if it cannot.
KeyName string `db:"Key_name"` // The name of the index. The primary key index always has the name of PRIMARY.
SeqInIndex int `db:"Seq_in_index"` // The column sequence number in the index. The first column sequence number starts from 1.
ColumnName string `db:"Column_name"` // The column name
Collation string `db:"Collation"` // Collation represents how the column is sorted in the index. A means ascending, B means descending, or NULL means not sorted.
}
DbIndex defines an index refer to https://www.mysqltutorial.org/mysql-index/mysql-show-indexes/
type ForeignKey ¶
type ForeignKey struct {
// Table the child table
Table string
// Constraint name of foreign key constraint
Constraint string
// Fk foreign key
Fk string
// ReferencedTable the referenced table
ReferencedTable string
// ReferencedCol the referenced column of ReferencedTable
ReferencedCol string
UpdateRule string
DeleteRule string
FullRule string
}
func (*ForeignKey) AddFkSql ¶
func (fk *ForeignKey) AddFkSql() (string, error)
func (*ForeignKey) DropFkSql ¶
func (fk *ForeignKey) DropFkSql() (string, error)
type Index ¶
Index define an index
func NewIndexFromDbIndexes ¶
func (*Index) AddIndexSql ¶
func (*Index) DropIndexSql ¶
type IndexItems ¶
type IndexItems []IndexItem
IndexItems slice type alias for IndexItem
func (IndexItems) Swap ¶
func (it IndexItems) Swap(i, j int)
Swap change position of elements at i and j
type Table ¶
type Table struct {
Name string
Columns []Column
Pk string
Indexes []Index
Meta astutils.StructMeta
Fks []ForeignKey
}
Table defines a table
func NewTableFromStruct ¶
func NewTableFromStruct(structMeta astutils.StructMeta, prefix ...string) Table
NewTableFromStruct creates a Table instance from structMeta
Example ¶
testDir := pathutils.Abs("../testdata/domain")
var files []string
var err error
err = filepath.Walk(testDir, astutils.Visit(&files))
if err != nil {
panic(err)
}
sc := astutils.NewStructCollector(astutils.ExprString)
for _, file := range files {
fset := token.NewFileSet()
root, err := parser.ParseFile(fset, file, nil, parser.ParseComments)
if err != nil {
panic(err)
}
ast.Walk(sc, root)
}
flattened := ddlast.FlatEmbed(sc.Structs)
for _, sm := range flattened {
tab := NewTableFromStruct(sm)
fmt.Println(len(tab.Indexes))
var statement string
if statement, err = tab.CreateSql(); err != nil {
panic(err)
}
fmt.Println(statement)
}
Output: 0 CREATE TABLE `order` ( `id` INT NOT NULL AUTO_INCREMENT, `amount` BIGINT NOT NULL, `user_id` int NOT NULL, `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP, `delete_at` DATETIME NULL, `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), CONSTRAINT `fk_ddl_user` FOREIGN KEY (`user_id`) REFERENCES `ddl_user`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION) 5 CREATE TABLE `user` ( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) NOT NULL DEFAULT 'jack', `phone` VARCHAR(255) NOT NULL DEFAULT '13552053960' comment '手机号', `age` INT NOT NULL, `no` int NOT NULL, `unique_col` int NOT NULL, `unique_col_2` int NOT NULL, `school` VARCHAR(255) NULL DEFAULT 'harvard' comment '学校', `is_student` TINYINT NOT NULL, `rule` varchar(255) NOT NULL comment '链接匹配规则,匹配的链接采用该css规则来爬', `rule_type` varchar(45) NOT NULL comment '链接匹配规则类型,支持prefix前缀匹配和regex正则匹配', `arrive_at` datetime NULL comment '到货时间', `status` tinyint(4) NOT NULL comment '0进行中 1完结 2取消', `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP, `delete_at` DATETIME NULL, `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), INDEX `age_idx` (`age` asc), INDEX `name_phone_idx` (`phone` asc,`name` asc), UNIQUE INDEX `no_idx` (`no` asc), UNIQUE INDEX `rule_idx` (`rule` asc), UNIQUE INDEX `unique_col_idx` (`unique_col` asc,`unique_col_2` asc))
func Struct2Table ¶
func Struct2Table(ctx context.Context, dir, pre string, existTables []string, db *sqlx.DB, schema string) (tables []Table)
Example ¶
terminator, db, err := Setup()
if err != nil {
panic(err)
}
defer terminator()
defer db.Close()
_ = Struct2Table(context.Background(), "../testdata/domain", "ddl_", []string{"ddl_user", "ddl_book"}, db, "test")
Output: CREATE TABLE `ddl_order` ( `id` INT NOT NULL AUTO_INCREMENT, `amount` BIGINT NOT NULL, `user_id` int NOT NULL, `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP, `delete_at` DATETIME NULL, `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), CONSTRAINT `fk_ddl_user` FOREIGN KEY (`user_id`) REFERENCES `ddl_user`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION) ALTER TABLE `ddl_user` CHANGE COLUMN `id` `id` INT NOT NULL AUTO_INCREMENT; ALTER TABLE `ddl_user` CHANGE COLUMN `name` `name` VARCHAR(255) NOT NULL DEFAULT 'jack'; ALTER TABLE `ddl_user` CHANGE COLUMN `phone` `phone` VARCHAR(255) NOT NULL DEFAULT '13552053960' comment '手机号'; ALTER TABLE `ddl_user` CHANGE COLUMN `age` `age` INT NOT NULL; ALTER TABLE `ddl_user` CHANGE COLUMN `no` `no` int NOT NULL; ALTER TABLE `ddl_user` ADD COLUMN `unique_col` int NOT NULL; ALTER TABLE `ddl_user` ADD COLUMN `unique_col_2` int NOT NULL; ALTER TABLE `ddl_user` CHANGE COLUMN `school` `school` VARCHAR(255) NULL DEFAULT 'harvard' comment '学校'; ALTER TABLE `ddl_user` CHANGE COLUMN `is_student` `is_student` TINYINT NOT NULL; ALTER TABLE `ddl_user` ADD COLUMN `rule` varchar(255) NOT NULL comment '链接匹配规则,匹配的链接采用该css规则来爬'; ALTER TABLE `ddl_user` ADD COLUMN `rule_type` varchar(45) NOT NULL comment '链接匹配规则类型,支持prefix前缀匹配和regex正则匹配'; ALTER TABLE `ddl_user` ADD COLUMN `arrive_at` datetime NULL comment '到货时间'; ALTER TABLE `ddl_user` ADD COLUMN `status` tinyint(4) NOT NULL comment '0进行中 1完结 2取消'; ALTER TABLE `ddl_user` CHANGE COLUMN `create_at` `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP; ALTER TABLE `ddl_user` CHANGE COLUMN `delete_at` `delete_at` DATETIME NULL; ALTER TABLE `ddl_user` CHANGE COLUMN `update_at` `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; ALTER TABLE `ddl_user` ADD UNIQUE INDEX `rule_idx` (`rule` asc); ALTER TABLE `ddl_user` ADD UNIQUE INDEX `unique_col_idx` (`unique_col` asc,`unique_col_2` asc);