package gorm

import (
	
	
	
	
	

	
	
	
	
)

// Create inserts value, returning the inserted data's primary key in value's id
func ( *DB) ( interface{}) ( *DB) {
	if .CreateBatchSize > 0 {
		return .CreateInBatches(, .CreateBatchSize)
	}

	 = .getInstance()
	.Statement.Dest = 
	return .callbacks.Create().Execute()
}

// CreateInBatches inserts value in batches of batchSize
func ( *DB) ( interface{},  int) ( *DB) {
	 := reflect.Indirect(reflect.ValueOf())

	switch .Kind() {
	case reflect.Slice, reflect.Array:
		var  int64
		 = .getInstance()

		// the reflection length judgment of the optimized value
		 := .Len()

		 := func( *DB) error {
			for  := 0;  < ;  +=  {
				 :=  + 
				if  >  {
					 = 
				}

				 := .getInstance()
				.Statement.Dest = .Slice(, ).Interface()
				.callbacks.Create().Execute()
				if .Error != nil {
					return .Error
				}
				 += .RowsAffected
			}
			return nil
		}

		if .SkipDefaultTransaction ||  <=  {
			.AddError((.Session(&Session{})))
		} else {
			.AddError(.Transaction())
		}

		.RowsAffected = 
	default:
		 = .getInstance()
		.Statement.Dest = 
		 = .callbacks.Create().Execute()
	}
	return
}

// Save updates value in database. If value doesn't contain a matching primary key, value is inserted.
func ( *DB) ( interface{}) ( *DB) {
	 = .getInstance()
	.Statement.Dest = 

	 := reflect.Indirect(reflect.ValueOf())
	for .Kind() == reflect.Ptr || .Kind() == reflect.Interface {
		 = reflect.Indirect()
	}

	switch .Kind() {
	case reflect.Slice, reflect.Array:
		if ,  := .Statement.Clauses["ON CONFLICT"]; ! {
			 = .Clauses(clause.OnConflict{UpdateAll: true})
		}
		 = .callbacks.Create().Execute(.Set("gorm:update_track_time", true))
	case reflect.Struct:
		if  := .Statement.Parse();  == nil && .Statement.Schema != nil {
			for ,  := range .Statement.Schema.PrimaryFields {
				if ,  := .ValueOf(.Statement.Context, );  {
					return .callbacks.Create().Execute()
				}
			}
		}

		fallthrough
	default:
		 := len(.Statement.Selects) != 0
		// when updating, use all fields including those zero-value fields
		if ! {
			.Statement.Selects = append(.Statement.Selects, "*")
		}

		 := .callbacks.Update().Execute(.Session(&Session{Initialized: true}))

		if .Error == nil && .RowsAffected == 0 && !.DryRun && ! {
			return .Session(&Session{SkipHooks: true}).Clauses(clause.OnConflict{UpdateAll: true}).Create()
		}

		return 
	}

	return
}

// First finds the first record ordered by primary key, matching given conditions conds
func ( *DB) ( interface{},  ...interface{}) ( *DB) {
	 = .Limit(1).Order(clause.OrderByColumn{
		Column: clause.Column{Table: clause.CurrentTable, Name: clause.PrimaryKey},
	})
	if len() > 0 {
		if  := .Statement.BuildCondition([0], [1:]...); len() > 0 {
			.Statement.AddClause(clause.Where{Exprs: })
		}
	}
	.Statement.RaiseErrorOnNotFound = true
	.Statement.Dest = 
	return .callbacks.Query().Execute()
}

// Take finds the first record returned by the database in no specified order, matching given conditions conds
func ( *DB) ( interface{},  ...interface{}) ( *DB) {
	 = .Limit(1)
	if len() > 0 {
		if  := .Statement.BuildCondition([0], [1:]...); len() > 0 {
			.Statement.AddClause(clause.Where{Exprs: })
		}
	}
	.Statement.RaiseErrorOnNotFound = true
	.Statement.Dest = 
	return .callbacks.Query().Execute()
}

