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