Managing WebAssembly Modules in the Database
SQL allows the creation of MLE WebAssembly (Wasm) modules as schema objects, assuming the necessary privileges are in place.
At a minimum, you need the CREATE MLE MODULE privilege to create or replace an MLE module in your own schema. Without their accompanying JavaScript bindings, Wasm modules cannot be used. It is through the use of the bindings that Wasm is exposed to JavaScript and SQL or PL/SQL.
See Also:
-
System and Object Privileges Required for Working with JavaScript in MLE for more information about MLE-specific privileges
-
Oracle AI Database Security Guide for more details about privileges and roles in Oracle AI Database
Naming WebAssembly Modules
Each new WebAssembly (Wasm) module name must be unique in the schema that 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 module name is case-sensitive if enclosed in double quotation marks. If the enclosing quotation marks are omitted, the name is implicitly converted to uppercase.
When choosing a unique name, note that MLE objects share the namespace with tables, views, materialized views, sequences, private synonyms, PL/SQL packages, functions, procedures, and cache groups.
Creating WebAssembly Modules in the Database
WebAssembly (Wasm) modules are created in the database using the CREATE MLE MODULE DDL statement, specifying name and binary source of the MLE module. Unlike JavaScript modules, Wasm modules must be provided in binary format, therefore requiring the USING BFILE or USING BLOB clause.
Some Wasm modules ship as hybrid JavaScript/Wasm modules, with the bindings provided in clear text with the Wasm module base64 decoded in-line. These do not need to be created as Wasm modules and should instead be created as JavaScript modules.
Note that Wasm modules cannot be invoked independently of their JavaScript bindings. Creating a Wasm module always implies a second call to create an MLE JavaScript module.
As soon as an MLE module has been created, it is persisted in the database dictionary.
See Also:
-
Oracle AI Database SQL Language Reference for the complete
CREATE MLE MODULEsyntax -
Oracle AI Database Development Guide for information about using the
IF[NOT]EXISTSsyntax
Example: Creating a WebAssembly Module in the Database
This example demonstrates the creation of an MLE Wasm module. It assumes that a directory named wasm_module exists and the user has read access to it. In this example, the popular Photon image manipulation library (written in Rust) is made available to developers to manipulate images programmatically.
--load the JavaScript bindings
CREATE OR REPLACE MLE MODULE photon
LANGUAGE JAVASCRIPT
USING BFILE(wasm_dir, 'photon_rs.js');
/
--create the actual Wasm module
CREATE OR REPLACE MLE MODULE photon_wasm
LANGUAGE WASM
VERSION '0.3.3'
USING BFILE(wasm_dir, 'photon_rs_bg.wasm');
/
With the Wasm module and its JavaScript bindings in place, you can use Photon in your code:
CREATE OR REPLACE MLE MODULE photon_demo
LANGUAGE JAVASCRIPT AS
import source photonWasm from "photon_wasm";
import * as photon from "photon";
/**
* Resizes a stored photo to 50% of its original dimensions.
*
* Initializes the Photon WebAssembly module, retrieves the source image from
* the 'PHOTOS' table, resizes it, and stores the resulting bytes in the
* 'OUTPUT' column. The update also records the current database user and
* timestamp.
*
* @async
* @param {number} id - Unique identifier of the photo to resize.
* @returns {Promise<void>} Resolves after the resized image has been stored.
* @throws {Error} If no photo exists with the supplied ID.
* @throws {Error} If the database update does not affect exactly one row.
* @throws {Error} Propagates errors from WebAssembly initialization, image
* decoding or resizing, and database operations.
*/
export async function resizePhoto(id) {
await photon.default({
module_or_path: photonWasm
})
// load the photo as a UINT8Array (not shown), then process it in Photon
const inputImage = photon.PhotonImage.new_from_byteslice(result.rows[0].INPUT);
// more processing
}
/