예제 #1
0
    async def delete(self, info: QueryInfo, *, _perm=None) -> IDList:
        model = self.mapping2model[info.from_table]
        when_before_delete, when_complete = [], []
        await info.from_table.on_delete(info, when_before_delete,
                                        when_complete, _perm)

        qi = info.clone()
        qi.select = []
        lst = await self.get_list(qi, _perm=_perm)

        # 选择项
        id_lst = [x.id for x in lst]

        for i in when_before_delete:
            await i(id_lst)

        if id_lst:
            phg = self.get_placeholder_generator()
            sql = Query().from_(model).delete().where(
                model.id.isin(phg.next(id_lst)))
            await self.execute_sql(sql.get_sql(), phg)

        for i in when_complete:
            await i()

        return id_lst
예제 #2
0
    async def update(self,
                     info: QueryInfo,
                     values: ValuesToWrite,
                     *,
                     _perm=None) -> IDList:
        # hook
        await info.from_table.on_query(info, _perm)
        when_before_update, when_complete = [], []
        await info.from_table.on_update(info, values, when_before_update,
                                        when_complete, _perm)

        model = self.mapping2model[info.from_table]
        tc = self._table_cache[info.from_table]
        qi = info.clone()
        qi.select = []
        lst = await self.get_list(qi, _perm=_perm)
        id_lst = [x.id for x in lst]

        for i in when_before_update:
            await i(id_lst)

        if id_lst:
            # 选择项
            phg = self.get_placeholder_generator()
            sql = Query().update(model)
            for k, v in values.items():
                vflag = values.data_flag.get(k)

                val = phg.next(v,
                               left_is_array=k in tc['array_fields'],
                               left_is_json=k in tc['json_fields'])

                if vflag:
                    if vflag == ValuesDataFlag.INCR:
                        # f'{k} + {val}'
                        sql = sql.set(
                            k,
                            ArithmeticExpression(Arithmetic.add,
                                                 PypikaField(k), val))

                    elif vflag == ValuesDataFlag.DECR:
                        # f'{k} - {val}'
                        sql = sql.set(
                            k,
                            ArithmeticExpression(Arithmetic.sub,
                                                 PypikaField(k), val))

                    elif vflag == ValuesDataFlag.ARRAY_EXTEND:
                        # f'{k} || {val}'
                        vexpr = ArithmeticExpression(ArithmeticExt.concat,
                                                     PypikaField(k), val)
                        sql = sql.set(k, vexpr)

                    elif vflag == ValuesDataFlag.ARRAY_PRUNE:
                        # TODO: 现在prune也会去重,这是不对的
                        # f'array(SELECT unnest({k}) EXCEPT SELECT unnest({val}))'
                        vexpr = PostgresArrayDifference(PypikaField(k), val)
                        sql = sql.set(k, vexpr)

                    elif vflag == ValuesDataFlag.ARRAY_EXTEND_DISTINCT:
                        # f'ARRAY(SELECT DISTINCT unnest({k} || {val}))'
                        vexpr = PostgresArrayDistinct(
                            ArithmeticExpression(ArithmeticExt.concat,
                                                 PypikaField(k), val))
                        sql = sql.set(k, vexpr)

                    elif vflag == ValuesDataFlag.ARRAY_PRUNE_DISTINCT:
                        vexpr = PostgresArrayDifference(PypikaField(k), val)
                        sql = sql.set(k, vexpr)

                else:
                    sql = sql.set(k, val)

            # 注意:生成的SQL顺序和values顺序的对应关系
            sql = sql.where(model.id.isin(phg.next(id_lst)))
            await self.execute_sql(sql.get_sql(), phg)

        for i in when_complete:
            await i()

        return id_lst