// Last finds the last record ordered by primary key, matching given conditions conds
func ( *DB) ( interface{},  ...interface{}) ( *DB) {
	 = .Limit(1).Order(clause.OrderByColumn{
		Column: clause.Column{Table: clause.CurrentTable, Name: clause.PrimaryKey},
		Desc:   true,
	})
	if len() > 0 {
		if  := .Statement.BuildCondition([0], [1:]...); len() > 0 {
			.Statement.AddClause(clause.Where{Exprs: })
		}
	}
	.Statement.RaiseErrorOnNotFound = true
	.Statement.Dest = 
	return .callbacks.Query().Execute()
}

// Find finds all records matching given conditions conds
func ( *DB) ( interface{},  ...interface{}) ( *DB) {
	 = .getInstance()
	if len() > 0 {
		if  := .Statement.BuildCondition([0], [1:]...); len() > 0 {
			.Statement.AddClause(clause.Where{Exprs: })
		}
	}
	.Statement.Dest = 
	return .callbacks.Query().Execute()
}

// FindInBatches finds all records in batches of batchSize
func ( *DB) ( interface{},  int,  func( *DB,  int) error) *DB {
	var (
		 = .Order(clause.OrderByColumn{
			Column: clause.Column{Table: clause.CurrentTable, Name: clause.PrimaryKey},
		}).Session(&Session{})
		      = 
		 int64
		        int
	)

	// user specified offset or limit
	var  int
	if ,  := .Statement.Clauses["LIMIT"];  {
		if ,  := .Expression.(clause.Limit);  {
			if .Limit != nil {
				 = *.Limit
			}

			if  > 0 &&  >  {
				 = 
			}

			// reset to offset to 0 in next batch
			 = .Offset(-1).Session(&Session{})
		}
	}

	for {
		 := .Limit().Find()
		 += .RowsAffected
		++

		if .Error == nil && .RowsAffected != 0 {
			 := .Session(&Session{NewDB: true})
			.RowsAffected = .RowsAffected
			.AddError((, ))
		} else if .Error != nil {
			.AddError(.Error)
		}

		if .Error != nil || int(.RowsAffected) <  {
			break
		}

		if  > 0 {
			if  <= int() {
				break
			}
			if / ==  {
				 =  % 
			}
		}

		// Optimize for-break
		 := reflect.Indirect(reflect.ValueOf())
		if .Statement.Schema.PrioritizedPrimaryField == nil {
			.AddError(ErrPrimaryKeyRequired)
			break
		}

		,  := .Statement.Schema.PrioritizedPrimaryField.ValueOf(.Statement.Context, .Index(.Len()-1))
		if  {
			.AddError(ErrPrimaryKeyRequired)
			break
		}
		 = .Clauses(clause.Gt{Column: clause.Column{Table: clause.CurrentTable, Name: clause.PrimaryKey}, Value: })
	}

	.RowsAffected = 
	return 
}

func ( *DB) ( ...interface{}) {
	for ,  := range  {
		switch v := .(type) {
		case []clause.Expression:
			for ,  := range  {
				if ,  := .(clause.Eq);  {
					switch column := .Column.(type) {
					case string:
						if  := .Statement.Schema.LookUpField();  != nil {
							.AddError(.Set(.Statement.Context, .Statement.ReflectValue, .Value))
						}
					case clause.Column:
						if  := .Statement.Schema.LookUpField(.Name);  != nil {
							.AddError(.Set(.Statement.Context, .Statement.ReflectValue, .Value))
						}
					}
				} else if ,  := .(clause.AndConditions);  {
					.(.Exprs)
				}
			}
		case clause.Expression, map[string]string, map[interface{}]interface{}, map[string]interface{}:
			if  := .Statement.BuildCondition(); len() > 0 {
				.()
			}
		default:
			if ,  := schema.Parse(, .cacheStore, .NamingStrategy);  == nil {
				 := reflect.Indirect(reflect.ValueOf())
				switch .Kind() {
				case reflect.Struct:
					for ,  := range .Fields {
						if .Readable {
							if ,  := .ValueOf(.Statement.Context, ); ! {
								if  := .Statement.Schema.LookUpField(.Name);  != nil {
									.AddError(.Set(.Statement.Context, .Statement.ReflectValue, ))
								}
							}
						}
					}
				}
			} else if len() > 0 {
				if  := .Statement.BuildCondition([0], [1:]...); len() > 0 {
					.()
				}
				return
			}
		}
	}
}

