Ihar Hrachyshka be1dd6730a Make sure we don't throw away exception on SQL script failure
If SQL script failed, we don't currently log the failure anywhere, so
users have hard time debugging an issue, if anything arises.

Let's log the failure before proceeding with rollback.

Change-Id: Ic92b1403c00bb238a68265a15150a4be6f6b2346
2014-08-23 21:34:13 +02:00

51 lines
1.7 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import logging
import shutil
from migrate.versioning.script import base
from migrate.versioning.template import Template
log = logging.getLogger(__name__)
class SqlScript(base.BaseScript):
"""A file containing plain SQL statements."""
@classmethod
def create(cls, path, **opts):
"""Create an empty migration script at specified path
:returns: :class:`SqlScript instance <migrate.versioning.script.sql.SqlScript>`"""
cls.require_notfound(path)
src = Template(opts.pop('templates_path', None)).get_sql_script(theme=opts.pop('templates_theme', None))
shutil.copy(src, path)
return cls(path)
# TODO: why is step parameter even here?
def run(self, engine, step=None, executemany=True):
"""Runs SQL script through raw dbapi execute call"""
text = self.source()
# Don't rely on SA's autocommit here
# (SA uses .startswith to check if a commit is needed. What if script
# starts with a comment?)
conn = engine.connect()
try:
trans = conn.begin()
try:
# HACK: SQLite doesn't allow multiple statements through
# its execute() method, but it provides executescript() instead
dbapi = conn.engine.raw_connection()
if executemany and getattr(dbapi, 'executescript', None):
dbapi.executescript(text)
else:
conn.execute(text)
trans.commit()
except Exception as e:
log.error("SQL script %s failed: %s", self.path, e)
trans.rollback()
raise
finally:
conn.close()