Introduction to subroutines
Subroutines are used to define business logic that is not used directly by the user interface but is only called by other business logic or by third party applications, be it through the OData API or a message protocol independent webservice. Subroutines can be for instance functions, stored procedures or services.
Creating a subroutine
menu Business Logic > Subroutines > tab Form
Different types of subroutines are available, depending on the application platform.
|Platform||Type||Description||Can be an API|
|SQL||CLR function||Common Language Runtime function||No|
|SQL||CLR procedure||Common Language Runtime procedure||No|
|SQL||DLL assembly||Assembly Library||No|
|DB2||External function||Function that references an external program||No|
|DB2||External procedure||Procedure that references an external program||No|
|SQL, DB2, Oracle||Function||SQL function||Yes|
|SQL, DB2, Oracle||Procedure||SQL stored procedure||Yes|
Depending on the selected subroutine, the following return values can be specified:
Scalar - The result is a single value. If you select this, the column Return scalar domain is displayed. A domain can be selected that determines the characteristics of the result value.
Table - The result is a table containing multiple rows. If this option is selected, the columns can be named in the Subroutine return columns tab. This will be displayed as the result in the table. These columns also refer to a domain.
The return values are not applicable for every program object.
Virtually every subroutine type has input parameters. These input parameters can be provided in the Subroutine parameters tab.
To view the object in the Code Overview screen, execute the task Go to object in Code overview . In the Code Overview, you can regenerate a program object's source code and execute it to the database. See also the Code overview guide.
Copy a subroutine
To make a copy of a subroutine:
menu Business logic > Subroutines > tab Settings
- Execute the Copy subroutine task.
- Enter a name for the copy in the field To subroutine.
- Select if you want to include Functionality assignments in the copy. If you deselect this option, the copied subroutine will not be assigned to any control procedure. Use this to create a bare object (the copied subroutine). Then, create a new control procedure, and assign the copied subroutine to it.
Copy a subroutine
Subroutine as API
Subroutines are generally used internally by the application and will not be accessible directly using Indicium. If a function or procedure has to be called by an external caller using Indicium, it can be marked as an API.
Operation-typed subroutines are always exposed as web services, not through Indicium but through a generated Java or C# SOAP service tier.
menu Business Logic > Subroutines > tab Form
Check the API box to publish the subroutine as an API by Indicium. Use API (legacy) to publish it by Indicium Legacy.
To submit a different API service name and parameter names: enter a Subroutine alias for subroutines and subroutine parameters. For example, if you don't want to use the Thinkwise naming convention (lowercase words separated by underscores) for your third party API.
Indicium will now expose the procedure or function as a web service.
It is possible to start and complete transactions manually in code. However, you can also run a procedure-based subroutine as an atomic transaction. This setting provides a generic solution with nested transaction support and proper error handling.
The Atomic transaction setting for new tasks or subroutines is by default enabled if:
- The model does not yet contain any tasks or subroutines.
- The atomic transaction option has been enabled in the majority of the existing tasks or subroutines. If not, the default value is disabled.
If Atomic transaction is enabled, data changes will be handled as follows:
- When the stored procedure uses a transaction, the data changes of each statement will be definitive once all statements within the task have run successfully. Errors will lead to a roll-back of the data changes made by earlier statements.
- A stored procedure that uses a transaction can be called by a trigger or another stored procedure that also uses a transaction. In that case, the data changes will be definitive once the caller finishes the transaction. Rolling back the transaction at any point will roll back all the nested transactions.
- When a stored procedure does not run in a transaction, data changes by each statement within the stored procedure are definitive the moment the individual statement has been executed (unless the caller opens a transaction).
To change the Atomic transaction setting:
Business logic > Subroutines > tab Settings > tab Subroutine
- Select or clear the Atomic transaction checkbox.
Not running a transaction is generally more performant since the database engine does not need to keep track of the data changes while the transaction is active. The data that is being tracked can also cause deadlocks as other transactions can be waiting to use this data.
However, not running in a transaction can cause data corruption, depending on how the code is written.
menu Business Logic > Subroutines > tab Subroutine options
Depending on the platform of the subroutine and the type of subroutine, various options are available to change its behavior.
|Platform||Subroutine type||Subroutine option||Description||Option values|
|SQL||CLR function||DLL Assembly||The ID of the DLL asssembly containing the CLR function.|
|SQL||CLR function||EXECUTE_AS||Specifies the user account that must execute the CLR function.|
|SQL||CLR function||RETURNS_NULL_ON_NULL_INPUT||Performance optimization that causes the function to return NULL when any of the parameters is null, without executing the function body.||- Yes|
|SQL||CLR procedure||EXECUTE_AS||Specifies the user account that must execute the CLR procedure.|
|SQL, Oracle||CLR procedure||DLL Assembly||The ID of the DLL asssembly containing the CLR procedure.|
|SQL, Oracle||DLL assembly||Assembly id||The ID of the DLL assembly.|
|SQL, Oracle||DLL assembly||DLL file location||The physical DLL file location as seen from the database server used to create the DLL assembly in the database.|
|SQL, Oracle||DLL assembly||Permission set||Specifies to what extent an assembly can access external system resources such as files, the network, environment variables, or the registry.||- SAFE|
|DB2||Function||DETERMINISTIC||Specifies whether the function returns the same results each time that the function is invoked with the same input arguments.|
|DB2||Function||MODIFIES SQL DATA||Specifies that the procedure can execute any SQL statement except statements that are not supported in procedures.|
|SQL||Function||EXECUTE_AS||Specifies the user account that must execute the subroutine. For example, SA specifies the system administrator user account.|
|SQL||Function||INLINE||Marks a scalar function as inlinable. The generated function header will no longer use user-defined datatypes. Instead, it will use the 'raw' datatypes of the domains. The script to create the function will use the INLINE = ON clause to force it to become inlinable. This feature can speed up queries that use the function. Note that there are restrictions to keep in mind when writing logic for an inlinable function.||- OFF|
|SQL||Function||RETURNS_NULL_ON_NULL_INPUT||Performance optimization that causes the function to return NULL when any of the parameters is null, without executing the function body.||- No|
|SQL||Function||SCHEMABINDING||Binds the function to the underlying objects. This may improve performance but causes the objects to become locked.||- No|
Example: using a subroutine option to mark a scalar function as inlinable