示例#1
0
    def test_update_to_expression_two(self, randomized_param_order_update, t,
                                      idx_to_value):
        """test update from an expression.

        this logic is triggered currently by a left side that doesn't
        have a key.  The current supported use case is updating the index
        of a PostgreSQL ARRAY type.

        """

        dialect = default.StrCompileDialect()
        dialect.paramstyle = "qmark"
        dialect.positional = True

        stmt = t.update().ordered_values(*[(col[idx], val)
                                           for col, idx, val in idx_to_value])

        self.assert_compile(
            stmt,
            "UPDATE foo SET %s" %
            (", ".join("%s[?]=?" % col.key for col, idx, val in idx_to_value)),
            dialect=dialect,
            checkpositional=tuple(
                itertools.chain.from_iterable(
                    (idx, val) for col, idx, val in idx_to_value)),
        )
示例#2
0
    def test_update_bound_ordering(self):
        """test that bound parameters between the UPDATE and FROM clauses
        order correctly in different SQL compilation scenarios.

        """
        table1 = self.tables.mytable
        table2 = self.tables.myothertable
        sel = select(table2).where(table2.c.otherid == 5).alias()
        upd = (table1.update().where(table1.c.name == sel.c.othername).values(
            name="foo"))

        dialect = default.StrCompileDialect()
        dialect.positional = True
        self.assert_compile(
            upd,
            "UPDATE mytable SET name=:name FROM (SELECT "
            "myothertable.otherid AS otherid, "
            "myothertable.othername AS othername "
            "FROM myothertable "
            "WHERE myothertable.otherid = :otherid_1) AS anon_1 "
            "WHERE mytable.name = anon_1.othername",
            checkpositional=("foo", 5),
            dialect=dialect,
        )

        self.assert_compile(
            upd,
            "UPDATE mytable, (SELECT myothertable.otherid AS otherid, "
            "myothertable.othername AS othername "
            "FROM myothertable "
            "WHERE myothertable.otherid = %s) AS anon_1 SET mytable.name=%s "
            "WHERE mytable.name = anon_1.othername",
            checkpositional=(5, "foo"),
            dialect=mysql.dialect(),
        )
示例#3
0
    def test_update_to_expression_two(self):
        """test update from an expression.

        this logic is triggered currently by a left side that doesn't
        have a key.  The current supported use case is updating the index
        of a PostgreSQL ARRAY type.

        """

        from sqlalchemy import ARRAY

        t = table(
            "foo",
            column("data1", ARRAY(Integer)),
            column("data2", ARRAY(Integer)),
        )

        stmt = t.update().ordered_values(
            (t.c.data1[5], 7), (t.c.data2[10], 18)
        )
        dialect = default.StrCompileDialect()
        dialect.paramstyle = "qmark"
        dialect.positional = True
        self.assert_compile(
            stmt,
            "UPDATE foo SET data1[?]=?, data2[?]=?",
            dialect=dialect,
            checkpositional=(5, 7, 10, 18),
        )
示例#4
0
    def test_autocorrelate_error(self):
        table1, table2 = self.tables.mytable, self.tables.myothertable

        stmt = table1.delete().where(table1.c.myid == table2.c.otherid).where(
            ~exists().where(table2.c.otherid == table1.c.myid).where(
                table2.c.othername == 'x'))

        assert_raises_message(
            exc.InvalidRequestError,
            ".*returned no FROM clauses due to auto-correlation.*",
            stmt.compile,
            dialect=default.StrCompileDialect())
示例#5
0
    def test_autocorrelate_error(self):
        users, addresses = self.tables.users, self.tables.addresses

        stmt = users.update().values(name="newname").where(
            users.c.id == addresses.c.user_id).where(~exists().where(
                addresses.c.user_id == users.c.id).where(
                    addresses.c.email_address == 'foo'))

        assert_raises_message(
            exc.InvalidRequestError,
            ".*returned no FROM clauses due to auto-correlation.*",
            stmt.compile,
            dialect=default.StrCompileDialect())
示例#6
0
    def randomized_param_order_update(self):
        from sqlalchemy.sql.dml import UpdateDMLState

        super_process_ordered_values = UpdateDMLState._process_ordered_values

        # this fixture is needed for Python 3.6 and above to work around
        # dictionaries being insert-ordered.  in python 2.7 the previous
        # logic fails pretty easily without this fixture.
        def _process_ordered_values(self, statement):
            super_process_ordered_values(self, statement)

            tuples = list(self._dict_parameters.items())
            random.shuffle(tuples)
            self._dict_parameters = dict(tuples)

        dialect = default.StrCompileDialect()
        dialect.paramstyle = "qmark"
        dialect.positional = True

        with mock.patch.object(UpdateDMLState, "_process_ordered_values",
                               _process_ordered_values):
            yield
