DoInsert inserts or updates data for given table. The list parameter must contain at least one record, which was previously validated.
( ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, )
| 19 | // DoInsert inserts or updates data for given table. |
| 20 | // The list parameter must contain at least one record, which was previously validated. |
| 21 | func (d *Driver) DoInsert( |
| 22 | ctx context.Context, |
| 23 | link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, |
| 24 | ) (result sql.Result, err error) { |
| 25 | switch option.InsertOption { |
| 26 | case |
| 27 | gdb.InsertOptionSave, |
| 28 | gdb.InsertOptionReplace: |
| 29 | // PostgreSQL does not support REPLACE INTO syntax, use Save (ON CONFLICT ... DO UPDATE) instead. |
| 30 | // Automatically detect primary keys if OnConflict is not specified. |
| 31 | if len(option.OnConflict) == 0 { |
| 32 | primaryKeys, err := d.Core.GetPrimaryKeys(ctx, table) |
| 33 | if err != nil { |
| 34 | return nil, gerror.WrapCode( |
| 35 | gcode.CodeInternalError, |
| 36 | err, |
| 37 | `failed to get primary keys for Save/Replace operation`, |
| 38 | ) |
| 39 | } |
| 40 | foundPrimaryKey := false |
| 41 | for _, primaryKey := range primaryKeys { |
| 42 | for dataKey := range list[0] { |
| 43 | if strings.EqualFold(dataKey, primaryKey) { |
| 44 | foundPrimaryKey = true |
| 45 | break |
| 46 | } |
| 47 | } |
| 48 | if foundPrimaryKey { |
| 49 | break |
| 50 | } |
| 51 | } |
| 52 | if !foundPrimaryKey { |
| 53 | return nil, gerror.NewCodef( |
| 54 | gcode.CodeMissingParameter, |
| 55 | `Replace/Save operation requires conflict detection: `+ |
| 56 | `either specify OnConflict() columns or ensure table '%s' has a primary key in the data`, |
| 57 | table, |
| 58 | ) |
| 59 | } |
| 60 | // TODO consider composite primary keys. |
| 61 | option.OnConflict = primaryKeys |
| 62 | } |
| 63 | // Treat Replace as Save operation |
| 64 | option.InsertOption = gdb.InsertOptionSave |
| 65 | |
| 66 | // pgsql support InsertIgnore natively, so no need to set primary key in context. |
| 67 | case gdb.InsertOptionIgnore, gdb.InsertOptionDefault: |
| 68 | // Get table fields to retrieve the primary key TableField object (not just the name) |
| 69 | // because DoExec needs the `TableField.Type` to determine if LastInsertId is supported. |
| 70 | tableFields, err := d.GetCore().GetDB().TableFields(ctx, table) |
| 71 | if err == nil { |
| 72 | for _, field := range tableFields { |
| 73 | if strings.EqualFold(field.Key, "pri") { |
| 74 | pkField := *field |
| 75 | ctx = context.WithValue(ctx, internalPrimaryKeyInCtx, pkField) |
| 76 | break |
| 77 | } |
| 78 | } |
nothing calls this directly
no test coverage detected