package orm

import (
	
	
	

	
)

type UpdateQuery struct {
	q           *Query
	omitZero    bool
	placeholder bool
}

var (
	_ QueryAppender = (*UpdateQuery)(nil)
	_ QueryCommand  = (*UpdateQuery)(nil)
)

func ( *Query,  bool) *UpdateQuery {
	return &UpdateQuery{
		q:        ,
		omitZero: ,
	}
}

func ( *UpdateQuery) () string {
	,  := .AppendQuery(defaultFmter, nil)
	if  != nil {
		panic()
	}
	return string()
}

func ( *UpdateQuery) () QueryOp {
	return UpdateOp
}

func ( *UpdateQuery) () QueryCommand {
	return &UpdateQuery{
		q:           .q.Clone(),
		omitZero:    .omitZero,
		placeholder: .placeholder,
	}
}

func ( *UpdateQuery) () *Query {
	return .q
}

func ( *UpdateQuery) ( []byte) ([]byte, error) {
	 := .Clone().(*UpdateQuery)
	.placeholder = true
	return .AppendQuery(dummyFormatter{}, )
}

func ( *UpdateQuery) ( QueryFormatter,  []byte) ( []byte,  error) {
	if .q.stickyErr != nil {
		return nil, .q.stickyErr
	}

	if len(.q.with) > 0 {
		,  = .q.appendWith(, )
		if  != nil {
			return nil, 
		}
	}

	 = append(, "UPDATE "...)

	,  = .q.appendFirstTableWithAlias(, )
	if  != nil {
		return nil, 
	}

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

	 := .q.isSliceModelWithData()
	if  || .q.hasMultiTables() {
		 = append(, " FROM "...)
		,  = .q.appendOtherTables(, )
		if  != nil {
			return nil, 
		}

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

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

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

	return , .q.stickyErr
}

func ( *UpdateQuery) (
	 QueryFormatter,  []byte,  bool,
) ( []byte,  error) {
	 = append(, " WHERE "...)

	if ! {
		return .q.mustAppendWhere(, )
	}

	if len(.q.where) > 0 {
		return .q.appendWhere(, )
	}

	 := .q.tableModel.Table()
	 = .checkPKs()
	if  != nil {
		return nil, 
	}

	 = appendWhereColumnAndColumn(, .Alias, .PKs)
	return , nil
}

func ( *UpdateQuery) ( QueryFormatter,  []byte) ( []byte,  error) {
	if len(.q.set) > 0 {
		return .q.appendSet(, )
	}

	 = append(, " SET "...)

	if ,  := .q.model.(*mapModel);  {
		return .appendMapSet(, .m), nil
	}

	if !.q.hasTableModel() {
		return nil, errModelNil
	}

	 := .q.tableModel.Value()
	if .Kind() == reflect.Struct {
		,  = .appendSetStruct(, , )
	} else {
		if .Len() > 0 {
			,  = .appendSetSlice()
		} else {
			 = fmt.Errorf("pg: can't bulk-update empty slice %s", .Type())
		}
	}
	if  != nil {
		return nil, 
	}

	return , nil
}

func ( *UpdateQuery) ( []byte,  map[string]interface{}) []byte {
	 := make([]string, 0, len())

	for  := range  {
		 = append(, )
	}
	sort.Strings()

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

		 = types.AppendIdent(, , 1)
		 = append(, " = "...)
		if .placeholder {
			 = append(, '?')
		} else {
			 = types.Append(, [], 1)
		}
	}

	return 
}

func ( *UpdateQuery) ( QueryFormatter,  []byte,  reflect.Value) ([]byte, error) {
	,  := .q.getFields()
	if  != nil {
		return nil, 
	}

	if len() == 0 {
		 = .q.tableModel.Table().DataFields
	}

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

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

		 = append(, .Column...)
		 = append(, " = "...)

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

		,  := .q.modelValues[.SQLName]
		if  {
			,  = .AppendQuery(, )
			if  != nil {
				return nil, 
			}
		} else {
			 = .AppendValue(, , 1)
		}
	}

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

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

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

	return , nil
}

func ( *UpdateQuery) ( []byte) ([]byte, error) {
	,  := .q.getFields()
	if  != nil {
		return nil, 
	}

	if len() == 0 {
		 = .q.tableModel.Table().DataFields
	}

	var  *Table
	if .omitZero {
		 = .q.tableModel.Table()
	}

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

		 = append(, .Column...)
		 = append(, " = "...)
		if .omitZero &&  != nil {
			 = append(, "COALESCE("...)
		}
		 = append(, "_data."...)
		 = append(, .Column...)
		if .omitZero &&  != nil {
			 = append(, ", "...)
			if .Alias != .SQLName {
				 = append(, .Alias...)
				 = append(, '.')
			}
			 = append(, .Column...)
			 = append(, ")"...)
		}
	}

	return , nil
}

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

	if len() > 0 {
		 = append(, .q.tableModel.Table().PKs...)
	} else {
		 = .q.tableModel.Table().Fields
	}

	return .appendSliceValues(, , , .q.tableModel.Value())
}

func ( *UpdateQuery) (
	 QueryFormatter,  []byte,  []*Field,  reflect.Value,
) ( []byte,  error) {
	 = append(, "(VALUES ("...)

	if .placeholder {
		,  = .appendValues(, , , reflect.Value{})
		if  != nil {
			return nil, 
		}
	} else {
		 := .Len()
		for  := 0;  < ; ++ {
			if  > 0 {
				 = append(, "), ("...)
			}
			,  = .appendValues(, , , .Index())
			if  != nil {
				return nil, 
			}
		}
	}

	 = append(, ")) AS _data("...)
	 = appendColumns(, "", )
	 = append(, ")"...)

	return , nil
}

func ( *UpdateQuery) (
	 QueryFormatter,  []byte,  []*Field,  reflect.Value,
) ( []byte,  error) {
	for ,  := range  {
		if  > 0 {
			 = append(, ", "...)
		}

		,  := .q.modelValues[.SQLName]
		if  {
			,  = .AppendQuery(, )
			if  != nil {
				return nil, 
			}
			continue
		}

		if .placeholder {
			 = append(, '?')
		} else {
			 = .AppendValue(, indirect(), 1)
		}

		 = append(, "::"...)
		 = append(, .SQLType...)
	}
	return , nil
}

func ( []byte,  types.Safe,  []*Field) []byte {
	for ,  := range  {
		if  > 0 {
			 = append(, " AND "...)
		}
		 = append(, ...)
		 = append(, '.')
		 = append(, .Column...)
		 = append(, " = _data."...)
		 = append(, .Column...)
	}
	return 
}