github.com/Ali-iotechsys/sqlboiler/v4@v4.0.0-20221208124957-6aec9a5f1f71/drivers/sqlboiler-sqlite3/driver/override/main/17_upsert.go.tpl (about) 1 {{- if or (not .Table.IsView) .Table.ViewCapabilities.CanUpsert -}} 2 {{- $alias := .Aliases.Table .Table.Name}} 3 {{- $schemaTable := .Table.Name | .SchemaTable}} 4 {{if .AddGlobal -}} 5 // UpsertG attempts an insert, and does an update or ignore on conflict. 6 func (o *{{$alias.UpSingular}}) UpsertG({{if not .NoContext}}ctx context.Context, {{end -}} updateOnConflict bool, conflictColumns []string, updateColumns, insertColumns boil.Columns) error { 7 return o.Upsert({{if .NoContext}}boil.GetDB(){{else}}ctx, boil.GetContextDB(){{end}}, updateOnConflict, conflictColumns, updateColumns, insertColumns) 8 } 9 10 {{end -}} 11 12 {{if and .AddGlobal .AddPanic -}} 13 // UpsertGP attempts an insert, and does an update or ignore on conflict. Panics on error. 14 func (o *{{$alias.UpSingular}}) UpsertGP({{if not .NoContext}}ctx context.Context, {{end -}} updateOnConflict bool, conflictColumns []string, updateColumns, insertColumns boil.Columns) { 15 if err := o.Upsert({{if .NoContext}}boil.GetDB(){{else}}ctx, boil.GetContextDB(){{end}}, updateOnConflict, conflictColumns, updateColumns, insertColumns); err != nil { 16 panic(boil.WrapErr(err)) 17 } 18 } 19 20 {{end -}} 21 22 {{if .AddPanic -}} 23 // UpsertP attempts an insert using an executor, and does an update or ignore on conflict. 24 // UpsertP panics on error. 25 func (o *{{$alias.UpSingular}}) UpsertP({{if .NoContext}}exec boil.Executor{{else}}ctx context.Context, exec boil.ContextExecutor{{end}}, updateOnConflict bool, conflictColumns []string, updateColumns, insertColumns boil.Columns) { 26 if err := o.Upsert({{if not .NoContext}}ctx, {{end -}} exec, updateOnConflict, conflictColumns, updateColumns, insertColumns); err != nil { 27 panic(boil.WrapErr(err)) 28 } 29 } 30 31 {{end -}} 32 33 // Upsert attempts an insert using an executor, and does an update or ignore on conflict. 34 // See boil.Columns documentation for how to properly use updateColumns and insertColumns. 35 func (o *{{$alias.UpSingular}}) Upsert({{if .NoContext}}exec boil.Executor{{else}}ctx context.Context, exec boil.ContextExecutor{{end}}, updateOnConflict bool, conflictColumns []string, updateColumns, insertColumns boil.Columns) error { 36 if o == nil { 37 return errors.New("{{.PkgName}}: no {{.Table.Name}} provided for upsert") 38 } 39 40 {{- template "timestamp_upsert_helper" . }} 41 42 {{if not .NoHooks -}} 43 if err := o.doBeforeUpsertHooks({{if not .NoContext}}ctx, {{end -}} exec); err != nil { 44 return err 45 } 46 {{- end}} 47 48 nzDefaults := queries.NonZeroDefaultSet({{$alias.DownSingular}}ColumnsWithDefault, o) 49 50 // Build cache key in-line uglily - mysql vs psql problems 51 buf := strmangle.GetBuffer() 52 if updateOnConflict { 53 buf.WriteByte('t') 54 } else { 55 buf.WriteByte('f') 56 } 57 buf.WriteByte('.') 58 for _, c := range conflictColumns { 59 buf.WriteString(c) 60 } 61 buf.WriteByte('.') 62 buf.WriteString(strconv.Itoa(updateColumns.Kind)) 63 for _, c := range updateColumns.Cols { 64 buf.WriteString(c) 65 } 66 buf.WriteByte('.') 67 buf.WriteString(strconv.Itoa(insertColumns.Kind)) 68 for _, c := range insertColumns.Cols { 69 buf.WriteString(c) 70 } 71 buf.WriteByte('.') 72 for _, c := range nzDefaults { 73 buf.WriteString(c) 74 } 75 key := buf.String() 76 strmangle.PutBuffer(buf) 77 78 {{$alias.DownSingular}}UpsertCacheMut.RLock() 79 cache, cached := {{$alias.DownSingular}}UpsertCache[key] 80 {{$alias.DownSingular}}UpsertCacheMut.RUnlock() 81 82 var err error 83 84 if !cached { 85 insert, ret := insertColumns.InsertColumnSet( 86 {{$alias.DownSingular}}AllColumns, 87 {{$alias.DownSingular}}ColumnsWithDefault, 88 {{$alias.DownSingular}}ColumnsWithoutDefault, 89 nzDefaults, 90 ) 91 update := updateColumns.UpdateColumnSet( 92 {{$alias.DownSingular}}AllColumns, 93 {{$alias.DownSingular}}PrimaryKeyColumns, 94 ) 95 96 if updateOnConflict && len(update) == 0 { 97 return errors.New("{{.PkgName}}: unable to upsert {{.Table.Name}}, could not build update column list") 98 } 99 100 conflict := conflictColumns 101 if len(conflict) == 0 { 102 conflict = make([]string, len({{$alias.DownSingular}}PrimaryKeyColumns)) 103 copy(conflict, {{$alias.DownSingular}}PrimaryKeyColumns) 104 } 105 cache.query = buildUpsertQuerySQLite(dialect, "{{$schemaTable}}", updateOnConflict, ret, update, conflict, insert) 106 107 cache.valueMapping, err = queries.BindMapping({{$alias.DownSingular}}Type, {{$alias.DownSingular}}Mapping, insert) 108 if err != nil { 109 return err 110 } 111 if len(ret) != 0 { 112 cache.retMapping, err = queries.BindMapping({{$alias.DownSingular}}Type, {{$alias.DownSingular}}Mapping, ret) 113 if err != nil { 114 return err 115 } 116 } 117 } 118 119 value := reflect.Indirect(reflect.ValueOf(o)) 120 vals := queries.ValuesFromMapping(value, cache.valueMapping) 121 var returns []interface{} 122 if len(cache.retMapping) != 0 { 123 returns = queries.PtrsFromMapping(value, cache.retMapping) 124 } 125 126 {{if .NoContext -}} 127 if boil.DebugMode { 128 fmt.Fprintln(boil.DebugWriter, cache.query) 129 fmt.Fprintln(boil.DebugWriter, vals) 130 } 131 {{else -}} 132 if boil.IsDebug(ctx) { 133 writer := boil.DebugWriterFrom(ctx) 134 fmt.Fprintln(writer, cache.query) 135 fmt.Fprintln(writer, vals) 136 } 137 {{end -}} 138 139 if len(cache.retMapping) != 0 { 140 {{if .NoContext -}} 141 err = exec.QueryRow(cache.query, vals...).Scan(returns...) 142 {{else -}} 143 err = exec.QueryRowContext(ctx, cache.query, vals...).Scan(returns...) 144 {{end -}} 145 if errors.Is(err, sql.ErrNoRows) { 146 err = nil // Postgres doesn't return anything when there's no update 147 } 148 } else { 149 {{if .NoContext -}} 150 _, err = exec.Exec(cache.query, vals...) 151 {{else -}} 152 _, err = exec.ExecContext(ctx, cache.query, vals...) 153 {{end -}} 154 } 155 if err != nil { 156 return errors.Wrap(err, "{{.PkgName}}: unable to upsert {{.Table.Name}}") 157 } 158 159 if !cached { 160 {{$alias.DownSingular}}UpsertCacheMut.Lock() 161 {{$alias.DownSingular}}UpsertCache[key] = cache 162 {{$alias.DownSingular}}UpsertCacheMut.Unlock() 163 } 164 165 {{if not .NoHooks -}} 166 return o.doAfterUpsertHooks({{if not .NoContext}}ctx, {{end -}} exec) 167 {{- else -}} 168 return nil 169 {{- end}} 170 } 171 {{end}}