Skip to content

Commit 207ec35

Browse files
committed
Fix has_table() to exclude other sessions' local temp tables
Fixes: sqlalchemy#6910 Change-Id: I9986566e1195d42ad7e9a01f0f84ef2074576257
1 parent 5219a0e commit 207ec35

2 files changed

Lines changed: 26 additions & 3 deletions

File tree

  • doc/build/changelog/unreleased_14
  • lib/sqlalchemy/dialects/mssql
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.. change::
2+
:tags: bug, mssql, reflection
3+
:tickets: 6910
4+
5+
Fixed an issue where :meth:`_reflection.has_table` returned
6+
``True`` for local temporary tables that actually belonged to a
7+
different SQL Server session (connection). An extra check is now
8+
performed to ensure that the temp table detected is in fact owned
9+
by the current session.

lib/sqlalchemy/dialects/mssql/base.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,7 @@ class MyTable(Base):
758758
from ... import schema as sa_schema
759759
from ... import Sequence
760760
from ... import sql
761+
from ... import text
761762
from ... import types as sqltypes
762763
from ... import util
763764
from ...engine import cursor as _cursor
@@ -2823,8 +2824,16 @@ def has_table(self, connection, tablename, dbname, owner, schema):
28232824
)
28242825
)
28252826

2826-
result = connection.execute(s.limit(1))
2827-
return result.scalar() is not None
2827+
table_name = connection.execute(s.limit(1)).scalar()
2828+
if table_name:
2829+
# #6910: verify it's not a temp table from another session
2830+
obj_id = connection.execute(
2831+
text("SELECT object_id(:table_name)"),
2832+
{"table_name": "tempdb.dbo.[{}]".format(table_name)},
2833+
).scalar()
2834+
return bool(obj_id)
2835+
else:
2836+
return False
28282837
else:
28292838
tables = ischema.tables
28302839

@@ -3009,7 +3018,12 @@ def get_view_definition(
30093018
return view_def
30103019

30113020
def _temp_table_name_like_pattern(self, tablename):
3012-
return tablename + (("___%") if not tablename.startswith("##") else "")
3021+
# LIKE uses '%' to match zero or more characters and '_' to match any
3022+
# single character. We want to match literal underscores, so T-SQL
3023+
# requires that we enclose them in square brackets.
3024+
return tablename + (
3025+
("[_][_][_]%") if not tablename.startswith("##") else ""
3026+
)
30133027

30143028
def _get_internal_temp_table_name(self, connection, tablename):
30153029
# it's likely that schema is always "dbo", but since we can

0 commit comments

Comments
 (0)