importrandomimportunittestfromsqlalchemyimportColumnfromsqlalchemyimportfuncfromsqlalchemyimportIntegerfromsqlalchemyimportMetaDatafromsqlalchemyimportselectfromsqlalchemyimportTablefromsqlalchemy.testingimportAssertsCompiledSQLfromsqlalchemy.testingimporteq_fromsqlalchemy.testingimportfixturesfrom.qualifyimportqualifyqt_table=Table("qt",MetaData(),Column("i",Integer),Column("p",Integer),Column("o",Integer),)classQualifyCompileTest(AssertsCompiledSQL,fixtures.CacheKeySuite):"""A sample test suite for the QUALIFY clause, making use of SQLAlchemy testing utilities. """__dialect__="default"@fixtures.CacheKeySuite.run_suite_testsdeftest_qualify_cache_key(self):"""A cache key suite using the ``CacheKeySuite.run_suite_tests`` decorator. This suite intends to test that the "_traverse_internals" structure of the custom SQL construct covers all the structural elements of the object. A decorated function should return a callable (e.g. a lambda) which returns a list of SQL structures. The suite will call upon this lambda multiple times, to make the same list of SQL structures repeatedly. It then runs comparisons of the generated cache key for each element in a particular list to all the other elements in that same list, as well as other versions of the list. The rules for this list are then as follows: * Each element of the list should store a SQL structure that is **structurally identical** each time, for a given position in the list. Successive versions of this SQL structure will be compared to previous ones in the same list position and they must be identical. * Each element of the list should store a SQL structure that is **structurally different** from **all other** elements in the list. Successive versions of this SQL structure will be compared to other members in other list positions, and they must be different each time. * The SQL structures returned in the list should exercise all of the structural features that are provided by the construct. This is to ensure that two different structural elements generate a different cache key and won't be mis-cached. * Literal parameters like strings and numbers are **not** part of the cache key itself since these are not "structural" elements; two SQL structures that are identical can nonetheless have different parameterized values. To better exercise testing that this variation is not stored as part of the cache key, ``random`` functions like ``random.randint()`` or ``random.choice()`` can be used to generate random literal values within a single element. """defstmt0():returnselect(qt_table)defstmt1():stmt=stmt0()returnstmt.ext(qualify(qt_table.c.p==random.choice([2,6,10])))defstmt2():stmt=stmt0()returnstmt.ext(qualify(func.row_number().over(order_by=qt_table.c.o)))defstmt3():stmt=stmt0()returnstmt.ext(qualify(func.row_number().over(partition_by=qt_table.c.i,order_by=qt_table.c.o)))returnlambda:[stmt0(),stmt1(),stmt2(),stmt3()]deftest_query_one(self):"""A compilation test. This makes use of the ``AssertsCompiledSQL.assert_compile()`` utility. """stmt=select(qt_table).ext(qualify(func.row_number().over(partition_by=qt_table.c.p,order_by=qt_table.c.o)==1))self.assert_compile(stmt,"SELECT qt.i, qt.p, qt.o FROM qt QUALIFY row_number() ""OVER (PARTITION BY qt.p ORDER BY qt.o) = :param_1",)deftest_query_two(self):"""A compilation test. This makes use of the ``AssertsCompiledSQL.assert_compile()`` utility. """row_num=(func.row_number().over(partition_by=qt_table.c.p,order_by=qt_table.c.o).label("row_num"))stmt=select(qt_table,row_num).ext(qualify(row_num.as_reference()==1))self.assert_compile(stmt,"SELECT qt.i, qt.p, qt.o, row_number() OVER ""(PARTITION BY qt.p ORDER BY qt.o) AS row_num ""FROM qt QUALIFY row_num = :param_1",)deftest_propagate_attrs(self):"""ORM propagate test. this is an optional test that tests apply_propagate_attrs, indicating when you pass ORM classes / attributes to your construct, there's a dictionary called ``._propagate_attrs`` that gets carried along to the statement, which marks it as an "ORM" statement. """row_num=(func.row_number().over(partition_by=qt_table.c.p).label("row_num"))row_num._propagate_attrs={"foo":"bar"}stmt=select(1).ext(qualify(row_num.as_reference()==1))eq_(stmt._propagate_attrs,{"foo":"bar"})classQualifyCompileUnittest(QualifyCompileTest,unittest.TestCase):passif__name__=="__main__":unittest.main()