package bun

import (
	
	
	
	

	
	
	
)

type UpdateQuery struct {
	whereBaseQuery
	returningQuery
	customValueQuery
	setQuery

	omitZero bool
}

func ( *DB) *UpdateQuery {
	 := &UpdateQuery{
		whereBaseQuery: whereBaseQuery{
			baseQuery: baseQuery{
				db:   ,
				conn: .DB,
			},
		},
	}
	return 
}

func ( *UpdateQuery) ( IConn) *UpdateQuery {
	.setConn()
	return 
}

func ( *UpdateQuery) ( interface{}) *UpdateQuery {
	.setTableModel()
	return 
}

// Apply calls the fn passing the SelectQuery as an argument.
func ( *UpdateQuery) ( func(*UpdateQuery) *UpdateQuery) *UpdateQuery {
	return ()
}

func ( *UpdateQuery) ( string,  schema.QueryAppender) *UpdateQuery {
	.addWith(, )
	return 
}

//------------------------------------------------------------------------------

func ( *UpdateQuery) ( ...string) *UpdateQuery {
	for ,  := range  {
		.addTable(schema.UnsafeIdent())
	}
	return 
}

func ( *UpdateQuery) ( string,  ...interface{}) *UpdateQuery {
	.addTable(schema.SafeQuery(, ))
	return 
}

func ( *UpdateQuery) ( string,  ...interface{}) *UpdateQuery {
	.modelTable = schema.SafeQuery(, )
	return 
}

//------------------------------------------------------------------------------

func ( *UpdateQuery) ( ...string) *UpdateQuery {
	for ,  := range  {
		.addColumn(schema.UnsafeIdent())
	}
	return 
}

func ( *UpdateQuery) ( ...string) *UpdateQuery {
	.excludeColumn()
	return 
}

func ( *UpdateQuery) ( string,  ...interface{}) *UpdateQuery {
	.addSet(schema.SafeQuery(, ))
	return 
}

// Value overwrites model value for the column.
func ( *UpdateQuery) ( string,  string,  ...interface{}) *UpdateQuery {
	if .table == nil {
		.err = errNilModel
		return 
	}
	.addValue(.table, , , )
	return 
}

//------------------------------------------------------------------------------

func ( *UpdateQuery) () *UpdateQuery {
	.flags = .flags.Set(wherePKFlag)
	return 
}

func ( *UpdateQuery) ( string,  ...interface{}) *UpdateQuery {
	.addWhere(schema.SafeQueryWithSep(, , " AND "))
	return 
}

func ( *UpdateQuery) ( string,  ...interface{}) *UpdateQuery {
	.addWhere(schema.SafeQueryWithSep(, , " OR "))
	return 
}

func ( *UpdateQuery) ( string,  func(*UpdateQuery) *UpdateQuery) *UpdateQuery {
	 := .where
	.where = nil

	 = ()

	 := .where
	.where = 

	.addWhereGroup(, )

	return 
}

func ( *UpdateQuery) () *UpdateQuery {
	.whereDeleted()
	return 
}

func ( *UpdateQuery) () *UpdateQuery {
	.whereAllWithDeleted()
	return 
}

//------------------------------------------------------------------------------

// Returning adds a RETURNING clause to the query.
//
// To suppress the auto-generated RETURNING clause, use `Returning("NULL")`.
func ( *UpdateQuery) ( string,  ...interface{}) *UpdateQuery {
	.addReturning(schema.SafeQuery(, ))
	return 
}

func ( *UpdateQuery) () bool {
	if !.db.features.Has(feature.Returning) {
		return false
	}
	return .returningQuery.hasReturning()
}

//------------------------------------------------------------------------------

func ( *UpdateQuery) () string {
	return "SELECT"
}

func ( *UpdateQuery) ( schema.Formatter,  []byte) ( []byte,  error) {
	if .err != nil {
		return nil, .err
	}
	 = formatterWithModel(, )

	,  = .appendWith(, )
	if  != nil {
		return nil, 
	}

	 = append(, "UPDATE "...)

	if .HasFeature(feature.UpdateMultiTable) {
		,  = .appendTablesWithAlias(, )
	} else {
		,  = .appendFirstTableWithAlias(, )
	}
	if  != nil {
		return nil, 
	}

	,  = .mustAppendSet(, )
	if  != nil {
		return nil, 
	}

	if !.HasFeature(feature.UpdateMultiTable) {
		,  = .appendOtherTables(, )
		if  != nil {
			return nil, 
		}
	}

	,  = .mustAppendWhere(, , true)
	if  != nil {
		return nil, 
	}

	if len(.returning) > 0 {
		,  = .appendReturning(, )
		if  != nil {
			return nil, 
		}
	}

	return , nil
}

