package squirrel

import (
	
	
	
	
	
	
	

	
)

type insertData struct {
	PlaceholderFormat PlaceholderFormat
	RunWith           BaseRunner
	Prefixes          []Sqlizer
	StatementKeyword  string
	Options           []string
	Into              string
	Columns           []string
	Values            [][]interface{}
	Suffixes          []Sqlizer
	Select            *SelectBuilder
}

func ( *insertData) () (sql.Result, error) {
	if .RunWith == nil {
		return nil, RunnerNotSet
	}
	return ExecWith(.RunWith, )
}

func ( *insertData) () (*sql.Rows, error) {
	if .RunWith == nil {
		return nil, RunnerNotSet
	}
	return QueryWith(.RunWith, )
}

func ( *insertData) () RowScanner {
	if .RunWith == nil {
		return &Row{err: RunnerNotSet}
	}
	,  := .RunWith.(QueryRower)
	if ! {
		return &Row{err: RunnerNotQueryRunner}
	}
	return QueryRowWith(, )
}

func ( *insertData) () ( string,  []interface{},  error) {
	if len(.Into) == 0 {
		 = errors.New("insert statements must specify a table")
		return
	}
	if len(.Values) == 0 && .Select == nil {
		 = errors.New("insert statements must have at least one set of values or select clause")
		return
	}

	 := &bytes.Buffer{}

	if len(.Prefixes) > 0 {
		,  = appendToSql(.Prefixes, , " ", )
		if  != nil {
			return
		}

		.WriteString(" ")
	}

	if .StatementKeyword == "" {
		.WriteString("INSERT ")
	} else {
		.WriteString(.StatementKeyword)
		.WriteString(" ")
	}

	if len(.Options) > 0 {
		.WriteString(strings.Join(.Options, " "))
		.WriteString(" ")
	}

	.WriteString("INTO ")
	.WriteString(.Into)
	.WriteString(" ")

	if len(.Columns) > 0 {
		.WriteString("(")
		.WriteString(strings.Join(.Columns, ","))
		.WriteString(") ")
	}

	if .Select != nil {
		,  = .appendSelectToSQL(, )
	} else {
		,  = .appendValuesToSQL(, )
	}
	if  != nil {
		return
	}

	if len(.Suffixes) > 0 {
		.WriteString(" ")
		,  = appendToSql(.Suffixes, , " ", )
		if  != nil {
			return
		}
	}

	,  = .PlaceholderFormat.ReplacePlaceholders(.String())
	return
}

func ( *insertData) ( io.Writer,  []interface{}) ([]interface{}, error) {
	if len(.Values) == 0 {
		return , errors.New("values for insert statements are not set")
	}

	io.WriteString(, "VALUES ")

	 := make([]string, len(.Values))
	for ,  := range .Values {
		 := make([]string, len())
		for ,  := range  {
			if ,  := .(Sqlizer);  {
				, ,  := .ToSql()
				if  != nil {
					return nil, 
				}
				[] = 
				 = append(, ...)
			} else {
				[] = "?"
				 = append(, )
			}
		}
		[] = fmt.Sprintf("(%s)", strings.Join(, ","))
	}

	io.WriteString(, strings.Join(, ","))

	return , nil
}

func ( *insertData) ( io.Writer,  []interface{}) ([]interface{}, error) {
	if .Select == nil {
		return , errors.New("select clause for insert statements are not set")
	}

	, ,  := .Select.ToSql()
	if  != nil {
		return , 
	}

	io.WriteString(, )
	 = append(, ...)

	return , nil
}
Builder
InsertBuilder builds SQL INSERT statements.
Format methods
PlaceholderFormat sets PlaceholderFormat (e.g. Question or Dollar) for the query.
func ( InsertBuilder) ( PlaceholderFormat) InsertBuilder {
	return builder.Set(, "PlaceholderFormat", ).(InsertBuilder)
}
Runner methods
RunWith sets a Runner (like database/sql.DB) to be used with e.g. Exec.
func ( InsertBuilder) ( BaseRunner) InsertBuilder {
	return setRunWith(, ).(InsertBuilder)
}
Exec builds and Execs the query with the Runner set by RunWith.
func ( InsertBuilder) () (sql.Result, error) {
	 := builder.GetStruct().(insertData)
	return .Exec()
}
Query builds and Querys the query with the Runner set by RunWith.
func ( InsertBuilder) () (*sql.Rows, error) {
	 := builder.GetStruct().(insertData)
	return .Query()
}
QueryRow builds and QueryRows the query with the Runner set by RunWith.
func ( InsertBuilder) () RowScanner {
	 := builder.GetStruct().(insertData)
	return .QueryRow()
}
Scan is a shortcut for QueryRow().Scan.
func ( InsertBuilder) ( ...interface{}) error {
	return .QueryRow().Scan(...)
}
SQL methods
ToSql builds the query into a SQL string and bound args.
func ( InsertBuilder) () (string, []interface{}, error) {
	 := builder.GetStruct().(insertData)
	return .ToSql()
}
Prefix adds an expression to the beginning of the query
func ( InsertBuilder) ( string,  ...interface{}) InsertBuilder {
	return .PrefixExpr(Expr(, ...))
}
PrefixExpr adds an expression to the very beginning of the query
func ( InsertBuilder) ( Sqlizer) InsertBuilder {
	return builder.Append(, "Prefixes", ).(InsertBuilder)
}
Options adds keyword options before the INTO clause of the query.
func ( InsertBuilder) ( ...string) InsertBuilder {
	return builder.Extend(, "Options", ).(InsertBuilder)
}
Into sets the INTO clause of the query.
func ( InsertBuilder) ( string) InsertBuilder {
	return builder.Set(, "Into", ).(InsertBuilder)
}
Columns adds insert columns to the query.
func ( InsertBuilder) ( ...string) InsertBuilder {
	return builder.Extend(, "Columns", ).(InsertBuilder)
}
Values adds a single row's values to the query.
func ( InsertBuilder) ( ...interface{}) InsertBuilder {
	return builder.Append(, "Values", ).(InsertBuilder)
}
Suffix adds an expression to the end of the query
func ( InsertBuilder) ( string,  ...interface{}) InsertBuilder {
	return .SuffixExpr(Expr(, ...))
}
SuffixExpr adds an expression to the end of the query
func ( InsertBuilder) ( Sqlizer) InsertBuilder {
	return builder.Append(, "Suffixes", ).(InsertBuilder)
}
SetMap set columns and values for insert builder from a map of column name and value note that it will reset all previous columns and values was set if any
Keep the columns in a consistent order by sorting the column key string.
	 := make([]string, 0, len())
	for  := range  {
		 = append(, )
	}
	sort.Strings()

	 := make([]interface{}, 0, len())
	for ,  := range  {
		 = append(, [])
	}

	 = builder.Set(, "Columns", ).(InsertBuilder)
	 = builder.Set(, "Values", [][]interface{}{}).(InsertBuilder)

	return 
}
Select set Select clause for insert query If Values and Select are used, then Select has higher priority
func ( InsertBuilder) ( SelectBuilder) InsertBuilder {
	return builder.Set(, "Select", &).(InsertBuilder)
}

func ( InsertBuilder) ( string) InsertBuilder {
	return builder.Set(, "StatementKeyword", ).(InsertBuilder)