github.com/goravel/framework@v1.13.9/database/gorm/query.go (about) 1 package gorm 2 3 import ( 4 "context" 5 "database/sql" 6 "errors" 7 "fmt" 8 "reflect" 9 10 "github.com/google/wire" 11 "github.com/spf13/cast" 12 "gorm.io/driver/mysql" 13 "gorm.io/driver/postgres" 14 "gorm.io/driver/sqlserver" 15 gormio "gorm.io/gorm" 16 "gorm.io/gorm/clause" 17 18 "github.com/goravel/framework/contracts/config" 19 ormcontract "github.com/goravel/framework/contracts/database/orm" 20 "github.com/goravel/framework/database/gorm/hints" 21 "github.com/goravel/framework/database/orm" 22 "github.com/goravel/framework/support/database" 23 ) 24 25 var QuerySet = wire.NewSet(BuildQueryImpl, wire.Bind(new(ormcontract.Query), new(*QueryImpl))) 26 var _ ormcontract.Query = &QueryImpl{} 27 28 type QueryImpl struct { 29 conditions Conditions 30 config config.Config 31 connection string 32 ctx context.Context 33 instance *gormio.DB 34 queries map[string]*QueryImpl 35 } 36 37 func NewQueryImpl(ctx context.Context, config config.Config, connection string, db *gormio.DB, conditions *Conditions) *QueryImpl { 38 queryImpl := &QueryImpl{ 39 config: config, 40 connection: connection, 41 ctx: ctx, 42 instance: db, 43 queries: make(map[string]*QueryImpl), 44 } 45 46 if conditions != nil { 47 queryImpl.conditions = *conditions 48 } 49 50 return queryImpl 51 } 52 53 func BuildQueryImpl(ctx context.Context, config config.Config, connection string, gorm Gorm) (*QueryImpl, error) { 54 db, err := gorm.Make() 55 if err != nil { 56 return nil, err 57 } 58 if ctx != nil { 59 db = db.WithContext(ctx) 60 } 61 62 return NewQueryImpl(ctx, config, connection, db, nil), nil 63 } 64 65 func (r *QueryImpl) Association(association string) ormcontract.Association { 66 query := r.buildConditions() 67 68 return query.instance.Association(association) 69 } 70 71 func (r *QueryImpl) Begin() (ormcontract.Transaction, error) { 72 tx := r.instance.Begin() 73 74 return NewTransaction(tx, r.config, r.connection), tx.Error 75 } 76 77 func (r *QueryImpl) Driver() ormcontract.Driver { 78 return ormcontract.Driver(r.instance.Dialector.Name()) 79 } 80 81 func (r *QueryImpl) Count(count *int64) error { 82 query := r.buildConditions() 83 84 return query.instance.Count(count).Error 85 } 86 87 func (r *QueryImpl) Create(value any) error { 88 query, err := r.refreshConnection(value) 89 if err != nil { 90 return err 91 } 92 query = query.buildConditions() 93 94 if len(query.instance.Statement.Selects) > 0 && len(query.instance.Statement.Omits) > 0 { 95 return errors.New("cannot set Select and Omits at the same time") 96 } 97 98 if len(query.instance.Statement.Selects) > 0 { 99 return query.selectCreate(value) 100 } 101 102 if len(query.instance.Statement.Omits) > 0 { 103 return query.omitCreate(value) 104 } 105 106 return query.create(value) 107 } 108 109 func (r *QueryImpl) Cursor() (chan ormcontract.Cursor, error) { 110 with := r.conditions.with 111 query := r.buildConditions() 112 r.conditions.with = with 113 114 var err error 115 cursorChan := make(chan ormcontract.Cursor) 116 go func() { 117 var rows *sql.Rows 118 rows, err = query.instance.Rows() 119 if err != nil { 120 return 121 } 122 defer rows.Close() 123 124 for rows.Next() { 125 val := make(map[string]any) 126 err = query.instance.ScanRows(rows, val) 127 if err != nil { 128 return 129 } 130 cursorChan <- &CursorImpl{query: r, row: val} 131 } 132 close(cursorChan) 133 }() 134 return cursorChan, err 135 } 136 137 func (r *QueryImpl) Delete(dest any, conds ...any) (*ormcontract.Result, error) { 138 query, err := r.refreshConnection(dest) 139 if err != nil { 140 return nil, err 141 } 142 query = query.buildConditions() 143 144 if err := query.deleting(dest); err != nil { 145 return nil, err 146 } 147 148 res := query.instance.Delete(dest, conds...) 149 if res.Error != nil { 150 return nil, res.Error 151 } 152 153 if err := query.deleted(dest); err != nil { 154 return nil, err 155 } 156 157 return &ormcontract.Result{ 158 RowsAffected: res.RowsAffected, 159 }, nil 160 } 161 162 func (r *QueryImpl) Distinct(args ...any) ormcontract.Query { 163 conditions := r.conditions 164 conditions.distinct = append(conditions.distinct, args...) 165 166 return r.setConditions(conditions) 167 } 168 169 func (r *QueryImpl) Exec(sql string, values ...any) (*ormcontract.Result, error) { 170 query := r.buildConditions() 171 result := query.instance.Exec(sql, values...) 172 173 return &ormcontract.Result{ 174 RowsAffected: result.RowsAffected, 175 }, result.Error 176 } 177 178 func (r *QueryImpl) Find(dest any, conds ...any) error { 179 query, err := r.refreshConnection(dest) 180 if err != nil { 181 return err 182 } 183 184 query = query.buildConditions() 185 186 if err := filterFindConditions(conds...); err != nil { 187 return err 188 } 189 if err := query.instance.Find(dest, conds...).Error; err != nil { 190 return err 191 } 192 193 return query.retrieved(dest) 194 } 195 196 func (r *QueryImpl) FindOrFail(dest any, conds ...any) error { 197 query, err := r.refreshConnection(dest) 198 if err != nil { 199 return err 200 } 201 202 query = query.buildConditions() 203 204 if err := filterFindConditions(conds...); err != nil { 205 return err 206 } 207 208 res := query.instance.Find(dest, conds...) 209 if err := res.Error; err != nil { 210 return err 211 } 212 213 if res.RowsAffected == 0 { 214 return orm.ErrRecordNotFound 215 } 216 217 return query.retrieved(dest) 218 } 219 220 func (r *QueryImpl) First(dest any) error { 221 query, err := r.refreshConnection(dest) 222 if err != nil { 223 return err 224 } 225 226 query = query.buildConditions() 227 228 res := query.instance.First(dest) 229 if res.Error != nil { 230 if errors.Is(res.Error, gormio.ErrRecordNotFound) { 231 return nil 232 } 233 234 return res.Error 235 } 236 237 return query.retrieved(dest) 238 } 239 240 func (r *QueryImpl) FirstOr(dest any, callback func() error) error { 241 query, err := r.refreshConnection(dest) 242 if err != nil { 243 return err 244 } 245 246 query = query.buildConditions() 247 248 if err := query.instance.First(dest).Error; err != nil { 249 if errors.Is(err, gormio.ErrRecordNotFound) { 250 return callback() 251 } 252 253 return err 254 } 255 256 return query.retrieved(dest) 257 } 258 259 func (r *QueryImpl) FirstOrCreate(dest any, conds ...any) error { 260 query, err := r.refreshConnection(dest) 261 if err != nil { 262 return err 263 } 264 265 query = query.buildConditions() 266 267 if len(conds) == 0 { 268 return errors.New("query condition is require") 269 } 270 271 var res *gormio.DB 272 if len(conds) > 1 { 273 res = query.instance.Attrs(conds[1]).FirstOrInit(dest, conds[0]) 274 } else { 275 res = query.instance.FirstOrInit(dest, conds[0]) 276 } 277 278 if res.Error != nil { 279 return res.Error 280 } 281 if res.RowsAffected > 0 { 282 return query.retrieved(dest) 283 } 284 285 return query.Create(dest) 286 } 287 288 func (r *QueryImpl) FirstOrFail(dest any) error { 289 query, err := r.refreshConnection(dest) 290 if err != nil { 291 return err 292 } 293 294 query = query.buildConditions() 295 296 if err := query.instance.First(dest).Error; err != nil { 297 if errors.Is(err, gormio.ErrRecordNotFound) { 298 return orm.ErrRecordNotFound 299 } 300 301 return err 302 } 303 304 return query.retrieved(dest) 305 } 306 307 func (r *QueryImpl) FirstOrNew(dest any, attributes any, values ...any) error { 308 query, err := r.refreshConnection(dest) 309 if err != nil { 310 return err 311 } 312 313 query = query.buildConditions() 314 315 var res *gormio.DB 316 if len(values) > 0 { 317 res = query.instance.Attrs(values[0]).FirstOrInit(dest, attributes) 318 } else { 319 res = query.instance.FirstOrInit(dest, attributes) 320 } 321 322 if res.Error != nil { 323 return res.Error 324 } 325 if res.RowsAffected > 0 { 326 return query.retrieved(dest) 327 } 328 329 return nil 330 } 331 332 func (r *QueryImpl) ForceDelete(value any, conds ...any) (*ormcontract.Result, error) { 333 query, err := r.refreshConnection(value) 334 if err != nil { 335 return nil, err 336 } 337 338 query = query.buildConditions() 339 340 if err := query.forceDeleting(value); err != nil { 341 return nil, err 342 } 343 344 res := query.instance.Unscoped().Delete(value, conds...) 345 if res.Error != nil { 346 return nil, res.Error 347 } 348 349 if res.RowsAffected > 0 { 350 if err := query.forceDeleted(value); err != nil { 351 return nil, err 352 } 353 } 354 355 return &ormcontract.Result{ 356 RowsAffected: res.RowsAffected, 357 }, res.Error 358 } 359 360 func (r *QueryImpl) Get(dest any) error { 361 return r.Find(dest) 362 } 363 364 func (r *QueryImpl) Group(name string) ormcontract.Query { 365 conditions := r.conditions 366 conditions.group = name 367 368 return r.setConditions(conditions) 369 } 370 371 func (r *QueryImpl) Having(query any, args ...any) ormcontract.Query { 372 conditions := r.conditions 373 conditions.having = &Having{ 374 query: query, 375 args: args, 376 } 377 378 return r.setConditions(conditions) 379 } 380 381 func (r *QueryImpl) Instance() *gormio.DB { 382 return r.instance 383 } 384 385 func (r *QueryImpl) Join(query string, args ...any) ormcontract.Query { 386 conditions := r.conditions 387 conditions.join = append(conditions.join, Join{ 388 query: query, 389 args: args, 390 }) 391 392 return r.setConditions(conditions) 393 } 394 395 func (r *QueryImpl) Limit(limit int) ormcontract.Query { 396 conditions := r.conditions 397 conditions.limit = &limit 398 399 return r.setConditions(conditions) 400 } 401 402 func (r *QueryImpl) Load(model any, relation string, args ...any) error { 403 if relation == "" { 404 return errors.New("relation cannot be empty") 405 } 406 407 destType := reflect.TypeOf(model) 408 if destType.Kind() != reflect.Pointer { 409 return errors.New("model must be pointer") 410 } 411 412 if id := database.GetID(model); id == nil { 413 return errors.New("id cannot be empty") 414 } 415 416 copyDest := copyStruct(model) 417 err := r.With(relation, args...).Find(model) 418 419 t := destType.Elem() 420 v := reflect.ValueOf(model).Elem() 421 for i := 0; i < t.NumField(); i++ { 422 if !t.Field(i).IsExported() { 423 continue 424 } 425 if t.Field(i).Name != relation { 426 v.Field(i).Set(copyDest.Field(i)) 427 } 428 } 429 430 return err 431 } 432 433 func (r *QueryImpl) LoadMissing(model any, relation string, args ...any) error { 434 destType := reflect.TypeOf(model) 435 if destType.Kind() != reflect.Pointer { 436 return errors.New("model must be pointer") 437 } 438 439 t := reflect.TypeOf(model).Elem() 440 v := reflect.ValueOf(model).Elem() 441 for i := 0; i < t.NumField(); i++ { 442 if !t.Field(i).IsExported() { 443 continue 444 } 445 if t.Field(i).Name == relation { 446 var id any 447 if v.Field(i).Kind() == reflect.Pointer { 448 if !v.Field(i).IsNil() { 449 id = database.GetIDByReflect(v.Field(i).Type().Elem(), v.Field(i).Elem()) 450 } 451 } else if v.Field(i).Kind() == reflect.Slice { 452 if v.Field(i).Len() > 0 { 453 return nil 454 } 455 } else { 456 id = database.GetIDByReflect(v.Field(i).Type(), v.Field(i)) 457 } 458 if cast.ToString(id) != "" { 459 return nil 460 } 461 } 462 } 463 464 return r.Load(model, relation, args...) 465 } 466 467 func (r *QueryImpl) LockForUpdate() ormcontract.Query { 468 conditions := r.conditions 469 conditions.lockForUpdate = true 470 471 return r.setConditions(conditions) 472 } 473 474 func (r *QueryImpl) Model(value any) ormcontract.Query { 475 conditions := r.conditions 476 conditions.model = value 477 478 return r.setConditions(conditions) 479 } 480 481 func (r *QueryImpl) Offset(offset int) ormcontract.Query { 482 conditions := r.conditions 483 conditions.offset = &offset 484 485 return r.setConditions(conditions) 486 } 487 488 func (r *QueryImpl) Omit(columns ...string) ormcontract.Query { 489 conditions := r.conditions 490 conditions.omit = columns 491 492 return r.setConditions(conditions) 493 } 494 495 func (r *QueryImpl) Order(value any) ormcontract.Query { 496 conditions := r.conditions 497 conditions.order = append(r.conditions.order, value) 498 499 return r.setConditions(conditions) 500 } 501 502 func (r *QueryImpl) OrWhere(query any, args ...any) ormcontract.Query { 503 conditions := r.conditions 504 conditions.where = append(r.conditions.where, Where{ 505 query: query, 506 args: args, 507 or: true, 508 }) 509 510 return r.setConditions(conditions) 511 } 512 513 func (r *QueryImpl) Paginate(page, limit int, dest any, total *int64) error { 514 query, err := r.refreshConnection(dest) 515 if err != nil { 516 return err 517 } 518 519 query = query.buildConditions() 520 521 offset := (page - 1) * limit 522 if total != nil { 523 if query.conditions.table == nil && query.conditions.model == nil { 524 if err := query.Model(dest).Count(total); err != nil { 525 return err 526 } 527 } else { 528 if err := query.Count(total); err != nil { 529 return err 530 } 531 } 532 } 533 534 return query.Offset(offset).Limit(limit).Find(dest) 535 } 536 537 func (r *QueryImpl) Pluck(column string, dest any) error { 538 query := r.buildConditions() 539 540 return query.instance.Pluck(column, dest).Error 541 } 542 543 func (r *QueryImpl) Raw(sql string, values ...any) ormcontract.Query { 544 return r.new(r.instance.Raw(sql, values...)) 545 } 546 547 func (r *QueryImpl) Save(value any) error { 548 query, err := r.refreshConnection(value) 549 if err != nil { 550 return err 551 } 552 553 query = query.buildConditions() 554 555 if len(query.instance.Statement.Selects) > 0 && len(query.instance.Statement.Omits) > 0 { 556 return errors.New("cannot set Select and Omits at the same time") 557 } 558 559 model := query.instance.Statement.Model 560 id := database.GetID(value) 561 update := id != nil 562 563 if err := query.saving(model, value); err != nil { 564 return err 565 } 566 if update { 567 if err := query.updating(model, value); err != nil { 568 return err 569 } 570 } else { 571 if err := query.creating(value); err != nil { 572 return err 573 } 574 } 575 576 if len(query.instance.Statement.Selects) > 0 { 577 if err := query.selectSave(value); err != nil { 578 return err 579 } 580 } else if len(query.instance.Statement.Omits) > 0 { 581 if err := query.omitSave(value); err != nil { 582 return err 583 } 584 } else { 585 if err := query.save(value); err != nil { 586 return err 587 } 588 } 589 590 if update { 591 if err := query.updated(model, value); err != nil { 592 return err 593 } 594 } else { 595 if err := query.created(value); err != nil { 596 return err 597 } 598 } 599 if err := query.saved(model, value); err != nil { 600 return err 601 } 602 603 return nil 604 } 605 606 func (r *QueryImpl) SaveQuietly(value any) error { 607 return r.WithoutEvents().Save(value) 608 } 609 610 func (r *QueryImpl) Scan(dest any) error { 611 query, err := r.refreshConnection(dest) 612 if err != nil { 613 return err 614 } 615 616 query = query.buildConditions() 617 618 return query.instance.Scan(dest).Error 619 } 620 621 func (r *QueryImpl) Scopes(funcs ...func(ormcontract.Query) ormcontract.Query) ormcontract.Query { 622 conditions := r.conditions 623 conditions.scopes = append(r.conditions.scopes, funcs...) 624 625 return r.setConditions(conditions) 626 } 627 628 func (r *QueryImpl) Select(query any, args ...any) ormcontract.Query { 629 conditions := r.conditions 630 conditions.selectColumns = &Select{ 631 query: query, 632 args: args, 633 } 634 635 return r.setConditions(conditions) 636 } 637 638 func (r *QueryImpl) SetContext(ctx context.Context) { 639 r.ctx = ctx 640 r.instance.Statement.Context = ctx 641 } 642 643 func (r *QueryImpl) SharedLock() ormcontract.Query { 644 conditions := r.conditions 645 conditions.sharedLock = true 646 647 return r.setConditions(conditions) 648 } 649 650 func (r *QueryImpl) Sum(column string, dest any) error { 651 query := r.buildConditions() 652 653 return query.instance.Select("SUM(" + column + ")").Row().Scan(dest) 654 } 655 656 func (r *QueryImpl) Table(name string, args ...any) ormcontract.Query { 657 conditions := r.conditions 658 conditions.table = &Table{ 659 name: name, 660 args: args, 661 } 662 663 return r.setConditions(conditions) 664 } 665 666 func (r *QueryImpl) Update(column any, value ...any) (*ormcontract.Result, error) { 667 query := r.buildConditions() 668 669 if _, ok := column.(string); !ok && len(value) > 0 { 670 return nil, errors.New("parameter error, please check the document") 671 } 672 673 var singleUpdate bool 674 model := query.instance.Statement.Model 675 if model != nil { 676 id := database.GetID(model) 677 singleUpdate = id != nil 678 } 679 680 if c, ok := column.(string); ok && len(value) > 0 { 681 query.instance.Statement.Dest = map[string]any{c: value[0]} 682 } 683 if len(value) == 0 { 684 query.instance.Statement.Dest = column 685 } 686 687 if singleUpdate { 688 if err := query.saving(model, query.instance.Statement.Dest); err != nil { 689 return nil, err 690 } 691 if err := query.updating(model, query.instance.Statement.Dest); err != nil { 692 return nil, err 693 } 694 } 695 696 res, err := query.updates(query.instance.Statement.Dest) 697 698 if singleUpdate && err == nil { 699 if err := query.updated(model, query.instance.Statement.Dest); err != nil { 700 return nil, err 701 } 702 if err := query.saved(model, query.instance.Statement.Dest); err != nil { 703 return nil, err 704 } 705 } 706 707 return res, err 708 } 709 710 func (r *QueryImpl) UpdateOrCreate(dest any, attributes any, values any) error { 711 query, err := r.refreshConnection(dest) 712 if err != nil { 713 return err 714 } 715 716 query = query.buildConditions() 717 718 res := query.instance.Assign(values).FirstOrInit(dest, attributes) 719 if res.Error != nil { 720 return res.Error 721 } 722 if res.RowsAffected > 0 { 723 return query.Save(dest) 724 } 725 726 return query.Create(dest) 727 } 728 729 func (r *QueryImpl) Where(query any, args ...any) ormcontract.Query { 730 conditions := r.conditions 731 conditions.where = append(r.conditions.where, Where{ 732 query: query, 733 args: args, 734 }) 735 736 return r.setConditions(conditions) 737 } 738 739 func (r *QueryImpl) With(query string, args ...any) ormcontract.Query { 740 conditions := r.conditions 741 conditions.with = append(r.conditions.with, With{ 742 query: query, 743 args: args, 744 }) 745 746 return r.setConditions(conditions) 747 } 748 749 func (r *QueryImpl) WithoutEvents() ormcontract.Query { 750 conditions := r.conditions 751 conditions.withoutEvents = true 752 753 return r.setConditions(conditions) 754 } 755 756 func (r *QueryImpl) WithTrashed() ormcontract.Query { 757 conditions := r.conditions 758 conditions.withTrashed = true 759 760 return r.setConditions(conditions) 761 } 762 763 func (r *QueryImpl) buildConditions() *QueryImpl { 764 query := r.buildModel() 765 db := query.instance 766 db = query.buildDistinct(db) 767 db = query.buildGroup(db) 768 db = query.buildHaving(db) 769 db = query.buildJoin(db) 770 db = query.buildLockForUpdate(db) 771 db = query.buildLimit(db) 772 db = query.buildOrder(db) 773 db = query.buildOffset(db) 774 db = query.buildOmit(db) 775 db = query.buildScopes(db) 776 db = query.buildSelectColumns(db) 777 db = query.buildSharedLock(db) 778 db = query.buildTable(db) 779 db = query.buildWith(db) 780 db = query.buildWithTrashed(db) 781 db = query.buildWhere(db) 782 783 return query.new(db) 784 } 785 786 func (r *QueryImpl) buildDistinct(db *gormio.DB) *gormio.DB { 787 if len(r.conditions.distinct) == 0 { 788 return db 789 } 790 791 db = db.Distinct(r.conditions.distinct...) 792 r.conditions.distinct = nil 793 794 return db 795 } 796 797 func (r *QueryImpl) buildGroup(db *gormio.DB) *gormio.DB { 798 if r.conditions.group == "" { 799 return db 800 } 801 802 db = db.Group(r.conditions.group) 803 r.conditions.group = "" 804 805 return db 806 } 807 808 func (r *QueryImpl) buildHaving(db *gormio.DB) *gormio.DB { 809 if r.conditions.having == nil { 810 return db 811 } 812 813 db = db.Having(r.conditions.having.query, r.conditions.having.args...) 814 r.conditions.having = nil 815 816 return db 817 } 818 819 func (r *QueryImpl) buildJoin(db *gormio.DB) *gormio.DB { 820 if r.conditions.join == nil { 821 return db 822 } 823 824 for _, item := range r.conditions.join { 825 db = db.Joins(item.query, item.args...) 826 } 827 828 r.conditions.join = nil 829 830 return db 831 } 832 833 func (r *QueryImpl) buildLimit(db *gormio.DB) *gormio.DB { 834 if r.conditions.limit == nil { 835 return db 836 } 837 838 db = db.Limit(*r.conditions.limit) 839 r.conditions.limit = nil 840 841 return db 842 } 843 844 func (r *QueryImpl) buildLockForUpdate(db *gormio.DB) *gormio.DB { 845 if !r.conditions.lockForUpdate { 846 return db 847 } 848 849 driver := r.instance.Name() 850 mysqlDialector := mysql.Dialector{} 851 postgresqlDialector := postgres.Dialector{} 852 sqlserverDialector := sqlserver.Dialector{} 853 854 if driver == mysqlDialector.Name() || driver == postgresqlDialector.Name() { 855 return db.Clauses(clause.Locking{Strength: "UPDATE"}) 856 } else if driver == sqlserverDialector.Name() { 857 return db.Clauses(hints.With("rowlock", "updlock", "holdlock")) 858 } 859 860 r.conditions.lockForUpdate = false 861 862 return db 863 } 864 865 func (r *QueryImpl) buildModel() *QueryImpl { 866 if r.conditions.model == nil { 867 return r 868 } 869 870 query, err := r.refreshConnection(r.conditions.model) 871 if err != nil { 872 return nil 873 } 874 875 return query.new(query.instance.Model(r.conditions.model)) 876 } 877 878 func (r *QueryImpl) buildOffset(db *gormio.DB) *gormio.DB { 879 if r.conditions.offset == nil { 880 return db 881 } 882 883 db = db.Offset(*r.conditions.offset) 884 r.conditions.offset = nil 885 886 return db 887 } 888 889 func (r *QueryImpl) buildOmit(db *gormio.DB) *gormio.DB { 890 if len(r.conditions.omit) == 0 { 891 return db 892 } 893 894 db = db.Omit(r.conditions.omit...) 895 r.conditions.omit = nil 896 897 return db 898 } 899 900 func (r *QueryImpl) buildOrder(db *gormio.DB) *gormio.DB { 901 if len(r.conditions.order) == 0 { 902 return db 903 } 904 905 for _, order := range r.conditions.order { 906 db = db.Order(order) 907 } 908 909 r.conditions.order = nil 910 911 return db 912 } 913 914 func (r *QueryImpl) buildSelectColumns(db *gormio.DB) *gormio.DB { 915 if r.conditions.selectColumns == nil { 916 return db 917 } 918 919 db = db.Select(r.conditions.selectColumns.query, r.conditions.selectColumns.args...) 920 r.conditions.selectColumns = nil 921 922 return db 923 } 924 925 func (r *QueryImpl) buildScopes(db *gormio.DB) *gormio.DB { 926 if len(r.conditions.scopes) == 0 { 927 return db 928 } 929 930 var gormFuncs []func(*gormio.DB) *gormio.DB 931 for _, scope := range r.conditions.scopes { 932 gormFuncs = append(gormFuncs, func(tx *gormio.DB) *gormio.DB { 933 queryImpl := r.new(tx) 934 query := scope(queryImpl) 935 queryImpl = query.(*QueryImpl) 936 queryImpl = queryImpl.buildConditions() 937 938 return queryImpl.instance 939 }) 940 } 941 942 db = db.Scopes(gormFuncs...) 943 r.conditions.scopes = nil 944 945 return db 946 } 947 948 func (r *QueryImpl) buildSharedLock(db *gormio.DB) *gormio.DB { 949 if !r.conditions.sharedLock { 950 return db 951 } 952 953 driver := r.instance.Name() 954 mysqlDialector := mysql.Dialector{} 955 postgresqlDialector := postgres.Dialector{} 956 sqlserverDialector := sqlserver.Dialector{} 957 958 if driver == mysqlDialector.Name() || driver == postgresqlDialector.Name() { 959 return db.Clauses(clause.Locking{Strength: "SHARE"}) 960 } else if driver == sqlserverDialector.Name() { 961 return db.Clauses(hints.With("rowlock", "holdlock")) 962 } 963 964 r.conditions.sharedLock = false 965 966 return db 967 } 968 969 func (r *QueryImpl) buildTable(db *gormio.DB) *gormio.DB { 970 if r.conditions.table == nil { 971 return db 972 } 973 974 db = db.Table(r.conditions.table.name, r.conditions.table.args...) 975 r.conditions.table = nil 976 977 return db 978 } 979 980 func (r *QueryImpl) buildWhere(db *gormio.DB) *gormio.DB { 981 if len(r.conditions.where) == 0 { 982 return db 983 } 984 985 for _, item := range r.conditions.where { 986 if item.or { 987 db = db.Or(item.query, item.args...) 988 } else { 989 db = db.Where(item.query, item.args...) 990 } 991 } 992 993 r.conditions.where = nil 994 995 return db 996 } 997 998 func (r *QueryImpl) buildWith(db *gormio.DB) *gormio.DB { 999 if len(r.conditions.with) == 0 { 1000 return db 1001 } 1002 1003 for _, item := range r.conditions.with { 1004 isSet := false 1005 if len(item.args) == 1 { 1006 if arg, ok := item.args[0].(func(ormcontract.Query) ormcontract.Query); ok { 1007 newArgs := []any{ 1008 func(tx *gormio.DB) *gormio.DB { 1009 queryImpl := NewQueryImpl(r.ctx, r.config, r.connection, tx, nil) 1010 query := arg(queryImpl) 1011 queryImpl = query.(*QueryImpl) 1012 queryImpl = queryImpl.buildConditions() 1013 1014 return queryImpl.instance 1015 }, 1016 } 1017 1018 db = db.Preload(item.query, newArgs...) 1019 isSet = true 1020 } 1021 } 1022 1023 if !isSet { 1024 db = db.Preload(item.query, item.args...) 1025 } 1026 } 1027 1028 r.conditions.with = nil 1029 1030 return db 1031 } 1032 1033 func (r *QueryImpl) buildWithTrashed(db *gormio.DB) *gormio.DB { 1034 if !r.conditions.withTrashed { 1035 return db 1036 } 1037 1038 db = db.Unscoped() 1039 r.conditions.withTrashed = false 1040 1041 return db 1042 } 1043 1044 func (r *QueryImpl) clearConditions() { 1045 r.conditions = Conditions{} 1046 } 1047 1048 func (r *QueryImpl) create(value any) error { 1049 if err := r.saving(nil, value); err != nil { 1050 return err 1051 } 1052 if err := r.creating(value); err != nil { 1053 return err 1054 } 1055 1056 if err := r.instance.Omit(orm.Associations).Create(value).Error; err != nil { 1057 return err 1058 } 1059 1060 if err := r.created(value); err != nil { 1061 return err 1062 } 1063 if err := r.saved(nil, value); err != nil { 1064 return err 1065 } 1066 1067 return nil 1068 } 1069 1070 func (r *QueryImpl) created(dest any) error { 1071 return r.event(ormcontract.EventCreated, nil, dest) 1072 } 1073 1074 func (r *QueryImpl) creating(dest any) error { 1075 return r.event(ormcontract.EventCreating, nil, dest) 1076 } 1077 1078 func (r *QueryImpl) deleting(dest any) error { 1079 return r.event(ormcontract.EventDeleting, nil, dest) 1080 } 1081 1082 func (r *QueryImpl) deleted(dest any) error { 1083 return r.event(ormcontract.EventDeleted, nil, dest) 1084 } 1085 1086 func (r *QueryImpl) forceDeleting(dest any) error { 1087 return r.event(ormcontract.EventForceDeleting, nil, dest) 1088 } 1089 1090 func (r *QueryImpl) forceDeleted(dest any) error { 1091 return r.event(ormcontract.EventForceDeleted, nil, dest) 1092 } 1093 1094 func (r *QueryImpl) event(event ormcontract.EventType, model, dest any) error { 1095 if r.conditions.withoutEvents { 1096 return nil 1097 } 1098 1099 instance := NewEvent(r, model, dest) 1100 1101 if dispatchesEvents, exist := dest.(ormcontract.DispatchesEvents); exist { 1102 if event, exist := dispatchesEvents.DispatchesEvents()[event]; exist { 1103 return event(instance) 1104 } 1105 1106 return nil 1107 } 1108 if model != nil { 1109 if dispatchesEvents, exist := model.(ormcontract.DispatchesEvents); exist { 1110 if event, exist := dispatchesEvents.DispatchesEvents()[event]; exist { 1111 return event(instance) 1112 } 1113 } 1114 1115 return nil 1116 } 1117 1118 if observer := observer(dest); observer != nil { 1119 if observerEvent := observerEvent(event, observer); observerEvent != nil { 1120 return observerEvent(instance) 1121 } 1122 1123 return nil 1124 } 1125 1126 if model != nil { 1127 if observer := observer(model); observer != nil { 1128 if observerEvent := observerEvent(event, observer); observerEvent != nil { 1129 return observerEvent(instance) 1130 } 1131 1132 return nil 1133 } 1134 } 1135 1136 return nil 1137 } 1138 1139 func (r *QueryImpl) new(db *gormio.DB) *QueryImpl { 1140 query := NewQueryImpl(r.ctx, r.config, r.connection, db, &r.conditions) 1141 1142 return query 1143 } 1144 1145 func (r *QueryImpl) omitCreate(value any) error { 1146 if len(r.instance.Statement.Omits) > 1 { 1147 for _, val := range r.instance.Statement.Omits { 1148 if val == orm.Associations { 1149 return errors.New("cannot set orm.Associations and other fields at the same time") 1150 } 1151 } 1152 } 1153 1154 if len(r.instance.Statement.Omits) == 1 && r.instance.Statement.Omits[0] == orm.Associations { 1155 r.instance.Statement.Selects = []string{} 1156 } 1157 1158 if err := r.saving(nil, value); err != nil { 1159 return err 1160 } 1161 if err := r.creating(value); err != nil { 1162 return err 1163 } 1164 1165 if len(r.instance.Statement.Omits) == 1 && r.instance.Statement.Omits[0] == orm.Associations { 1166 if err := r.instance.Omit(orm.Associations).Create(value).Error; err != nil { 1167 return err 1168 } 1169 } else { 1170 if err := r.instance.Create(value).Error; err != nil { 1171 return err 1172 } 1173 } 1174 1175 if err := r.created(value); err != nil { 1176 return err 1177 } 1178 if err := r.saved(nil, value); err != nil { 1179 return err 1180 } 1181 1182 return nil 1183 } 1184 1185 func (r *QueryImpl) omitSave(value any) error { 1186 for _, val := range r.instance.Statement.Omits { 1187 if val == orm.Associations { 1188 return r.instance.Omit(orm.Associations).Save(value).Error 1189 } 1190 } 1191 1192 return r.instance.Save(value).Error 1193 } 1194 1195 func (r *QueryImpl) refreshConnection(model any) (*QueryImpl, error) { 1196 connection, err := getModelConnection(model) 1197 if err != nil { 1198 return nil, err 1199 } 1200 if connection == "" || connection == r.connection { 1201 return r, nil 1202 } 1203 1204 query, ok := r.queries[connection] 1205 if !ok { 1206 var err error 1207 query, err = InitializeQuery(r.ctx, r.config, connection) 1208 if err != nil { 1209 return nil, err 1210 } 1211 1212 if r.queries == nil { 1213 r.queries = make(map[string]*QueryImpl) 1214 } 1215 r.queries[connection] = query 1216 } 1217 1218 query.conditions = r.conditions 1219 1220 return query, nil 1221 } 1222 1223 func (r *QueryImpl) retrieved(dest any) error { 1224 return r.event(ormcontract.EventRetrieved, nil, dest) 1225 } 1226 1227 func (r *QueryImpl) save(value any) error { 1228 return r.instance.Omit(orm.Associations).Save(value).Error 1229 } 1230 1231 func (r *QueryImpl) saved(model, dest any) error { 1232 return r.event(ormcontract.EventSaved, model, dest) 1233 } 1234 1235 func (r *QueryImpl) saving(model, dest any) error { 1236 return r.event(ormcontract.EventSaving, model, dest) 1237 } 1238 1239 func (r *QueryImpl) selectCreate(value any) error { 1240 if len(r.instance.Statement.Selects) > 1 { 1241 for _, val := range r.instance.Statement.Selects { 1242 if val == orm.Associations { 1243 return errors.New("cannot set orm.Associations and other fields at the same time") 1244 } 1245 } 1246 } 1247 1248 if len(r.instance.Statement.Selects) == 1 && r.instance.Statement.Selects[0] == orm.Associations { 1249 r.instance.Statement.Selects = []string{} 1250 } 1251 1252 if err := r.saving(nil, value); err != nil { 1253 return err 1254 } 1255 if err := r.creating(value); err != nil { 1256 return err 1257 } 1258 1259 if err := r.instance.Create(value).Error; err != nil { 1260 return err 1261 } 1262 1263 if err := r.created(value); err != nil { 1264 return err 1265 } 1266 if err := r.saved(nil, value); err != nil { 1267 return err 1268 } 1269 1270 return nil 1271 } 1272 1273 func (r *QueryImpl) selectSave(value any) error { 1274 for _, val := range r.instance.Statement.Selects { 1275 if val == orm.Associations { 1276 return r.instance.Session(&gormio.Session{FullSaveAssociations: true}).Save(value).Error 1277 } 1278 } 1279 1280 if err := r.instance.Save(value).Error; err != nil { 1281 return err 1282 } 1283 1284 return nil 1285 } 1286 1287 func (r *QueryImpl) setConditions(conditions Conditions) *QueryImpl { 1288 query := r.new(r.instance) 1289 query.conditions = conditions 1290 1291 return query 1292 } 1293 1294 func (r *QueryImpl) updating(model, dest any) error { 1295 return r.event(ormcontract.EventUpdating, model, dest) 1296 } 1297 1298 func (r *QueryImpl) updated(model, dest any) error { 1299 return r.event(ormcontract.EventUpdated, model, dest) 1300 } 1301 1302 func (r *QueryImpl) updates(values any) (*ormcontract.Result, error) { 1303 if len(r.instance.Statement.Selects) > 0 && len(r.instance.Statement.Omits) > 0 { 1304 return nil, errors.New("cannot set Select and Omits at the same time") 1305 } 1306 1307 if len(r.instance.Statement.Selects) > 0 { 1308 for _, val := range r.instance.Statement.Selects { 1309 if val == orm.Associations { 1310 result := r.instance.Session(&gormio.Session{FullSaveAssociations: true}).Updates(values) 1311 return &ormcontract.Result{ 1312 RowsAffected: result.RowsAffected, 1313 }, result.Error 1314 } 1315 } 1316 1317 result := r.instance.Updates(values) 1318 1319 return &ormcontract.Result{ 1320 RowsAffected: result.RowsAffected, 1321 }, result.Error 1322 } 1323 1324 if len(r.instance.Statement.Omits) > 0 { 1325 for _, val := range r.instance.Statement.Omits { 1326 if val == orm.Associations { 1327 result := r.instance.Omit(orm.Associations).Updates(values) 1328 1329 return &ormcontract.Result{ 1330 RowsAffected: result.RowsAffected, 1331 }, result.Error 1332 } 1333 } 1334 result := r.instance.Updates(values) 1335 1336 return &ormcontract.Result{ 1337 RowsAffected: result.RowsAffected, 1338 }, result.Error 1339 } 1340 result := r.instance.Omit(orm.Associations).Updates(values) 1341 1342 return &ormcontract.Result{ 1343 RowsAffected: result.RowsAffected, 1344 }, result.Error 1345 } 1346 1347 func filterFindConditions(conds ...any) error { 1348 if len(conds) > 0 { 1349 switch cond := conds[0].(type) { 1350 case string: 1351 if cond == "" { 1352 return ErrorMissingWhereClause 1353 } 1354 default: 1355 reflectValue := reflect.Indirect(reflect.ValueOf(cond)) 1356 switch reflectValue.Kind() { 1357 case reflect.Slice, reflect.Array: 1358 if reflectValue.Len() == 0 { 1359 return ErrorMissingWhereClause 1360 } 1361 } 1362 } 1363 } 1364 1365 return nil 1366 } 1367 1368 func getModelConnection(model any) (string, error) { 1369 value1 := reflect.ValueOf(model) 1370 if value1.Kind() == reflect.Ptr && value1.IsNil() { 1371 value1 = reflect.New(value1.Type().Elem()) 1372 } 1373 modelType := reflect.Indirect(value1).Type() 1374 1375 if modelType.Kind() == reflect.Interface { 1376 modelType = reflect.Indirect(reflect.ValueOf(model)).Elem().Type() 1377 } 1378 1379 for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr { 1380 modelType = modelType.Elem() 1381 } 1382 1383 if modelType.Kind() != reflect.Struct { 1384 if modelType.PkgPath() == "" { 1385 return "", errors.New("invalid model") 1386 } 1387 return "", fmt.Errorf("%s: %s.%s", "invalid model", modelType.PkgPath(), modelType.Name()) 1388 } 1389 1390 modelValue := reflect.New(modelType) 1391 connectionModel, ok := modelValue.Interface().(ormcontract.ConnectionModel) 1392 if !ok { 1393 return "", nil 1394 } 1395 1396 return connectionModel.Connection(), nil 1397 } 1398 1399 func observer(dest any) ormcontract.Observer { 1400 destType := reflect.TypeOf(dest) 1401 if destType.Kind() == reflect.Pointer { 1402 destType = destType.Elem() 1403 } 1404 1405 for _, observer := range orm.Observers { 1406 modelType := reflect.TypeOf(observer.Model) 1407 if modelType.Kind() == reflect.Pointer { 1408 modelType = modelType.Elem() 1409 } 1410 if destType.Name() == modelType.Name() { 1411 return observer.Observer 1412 } 1413 } 1414 1415 return nil 1416 } 1417 1418 func observerEvent(event ormcontract.EventType, observer ormcontract.Observer) func(ormcontract.Event) error { 1419 switch event { 1420 case ormcontract.EventRetrieved: 1421 return observer.Retrieved 1422 case ormcontract.EventCreating: 1423 return observer.Creating 1424 case ormcontract.EventCreated: 1425 return observer.Created 1426 case ormcontract.EventUpdating: 1427 return observer.Updating 1428 case ormcontract.EventUpdated: 1429 return observer.Updated 1430 case ormcontract.EventSaving: 1431 return observer.Saving 1432 case ormcontract.EventSaved: 1433 return observer.Saved 1434 case ormcontract.EventDeleting: 1435 return observer.Deleting 1436 case ormcontract.EventDeleted: 1437 return observer.Deleted 1438 case ormcontract.EventForceDeleting: 1439 return observer.ForceDeleting 1440 case ormcontract.EventForceDeleted: 1441 return observer.ForceDeleted 1442 } 1443 1444 return nil 1445 }