// FirstOrInit finds the first matching record, otherwise if not found initializes a new instance with given conds.
// Each conds must be a struct or map.
//
// FirstOrInit never modifies the database. It is often used with Assign and Attrs.
//
//	// assign an email if the record is not found
//	db.Where(User{Name: "non_existing"}).Attrs(User{Email: "fake@fake.org"}).FirstOrInit(&user)
//	// user -> User{Name: "non_existing", Email: "fake@fake.org"}
//
//	// assign email regardless of if record is found
//	db.Where(User{Name: "jinzhu"}).Assign(User{Email: "fake@fake.org"}).FirstOrInit(&user)
//	// user -> User{Name: "jinzhu", Age: 20, Email: "fake@fake.org"}
func ( *DB) ( interface{},  ...interface{}) ( *DB) {
	 := .Limit(1).Order(clause.OrderByColumn{
		Column: clause.Column{Table: clause.CurrentTable, Name: clause.PrimaryKey},
	})

	if  = .Find(, ...); .RowsAffected == 0 {
		if ,  := .Statement.Clauses["WHERE"];  {
			if ,  := .Expression.(clause.Where);  {
				.assignInterfacesToValue(.Exprs)
			}
		}

		// initialize with attrs, conds
		if len(.Statement.attrs) > 0 {
			.assignInterfacesToValue(.Statement.attrs...)
		}
	}

	// initialize with attrs, conds
	if len(.Statement.assigns) > 0 {
		.assignInterfacesToValue(.Statement.assigns...)
	}
	return
}

// FirstOrCreate finds the first matching record, otherwise if not found creates a new instance with given conds.
// Each conds must be a struct or map.
//
// Using FirstOrCreate in conjunction with Assign will result in an update to the database even if the record exists.
//
//	// assign an email if the record is not found
//	result := db.Where(User{Name: "non_existing"}).Attrs(User{Email: "fake@fake.org"}).FirstOrCreate(&user)
//	// user -> User{Name: "non_existing", Email: "fake@fake.org"}
//	// result.RowsAffected -> 1
//
//	// assign email regardless of if record is found
//	result := db.Where(User{Name: "jinzhu"}).Assign(User{Email: "fake@fake.org"}).FirstOrCreate(&user)
//	// user -> User{Name: "jinzhu", Age: 20, Email: "fake@fake.org"}
//	// result.RowsAffected -> 1
func ( *DB) ( interface{},  ...interface{}) ( *DB) {
	 = .getInstance()
	 := .Session(&Session{}).Limit(1).Order(clause.OrderByColumn{
		Column: clause.Column{Table: clause.CurrentTable, Name: clause.PrimaryKey},
	})

	 := .Find(, ...)
	if .Error != nil {
		.Error = .Error
		return 
	}

	if .RowsAffected == 0 {
		if ,  := .Statement.Clauses["WHERE"];  {
			if ,  := .Expression.(clause.Where);  {
				.assignInterfacesToValue(.Exprs)
			}
		}

		// initialize with attrs, conds
		if len(.Statement.attrs) > 0 {
			.assignInterfacesToValue(.Statement.attrs...)
		}

		// initialize with attrs, conds
		if len(.Statement.assigns) > 0 {
			.assignInterfacesToValue(.Statement.assigns...)
		}

		return .Create()
	} else if len(.Statement.assigns) > 0 {
		 := .Statement.BuildCondition(.Statement.assigns[0], .Statement.assigns[1:]...)
		 := map[string]interface{}{}
		for ,  := range  {
			if ,  := .(clause.Eq);  {
				switch column := .Column.(type) {
				case string:
					[] = .Value
				case clause.Column:
					[.Name] = .Value
				}
			}
		}

		return .Model().Updates()
	}

	return 
}

