def _get_all_rel_tables(self, tb_id, result, tb_map, dep=0, index=0): """ 获取一张表的所有被依赖表 :param tb_id: :param result: :param dep: :param tb_map: 用于判断是否存在循环依赖,防止死循环 :param index: 被依赖表的索引,用于按照依赖关系排序,保证合表次序不会错乱 :return: """ if tb_id in tb_map: raise Exception("there is a cycle in the relation graph") tb_map[tb_id] = dep share_model = Share() shares = share_model.get({Share.TB_ID: tb_id}, (Share.SH_ID, )) sh_ids = [s[Share.SH_ID] for s in shares] del share_model tb_ids = [tb_id] + sh_ids rel_tables = self.get_rel_tables(tb_ids) for rel_tb in rel_tables: rel_tb['id'] = index index += 1 dep += 1 for rel_table in rel_tables: rel_tb_id = rel_table[Relation.TB_ID] result.append(rel_table) index = self._get_all_rel_tables(rel_tb_id, result, tb_map, dep, index) tb_map.pop(tb_id) return index
def add_with_share(self, params): field_id = self.create(params) tb_or_share_id = params[self.TB_ID] share_model = Share() shares = share_model.get({Share.TB_ID: tb_or_share_id}, (Share.SH_ID, Share.COL_FILTER)) for share in shares: col_filter = json.loads(share[Share.COL_FILTER]) col_filter.append(field_id)
def update(self, tb_id, params, update_share_version=True, is_del=False): if TB.VERSION in params and update_share_version: # 更新此表依赖的分享表的version share_model = Share() shares = share_model.get( {Share.TB_ID: tb_id}, (Share.SH_ID, Share.VERSION, Share.ROW_FILTER, Share.DEP_ID)) if shares: cond = (VField.FIELD_ID, VField.TITLE, VField.AGGREGATOR) table_vfield = VField().get( { VField.TB_ID: tb_id, VField.FLAG: VField.TABLE_VFIELD_FLAG }, cond) tb_info = self.get_one({TB.TB_ID: tb_id}, (TB.STORAGE_ID, )) storage_id = tb_info[TB.STORAGE_ID] # todo: 这里依赖mobius实现的不太好 mobius = Mobius() for share in shares: share[Share.VERSION] = 0 if share[ Share.VERSION] is None else share[Share.VERSION] update_info = {Share.VERSION: share[Share.VERSION] + 1} # 更新分享表的数据条数 if share[Share. ROW_FILTER] == '[]' and not share[Share.DEP_ID]: if TB.DATA_COUNT in params: update_info[Share.DATA_COUNT] = params[ TB.DATA_COUNT] else: if TB.DATA_COUNT in params and params[ TB.DATA_COUNT] == 0: update_info[Share.DATA_COUNT] = 0 else: dep_list = [share] self.find_parent_sh(shares, share[Share.SH_ID], dep_list) row_filter = [] for sh in dep_list: row_filter += json.loads(sh[Share.ROW_FILTER]) expand_filter = expand_vfield( row_filter, table_vfield) where = ' and '.join(expand_filter) if not expand_filter and TB.DATA_COUNT in params: update_info[Share.DATA_COUNT] = params[ TB.DATA_COUNT] else: try: count_data = mobius.query( 'select count(1) as count from %s where %s' % (storage_id, where)) update_info[Share.DATA_COUNT] = count_data[ 'data'][0][0] except Exception as e: self.logger.error(e) share_model.update(share[Share.SH_ID], update_info) return self._update({TB.TB_ID: tb_id, 'is_del': is_del}, params)
def get_cascade_update_plan(self, tb_id_list=[]): """ 此接口可以接收多个tb_id作为参数,根据级联更新关系给出一个执行级联更新的tb_id顺序 :param tb_id_list: :return: 区别于get_all_rel_tables,此函数返回数列返回已经是排好序并去重后的结果 """ if not tb_id_list: return [] return_list = [] # 去除源tb_list对应的所有分配表 share_model = Share() shares = share_model.get({Share.TB_ID: tb_id_list}, (Share.SH_ID, )) sh_ids = [s[Share.SH_ID] for s in shares] tb_id_list += sh_ids # 纪录第一层的所有tb_id, 这些tb_id是不用加入执行计划的,因为他们的类型不是view origin_tb_id_list = copy.deepcopy(tb_id_list) # 广度遍历并去重,如果有依赖重复出线的情况下,取更靠后的任务以保证任务依赖的正确 while tb_id_list: # 第一层的tb是不用加入到结果的,因为不是gen类型的 for tb_id in tb_id_list: if tb_id in return_list: return_list.remove(tb_id) return_list.append(tb_id) share_tb_list = [ share[Share.SH_ID] for share in share_model.get( {Share.TB_ID: tb_id_list}, [Share.SH_ID]) ] tb_ids = list(set(tb_id_list + share_tb_list)) tb_id_list = list( set([ tmp_tb[Relation.TB_ID] for tmp_tb in self.get_rel_tables(tb_ids) ])) return_list = [r for r in return_list if r not in origin_tb_id_list] return return_list
def delete_with_share(self, tb_id, field_id): """ 删除字段,并从分配表中也将分配的字段移除 """ result = self._delete({Field.TB_ID: tb_id, Field.FIELD_ID: field_id}) if result: share_model = Share() shares = share_model.get({Share.TB_ID: tb_id}, (Share.SH_ID, Share.COL_FILTER)) for share_info in shares: share_info[Share.COL_FILTER] = json.loads( share_info[Share.COL_FILTER]) if field_id in share_info[Share.COL_FILTER]: share_info[Share.COL_FILTER].remove(field_id) share_model._update( {Share.SH_ID: share_info[Share.SH_ID]}, {Share.COL_FILTER: share_info[Share.COL_FILTER]}) return result
def add_with_share(self, params): required_params = (Field.NAME, Field.TYPE) for rp in required_params: if rp not in params: self.logger.warn('缺失字段:%s' % rp) return None if not params.get(Field.FIELD_ID, ''): params[Field.FIELD_ID] = create_field_id() if params[Field.TYPE] == Field.NULL_DATA_TYPE: params[Field.TYPE] = Field.STRING_TYPE fid = params[Field.FIELD_ID] if self._create(params): tb_id = params[Field.TB_ID] share_model = Share() shares = share_model.get({Share.TB_ID: tb_id}, (Share.SH_ID, Share.COL_FILTER)) for share in shares: col_filter = json.loads(share[Share.COL_FILTER]) col_filter.append(fid) share_model.update(share[Share.SH_ID], {Share.COL_FILTER: col_filter}) return fid else: return None