github.com/Ali-iotechsys/sqlboiler/v4@v4.0.0-20221208124957-6aec9a5f1f71/drivers/sqlboiler-mssql/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 -}} updateColumns, insertColumns boil.Columns) error {
     7  	return o.Upsert({{if .NoContext}}boil.GetDB(){{else}}ctx, boil.GetContextDB(){{end}}, 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 -}} updateColumns, insertColumns boil.Columns) {
    15  	if err := o.Upsert({{if .NoContext}}boil.GetDB(){{else}}ctx, boil.GetContextDB(){{end}}, 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}}, updateColumns, insertColumns boil.Columns) {
    26  	if err := o.Upsert({{if not .NoContext}}ctx, {{end -}} exec, 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  func (o *{{$alias.UpSingular}}) Upsert({{if .NoContext}}exec boil.Executor{{else}}ctx context.Context, exec boil.ContextExecutor{{end}}, updateColumns, insertColumns boil.Columns) error {
    35  	if o == nil {
    36  		return errors.New("{{.PkgName}}: no {{.Table.Name}} provided for upsert")
    37  	}
    38  
    39  	{{- template "timestamp_upsert_helper" . }}
    40  
    41  	{{if not .NoHooks -}}
    42  	if err := o.doBeforeUpsertHooks({{if not .NoContext}}ctx, {{end -}} exec); err != nil {
    43  		return err
    44  	}
    45  	{{- end}}
    46  
    47  	nzDefaults := queries.NonZeroDefaultSet({{$alias.DownSingular}}ColumnsWithDefault, o)
    48  
    49  	// Build cache key in-line uglily - mysql vs psql problems
    50  	buf := strmangle.GetBuffer()
    51  	buf.WriteString(strconv.Itoa(updateColumns.Kind))
    52  	for _, c := range updateColumns.Cols {
    53  		buf.WriteString(c)
    54  	}
    55  	buf.WriteByte('.')
    56  	buf.WriteString(strconv.Itoa(insertColumns.Kind))
    57  	for _, c := range insertColumns.Cols {
    58  		buf.WriteString(c)
    59  	}
    60  	buf.WriteByte('.')
    61  	for _, c := range nzDefaults {
    62  		buf.WriteString(c)
    63  	}
    64  	key := buf.String()
    65  	strmangle.PutBuffer(buf)
    66  
    67  	{{$alias.DownSingular}}UpsertCacheMut.RLock()
    68  	cache, cached := {{$alias.DownSingular}}UpsertCache[key]
    69  	{{$alias.DownSingular}}UpsertCacheMut.RUnlock()
    70  
    71  	var err error
    72  
    73  	if !cached {
    74  		insert, ret := insertColumns.InsertColumnSet(
    75  			{{$alias.DownSingular}}AllColumns,
    76  			{{$alias.DownSingular}}ColumnsWithDefault,
    77  			{{$alias.DownSingular}}ColumnsWithoutDefault,
    78  			nzDefaults,
    79  		)
    80  		{{if filterColumnsByAuto true .Table.Columns }}
    81  		insert = strmangle.SetComplement(insert, {{$alias.DownSingular}}GeneratedColumns)
    82  		{{end}}
    83  
    84  		for i, v := range insert {
    85  			if strmangle.ContainsAny({{$alias.DownSingular}}PrimaryKeyColumns, v) && strmangle.ContainsAny({{$alias.DownSingular}}ColumnsWithDefault, v) {
    86  				insert = append(insert[:i], insert[i+1:]...)
    87  			}
    88  		}
    89  		if len(insert) == 0 {
    90  			return errors.New("{{.PkgName}}: unable to upsert {{.Table.Name}}, could not build insert column list")
    91  		}
    92  
    93  		update := updateColumns.UpdateColumnSet(
    94  			{{$alias.DownSingular}}AllColumns,
    95  			{{$alias.DownSingular}}PrimaryKeyColumns,
    96  		)
    97  		{{if filterColumnsByAuto true .Table.Columns }}
    98  		insert = strmangle.SetComplement(insert, {{$alias.DownSingular}}GeneratedColumns)
    99  		{{end}}
   100  
   101  		if !updateColumns.IsNone() && len(update) == 0 {
   102  			return errors.New("{{.PkgName}}: unable to upsert {{.Table.Name}}, could not build update column list")
   103  		}
   104  
   105  		cache.query = buildUpsertQueryMSSQL(dialect, "{{$schemaTable}}", {{$alias.DownSingular}}PrimaryKeyColumns, update, insert, ret)
   106  
   107  		whitelist := make([]string, len({{$alias.DownSingular}}PrimaryKeyColumns))
   108  		copy(whitelist, {{$alias.DownSingular}}PrimaryKeyColumns)
   109  		whitelist = append(whitelist, update...)
   110  		whitelist = append(whitelist, insert...)
   111  
   112  		cache.valueMapping, err = queries.BindMapping({{$alias.DownSingular}}Type, {{$alias.DownSingular}}Mapping, whitelist)
   113  		if err != nil {
   114  			return err
   115  		}
   116  		if len(ret) != 0 {
   117  			cache.retMapping, err = queries.BindMapping({{$alias.DownSingular}}Type, {{$alias.DownSingular}}Mapping, ret)
   118  			if err != nil {
   119  				return err
   120  			}
   121  		}
   122  	}
   123  
   124  	value := reflect.Indirect(reflect.ValueOf(o))
   125  	vals := queries.ValuesFromMapping(value, cache.valueMapping)
   126  	var returns []interface{}
   127  	if len(cache.retMapping) != 0 {
   128  		returns = queries.PtrsFromMapping(value, cache.retMapping)
   129  	}
   130  
   131  	{{if .NoContext -}}
   132  	if boil.DebugMode {
   133  		fmt.Fprintln(boil.DebugWriter, cache.query)
   134  		fmt.Fprintln(boil.DebugWriter, vals)
   135  	}
   136  	{{else -}}
   137  	if boil.IsDebug(ctx) {
   138  		writer := boil.DebugWriterFrom(ctx)
   139  		fmt.Fprintln(writer, cache.query)
   140  		fmt.Fprintln(writer, vals)
   141  	}
   142  	{{end -}}
   143  
   144  	if len(cache.retMapping) != 0 {
   145  		{{if .NoContext -}}
   146  		err = exec.QueryRow(cache.query, vals...).Scan(returns...)
   147  		{{else -}}
   148  		err = exec.QueryRowContext(ctx, cache.query, vals...).Scan(returns...)
   149  		{{end -}}
   150  		if errors.Is(err, sql.ErrNoRows) {
   151  			err = nil // MSSQL doesn't return anything when there's no update
   152  		}
   153  	} else {
   154  		{{if .NoContext -}}
   155  		_, err = exec.Exec(cache.query, vals...)
   156  		{{else -}}
   157  		_, err = exec.ExecContext(ctx, cache.query, vals...)
   158  		{{end -}}
   159  	}
   160  	if err != nil {
   161  		return errors.Wrap(err, "{{.PkgName}}: unable to upsert {{.Table.Name}}")
   162  	}
   163  
   164  	if !cached {
   165  		{{$alias.DownSingular}}UpsertCacheMut.Lock()
   166  		{{$alias.DownSingular}}UpsertCache[key] = cache
   167  		{{$alias.DownSingular}}UpsertCacheMut.Unlock()
   168  	}
   169  
   170  	{{if not .NoHooks -}}
   171  	return o.doAfterUpsertHooks({{if not .NoContext}}ctx, {{end -}} exec)
   172  	{{- else -}}
   173  	return nil
   174  	{{- end}}
   175  }
   176  {{end}}