// Update updates column with value using callbacks. Reference: https://gorm.io/docs/update.html#Update-Changed-Fields
func ( *DB) ( string,  interface{}) ( *DB) {
	 = .getInstance()
	.Statement.Dest = map[string]interface{}{: }
	return .callbacks.Update().Execute()
}

// Updates updates attributes using callbacks. values must be a struct or map. Reference: https://gorm.io/docs/update.html#Update-Changed-Fields
func ( *DB) ( interface{}) ( *DB) {
	 = .getInstance()
	.Statement.Dest = 
	return .callbacks.Update().Execute()
}

func ( *DB) ( string,  interface{}) ( *DB) {
	 = .getInstance()
	.Statement.Dest = map[string]interface{}{: }
	.Statement.SkipHooks = true
	return .callbacks.Update().Execute()
}

func ( *DB) ( interface{}) ( *DB) {
	 = .getInstance()
	.Statement.Dest = 
	.Statement.SkipHooks = true
	return .callbacks.Update().Execute()
}

// Delete deletes value matching given conditions. If value contains primary key it is included in the conditions. If
// value includes a deleted_at field, then Delete performs a soft delete instead by setting deleted_at with the current
// time if null.
func ( *DB) ( interface{},  ...interface{}) ( *DB) {
	 = .getInstance()
	if len() > 0 {
		if  := .Statement.BuildCondition([0], [1:]...); len() > 0 {
			.Statement.AddClause(clause.Where{Exprs: })
		}
	}
	.Statement.Dest = 
	return .callbacks.Delete().Execute()
}

func ( *DB) ( *int64) ( *DB) {
	 = .getInstance()
	if .Statement.Model == nil {
		.Statement.Model = .Statement.Dest
		defer func() {
			.Statement.Model = nil
		}()
	}

	if ,  := .Statement.Clauses["SELECT"];  {
		defer func() {
			.Statement.Clauses["SELECT"] = 
		}()
	} else {
		defer delete(.Statement.Clauses, "SELECT")
	}

	if len(.Statement.Selects) == 0 {
		.Statement.AddClause(clause.Select{Expression: clause.Expr{SQL: "count(*)"}})
	} else if !strings.HasPrefix(strings.TrimSpace(strings.ToLower(.Statement.Selects[0])), "count(") {
		 := clause.Expr{SQL: "count(*)"}

		if len(.Statement.Selects) == 1 {
			 := .Statement.Selects[0]
			 := strings.FieldsFunc(, utils.IsValidDBNameChar)
			if len() == 1 || (len() == 3 && (strings.ToUpper([1]) == "AS" || [1] == ".")) {
				if .Statement.Parse(.Statement.Model) == nil {
					if  := .Statement.Schema.LookUpField();  != nil {
						 = .DBName
					}
				}

				if .Statement.Distinct {
					 = clause.Expr{SQL: "COUNT(DISTINCT(?))", Vars: []interface{}{clause.Column{Name: }}}
				} else if  != "*" {
					 = clause.Expr{SQL: "COUNT(?)", Vars: []interface{}{clause.Column{Name: }}}
				}
			}
		}

		.Statement.AddClause(clause.Select{Expression: })
	}

	if ,  := .Statement.Clauses["ORDER BY"];  {
		if ,  := .Statement.Clauses["GROUP BY"]; ! {
			delete(.Statement.Clauses, "ORDER BY")
			defer func() {
				.Statement.Clauses["ORDER BY"] = 
			}()
		}
	}

	.Statement.Dest = 
	 = .callbacks.Query().Execute()

	if ,  := .Statement.Clauses["GROUP BY"];  || .RowsAffected != 1 {
		* = .RowsAffected
	}

	return
}

