Oracle Form - 文件夹数据块点击排序后只剩一行显示(已解决)

  • 问题现象

最近在工作中遇到一个诡异的问题:背景是我开发了一个主从结构的表单,而且主从块都使用了文件夹功能;问题现象是,在查询出结果后,点击主块的标题执行排序,主块突然变成了只显示一行

查看排序前后主块的last query发现异样:

图一为排序前主块last query的WHERE条件,year=2019是块属性里面设置的Where子句,year between 2017 and 2022是我为了方便观察在pre-query触发器里加的查询条件

图二为排序后,可以看到year=2019这一句没变,但是后一句变成了delivery_plan_header_id=34179,就是它直接导致主块只变成一行了,因为这个字段是主键

补充一句:这个现象只在查询后主块第一行没有关联的从块数据时发生

  • 检查过程

经过检查APPFLDR库,我找到了问题原因

首先简述一下排序的实现机制:1、安排好排序字段,顺序,升降序;2、给块设置一个临时的Default Where属性;3、执行查询;4、将块的Default Where属性复原

(参见APPFLDR库文件过程app_folder_drag_and_drop)

这里的第二步我分析其目的就是为了重新执行的查询条件和排序前执行的最后一次查询保持一致

这里设置的临时Default Where属性其内容为:

app_folder.base_where_clause || ' AND -1=-1 AND ' ||
app_folder.pending_where_clause || ' AND -2=-2'

在这里可以看到上图二中标志性的-1=-1和-2=-2,同时也推断出delivery_plan_header_id=34179即是当时app_folder.pending_where_clause的内容

进一步查看发现,这个pending_where_clause是在app_folder_ext_whr_cls过程中做初始赋值的:内容来源于system.last_query,从中截取WHERE到ORDER BY中间的内容

并且该过程还会将这个内容放入记录组folder_master_props.pending_where_clause里与当前块进行绑定

最后还会将一个全局变量global.folder_where_extracted标记为TRUE

这个变量大有来头:

1、在app_folder.event('PRE-QUERY')中,会直接令其为FALSE

2、在app_folder.event('POST-QUERY')中,会判断当它是FALSE时,执行app_folder_ext_whr_cls

3、app_folder.event('KEY-EXEQRY')中,只做了两件事:execute_query,和判断global.folder_where_extracted为FALSE时,执行app_folder_ext_whr_cls

另外,我又在app_folder.event('PRE-BLOCK')中发现,它调用的app_folder_get_instance_values过程,会用system.trigger_name去匹配出folder_master_props.pending_where_clause的内容存放至app_folder.pending_where_clause

至此问题就讲得通了

  • 问题原因

对于一个独立的文件夹数据块来说,执行查询时触发器的执行顺序是:

KEY-EXEQRY

        PRE-QUERY

        POST-QUERY

KEY-EXEQRY

这里没有对齐的原因是PRE-QUERY是从KEY-EXEQRY中断去执行的,PRE-QUERY只执行一次,POST-QUERY在每加载出一行记录后各执行一次,最后回到KEY-EXEQRY来

而如果这个数据块同时又是一个主数据块,它在自己的最后一行加载出来,执行一次POST-QUERY后,便会回到第一条记录,再跳到从块上执行关联查询

这时先触发主块的POST-BLOCK,接下来依次是从块的PRE-BLOCK、PRE-QUERY、POST-QUERY、POST-BLOCK,再又回到主块,触发PRE-BLOCK,中断结束,继续KEY-EXEQRY触发器

问题就发生在这个过程中:当从块没有数据时,其POST-QUERY就没有执行;而它的PRE-QUERY已将全局变量global.folder_where_extracted赋值为FALSE了,此时回到主块的KEY-EXEQRY,正是执行完execute_query,该判断这个参数的时候了,程序发现它是FALSE,当即执行app_folder_ext_whr_cls,然而此时的system.last_query是时方才从块的last query,结果就是张冠李戴了

前图二中的delivery_plan_header_id正是设置的主从块关系条件

  • 解决方法

方法一:主块不使用app_folder.event('KEY-EXEQRY')作为KEY-EXEQRY触发器,或者干脆不增加KEY-EXEQRY触发器

方法二:客制化app_folder.event('PRE-BLOCK'),即在取出app_folder.pending_where_clause内容后,举手之劳把global.folder_where_extracted赋值为TRUE

附程序单元:

1)程序包规格

PACKAGE bhsc_folder IS
  procedure event(trigger_name varchar2);
END;

2)程序包主体

