package orm

import (
	
	
	

	
)

type InsertQuery struct {
	q               *Query
	returningFields []*Field
	placeholder     bool
}

var _ QueryCommand = (*InsertQuery)(nil)

func ( *Query) *InsertQuery {
	return &InsertQuery{
		q: ,
	}
}

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

func ( *InsertQuery) () QueryOp {
	return InsertOp
}

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

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

var _ TemplateAppender = (*InsertQuery)(nil)

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

var _ QueryAppender = (*InsertQuery)(nil)

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

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

	 = append(, "INSERT INTO "...)
	if .q.onConflict != nil {
		,  = .q.appendFirstTableWithAlias(, )
	} else {
		,  = .q.appendFirstTable(, )
	}
	if  != nil {
		return nil, 
	}

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

	if .q.onConflict != nil {
		 = append(, " ON CONFLICT "...)
		,  = .q.onConflict.AppendQuery(, )
		if  != nil {
			return nil, 
		}

		if .q.onConflictDoUpdate() {
			if len(.q.set) > 0 {
				,  = .q.appendSet(, )
				if  != nil {
					return nil, 
				}
			} else {
				,  := .q.getDataFields()
				if  != nil {
					return nil, 
				}

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

				 = .appendSetExcluded(, )
			}

			if len(.q.updWhere) > 0 {
				 = append(, " WHERE "...)
				,  = .q.appendUpdWhere(, )
				if  != nil {
					return nil, 
				}
			}
		}
	}

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

	return , .q.stickyErr
}

func ( *InsertQuery) ( QueryFormatter,  []byte) ( []byte,  error) {
	if .q.hasMultiTables() {
		if .q.columns != nil {
			 = append(, " ("...)
			,  = .q.appendColumns(, )
			if  != nil {
				return nil, 
			}
			 = append(, ")"...)
		}

		 = append(, " SELECT * FROM "...)
		,  = .q.appendOtherTables(, )
		if  != nil {
			return nil, 
		}

		return , nil
	}

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

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

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

	if len() == 0 {
		 = .q.tableModel.Table().Fields
	}
	 := .q.tableModel.Value()

	 = append(, " ("...)
	 = .appendColumns(, )
	 = append(, ") VALUES ("...)
	if ,  := .q.tableModel.(*sliceTableModel);  {
		if .sliceLen == 0 {
			 = fmt.Errorf("pg: can't bulk-insert empty slice %s", .Type())
			return nil, 
		}
		,  = .appendSliceValues(, , , )
		if  != nil {
			return nil, 
		}
	} else {
		,  = .appendValues(, , , )
		if  != nil {
			return nil, 
		}
	}
	 = append(, ")"...)

	return , nil
}

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

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

	 = append(, " ("...)

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

	 = append(, ") VALUES ("...)

	for ,  := range  {
		if  > 0 {
			 = append(, ", "...)
		}
		if .placeholder {
			 = append(, '?')
		} else {
			 = types.Append(, [], 1)
		}
	}

	 = append(, ")"...)

	return 
}

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

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

		switch {
		case .placeholder:
			 = append(, '?')
		case (.Default != "" || .NullZero()) && .HasZeroValue():
			 = append(, "DEFAULT"...)
			.addReturningField()
		default:
			 = .AppendValue(, , 1)
		}
	}

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

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

	return , nil
}

func ( *InsertQuery) (
	 QueryFormatter,  []byte,  []*Field,  reflect.Value,
) ( []byte,  error) {
	if .placeholder {
		return .appendValues(, , , reflect.Value{})
	}

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

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

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

	return , nil
}

func ( *InsertQuery) ( *Field) {
	if len(.q.returning) > 0 {
		return
	}
	for ,  := range .returningFields {
		if  ==  {
			return
		}
	}
	.returningFields = append(.returningFields, )
}

func ( *InsertQuery) ( []byte,  []*Field) []byte {
	 = append(, " SET "...)
	for ,  := range  {
		if  > 0 {
			 = append(, ", "...)
		}
		 = append(, .Column...)
		 = append(, " = EXCLUDED."...)
		 = append(, .Column...)
	}
	return 
}

func ( *InsertQuery) ( []byte,  []*Field) []byte {
	 = appendColumns(, "", )
	for ,  := range .q.extraValues {
		if  > 0 || len() > 0 {
			 = append(, ", "...)
		}
		 = types.AppendIdent(, .column, 1)
	}
	return 
}

func ( []byte,  []*Field) []byte {
	 = append(, " RETURNING "...)
	 = appendColumns(, "", )
	return 
}