provision.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. from sqlalchemy import inspect
  2. from sqlalchemy import Integer
  3. from ... import create_engine
  4. from ... import exc
  5. from ...schema import Column
  6. from ...schema import DropConstraint
  7. from ...schema import ForeignKeyConstraint
  8. from ...schema import MetaData
  9. from ...schema import Table
  10. from ...testing.provision import create_db
  11. from ...testing.provision import drop_all_schema_objects_pre_tables
  12. from ...testing.provision import drop_db
  13. from ...testing.provision import get_temp_table_name
  14. from ...testing.provision import log
  15. from ...testing.provision import run_reap_dbs
  16. from ...testing.provision import temp_table_keyword_args
  17. @create_db.for_db("mssql")
  18. def _mssql_create_db(cfg, eng, ident):
  19. with eng.connect().execution_options(isolation_level="AUTOCOMMIT") as conn:
  20. conn.exec_driver_sql("create database %s" % ident)
  21. conn.exec_driver_sql(
  22. "ALTER DATABASE %s SET ALLOW_SNAPSHOT_ISOLATION ON" % ident
  23. )
  24. conn.exec_driver_sql(
  25. "ALTER DATABASE %s SET READ_COMMITTED_SNAPSHOT ON" % ident
  26. )
  27. conn.exec_driver_sql("use %s" % ident)
  28. conn.exec_driver_sql("create schema test_schema")
  29. conn.exec_driver_sql("create schema test_schema_2")
  30. @drop_db.for_db("mssql")
  31. def _mssql_drop_db(cfg, eng, ident):
  32. with eng.connect().execution_options(isolation_level="AUTOCOMMIT") as conn:
  33. _mssql_drop_ignore(conn, ident)
  34. def _mssql_drop_ignore(conn, ident):
  35. try:
  36. # typically when this happens, we can't KILL the session anyway,
  37. # so let the cleanup process drop the DBs
  38. # for row in conn.exec_driver_sql(
  39. # "select session_id from sys.dm_exec_sessions "
  40. # "where database_id=db_id('%s')" % ident):
  41. # log.info("killing SQL server session %s", row['session_id'])
  42. # conn.exec_driver_sql("kill %s" % row['session_id'])
  43. conn.exec_driver_sql("drop database %s" % ident)
  44. log.info("Reaped db: %s", ident)
  45. return True
  46. except exc.DatabaseError as err:
  47. log.warning("couldn't drop db: %s", err)
  48. return False
  49. @run_reap_dbs.for_db("mssql")
  50. def _reap_mssql_dbs(url, idents):
  51. log.info("db reaper connecting to %r", url)
  52. eng = create_engine(url)
  53. with eng.connect().execution_options(isolation_level="AUTOCOMMIT") as conn:
  54. log.info("identifiers in file: %s", ", ".join(idents))
  55. to_reap = conn.exec_driver_sql(
  56. "select d.name from sys.databases as d where name "
  57. "like 'TEST_%' and not exists (select session_id "
  58. "from sys.dm_exec_sessions "
  59. "where database_id=d.database_id)"
  60. )
  61. all_names = {dbname.lower() for (dbname,) in to_reap}
  62. to_drop = set()
  63. for name in all_names:
  64. if name in idents:
  65. to_drop.add(name)
  66. dropped = total = 0
  67. for total, dbname in enumerate(to_drop, 1):
  68. if _mssql_drop_ignore(conn, dbname):
  69. dropped += 1
  70. log.info(
  71. "Dropped %d out of %d stale databases detected", dropped, total
  72. )
  73. @temp_table_keyword_args.for_db("mssql")
  74. def _mssql_temp_table_keyword_args(cfg, eng):
  75. return {}
  76. @get_temp_table_name.for_db("mssql")
  77. def _mssql_get_temp_table_name(cfg, eng, base_name):
  78. return "##" + base_name
  79. @drop_all_schema_objects_pre_tables.for_db("mssql")
  80. def drop_all_schema_objects_pre_tables(cfg, eng):
  81. with eng.connect().execution_options(isolation_level="AUTOCOMMIT") as conn:
  82. inspector = inspect(conn)
  83. for schema in (None, "dbo", cfg.test_schema, cfg.test_schema_2):
  84. for tname in inspector.get_table_names(schema=schema):
  85. tb = Table(
  86. tname,
  87. MetaData(),
  88. Column("x", Integer),
  89. Column("y", Integer),
  90. schema=schema,
  91. )
  92. for fk in inspect(conn).get_foreign_keys(tname, schema=schema):
  93. conn.execute(
  94. DropConstraint(
  95. ForeignKeyConstraint(
  96. [tb.c.x], [tb.c.y], name=fk["name"]
  97. )
  98. )
  99. )