func ( *UpdateQuery) ( schema.Formatter,  []byte) ( []byte,  error) {
	 = append(, " SET "...)

	if len(.set) > 0 {
		return .appendSet(, )
	}

	if ,  := .model.(*mapModel);  {
		return .appendSet(, ), nil
	}

	if .tableModel == nil {
		return nil, errNilModel
	}

	switch model := .tableModel.(type) {
	case *structTableModel:
		,  = .appendSetStruct(, , )
		if  != nil {
			return nil, 
		}
	case *sliceTableModel:
		return nil, errors.New("bun: to bulk Update, use CTE and VALUES")
	default:
		return nil, fmt.Errorf("bun: Update does not support %T", .tableModel)
	}

	return , nil
}

func ( *UpdateQuery) (
	 schema.Formatter,  []byte,  *structTableModel,
) ([]byte, error) {
	,  := .getDataFields()
	if  != nil {
		return nil, 
	}

	 := .IsNop()
	 := len()
	for ,  := range  {
		if .omitZero && .NullZero && .HasZeroValue(.strct) {
			continue
		}

		if len() !=  {
			 = append(, ", "...)
			 = len()
		}

		 = append(, .SQLName...)
		 = append(, " = "...)

		if  {
			 = append(, '?')
			continue
		}

		,  := .modelValues[.Name]
		if  {
			,  = .AppendQuery(, )
			if  != nil {
				return nil, 
			}
		} else {
			 = .AppendValue(, , .strct)
		}
	}

	for ,  := range .extraValues {
		if  > 0 || len() > 0 {
			 = append(, ", "...)
		}

		 = append(, .column...)
		 = append(, " = "...)

		,  = .value.AppendQuery(, )
		if  != nil {
			return nil, 
		}
	}

	return , nil
}

func ( *UpdateQuery) ( schema.Formatter,  []byte) ( []byte,  error) {
	if !.hasMultiTables() {
		return , nil
	}

	 = append(, " FROM "...)

	,  = .whereBaseQuery.appendOtherTables(, )
	if  != nil {
		return nil, 
	}

	return , nil
}

//------------------------------------------------------------------------------

func ( *UpdateQuery) () *UpdateQuery {
	,  := .model.(*sliceTableModel)
	if ! {
		.setErr(fmt.Errorf("bun: Bulk requires a slice, got %T", .model))
		return 
	}

	,  := .updateSliceSet(.db.fmter, )
	if  != nil {
		.setErr()
		return 
	}

	 := .db.NewValues()
	.customValueQuery = .customValueQuery

	return .With("_data", ).
		Model().
		TableExpr("_data").
		Set().
		Where(.updateSliceWhere())
}

func ( *UpdateQuery) (
	 schema.Formatter,  *sliceTableModel,
) (string, error) {
	,  := .getDataFields()
	if  != nil {
		return "", 
	}

	var  []byte
	for ,  := range  {
		if  > 0 {
			 = append(, ", "...)
		}
		if .HasFeature(feature.UpdateMultiTable) {
			 = append(, .table.SQLAlias...)
			 = append(, '.')
		}
		 = append(, .SQLName...)
		 = append(, " = _data."...)
		 = append(, .SQLName...)
	}
	return internal.String(), nil
}

func ( *UpdateQuery) ( *sliceTableModel) string {
	var  []byte
	for ,  := range .table.PKs {
		if  > 0 {
			 = append(, " AND "...)
		}
		 = append(, .table.SQLAlias...)
		 = append(, '.')
		 = append(, .SQLName...)
		 = append(, " = _data."...)
		 = append(, .SQLName...)
	}
	return internal.String()
}

//------------------------------------------------------------------------------

func ( *UpdateQuery) ( context.Context,  ...interface{}) (sql.Result, error) {
	if .table != nil {
		if  := .beforeUpdateHook();  != nil {
			return nil, 
		}
	}

	,  := .AppendQuery(.db.fmter, .db.makeQueryBytes())
	if  != nil {
		return nil, 
	}

	 := internal.String()

	var  sql.Result

	if  := len() > 0;  || .hasReturning() {
		,  := .getModel()
		if  != nil {
			return nil, 
		}

		,  = .scan(, , , , )
		if  != nil {
			return nil, 
		}
	} else {
		,  = .exec(, , )
		if  != nil {
			return nil, 
		}
	}

	if .table != nil {
		if  := .afterUpdateHook();  != nil {
			return nil, 
		}
	}

	return , nil
}

func ( *UpdateQuery) ( context.Context) error {
	if ,  := .table.ZeroIface.(BeforeUpdateHook);  {
		if  := .BeforeUpdate(, );  != nil {
			return 
		}
	}
	return nil
}

func ( *UpdateQuery) ( context.Context) error {
	if ,  := .table.ZeroIface.(AfterUpdateHook);  {
		if  := .AfterUpdate(, );  != nil {
			return 
		}
	}
	return nil
}

// FQN returns a fully qualified column name. For MySQL, it returns the column name with
// the table alias. For other RDBMS, it returns just the column name.
func ( *UpdateQuery) ( string) Ident {
	if .db.fmter.HasFeature(feature.UpdateMultiTable) {
		return Ident(.table.Alias + "." + )
	}
	return Ident()
}