diff --git a/docs/backends/_utils.py b/docs/backends/_utils.py index e54de2ce120e..53fad59bf176 100644 --- a/docs/backends/_utils.py +++ b/docs/backends/_utils.py @@ -40,10 +40,7 @@ def find_member_with_docstring(member): if base not in resolved_bases: resolved_bases.append(base) - # Remove `CanCreateSchema` and `CanListSchema` since they are deprecated - # and we don't want to document their existence. - filtered_bases = filter(lambda x: "schema" not in x.name.lower(), resolved_bases) - for base in filtered_bases: + for base in resolved_bases: try: parent_member = get_callable(base, member.name) except KeyError: diff --git a/ibis/backends/__init__.py b/ibis/backends/__init__.py index 8b73d812a34b..f1c06f1a4adb 100644 --- a/ibis/backends/__init__.py +++ b/ibis/backends/__init__.py @@ -741,44 +741,6 @@ def drop_database( """ -# TODO: remove this for 10.0 -class CanListSchema: - @util.deprecated( - instead="Use `list_databases` instead`", as_of="9.0", removed_in="10.0" - ) - def list_schemas( - self, like: str | None = None, database: str | None = None - ) -> list[str]: - return self.list_databases(like=like, catalog=database) - - @property - @util.deprecated( - instead="Use `Backend.current_database` instead.", - as_of="9.0", - removed_in="10.0", - ) - def current_schema(self) -> str: - return self.current_database - - -class CanCreateSchema(CanListSchema): - @util.deprecated( - instead="Use `create_database` instead", as_of="9.0", removed_in="10.0" - ) - def create_schema( - self, name: str, database: str | None = None, force: bool = False - ) -> None: - self.create_database(name=name, catalog=database, force=force) - - @util.deprecated( - instead="Use `drop_database` instead", as_of="9.0", removed_in="10.0" - ) - def drop_schema( - self, name: str, database: str | None = None, force: bool = False - ) -> None: - self.drop_database(name=name, catalog=database, force=force) - - class CacheEntry(NamedTuple): orig_op: ops.Relation cached_op_ref: weakref.ref[ops.Relation] diff --git a/ibis/backends/bigquery/__init__.py b/ibis/backends/bigquery/__init__.py index df1b2f3674d9..d87549394223 100644 --- a/ibis/backends/bigquery/__init__.py +++ b/ibis/backends/bigquery/__init__.py @@ -25,7 +25,7 @@ import ibis.expr.schema as sch import ibis.expr.types as ir from ibis import util -from ibis.backends import CanCreateDatabase, CanCreateSchema +from ibis.backends import CanCreateDatabase from ibis.backends.bigquery.client import ( bigquery_param, parse_project_and_dataset, @@ -155,7 +155,7 @@ def _postprocess_arrow( return table_or_batch.rename_columns(names) -class Backend(SQLBackend, CanCreateDatabase, CanCreateSchema): +class Backend(SQLBackend, CanCreateDatabase): name = "bigquery" compiler = sc.bigquery.compiler supports_python_udfs = False @@ -520,6 +520,10 @@ def disconnect(self) -> None: def _parse_project_and_dataset(self, dataset) -> tuple[str, str]: if isinstance(dataset, sge.Table): + if (sg_cat := dataset.args["catalog"]) is not None: + sg_cat.args["quoted"] = False + if (sg_db := dataset.args["db"]) is not None: + sg_db.args["quoted"] = False dataset = dataset.sql(self.dialect) if not dataset and not self.dataset: raise ValueError("Unable to determine BigQuery dataset.") @@ -582,9 +586,11 @@ def drop_database( self.raw_sql(stmt.sql(self.name)) def table( - self, name: str, database: str | None = None, schema: str | None = None + self, + name: str, + database: str | None = None, ) -> ir.Table: - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) table = sg.parse_one(f"`{name}`", into=sge.Table, read=self.name) # Bigquery, unlike other backends, had existing support for specifying @@ -612,10 +618,7 @@ def table( else: db = table.db - database = ( - sg.table(None, db=db, catalog=catalog, quoted=False).sql(dialect=self.name) - or None - ) + database = sg.table(None, db=db, catalog=catalog, quoted=False) or None project, dataset = self._parse_project_and_dataset(database) @@ -722,7 +725,6 @@ def insert( self, table_name: str, obj: pd.DataFrame | ir.Table | list | dict, - schema: str | None = None, database: str | None = None, overwrite: bool = False, ): @@ -734,15 +736,13 @@ def insert( The name of the table to which data needs will be inserted obj The source data or expression to insert - schema - The name of the schema that the table is located in database Name of the attached database that the table is located in. overwrite If `True` then replace existing contents of table """ - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) catalog, db = self._to_catalog_db_tuple(table_loc) if catalog is None: catalog = self.current_catalog @@ -896,7 +896,6 @@ def list_tables( self, like: str | None = None, database: tuple[str, str] | str | None = None, - schema: str | None = None, ) -> list[str]: """List the tables in the database. @@ -924,10 +923,8 @@ def list_tables( To specify a table in a separate BigQuery dataset, you can pass in the dataset and project as a string `"dataset.project"`, or as a tuple of strings `(dataset, project)`. - schema - [deprecated] The schema (dataset) inside `database` to perform the list against. """ - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) project, dataset = self._parse_project_and_dataset(table_loc) dataset_ref = bq.DatasetReference(project, dataset) @@ -1090,11 +1087,10 @@ def drop_table( self, name: str, *, - schema: str | None = None, database: tuple[str | str] | str | None = None, force: bool = False, ) -> None: - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) catalog, db = self._to_catalog_db_tuple(table_loc) stmt = sge.Drop( kind="TABLE", @@ -1112,11 +1108,10 @@ def create_view( name: str, obj: ir.Table, *, - schema: str | None = None, database: str | None = None, overwrite: bool = False, ) -> ir.Table: - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) catalog, db = self._to_catalog_db_tuple(table_loc) stmt = sge.Create( @@ -1137,11 +1132,10 @@ def drop_view( self, name: str, *, - schema: str | None = None, database: str | None = None, force: bool = False, ) -> None: - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) catalog, db = self._to_catalog_db_tuple(table_loc) stmt = sge.Drop( @@ -1169,32 +1163,6 @@ def _register_udfs(self, expr: ir.Expr) -> None: def _safe_raw_sql(self, *args, **kwargs): yield self.raw_sql(*args, **kwargs) - # TODO: remove when the schema kwarg is removed - def _warn_and_create_table_loc(self, database=None, schema=None): - if schema is not None: - self._warn_schema() - if database is not None and schema is not None: - if isinstance(database, str): - table_loc = f"{database}.{schema}" - elif isinstance(database, tuple): - table_loc = database + schema - elif schema is not None: - table_loc = schema - elif database is not None: - table_loc = database - else: - table_loc = None - - table_loc = self._to_sqlglot_table(table_loc) - - if table_loc is not None: - if (sg_cat := table_loc.args["catalog"]) is not None: - sg_cat.args["quoted"] = False - if (sg_db := table_loc.args["db"]) is not None: - sg_db.args["quoted"] = False - - return table_loc - def compile(expr, params=None, **kwargs): """Compile an expression for BigQuery.""" diff --git a/ibis/backends/bigquery/tests/system/test_client.py b/ibis/backends/bigquery/tests/system/test_client.py index ad837065a949..df378c43e78d 100644 --- a/ibis/backends/bigquery/tests/system/test_client.py +++ b/ibis/backends/bigquery/tests/system/test_client.py @@ -34,6 +34,16 @@ def test_list_tables(con): tables = con.list_tables(like="functional_alltypes") assert set(tables) == {"functional_alltypes", "functional_alltypes_parted"} + pypi_tables = [ + "external", + "native", + ] + + assert con.list_tables() + + assert con.list_tables(database="ibis-gbq.pypi") == pypi_tables + assert con.list_tables(database=("ibis-gbq", "pypi")) == pypi_tables + def test_current_catalog(con): assert con.current_catalog == con.billing_project @@ -386,22 +396,6 @@ def test_create_table_with_options(con): con.drop_table(name) -def test_list_tables_schema_warning_refactor(con): - pypi_tables = [ - "external", - "native", - ] - - assert con.list_tables() - - # Warn but succeed for schema list - with pytest.raises(FutureWarning): - assert con.list_tables(schema="pypi") == pypi_tables - - assert con.list_tables(database="ibis-gbq.pypi") == pypi_tables - assert con.list_tables(database=("ibis-gbq", "pypi")) == pypi_tables - - def test_create_temp_table_from_scratch(project_id, dataset_id): con = ibis.bigquery.connect(project_id=project_id, dataset_id=dataset_id) name = gen_name("bigquery_temp_table") diff --git a/ibis/backends/conftest.py b/ibis/backends/conftest.py index 7b4ef991fee8..c1ca256bc638 100644 --- a/ibis/backends/conftest.py +++ b/ibis/backends/conftest.py @@ -17,7 +17,6 @@ from ibis.backends import ( CanCreateCatalog, CanCreateDatabase, - CanListSchema, _get_backend_names, ) from ibis.conftest import WINDOWS @@ -424,14 +423,6 @@ def con_no_data(backend_no_data): return backend_no_data.connection -@pytest.fixture(scope="session") -def con_list_schema(con): - if isinstance(con, CanListSchema): - return con - else: - pytest.skip(f"{con.name} backend cannot create schemas") - - @pytest.fixture(scope="session") def con_create_catalog(con): if isinstance(con, CanCreateCatalog): diff --git a/ibis/backends/datafusion/__init__.py b/ibis/backends/datafusion/__init__.py index 0570f163e9f9..8ea440b3cdfa 100644 --- a/ibis/backends/datafusion/__init__.py +++ b/ibis/backends/datafusion/__init__.py @@ -22,7 +22,7 @@ import ibis.expr.schema as sch import ibis.expr.types as ir from ibis import util -from ibis.backends import CanCreateCatalog, CanCreateDatabase, CanCreateSchema, NoUrl +from ibis.backends import CanCreateCatalog, CanCreateDatabase, NoUrl from ibis.backends.sql import SQLBackend from ibis.backends.sql.compilers.base import C from ibis.common.dispatch import lazy_singledispatch @@ -69,7 +69,7 @@ def as_nullable(dtype: dt.DataType) -> dt.DataType: return dtype.copy(nullable=True) -class Backend(SQLBackend, CanCreateCatalog, CanCreateDatabase, CanCreateSchema, NoUrl): +class Backend(SQLBackend, CanCreateCatalog, CanCreateDatabase, NoUrl): name = "datafusion" supports_arrays = True compiler = sc.datafusion.compiler @@ -674,8 +674,10 @@ def create_table( return self.table(name, database=database) def truncate_table( - self, name: str, database: str | None = None, schema: str | None = None - ) -> None: + self, + name: str, + database: str | None = None, + ): """Delete all rows from a table. Parameters @@ -684,14 +686,12 @@ def truncate_table( Table name database Database name - schema - Schema name """ # datafusion doesn't support `TRUNCATE TABLE` so we use `DELETE FROM` # # however datafusion as of 34.0.0 doesn't implement DELETE DML yet - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) catalog, db = self._to_catalog_db_tuple(table_loc) ident = sg.table(name, db=db, catalog=catalog).sql(self.dialect) diff --git a/ibis/backends/duckdb/__init__.py b/ibis/backends/duckdb/__init__.py index bb4d4f7aa9fd..0bdaa57a0f66 100644 --- a/ibis/backends/duckdb/__init__.py +++ b/ibis/backends/duckdb/__init__.py @@ -26,7 +26,7 @@ import ibis.expr.schema as sch import ibis.expr.types as ir from ibis import util -from ibis.backends import CanCreateDatabase, CanCreateSchema, UrlFromPath +from ibis.backends import CanCreateDatabase, UrlFromPath from ibis.backends.duckdb.converter import DuckDBPandasData from ibis.backends.sql import SQLBackend from ibis.backends.sql.compilers.base import STAR, AlterTable, C @@ -70,7 +70,7 @@ def __repr__(self): return repr(self.con.sql("from duckdb_settings()")) -class Backend(SQLBackend, CanCreateDatabase, CanCreateSchema, UrlFromPath): +class Backend(SQLBackend, CanCreateDatabase, UrlFromPath): name = "duckdb" compiler = sc.duckdb.compiler @@ -232,17 +232,13 @@ def create_table( return self.table(name, database=(catalog, database)) - def table( - self, name: str, schema: str | None = None, database: str | None = None - ) -> ir.Table: + def table(self, name: str, database: str | None = None) -> ir.Table: """Construct a table expression. Parameters ---------- name Table name - schema - [deprecated] Schema name database Database name @@ -252,7 +248,7 @@ def table( Table expression """ - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) # TODO: set these to better defaults catalog = table_loc.catalog or None @@ -987,7 +983,6 @@ def list_tables( self, like: str | None = None, database: tuple[str, str] | str | None = None, - schema: str | None = None, ) -> list[str]: """List tables and views. @@ -1015,8 +1010,6 @@ def list_tables( To specify a table in a separate catalog, you can pass in the catalog and database as a string `"catalog.database"`, or as a tuple of strings `("catalog", "database")`. - schema - [deprecated] Schema name. If not passed, uses the current schema. Returns ------- @@ -1042,7 +1035,7 @@ def list_tables( ['baz'] """ - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) catalog = table_loc.catalog or self.current_catalog database = table_loc.db or self.current_database diff --git a/ibis/backends/duckdb/tests/test_client.py b/ibis/backends/duckdb/tests/test_client.py index b4c357557f76..f02af4f040b6 100644 --- a/ibis/backends/duckdb/tests/test_client.py +++ b/ibis/backends/duckdb/tests/test_client.py @@ -78,13 +78,12 @@ def test_cross_db(tmpdir): con2.attach(path1, name="test1", read_only=True) - with pytest.warns(FutureWarning): - t1_from_con2 = con2.table("t1", schema="main", database="test1") + t1_from_con2 = con2.table("t1", database="test1.main") assert t1_from_con2.schema() == t2.schema() assert t1_from_con2.execute().equals(t2.execute()) - with pytest.warns(FutureWarning): - foo_t1_from_con2 = con2.table("t1", schema="foo", database="test1") + foo_t1_from_con2 = con2.table("t1", database="test1.foo") + assert foo_t1_from_con2.schema() == t2.schema() assert foo_t1_from_con2.execute().equals(t2.execute()) @@ -282,7 +281,7 @@ def test_invalid_connect(tmp_path): ibis.connect(url) -def test_list_tables_schema_warning_refactor(con): +def test_list_tables(con): assert { "astronauts", "awards_players", @@ -294,9 +293,6 @@ def test_list_tables_schema_warning_refactor(con): icecream_table = ["ice_cream"] - with pytest.warns(FutureWarning): - assert con.list_tables(schema="shops") == icecream_table - assert con.list_tables(database="shops") == icecream_table assert con.list_tables(database=("shops",)) == icecream_table diff --git a/ibis/backends/exasol/__init__.py b/ibis/backends/exasol/__init__.py index ee381b2b363c..b1bdb134bd67 100644 --- a/ibis/backends/exasol/__init__.py +++ b/ibis/backends/exasol/__init__.py @@ -18,7 +18,7 @@ import ibis.expr.schema as sch import ibis.expr.types as ir from ibis import util -from ibis.backends import CanCreateDatabase, CanCreateSchema +from ibis.backends import CanCreateDatabase from ibis.backends.sql import SQLBackend from ibis.backends.sql.compilers.base import STAR, C @@ -36,7 +36,7 @@ _VARCHAR_REGEX = re.compile(r"^((VAR)?CHAR(?:\(\d+\)))?(?:\s+.+)?$") -class Backend(SQLBackend, CanCreateDatabase, CanCreateSchema): +class Backend(SQLBackend, CanCreateDatabase): name = "exasol" compiler = sc.exasol.compiler supports_temporary_tables = False diff --git a/ibis/backends/mssql/__init__.py b/ibis/backends/mssql/__init__.py index 3a215e1ece0b..d424d903179e 100644 --- a/ibis/backends/mssql/__init__.py +++ b/ibis/backends/mssql/__init__.py @@ -22,7 +22,7 @@ import ibis.expr.schema as sch import ibis.expr.types as ir from ibis import util -from ibis.backends import CanCreateCatalog, CanCreateDatabase, CanCreateSchema +from ibis.backends import CanCreateCatalog, CanCreateDatabase from ibis.backends.sql import SQLBackend from ibis.backends.sql.compilers.base import STAR, C @@ -75,7 +75,7 @@ def datetimeoffset_to_datetime(value): # Databases: sys.schemas -class Backend(SQLBackend, CanCreateCatalog, CanCreateDatabase, CanCreateSchema): +class Backend(SQLBackend, CanCreateCatalog, CanCreateDatabase): name = "mssql" compiler = sc.mssql.compiler supports_create_or_replace = False @@ -527,7 +527,6 @@ def list_tables( self, like: str | None = None, database: tuple[str, str] | str | None = None, - schema: str | None = None, ) -> list[str]: """List the tables in the database. @@ -552,10 +551,9 @@ def list_tables( To specify a table in a separate catalog, you can pass in the catalog and database as a string `"catalog.database"`, or as a tuple of strings `("catalog", "database")`. - schema - [deprecated] The schema inside `database` to perform the list against. + """ - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) catalog, db = self._to_catalog_db_tuple(table_loc) sql = ( diff --git a/ibis/backends/mssql/tests/test_client.py b/ibis/backends/mssql/tests/test_client.py index 95b12c2972b7..3a72a75746c1 100644 --- a/ibis/backends/mssql/tests/test_client.py +++ b/ibis/backends/mssql/tests/test_client.py @@ -176,7 +176,7 @@ def test_glorious_length_function_hack(con, string): assert result == len(string) -def test_list_tables_schema_warning_refactor(con): +def test_list_tables(con): assert set(con.list_tables()) >= { "astronauts", "awards_players", @@ -188,12 +188,6 @@ def test_list_tables_schema_warning_refactor(con): restore_tables = ["restorefile", "restorefilegroup", "restorehistory"] - with pytest.warns(FutureWarning): - assert ( - con.list_tables(database="msdb", schema="dbo", like="restore") - == restore_tables - ) - assert con.list_tables(database="msdb.dbo", like="restore") == restore_tables assert con.list_tables(database=("msdb", "dbo"), like="restore") == restore_tables diff --git a/ibis/backends/mysql/__init__.py b/ibis/backends/mysql/__init__.py index c477c191ffb7..2490bc275ef3 100644 --- a/ibis/backends/mysql/__init__.py +++ b/ibis/backends/mysql/__init__.py @@ -313,7 +313,6 @@ def raw_sql(self, query: str | sg.Expression, **kwargs: Any) -> Any: def list_tables( self, like: str | None = None, - schema: str | None = None, database: tuple[str, str] | str | None = None, ) -> list[str]: """List the tables in the database. @@ -333,27 +332,11 @@ def list_tables( ---------- like A pattern to use for listing tables. - schema - [deprecated] The schema to perform the list against. database Database to list tables from. Default behavior is to show tables in the current database (`self.current_database`). """ - if schema is not None: - self._warn_schema() - - if schema is not None and database is not None: - raise ValueError( - "Using both the `schema` and `database` kwargs is not supported. " - "`schema` is deprecated and will be removed in Ibis 10.0" - "\nUse the `database` kwarg with one of the following patterns:" - '\ndatabase="database"' - '\ndatabase=("catalog", "database")' - '\ndatabase="catalog.database"', - ) - elif schema is not None: - table_loc = schema - elif database is not None: + if database is not None: table_loc = database else: table_loc = self.current_database diff --git a/ibis/backends/mysql/tests/test_client.py b/ibis/backends/mysql/tests/test_client.py index 95f4bd048c8e..831363d71362 100644 --- a/ibis/backends/mysql/tests/test_client.py +++ b/ibis/backends/mysql/tests/test_client.py @@ -226,7 +226,7 @@ def json_arrayagg(a) -> str: assert result == expected -def test_list_tables_schema_warning_refactor(con): +def test_list_tables(con): mysql_tables = { "column_stats", "columns_priv", @@ -236,9 +236,6 @@ def test_list_tables_schema_warning_refactor(con): } assert con.list_tables() - with pytest.warns(FutureWarning): - assert mysql_tables.issubset(con.list_tables(schema="mysql")) - assert mysql_tables.issubset(con.list_tables(database="mysql")) assert mysql_tables.issubset(con.list_tables(database=("mysql",))) diff --git a/ibis/backends/oracle/__init__.py b/ibis/backends/oracle/__init__.py index 6bcfe69b9591..b189ba3d3778 100644 --- a/ibis/backends/oracle/__init__.py +++ b/ibis/backends/oracle/__init__.py @@ -22,7 +22,7 @@ import ibis.expr.schema as sch import ibis.expr.types as ir from ibis import util -from ibis.backends import CanListDatabase, CanListSchema +from ibis.backends import CanListDatabase from ibis.backends.sql import SQLBackend from ibis.backends.sql.compilers.base import NULL, STAR, C @@ -75,7 +75,7 @@ def metadata_row_to_type( return typ -class Backend(SQLBackend, CanListDatabase, CanListSchema): +class Backend(SQLBackend, CanListDatabase): name = "oracle" compiler = sc.oracle.compiler @@ -270,7 +270,6 @@ def raw_sql(self, query: str | sg.Expression, **kwargs: Any) -> Any: def list_tables( self, like: str | None = None, - schema: str | None = None, database: tuple[str, str] | str | None = None, ) -> list[str]: """List the tables in the database. @@ -290,31 +289,17 @@ def list_tables( ---------- like A pattern to use for listing tables. - schema - [deprecated] The schema to perform the list against. database Database to list tables from. Default behavior is to show tables in the current database. """ - if schema is not None and database is not None: - raise exc.IbisInputError( - "Using both the `schema` and `database` kwargs is not supported. " - "`schema` is deprecated and will be removed in Ibis 10.0" - "\nUse the `database` kwarg with one of the following patterns:" - '\ndatabase="database"' - '\ndatabase=("catalog", "database")' - '\ndatabase="catalog.database"', - ) - if schema is not None: - # TODO: remove _warn_schema when the schema kwarg is removed - self._warn_schema() - table_loc = schema - elif database is not None: + if database is not None: table_loc = database else: table_loc = self.con.username.upper() + table_loc = self._to_sqlglot_table(table_loc) # Deeply frustrating here where if we call `convert` on `table_loc`, diff --git a/ibis/backends/oracle/tests/test_client.py b/ibis/backends/oracle/tests/test_client.py index 1806a2e0e1d4..97765b4d754f 100644 --- a/ibis/backends/oracle/tests/test_client.py +++ b/ibis/backends/oracle/tests/test_client.py @@ -8,7 +8,6 @@ import pytest import ibis -import ibis.common.exceptions as exc from ibis import udf from ibis.backends.oracle.tests.conftest import ( ORACLE_HOST, @@ -67,15 +66,9 @@ def stats_one_way_anova(x, y, value: str) -> int: tm.assert_frame_equal(result, expected, check_dtype=False) -def test_list_tables_schema_warning_refactor(con): +def test_list_tables(con): assert con.list_tables() - with pytest.raises(exc.IbisInputError): - con.list_tables(database="not none", schema="not none") - - with pytest.warns(FutureWarning): - assert con.list_tables(schema="SYS", like="EXU8OPT") == ["EXU8OPT"] - assert con.list_tables(database="SYS", like="EXU8OPT") == ["EXU8OPT"] diff --git a/ibis/backends/postgres/__init__.py b/ibis/backends/postgres/__init__.py index 68feacd6c02c..ddc3d4e169c4 100644 --- a/ibis/backends/postgres/__init__.py +++ b/ibis/backends/postgres/__init__.py @@ -21,7 +21,7 @@ import ibis.expr.schema as sch import ibis.expr.types as ir from ibis import util -from ibis.backends import CanCreateDatabase, CanCreateSchema, CanListCatalog +from ibis.backends import CanCreateDatabase, CanListCatalog from ibis.backends.sql import SQLBackend from ibis.backends.sql.compilers.base import TRUE, C, ColGen, F @@ -35,7 +35,7 @@ import pyarrow as pa -class Backend(SQLBackend, CanListCatalog, CanCreateDatabase, CanCreateSchema): +class Backend(SQLBackend, CanListCatalog, CanCreateDatabase): name = "postgres" compiler = sc.postgres.compiler supports_python_udfs = True @@ -302,7 +302,6 @@ def _session_temp_db(self) -> str | None: def list_tables( self, like: str | None = None, - schema: str | None = None, database: tuple[str, str] | str | None = None, ) -> list[str]: """List the tables in the database. @@ -322,27 +321,12 @@ def list_tables( ---------- like A pattern to use for listing tables. - schema - [deprecated] The schema to perform the list against. database Database to list tables from. Default behavior is to show tables in the current database. """ - if schema is not None: - self._warn_schema() - - if schema is not None and database is not None: - raise ValueError( - "Using both the `schema` and `database` kwargs is not supported. " - "`schema` is deprecated and will be removed in Ibis 10.0" - "\nUse the `database` kwarg with one of the following patterns:" - '\ndatabase="database"' - '\ndatabase=("catalog", "database")' - '\ndatabase="catalog.database"', - ) - elif schema is not None: - table_loc = schema - elif database is not None: + + if database is not None: table_loc = database else: table_loc = (self.current_catalog, self.current_database) diff --git a/ibis/backends/snowflake/__init__.py b/ibis/backends/snowflake/__init__.py index 0d62bb76f438..5a53532f3e2f 100644 --- a/ibis/backends/snowflake/__init__.py +++ b/ibis/backends/snowflake/__init__.py @@ -27,7 +27,7 @@ import ibis.expr.schema as sch import ibis.expr.types as ir from ibis import util -from ibis.backends import CanCreateCatalog, CanCreateDatabase, CanCreateSchema +from ibis.backends import CanCreateCatalog, CanCreateDatabase from ibis.backends.snowflake.converter import SnowflakePandasData from ibis.backends.sql import SQLBackend from ibis.backends.sql.compilers.base import STAR @@ -137,7 +137,7 @@ } -class Backend(SQLBackend, CanCreateCatalog, CanCreateDatabase, CanCreateSchema): +class Backend(SQLBackend, CanCreateCatalog, CanCreateDatabase): name = "snowflake" compiler = sc.snowflake.compiler supports_python_udfs = True @@ -619,7 +619,6 @@ def list_tables( self, like: str | None = None, database: tuple[str, str] | str | None = None, - schema: str | None = None, ) -> list[str]: """List the tables in the database. @@ -644,10 +643,8 @@ def list_tables( To specify a table in a separate Snowflake catalog, you can pass in the catalog and database as a string `"catalog.database"`, or as a tuple of strings `("catalog", "database")`. - schema - [deprecated] The schema inside `database` to perform the list against. """ - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) tables_query = "SHOW TABLES" views_query = "SHOW VIEWS" @@ -1181,7 +1178,6 @@ def insert( self, table_name: str, obj: pd.DataFrame | ir.Table | list | dict, - schema: str | None = None, database: str | None = None, overwrite: bool = False, ) -> None: @@ -1202,8 +1198,6 @@ def insert( The name of the table to which data needs will be inserted obj The source data or expression to insert - schema - [deprecated] The name of the schema that the table is located in database Name of the attached database that the table is located in. @@ -1214,7 +1208,7 @@ def insert( If `True` then replace existing contents of table """ - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) catalog, db = self._to_catalog_db_tuple(table_loc) if not isinstance(obj, ir.Table): diff --git a/ibis/backends/snowflake/tests/test_client.py b/ibis/backends/snowflake/tests/test_client.py index 5e64c45a05bd..cd447104a25d 100644 --- a/ibis/backends/snowflake/tests/test_client.py +++ b/ibis/backends/snowflake/tests/test_client.py @@ -355,7 +355,7 @@ def test_struct_of_json(con): assert all(value == raw for value in result.to_pylist()) -def test_list_tables_schema_warning_refactor(con): +def test_list_tables(con): assert { "ASTRONAUTS", "AWARDS_PLAYERS", @@ -373,14 +373,6 @@ def test_list_tables_schema_warning_refactor(con): "TABLE_STORAGE_METRICS", ] - with pytest.warns(FutureWarning): - assert ( - con.list_tables( - database="IBIS_TESTING", schema="INFORMATION_SCHEMA", like="TABLE" - ) - == like_table - ) - assert ( con.list_tables(database="IBIS_TESTING.INFORMATION_SCHEMA", like="TABLE") == like_table diff --git a/ibis/backends/sql/__init__.py b/ibis/backends/sql/__init__.py index 2d64efe6076b..c2e4d47d5b76 100644 --- a/ibis/backends/sql/__init__.py +++ b/ibis/backends/sql/__init__.py @@ -25,47 +25,7 @@ from ibis.expr.schema import SchemaLike -class _DatabaseSchemaHandler: - """Temporary mixin collecting several helper functions and code snippets. - - Help to 'gracefully' deprecate the use of `schema` as a hierarchical term. - """ - - @staticmethod - def _warn_schema(): - util.warn_deprecated( - name="schema", - as_of="9.0", - removed_in="10.0", - instead="Use the `database` kwarg with one of the following patterns:" - '\ndatabase="database"' - '\ndatabase=("catalog", "database")' - '\ndatabase="catalog.database"', - # TODO: add option for namespace object - ) - - def _warn_and_create_table_loc(self, database=None, schema=None): - if schema is not None: - self._warn_schema() - - if database is not None and schema is not None: - if isinstance(database, str): - table_loc = f"{database}.{schema}" - elif isinstance(database, tuple): - table_loc = database + schema - elif schema is not None: - table_loc = schema - elif database is not None: - table_loc = database - else: - table_loc = None - - table_loc = self._to_sqlglot_table(table_loc) - - return table_loc - - -class SQLBackend(BaseBackend, _DatabaseSchemaHandler): +class SQLBackend(BaseBackend): compiler: ClassVar[SQLGlotCompiler] name: ClassVar[str] @@ -109,7 +69,6 @@ def _fetch_from_cursor(self, cursor, schema: sch.Schema) -> pd.DataFrame: def table( self, name: str, - schema: str | None = None, database: tuple[str, str] | str | None = None, ) -> ir.Table: """Construct a table expression. @@ -118,8 +77,6 @@ def table( ---------- name Table name - schema - [deprecated] Schema name database Database name @@ -129,7 +86,7 @@ def table( Table expression """ - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) catalog = table_loc.catalog or None database = table_loc.db or None @@ -218,10 +175,9 @@ def create_view( obj: ir.Table, *, database: str | None = None, - schema: str | None = None, overwrite: bool = False, ) -> ir.Table: - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) catalog, db = self._to_catalog_db_tuple(table_loc) src = sge.Create( @@ -240,10 +196,9 @@ def drop_view( name: str, *, database: str | None = None, - schema: str | None = None, force: bool = False, ) -> None: - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) catalog, db = self._to_catalog_db_tuple(table_loc) src = sge.Drop( @@ -281,7 +236,7 @@ def drop_table( database: tuple[str, str] | str | None = None, force: bool = False, ) -> None: - table_loc = self._warn_and_create_table_loc(database, None) + table_loc = self._to_sqlglot_table(database) catalog, db = self._to_catalog_db_tuple(table_loc) drop_stmt = sg.exp.Drop( @@ -358,7 +313,6 @@ def insert( self, table_name: str, obj: pd.DataFrame | ir.Table | list | dict, - schema: str | None = None, database: str | None = None, overwrite: bool = False, ) -> None: @@ -381,8 +335,6 @@ def insert( The name of the table to which data needs will be inserted obj The source data or expression to insert - schema - [deprecated] The name of the schema that the table is located in database Name of the attached database that the table is located in. @@ -393,7 +345,7 @@ def insert( If `True` then replace existing contents of table """ - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) catalog, db = self._to_catalog_db_tuple(table_loc) if overwrite: @@ -485,7 +437,9 @@ def _build_insert_template( ).sql(self.dialect) def truncate_table( - self, name: str, database: str | None = None, schema: str | None = None + self, + name: str, + database: str | None = None, ) -> None: """Delete all rows from a table. @@ -509,11 +463,10 @@ def truncate_table( For backends that support multi-level table hierarchies, you can pass in a dotted string path like `"catalog.database"` or a tuple of strings like `("catalog", "database")`. - schema - [deprecated] Schema name + """ - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) catalog, db = self._to_catalog_db_tuple(table_loc) ident = sg.table(name, db=db, catalog=catalog, quoted=self.compiler.quoted).sql( diff --git a/ibis/backends/sqlite/__init__.py b/ibis/backends/sqlite/__init__.py index a1f4f078178d..a5c074aefbd8 100644 --- a/ibis/backends/sqlite/__init__.py +++ b/ibis/backends/sqlite/__init__.py @@ -560,13 +560,8 @@ def create_view( obj: ir.Table, *, database: str | None = None, - schema: str | None = None, overwrite: bool = False, ) -> ir.Table: - # schema was never used here, but warn for consistency - if schema is not None: - self._warn_schema() - view = sg.table(name, catalog=database, quoted=self.compiler.quoted) stmts = [] diff --git a/ibis/backends/tests/test_client.py b/ibis/backends/tests/test_client.py index f76474667684..069d6a525b2a 100644 --- a/ibis/backends/tests/test_client.py +++ b/ibis/backends/tests/test_client.py @@ -1375,33 +1375,6 @@ def test_create_database(con_create_database): assert database not in con_create_database.list_databases() -def test_list_schema_warns(con_list_schema): - with pytest.warns(FutureWarning): - con_list_schema.list_schemas() - - -@pytest.mark.never( - [ - "clickhouse", - "mysql", - "pyspark", - "flink", - ], - reason="No schema methods", -) -def test_create_schema(con_create_database): - schema = gen_name("test_create_schema") - with pytest.warns(FutureWarning): - con_create_database.create_schema(schema) - with pytest.warns(FutureWarning): - assert schema in con_create_database.list_schemas() - schema = schema.lower() - with pytest.warns(FutureWarning): - con_create_database.drop_schema(schema) - with pytest.warns(FutureWarning): - assert schema not in con_create_database.list_schemas() - - def test_list_databases(con_create_database): databases = con_create_database.list_databases() assert len(databases) == len(set(databases)) diff --git a/ibis/backends/tests/test_signatures.py b/ibis/backends/tests/test_signatures.py index 7d4095c44642..d1065867c0bf 100644 --- a/ibis/backends/tests/test_signatures.py +++ b/ibis/backends/tests/test_signatures.py @@ -82,7 +82,7 @@ def _scrape_methods(modules, params): "insert": pytest.param( SQLBackend, "insert", - marks=pytest.mark.notyet(["clickhouse", "flink", "impala", "sqlite"]), + marks=pytest.mark.notyet(["clickhouse", "flink", "impala"]), ), "list_databases": pytest.param( CanCreateDatabase, @@ -102,9 +102,7 @@ def _scrape_methods(modules, params): "list_tables": pytest.param( BaseBackend, "list_tables", - marks=pytest.mark.notyet( - ["flink", "mysql", "oracle", "postgres", "risingwave"] - ), + marks=pytest.mark.notyet(["flink"]), ), "read_csv": pytest.param( BaseBackend, @@ -131,21 +129,7 @@ def _scrape_methods(modules, params): "table", marks=pytest.mark.notyet( [ - "clickhouse", - "datafusion", - "druid", - "duckdb", - "exasol", - "mssql", - "mysql", - "oracle", "polars", - "postgres", - "risingwave", - "snowflake", - "sqlite", - "trino", - "pyspark", ] ), ), @@ -154,11 +138,6 @@ def _scrape_methods(modules, params): "to_parquet_dir", marks=pytest.mark.notyet(["pyspark"]), ), - "truncate_table": pytest.param( - SQLBackend, - "truncate_table", - marks=pytest.mark.notyet(["clickhouse", "impala"]), - ), } params = _scrape_methods( diff --git a/ibis/backends/trino/__init__.py b/ibis/backends/trino/__init__.py index 61c3c9a4b223..9ee1d628a007 100644 --- a/ibis/backends/trino/__init__.py +++ b/ibis/backends/trino/__init__.py @@ -20,7 +20,7 @@ import ibis.expr.schema as sch import ibis.expr.types as ir from ibis import util -from ibis.backends import CanCreateDatabase, CanCreateSchema, CanListCatalog +from ibis.backends import CanCreateDatabase, CanListCatalog from ibis.backends.sql import SQLBackend from ibis.backends.sql.compilers.base import AlterTable, C @@ -35,7 +35,7 @@ import ibis.expr.operations as ops -class Backend(SQLBackend, CanListCatalog, CanCreateDatabase, CanCreateSchema): +class Backend(SQLBackend, CanListCatalog, CanCreateDatabase): name = "trino" compiler = sc.trino.compiler supports_create_or_replace = False @@ -213,7 +213,6 @@ def list_tables( self, like: str | None = None, database: tuple[str, str] | str | None = None, - schema: str | None = None, ) -> list[str]: """List the tables in the database. @@ -230,10 +229,8 @@ def list_tables( To specify a table in a separate catalog, you can pass in the catalog and database as a string `"catalog.database"`, or as a tuple of strings `("catalog", "database")`. - schema - [deprecated] The schema inside `database` to perform the list against. """ - table_loc = self._warn_and_create_table_loc(database, schema) + table_loc = self._to_sqlglot_table(database) query = "SHOW TABLES" diff --git a/ibis/backends/trino/tests/test_client.py b/ibis/backends/trino/tests/test_client.py index 33a019c463e9..0efeb789b317 100644 --- a/ibis/backends/trino/tests/test_client.py +++ b/ibis/backends/trino/tests/test_client.py @@ -171,7 +171,7 @@ def test_table_access_database_schema(con): con.table("region", database="system.tpch.sf1") -def test_list_tables_schema_warning_refactor(con): +def test_list_tables(con): tpch_tables = [ "customer", "lineitem", @@ -185,14 +185,6 @@ def test_list_tables_schema_warning_refactor(con): assert con.list_tables() - # Error if user mixes tuple inputs and string inputs for database and schema - with pytest.raises(FutureWarning): - with pytest.raises(exc.IbisInputError): - con.list_tables(database=("tuple", "ohstuff"), schema="str") - - with pytest.warns(FutureWarning): - assert con.list_tables(database="tpch", schema="sf1") == tpch_tables - assert con.list_tables(database="tpch.sf1") == tpch_tables assert con.list_tables(database=("tpch", "sf1")) == tpch_tables