func (b *Backend) Inspect(db *sql.DB, m driver.Model) (*sql.Table, error) { var database string if err := db.QueryRow("SELECT DATABASE() FROM DUAL").Scan(&database); err != nil { return nil, err } return b.SqlBackend.Inspect(db, m, database) }
func (b *Backend) HasIndex(db *sql.DB, m driver.Model, idx *index.Index, name string) (bool, error) { var exists int err := db.QueryRow("SELECT 1 FROM pg_class WHERE relname = $1 AND relkind = 'i'", name).Scan(&exists) if err == sql.ErrNoRows { err = nil } return exists != 0, err }
func (b *Backend) HasIndex(db *sql.DB, m driver.Model, idx *index.Index, name string) (bool, error) { rows, err := db.Query("SHOW INDEX FROM ? WHERE Key_name = ?", m.Table(), name) if err != nil { return false, err } has := rows.Next() rows.Close() return has, nil }
func (b *Backend) HasIndex(db *sql.DB, m driver.Model, idx *index.Index, name string) (bool, error) { rows, err := db.Query(fmt.Sprintf("PRAGMA index_info(%s)", name)) if err != nil { return false, err } has := rows.Next() rows.Close() return has, nil }
func (b *Backend) Insert(db *sql.DB, m driver.Model, query string, args ...interface{}) (driver.Result, error) { fields := m.Fields() if fields.AutoincrementPk { q := query + " RETURNING " + fields.MNames[fields.PrimaryKey] var id int64 err := db.QueryRow(q, args...).Scan(&id) // We need to perform a "real" insert to find the real error, so // just let the code fall to the Exec at the end of the function // if there's an error. if err == nil { return insertResult(id), nil } } return db.Exec(query, args...) }
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) 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 }
func (b *Backend) Inspect(db *sql.DB, m driver.Model) (*sql.Table, error) { name := db.QuoteString(m.Table()) rows, err := db.Query(fmt.Sprintf("PRAGMA table_info(%s)", name)) if err != nil { return nil, err } defer rows.Close() fieldsByName := make(map[string]*sql.Field) var fields []*sql.Field for rows.Next() { var cid int var f sql.Field var notnull int var def *string var pk int if err := rows.Scan(&cid, &f.Name, &f.Type, ¬null, &def, &pk); err != nil { return nil, err } f.Type = strings.ToUpper(f.Type) if notnull != 0 { f.AddConstraint(sql.ConstraintNotNull) } if def != nil { f.Default = *def } if pk != 0 { f.AddConstraint(sql.ConstraintPrimaryKey) } fields = append(fields, &f) fieldsByName[f.Name] = &f } if err := rows.Err(); err != nil { return nil, err } rows, err = db.Query(fmt.Sprintf("PRAGMA foreign_key_list(%s)", name)) if err != nil { return nil, err } defer rows.Close() for rows.Next() { var id, seq int var table, from, to, onUpdate, onDelete, match string if err := rows.Scan(&id, &seq, &table, &from, &to, &onUpdate, &onDelete, &match); err != nil { return nil, err } field := fieldsByName[from] field.Constraints = append(field.Constraints, &sql.Constraint{Type: sql.ConstraintForeignKey, References: sql.MakeReference(table, to)}) } if err := rows.Err(); err != nil { return nil, err } if len(fields) > 0 { return &sql.Table{Fields: fields}, nil } return nil, nil }
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) }