func (b *Backend) AlterField(db *sql.DB, m driver.Model, table *sql.Table, oldField *sql.Field, newField *sql.Field) error { fsql, cons, err := newField.SQL(db, m, table) if err != nil { return err } tableName := db.QuoteIdentifier(m.Table()) if _, err = db.Exec(fmt.Sprintf("ALTER TABLE %s CHANGE COLUMN %s %s", tableName, db.QuoteIdentifier(oldField.Name), fsql)); err != nil { return err } for _, c := range cons { if _, err = db.Exec(fmt.Sprintf("ALTER TABLE %s ADD CONSTRAINT %s", tableName, c)); err != nil { return err } } return err }
func (b *Backend) AddFields(db *sql.DB, m driver.Model, prevTable *sql.Table, newTable *sql.Table, fields []*sql.Field) error { rewrite := false for _, v := range fields { if !b.canAddField(v) { rewrite = true break } } if rewrite { name := db.QuoteIdentifier(m.Table()) tmpName := fmt.Sprintf("%s_%s", m.Table(), stringutil.Random(8)) quotedTmpName := db.QuoteIdentifier(tmpName) createSql, err := newTable.SQL(db, b, m, tmpName) if err != nil { return err } if _, err := db.Exec(createSql); err != nil { return err } fieldNames := generic.Map(prevTable.Fields, func(f *sql.Field) string { return f.Name }).([]string) // The previous table might have fields that we're not part // of the new table. fieldSet := make(map[string]bool) for _, v := range newTable.Fields { fieldSet[v.Name] = true } fieldNames = generic.Filter(fieldNames, func(n string) bool { return fieldSet[n] }).([]string) sqlFields := strings.Join(generic.Map(fieldNames, db.QuoteIdentifier).([]string), ", ") copySql := fmt.Sprintf("INSERT INTO %s (%s) SELECT %s FROM %s", quotedTmpName, sqlFields, sqlFields, name) if _, err := db.Exec(copySql); err != nil { return err } if _, err := db.Exec(fmt.Sprintf("DROP TABLE %s", name)); err != nil { return err } if _, err := db.Exec(fmt.Sprintf("ALTER TABLE %s RENAME TO %s", quotedTmpName, name)); err != nil { return err } return nil } return b.SqlBackend.AddFields(db, m, prevTable, newTable, fields) }
func (b *Backend) DefineField(db *sql.DB, m driver.Model, table *sql.Table, field *sql.Field) (string, []string, error) { def, cons, err := b.SqlBackend.DefineField(db, m, table, field) if err != nil { return "", nil, err } if ref := field.Constraint(sql.ConstraintForeignKey); ref != nil { if pos := strings.Index(def, " REFERENCES"); pos >= 0 { def = def[:pos] } refTable := ref.References.Table() refField := ref.References.Field() fkName := db.QuoteIdentifier(fmt.Sprintf("%s_%s_%s_%s", m.Table(), field.Name, refTable, refField)) cons = append(cons, fmt.Sprintf("FOREIGN KEY %s(%s) REFERENCES %s(%s)", fkName, db.QuoteIdentifier(field.Name), db.QuoteIdentifier(refTable), db.QuoteIdentifier(refField))) } return strings.Replace(def, "AUTOINCREMENT", "AUTO_INCREMENT", -1), cons, nil }