Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/sqlalchemy/dialects/mssql/mxodbc.py: 56%

45 statements  

« prev     ^ index     » next       coverage.py v7.0.1, created at 2022-12-25 06:11 +0000

1# mssql/mxodbc.py 

2# Copyright (C) 2005-2022 the SQLAlchemy authors and contributors 

3# <see AUTHORS file> 

4# 

5# This module is part of SQLAlchemy and is released under 

6# the MIT License: https://www.opensource.org/licenses/mit-license.php 

7 

8""" 

9.. dialect:: mssql+mxodbc 

10 :name: mxODBC 

11 :dbapi: mxodbc 

12 :connectstring: mssql+mxodbc://<username>:<password>@<dsnname> 

13 :url: https://www.egenix.com/ 

14 

15.. deprecated:: 1.4 The mxODBC DBAPI is deprecated and will be removed 

16 in a future version. Please use one of the supported DBAPIs to 

17 connect to mssql. 

18 

19Execution Modes 

20--------------- 

21 

22mxODBC features two styles of statement execution, using the 

23``cursor.execute()`` and ``cursor.executedirect()`` methods (the second being 

24an extension to the DBAPI specification). The former makes use of a particular 

25API call specific to the SQL Server Native Client ODBC driver known 

26SQLDescribeParam, while the latter does not. 

27 

28mxODBC apparently only makes repeated use of a single prepared statement 

29when SQLDescribeParam is used. The advantage to prepared statement reuse is 

30one of performance. The disadvantage is that SQLDescribeParam has a limited 

31set of scenarios in which bind parameters are understood, including that they 

32cannot be placed within the argument lists of function calls, anywhere outside 

33the FROM, or even within subqueries within the FROM clause - making the usage 

34of bind parameters within SELECT statements impossible for all but the most 

35simplistic statements. 

36 

37For this reason, the mxODBC dialect uses the "native" mode by default only for 

38INSERT, UPDATE, and DELETE statements, and uses the escaped string mode for 

39all other statements. 

40 

41This behavior can be controlled via 

42:meth:`~sqlalchemy.sql.expression.Executable.execution_options` using the 

43``native_odbc_execute`` flag with a value of ``True`` or ``False``, where a 

44value of ``True`` will unconditionally use native bind parameters and a value 

45of ``False`` will unconditionally use string-escaped parameters. 

46 

47""" 

48 

49 

50from .base import _MSDate 

51from .base import _MSDateTime 

52from .base import _MSTime 

53from .base import MSDialect 

54from .base import VARBINARY 

55from .pyodbc import _MSNumeric_pyodbc 

56from .pyodbc import MSExecutionContext_pyodbc 

57from ... import types as sqltypes 

58from ...connectors.mxodbc import MxODBCConnector 

59 

60 

61class _MSNumeric_mxodbc(_MSNumeric_pyodbc): 

62 """Include pyodbc's numeric processor.""" 

63 

64 

65class _MSDate_mxodbc(_MSDate): 

66 def bind_processor(self, dialect): 

67 def process(value): 

68 if value is not None: 

69 return "%s-%s-%s" % (value.year, value.month, value.day) 

70 else: 

71 return None 

72 

73 return process 

74 

75 

76class _MSTime_mxodbc(_MSTime): 

77 def bind_processor(self, dialect): 

78 def process(value): 

79 if value is not None: 

80 return "%s:%s:%s" % (value.hour, value.minute, value.second) 

81 else: 

82 return None 

83 

84 return process 

85 

86 

87class _VARBINARY_mxodbc(VARBINARY): 

88 

89 """ 

90 mxODBC Support for VARBINARY column types. 

91 

92 This handles the special case for null VARBINARY values, 

93 which maps None values to the mx.ODBC.Manager.BinaryNull symbol. 

94 """ 

95 

96 def bind_processor(self, dialect): 

97 if dialect.dbapi is None: 

98 return None 

99 

100 DBAPIBinary = dialect.dbapi.Binary 

101 

102 def process(value): 

103 if value is not None: 

104 return DBAPIBinary(value) 

105 else: 

106 # should pull from mx.ODBC.Manager.BinaryNull 

107 return dialect.dbapi.BinaryNull 

108 

109 return process 

110 

111 

112class MSExecutionContext_mxodbc(MSExecutionContext_pyodbc): 

113 """ 

114 The pyodbc execution context is useful for enabling 

115 SELECT SCOPE_IDENTITY in cases where OUTPUT clause 

116 does not work (tables with insert triggers). 

117 """ 

118 

119 # todo - investigate whether the pyodbc execution context 

120 # is really only being used in cases where OUTPUT 

121 # won't work. 

122 

123 

124class MSDialect_mxodbc(MxODBCConnector, MSDialect): 

125 

126 # this is only needed if "native ODBC" mode is used, 

127 # which is now disabled by default. 

128 # statement_compiler = MSSQLStrictCompiler 

129 supports_statement_cache = True 

130 

131 execution_ctx_cls = MSExecutionContext_mxodbc 

132 

133 # flag used by _MSNumeric_mxodbc 

134 _need_decimal_fix = True 

135 

136 colspecs = { 

137 sqltypes.Numeric: _MSNumeric_mxodbc, 

138 sqltypes.DateTime: _MSDateTime, 

139 sqltypes.Date: _MSDate_mxodbc, 

140 sqltypes.Time: _MSTime_mxodbc, 

141 VARBINARY: _VARBINARY_mxodbc, 

142 sqltypes.LargeBinary: _VARBINARY_mxodbc, 

143 } 

144 

145 def __init__(self, description_encoding=None, **params): 

146 super(MSDialect_mxodbc, self).__init__(**params) 

147 self.description_encoding = description_encoding 

148 

149 

150dialect = MSDialect_mxodbc