// Appends an item (map or struct) into the collection. func (self *table) Append(item interface{}) (interface{}, error) { var pKey string var columns sqlgen.Columns var values sqlgen.Values var arguments []interface{} var id int64 cols, vals, err := self.FieldValues(item, toInternal) if err != nil { return nil, err } columns = make(sqlgen.Columns, 0, len(cols)) for i := range cols { columns = append(columns, sqlgen.Column{cols[i]}) } arguments = make([]interface{}, 0, len(vals)) values = make(sqlgen.Values, 0, len(vals)) for i := range vals { switch v := vals[i].(type) { case sqlgen.Value: // Adding value. values = append(values, v) default: // Adding both value and placeholder. values = append(values, sqlPlaceholder) arguments = append(arguments, v) } } if pKey, err = self.source.getPrimaryKey(self.tableN(0)); err != nil { if err != sql.ErrNoRows { // Can't tell primary key. return nil, err } } stmt := sqlgen.Statement{ Type: sqlgen.SqlInsert, Table: sqlgen.Table{self.tableN(0)}, Columns: columns, Values: values, } if pKey == "" { // No primary key found. var res sql.Result if res, err = self.source.doExec(stmt, arguments...); err != nil { return nil, err } // Attempt to use LastInsertId() (probably won't work, but the exec() // succeeded, so the error from LastInsertId() is ignored). id, _ = res.LastInsertId() return id, nil } else { var row *sql.Row // A primary key was found. stmt.Extra = sqlgen.Extra(fmt.Sprintf(`RETURNING "%s"`, pKey)) if row, err = self.source.doQueryRow(stmt, arguments...); err != nil { return nil, err } // Retrieving key value. if err = row.Scan(&id); err != nil { if err == sql.ErrNoRows { // Can't tell the row's id. Maybe there isn't any? return nil, nil } // Other kind of error. return nil, err } return id, nil } return nil, nil }
// Appends an item (map or struct) into the collection. func (t *table) Append(item interface{}) (interface{}, error) { var pKey []string var columns sqlgen.Columns var values sqlgen.Values var arguments []interface{} //var id []interface{} cols, vals, err := t.FieldValues(item, toInternal) if err != nil { return nil, err } columns = make(sqlgen.Columns, 0, len(cols)) for i := range cols { columns = append(columns, sqlgen.Column{cols[i]}) } arguments = make([]interface{}, 0, len(vals)) values = make(sqlgen.Values, 0, len(vals)) for i := range vals { switch v := vals[i].(type) { case sqlgen.Value: // Adding value. values = append(values, v) default: // Adding both value and placeholder. values = append(values, sqlPlaceholder) arguments = append(arguments, v) } } if pKey, err = t.source.getPrimaryKey(t.tableN(0)); err != nil { if err != sql.ErrNoRows { // Can't tell primary key. return nil, err } } stmt := sqlgen.Statement{ Type: sqlgen.SqlInsert, Table: sqlgen.Table{t.tableN(0)}, Columns: columns, Values: values, } // No primary keys defined. if len(pKey) == 0 { var res sql.Result if res, err = t.source.doExec(stmt, arguments...); err != nil { return nil, err } // Attempt to use LastInsertId() (probably won't work, but the exec() // succeeded, so the error from LastInsertId() is ignored). lastID, _ := res.LastInsertId() return lastID, nil } var rows *sql.Rows // A primary key was found. stmt.Extra = sqlgen.Extra(fmt.Sprintf(`RETURNING "%s"`, strings.Join(pKey, `", "`))) if rows, err = t.source.doQuery(stmt, arguments...); err != nil { return nil, err } defer rows.Close() var keyMap map[string]interface{} err = sqlutil.FetchRow(rows, &keyMap) // Does the item satisfy the db.IDSetter interface? if setter, ok := item.(db.IDSetter); ok { if err := setter.SetID(keyMap); err != nil { return nil, err } return nil, nil } // The IDSetter interface does not match, we'll be looking for another // interface match. if len(keyMap) == 1 { id := keyMap[pKey[0]] // Matches db.Int64IDSetter if setter, ok := item.(db.Int64IDSetter); ok { if err = setter.SetID(to.Int64(id)); err != nil { return nil, err } return nil, nil } // Matches db.Uint64IDSetter if setter, ok := item.(db.Uint64IDSetter); ok { if err = setter.SetID(to.Uint64(id)); err != nil { return nil, err } return nil, nil } // No interface matched, falling back to old behaviour. return to.Int64(id), nil } // More than one key, no interface matched, let's return a map. return keyMap, nil }