lxd/db/query/objects.go
func UpsertObject(tx *sql.Tx, table string, columns []string, values []interface{}) (int64, error) {
	n := len(columns)
	if n == 0 {
		return -1, fmt.Errorf("columns length is zero")
	}
	if n != len(values) {
		return -1, fmt.Errorf("columns length does not match values length")
	}

	stmt := fmt.Sprintf(
		"INSERT OR REPLACE INTO %s (%s) VALUES %s",
		table, strings.Join(columns, ", "), Params(n))
	result, err := tx.Exec(stmt, values...)
	if err != nil {
		return -1, err
	}
	id, err := result.LastInsertId()
	if err != nil {
		return -1, err
	}
	return id, nil
}
func UpsertObject(tx *sql.Tx, table string, columns []string, values []interface{}) (int64, error) {
	n := len(columns)
	if n == 0 {
		return -1, fmt.Errorf("columns length is zero")
	}
	if n != len(values) {
		return -1, fmt.Errorf("columns length does not match values length")
	}

	stmt := fmt.Sprintf(
		"INSERT OR REPLACE INTO %s (%s) VALUES %s",
		table, strings.Join(columns, ", "), Params(n))
	result, err := tx.Exec(stmt, values...)
	if err != nil {
		return -1, err
	}
	id, err := result.LastInsertId()
	if err != nil {
		return -1, err
	}
	return id, nil
}
// UpsertObject inserts or replaces a new row with the given column values, to
// the given table using columns order. For example:
//
// UpsertObject(tx, "cars", []string{"id", "brand"}, []interface{}{1, "ferrari"})
//
// The number of elements in 'columns' must match the one in 'values'.