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
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