-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathinsert.go
123 lines (111 loc) · 2.79 KB
/
insert.go
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package sqlbuilder
// InsertStatement represents a INSERT statement.
type InsertStatement struct {
columns ColumnList
values []literal
into Table
err error
}
// Insert returns new INSERT statement. The table is Table object for into.
func Insert(into Table) *InsertStatement {
if into == nil {
return &InsertStatement{
err: newError("table is nil."),
}
}
if _, ok := into.(*table); !ok {
return &InsertStatement{
err: newError("table is not natural table."),
}
}
return &InsertStatement{
into: into,
columns: make(ColumnList, 0),
values: make([]literal, 0),
}
}
// Columns sets columns for insert. This overwrite old results of Columns() or Set().
// If not set this, get error on ToSql().
func (b *InsertStatement) Columns(columns ...Column) *InsertStatement {
if b.err != nil {
return b
}
for _, col := range columns {
if !b.into.hasColumn(col) {
b.err = newError("column not found in table.")
return b
}
}
b.columns = ColumnList(columns)
return b
}
// Values sets VALUES clause. This overwrite old results of Values() or Set().
func (b *InsertStatement) Values(values ...interface{}) *InsertStatement {
if b.err != nil {
return b
}
sl := make([]literal, len(values))
for i := range values {
sl[i] = toLiteral(values[i])
}
b.values = sl
return b
}
// Set sets the column and value togeter.
// Set cannot be called with Columns() or Values() in a statement.
func (b *InsertStatement) Set(column Column, value interface{}) *InsertStatement {
if b.err != nil {
return b
}
if !b.into.hasColumn(column) {
b.err = newError("column not found in FROM.")
return b
}
b.columns = append(b.columns, column)
b.values = append(b.values, toLiteral(value))
return b
}
// ToSql generates query string, placeholder arguments, and returns err on errors.
func (b *InsertStatement) ToSql() (query string, args []interface{}, err error) {
bldr := newBuilder()
defer func() {
query, args, err = bldr.Query(), bldr.Args(), bldr.Err()
}()
if b.err != nil {
bldr.SetError(b.err)
return
}
// INSERT
bldr.Append("INSERT")
// INTO Table
bldr.Append(" INTO ")
bldr.AppendItem(b.into)
// (COLUMN)
if len(b.columns) == 0 {
b.columns = b.into.Columns()
}
bldr.Append(" ( ")
bldr.AppendItem(b.columns)
bldr.Append(" )")
// VALUES
if len(b.columns) != len(b.values) {
bldr.SetError(newError("%d values needed, but got %d.", len(b.columns), len(b.values)))
return
}
for i := range b.columns {
if !b.columns[i].acceptType(b.values[i]) {
bldr.SetError(newError("%s column not accept %T.",
b.columns[i].config().Type().String(),
b.values[i].Raw()))
return
}
}
bldr.Append(" VALUES ( ")
values := make([]serializable, len(b.values))
for i := range values {
values[i] = b.values[i]
}
bldr.AppendItems(values, ", ")
bldr.Append(" )")
return
}