diff --git a/dlt/destinations/impl/sqlalchemy/db_api_client.py b/dlt/destinations/impl/sqlalchemy/db_api_client.py index 27c4f2f1f9..9c83a7424f 100644 --- a/dlt/destinations/impl/sqlalchemy/db_api_client.py +++ b/dlt/destinations/impl/sqlalchemy/db_api_client.py @@ -435,17 +435,36 @@ def _make_database_exception(e: Exception) -> Exception: return DatabaseUndefinedRelation(e) msg = str(e).lower() if isinstance(e, (sa.exc.ProgrammingError, sa.exc.OperationalError)): - if "exist" in msg: # TODO: Hack - return DatabaseUndefinedRelation(e) - elif "unknown table" in msg: - return DatabaseUndefinedRelation(e) - elif "unknown database" in msg: - return DatabaseUndefinedRelation(e) - elif "no such table" in msg: # sqlite # TODO: Hack - return DatabaseUndefinedRelation(e) - elif "no such database" in msg: # sqlite # TODO: Hack - return DatabaseUndefinedRelation(e) - elif "syntax" in msg: + patterns = [ + # MySQL / MariaDB + r"unknown database", # Missing schema + r"doesn't exist", # Missing table + r"unknown table", # Missing table + # SQLite + r"no such table", # Missing table + r"no such database", # Missing table + # PostgreSQL / Trino / Vertica + r"does not exist", # Missing schema, relation + # r"does not exist", # Missing table + # MSSQL + r"invalid object name", # Missing schema or table + # Oracle + r"ora-00942: table or view does not exist", # Missing schema or table + # SAP HANA + r"invalid schema name", # Missing schema + r"invalid table name", # Missing table + # DB2 + r"is an undefined name", # SQL0204N... Missing schema or table + # Apache Hive + r"table not found", # Missing table + r"database does not exist", + ] + # entity not found + for pat_ in patterns: + if pat_ in msg: + return DatabaseUndefinedRelation(e) + + if "syntax" in msg: return DatabaseTransientException(e) elif isinstance(e, (sa.exc.OperationalError, sa.exc.IntegrityError)): return DatabaseTerminalException(e) diff --git a/tests/load/filesystem/test_filesystem_common.py b/tests/load/filesystem/test_filesystem_common.py index afcd9105a8..14c910a222 100644 --- a/tests/load/filesystem/test_filesystem_common.py +++ b/tests/load/filesystem/test_filesystem_common.py @@ -157,6 +157,20 @@ def test_glob_files(with_gdrive_buckets_env: str, load_content: bool, glob_filte assert_sample_files(all_file_items, filesystem, config, load_content, glob_filter) +@pytest.mark.parametrize("load_content", (True, False)) +def test_glob_single_file(with_gdrive_buckets_env: str, load_content: bool) -> None: + bucket_url = os.environ["DESTINATION__FILESYSTEM__BUCKET_URL"] + bucket_url, config, filesystem = glob_test_setup( + bucket_url, "standard_source/samples/met_csv/A803" + ) + # use glob to get data + all_file_items = list(glob_files(filesystem, bucket_url, "A803_20230919.csv")) + assert len(all_file_items) == 1 + assert ( + all_file_items[0]["relative_path"] == all_file_items[0]["file_name"] == "A803_20230919.csv" + ) + + def test_glob_overlapping_path_files(with_gdrive_buckets_env: str) -> None: bucket_url = os.environ["DESTINATION__FILESYSTEM__BUCKET_URL"] # "standard_source/sample" overlaps with a real existing "standard_source/samples". walk operation on azure