lxd/db/schema/schema.go
func (s *Schema) Ensure(db *sql.DB) (int, error) {
	var current int
	aborted := false
	err := query.Transaction(db, func(tx *sql.Tx) error {
		err := execFromFile(tx, s.path, s.hook)
		if err != nil {
			return errors.Wrapf(err, "failed to execute queries from %s", s.path)
		}

		err = ensureSchemaTableExists(tx)
		if err != nil {
			return err
		}

		current, err = queryCurrentVersion(tx)
		if err != nil {
			return err
		}

		if s.check != nil {
			err := s.check(current, tx)
			if err == ErrGracefulAbort {
				// Abort the update gracefully, committing what
				// we've done so far.
				aborted = true
				return nil
			}
			if err != nil {
				return err
			}
		}

		// When creating the schema from scratch, use the fresh dump if
		// available. Otherwise just apply all relevant updates.
		if current == 0 && s.fresh != "" {
			_, err = tx.Exec(s.fresh)
			if err != nil {
				return fmt.Errorf("cannot apply fresh schema: %v", err)
			}
		} else {
			err = ensureUpdatesAreApplied(tx, current, s.updates, s.hook)
			if err != nil {
				return err
			}
		}

		return nil
	})
	if err != nil {
		return -1, err
	}
	if aborted {
		return current, ErrGracefulAbort
	}
	return current, nil
}
func (s *Schema) Ensure(db *sql.DB) (int, error) {
	var current int
	aborted := false
	err := query.Transaction(db, func(tx *sql.Tx) error {
		err := execFromFile(tx, s.path, s.hook)
		if err != nil {
			return errors.Wrapf(err, "failed to execute queries from %s", s.path)
		}

		err = ensureSchemaTableExists(tx)
		if err != nil {
			return err
		}

		current, err = queryCurrentVersion(tx)
		if err != nil {
			return err
		}

		if s.check != nil {
			err := s.check(current, tx)
			if err == ErrGracefulAbort {
				// Abort the update gracefully, committing what
				// we've done so far.
				aborted = true
				return nil
			}
			if err != nil {
				return err
			}
		}

		// When creating the schema from scratch, use the fresh dump if
		// available. Otherwise just apply all relevant updates.
		if current == 0 && s.fresh != "" {
			_, err = tx.Exec(s.fresh)
			if err != nil {
				return fmt.Errorf("cannot apply fresh schema: %v", err)
			}
		} else {
			err = ensureUpdatesAreApplied(tx, current, s.updates, s.hook)
			if err != nil {
				return err
			}
		}

		return nil
	})
	if err != nil {
		return -1, err
	}
	if aborted {
		return current, ErrGracefulAbort
	}
	return current, nil
}
// Ensure makes sure that the actual schema in the given database matches the
// one defined by our updates.
//
// All updates are applied transactionally. In case any error occurs the
// transaction will be rolled back and the database will remain unchanged.
//
// A update will be applied only if it hasn't been before (currently applied
// updates are tracked in the a 'shema' table, which gets automatically
// created).
//
// If no error occurs, the integer returned by this method is the
// initial version that the schema has been upgraded from.