Insert is used to add or update an object into the given table. When updating an object, the obj provided should be a copy rather than a value updated in-place. Modifying values in-place that are already inserted into MemDB is not supported behavior.
(table string, obj interface{})
| 181 | // than a value updated in-place. Modifying values in-place that are already |
| 182 | // inserted into MemDB is not supported behavior. |
| 183 | func (txn *Txn) Insert(table string, obj interface{}) error { |
| 184 | if !txn.write { |
| 185 | return fmt.Errorf("cannot insert in read-only transaction") |
| 186 | } |
| 187 | |
| 188 | // Get the table schema |
| 189 | tableSchema, ok := txn.db.schema.Tables[table] |
| 190 | if !ok { |
| 191 | return fmt.Errorf("invalid table '%s'", table) |
| 192 | } |
| 193 | |
| 194 | // Get the primary ID of the object |
| 195 | idSchema := tableSchema.Indexes[id] |
| 196 | idIndexer := idSchema.Indexer.(SingleIndexer) |
| 197 | ok, idVal, err := idIndexer.FromObject(obj) |
| 198 | if err != nil { |
| 199 | return fmt.Errorf("failed to build primary index: %v", err) |
| 200 | } |
| 201 | if !ok { |
| 202 | return fmt.Errorf("object missing primary index") |
| 203 | } |
| 204 | |
| 205 | // Lookup the object by ID first, to see if this is an update |
| 206 | idTxn := txn.writableIndex(table, id) |
| 207 | existing, update := idTxn.Get(idVal) |
| 208 | |
| 209 | // On an update, there is an existing object with the given |
| 210 | // primary ID. We do the update by deleting the current object |
| 211 | // and inserting the new object. |
| 212 | for name, indexSchema := range tableSchema.Indexes { |
| 213 | indexTxn := txn.writableIndex(table, name) |
| 214 | |
| 215 | // Determine the new index value |
| 216 | var ( |
| 217 | ok bool |
| 218 | vals [][]byte |
| 219 | err error |
| 220 | ) |
| 221 | switch indexer := indexSchema.Indexer.(type) { |
| 222 | case SingleIndexer: |
| 223 | var val []byte |
| 224 | ok, val, err = indexer.FromObject(obj) |
| 225 | vals = [][]byte{val} |
| 226 | case MultiIndexer: |
| 227 | ok, vals, err = indexer.FromObject(obj) |
| 228 | } |
| 229 | if err != nil { |
| 230 | return fmt.Errorf("failed to build index '%s': %v", name, err) |
| 231 | } |
| 232 | |
| 233 | // Handle non-unique index by computing a unique index. |
| 234 | // This is done by appending the primary key which must |
| 235 | // be unique anyways. |
| 236 | if ok && !indexSchema.Unique { |
| 237 | for i := range vals { |
| 238 | vals[i] = append(vals[i], idVal...) |
| 239 | } |
| 240 | } |