PACKAGE BODY bhsc_folder IS
	PROCEDURE my_folder_get_instance_values (target_block varchar2) IS
	--
	-- Sets pointers and package globals for the proper folder block
	--
	  block_name      VARCHAR2(30);
	  function_mask   VARCHAR2(18);
	  item_name       VARCHAR2(30);
	  item_id         ITEM;
	  item_width      NUMBER;
	  item_prompt     VARCHAR2(80); 
	  item_x          NUMBER := null;
	  item_y          NUMBER := null;
	  folder_item_id  ITEM;
	  dummy           groupcolumn; --dummy colid to allow creation of the tab order column
	  pointers_set    BOOLEAN := FALSE;
	  rg_id 	  recordgroup;
	  rg_col_id       groupcolumn; 
	  errcode         NUMBER;
	  curr_block_id   BLOCK;
	BEGIN
	  app_folder_frd_stmt('Entering app_folder_get_instance_values. Target_block is '||target_block);
	  app_folder.master_props_id := find_group('folder_master_props');
	  if id_null(app_folder.master_props_id) then 
	    app_folder_set_static_handles;
	  end if;
	  
	  -- Check to see if this block exists in the master_props record group.  
	  -- If not, do nothing.
	  --
	  if (get_group_record_number('folder_master_props.folder_block', target_block)=0) then 
	    return;
	  end if;
	
	  -- 
	  -- Get the current slot in master properties, and the current object name, 
	  -- so that we can use them to check for a default folder
	  -- 
	  app_folder.current_slot := get_group_record_number('folder_master_props.folder_block', target_block);
	  if (app_folder.current_slot = 0) then 
	    message('FOLDER ERROR: Block not defined as folder block: ' || target_block);
	    for i in 1..get_group_row_count(app_folder.master_props_id) loop
	      message('row ' || to_char(i) || ': ' || get_group_char_cell('folder_master_props.prompt_block', i));
	    end loop;
	    return;
	  end if;
	
	  app_folder.curr_object :=
	    get_group_char_cell('folder_master_props.curr_object', app_folder.current_slot);  
	
	  --
	  -- Check to see if master/active record groups have already been created.  If not, 
	  -- check for a default folder, then create and populate the record groups.
	  -- 
	  app_folder.master_list_id := find_group('folderm_'||target_block);
	  if id_null(app_folder.master_list_id) then
	    --
	    -- Get the default folder id if there is one
	    -- 
	    app_folder.default_folder_id := app_folder_get_default_id; 
	    set_group_number_cell('folder_master_props.default_folder_id', app_folder.current_slot, app_folder.default_folder_id);
	    -- 
	    -- Call app_folder_create_groups to create and populate 
	    -- the master and active lists for this block
	    --
	    app_folder_create_groups(target_block);
	    pointers_set := TRUE;
	  end if;
	
	  if app_folder.folder_block != target_block then
	    block_name := target_block;
	    app_folder.folder_block := block_name;
	    app_folder.folder_block_id := find_block(block_name);
	    app_folder.folder_window := get_group_char_cell('folder_master_props.folder_window', app_folder.current_slot);
	    app_folder.folder_window_id := find_window(app_folder.folder_window);
	    app_folder.folder_canvas :=
	      get_group_char_cell('folder_master_props.folder_canvas', app_folder.current_slot);
	    app_folder.folder_tab_canvas :=
	      get_group_char_cell('folder_master_props.folder_tab_canvas', app_folder.current_slot);
	    app_folder.folder_content_canvas :=
	      get_group_char_cell('folder_master_props.folder_content_canvas', app_folder.current_slot);
	    app_folder.folder_fixed_canvas :=
	      get_group_char_cell('folder_master_props.folder_fixed_canvas', app_folder.current_slot);
	    app_folder.prompt_block := 
	      get_group_char_cell('folder_master_props.prompt_block', app_folder.current_slot);
	    app_folder.total_block := 
	      get_group_char_cell('folder_master_props.total_block', app_folder.current_slot);
	    app_folder.total_fields :=
	      get_group_number_cell('folder_master_props.total_fields', app_folder.current_slot);
	    app_folder.base_records_displayed :=
	      get_group_number_cell('folder_master_props.base_records_displayed', app_folder.current_slot);
	    app_folder.base_order_by := 
	      get_group_char_cell('folder_master_props.base_order_by', app_folder.current_slot);
	    app_folder.base_where_clause := 
	      get_group_char_cell('folder_master_props.base_where_clause', app_folder.current_slot);
	    --fnd_message.debug('Setting damage flag in GIV');
	    app_folder.damage_flag := 
	      (get_group_char_cell('folder_master_props.damage_flag', app_folder.current_slot) = 'Y');
	    app_folder.instantiated := 
	      (get_group_char_cell('folder_master_props.instantiated', app_folder.current_slot) = 'Y');
	    app_folder.tab_sorted := 
	      (get_group_char_cell('folder_master_props.tab_sorted', app_folder.current_slot) = 'Y');
	    app_folder.cut_column_flag := 
	      get_group_char_cell('folder_master_props.cut_column_flag', app_folder.current_slot);
	    app_folder.curr_folder_name := 
	      get_group_char_cell('folder_master_props.curr_folder_name', app_folder.current_slot);
	    app_folder.curr_folder_id :=
	      get_group_number_cell('folder_master_props.curr_folder_id', app_folder.current_slot);
	    app_folder.curr_autoquery_flag :=
	      get_group_char_cell('folder_master_props.curr_autoquery_flag', app_folder.current_slot);
	    app_folder.curr_owner_id :=          
	      get_group_number_cell('folder_master_props.curr_owner_id', app_folder.current_slot);
	    app_folder.curr_public_flag :=
	      get_group_char_cell('folder_master_props.curr_public_flag', app_folder.current_slot);
	    app_folder.curr_default_flag :=
	      get_group_char_cell('folder_master_props.curr_default_flag', app_folder.current_slot);
	    app_folder.curr_where_clause :=
	      get_group_char_cell('folder_master_props.curr_where_clause', app_folder.current_slot);
	    --
	    -- Moving this call to beginning of procedure, since we need the object name to 
	    -- determine whether the user has a default. 
	    --
	    --app_folder.curr_object :=
	      --get_group_char_cell('folder_master_props.curr_object', app_folder.current_slot);  
	    app_folder.pending_where_clause :=
	      get_group_char_cell('folder_master_props.pending_where_clause', app_folder.current_slot);
	    copy('TRUE', 'global.folder_query_extracted'); --added by yusuf 19-sept-2022
	    app_folder.developer_folder_id := 
	      get_group_number_cell('folder_master_props.developer_folder_id', app_folder.current_slot);
	    --
	    -- Set the master and active record group pointers if not just created.
	    --
	    if not pointers_set then 
	      -- app_folder.master_list_id was set at beginning of routine.
	      -- app_folder.master_list_id := find_group('folderm_'||block_name);
	      app_folder.master_name_id := find_column('folderm_'||block_name||'.name');  
	      app_folder.master_prompt_id := find_column('folderm_'||block_name||'.prompt'); 
	      --app_folder.master_active_flag_id := find_column('folderm_'||block_name||'.active_flag'); 
	      app_folder.master_width_id := find_column('folderm_'||block_name||'.width');
	      app_folder.master_allow_cut_flag_id := find_column('folderm_'||block_name||'.allow_cut_flag');
	      app_folder.master_rows := get_group_row_count(app_folder.master_list_id);
	      --
	      app_folder.active_list_id := find_group('foldera_'||block_name);
	      app_folder.active_name_id := find_column('foldera_'||block_name||'.name');  
	      app_folder.active_prompt_id := find_column('foldera_'||block_name||'.prompt'); 
	      app_folder.active_width_id := find_column('foldera_'||block_name||'.width');
	      app_folder.active_x_pos_id := find_column('foldera_'||block_name||'.x_pos');
	      app_folder.active_y_pos_id := find_column('foldera_'||block_name||'.y_pos');
	      app_folder.active_rows := get_group_row_count(app_folder.active_list_id);
	      -- 
	      -- Also reset default_folder_id
	      -- 
	      app_folder.default_folder_id := get_group_number_cell('folder_master_props.default_folder_id', app_folder.current_slot);
	    end if;
	    --
	    -- Set the function allowed flags from the function mask
	    --
	    function_mask := 
	      get_group_char_cell('folder_master_props.allowed_functions', app_folder.current_slot);  
	    app_folder.autoquery_allowed := (instr(function_mask, 'A') != 0);
	    app_folder.public_allowed    := (instr(function_mask, 'B') != 0);
	    app_folder.default_allowed   := (instr(function_mask, 'C') != 0);
	    app_folder.orderby_allowed := (instr(function_mask, 'D') != 0);
	    app_folder.open_allowed := (instr(function_mask, 'E') != 0);
	    app_folder.tools_allowed := (instr(function_mask, 'F') != 0);
	    app_folder.new_allowed := (instr(function_mask, 'G') != 0);
	    app_folder.save_allowed := (instr(function_mask, 'H') != 0);
	    app_folder.delete_allowed := (instr(function_mask, 'I') != 0);
	    app_folder.add_allowed := (instr(function_mask, 'J') != 0);
	    app_folder.cut_allowed := (instr(function_mask, 'K') != 0);
	    app_folder.swap_allowed := (instr(function_mask, 'L') != 0);
	    app_folder.bigger_allowed := (instr(function_mask, 'M') != 0);
	    app_folder.smaller_allowed := (instr(function_mask, 'N') != 0);
	    app_folder.autosize_allowed := (instr(function_mask, 'O') != 0);
	    app_folder.prompt_allowed := (instr(function_mask, 'P') != 0);
	    app_folder.contents_allowed := (instr(function_mask, 'Q') != 0);
	    app_folder.reset_allowed := (instr(function_mask, 'R') != 0);
	    --
	  end if;
	  app_folder_frd_stmt('Completed app_folder_get_instance_values.');
	END my_folder_get_instance_values;
  
  
  procedure event(trigger_name varchar2) is
  
  begin
  	if upper(trigger_name) = 'PRE-BLOCK' THEN
  	  my_folder_get_instance_values(name_in('system.trigger_block'));
  	ELSE
  	  app_folder_fldr_handler(trigger_name);
  	end if;
  end;
  
END;

3)触发器

bhsc_folder.event('PRE-BLOCK');

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值