From: Reuven Starodubski Date: Wed, 10 Sep 2025 06:19:47 +0000 (+0300) Subject: Fixes: #12853 Move tests from pg dialect X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=75f97886b5ba2cfe374511259bc40166459433c5;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Fixes: #12853 Move tests from pg dialect --- diff --git a/test/dialect/postgresql/test_compiler.py b/test/dialect/postgresql/test_compiler.py index cd08ff6223..57bf1d526d 100644 --- a/test/dialect/postgresql/test_compiler.py +++ b/test/dialect/postgresql/test_compiler.py @@ -40,7 +40,6 @@ from sqlalchemy import UniqueConstraint from sqlalchemy import update from sqlalchemy import VARCHAR from sqlalchemy.dialects import postgresql -from sqlalchemy.dialects.postgresql import aggregate_order_by from sqlalchemy.dialects.postgresql import ARRAY as PG_ARRAY from sqlalchemy.dialects.postgresql import array from sqlalchemy.dialects.postgresql import array_agg as pg_array_agg @@ -64,7 +63,6 @@ from sqlalchemy.sql import column from sqlalchemy.sql import literal_column from sqlalchemy.sql import operators from sqlalchemy.sql import table -from sqlalchemy.sql import util as sql_util from sqlalchemy.sql.functions import GenericFunction from sqlalchemy.testing import expect_raises from sqlalchemy.testing import expect_raises_message @@ -2248,60 +2246,6 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): dialect=postgresql.dialect(), ) - def test_aggregate_order_by_one(self): - m = MetaData() - table = Table("table1", m, Column("a", Integer), Column("b", Integer)) - expr = func.array_agg(aggregate_order_by(table.c.a, table.c.b.desc())) - stmt = select(expr) - - # note this tests that the object exports FROM objects - # correctly - self.assert_compile( - stmt, - "SELECT array_agg(table1.a ORDER BY table1.b DESC) " - "AS array_agg_1 FROM table1", - ) - - def test_aggregate_order_by_two(self): - m = MetaData() - table = Table("table1", m, Column("a", Integer), Column("b", Integer)) - expr = func.string_agg( - table.c.a, aggregate_order_by(literal_column("','"), table.c.a) - ) - stmt = select(expr) - - self.assert_compile( - stmt, - "SELECT string_agg(table1.a, ',' ORDER BY table1.a) " - "AS string_agg_1 FROM table1", - ) - - def test_aggregate_order_by_multi_col(self): - m = MetaData() - table = Table("table1", m, Column("a", Integer), Column("b", Integer)) - expr = func.string_agg( - table.c.a, - aggregate_order_by( - literal_column("','"), table.c.a, table.c.b.desc() - ), - ) - stmt = select(expr) - - self.assert_compile( - stmt, - "SELECT string_agg(table1.a, " - "',' ORDER BY table1.a, table1.b DESC) " - "AS string_agg_1 FROM table1", - ) - - def test_aggregate_orcer_by_no_arg(self): - assert_raises_message( - TypeError, - "at least one ORDER BY element is required", - aggregate_order_by, - literal_column("','"), - ) - def test_pg_array_agg_implicit_pg_array(self): expr = pg_array_agg(column("data", Integer)) assert isinstance(expr.type, PG_ARRAY) @@ -2334,20 +2278,6 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): assert isinstance(expr.type, PG_ARRAY) is_(expr.type.item_type._type_affinity, Integer) - def test_aggregate_order_by_adapt(self): - m = MetaData() - table = Table("table1", m, Column("a", Integer), Column("b", Integer)) - expr = func.array_agg(aggregate_order_by(table.c.a, table.c.b.desc())) - stmt = select(expr) - - a1 = table.alias("foo") - stmt2 = sql_util.ClauseAdapter(a1).traverse(stmt) - self.assert_compile( - stmt2, - "SELECT array_agg(foo.a ORDER BY foo.b DESC) AS array_agg_1 " - "FROM table1 AS foo", - ) - def test_array_agg_w_filter_subscript(self): series = func.generate_series(1, 100).alias("series") series_col = column("series") @@ -4208,37 +4138,6 @@ class RegexpTest(fixtures.TestBase, testing.AssertsCompiledSQL): class CacheKeyTest(fixtures.CacheKeyFixture, fixtures.TestBase): - def test_aggregate_order_by(self): - """test #8574""" - - self._run_cache_key_fixture( - lambda: ( - aggregate_order_by(column("a"), column("a")), - aggregate_order_by(column("a"), column("b")), - aggregate_order_by(column("a"), column("a").desc()), - aggregate_order_by(column("a"), column("a").nulls_first()), - aggregate_order_by( - column("a"), column("a").desc().nulls_first() - ), - aggregate_order_by(column("a", Integer), column("b")), - aggregate_order_by(column("a"), column("b"), column("c")), - aggregate_order_by(column("a"), column("c"), column("b")), - aggregate_order_by( - column("a"), column("b").desc(), column("c") - ), - aggregate_order_by( - column("a"), column("b").nulls_first(), column("c") - ), - aggregate_order_by( - column("a"), column("b").desc().nulls_first(), column("c") - ), - aggregate_order_by( - column("a", Integer), column("a"), column("b") - ), - ), - compare_values=False, - ) - def test_array_equivalent_keys_one_element(self): self._run_cache_key_equal_fixture( lambda: ( diff --git a/test/dialect/postgresql/test_types.py b/test/dialect/postgresql/test_types.py index 6d1bdcfa38..d25c30455e 100644 --- a/test/dialect/postgresql/test_types.py +++ b/test/dialect/postgresql/test_types.py @@ -42,7 +42,6 @@ from sqlalchemy import types from sqlalchemy import Unicode from sqlalchemy import util from sqlalchemy.dialects import postgresql -from sqlalchemy.dialects.postgresql import aggregate_order_by from sqlalchemy.dialects.postgresql import array from sqlalchemy.dialects.postgresql import array_agg from sqlalchemy.dialects.postgresql import asyncpg @@ -80,6 +79,7 @@ from sqlalchemy.exc import CompileError from sqlalchemy.exc import DBAPIError from sqlalchemy.orm import declarative_base from sqlalchemy.orm import Session +from sqlalchemy.sql import aggregate_order_by from sqlalchemy.sql import bindparam from sqlalchemy.sql import operators from sqlalchemy.sql import sqltypes diff --git a/test/sql/test_compare.py b/test/sql/test_compare.py index 2a58906ae0..c79efda0e4 100644 --- a/test/sql/test_compare.py +++ b/test/sql/test_compare.py @@ -33,6 +33,7 @@ from sqlalchemy import values from sqlalchemy.dialects import mysql from sqlalchemy.dialects import postgresql from sqlalchemy.schema import Sequence +from sqlalchemy.sql import aggregate_order_by from sqlalchemy.sql import bindparam from sqlalchemy.sql import ColumnElement from sqlalchemy.sql import dml @@ -1418,6 +1419,37 @@ class CacheKeyTest(fixtures.CacheKeyFixture, CoreFixtures, fixtures.TestBase): is_not(ck1, None) is_not(ck3, None) + def test_aggregate_order_by(self): + """test #8574""" + + self._run_cache_key_fixture( + lambda: ( + aggregate_order_by(column("a"), column("a")), + aggregate_order_by(column("a"), column("b")), + aggregate_order_by(column("a"), column("a").desc()), + aggregate_order_by(column("a"), column("a").nulls_first()), + aggregate_order_by( + column("a"), column("a").desc().nulls_first() + ), + aggregate_order_by(column("a", Integer), column("b")), + aggregate_order_by(column("a"), column("b"), column("c")), + aggregate_order_by(column("a"), column("c"), column("b")), + aggregate_order_by( + column("a"), column("b").desc(), column("c") + ), + aggregate_order_by( + column("a"), column("b").nulls_first(), column("c") + ), + aggregate_order_by( + column("a"), column("b").desc().nulls_first(), column("c") + ), + aggregate_order_by( + column("a", Integer), column("a"), column("b") + ), + ), + compare_values=False, + ) + def all_hascachekey_subclasses(ignore_subclasses=()): def find_subclasses(cls: type): diff --git a/test/sql/test_functions.py b/test/sql/test_functions.py index 28cdb03a96..b29a29a817 100644 --- a/test/sql/test_functions.py +++ b/test/sql/test_functions.py @@ -17,6 +17,7 @@ from sqlalchemy import Integer from sqlalchemy import JSON from sqlalchemy import literal from sqlalchemy import literal_column +from sqlalchemy import MetaData from sqlalchemy import Numeric from sqlalchemy import select from sqlalchemy import Sequence @@ -34,6 +35,7 @@ from sqlalchemy.dialects import sqlite from sqlalchemy.dialects.postgresql import ARRAY as PG_ARRAY from sqlalchemy.dialects.postgresql import array from sqlalchemy.ext.compiler import compiles +from sqlalchemy.sql import aggregate_order_by from sqlalchemy.sql import column from sqlalchemy.sql import functions from sqlalchemy.sql import LABEL_STYLE_TABLENAME_PLUS_COL @@ -41,6 +43,7 @@ from sqlalchemy.sql import operators from sqlalchemy.sql import quoted_name from sqlalchemy.sql import sqltypes from sqlalchemy.sql import table +from sqlalchemy.sql import util from sqlalchemy.sql.compiler import BIND_TEMPLATES from sqlalchemy.sql.functions import FunctionElement from sqlalchemy.sql.functions import GenericFunction @@ -1064,6 +1067,70 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): }, ) + def test_aggregate_order_by_one(self): + table = Table("table1", MetaData(), Column("a", Integer), Column("b", Integer)) + expr = func.array_agg(aggregate_order_by(table.c.a, table.c.b.desc())) + stmt = select(expr) + + # note this tests that the object exports FROM objects + # correctly + self.assert_compile( + stmt, + "SELECT array_agg(table1.a ORDER BY table1.b DESC) " + "AS array_agg_1 FROM table1", + ) + + def test_aggregate_order_by_two(self): + table = Table("table1", MetaData(), Column("a", Integer), Column("b", Integer)) + expr = func.string_agg( + table.c.a, aggregate_order_by(literal_column("','"), table.c.a) + ) + stmt = select(expr) + + self.assert_compile( + stmt, + "SELECT string_agg(table1.a, ',' ORDER BY table1.a) " + "AS string_agg_1 FROM table1", + ) + + def test_aggregate_order_by_multi_col(self): + table = Table("table1", MetaData(), Column("a", Integer), Column("b", Integer)) + expr = func.string_agg( + table.c.a, + aggregate_order_by( + literal_column("','"), table.c.a, table.c.b.desc() + ), + ) + stmt = select(expr) + + self.assert_compile( + stmt, + "SELECT string_agg(table1.a, " + "',' ORDER BY table1.a, table1.b DESC) " + "AS string_agg_1 FROM table1", + ) + + def test_aggregate_order_by_no_arg(self): + assert_raises_message( + TypeError, + "at least one ORDER BY element is required", + aggregate_order_by, + literal_column("','"), + ) + + def test_aggregate_order_by_adapt(self): + table = Table("table1", MetaData(), Column("a", Integer), Column("b", Integer)) + expr = func.array_agg(aggregate_order_by(table.c.a, table.c.b.desc())) + stmt = select(expr) + + a1 = table.alias("foo") + stmt2 = util.ClauseAdapter(a1).traverse(stmt) + self.assert_compile( + stmt2, + "SELECT array_agg(foo.a ORDER BY foo.b DESC) AS array_agg_1 " + "FROM table1 AS foo", + ) + class ReturnTypeTest(AssertsCompiledSQL, fixtures.TestBase): def test_array_agg(self): diff --git a/test/typing/plain_files/dialects/postgresql/pg_stuff.py b/test/typing/plain_files/dialects/postgresql/pg_stuff.py index 0f1e588bd9..68ce28e796 100644 --- a/test/typing/plain_files/dialects/postgresql/pg_stuff.py +++ b/test/typing/plain_files/dialects/postgresql/pg_stuff.py @@ -10,7 +10,8 @@ from sqlalchemy import or_ from sqlalchemy import select from sqlalchemy import Text from sqlalchemy import UniqueConstraint -from sqlalchemy.dialects.postgresql import aggregate_order_by +from sqlalchemy.sql import aggregate_order_by +from sqlalchemy.dialects.postgresql import aggregate_order_by as pg_aggregate_order_by from sqlalchemy.dialects.postgresql import ARRAY from sqlalchemy.dialects.postgresql import array from sqlalchemy.dialects.postgresql import DATERANGE @@ -154,3 +155,13 @@ stmt_array_agg_order_by_2 = select( # EXPECTED_TYPE: Select[Tuple[Sequence[str]]] reveal_type(stmt_array_agg_order_by_2) + +# Test backwards compatibility - both should work the same +stmt_backwards_compat = select( + func.array_agg( + pg_aggregate_order_by(Test.ident_str, Test.id.desc(), Test.ident), + ) +) + +# EXPECTED_TYPE: Select[Tuple[Sequence[str]]] +reveal_type(stmt_backwards_compat)