Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1#!/usr/bin/env python 

2# cardinal_pythonlib/sqlalchemy/sqlserver.py 

3 

4""" 

5=============================================================================== 

6 

7 Original code copyright (C) 2009-2021 Rudolf Cardinal (rudolf@pobox.com). 

8 

9 This file is part of cardinal_pythonlib. 

10 

11 Licensed under the Apache License, Version 2.0 (the "License"); 

12 you may not use this file except in compliance with the License. 

13 You may obtain a copy of the License at 

14 

15 https://www.apache.org/licenses/LICENSE-2.0 

16 

17 Unless required by applicable law or agreed to in writing, software 

18 distributed under the License is distributed on an "AS IS" BASIS, 

19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

20 See the License for the specific language governing permissions and 

21 limitations under the License. 

22 

23=============================================================================== 

24 

25**SQLAlchemy functions specific to Microsoft SQL Server.** 

26 

27""" 

28 

29from contextlib import contextmanager 

30 

31from sqlalchemy.orm import Session as SqlASession 

32 

33from cardinal_pythonlib.sqlalchemy.dialect import quote_identifier 

34from cardinal_pythonlib.sqlalchemy.engine_func import is_sqlserver 

35from cardinal_pythonlib.sqlalchemy.session import get_engine_from_session 

36 

37 

38# ============================================================================= 

39# Workarounds for SQL Server "DELETE takes forever" bug 

40# ============================================================================= 

41 

42@contextmanager 

43def if_sqlserver_disable_constraints(session: SqlASession, 

44 tablename: str) -> None: 

45 """ 

46 If we're running under SQL Server, disable constraint checking for the 

47 specified table while the resource is held. 

48 

49 Args: 

50 session: SQLAlchemy :class:`Session` 

51 tablename: table name 

52 

53 See 

54 https://stackoverflow.com/questions/123558/sql-server-2005-t-sql-to-temporarily-disable-a-trigger 

55 """ # noqa 

56 engine = get_engine_from_session(session) 

57 if is_sqlserver(engine): 

58 quoted_tablename = quote_identifier(tablename, engine) 

59 session.execute( 

60 f"ALTER TABLE {quoted_tablename} NOCHECK CONSTRAINT all") 

61 yield 

62 session.execute( 

63 f"ALTER TABLE {quoted_tablename} WITH CHECK CHECK CONSTRAINT all") 

64 else: 

65 yield 

66 

67 

68@contextmanager 

69def if_sqlserver_disable_triggers(session: SqlASession, 

70 tablename: str) -> None: 

71 """ 

72 If we're running under SQL Server, disable triggers for the specified table 

73 while the resource is held. 

74 

75 Args: 

76 session: SQLAlchemy :class:`Session` 

77 tablename: table name 

78 

79 See 

80 https://stackoverflow.com/questions/123558/sql-server-2005-t-sql-to-temporarily-disable-a-trigger 

81 """ # noqa 

82 engine = get_engine_from_session(session) 

83 if is_sqlserver(engine): 

84 quoted_tablename = quote_identifier(tablename, engine) 

85 session.execute( 

86 f"ALTER TABLE {quoted_tablename} DISABLE TRIGGER all") 

87 yield 

88 session.execute( 

89 f"ALTER TABLE {quoted_tablename} ENABLE TRIGGER all") 

90 else: 

91 yield 

92 

93 

94@contextmanager 

95def if_sqlserver_disable_constraints_triggers(session: SqlASession, 

96 tablename: str) -> None: 

97 """ 

98 If we're running under SQL Server, disable triggers AND constraints for the 

99 specified table while the resource is held. 

100 

101 Args: 

102 session: SQLAlchemy :class:`Session` 

103 tablename: table name 

104 """ 

105 with if_sqlserver_disable_constraints(session, tablename): 

106 with if_sqlserver_disable_triggers(session, tablename): 

107 yield