func ( *DB) () *sql.Row {
	 := .getInstance().Set("rows", false)
	 = .callbacks.Row().Execute()
	,  := .Statement.Dest.(*sql.Row)
	if ! && .DryRun {
		.Logger.Error(.Statement.Context, ErrDryRunModeUnsupported.Error())
	}
	return 
}

func ( *DB) () (*sql.Rows, error) {
	 := .getInstance().Set("rows", true)
	 = .callbacks.Row().Execute()
	,  := .Statement.Dest.(*sql.Rows)
	if ! && .DryRun && .Error == nil {
		.Error = ErrDryRunModeUnsupported
	}
	return , .Error
}

// Scan scans selected value to the struct dest
func ( *DB) ( interface{}) ( *DB) {
	 := *.Config
	,  := .Logger, logger.Recorder.New()
	.Logger = 

	 = .getInstance()
	.Config = &

	if ,  := .Rows();  == nil {
		if .Next() {
			.ScanRows(, )
		} else {
			.RowsAffected = 0
			.AddError(.Err())
		}
		.AddError(.Close())
	}

	.Trace(.Statement.Context, .BeginAt, func() (string, int64) {
		return .SQL, .RowsAffected
	}, .Error)
	.Logger = 
	return
}

// Pluck queries a single column from a model, returning in the slice dest. E.g.:
//
//	var ages []int64
//	db.Model(&users).Pluck("age", &ages)
func ( *DB) ( string,  interface{}) ( *DB) {
	 = .getInstance()
	if .Statement.Model != nil {
		if .Statement.Parse(.Statement.Model) == nil {
			if  := .Statement.Schema.LookUpField();  != nil {
				 = .DBName
			}
		}
	}

	if len(.Statement.Selects) != 1 {
		 := strings.FieldsFunc(, utils.IsValidDBNameChar)
		.Statement.AddClauseIfNotExists(clause.Select{
			Distinct: .Statement.Distinct,
			Columns:  []clause.Column{{Name: , Raw: len() != 1}},
		})
	}
	.Statement.Dest = 
	return .callbacks.Query().Execute()
}

func ( *DB) ( *sql.Rows,  interface{}) error {
	 := .getInstance()
	if  := .Statement.Parse(); !errors.Is(, schema.ErrUnsupportedDataType) {
		.AddError()
	}
	.Statement.Dest = 
	.Statement.ReflectValue = reflect.ValueOf()
	for .Statement.ReflectValue.Kind() == reflect.Ptr {
		 := .Statement.ReflectValue.Elem()
		if !.IsValid() {
			 = reflect.New(.Statement.ReflectValue.Type().Elem())
			.Statement.ReflectValue.Set()
		}
		.Statement.ReflectValue = 
	}
	Scan(, , ScanInitialized)
	return .Error
}

// Connection uses a db connection to execute an arbitrary number of commands in fc. When finished, the connection is
// returned to the connection pool.
func ( *DB) ( func( *DB) error) ( error) {
	if .Error != nil {
		return .Error
	}

	 := .getInstance()
	,  := .DB()
	if  != nil {
		return
	}

	,  := .Conn(.Statement.Context)
	if  != nil {
		return
	}

	defer .Close()
	.Statement.ConnPool = 
	return ()
}

