aminghadersohi commented on code in PR #44091:
URL: https://github.com/apache/superset/pull/44091#discussion_r4028871309
##########
tests/unit_tests/versioning/test_db_errors.py:
##########
@@ -107,3 +111,192 @@ def
test_connection_drop_with_no_code_is_not_missing_table() -> None:
_FakeDriverError("server closed the connection unexpectedly"),
)
assert is_missing_table_error(error) is False
+
+
+# ---------------------------------------------------------------------------
+# is_lock_contention_error (sc-120050)
+# ---------------------------------------------------------------------------
+
+
+def _op_error(orig: object) -> OperationalError:
+ err: OperationalError = OperationalError("stmt", None, Exception("boom"))
+ err.orig = orig
+ return err
+
+
+class _FakeLockDriverError(Exception): # noqa: N818 — a driver error, not ours
+ """A stand-in for a DBAPI driver error.
+
+ A real driver error IS an exception carrying its own diagnostic, so
+ the fake is one too: the classifier reads ``args`` / ``pgcode`` /
+ ``sqlstate`` and, for code-less drivers, ``str()`` of THIS object —
+ never of the SQLAlchemy wrapper around it.
+ """
+
+ def __init__(
+ self,
+ args: tuple[object, ...] = (),
+ pgcode: str | None = None,
+ sqlstate: str | None = None,
+ message: str = "",
+ ) -> None:
+ super().__init__(*args)
+ self.args: tuple[object, ...] = args
+ self._message: str = message
+ if pgcode is not None:
+ self.pgcode: str = pgcode
+ if sqlstate is not None:
+ self.sqlstate: str = sqlstate
+
+ def __str__(self) -> str:
+ return self._message or super().__str__()
+
+
+#: Statement prefix for the contamination fixtures; the lock phrase is
+#: appended as a trailing SQL comment.
+_CONTAMINATED_SQL: str = (
+ "INSERT INTO slices (slice_name, description) "
+ "VALUES (%(slice_name)s, %(description)s) -- "
+)
+
+
+def _contaminated_statement(phrase: str) -> tuple[str, dict[str, str]]:
+ """SQL + bound parameters that merely CONTAIN a contention phrase.
+
+ The realistic shape: a user naming a chart "deadlock analysis", or a
+ column literally called ``lock_wait_timeout``. ``str()`` of a
+ SQLAlchemy wrapper renders both, which is why the classifier must
+ read the driver diagnostic instead.
+ """
+ # The phrase rides BOTH halves a wrapper renders: a trailing SQL
+ # comment (stands in for a table or column whose name contains it)
+ # and a bound parameter (a user-supplied chart name). Inert fixture
+ # text — nothing here is ever executed.
+ statement: str = _CONTAMINATED_SQL + phrase
+ return statement, {"slice_name": f"{phrase} analysis", "description":
phrase}
+
+
[email protected](
+ "orig",
+ [
+ _FakeLockDriverError(args=(1213, "Deadlock found when trying to get
lock")),
+ _FakeLockDriverError(args=(1205, "Lock wait timeout exceeded")),
Review Comment:
These fakes set `args` XOR `sqlstate`; real PyMySQL (dist 1.2.0) sets both —
1213 carries `40001`, 1205 carries `HY000`. So nothing pins
errno-before-sqlstate: swapping that order keeps all 52 green while real 1205
flips to False. 1213 survives the swap by coincidence, so the case has to be
1205.
```suggestion
_FakeLockDriverError(
args=(1213, "Deadlock found when trying to get lock"),
sqlstate="40001"
),
_FakeLockDriverError(
args=(1205, "Lock wait timeout exceeded"), sqlstate="HY000"
),
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]