def update(self, id, **kwargs): ret = Storage() if self.parent: ret.parent = self.parent.update(id,**kwargs) self._write_history(id) db = self.db splited_args = self._split_args(kwargs) # update own if splited_args['own_args']: ret.own = db(self.own.id==id).update(**splited_args['own_args']) # update opt opt_args = splited_args['opt_args'] if opt_args: for opt_tbl in opt_args: rows_to_update = opt_args[opt_tbl] if not rows_to_update: continue rows_to_update = isinstance(rows_to_update, (list, tuple)) and rows_to_update \ or (rows_to_update,) own_FK_name = opt_tbl._entopt.own_FK.name ret_opt = ret[opt_tbl._tablename] = Storage(upd_ids=[], del_ids=[], ins_ids=[]) for row in rows_to_update: row[own_FK_name] = id rec_id = row.get('id', None) or (opt_tbl._entopt.type=='one' and id) rec = opt_tbl(rec_id) if rec: # delete or update rec = rec.as_dict() if not rec: raise RuntimeError('option update err: '+ opt_tbl._tablename+'[%s]'%rec_id+' - not found') if rec[own_FK_name]!=id: raise RuntimeError('option update err: '+ opt_tbl._tablename+'[%s]'%rec_id+' - has alien FK') rec.update(row) if self.is_all_null(rec, ('id', own_FK_name)): db(opt_tbl._id==rec_id).delete() ret_opt.del_ids.append(rec_id) else: db(opt_tbl._id==rec_id).update(**rec) ret_opt.upd_ids.append(rec_id) elif not self.is_all_null(row, ('id', own_FK_name)): # insert ret_opt.ins_ids.append(opt_tbl.insert(**row)) return ret
def insert(self, **kwargs): ret = Storage() if self.parent: kwargs[self.parent.D_field.name] = self.D_value ret.parent = self.parent.insert(**kwargs) kwargs['id'] = ret.parent.own splited_args = self._split_args(kwargs) id = self.own.insert(**splited_args['own_args']) opt_args = splited_args['opt_args'] for opt_tbl in opt_args: rows_to_insert = opt_args[opt_tbl] rows_to_insert = isinstance(rows_to_insert, (list, tuple)) and rows_to_insert \ or (rows_to_insert,) own_FK_name = opt_tbl._entopt.own_FK.name ret[opt_tbl._tablename] = [] for row in rows_to_insert: if self.is_all_null(row,['id', own_FK_name]): continue row.pop('id', None) row[own_FK_name] = id ret[opt_tbl._tablename].append( opt_tbl.insert(**row) ) ret.own = id return ret
def update_many(self, q, del_insert = False, **kwargs): ret = Storage() if self.parent: ret.parent = self.parent.update_many(q, del_insert, **kwargs) self._write_history(q) db = self.db #del_insert = kwargs.pop('del_insert', None) pg_com = db.executesql pg_com('CREATE TEMP TABLE IF NOT EXISTS tmp_ids (id bigint primary key);') pg_com(' TRUNCATE tmp_ids;') # select ids into temp sel_str = db(q)._select(self.own._id) save_str = ' INSERT INTO tmp_ids (%s);'%sel_str[:-1] pg_com(save_str) splited_args = self._split_args(kwargs) # update own sel_ids = 'select tmp_ids.id from tmp_ids;' ret.own = db(self.own.id.belongs(sel_ids)).update(**splited_args['own_args']) # update opt opt_args = splited_args['opt_args'] for opt_tbl in opt_args: own_FK_name = opt_tbl._entopt.own_FK.name row_to_update = opt_args[opt_tbl] if opt_tbl._entopt.type == 'list': #if isinstance(row_to_update, (list, tuple)): if not del_insert: raise RuntimeError('Can\'t update list option \'%s\' by query, set del_insert=True'%opt_tbl._tablename) else: ids = db().select(db.tmp_ids.id) ret_del_ins = ret[opt_tbl._tablename] = Storage() ret_del_ins.deleted = db(opt_tbl._entopt.own_FK.belongs(sel_ids)).delete() ret_del_ins.inserted_ids = [] row_to_ins=[r for r in row_to_update if not self.is_all_null(r, [own_FK_name, 'id'])] for rid in ids: for r in row_to_ins: r.pop('id', None) r[own_FK_name] = rid.id ret_del_ins.inserted_ids.append(opt_tbl.insert(**r)) else: ret_upd_ins = ret[opt_tbl._tablename] = Storage() ret_upd_ins.updated = db(opt_tbl[own_FK_name].belongs(sel_ids)).update(**row_to_update) ret_upd_ins.inserted_ids=[] ret_upd_ins.deleted=[] if ret[opt_tbl._tablename] != db(db.tmp_ids).count(): #preform insert ids= db(opt_tbl[own_FK_name]==None).select(db.tmp_ids.id, left = opt_tbl.on(opt_tbl[own_FK_name]==db.tmp_ids.id)) for r in ids: row_to_update[own_FK_name] = r.id ret_upd_ins.inserted_ids.append(opt_tbl.insert(**row_to_update)) #delete nulls rows fld_lst= [f for f in opt_tbl if f is not opt_tbl._entopt.own_FK] q_to_del = (fld_lst[0]==None) | ((fld_lst[0]=='')) q_to_del=reduce( lambda q, f: q & ((f==None) | (f=='')) , fld_lst[1:] , q_to_del ) ret_upd_ins.deleted = db(q_to_del).delete() return ret