示例#7
0
    def test_update_to_expression_three(self):
        # this test is from test_defaults but exercises a particular
        # parameter ordering issue
        metadata = MetaData()

        q = Table(
            "q",
            metadata,
            Column("x", Integer, default=2),
            Column("y", Integer, onupdate=5),
            Column("z", Integer),
        )

        p = Table(
            "p",
            metadata,
            Column("s", Integer),
            Column("t", Integer),
            Column("u", Integer, onupdate=1),
        )

        cte = (
            q.update().where(q.c.z == 1).values(x=7).returning(q.c.z).cte("c")
        )
        stmt = select([p.c.s, cte.c.z]).where(p.c.s == cte.c.z)

        dialect = default.StrCompileDialect()
        dialect.paramstyle = "qmark"
        dialect.positional = True

        self.assert_compile(
            stmt,
            "WITH c AS (UPDATE q SET x=?, y=? WHERE q.z = ? RETURNING q.z) "
            "SELECT p.s, c.z FROM p, c WHERE p.s = c.z",
            checkpositional=(7, None, 1),
            dialect=dialect,
        )
示例#8
0
    def assert_compile(self,
                       clause,
                       result,
                       params=None,
                       checkparams=None,
                       dialect=None,
                       checkpositional=None,
                       check_prefetch=None,
                       use_default_dialect=False,
                       allow_dialect_select=False,
                       literal_binds=False,
                       schema_translate_map=None):
        if use_default_dialect:
            dialect = default.DefaultDialect()
        elif allow_dialect_select:
            dialect = None
        else:
            if dialect is None:
                dialect = getattr(self, '__dialect__', None)

            if dialect is None:
                dialect = config.db.dialect
            elif dialect == 'default':
                dialect = default.DefaultDialect()
            elif dialect == 'default_enhanced':
                dialect = default.StrCompileDialect()
            elif isinstance(dialect, util.string_types):
                dialect = url.URL(dialect).get_dialect()()

        kw = {}
        compile_kwargs = {}

        if schema_translate_map:
            kw['schema_translate_map'] = schema_translate_map

        if params is not None:
            kw['column_keys'] = list(params)

        if literal_binds:
            compile_kwargs['literal_binds'] = True

        if isinstance(clause, orm.Query):
            context = clause._compile_context()
            context.statement.use_labels = True
            clause = context.statement

        if compile_kwargs:
            kw['compile_kwargs'] = compile_kwargs

        c = clause.compile(dialect=dialect, **kw)

        param_str = repr(getattr(c, 'params', {}))

        if util.py3k:
            param_str = param_str.encode('utf-8').decode('ascii', 'ignore')
            print(("\nSQL String:\n" + util.text_type(c) +
                   param_str).encode('utf-8'))
        else:
            print("\nSQL String:\n" + util.text_type(c).encode('utf-8') +
                  param_str)

        cc = re.sub(r'[\n\t]', '', util.text_type(c))

        eq_(cc, result, "%r != %r on dialect %r" % (cc, result, dialect))

        if checkparams is not None:
            eq_(c.construct_params(params), checkparams)
        if checkpositional is not None:
            p = c.construct_params(params)
            eq_(tuple([p[x] for x in c.positiontup]), checkpositional)
        if check_prefetch is not None:
            eq_(c.prefetch, check_prefetch)
示例#9
0
    def assert_compile(
        self,
        clause,
        result,
        params=None,
        checkparams=None,
        dialect=None,
        checkpositional=None,
        check_prefetch=None,
        use_default_dialect=False,
        allow_dialect_select=False,
        literal_binds=False,
        schema_translate_map=None,
    ):
        if use_default_dialect:
            dialect = default.DefaultDialect()
        elif allow_dialect_select:
            dialect = None
        else:
            if dialect is None:
                dialect = getattr(self, "__dialect__", None)

            if dialect is None:
                dialect = config.db.dialect
            elif dialect == "default":
                dialect = default.DefaultDialect()
            elif dialect == "default_enhanced":
                dialect = default.StrCompileDialect()
            elif isinstance(dialect, util.string_types):
                dialect = url.URL(dialect).get_dialect()()

        kw = {}
        compile_kwargs = {}

        if schema_translate_map:
            kw["schema_translate_map"] = schema_translate_map

        if params is not None:
            kw["column_keys"] = list(params)

        if literal_binds:
            compile_kwargs["literal_binds"] = True

        if isinstance(clause, orm.Query):
            context = clause._compile_context()
            context.statement.use_labels = True
            clause = context.statement
        elif isinstance(clause, orm.persistence.BulkUD):
            with mock.patch.object(clause, "_execute_stmt") as stmt_mock:
                clause.exec_()
                clause = stmt_mock.mock_calls[0][1][0]

        if compile_kwargs:
            kw["compile_kwargs"] = compile_kwargs

        c = clause.compile(dialect=dialect, **kw)

        param_str = repr(getattr(c, "params", {}))

        if util.py3k:
            param_str = param_str.encode("utf-8").decode("ascii", "ignore")
            print(("\nSQL String:\n" + util.text_type(c) +
                   param_str).encode("utf-8"))
        else:
            print("\nSQL String:\n" + util.text_type(c).encode("utf-8") +
                  param_str)

        cc = re.sub(r"[\n\t]", "", util.text_type(c))

        eq_(cc, result, "%r != %r on dialect %r" % (cc, result, dialect))

        if checkparams is not None:
            eq_(c.construct_params(params), checkparams)
        if checkpositional is not None:
            p = c.construct_params(params)
            eq_(tuple([p[x] for x in c.positiontup]), checkpositional)
        if check_prefetch is not None:
            eq_(c.prefetch, check_prefetch)