diff --git a/docs/install-js-lang.md b/docs/install-js-lang.md new file mode 100644 index 00000000000..def45c33bc9 --- /dev/null +++ b/docs/install-js-lang.md @@ -0,0 +1,15 @@ +# Install js_lang component + +The `plugin_dir` system variable defines the component library location. If needed, at server startup, set the `plugin_dir` variable. + +To install the `js_lang` component, run the following command: + +```{.bash data-prompt="mysql>"} +mysql> INSTALL COMPONENT 'file://component_js_lang'; +``` + +If you uninstall the component, you may need to restart the server before a reinstall. + +When you install `component_js_lang`, you get a new global privilege called `CREATE_JS_ROUTINE`. This privilege lets you create JS routines within the database. + +Find more information in [INSTALL COMPONENT](install-component.md). \ No newline at end of file diff --git a/docs/js-lang-overview.md b/docs/js-lang-overview.md new file mode 100644 index 00000000000..edecdf8b327 --- /dev/null +++ b/docs/js-lang-overview.md @@ -0,0 +1,64 @@ +# JS language support overview + +Creating stored procedures in JavaScript within a MySQL-compatible database offers a flexible and efficient way to handle complex data processing. It boosts performance and makes the development process easier for those familiar with JavaScript. + +| **Advantage** | **Details** | +|---|---| +| **Developer Benefits** | Most developers know JavaScript well and can start writing procedures quickly. You process complex data like JSON and strings using familiar JavaScript methods. Developers use their existing JavaScript skills to write database code faster. | +| **Performance Benefits** | Process your data directly in the database instead of moving it around. Network traffic decreases when data stays in the database. | +| **Code and Tools** | Use JavaScript's built-in functions for data tasks. Connect with JavaScript libraries and tools you already use. Write procedures using modern JavaScript features. | +| **Security Benefits** | Keep business rules inside stored procedures. Control database access through procedures. Protect your data by limiting direct table access. | + +## Limitations + +The JS procedure parameters cannot be [JS reserved words](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words) and must be [legal JS identifiers](https://www.capscode.in/blog/valid-identifier-in-js). + +Our implementation offers the same level of JS support as the V8 engine inside the context of a database engine. You can check out the details at [v8.dev/docs](https://v8.dev/docs) and [tc39.es/ecma262](https://v8.dev/docs). You can access to standard operators, data types, objects (like Math), and functions defined in the ECMAScript standard. You do not have access to node.js or a browser. + +Within a typical database environment, direct access to external files (like reading or writing files on the server's file system) and DOM objects (which are browser-specific) is restricted. Our implementation adheres to a trusted external routine language policy, ensuring that routines cannot perform operations beyond what is normally possible for database users. Consequently, file or network I/O operations are not supported within our routines. + +Our system supports asynchronous JavaScript (JS) code, but it doesn’t work well for database routines. Since everything runs on the same thread and there’s nothing to wait for asynchronously, using asynchronous code is unnecessary and not recommended. + +We always run JS code in strict mode, and you cannot disable or change this setting. + +## Converting data types to JS + +SQL and JS use different data types, so our implementation converts values when passing SQL parameters to JS and back. The following rules explain how these conversions work: + +SQL `NULL` values are converted to JS `null` values. + +| Source SQL data type | Target JS data type | +|---|---| +| BOOLEAN, TINYINT, SHORTINT, MEDIUMINT, INT | Number | +| BIGINT | Number for values [-2^53-1, 2^53-1], BigInt object otherwise | +| DECIMAL | String | +| FLOAT, DOUBLE | Number | +| BIT(k) | Number for k ≤ 53, BigInt for k > 53 | +| TIME, DATE, TIMESTAMP, DATETIME | String | +| YEAR | Number | +| CHAR, VARCHAR, TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT | String. Fails if length exceeds 2^29 - 24. | +| BINARY, VARBINARY, TINYBLOB, BLOB, MEDIUMBLOB, LONGBLOB | DataView | +| ENUM, SET | String | +| GEOMETRY and other spatial types | DataView | +| JSON | Object | + +When the data converts to a JS string, it automatically changes from the SQL parameter’s character set to `utf8mb4`, which JS uses. + +## Converting data types to SQL + +The target SQL data type defines how the system converts values. The system typically converts a JS value to one of the basic types, such as string, integer, or double, depending on the SQL data type. After the conversion, the system stores the result in the SQL parameter or return value. This step can fail if the value is too large or has an incorrect format, which will cause an error. During the process, JS strings automatically convert from `utf8mb4` to the character set of the SQL parameter. + +JS `null` and `undefined` values always convert to SQL `NULL` values for the target SQL type. + +| Target SQL data type | Rules for converting JS value | +|---|---| +| BOOLEAN, TINYINT, SHORTINT, MEDIUMINT, INT, BIGINT | JS integer values are stored as integers in the SQL parameter. BigInt values are also stored as integers. All other JS values, including non-integer Numbers, are converted to strings and stored in the SQL parameter. | +| DECIMAL | The system converts the JS value to a string and stores the string in the SQL parameter. | +| FLOAT, DOUBLE | SQL stores JS Numbers as doubles (floating-point numbers). SQL converts other JS values to strings and stores the result in a SQL parameter. | +| BIT | JS BigInt values store as integers in SQL parameters. Other JS values convert to Numbers, and the result is stored in SQL parameters. JS values that cannot convert to Numbers cause an error. | +| TIME, DATE, TIMESTAMP, DATETIME | The JS value converts to a string, and the string stores in the SQL parameter. | +| CHAR, VARCHAR, TINYTEXT, TEXT, MEDIUMTEXT, ENUM | The JS value converts to a string, and the result stores in the SQL parameter. If needed, the charset converts during the process. | +| BINARY, VARBINARY, TINYBLOB, BLOB, MEDIUMBLOB, LONGBLOB | Binary data from JS ArrayBufferView and ArrayBuffer objects is directly stored in the SQL parameter. For other JS values, the value is converted to a string and stored in the SQL parameter. | +| SET | JS integer values are stored as integers in the SQL parameter. Non-integer Number values are stored as doubles (floating-point values). BigInt values are stored as integers. All other JS values are converted to strings and stored in the SQL parameter, with charset conversion if needed. | +| GEOMETRY | Binary data from JS ArrayBufferView or ArrayBuffer objects is stored as is in the SQL parameter, assuming the data represents a valid SQL GEOMETRY value. For other JS values, an error occurs. | +| JSON | JS values are converted into a JSON string using JSON.stringify(), and the result is stored in the SQL parameter. | \ No newline at end of file diff --git a/docs/js-lang-privileges.md b/docs/js-lang-privileges.md new file mode 100644 index 00000000000..f4cdb534e86 --- /dev/null +++ b/docs/js-lang-privileges.md @@ -0,0 +1,15 @@ +# JavaScript routine support + +Privileges control what users can do. You use them to give specific permissions to different users. This ability helps you keep your data secure by only allowing authorized users to access and change information in the database. + +## Privileges + +To create routines, you must have the global dynamic `CREATE_JS_ROUTINE` privilege in addtion to the standard `CREATE ROUTINE` privilege. + +```{.bash data-prompt="mysql>"} +mysql> GRANT CREATE_JS_ROUTINE ON *.* TO user1@localhost; +``` + +If a user can create routines and has the `CREATE_JS_ROUTINE` privilege, they can now create stored functions and procedures using JS. + +However, you can't currently create JS triggers or events. \ No newline at end of file diff --git a/docs/js-lang-procedures.md b/docs/js-lang-procedures.md new file mode 100644 index 00000000000..b403b84f290 --- /dev/null +++ b/docs/js-lang-procedures.md @@ -0,0 +1,34 @@ +# JS stored function or procedure + +After component is installed it becomes possible to create stored function or stored procedure in JS language using the following syntax: + +```{.text .no-copy} +CREATE + [DEFINER = user] + FUNCTION [IF NOT EXISTS] sp_name ([func_parameter[,...]]) + RETURNS type + LANGUAGE JS [other-func-characteristic ...] AS js_routine_body + +CREATE + [DEFINER = user] + PROCEDURE [IF NOT EXISTS] sp_name ([proc_parameter[,...]]) + LANGUAGE JS [other-proc-characteristic ...] AS js_routine_body + +routine_body: + text_string_literal | dollar_quoted_string +``` + +Use the `LANGUAGE JS` clause when creating a routine. + +```{.bash data-prompt="mysql>"} +mysql> CREATE FUNCTION f1(n INT) RETURNS INT LANGUAGE JS AS $$ + return n*42; +$$ + +mysql> CREATE PROCEDURE p1(a INT, b INT, OUT r INT) LANGUAGE JS AS $$ + r = a * b; +$$ +``` + +You can modify or delete stored programs in JS using the standard `ALTER PROCEDURE/FUNCTION` and `DROP PROCEDURE/FUNCTION` statements. These statements do not require the additional `CREATE_JS_ROUTINE` privilege. + diff --git a/docs/js-lang-troubleshoot.md b/docs/js-lang-troubleshoot.md new file mode 100644 index 00000000000..ba3a2b0952b --- /dev/null +++ b/docs/js-lang-troubleshoot.md @@ -0,0 +1,11 @@ +# Troubleshoot JS lang procedures + +The component includes a set of User-Defined Functions (UDFs) that retrieve and clear information about the last JS error that occurred in the current connection for the current user. This information updates each time a JS error occurs for the current connection and user. Successful execution of JS code does not change this state. + +The following UDFs are helpful for debugging JS code. + +* `JS_GET_LAST_ERROR()`: Returns the error message for the last JS error that occurred in the current connection for the current user. + +* `JS_GET_LAST_ERROR_INFO()`: Provides extended information about the last JS error that occurred in the current connection for the current user. In addition to the error message, it includes the exact line and column where the problem occurred and the stack trace if available. + +* `JS_CLEAR_LAST_ERROR()`: Resets the information about the last JS error for the current connection and user, as if no error had occurred. \ No newline at end of file diff --git a/docs/uninstall-js-lang.md b/docs/uninstall-js-lang.md new file mode 100644 index 00000000000..9d484d255d1 --- /dev/null +++ b/docs/uninstall-js-lang.md @@ -0,0 +1,9 @@ +# Uninstall the js_lang component + +The uninstall works only when no connections are using JavaScript stored programs. If there are connections, the procedure fails with an error. + +To remove the component, run the following: + +```{.bash data-prompt="mysql>"} +mysql> UNINSTALL COMPONENT 'file://component_js_lang'; +``` \ No newline at end of file diff --git a/mkdocs-base.yml b/mkdocs-base.yml index c678158ce94..c3d87a859d0 100644 --- a/mkdocs-base.yml +++ b/mkdocs-base.yml @@ -212,6 +212,13 @@ nav: - extended-select-into-outfile.md - fips.md - innodb-expanded-fast-index-creation.md + - JS language support: + - js-lang-overview.md + - install-js-lang.md + - js-lang-privileges.md + - js-lang-procedures.md + - js-lang-troubleshoot.md + - uninstall-js-lang.md - kill-idle-trx.md - percona-sequence-table.md - procfs-plugin.md