Specifying Environments for MLE Modules

MLE environments are schema objects in the database. Their functionality and management methods are described.

MLE environments complement MLE modules and allow you to do the following:

  • Set language options to customize the JavaScript runtime in its execution context

  • Enable specific MLE modules to be imported

  • Manage name resolution and the import chain

Topics

Creating MLE Environments in the Database

The SQL DDL supports the creation of MLE environments.

Just like MLE modules, MLE environments are schema objects in the database, persisted in the data dictionary.

At a minimum, you must have the CREATE MLE MODULE privilege to create or replace an MLE environment in your own schema.

See Also:

Topics

Naming MLE Environments

Each JavaScript environment's name must be unique in the schema it is created in. Unless a fully qualified name is used, the current user's schema is used.

As with other schema object identifiers, the name is case-sensitive if enclosed in double quotation marks. If the enclosing quotation marks are omitted, the name is implicitly converted to uppercase.

MLE environments cannot contain import mappings that conflict with the names of the MLE built-in modules (mle-js-oracledb, mle-js-bindings, mle-js-plsqltypes, mle-js-fetch, mle-encode-base64, mle-js-encodings, and mle-js-plsql-ffi). If you attempt to add such a mapping using either the CREATE MLE ENV or ALTER MLE ENV DDL, the operation fails with an error.

Creating an Empty MLE Environment

The DDL statement CREATE MLE ENV can be used to create an MLE environment.

In its most basic form, an environment can be created empty as shown in the following snippet:

CREATE MLE ENV myEnv;

Subsequent calls to ALTER MLE ENV can be used to add properties to the environment.

Just like with MLE modules, it is possible to append the OR REPLACE clause to instruct the database to replace an existing MLE environment rather than throwing an error.

Furthermore, the IF NOT EXISTS clause can be used instead of the OR REPLACE clause to prevent the creation of a new MLE environment in the case that one already exists with the same name. In this case, the statement used to create the environment changes to the following:

CREATE MLE ENV IF NOT EXISTS myEnv;

Note:

The IF NOT EXISTS and OR REPLACE clauses are mutually exclusive.

You can optionally include the PURE keyword to indicate that any JavaScript code using the environment should be run in a restricted execution context that disallows access to the database state. PURE execution provides an extra layer of security by isolating certain code, such as third-party JavaScript libraries, from the database. Environments that are created using the PURE keyword can be referenced by MLE modules and when using DBMS_MLE for dynamic execution. The PURE keyword can be specified as follows:

CREATE OR REPLACE MLE ENV my_pure_env PURE;

See Also:

Modifying MLE Environments for information about editing existing environments

About Restricted Execution Contexts for information about the PURE keyword and restricted contexts

Oracle Database SQL Language Reference for the full syntax of CREATE MLE ENV

Creating an Environment as a Clone of an Existing Environment

If needed, a new environment can be created as a point-in-time copy of an existing environment.

The new environment inherits all settings from its source. Subsequent changes to the source are not propagated to the clone. A clone can be created as shown in the following statement:

CREATE MLE ENV MyEnvDuplicate CLONE MyEnv

Using MLE Environments for Import Resolution

It is possible to import functionality exported by one JavaScript module into another using the import statement.

The separation of code allows for finer control over changes and the ability to write more reusable code. Simplified code maintenance is another positive effect of this approach.

Only those identifiers marked with the export keyword are eligible for importing.

Modules attempting to import functionality from other modules stored in the database require MLE environments in order to perform name resolution. To create an MLE environment with that information, the IMPORTS clause must be used. Example 3-13 demonstrates how a mapping is created between the identifier po_module and JavaScript module PO_MODULE, created in Example 3-1.

Multiple imports can be provided as a comma-separated list. In Example 3-13, the first parameter in single quotation marks is known as the import name. The import name is used by another module's import statement. In this case, 'po_module' is the import name and refers to the module of the same name.

Note:

The import name does not have to match the module name. Any valid JavaScript identifier can be used. The closer the import name matches the module name it refers to, the easier it is to identify the link between the two.

The CREATE MLE ENV command fails if a module referenced in the IMPORTS clause does not exist or is not accessible to you.

Built-in JavaScript modules can be imported directly without having to specify additional MLE environments.

See Also:

Overview of Built-in JavaScript Modules for more information about built-in modules

Example 3-13 Map Identifier to JavaScript Module


CREATE OR REPLACE MLE ENV 
    po_env
IMPORTS (
    'po_module' MODULE PO_MODULE
);

Example 3-14 Import Module Functionality


CREATE OR REPLACE MLE MODULE import_example_module
LANGUAGE JAVASCRIPT AS
 
import * as po from "po_module";
/**
* use po_module's getValue() function to calculate the value of
* a purchase order. In later chapters, when discussing the MLE
* JavaScript SQL driver the hard-coded value used as the PO will
* be replaced by calls to the database
* @returns {number} the value of all line items in the purchase order
*/
export function purchaseOrderValue() {
 
    const purchaseOrder = {
        "PONumber": 1600,
        "Reference": "ABULL-20140421",
        "Requestor": "Alexis Bull",
        "User": "ABULL",
        "CostCenter": "A50",
        "ShippingInstructions": {
            "name": "Alexis Bull",
            "Address": {
                "street": "200 Sporting Green",
                "city": "South San Francisco",
                "state": "CA",
                "zipCode": 99236,
                "country": "United States of America"
            },
            "Phone": [
                {
                    "type": "Office",
                    "number": "909-555-7307"
                },
                {
                    "type": "Mobile",
                    "number": "415-555-1234"
                }
            ]
        },
        "Special Instructions": null,
        "AllowPartialShipment": true,
        "LineItems": [
            {
                "ItemNumber": 1,
                "Part": {
                    "Description": "One Magic Christmas",
                    "UnitPrice": 19.95,
                    "UPCCode": 13131092899
                },
                "Quantity": 9.0
            },
            {
                "ItemNumber": 2,
                "Part": {
                    "Description": "Lethal Weapon",
                    "UnitPrice": 19.95,
                    "UPCCode": 85391628927
                },
                "Quantity": 5.0
            }
        ]
    };
 
    return po.orderValue(purchaseOrder.LineItems);
}
/
The following call specification allows you to call the purchaseOrderValue function:

