Merge "Unwind circular import issue with api / utils"
This commit is contained in:
commit
b796673f39
@ -38,6 +38,7 @@ from six.moves import range
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import and_
|
||||
from sqlalchemy.exc import NoSuchTableError
|
||||
from sqlalchemy.ext.compiler import compiles
|
||||
from sqlalchemy import MetaData
|
||||
from sqlalchemy import or_
|
||||
from sqlalchemy.orm import aliased
|
||||
@ -50,6 +51,7 @@ from sqlalchemy.schema import Table
|
||||
from sqlalchemy import sql
|
||||
from sqlalchemy.sql.expression import asc
|
||||
from sqlalchemy.sql.expression import desc
|
||||
from sqlalchemy.sql.expression import UpdateBase
|
||||
from sqlalchemy.sql import false
|
||||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.sql import null
|
||||
@ -416,6 +418,23 @@ class InequalityCondition(object):
|
||||
return [field != value for value in self.values]
|
||||
|
||||
|
||||
class DeleteFromSelect(UpdateBase):
|
||||
def __init__(self, table, select, column):
|
||||
self.table = table
|
||||
self.select = select
|
||||
self.column = column
|
||||
|
||||
|
||||
# NOTE(guochbo): some versions of MySQL doesn't yet support subquery with
|
||||
# 'LIMIT & IN/ALL/ANY/SOME' We need work around this with nesting select .
|
||||
@compiles(DeleteFromSelect)
|
||||
def visit_delete_from_select(element, compiler, **kw):
|
||||
return "DELETE FROM %s WHERE %s in (SELECT T1.%s FROM (%s) as T1)" % (
|
||||
compiler.process(element.table, asfrom=True),
|
||||
compiler.process(element.column),
|
||||
element.column.name,
|
||||
compiler.process(element.select))
|
||||
|
||||
###################
|
||||
|
||||
|
||||
@ -6284,10 +6303,6 @@ def _archive_if_instance_deleted(table, shadow_table, instances, conn,
|
||||
Logic is: if I have a column called instance_uuid, and that instance
|
||||
is deleted, then I can be deleted.
|
||||
"""
|
||||
# NOTE(guochbo): There is a circular import, nova.db.sqlalchemy.utils
|
||||
# imports nova.db.sqlalchemy.api.
|
||||
from nova.db.sqlalchemy import utils as db_utils
|
||||
|
||||
query_insert = shadow_table.insert(inline=True).\
|
||||
from_select(
|
||||
[c.name for c in table.c],
|
||||
@ -6302,8 +6317,8 @@ def _archive_if_instance_deleted(table, shadow_table, instances, conn,
|
||||
and_(instances.c.deleted != instances.c.deleted.default.arg,
|
||||
instances.c.uuid == table.c.instance_uuid)).\
|
||||
order_by(table.c.id).limit(max_rows)
|
||||
delete_statement = db_utils.DeleteFromSelect(table, query_delete,
|
||||
table.c.id)
|
||||
delete_statement = DeleteFromSelect(table, query_delete,
|
||||
table.c.id)
|
||||
|
||||
try:
|
||||
with conn.begin():
|
||||
@ -6323,10 +6338,6 @@ def _archive_deleted_rows_for_table(tablename, max_rows):
|
||||
|
||||
:returns: number of rows archived
|
||||
"""
|
||||
# NOTE(guochbo): There is a circular import, nova.db.sqlalchemy.utils
|
||||
# imports nova.db.sqlalchemy.api.
|
||||
from nova.db.sqlalchemy import utils as db_utils
|
||||
|
||||
engine = get_engine()
|
||||
conn = engine.connect()
|
||||
metadata = MetaData()
|
||||
@ -6396,7 +6407,7 @@ def _archive_deleted_rows_for_table(tablename, max_rows):
|
||||
deleted_column != deleted_column.default.arg).\
|
||||
order_by(column).limit(max_rows)
|
||||
|
||||
delete_statement = db_utils.DeleteFromSelect(table, query_delete, column)
|
||||
delete_statement = DeleteFromSelect(table, query_delete, column)
|
||||
try:
|
||||
# Group the insert and delete in a transaction.
|
||||
with conn.begin():
|
||||
|
@ -17,9 +17,7 @@ from oslo_db import exception as db_exc
|
||||
from oslo_db.sqlalchemy import utils as oslodbutils
|
||||
from oslo_log import log as logging
|
||||
from sqlalchemy.exc import OperationalError
|
||||
from sqlalchemy.ext.compiler import compiles
|
||||
from sqlalchemy import MetaData
|
||||
from sqlalchemy.sql.expression import UpdateBase
|
||||
from sqlalchemy import Table
|
||||
from sqlalchemy.types import NullType
|
||||
|
||||
@ -31,24 +29,6 @@ from nova.i18n import _, _LE
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DeleteFromSelect(UpdateBase):
|
||||
def __init__(self, table, select, column):
|
||||
self.table = table
|
||||
self.select = select
|
||||
self.column = column
|
||||
|
||||
|
||||
# NOTE(guochbo): some versions of MySQL doesn't yet support subquery with
|
||||
# 'LIMIT & IN/ALL/ANY/SOME' We need work around this with nesting select .
|
||||
@compiles(DeleteFromSelect)
|
||||
def visit_delete_from_select(element, compiler, **kw):
|
||||
return "DELETE FROM %s WHERE %s in (SELECT T1.%s FROM (%s) as T1)" % (
|
||||
compiler.process(element.table, asfrom=True),
|
||||
compiler.process(element.column),
|
||||
element.column.name,
|
||||
compiler.process(element.select))
|
||||
|
||||
|
||||
def check_shadow_table(migrate_engine, table_name):
|
||||
"""This method checks that table with ``table_name`` and
|
||||
corresponding shadow table have same columns.
|
||||
|
@ -78,8 +78,8 @@ class TestMigrationUtilsSQLite(test_base.DbTestCase):
|
||||
column = test_table.c.id
|
||||
query_delete = sql.select([column],
|
||||
test_table.c.id < 5).order_by(column)
|
||||
delete_statement = utils.DeleteFromSelect(test_table,
|
||||
query_delete, column)
|
||||
delete_statement = db.DeleteFromSelect(test_table,
|
||||
query_delete, column)
|
||||
result_delete = conn.execute(delete_statement)
|
||||
# Verify we delete 4 rows
|
||||
self.assertEqual(result_delete.rowcount, 4)
|
||||
|
Loading…
Reference in New Issue
Block a user