Skip to content

Removal of Global Variables

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.

Setup

  • Use Developer Studio
  • Run the report "Validate Implementation File" within Developer Studio, in order to obtain the list of illegal global variables and global constants.
    The "Validate Implementation File" is an RMB on the project node in Developer Studio.
  • When opening an implementation file in Developer Studio, you will get red markings in the file if you have an illegal global variable or illegal global constant.

Main Cases

The main cases are:

  • The global variable resides in the Private Declaration of the plsql file (in apy file, in code before IFSAPP9).
    • In this case you need only to search and change in the plsql file as the global variable is only used there.
  • The global variable resides in the Public Declaration of the plsql file (in api file, in code before IFSAPP9).
    • In this case you need to search the entire file tree (both client and plsql files) as the global variable can be used in other plsql files and in client, and then enable the necessary changes.
  • The global variable resides in rdf file
    • In this case you need only to search and change in the rdf file as the global variable is only used there.

Scenarios

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.

Types of global variable

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 .
- See Conditional Compilation
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.
- Remark that it can be used in one or several methods and can change value.
- Remove the global variable.
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.
- Remark that it can be used in one or several methods.
- Remove the global variable.
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

Allowed types of global variable

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

Conditional Compilation

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:

  • Rewrite from dynamic code to conditional compilation
  • Remove the global variable declaration
  • Remove the stmt_ declaration, which in most cases will not be used anymore
  • Observe that you might add $ELSE statement with NULL; if the conditional compilation if statement is the second or later if statement. Otherwise it will fail.

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, <br/>:code_part_value ); END;';<br/><br/>    -- IFS_ASSERT_SAFE wapelk 220611<br/><br/>    EXECUTE IMMEDIATE stmt_ using IN OUT il_hold_ ,IN remrec_.company,IN remrec_.code_part_value;<br/><br/>    IF (il_hold_ = 'TRUE') <br/>THEN<br/><br/>         Error_Sys.Record_General( lu_name_,'NOTALLOWEDDELETE: You cannot delete <br/>the account since it is used in wait table.');<br/><br/>    END IF;<br/><br/>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