The removal of global variables is necessary due to the new session handling, which reuses the sessions after calls to the database. The work to remove global variables can be done already when using the api and apy files; but it is often easier to remove them when you have the new plsql file. This because you then only sees the global variables that you have created.
There is no common rule for getting rid of the global variables and global constants. It’s a manual task. Please use this documentation as suggestions as to how this can be achieved. It is not intended as a step by step instruction that will work for each and every global variable. Redesign of the functionality will probably be required in order to get rid of some of the more tricky global variables.
The main cases are:
Below are some of the most common scenarios, plus a brief explanation of where to find the global variable and what approach needs to be done in order to get rid of it.
What | Solution | Remark |
---|---|---|
Global variable is declared in plsql file Private Declaration but never used in the plsql file | - Remove the global variable from the Private Declaration section | Easy |
Global variable is declared in plsql file Private Declaration and used in only one method | - Move
the global variable inside the method. - Remove the global variable from the Private Declaration section. |
Easy |
Global variable is declared in plsql file Private Declaration and used in more than one method | - Move
the package global variable inside the method or pass the method in the
function calls or procedure calls. - Very hard to say exactly what the best solution is here and investigation will be required to find the optimal solution. - Remove the global variable from the Private Declaration section. |
Tricky |
Global variable is declared in plsql file Public Declaration, but never used in the plsql file | - Check if it’s used
somewhere else in the system. As this global variable is declared in the
Public Declaration of the plsql file it could be used both in the client
and in another server file. - Remove the global variable after you handled the instances where it is used. |
Easy or tricky depending if it is used somewhere else or not, |
Global variable is declared in plsql file Public Declaration and used in the plsql file | - Check if it’s used somewhere else
in the system. As this global variable is declared in the
Public Declaration of the plsql file it could be used both in the client
and in another server file. - Remove the global variable after you handled the instances where it is used. |
Tricky |
Global Cursor is declared in the Public Declaration | - Check where it is used in IFS
Applications, both server and client code. - If the cursor is opened in one method and closed in another method, the code need to be re factored. - If the cursor is used in FOR loops or if it is open and closed in the same method, you can continue to use the global cursor. |
Easy or tricky depending on situation. |
Global Cursor is declared in the Private Declaration | - Check where it is used in the plsql
file - If the cursor is opened in one method and closed in another method, the code need to be re factored. - If the cursor is used in FOR loops or if it is open and closed in the same method, you can keep to cursor |
Easy in most cases. |
Here are the most common types of global variables and suggestions on how to remove them.
Type | Examples | Solution | Remark |
---|---|---|---|
Variable is of type INST_<Component>. |
inst_payled_ CONSTANT BOOLEAN :=
Dictionary_SYS.Component_Is_Installed('PAYLED'); inst_docman_ CONSTANT BOOLEAN := Dictionary_SYS.Component_Is_Installed('DOCMAN'); |
- Check where it
is used and the place(s) where it is used, we usually have dynamic code after it. - Change the dynamic code to condition compilation and instead of using the global package. variable, change it to use Component_<component_name>_SYS.<"component_name">. - See Conditional Compilation - Remove the global variable. |
Easy |
Variable is of type <LU-name>_INST_. |
act_api_ CONSTANT BOOLEAN :=
Transaction_SYS.Logical_Unit_Is_Installed('Activity'); activity_inst_ CONSTANT BOOLEAN := Dictionary_SYS.Logical_Unit_Is_Installed('Activity'); |
- Check where it
is used
and in the place(s) where it’s used, we usually have dynamic code after it. - Change the dynamic code to condition compilation and instead of using the global package variable, change it to use Component_<component_name>_SYS.<"component_name">. - See Conditional Compilation - Remove the global variable. |
Easy |
Variable is of type xxx_EXISTS or xxx_EXITS. |
proj_site_lu_exits_ CONSTANT BOOLEAN :=
Dictionary_SYS.Logical_Unit_Is_Installed('ProjectSite'); proj_lu_exits_ CONSTANT BOOLEAN := Dictionary_SYS.Logical_Unit_Is_Installed('Project'); |
- In many cases this is
used as in point 1 and 2 above and the same solution as for them should be
applied. - But it needs to be checked in
each instance as there can be exists_ or exits_ for other purposes as
well . |
Easy |
Variable is of type Function or Procedure but not a constant. |
purch_struct_ VARCHAR2(20) :=
Shop_Ord_Code_API.Get_Db_Value(2); do_rs_ BOOLEAN := Report_SYS.Should_Generate_Result_Set('&VIEW'); do_xml_ BOOLEAN := Report_SYS.Should_Generate_Xml('&VIEW');
|
- Check where it is used in the
plsql file and move the variable inside the methods or pass it between
methods. - Check the client as well. |
Tricky |
Variable is of type Function or Procedure but is a constant. |
G_NO_ACCESS_ CONSTANT VARCHAR2(10) :=
Gl_Security_Access_Type_API.Get_Db_Value(1); p_t_plus_calc_vat_ CONSTANT VARCHAR2(20) := Company_Invoice_Info_API.calc_out_; |
- Check where it is used in the
plsql file and move the variable inside the methods.
- Check the client as well. |
Tricky in most cases |
Variable is declared to get a value number or Boolean and is not a constant. | code_1_value_ VARCHAR2(20); g_tot_amount_ NUMBER DEFAULT 0.0; seq_no_error_ BOOLEAN := FALSE; xml_ CLOB; prev_id_country_ company_tab.country%TYPE |
- Check where it is used in the
plsql file and move the variable inside the methods or pass it
between methods. - Check the client as well - Remark that it can be used in one or several methods and can change value. - Remove the global variable |
Tricky |
There are some types of global variables that are allowed, as they are safe, or can be used in a way that can be handled safely.
Allowed Type | Examples |
---|---|
The global variable is of type literal, which has a pre-defined value | pc_code_part_ CONSTANT
VARCHAR2(1) := 'C' checkout_ CONSTANT NUMBER := 1 |
The global package variable is of type literal, which calls for a STD Method in Oracle | crlf_ CONSTANT VARCHAR2(2) := chr(13)||chr(10) |
The global variable is of type Micro_Cache | MICRO_CACHE_COMPANY_ MICRO_CACHE_TIME_ MICRO_CACHE_VALUE_ MICRO_CACHE_CURRENCY_CODE_ |
The global variable is of type xxx_separator, which calls for a string value | field_separator_ CONSTANT
VARCHAR2(1) := Client_SYS.field_separator_ text_separator_ CONSTANT VARCHAR2(1) := Client_SYS.text_separator_ record_separator_ CONSTANT VARCHAR2(1) := Client_SYS.record_separator_ group_separator_ CONSTANT VARCHAR2(1) := Client_SYS.Group_Separator_ date_format_ CONSTANT VARCHAR2(40) := Client_SYS.Date_Format_ |
The global variable is of type function call xxx_API.Db_yyy, which fetches a db value | db_picking_ CONSTANT
VARCHAR2(7) := Inventory_Location_Type_API.db_picking; db_floor_stock_ CONSTANT VARCHAR2(1) := Inventory_Location_Type_API.db_floor_stock; db_production_line_ CONSTANT VARCHAR2(13) := Inventory_Location_Type_API.db_production_line; |
The global cursor is used in a FOR loop or if the cursor is Open and Closed in the same method. |
Many of the global variables have been used to code dynamic dependencies towards other components, if that component is not installed. When disposing of the global variable the code should be changed to use conditional compilation instead of executing immediately or moving the global variable within that method. This is to catch existing errors at deploy time instead of runtime. Please read how this happens in Dynamic calls to optional components.
When you have a global variable that includes a dynamic call, then carry out the following:
Below is an example of dynamic code implementation, written in an old style:
IF inst_Intled_ THEN
stmt_ := 'BEGIN :il_hold_ := '; stmt_ := stmt_ || 'Internal_Hold_Voucher_Row_Api.Account_Exist_In_IL_Hold(:company, :code_part_value ); END;';
-- IFS_ASSERT_SAFE wapelk 220611
EXECUTE IMMEDIATE stmt_ using IN OUT il_hold_ ,IN remrec_.company,IN remrec_.code_part_value;
IF (il_hold_ = 'TRUE') THEN
Error_Sys.Record_General( lu_name_,'NOTALLOWEDDELETE: You cannot delete the account since it is used in wait table.');
END IF;
END IF;
IF inst_genled_ THEN
stmt_ := 'BEGIN Accounting_Structure_Item_API.Remove_Structure_Items(:company_, :code_part_, :code_part_value_); END;';
-- ifs_assert_safe gawilk 120219
EXECUTE IMMEDIATE stmt_ USING remrec_.company, remrec_.code_part, remrec_.code_part_value;
END IF;
Example after re write:
$IF Component_Intled_SYS.INSTALLED $THEN
il_hold_ := Internal_Hold_Voucher_Row_Api.Account_Exist_In_IL_Hold(remrec_.company, remrec_.code_part_value );
IF (il_hold_ = 'TRUE') THEN
Error_Sys.Record_General( lu_name_,'NOTALLOWEDDELETE: You cannot delete the account since it is used in the wait table.');
END IF;
$END
$IF Component_Intled_SYS.INSTALLED $THEN
Accounting_Structure_Item_API.Remove_Structure_Items(remrec_.company, remrec_.code_part, remrec_.code_part_value);
$END