github.com/unionj-cloud/go-doudou@v1.3.8-0.20221011095552-0088008e5b31/cmd/internal/ddl/table/ddl_test.go (about) 1 package table 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 _ "github.com/go-sql-driver/mysql" 8 "github.com/jmoiron/sqlx" 9 "github.com/stretchr/testify/assert" 10 "github.com/unionj-cloud/go-doudou/cmd/internal/ddl/columnenum" 11 "github.com/unionj-cloud/go-doudou/cmd/internal/ddl/sortenum" 12 "github.com/unionj-cloud/go-doudou/toolkit/sqlext/wrapper" 13 "reflect" 14 "testing" 15 ) 16 17 func ExampleCreateTable() { 18 terminator, db, err := Setup() 19 if err != nil { 20 panic(err) 21 } 22 defer terminator() 23 defer db.Close() 24 25 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}}` 26 var table Table 27 if err = json.Unmarshal([]byte(expectjson), &table); err != nil { 28 panic(err) 29 } 30 if err := CreateTable(context.Background(), db, table); (err != nil) != false { 31 panic(fmt.Sprintf("CreateTable() error = %v, wantErr %v", err, false)) 32 } 33 34 // Output: 35 //CREATE TABLE `user_createtable` ( 36 //`id` INT NOT NULL AUTO_INCREMENT, 37 //`name` VARCHAR(255) NOT NULL DEFAULT 'jack', 38 //`phone` VARCHAR(255) NOT NULL DEFAULT '13552053960' comment '手机号', 39 //`age` INT NOT NULL, 40 //`no` INT NOT NULL, 41 //`school` VARCHAR(255) NULL DEFAULT 'harvard' comment '学校', 42 //`is_student` TINYINT NOT NULL, 43 //`delete_at` DATETIME NULL, 44 //`create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP, 45 //`update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 46 //PRIMARY KEY (`id`), 47 //INDEX `name_phone_idx` (`phone` asc,`name` asc), 48 //INDEX `age_idx` (`age` asc), 49 //UNIQUE INDEX `no_idx` (`no` asc)) 50 } 51 52 func TestChangeColumn(t *testing.T) { 53 terminator, db, err := Setup() 54 if err != nil { 55 panic(err) 56 } 57 defer terminator() 58 defer db.Close() 59 60 type args struct { 61 db *sqlx.DB 62 col Column 63 } 64 tests := []struct { 65 name string 66 args args 67 wantErr bool 68 errmsg string 69 }{ 70 { 71 name: "1", 72 args: args{ 73 db: db, 74 col: Column{ 75 Table: "ddl_user", 76 Name: "school", 77 Type: "varchar(45)", 78 Default: "'Beijing Univ.'", 79 }, 80 }, 81 wantErr: false, 82 }, 83 { 84 name: "2", 85 args: args{ 86 db: db, 87 col: Column{ 88 Table: "ddl_user", 89 Name: "school", 90 Type: columnenum.TextType, 91 Default: "'Beijing Univ.'", 92 }, 93 }, 94 wantErr: true, 95 errmsg: `Error 1101: BLOB, TEXT, GEOMETRY or JSON column 'school' can't have a default value`, 96 }, 97 { 98 name: "3", 99 args: args{ 100 db: db, 101 col: Column{ 102 Table: "ddl_user", 103 Name: "school", 104 Type: "varchar(45)", 105 Default: "Beijing Univ.", 106 }, 107 }, 108 wantErr: true, 109 errmsg: `Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Beijing Univ.' at line 2`, 110 }, 111 } 112 for _, tt := range tests { 113 t.Run(tt.name, func(t *testing.T) { 114 var err error 115 if err = ChangeColumn(context.Background(), tt.args.db, tt.args.col); (err != nil) != tt.wantErr { 116 t.Errorf("ChangeColumn() error = %v, wantErr %v", err, tt.wantErr) 117 } 118 if err != nil { 119 if err.Error() != tt.errmsg { 120 t.Errorf("want %s, got %s", tt.errmsg, err.Error()) 121 } 122 } 123 }) 124 } 125 } 126 127 func TestAddColumn(t *testing.T) { 128 terminator, db, err := Setup() 129 if err != nil { 130 panic(err) 131 } 132 defer terminator() 133 defer db.Close() 134 135 type args struct { 136 db *sqlx.DB 137 col Column 138 } 139 tests := []struct { 140 name string 141 args args 142 wantErr bool 143 errmsg string 144 }{ 145 { 146 name: "1", 147 args: args{ 148 db: db, 149 col: Column{ 150 Table: "ddl_user", 151 Name: "favourite", 152 Type: "varchar(45)", 153 Default: "'football'", 154 }, 155 }, 156 wantErr: false, 157 }, 158 } 159 for _, tt := range tests { 160 t.Run(tt.name, func(t *testing.T) { 161 var err error 162 if err = AddColumn(context.Background(), tt.args.db, tt.args.col); (err != nil) != tt.wantErr { 163 t.Errorf("ChangeColumn() error = %v, wantErr %v", err, tt.wantErr) 164 } 165 }) 166 } 167 } 168 169 func TestDropIndex(t *testing.T) { 170 terminator, db, err := Setup() 171 if err != nil { 172 panic(err) 173 } 174 defer terminator() 175 defer db.Close() 176 177 type args struct { 178 ctx context.Context 179 db wrapper.Querier 180 idx Index 181 } 182 tests := []struct { 183 name string 184 args args 185 wantErr bool 186 }{ 187 { 188 name: "", 189 args: args{ 190 ctx: context.Background(), 191 db: db, 192 idx: Index{ 193 Table: "ddl_user", 194 Unique: true, 195 Name: "age_idx", 196 Items: []IndexItem{ 197 { 198 Column: "age", 199 Order: 1, 200 Sort: sortenum.Asc, 201 }, 202 }, 203 }, 204 }, 205 wantErr: false, 206 }, 207 } 208 for _, tt := range tests { 209 t.Run(tt.name, func(t *testing.T) { 210 if err := dropIndex(tt.args.ctx, tt.args.db, tt.args.idx); (err != nil) != tt.wantErr { 211 t.Errorf("dropIndex() error = %v, wantErr %v", err, tt.wantErr) 212 } 213 }) 214 } 215 } 216 217 func TestAddIndex(t *testing.T) { 218 terminator, db, err := Setup() 219 if err != nil { 220 panic(err) 221 } 222 defer terminator() 223 defer db.Close() 224 225 type args struct { 226 ctx context.Context 227 db wrapper.Querier 228 idx Index 229 } 230 tests := []struct { 231 name string 232 args args 233 wantErr bool 234 }{ 235 { 236 name: "", 237 args: args{ 238 ctx: context.Background(), 239 db: db, 240 idx: Index{ 241 Table: "ddl_user", 242 Unique: true, 243 Name: "school_idx", 244 Items: []IndexItem{ 245 { 246 Column: "school", 247 Order: 1, 248 Sort: sortenum.Asc, 249 }, 250 }, 251 }, 252 }, 253 wantErr: false, 254 }, 255 } 256 for _, tt := range tests { 257 t.Run(tt.name, func(t *testing.T) { 258 if err := addIndex(tt.args.ctx, tt.args.db, tt.args.idx); (err != nil) != tt.wantErr { 259 t.Errorf("addIndex() error = %v, wantErr %v", err, tt.wantErr) 260 } 261 }) 262 } 263 } 264 265 func TestDropAddIndex(t *testing.T) { 266 terminator, db, err := Setup() 267 if err != nil { 268 panic(err) 269 } 270 defer terminator() 271 defer db.Close() 272 273 type args struct { 274 ctx context.Context 275 db wrapper.Querier 276 idx Index 277 } 278 tests := []struct { 279 name string 280 args args 281 wantErr bool 282 }{ 283 { 284 name: "", 285 args: args{ 286 ctx: context.Background(), 287 db: db, 288 idx: Index{ 289 Table: "ddl_user", 290 Unique: true, 291 Name: "age_idx", 292 Items: []IndexItem{ 293 { 294 Column: "age", 295 Order: 1, 296 Sort: sortenum.Asc, 297 }, 298 { 299 Column: "school", 300 Order: 2, 301 Sort: sortenum.Asc, 302 }, 303 }, 304 }, 305 }, 306 wantErr: false, 307 }, 308 } 309 for _, tt := range tests { 310 t.Run(tt.name, func(t *testing.T) { 311 if err := dropAddIndex(tt.args.ctx, tt.args.db, tt.args.idx); (err != nil) != tt.wantErr { 312 t.Errorf("dropAddIndex() error = %v, wantErr %v", err, tt.wantErr) 313 } 314 }) 315 } 316 } 317 318 func Test_foreignKeys(t *testing.T) { 319 terminator, db, err := Setup() 320 if err != nil { 321 panic(err) 322 } 323 defer terminator() 324 defer db.Close() 325 326 type args struct { 327 ctx context.Context 328 db *sqlx.DB 329 schema string 330 t string 331 } 332 tests := []struct { 333 name string 334 args args 335 wantFks []ForeignKey 336 }{ 337 { 338 name: "", 339 args: args{ 340 ctx: context.Background(), 341 db: db, 342 schema: "test", 343 t: "ddl_book", 344 }, 345 wantFks: []ForeignKey{ 346 { 347 Table: "ddl_book", 348 Constraint: "fk_user", 349 Fk: "user_id", 350 ReferencedTable: "ddl_user", 351 ReferencedCol: "id", 352 UpdateRule: "NO ACTION", 353 DeleteRule: "CASCADE", 354 FullRule: "ON DELETE CASCADE ON UPDATE NO ACTION", 355 }, 356 }, 357 }, 358 } 359 for _, tt := range tests { 360 t.Run(tt.name, func(t *testing.T) { 361 if gotFks := foreignKeys(tt.args.ctx, tt.args.db, tt.args.schema, tt.args.t); !reflect.DeepEqual(gotFks, tt.wantFks) { 362 t.Errorf("foreignKeys() = %v, want %v", gotFks, tt.wantFks) 363 } 364 }) 365 } 366 } 367 368 func TestTable2struct(t *testing.T) { 369 terminator, db, err := Setup() 370 if err != nil { 371 panic(err) 372 } 373 defer terminator() 374 defer db.Close() 375 376 type args struct { 377 ctx context.Context 378 dir string 379 pre string 380 schema string 381 existTables []string 382 db *sqlx.DB 383 } 384 tests := []struct { 385 name string 386 args args 387 wantTables []Table 388 }{ 389 { 390 name: "", 391 args: args{ 392 ctx: context.Background(), 393 pre: "ddl_", 394 schema: "test", 395 existTables: []string{"ddl_book", "ddl_user"}, 396 db: db, 397 }, 398 }, 399 } 400 for _, tt := range tests { 401 assert.NotPanics(t, func() { 402 Table2struct(tt.args.ctx, tt.args.pre, tt.args.schema, tt.args.existTables, tt.args.db) 403 }) 404 } 405 } 406 407 func ExampleStruct2Table() { 408 terminator, db, err := Setup() 409 if err != nil { 410 panic(err) 411 } 412 defer terminator() 413 defer db.Close() 414 415 _ = Struct2Table(context.Background(), "../testdata/domain", "ddl_", []string{"ddl_user", "ddl_book"}, db, "test") 416 // Output: 417 //CREATE TABLE `ddl_order` ( 418 //`id` INT NOT NULL AUTO_INCREMENT, 419 //`amount` BIGINT NOT NULL, 420 //`user_id` int NOT NULL, 421 //`create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP, 422 //`delete_at` DATETIME NULL, 423 //`update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 424 //PRIMARY KEY (`id`), 425 //CONSTRAINT `fk_ddl_user` FOREIGN KEY (`user_id`) 426 //REFERENCES `ddl_user`(`id`) 427 //ON DELETE CASCADE ON UPDATE NO ACTION) 428 //ALTER TABLE `ddl_user` 429 //CHANGE COLUMN `id` `id` INT NOT NULL AUTO_INCREMENT; 430 //ALTER TABLE `ddl_user` 431 //CHANGE COLUMN `name` `name` VARCHAR(255) NOT NULL DEFAULT 'jack'; 432 //ALTER TABLE `ddl_user` 433 //CHANGE COLUMN `phone` `phone` VARCHAR(255) NOT NULL DEFAULT '13552053960' comment '手机号'; 434 //ALTER TABLE `ddl_user` 435 //CHANGE COLUMN `age` `age` INT NOT NULL; 436 //ALTER TABLE `ddl_user` 437 //CHANGE COLUMN `no` `no` int NOT NULL; 438 //ALTER TABLE `ddl_user` 439 //ADD COLUMN `unique_col` int NOT NULL; 440 //ALTER TABLE `ddl_user` 441 //ADD COLUMN `unique_col_2` int NOT NULL; 442 //ALTER TABLE `ddl_user` 443 //CHANGE COLUMN `school` `school` VARCHAR(255) NULL DEFAULT 'harvard' comment '学校'; 444 //ALTER TABLE `ddl_user` 445 //CHANGE COLUMN `is_student` `is_student` TINYINT NOT NULL; 446 //ALTER TABLE `ddl_user` 447 //ADD COLUMN `rule` varchar(255) NOT NULL comment '链接匹配规则,匹配的链接采用该css规则来爬'; 448 //ALTER TABLE `ddl_user` 449 //ADD COLUMN `rule_type` varchar(45) NOT NULL comment '链接匹配规则类型,支持prefix前缀匹配和regex正则匹配'; 450 //ALTER TABLE `ddl_user` 451 //ADD COLUMN `arrive_at` datetime NULL comment '到货时间'; 452 //ALTER TABLE `ddl_user` 453 //ADD COLUMN `status` tinyint(4) NOT NULL comment '0进行中 454 //1完结 455 //2取消'; 456 //ALTER TABLE `ddl_user` 457 //CHANGE COLUMN `create_at` `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP; 458 //ALTER TABLE `ddl_user` 459 //CHANGE COLUMN `delete_at` `delete_at` DATETIME NULL; 460 //ALTER TABLE `ddl_user` 461 //CHANGE COLUMN `update_at` `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; 462 //ALTER TABLE `ddl_user` ADD UNIQUE INDEX `rule_idx` (`rule` asc); 463 //ALTER TABLE `ddl_user` ADD UNIQUE INDEX `unique_col_idx` (`unique_col` asc,`unique_col_2` asc); 464 } 465 466 func ExampleStruct2TableDrapAddFk() { 467 terminator, db, err := Setup() 468 if err != nil { 469 panic(err) 470 } 471 defer terminator() 472 defer db.Close() 473 474 _ = Struct2Table(context.Background(), "../testdata/domain2", "ddl_", []string{"ddl_user", "ddl_book", "ddl_publisher"}, db, "test") 475 // Output: 476 //ALTER TABLE `ddl_book` 477 //CHANGE COLUMN `id` `id` INT NOT NULL AUTO_INCREMENT; 478 //ALTER TABLE `ddl_book` 479 //CHANGE COLUMN `user_id` `user_id` int NOT NULL; 480 //ALTER TABLE `ddl_book` 481 //CHANGE COLUMN `publisher_id` `publisher_id` INT NOT NULL; 482 //ALTER TABLE `ddl_book` 483 //ADD COLUMN `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP; 484 //ALTER TABLE `ddl_book` 485 //ADD COLUMN `delete_at` DATETIME NULL; 486 //ALTER TABLE `ddl_book` 487 //ADD COLUMN `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; 488 //ALTER TABLE `ddl_book` DROP FOREIGN KEY fk_user; 489 //ALTER TABLE `ddl_book` ADD CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES ddl_publisher(id) ON DELETE CASCADE ON UPDATE NO ACTION; 490 //ALTER TABLE `ddl_publisher` 491 //CHANGE COLUMN `id` `id` INT NOT NULL AUTO_INCREMENT; 492 //ALTER TABLE `ddl_publisher` 493 //CHANGE COLUMN `name` `name` VARCHAR(255) NOT NULL; 494 //ALTER TABLE `ddl_publisher` 495 //ADD COLUMN `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP; 496 //ALTER TABLE `ddl_publisher` 497 //ADD COLUMN `delete_at` DATETIME NULL; 498 //ALTER TABLE `ddl_publisher` 499 //ADD COLUMN `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; 500 //ALTER TABLE `ddl_user` 501 //CHANGE COLUMN `id` `id` INT NOT NULL AUTO_INCREMENT; 502 //ALTER TABLE `ddl_user` 503 //CHANGE COLUMN `name` `name` VARCHAR(255) NOT NULL DEFAULT 'jack'; 504 //ALTER TABLE `ddl_user` 505 //CHANGE COLUMN `phone` `phone` VARCHAR(255) NOT NULL DEFAULT '13552053960' comment '手机号'; 506 //ALTER TABLE `ddl_user` 507 //CHANGE COLUMN `age` `age` INT NOT NULL; 508 //ALTER TABLE `ddl_user` 509 //CHANGE COLUMN `no` `no` int NOT NULL; 510 //ALTER TABLE `ddl_user` 511 //ADD COLUMN `unique_col` int NOT NULL; 512 //ALTER TABLE `ddl_user` 513 //ADD COLUMN `unique_col_2` int NOT NULL; 514 //ALTER TABLE `ddl_user` 515 //CHANGE COLUMN `school` `school` VARCHAR(255) NULL DEFAULT 'harvard' comment '学校'; 516 //ALTER TABLE `ddl_user` 517 //CHANGE COLUMN `is_student` `is_student` TINYINT NOT NULL; 518 //ALTER TABLE `ddl_user` 519 //ADD COLUMN `rule` varchar(255) NOT NULL comment '链接匹配规则,匹配的链接采用该css规则来爬'; 520 //ALTER TABLE `ddl_user` 521 //ADD COLUMN `rule_type` varchar(45) NOT NULL comment '链接匹配规则类型,支持prefix前缀匹配和regex正则匹配'; 522 //ALTER TABLE `ddl_user` 523 //ADD COLUMN `arrive_at` datetime NULL comment '到货时间'; 524 //ALTER TABLE `ddl_user` 525 //ADD COLUMN `status` tinyint(4) NOT NULL comment '0进行中 526 //1完结 527 //2取消'; 528 //ALTER TABLE `ddl_user` 529 //CHANGE COLUMN `create_at` `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP; 530 //ALTER TABLE `ddl_user` 531 //CHANGE COLUMN `delete_at` `delete_at` DATETIME NULL; 532 //ALTER TABLE `ddl_user` 533 //CHANGE COLUMN `update_at` `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; 534 //ALTER TABLE `ddl_user` ADD UNIQUE INDEX `rule_idx` (`rule` asc); 535 //ALTER TABLE `ddl_user` ADD UNIQUE INDEX `unique_col_idx` (`unique_col` asc,`unique_col_2` asc); 536 } 537 538 func ExampleStruct2TableShouldDropDropFkAddFk() { 539 terminator, db, err := Setup() 540 if err != nil { 541 panic(err) 542 } 543 defer terminator() 544 defer db.Close() 545 546 _ = Struct2Table(context.Background(), "../testdata/domain3", "ddl_", []string{"ddl_user", "ddl_book", "ddl_publisher"}, db, "test") 547 // Output: 548 //ALTER TABLE `ddl_book` 549 //CHANGE COLUMN `id` `id` INT NOT NULL AUTO_INCREMENT; 550 //ALTER TABLE `ddl_book` 551 //CHANGE COLUMN `user_id` `user_id` int NOT NULL; 552 //ALTER TABLE `ddl_book` 553 //CHANGE COLUMN `publisher_id` `publisher_id` INT NOT NULL; 554 //ALTER TABLE `ddl_book` 555 //ADD COLUMN `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP; 556 //ALTER TABLE `ddl_book` 557 //ADD COLUMN `delete_at` DATETIME NULL; 558 //ALTER TABLE `ddl_book` 559 //ADD COLUMN `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; 560 //ALTER TABLE `ddl_book` ADD CONSTRAINT fk_publisher FOREIGN KEY (publisher_id) REFERENCES ddl_publisher(id) ON DELETE CASCADE ON UPDATE NO ACTION; 561 //ALTER TABLE `ddl_book` DROP FOREIGN KEY fk_user; 562 //ALTER TABLE `ddl_publisher` 563 //CHANGE COLUMN `id` `id` INT NOT NULL AUTO_INCREMENT; 564 //ALTER TABLE `ddl_publisher` 565 //CHANGE COLUMN `name` `name` VARCHAR(255) NOT NULL; 566 //ALTER TABLE `ddl_publisher` 567 //ADD COLUMN `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP; 568 //ALTER TABLE `ddl_publisher` 569 //ADD COLUMN `delete_at` DATETIME NULL; 570 //ALTER TABLE `ddl_publisher` 571 //ADD COLUMN `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; 572 //ALTER TABLE `ddl_user` 573 //CHANGE COLUMN `id` `id` INT NOT NULL AUTO_INCREMENT; 574 //ALTER TABLE `ddl_user` 575 //CHANGE COLUMN `name` `name` VARCHAR(255) NOT NULL DEFAULT 'jack'; 576 //ALTER TABLE `ddl_user` 577 //CHANGE COLUMN `phone` `phone` VARCHAR(255) NOT NULL DEFAULT '13552053960' comment '手机号'; 578 //ALTER TABLE `ddl_user` 579 //CHANGE COLUMN `age` `age` INT NOT NULL; 580 //ALTER TABLE `ddl_user` 581 //CHANGE COLUMN `no` `no` int NOT NULL; 582 //ALTER TABLE `ddl_user` 583 //ADD COLUMN `unique_col` int NOT NULL; 584 //ALTER TABLE `ddl_user` 585 //ADD COLUMN `unique_col_2` int NOT NULL; 586 //ALTER TABLE `ddl_user` 587 //CHANGE COLUMN `school` `school` VARCHAR(255) NULL DEFAULT 'harvard' comment '学校'; 588 //ALTER TABLE `ddl_user` 589 //CHANGE COLUMN `is_student` `is_student` TINYINT NOT NULL; 590 //ALTER TABLE `ddl_user` 591 //ADD COLUMN `rule` varchar(255) NOT NULL comment '链接匹配规则,匹配的链接采用该css规则来爬'; 592 //ALTER TABLE `ddl_user` 593 //ADD COLUMN `rule_type` varchar(45) NOT NULL comment '链接匹配规则类型,支持prefix前缀匹配和regex正则匹配'; 594 //ALTER TABLE `ddl_user` 595 //ADD COLUMN `arrive_at` datetime NULL comment '到货时间'; 596 //ALTER TABLE `ddl_user` 597 //ADD COLUMN `status` tinyint(4) NOT NULL comment '0进行中 598 //1完结 599 //2取消'; 600 //ALTER TABLE `ddl_user` 601 //CHANGE COLUMN `create_at` `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP; 602 //ALTER TABLE `ddl_user` 603 //CHANGE COLUMN `delete_at` `delete_at` DATETIME NULL; 604 //ALTER TABLE `ddl_user` 605 //CHANGE COLUMN `update_at` `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; 606 //ALTER TABLE `ddl_user` ADD UNIQUE INDEX `rule_idx` (`rule` asc); 607 //ALTER TABLE `ddl_user` ADD UNIQUE INDEX `unique_col_idx` (`unique_col` asc,`unique_col_2` asc); 608 //ALTER TABLE `ddl_user` DROP INDEX `age_idx`; 609 } 610 611 func ExampleStruct2TableFkContinue() { 612 terminator, db, err := Setup() 613 if err != nil { 614 panic(err) 615 } 616 defer terminator() 617 defer db.Close() 618 619 _ = Struct2Table(context.Background(), "../testdata/domain4", "ddl_", []string{"ddl_user", "ddl_book", "ddl_publisher"}, db, "test") 620 // Output: 621 //ALTER TABLE `ddl_book` 622 //CHANGE COLUMN `id` `id` INT NOT NULL AUTO_INCREMENT; 623 //ALTER TABLE `ddl_book` 624 //CHANGE COLUMN `user_id` `user_id` int NOT NULL; 625 //ALTER TABLE `ddl_book` 626 //CHANGE COLUMN `publisher_id` `publisher_id` INT NOT NULL; 627 //ALTER TABLE `ddl_book` 628 //ADD COLUMN `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP; 629 //ALTER TABLE `ddl_book` 630 //ADD COLUMN `delete_at` DATETIME NULL; 631 //ALTER TABLE `ddl_book` 632 //ADD COLUMN `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; 633 //ALTER TABLE `ddl_publisher` 634 //CHANGE COLUMN `id` `id` INT NOT NULL AUTO_INCREMENT; 635 //ALTER TABLE `ddl_publisher` 636 //CHANGE COLUMN `name` `name` VARCHAR(255) NOT NULL; 637 //ALTER TABLE `ddl_publisher` 638 //ADD COLUMN `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP; 639 //ALTER TABLE `ddl_publisher` 640 //ADD COLUMN `delete_at` DATETIME NULL; 641 //ALTER TABLE `ddl_publisher` 642 //ADD COLUMN `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; 643 //ALTER TABLE `ddl_user` 644 //CHANGE COLUMN `id` `id` INT NOT NULL AUTO_INCREMENT; 645 //ALTER TABLE `ddl_user` 646 //CHANGE COLUMN `name` `name` VARCHAR(255) NOT NULL DEFAULT 'jack'; 647 //ALTER TABLE `ddl_user` 648 //CHANGE COLUMN `phone` `phone` VARCHAR(255) NOT NULL DEFAULT '13552053960' comment '手机号'; 649 //ALTER TABLE `ddl_user` 650 //CHANGE COLUMN `age` `age` INT NOT NULL; 651 //ALTER TABLE `ddl_user` 652 //CHANGE COLUMN `no` `no` int NOT NULL; 653 //ALTER TABLE `ddl_user` 654 //ADD COLUMN `unique_col` int NOT NULL; 655 //ALTER TABLE `ddl_user` 656 //ADD COLUMN `unique_col_2` int NOT NULL; 657 //ALTER TABLE `ddl_user` 658 //CHANGE COLUMN `school` `school` VARCHAR(255) NULL DEFAULT 'harvard' comment '学校'; 659 //ALTER TABLE `ddl_user` 660 //CHANGE COLUMN `is_student` `is_student` TINYINT NOT NULL; 661 //ALTER TABLE `ddl_user` 662 //ADD COLUMN `rule` varchar(255) NOT NULL comment '链接匹配规则,匹配的链接采用该css规则来爬'; 663 //ALTER TABLE `ddl_user` 664 //ADD COLUMN `rule_type` varchar(45) NOT NULL comment '链接匹配规则类型,支持prefix前缀匹配和regex正则匹配'; 665 //ALTER TABLE `ddl_user` 666 //ADD COLUMN `arrive_at` datetime NULL comment '到货时间'; 667 //ALTER TABLE `ddl_user` 668 //ADD COLUMN `status` tinyint(4) NOT NULL comment '0进行中 669 //1完结 670 //2取消'; 671 //ALTER TABLE `ddl_user` 672 //CHANGE COLUMN `create_at` `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP; 673 //ALTER TABLE `ddl_user` 674 //CHANGE COLUMN `delete_at` `delete_at` DATETIME NULL; 675 //ALTER TABLE `ddl_user` 676 //CHANGE COLUMN `update_at` `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; 677 //ALTER TABLE `ddl_user` DROP INDEX `name_phone_idx`; 678 //ALTER TABLE `ddl_user` ADD INDEX `name_phone_idx` (`school` asc,`name` asc); 679 //ALTER TABLE `ddl_user` ADD UNIQUE INDEX `rule_idx` (`rule` asc); 680 //ALTER TABLE `ddl_user` ADD UNIQUE INDEX `unique_col_idx` (`unique_col` asc,`unique_col_2` asc); 681 //ALTER TABLE `ddl_user` DROP INDEX `age_idx`; 682 } 683 684 func ExampleStruct2TableDropAddIndex_name_phone_idx() { 685 terminator, db, err := Setup() 686 if err != nil { 687 panic(err) 688 } 689 defer terminator() 690 defer db.Close() 691 692 _ = Struct2Table(context.Background(), "../testdata/domain4", "ddl_", []string{"ddl_user", "ddl_book", "ddl_publisher"}, db, "test") 693 // Output: 694 //ALTER TABLE `ddl_book` 695 //CHANGE COLUMN `id` `id` INT NOT NULL AUTO_INCREMENT; 696 //ALTER TABLE `ddl_book` 697 //CHANGE COLUMN `user_id` `user_id` int NOT NULL; 698 //ALTER TABLE `ddl_book` 699 //CHANGE COLUMN `publisher_id` `publisher_id` INT NOT NULL; 700 //ALTER TABLE `ddl_book` 701 //ADD COLUMN `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP; 702 //ALTER TABLE `ddl_book` 703 //ADD COLUMN `delete_at` DATETIME NULL; 704 //ALTER TABLE `ddl_book` 705 //ADD COLUMN `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; 706 //ALTER TABLE `ddl_publisher` 707 //CHANGE COLUMN `id` `id` INT NOT NULL AUTO_INCREMENT; 708 //ALTER TABLE `ddl_publisher` 709 //CHANGE COLUMN `name` `name` VARCHAR(255) NOT NULL; 710 //ALTER TABLE `ddl_publisher` 711 //ADD COLUMN `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP; 712 //ALTER TABLE `ddl_publisher` 713 //ADD COLUMN `delete_at` DATETIME NULL; 714 //ALTER TABLE `ddl_publisher` 715 //ADD COLUMN `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; 716 //ALTER TABLE `ddl_user` 717 //CHANGE COLUMN `id` `id` INT NOT NULL AUTO_INCREMENT; 718 //ALTER TABLE `ddl_user` 719 //CHANGE COLUMN `name` `name` VARCHAR(255) NOT NULL DEFAULT 'jack'; 720 //ALTER TABLE `ddl_user` 721 //CHANGE COLUMN `phone` `phone` VARCHAR(255) NOT NULL DEFAULT '13552053960' comment '手机号'; 722 //ALTER TABLE `ddl_user` 723 //CHANGE COLUMN `age` `age` INT NOT NULL; 724 //ALTER TABLE `ddl_user` 725 //CHANGE COLUMN `no` `no` int NOT NULL; 726 //ALTER TABLE `ddl_user` 727 //ADD COLUMN `unique_col` int NOT NULL; 728 //ALTER TABLE `ddl_user` 729 //ADD COLUMN `unique_col_2` int NOT NULL; 730 //ALTER TABLE `ddl_user` 731 //CHANGE COLUMN `school` `school` VARCHAR(255) NULL DEFAULT 'harvard' comment '学校'; 732 //ALTER TABLE `ddl_user` 733 //CHANGE COLUMN `is_student` `is_student` TINYINT NOT NULL; 734 //ALTER TABLE `ddl_user` 735 //ADD COLUMN `rule` varchar(255) NOT NULL comment '链接匹配规则,匹配的链接采用该css规则来爬'; 736 //ALTER TABLE `ddl_user` 737 //ADD COLUMN `rule_type` varchar(45) NOT NULL comment '链接匹配规则类型,支持prefix前缀匹配和regex正则匹配'; 738 //ALTER TABLE `ddl_user` 739 //ADD COLUMN `arrive_at` datetime NULL comment '到货时间'; 740 //ALTER TABLE `ddl_user` 741 //ADD COLUMN `status` tinyint(4) NOT NULL comment '0进行中 742 //1完结 743 //2取消'; 744 //ALTER TABLE `ddl_user` 745 //CHANGE COLUMN `create_at` `create_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP; 746 //ALTER TABLE `ddl_user` 747 //CHANGE COLUMN `delete_at` `delete_at` DATETIME NULL; 748 //ALTER TABLE `ddl_user` 749 //CHANGE COLUMN `update_at` `update_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; 750 //ALTER TABLE `ddl_user` DROP INDEX `name_phone_idx`; 751 //ALTER TABLE `ddl_user` ADD INDEX `name_phone_idx` (`school` asc,`name` asc); 752 //ALTER TABLE `ddl_user` ADD UNIQUE INDEX `rule_idx` (`rule` asc); 753 //ALTER TABLE `ddl_user` ADD UNIQUE INDEX `unique_col_idx` (`unique_col` asc,`unique_col_2` asc); 754 //ALTER TABLE `ddl_user` DROP INDEX `age_idx`; 755 } 756 757 func Test_addFk(t *testing.T) { 758 terminator, db, err := Setup() 759 if err != nil { 760 panic(err) 761 } 762 defer terminator() 763 defer db.Close() 764 765 type args struct { 766 ctx context.Context 767 db wrapper.Querier 768 fk ForeignKey 769 } 770 tests := []struct { 771 name string 772 args args 773 wantErr bool 774 }{ 775 { 776 name: "", 777 args: args{ 778 ctx: context.Background(), 779 db: db, 780 fk: ForeignKey{ 781 Table: "ddl_book", 782 Constraint: "fk_addFk", 783 Fk: "publisher_id", 784 ReferencedTable: "ddl_publisher", 785 ReferencedCol: "id", 786 UpdateRule: "NO ACTION", 787 DeleteRule: "NO ACTION", 788 FullRule: "ON DELETE NO ACTION ON UPDATE NO ACTION", 789 }, 790 }, 791 wantErr: false, 792 }, 793 } 794 for _, tt := range tests { 795 t.Run(tt.name, func(t *testing.T) { 796 if err := addFk(tt.args.ctx, tt.args.db, tt.args.fk); (err != nil) != tt.wantErr { 797 t.Errorf("addFk() error = %v, wantErr %v", err, tt.wantErr) 798 } 799 }) 800 } 801 } 802 803 func Test_dropFk(t *testing.T) { 804 terminator, db, err := Setup() 805 if err != nil { 806 panic(err) 807 } 808 defer terminator() 809 defer db.Close() 810 811 type args struct { 812 ctx context.Context 813 db wrapper.Querier 814 fk ForeignKey 815 } 816 tests := []struct { 817 name string 818 args args 819 wantErr bool 820 }{ 821 { 822 name: "", 823 args: args{ 824 ctx: context.Background(), 825 db: db, 826 fk: ForeignKey{ 827 Table: "ddl_book", 828 Constraint: "fk_user", 829 Fk: "user_id", 830 ReferencedTable: "ddl_user", 831 ReferencedCol: "id", 832 UpdateRule: "NO ACTION", 833 DeleteRule: "NO ACTION", 834 FullRule: "ON DELETE NO ACTION ON UPDATE NO ACTION", 835 }, 836 }, 837 wantErr: false, 838 }, 839 } 840 for _, tt := range tests { 841 t.Run(tt.name, func(t *testing.T) { 842 if err := dropFk(tt.args.ctx, tt.args.db, tt.args.fk); (err != nil) != tt.wantErr { 843 t.Errorf("addFk() error = %v, wantErr %v", err, tt.wantErr) 844 } 845 }) 846 } 847 } 848 849 func Test_dropAddFk(t *testing.T) { 850 terminator, db, err := Setup() 851 if err != nil { 852 panic(err) 853 } 854 defer terminator() 855 defer db.Close() 856 857 type args struct { 858 ctx context.Context 859 db wrapper.Querier 860 fk ForeignKey 861 } 862 tests := []struct { 863 name string 864 args args 865 wantErr bool 866 }{ 867 { 868 name: "", 869 args: args{ 870 ctx: context.Background(), 871 db: db, 872 fk: ForeignKey{ 873 Table: "ddl_book", 874 Constraint: "fk_user", 875 Fk: "user_id", 876 ReferencedTable: "ddl_publisher", 877 ReferencedCol: "id", 878 UpdateRule: "NO ACTION", 879 DeleteRule: "NO ACTION", 880 FullRule: "ON DELETE NO ACTION ON UPDATE NO ACTION", 881 }, 882 }, 883 wantErr: false, 884 }, 885 } 886 for _, tt := range tests { 887 t.Run(tt.name, func(t *testing.T) { 888 if err := dropAddFk(tt.args.ctx, tt.args.db, tt.args.fk); (err != nil) != tt.wantErr { 889 t.Errorf("addFk() error = %v, wantErr %v", err, tt.wantErr) 890 } 891 }) 892 } 893 }