def test_limit_offset_for_update(self, metadata, connection): # oracle can't actually do the ROWNUM thing with FOR UPDATE # very well. t = Table( "t1", metadata, Column("id", Integer, primary_key=True), Column("data", Integer), ) metadata.create_all(connection) connection.execute( t.insert(), [ { "id": 1, "data": 1 }, { "id": 2, "data": 7 }, { "id": 3, "data": 12 }, { "id": 4, "data": 15 }, { "id": 5, "data": 32 }, ], ) # here, we can't use ORDER BY. # as of #8221, this fails also. limit w/o order by is useless # in any case. stmt = t.select().with_for_update().limit(2) if testing.against("oracle>=12"): with expect_raises_message(exc.DatabaseError, "ORA-02014"): connection.execute(stmt).fetchall() else: eq_( connection.execute(stmt).fetchall(), [(1, 1), (2, 7)], ) # here, its impossible. But we'd prefer it to raise ORA-02014 # instead of issuing a syntax error. with expect_raises_message(exc.DatabaseError, "ORA-02014"): connection.execute(t.select().with_for_update().limit(2).offset(3))
def test_abs_concrete_extension_warn_for_overlap(self): class Employee(AbstractConcreteBase, Base, fixtures.ComparableEntity): name = Column(String(50)) __mapper_args__ = { "polymorphic_identity": "employee", "concrete": True, } class Manager(Employee): __tablename__ = "manager" employee_id = Column(Integer, primary_key=True, test_needs_autoincrement=True) type = Column(String(50)) __mapper_args__ = { "polymorphic_identity": "manager", "concrete": True, } with expect_raises_message( sa_exc.InvalidRequestError, "Polymorphic union can't use 'type' as the discriminator " "column due to mapped column " r"Column\('type', String\(length=50\), table=<manager>\); " "please " "apply the 'typecolname' argument; this is available on " "ConcreteBase as '_concrete_discriminator_name'", ): configure_mappers()
def test_no_order_by_text(self): stmt = select(text("foo")).order_by("foo") with expect_raises_message( exc.CompileError, r"Can't resolve label reference for ORDER BY / GROUP BY / ", ): stmt.compile()
def test_star_must_be_alone(self): self._downgrade_fixture() User = self.classes.User with expect_raises_message( sa.exc.ArgumentError, "Wildcard token cannot be followed by another entity", ): subqueryload("*", User.addresses)
def test_minimum_version(self): with expect_raises_message( exc.InvalidRequestError, "oracledb version 1 and above are supported", ): oracledb.OracleDialect_oracledb(dbapi=Mock(version="0.1.5")) dialect = oracledb.OracleDialect_oracledb(dbapi=Mock(version="7.1.0")) eq_(dialect.oracledb_ver, (7, 1, 0))
def test_minimum_version(self): with expect_raises_message( exc.InvalidRequestError, "cx_Oracle version 7 and above are supported", ): cx_oracle.OracleDialect_cx_oracle(dbapi=Mock(version="5.1.5")) dialect = cx_oracle.OracleDialect_cx_oracle(dbapi=Mock( version="7.1.0")) eq_(dialect.cx_oracle_ver, (7, 1, 0))
def test_star_cant_be_followed(self): self._downgrade_fixture() User = self.classes.User Order = self.classes.Order with expect_raises_message( sa.exc.ArgumentError, "Wildcard token cannot be followed by another entity", ): subqueryload(User.addresses).joinedload("*").selectinload( Order.items)
def test_custom_op_no_impl(self): """test #3162""" User = self.classes.User with expect_raises_message( evaluator.UnevaluatableError, r"Custom operator '\^\^' can't be evaluated in " "Python unless it specifies", ): compiler.process(User.name.op("^^")("bar"))
def test_no_out_params_w_returning(self, connection, metadata): t = Table("t", metadata, Column("x", Integer), Column("y", Integer)) metadata.create_all(connection) stmt = (t.insert().values(x=5, y=10).returning( outparam("my_param", Integer), t.c.x)) with expect_raises_message( exc.InvalidRequestError, r"Using explicit outparam\(\) objects with " r"UpdateBase.returning\(\) in the same Core DML statement " "is not supported in the Oracle dialect.", ): connection.execute(stmt)
def test_implicit_returning_engine_parameter(self, implicit_returning): if implicit_returning is None: e = engines.testing_engine() else: with assertions.expect_deprecated(ce_implicit_returning): e = engines.testing_engine( options={"implicit_returning": implicit_returning}) if implicit_returning is None: eq_( e.dialect.implicit_returning, testing.db.dialect.implicit_returning, ) else: eq_(e.dialect.implicit_returning, implicit_returning) t = Table( "t", MetaData(), Column("id", Integer, primary_key=True), Column("data", String(50)), ) t2 = Table( "t", MetaData(), Column("id", Integer, primary_key=True), Column("data", String(50)), implicit_returning=False, ) with e.connect() as conn: stmt = insert(t).values(data="data") if implicit_returning: if not testing.requires.returning.enabled: with expect_raises_message(exc.CompileError, "RETURNING is not supported"): stmt.compile(conn) else: eq_(stmt.compile(conn).implicit_returning, [t.c.id]) elif (implicit_returning is None and testing.db.dialect.implicit_returning): eq_(stmt.compile(conn).implicit_returning, [t.c.id]) else: eq_(stmt.compile(conn).implicit_returning, []) # table setting it to False disables it stmt2 = insert(t2).values(data="data") eq_(stmt2.compile(conn).implicit_returning, [])
def test_engine_from_config_future_false_raises(self): dbapi = mock_dbapi config = { "sqlalchemy.url": "postgresql+psycopg2://scott:tiger@somehost/test" "?fooz=somevalue", "sqlalchemy.future": "false", } with expect_raises_message( exc.ArgumentError, r"The 'future' parameter passed to create_engine\(\) " r"may only be set to True.", ): engine_from_config(config, module=dbapi, _initialize=False)
def test_selectinload_w_joinedload_after_base_target_fails( self, use_of_type): A, B, C = self.classes("A", "B", "C") s = Session(testing.db) partitioned_b = self.partitioned_b if use_of_type: opt = selectinload( A.partitioned_bs.of_type(partitioned_b)).joinedload(B.cs) else: opt = selectinload(A.partitioned_bs).joinedload(B.cs) q = s.query(A).options(opt) with expect_raises_message( exc.ArgumentError, r'Attribute "B.cs" does not link from element "aliased\(B\)"', ): q._compile_context()
def test_no_star_orm_combinations(self, exprtype, testcase): """test for #8235""" User = self.classes.User if exprtype == "plain": star = "*" elif exprtype == "text": star = text("*") elif exprtype == "literal_column": star = literal_column("*") else: assert False args = testing.resolve_lambda(testcase, User=User, star=star) stmt = select(*args).select_from(User) s = fixture_session() with expect_raises_message( exc.CompileError, r"Can't generate ORM query that includes multiple expressions " r"at the same time as '\*';", ): s.execute(stmt)
def test_subclass_loadattr(self, first_option, second_option, second_argument, expect_load): Parent, Entity, SubEntity = self.classes("Parent", "Entity", "SubEntity") stmt = select(Parent) will_lazyload = first_option in (defaultload, lazyload) if second_argument == "name": second_argument = SubEntity.name opt = first_option(Parent.entity.of_type(SubEntity)) elif second_argument == "id": opt = first_option(Parent.entity) second_argument = Entity.id else: opt = first_option(Parent.entity) if second_option is None: sub_opt = opt elif second_option == "raise": sub_opt = opt.defer(second_argument, raiseload=True) else: sub_opt = getattr(opt, second_option)(second_argument) stmt = stmt.options(sub_opt) session = fixture_session() result = session.execute(stmt).scalars() parent_obj = result.first() entity_id = parent_obj.__dict__["entity_id"] with assertsql.assert_engine(testing.db) as asserter_: if expect_load: eq_(parent_obj.entity.name, "some name") else: with expect_raises_message( exc.InvalidRequestError, "'SubEntity.name' is not available due to raiseload=True", ): parent_obj.entity.name expected = [] if will_lazyload: expected.append( CompiledSQL( "SELECT entity.id AS entity_id, " "entity.type AS entity_type FROM entity " "WHERE entity.id = :pk_1", [{ "pk_1": entity_id }], )) if second_option in ("load_only", None) or ( second_option == "undefer" and first_option in (defaultload, lazyload)): # load will be a mapper optimized load for the name alone expected.append( CompiledSQL( "SELECT sub_entity.name AS sub_entity_name " "FROM sub_entity " "WHERE :param_1 = sub_entity.id", [{ "param_1": entity_id }], )) elif second_option == "defer": # load will be a deferred load. this is because the explicit # call to the deferred load put a deferred loader on the attribute expected.append( CompiledSQL( "SELECT sub_entity.name AS sub_entity_name " "FROM sub_entity " "WHERE :param_1 = sub_entity.id", [{ "param_1": entity_id }], )) asserter_.assert_(*expected)
async def run_test(subject, trans_on_subject, execute_on_subject): async with subject.begin() as trans: if begin_nested: if not config.requirements.savepoints.enabled: config.skip_test("savepoints not enabled") if execute_on_subject: nested_trans = subject.begin_nested() else: nested_trans = trans.begin_nested() async with nested_trans: if execute_on_subject: await subject.execute(t.insert(), {"data": 10}) else: await trans.execute(t.insert(), {"data": 10}) # for nested trans, we always commit/rollback on the # "nested trans" object itself. # only Session(future=False) will affect savepoint # transaction for session.commit/rollback if rollback: await nested_trans.rollback() else: await nested_trans.commit() if run_second_execute: with assertions.expect_raises_message( exc.InvalidRequestError, "Can't operate on closed transaction " "inside context manager. Please complete the " "context manager " "before emitting further commands.", ): if execute_on_subject: await subject.execute( t.insert(), {"data": 12}) else: await trans.execute( t.insert(), {"data": 12}) # outside the nested trans block, but still inside the # transaction block, we can run SQL, and it will be # committed if execute_on_subject: await subject.execute(t.insert(), {"data": 14}) else: await trans.execute(t.insert(), {"data": 14}) else: if execute_on_subject: await subject.execute(t.insert(), {"data": 10}) else: await trans.execute(t.insert(), {"data": 10}) if trans_on_subject: if rollback: await subject.rollback() else: await subject.commit() else: if rollback: await trans.rollback() else: await trans.commit() if run_second_execute: with assertions.expect_raises_message( exc.InvalidRequestError, "Can't operate on closed transaction inside " "context " "manager. Please complete the context manager " "before emitting further commands.", ): if execute_on_subject: await subject.execute(t.insert(), {"data": 12}) else: await trans.execute(t.insert(), {"data": 12}) expected_committed = 0 if begin_nested: # begin_nested variant, we inserted a row after the nested # block expected_committed += 1 if not rollback: # not rollback variant, our row inserted in the target # block itself would be committed expected_committed += 1 if execute_on_subject: eq_( await subject.scalar(select(func.count()).select_from(t)), expected_committed, ) else: with subject.connect() as conn: eq_( await conn.scalar(select(func.count()).select_from(t)), expected_committed, )
def test_query_dict_immutable(self, urlstr): url_obj = url.make_url(urlstr) with expect_raises_message(TypeError, ".*immutable"): url_obj.query["foo"] = "hoho"
def test_determine_local_remote_pairs_o2m_overlap_func_warning(self): with expect_raises_message(exc.ArgumentError, "Could not locate any relevant"): self._assert_non_simple_warning( self._join_fixture_m2o_sub_to_joined_sub_func)