CREATE FUNCTION purchase_order_value
RETURN NUMBER AS
MLE MODULE import_example_module
ENV po_env
SIGNATURE 'purchaseOrderValue';
/

SELECT purchase_order_value;
/

Result:


PURCHASE_ORDER_VALUE
--------------------
               279.3

Providing Language Options

MLE allows the customization of JavaScript's runtime by setting language-specific options in MLE environments.

Any options specified in the MLE environment take precedence over the default settings.

Multiple language options can be provided as a comma-separated list of '<key>=<value>' strings. The following snippet demonstrates how to enforce JavaScript's strict mode.

CREATE MLE ENV MyEnvOpt
    LANGUAGE OPTIONS 'js.strict=true';

Changes made to the language options of an environment are not propagated to execution contexts that have already been created using the environment. For changes to take effect for existing contexts, the contexts need to be dropped and recreated.

Note:

White space characters are not allowed between the key, equal sign, and value.

Topics

JavaScript Language Options

A full list of JavaScript language options available to be used with MLE are included.

Table 3-1 JavaScript Language Options

Language Option Accepted Value Type Default Description
js.strict boolean false Enforce strict mode.
js.console boolean true Provide console global property.
js.polyglot-builtin boolean true Provide Polyglot global property.

Dropping MLE Environments

MLE environments that are no longer needed can be dropped using the DROP MLE ENV command.

The following snippet demonstrates a basic example of dropping an MLE module:

DROP MLE ENV myOldEnv;

As with MLE modules, the IF EXISTS clause prevents an error if the named MLE environment does not exist, as shown in the following snippet:

DROP MLE ENV IF EXISTS myOldEnv;

Modifying MLE Environments

Existing MLE environments can be modified using the ALTER MLE ENV command.

It is possible to modify language options and the imports clause.

Topics

Altering Language Options

You can modify language options provided to an MLE module.

Use the ALTER MLE ENV clause to modify language options, as shown in the following snippet:

ALTER MLE ENV MyEnvOpt
    SET LANGUAGE OPTIONS 'js.strict=false';

Modifying Module Imports

In the context of MLE module imports, the ALTER MLE ENV command allows you to add additional imports as well as modify and drop existing imports.

Imports not specified during an environment's creation can be added to existing MLE environments using the ADD IMPORTS clause. Import names, once defined, are static and must be dropped before they can be added as desired. Assuming you have run a new CREATE MLE DDL to replace IMPORT_EXAMPLE_MODULE from Example 3-1 with the module name IMPORT_EXAMPLE_MODULE_V2, the following statement will run successfully:


ALTER MLE ENV po_env 
ADD IMPORTS (
    'import_example' MODULE IMPORT_EXAMPLE_MODULE_V2
);

Any imports no longer needed can be dropped using the DROP IMPORTS clause:

ALTER MLE ENV po_env DROP IMPORTS('import_example');

The case of the import identifier must match that in the data dictionary's USER_MLE_ENV_IMPORTS view.

Dictionary Views Related to MLE JavaScript Environments

Details about MLE environments are available in these families of views: USER_MLE_ENVS and USER_MLE_ENV_IMPORTS.

In addition to the USER prefix, these views exist in all namespaces: CDB, DBA, ALL, and USER.

Topics

USER_MLE_ENVS

The USER_MLE_ENVS view lists all MLE environments available to you along with the defined language options.

For more information about *_MLE_ENVS, see Oracle Database Reference.

Example 3-15 List Available MLE Environments Using USER_MLE_ENVS

SELECT ENV_NAME, LANGUAGE_OPTIONS
FROM USER_MLE_ENVS
WHERE ENV_NAME='MYENVOPT'
/

Example SQL*Plus output:

ENV_OWNER            ENV_NAME   LANGUAGE_OPTIONS
-------------------- ---------- ----------------------
JSDEV01              MYENVOPT   js.strict=true

USER_MLE_ENV_IMPORTS

The [USER | ALL | DBA | CDB]_MLE_ENV_IMPORTS family of views lists imported modules.

MLE environments are the key enablers for resolving names of imported modules. Example 3-16 demonstrates a query against USER_MLE_ENV_IMPORTS to list IMPORT_NAME, MODULE_OWNER, and MODULE_NAME.

For more information about *_MLE_ENV_IMPORTS, see Oracle Database Reference

Example 3-16 List Module Import Information Using USER_MLE_ENV_IMPORTS

SELECT IMPORT_NAME, MODULE_OWNER, MODULE_NAME
    FROM USER_MLE_ENV_IMPORTS
    WHERE ENV_NAME='MYFACTORIALENV';
/

SQL*Plus output:

IMPORT_NAME            MODULE_OWNER              MODULE_NAME
---------------------- ------------------------- ------------------
FACTORIAL_MOD          DEVELOPER1                FACTORIAL_MOD