github.com/acoshift/pgsql@v0.15.3/pgstmt/insert.go (about) 1 package pgstmt 2 3 // Insert builds insert statement 4 func Insert(f func(b InsertStatement)) *Result { 5 var st insertStmt 6 f(&st) 7 return newResult(build(st.make())) 8 } 9 10 // InsertStatement is the insert statement builder 11 type InsertStatement interface { 12 Into(table string) 13 Columns(col ...string) 14 OverridingSystemValue() 15 OverridingUserValue() 16 DefaultValues() 17 Value(value ...any) 18 Values(values ...[]any) 19 Select(f func(b SelectStatement)) 20 21 OnConflict(f func(b ConflictTarget)) ConflictAction 22 23 // OnConflictDoNothing is the shortcut for 24 // OnConflict(func(b ConflictTarget) {}).DoNothing() 25 OnConflictDoNothing() 26 27 // OnConflictIndex is the shortcut for 28 // OnConflict(func(b ConflictTarget) { 29 // b.Index(target...) 30 // }) 31 OnConflictIndex(target ...string) ConflictAction 32 33 // OnConflictOnConstraint is the shortcut for 34 // OnConflict(func(b ConflictTarget) { 35 // b.OnConstraint(constraintName) 36 // }) 37 OnConflictOnConstraint(constraintName string) ConflictAction 38 39 Returning(col ...string) 40 } 41 42 type ConflictTarget interface { 43 Index(target ...string) 44 Where(f func(b Cond)) 45 OnConstraint(constraintName string) 46 } 47 48 type ConflictAction interface { 49 DoNothing() 50 DoUpdate(f func(b UpdateStatement)) 51 } 52 53 type insertStmt struct { 54 table string 55 columns parenGroup 56 overridingValue string 57 defaultValues bool 58 conflict *conflict 59 values group 60 selects *selectStmt 61 returning group 62 } 63 64 func (st *insertStmt) Into(table string) { 65 st.table = table 66 } 67 68 func (st *insertStmt) Columns(col ...string) { 69 st.columns.pushString(col...) 70 } 71 72 func (st *insertStmt) OverridingSystemValue() { 73 st.overridingValue = "system" 74 } 75 76 func (st *insertStmt) OverridingUserValue() { 77 st.overridingValue = "user" 78 } 79 80 func (st *insertStmt) DefaultValues() { 81 st.defaultValues = true 82 } 83 84 func (st *insertStmt) Value(value ...any) { 85 var x parenGroup 86 for _, v := range value { 87 x.push(Arg(v)) 88 } 89 st.values.push(&x) 90 } 91 92 func (st *insertStmt) Values(values ...[]any) { 93 for _, value := range values { 94 st.Value(value...) 95 } 96 } 97 98 func (st *insertStmt) Select(f func(b SelectStatement)) { 99 var x selectStmt 100 f(&x) 101 st.selects = &x 102 } 103 104 func (st *insertStmt) OnConflict(f func(b ConflictTarget)) ConflictAction { 105 var x conflict 106 f(&x) 107 st.conflict = &x 108 return &st.conflict.action 109 } 110 111 func (st *insertStmt) OnConflictDoNothing() { 112 st.conflict = &conflict{ 113 action: conflictAction{ 114 doNothing: true, 115 }, 116 } 117 } 118 119 func (st *insertStmt) OnConflictIndex(target ...string) ConflictAction { 120 return st.OnConflict(func(b ConflictTarget) { 121 b.Index(target...) 122 }) 123 } 124 125 func (st *insertStmt) OnConflictOnConstraint(constraintName string) ConflictAction { 126 return st.OnConflict(func(b ConflictTarget) { 127 b.OnConstraint(constraintName) 128 }) 129 } 130 131 func (st *insertStmt) Returning(col ...string) { 132 st.returning.pushString(col...) 133 } 134 135 func (st *insertStmt) make() *buffer { 136 var b buffer 137 b.push("insert") 138 if st.table != "" { 139 b.push("into", st.table) 140 } 141 if !st.columns.empty() { 142 b.push(&st.columns) 143 } 144 if st.overridingValue != "" { 145 b.push("overriding", st.overridingValue, "value") 146 } 147 if st.defaultValues { 148 b.push("default values") 149 } 150 if !st.values.empty() { 151 b.push("values", &st.values) 152 } 153 if st.selects != nil { 154 b.push(st.selects.make()) 155 } 156 if st.conflict != nil { 157 b.push(st.conflict.make()) 158 } 159 if !st.returning.empty() { 160 b.push("returning", &st.returning) 161 } 162 163 return &b 164 } 165 166 type conflict struct { 167 targets []string 168 where cond 169 constraint string 170 action conflictAction 171 } 172 173 func (st *conflict) make() *buffer { 174 // on conflict can be one of 175 // => ( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] ) [ WHERE index_predicate ] 176 // => ON CONSTRAINT constraint_name 177 178 var b buffer 179 180 b.push("on conflict") 181 182 if len(st.targets) > 0 { 183 b.push(parenString(st.targets...)) 184 185 if !st.where.empty() { 186 b.push("where", &st.where) 187 } 188 } else if st.constraint != "" { 189 b.push("on constraint", st.constraint) 190 } 191 192 b.push(st.action.make()) 193 194 return &b 195 } 196 197 func (st *conflict) Index(target ...string) { 198 st.targets = append(st.targets, target...) 199 } 200 201 func (st *conflict) Where(f func(b Cond)) { 202 f(&st.where) 203 } 204 205 func (st *conflict) OnConstraint(constraintName string) { 206 st.constraint = constraintName 207 } 208 209 type conflictAction struct { 210 doNothing bool 211 doUpdate *updateStmt 212 } 213 214 func (st *conflictAction) make() *buffer { 215 var b buffer 216 if st.doNothing { 217 b.push("do nothing") 218 } 219 if st.doUpdate != nil { 220 b.push("do", st.doUpdate.make()) 221 } 222 return &b 223 } 224 225 func (st *conflictAction) DoNothing() { 226 st.doNothing = true 227 } 228 229 func (st *conflictAction) DoUpdate(f func(b UpdateStatement)) { 230 var x updateStmt 231 f(&x) 232 st.doUpdate = &x 233 }