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}}