(
self,
connection: Connection,
table_name: str,
schema: Optional[str] = None,
**kw: Any,
)
| 3041 | |
| 3042 | @reflection.cache |
| 3043 | def has_table( |
| 3044 | self, |
| 3045 | connection: Connection, |
| 3046 | table_name: str, |
| 3047 | schema: Optional[str] = None, |
| 3048 | **kw: Any, |
| 3049 | ) -> bool: |
| 3050 | self._ensure_has_table_connection(connection) |
| 3051 | |
| 3052 | if schema is None: |
| 3053 | schema = self.default_schema_name |
| 3054 | |
| 3055 | assert schema is not None |
| 3056 | |
| 3057 | full_name = ".".join( |
| 3058 | self.identifier_preparer._quote_free_identifiers( |
| 3059 | schema, table_name |
| 3060 | ) |
| 3061 | ) |
| 3062 | |
| 3063 | # DESCRIBE *must* be used because there is no information schema |
| 3064 | # table that returns information on temp tables that is consistently |
| 3065 | # available on MariaDB / MySQL / engine-agnostic etc. |
| 3066 | # therefore we have no choice but to use DESCRIBE and an error catch |
| 3067 | # to detect "False". See issue #9058 |
| 3068 | |
| 3069 | try: |
| 3070 | with connection.exec_driver_sql( |
| 3071 | f"DESCRIBE {full_name}", |
| 3072 | execution_options={"skip_user_error_events": True}, |
| 3073 | ) as rs: |
| 3074 | return rs.fetchone() is not None |
| 3075 | except exc.DBAPIError as e: |
| 3076 | # https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html # noqa: E501 |
| 3077 | # there are a lot of codes that *may* pop up here at some point |
| 3078 | # but we continue to be fairly conservative. We include: |
| 3079 | # 1146: Table '%s.%s' doesn't exist - what every MySQL has emitted |
| 3080 | # for decades |
| 3081 | # |
| 3082 | # mysql 8 suddenly started emitting: |
| 3083 | # 1049: Unknown database '%s' - for nonexistent schema |
| 3084 | # |
| 3085 | # also added: |
| 3086 | # 1051: Unknown table '%s' - not known to emit |
| 3087 | # |
| 3088 | # there's more "doesn't exist" kinds of messages but they are |
| 3089 | # less clear if mysql 8 would suddenly start using one of those |
| 3090 | if self._extract_error_code(e.orig) in (1146, 1049, 1051): # type: ignore # noqa: E501 |
| 3091 | return False |
| 3092 | raise |
| 3093 | |
| 3094 | @reflection.cache |
| 3095 | def has_sequence( |
nothing calls this directly
no test coverage detected