Example #1
0
class Migranto:

    def __init__(self, options):
        self.path = options.path
        self.dbstring = options.database
        self.name = options.name
        self.toStep = options.migration if options.migration is not None else 'max'
        self.nowStep = None
        self.topStep = 0
        self.wasStep = None
        self.verbose = options.verbose
        self.migrations = {}
        self.storage = options.storage
        self.fake = options.fake
        self.home_path = os.path.join(os.path.realpath(os.path.dirname(__file__)), '..')

        if options.out:
            self.out = sys.stdout
        else:
            self.out = False

    def dbConnect(self):
        self.db = Db(self.dbstring, self.out)
        self.SQL = getattr(SQL, self.db.scheme)

    def dbClose(self):
        self.db.close()

    def getLastMigration(self):
        self.nowStep = self.db.fetchOneResult(self.SQL['selectLatestMigration'].format(tablename = self.storage) , (self.name,))

        return self.nowStep

    def createNewMigration(self, name):
        try:
            self.db.begin()
            self.db.execute(self.SQL['insertMigration'].format(tablename = self.storage), (name,))
            self.db.commit()
        except Exception:
            self.db.rollback()
            self.db.execute(self.SQL['createTable'].format(tablename = self.storage))
            self.db.execute(self.SQL['insertMigration'].format(tablename = self.storage), (name,))
            self.db.commit()

    def loadMigrations(self):
        migration_files = getFileListByMask(self.path, ['*.sql'])

        r = re.compile('.*(\d+)_.*?(_rollback)?\.sql$', re.IGNORECASE)

        if migration_files:
            for migration_file in migration_files:
                m = r.findall(migration_file)[0]

                if m:
                    m_step = int(m[0])

                    if m_step in self.migrations:
                        migration = self.migrations[m_step]
                    else:
                        self.migrations[m_step] = migration = {}

                    if m[1]:
                        if "down" not in migration:
                            migration["down"] = migration_file
                        else:
                            raise APIError("Migration duplicates at %d step", m_step)
                    else:
                        if "up" not in migration:
                            migration["up"] = migration_file
                        else:
                            raise APIError("Migration duplicates at %d step", m_step)

                    if m_step > self.topStep:
                        self.topStep = m_step
                else:
                    continue
        else:
            raise APIError('No migration files found')

        if self.toStep == 'max':
            self.toStep = self.topStep


    def applyMigrations(self):
        if self.toStep > self.topStep:
            raise APIError('Top migration is %d' % self.topStep)

        # db is up to date
        if self.toStep == self.nowStep:
            raise APIError("Database for %s is up to date. No migration applied" % self.name )

        # down
        if self.toStep < self.nowStep:
            for i in range(self.nowStep, self.toStep, -1):
                self.applyMigration(self.migrations[i], 'down', i)

            return  self.toStep

        # up
        elif self.toStep > self.nowStep:
            # no migrations applied yet
            if not self.nowStep:
                self.nowStep = 0

            for i in range(self.nowStep + 1, self.toStep + 1):
                self.applyMigration(self.migrations[i], 'up', i)

            return  self.toStep

    def applyMigration(self, migration, flow, number):
        if flow not in migration:
            migration[flow] = None

        if self.out:
            print "--", migration[flow] if migration[flow] else "Empty %s migration" % flow
        else:
            print "%s %d: %s" % (self.name, number, migration[flow] if migration[flow] else "Empty %s migration" % flow),

        try:
            self.db.begin()
            if not self.fake:
                self.db.executeFile(migration[flow])
            self.db.execute(self.SQL['updateMigration'].format(tablename = self.storage), ( number - 1 if flow == 'down' else number, self.name))
            self.db.commit()
            if not self.out:
                print " Done!"

        except Exception, exc:
            try:
                self.db.rollback()
            except Exception, rollback_exc:
                raise APIError('Error: ' + str(exc) + 'Rollback error: ' + str(rollback_exc))
            raise APIError('Error: ' + str(exc))
Example #2
0
 def dbConnect(self):
     self.db = Db(self.dbstring, self.out)
     self.SQL = getattr(SQL, self.db.scheme)