// Transaction start a transaction as a block, return error will rollback, otherwise to commit. Transaction executes an
// arbitrary number of commands in fc within a transaction. On success the changes are committed; if an error occurs
// they are rolled back.
func ( *DB) ( func( *DB) error,  ...*sql.TxOptions) ( error) {
	 := true

	if ,  := .Statement.ConnPool.(TxCommitter);  &&  != nil {
		// nested transaction
		if !.DisableNestedTransaction {
			 = .SavePoint(fmt.Sprintf("sp%p", )).Error
			if  != nil {
				return
			}
			defer func() {
				// Make sure to rollback when panic, Block error or Commit error
				if  ||  != nil {
					.RollbackTo(fmt.Sprintf("sp%p", ))
				}
			}()
		}
		 = (.Session(&Session{NewDB: .clone == 1}))
	} else {
		 := .Begin(...)
		if .Error != nil {
			return .Error
		}

		defer func() {
			// Make sure to rollback when panic, Block error or Commit error
			if  ||  != nil {
				.Rollback()
			}
		}()

		if  = ();  == nil {
			 = false
			return .Commit().Error
		}
	}

	 = false
	return
}

// Begin begins a transaction with any transaction options opts
func ( *DB) ( ...*sql.TxOptions) *DB {
	var (
		// clone statement
		  = .getInstance().Session(&Session{Context: .Statement.Context, NewDB: .clone == 1})
		 *sql.TxOptions
		 error
	)

	if len() > 0 {
		 = [0]
	}

	switch beginner := .Statement.ConnPool.(type) {
	case TxBeginner:
		.Statement.ConnPool,  = .BeginTx(.Statement.Context, )
	case ConnPoolBeginner:
		.Statement.ConnPool,  = .BeginTx(.Statement.Context, )
	default:
		 = ErrInvalidTransaction
	}

	if  != nil {
		.AddError()
	}

	return 
}

// Commit commits the changes in a transaction
func ( *DB) () *DB {
	if ,  := .Statement.ConnPool.(TxCommitter);  &&  != nil && !reflect.ValueOf().IsNil() {
		.AddError(.Commit())
	} else {
		.AddError(ErrInvalidTransaction)
	}
	return 
}

// Rollback rollbacks the changes in a transaction
func ( *DB) () *DB {
	if ,  := .Statement.ConnPool.(TxCommitter);  &&  != nil {
		if !reflect.ValueOf().IsNil() {
			.AddError(.Rollback())
		}
	} else {
		.AddError(ErrInvalidTransaction)
	}
	return 
}

func ( *DB) ( string) *DB {
	if ,  := .Dialector.(SavePointerDialectorInterface);  {
		// close prepared statement, because SavePoint not support prepared statement.
		// e.g. mysql8.0 doc: https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html
		var (
			   *PreparedStmtTX
			 bool
		)
		// close prepared statement, because SavePoint not support prepared statement.
		if ,  = .Statement.ConnPool.(*PreparedStmtTX);  {
			.Statement.ConnPool = .Tx
		}
		.AddError(.SavePoint(, ))
		// restore prepared statement
		if  {
			.Statement.ConnPool = 
		}
	} else {
		.AddError(ErrUnsupportedDriver)
	}
	return 
}

func ( *DB) ( string) *DB {
	if ,  := .Dialector.(SavePointerDialectorInterface);  {
		// close prepared statement, because RollbackTo not support prepared statement.
		// e.g. mysql8.0 doc: https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html
		var (
			   *PreparedStmtTX
			 bool
		)
		// close prepared statement, because SavePoint not support prepared statement.
		if ,  = .Statement.ConnPool.(*PreparedStmtTX);  {
			.Statement.ConnPool = .Tx
		}
		.AddError(.RollbackTo(, ))
		// restore prepared statement
		if  {
			.Statement.ConnPool = 
		}
	} else {
		.AddError(ErrUnsupportedDriver)
	}
	return 
}

// Exec executes raw sql
func ( *DB) ( string,  ...interface{}) ( *DB) {
	 = .getInstance()
	.Statement.SQL = strings.Builder{}

	if strings.Contains(, "@") {
		clause.NamedExpr{SQL: , Vars: }.Build(.Statement)
	} else {
		clause.Expr{SQL: , Vars: }.Build(.Statement)
	}

	return .callbacks.Raw().Execute()
}