JavaScript UDF Limitations¶
To ensure stability within the Snowflake environment, Snowflake places the following limitations on JavaScript UDFs. These limitations are not invoked at the time of UDF creation, but rather at runtime when the UDF is called. This topic covers general JavaScript UDF (user-defined function) requirements and usage details, as well as limitations that are specific to JavaScript UDFs.
Code Size¶
Snowflake limits the maximum size of the JavaScript source code in the body of a JavaScript UDF. Snowflake recommends limiting the size to 100 KB. (The code is stored in a compressed form, and the exact limit depends on the compressibility of the code.)
Memory¶
JavaScript UDFs will fail if they consume too much memory. The specific limit is subject to change. Using too much memory will result in an error being returned.
Time¶
JavaScript UDFs that take too long to complete will be killed and an error returned to the user. In addition, JavaScript UDFs that enter endless loops will result in errors.
Stack Depth¶
Excessive stack depth due to recursion will result in an error.
Global State¶
Snowflake usually preserves the JavaScript global state between iterations of a UDF. However, you should not rely on previous modifications to the global state being available between function calls. Additionally, you should not assume that all rows will execute within the same JavaScript environment.
In practice, the global state is relevant with:
Complex/expensive initialization logic. By default, the provided UDF code is evaluated for every row processed. If that code contains complex logic, this might be inefficient.
Functions that contain code that is not idempotent. A typical pattern would be:
Date.prototype._originalToString = Date.prototype.toString; Date.prototype.toString = function() { /* ... SOME CUSTOM CODE ... */ this._originalToString() }
The first time that this code is executed, it changes the state of
toString
and_originalToString
. Those changes are preserved in the global state, and the second time that this code is executed, the values are changed again in a way that creates recursion. The second time thattoString
is called, the code recurses infinitely (until it runs out of stack space).
For these situations, a recommended pattern is to guarantee that relevant code is evaluated only once, using JavaScript’s global variable semantics. For example:
var setup = function() { /* SETUP LOGIC */ }; if (typeof(setup_done) === "undefined") { setup(); setup_done = true; // setting global variable to true }
Note that this mechanism is only safe for caching the effects of code evaluation. It is not guaranteed that after an initialization the global context will be preserved for all rows, and no business logic should depend on it.
Libraries¶
JavaScript UDFs support access to the standard JavaScript library. Note that this excludes many objects and methods typically provided by browsers. There is no mechanism to import, include, or call additional libraries. All required code should be embedded within the UDF.
Additionally, the built-in JavaScript eval()
function is disabled.
Returned Variant Size and Depth¶
Returned variant objects are subject to size and nesting-depth limitations:
- Size
Currently limited to several megabytes, but subject to change.
- Depth
Currently limited to a nesting depth of 1000, but subject to change.
If any object is too large or too deep, an error is returned when the UDF is called.