aboutsummaryrefslogtreecommitdiff
path: root/src/models/psql_upsert.go
blob: d71b7d666c5e85019b7f62a4c8fa3ac6da02e7f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Code generated by SQLBoiler 4.16.1 (https://github.com/volatiletech/sqlboiler). DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.

package models

import (
	"fmt"
	"strings"

	"github.com/volatiletech/sqlboiler/v4/drivers"
	"github.com/volatiletech/strmangle"
)

type UpsertOptions struct {
	conflictTarget string
	updateSet      string
}

type UpsertOptionFunc func(o *UpsertOptions)

func UpsertConflictTarget(conflictTarget string) UpsertOptionFunc {
	return func(o *UpsertOptions) {
		o.conflictTarget = conflictTarget
	}
}

func UpsertUpdateSet(updateSet string) UpsertOptionFunc {
	return func(o *UpsertOptions) {
		o.updateSet = updateSet
	}
}

// buildUpsertQueryPostgres builds a SQL statement string using the upsertData provided.
func buildUpsertQueryPostgres(dia drivers.Dialect, tableName string, updateOnConflict bool, ret, update, conflict, whitelist []string, opts ...UpsertOptionFunc) string {
	conflict = strmangle.IdentQuoteSlice(dia.LQ, dia.RQ, conflict)
	whitelist = strmangle.IdentQuoteSlice(dia.LQ, dia.RQ, whitelist)
	ret = strmangle.IdentQuoteSlice(dia.LQ, dia.RQ, ret)

	upsertOpts := &UpsertOptions{}
	for _, o := range opts {
		o(upsertOpts)
	}

	buf := strmangle.GetBuffer()
	defer strmangle.PutBuffer(buf)

	columns := "DEFAULT VALUES"
	if len(whitelist) != 0 {
		columns = fmt.Sprintf("(%s) VALUES (%s)",
			strings.Join(whitelist, ", "),
			strmangle.Placeholders(dia.UseIndexPlaceholders, len(whitelist), 1, 1))
	}

	fmt.Fprintf(
		buf,
		"INSERT INTO %s %s ON CONFLICT ",
		tableName,
		columns,
	)

	if upsertOpts.conflictTarget != "" {
		buf.WriteString(upsertOpts.conflictTarget)
	} else if len(conflict) != 0 {
		buf.WriteByte('(')
		buf.WriteString(strings.Join(conflict, ", "))
		buf.WriteByte(')')
	}
	buf.WriteByte(' ')

	if !updateOnConflict || len(update) == 0 {
		buf.WriteString("DO NOTHING")
	} else {
		buf.WriteString("DO UPDATE SET ")

		if upsertOpts.updateSet != "" {
			buf.WriteString(upsertOpts.updateSet)
		} else {
			for i, v := range update {
				if len(v) == 0 {
					continue
				}
				if i != 0 {
					buf.WriteByte(',')
				}
				quoted := strmangle.IdentQuote(dia.LQ, dia.RQ, v)
				buf.WriteString(quoted)
				buf.WriteString(" = EXCLUDED.")
				buf.WriteString(quoted)
			}
		}
	}

	if len(ret) != 0 {
		buf.WriteString(" RETURNING ")
		buf.WriteString(strings.Join(ret, ", "))
	}

	return buf.String()
}