diff --git a/modules/guides/pages/call-user-defined-function.adoc b/modules/guides/pages/call-user-defined-function.adoc index 0891a1c2e..33d7890dc 100644 --- a/modules/guides/pages/call-user-defined-function.adoc +++ b/modules/guides/pages/call-user-defined-function.adoc @@ -4,6 +4,7 @@ :page-edition: Enterprise Edition :page-topic-type: guide :page-toclevels: 2 +:imagesdir: ../assets/images :flag-devex-escape-hatch!: [abstract] @@ -14,12 +15,11 @@ include::partial$other-guide.adoc[] == Introduction -A User-Defined Function can be called like any other {sqlpp} function. -The Javascript is not called directly; it is called through the {sqlpp} User-Defined Function. +A user-defined function can be called like any other {sqlpp} function. == Calling the {sqlpp} User-Defined Function -An {sqlpp} User-Defined Function can be called from anywhere that a standard {sqlpp} function can be called. +An {sqlpp} user-defined function can be called from anywhere that a standard {sqlpp} function can be called. [tabs] ==== @@ -67,7 +67,7 @@ include::example$javascript-udfs/execute-scoped-function.n1ql[] [NOTE] ===== -The {sqlpp} User-Defined Function can be used in any {sqlpp} statement in exactly the same way as a standard built-in function. +The {sqlpp} user-defined function can be used in any {sqlpp} statement in exactly the same way as a standard built-in function. [source, sqlpp] ---- @@ -78,6 +78,6 @@ include::example$javascript-udfs/select-true-alias-get-business-days.n1ql[] ==== -== Further Reading +== Related Links include::partial$javascript-udfs/further-reading.adoc[tags="create-function;user-defined-functions"] \ No newline at end of file diff --git a/modules/guides/pages/create-javascript-library.adoc b/modules/guides/pages/create-javascript-library.adoc index ca0f7a796..ee9d7ebf6 100644 --- a/modules/guides/pages/create-javascript-library.adoc +++ b/modules/guides/pages/create-javascript-library.adoc @@ -4,6 +4,7 @@ :page-edition: Enterprise Edition :page-topic-type: guide :page-toclevels: 2 +:imagesdir: ../assets/images :flag-devex-escape-hatch!: [abstract] @@ -14,13 +15,14 @@ include::partial$other-guide.adoc[] == Introduction -In this guide you will learn how to create a library for storing JavaScript functions, and how to add a new function to the library. +You can create an external library for storing JavaScript functions. +When you create a new library you can add a new JavaScript function to the library at the same time. include::partial$before-you-begin.adoc[tag=body] include::partial$query-tools.adoc[tags=body;!thumbs] [#creating-the-library-and-adding-your-first-function] -== Creating the Library and Adding Your First Function +== Creating the Library and Adding JavaScript Code You can use the Query Workbench UI or the REST API to create a library. The process for creating the library is as follows: @@ -46,7 +48,7 @@ Query Workbench:: + image::javascript-udfs/navigate-to-udf-query.png[alt="route to the user-defined functions screen"] -. Click on the *{plus} add function library* link in the `Javascript Function Libraries` table to show the `Add Library` screen. +. Click on the *{plus} add function library* link in the `JavaScript Function Libraries` table to show the `Add Library` screen. . Select your `Namespace` from the drop-down lists. In this example, the namespace has been set to the `inventory` scope inside the `travel-sample` bucket. @@ -90,12 +92,8 @@ The parameters in the URL denote that the function should reside in the `travel- -- ==== -You have now created your JavaScript library. -In the xref:create-user-defined-function.adoc[next step], you'll create an {sqlpp} User-Defined function that references your library function, so it can be called as part of any {sqlpp} statement. +When you have created an external library and added JavaScript code, you must create an {sqlpp} user-defined function to reference the JavaScript code in the library, so it can be called as part of any {sqlpp} statement. - - -== Further Reading +== Related Links include::partial$javascript-udfs/further-reading.adoc[tags="user-defined-functions-ui;rest-create-library-call"] - diff --git a/modules/guides/pages/create-user-defined-function.adoc b/modules/guides/pages/create-user-defined-function.adoc index cf788320d..102d037b0 100644 --- a/modules/guides/pages/create-user-defined-function.adoc +++ b/modules/guides/pages/create-user-defined-function.adoc @@ -1,9 +1,11 @@ = Creating a User-Defined Function -:description: How to create a user-defined function to call your JavaScript function. +:description: How to create a user-defined function to call external JavaScript code. +:page-pagination: :page-edition: Enterprise Edition :page-topic-type: guide :page-toclevels: 2 :keywords: N1QL, UDF, user-defined function, SQL++ +:imagesdir: ../assets/images :flag-devex-escape-hatch!: [abstract] @@ -12,70 +14,63 @@ include::partial$other-guide.adoc[] -- -[#creating-the-n1ql-udf-function] -== Creating the {sqlpp} User-Defined Function +== Introduction + +You cannot call external JavaScript code directly from a {sqlpp} query. +You must create a {sqlpp} user-defined function to reference the external JavaScript code. + +If you have created a JavaScript function in an external library (see xref:create-javascript-library.adoc[]), you must create a {sqlpp} user-defined function to reference it. -Before you can run the JavaScript function you have created (see xref:create-javascript-library.adoc[]), you will need to create a {sqlpp} User-Defined Function to reference it. -You can create a {sqlpp} User-Defined Function by using: +You can also create a {sqlpp} user-defined function and the external JavaScript code in a single operation. +In this case, the JavaScript code is not stored in an external library. -* the xref:tools:udfs-ui.adoc[UDF UI] in the Query Workbench. -* the xref:n1ql:n1ql-language-reference/createfunction.adoc[standard {sqlpp} `CREATE FUNCTION` DDL], using the _External Functions_ option to reference the Javascript function. -* the REST-API to execute a xref:n1ql:n1ql-language-reference/createfunction.adoc[`CREATE FUNCTION`] call. +[#creating-the-n1ql-udf-function] +== Creating a {sqlpp} User-Defined Function to Reference an External Library -For more information on {sqlpp} User Defined Functions in general, read xref:n1ql:n1ql-language-reference/userfun.adoc[]. +To create a {sqlpp} user-defined function to reference an external library, do one of the following: +* Use the xref:tools:udfs-ui.adoc[UDF UI] in the Query Workbench. +* Use the {sqlpp} xref:n1ql:n1ql-language-reference/createfunction.adoc[CREATE FUNCTION] statement, and reference the external library and JavaScript function. [tabs] ==== Query Workbench:: + -- -. Access the `UDF` screen from the administration console. +. Access the *UDF* screen from the administration console. + image::javascript-udfs/navigate-to-udf-query.png[] -. Click on the `{plus}{nbsp}add function` link from the `UDFs` screen. +. Click on the *{plus}{nbsp}add function* link. + image::javascript-udfs/my-library-list-add-function-button.png[alt="library list"] + -which will display the `Add Function` screen. +The *Add Function* dialog is displayed. + image::javascript-udfs/add-function-dialog.png[ ,400] -. Use the `Namespace` drop-down lists to select the bucket and scope where your Javascript function resides. +. Use the *Namespace* drop-down lists to select the bucket and scope where your JavaScript function resides. -. Fill in the `Function Name` of your {sqlpp} User-Defined Function. +. Fill in the *Function Name* of your {sqlpp} user-defined function. -. Leave the `Parameters` as they are. +. Specify *Parameters* for the function. + NOTE: The `...` in the parameters box denotes a variable length list of parameters. -This is why you don't have to fill in this field. -. Select `Javascript` for the function type. -A field will appear in the dialog with a list of available libraries in the namespace you selected. +. Select *JavaScript* for the function type. +A field appears in the dialog with a list of available libraries in the namespace you selected. + image::javascript-udfs/add-function-dialog-switch-to-javascript.png[] + -From this list select the library containing your function. +From this list select the library containing your function. . Enter the name of the JavaScript function in the `Library Function Name` field. -- -REST API:: -+ --- -Run a `curl` command from the shell to add a {sqlpp} User-Defined Function that calls your Javascript function. - -[source, console] ----- -include::example$javascript-udfs/create-scoped-n1ql-udf-with-rest.sh[] ----- --- - {sqlpp}:: + -- -Execute the `CREATE FUNCTION` in the CBQ Shell to create the {sqlpp} User-Defined Function: +Execute the `CREATE FUNCTION` in the CBQ Shell to create the {sqlpp} user-defined function: [source, sqlpp] ---- @@ -84,6 +79,8 @@ include::example$javascript-udfs/create-scoped-n1ql-udf.n1ql[] -- ==== -NOTE: The {sqlpp} User-Defined Function will take the same scope as the JavaScript UDF it is referencing. +NOTE: The {sqlpp} user-defined function will take the same scope as the JavaScript UDF it is referencing. + +== Related Links -Having created your {sqlpp} User-Defined Function, the xref:call-user-defined-function.adoc[next step] is to use a {sqlpp} statement to call the function. +* To create a {sqlpp} user-defined function and the external JavaScript code in a single operation, see xref:n1ql:n1ql-language-reference/createfunction.adoc[CREATE FUNCTION]. diff --git a/modules/guides/pages/javascript-udfs.adoc b/modules/guides/pages/javascript-udfs.adoc index e308e296c..48b0fb4e4 100644 --- a/modules/guides/pages/javascript-udfs.adoc +++ b/modules/guides/pages/javascript-udfs.adoc @@ -1,4 +1,4 @@ -= User-defined Functions with JavaScript += User-Defined Functions with JavaScript :description: How to extend the {sqlpp} query language by adding your own functions written in JavaScript. :page-pagination: next :page-edition: Enterprise Edition @@ -35,17 +35,3 @@ If you wish to look into the constructs and available in the language itself, th * xref:javascript-udfs:calling-javascript-from-n1ql.adoc[] * xref:javascript-udfs:calling-n1ql-from-javascript.adoc[] * xref:javascript-udfs:handling-errors-javascript-udf.adoc[] - - - - - - - - - - - - - - diff --git a/modules/javascript-udfs/pages/calling-javascript-from-n1ql.adoc b/modules/javascript-udfs/pages/calling-javascript-from-n1ql.adoc index eb4fefaf3..44d2b6773 100644 --- a/modules/javascript-udfs/pages/calling-javascript-from-n1ql.adoc +++ b/modules/javascript-udfs/pages/calling-javascript-from-n1ql.adoc @@ -10,11 +10,11 @@ == Introduction Before you can call a JavaScript function, you must first create a {sqlpp} User-Defined Function to call it. -The process to do this is explained in the xref:guides:create-user-defined-function.adoc#creating-the-n1ql-udf-function[Creating the {sqlpp} User-Defined Function] section of our xref:guides:javascript-udfs.adoc[] guide. +The process to do this is explained in the xref:guides:create-user-defined-function.adoc#creating-the-n1ql-udf-function[Creating the {sqlpp} User-Defined Function] section of the xref:guides:javascript-udfs.adoc[] guide. If you are unfamiliar with creating User-Defined Functions to call JavaScript, then the xref:guides:javascript-udfs.adoc[guide] is the best place to start. -In this section, we're going to take a closer look at concepts around {sqlpp} User-Defined Functions, such as variadic parameter lists. +In this section, you're going to take a closer look at concepts around {sqlpp} User-Defined Functions, such as variadic parameter lists. == Scopes and {sqlpp} User-Defined Functions @@ -94,7 +94,7 @@ include::example$select-true-alias-get-business-days.n1ql[] == Variadic Parameters You can define a {sqlpp} User-Defined Function with a variadic parameter, which means that the parameter will accept a list of values which it will pass to the JavaScript function it references. -We can create the `GetBusinessDays` function using a variadic parameter rather than the `startDate` and `endDate` parameters: +You can create the `GetBusinessDays` function using a variadic parameter rather than the `startDate` and `endDate` parameters: [source, sqlpp] ---- diff --git a/modules/javascript-udfs/pages/calling-n1ql-from-javascript.adoc b/modules/javascript-udfs/pages/calling-n1ql-from-javascript.adoc index bb47eee6c..ac558874e 100644 --- a/modules/javascript-udfs/pages/calling-n1ql-from-javascript.adoc +++ b/modules/javascript-udfs/pages/calling-n1ql-from-javascript.adoc @@ -1,5 +1,5 @@ = Calling {sqlpp} from JavaScript -:description: Executing {sqlpp} statements from Javascript functions. +:description: Executing {sqlpp} statements from JavaScript functions. :page-edition: Enterprise Edition :page-toclevels: 2 :stem: @@ -9,19 +9,19 @@ == Introduction -As well as being able to call JavaScript functions from {sqlpp}, you can also call {sqlpp} statements from inside your Javascript functions. +As well as being able to call JavaScript functions from {sqlpp}, you can also call {sqlpp} statements from inside your JavaScript functions. [#calling-statements-inline] -== Calling {sqlpp} statements inline +== Calling {sqlpp} Statements Inline -You can embed a {sqlpp} statement directly in your Javascript code: +You can embed a {sqlpp} statement directly in your JavaScript code: [source,javascript] ---- include::example$add-airline-inline-call.js[] ---- -== Executing {sqlpp} statements using the N1QL() call +== Executing {sqlpp} Statements Using the N1QL() Call In addition, you can also execute a {sqlpp} statement by calling it from the `N1QL(…)` function. [source, javascript] @@ -47,12 +47,12 @@ will generate an error because the `AddAirline()` function will attempt to alter IMPORTANT: Functions that change data must be called using the `EXECUTE FUNCTION` statement. -== Returning values from {sqlpp} statements +== Returning Values from {sqlpp} Statements As shown in the <>, embedded {sqlpp} statements return values which can be used later on in your code. -The values returned from the statement calls are Javascript https://www.w3schools.com/js/js_object_iterables.asp[iterators^]: lists of values or documents returned from the database. -In the next example, we're going to retrieve a list of the hotels stored in the `travel-sample` database: +The values returned from the statement calls are JavaScript https://www.w3schools.com/js/js_object_iterables.asp[iterators^]: lists of values or documents returned from the database. +In the next example, you're going to retrieve a list of the hotels stored in the `travel-sample` database: [source, javascript] ---- @@ -60,13 +60,13 @@ include::example$select-hotels-inline.js[] ---- <.> The {sqlpp} statement returns an iterator containing the items retrieved by the query. -<.> Using the standard Javascript iterator pattern to loop through the items returned in `q`. +<.> Using the standard JavaScript iterator pattern to loop through the items returned in `q`. <.> Add the current document from the iterator to the result array `res`. <.> Once all the items have been retrieved, return the result array. [IMPORTANT] ==== -If an inline statement/{sqlpp} call does not return a value, then the associated {sqlpp} statement is executed as part of a synchronous operation. i.e. the runtime will wait until the statement completes before moving on to the next line of Javascript. +If an inline statement/{sqlpp} call does not return a value, then the associated {sqlpp} statement is executed as part of a synchronous operation. i.e. the runtime will wait until the statement completes before moving on to the next line of JavaScript. If the inline statement/{sqlpp} call returns a value then it is executed _asynchronously_: execution continues before the iterator is returned. Each document is fetched from the bucket as it requested by the iterator. @@ -77,9 +77,9 @@ include::partial$diagrams/inline-call-sequence.puml[] .... ==== -== Passing Parameters to {sqlpp} statements +== Passing Parameters to {sqlpp} Statements -You can pass parameters from your Javascript to your {sqlpp} statements. +You can pass parameters from your JavaScript to your {sqlpp} statements. Parameters can either be _positional_ or _named_. Positional:: The parameters are applied to the statement in the order they appear in the list. @@ -96,7 +96,7 @@ Named:: The parameters are given a mnemonic name attached to the value, so they include::example$add-airline-named-parameters.js[] ---- + -NOTE: The names of the parameters passed into the Javascript function are used in the {sqlpp} statement without any need to assign the parameters in a separate step. +NOTE: The names of the parameters passed into the JavaScript function are used in the {sqlpp} statement without any need to assign the parameters in a separate step. [sidebar] **** @@ -121,7 +121,7 @@ Inline calls only support named parameters. == Transactions -Transactions are supported from {sqlpp} statements called from Javascript functions. +Transactions are supported from {sqlpp} statements called from JavaScript functions. * The function can run statements in a transaction that was started before the function was executed. * The function can run a statement that starts the transaction. @@ -140,13 +140,13 @@ include::partial$diagrams/transactions-and-iterators.puml[] == Role-Based Access Control -In order to execute {sqlpp} statements as part of a Javascript function, the user executing the function must have the appropriate privileges to perform the action on any objects referenced in the {sqlpp} statement. +In order to execute {sqlpp} statements as part of a JavaScript function, the user executing the function must have the appropriate privileges to perform the action on any objects referenced in the {sqlpp} statement. -== Executing {sqlpp} statements that call functions +== Executing {sqlpp} Statements that Call Functions -It is often the case that Javascript function will call a {sqlpp} statement that may itself call another Javascript function. -However, it is important to be aware that each Javascript function call executed from a parent call will use a new Javascript worker process to run. -The deeper the calls are nested, the fewer Javascript workers are available to run, so the calling chain will eventually fail and throw an error. +It is often the case that JavaScript function will call a {sqlpp} statement that may itself call another JavaScript function. +However, it is important to be aware that each JavaScript function call executed from a parent call will use a new JavaScript worker process to run. +The deeper the calls are nested, the fewer JavaScript workers are available to run, so the calling chain will eventually fail and throw an error. This can be demonstrated using a recursive call sequence as shown below: [source, javascript] @@ -168,7 +168,7 @@ returns the following result: ---- include::example$do-recursion-response.jsonc[] ---- -<.> The call failed after {number-of-calls} nested call, which exhausted the number of Javascript workers available during the call sequence. +<.> The call failed after {number-of-calls} nested call, which exhausted the number of JavaScript workers available during the call sequence. [NOTE] ==== @@ -176,8 +176,7 @@ The JavaScript workers are created when the Couchbase server is started up. asciimath:["Number of JavaScript Workers" = 4 xx "Number of CPUs"] -The service will automatically prevent recursive calls if there are less than 50% javascript workers available - +The service will automatically prevent recursive calls if there are fewer than 50% JavaScript workers available. ==== == Further Reading diff --git a/modules/javascript-udfs/pages/handling-errors-javascript-udf.adoc b/modules/javascript-udfs/pages/handling-errors-javascript-udf.adoc index 053a78a77..2d8e966c9 100644 --- a/modules/javascript-udfs/pages/handling-errors-javascript-udf.adoc +++ b/modules/javascript-udfs/pages/handling-errors-javascript-udf.adoc @@ -1,14 +1,16 @@ -= Handling Errors in Javascript Functions -:description: Error handling in Javascript user-defined functions use the same standard exception mechanism as part of the language standard. += Handling Errors in JavaScript Functions +:description: Error handling in JavaScript user-defined functions use the same standard exception mechanism as part of the language standard. :page-edition: Enterprise Edition -:page-topic-type: guide +:page-topic-type: reference :page-toclevels: 2 [abstract] {description} +== Handle Errors with the Runtime + Errors that occur during the execution of a {sqlpp} statement are usually handled by the runtime, which will return a JSON object giving details of the error. -For example, if we execute a record insertion function with a key that already exists: +For example, if you execute a record insertion function with a key that already exists: [source, sqlpp] ---- @@ -22,7 +24,9 @@ then an error object is returned: include::example$duplicate-key-error.json5[] ---- -In most cases, it's a lot better if the Javascript function itself can handle errors that are likely to occur. +== Handle Errors with the Function + +In most cases, it's a lot better if the JavaScript function itself can handle errors that are likely to occur. This gives the developer the option of responding with a more user-friendly message, or taking an alternative course of action. The following function will add an airline record, but will return an `failure` message if the attempt isn't successful. @@ -39,7 +43,7 @@ If the record key already exists, then calling this method with `EXECUTE FUNCTIO include::example$add-airline-with-check-failure-return-response.jsonc[] ---- -Alternatively, we can simply throw the error, rather than returning it as a string: +Alternatively, you can simply throw the error, rather than returning it as a string: [source, javascript] ---- @@ -53,16 +57,15 @@ which will produce the following result: include::example$add-airline-with-check-failure-throw-response.jsonc[] ---- -As well as wrapping the expection in a detailed JSON object, there is another fundamental difference between throwing an error or returning it: +As well as wrapping the expection in a detailed JSON object, there is another fundamental difference between throwing an error or returning it. + +=== Throw vs Return -.Throw vs Return -**** Aside from the data returned, throwing an error or returning a value/error will affect how subsequent {sqlpp} operations are processed. *Returning an error*:: If the JavaScript function _returns_ any value, then the {sqlpp} runtime will assume that the function completed successfully, and the caller will continue to run subsequent statements. *Throwing an error*:: If an error is _thrown_ then this is treated as an error condition, so further statements in the request will not be run. -**** You can, of course, throw the error object itself, rather than just a string. @@ -78,6 +81,8 @@ which deliver a lot more useful information than just posting back a string: include::example$add-airline-with-check-failure-throw-object-response.jsonc[] ---- +=== Parse the Error + Another approach is to parse the error using the `JSON.parse()` function and return the resulting object: [source, javascript] @@ -93,7 +98,9 @@ This code will send back the entire message structure. include::example$parsed-error-in-full.json5[] ---- -Once we know the structure of the error message, there's no reason why we can't carry out alternative actions depending on the type of error encountered: +=== Carry Out Alternative Actions + +Once you know the structure of the error message, there's no reason why you can't carry out alternative actions depending on the type of error encountered: [source, javascript] ---- diff --git a/modules/javascript-udfs/pages/javascript-functions-with-couchbase.adoc b/modules/javascript-udfs/pages/javascript-functions-with-couchbase.adoc index 6970d51d3..e3c82c9f2 100644 --- a/modules/javascript-udfs/pages/javascript-functions-with-couchbase.adoc +++ b/modules/javascript-udfs/pages/javascript-functions-with-couchbase.adoc @@ -11,11 +11,11 @@ include::partial$javascript-udf-introduction.adoc[] -If you want to learn how to create JavaScript function libraries using the administration console and/or the REST-API then take a look at our xref:guides:javascript-udfs.adoc[JavaScript UDF Guides]. +If you want to learn how to create JavaScript function libraries using the administration console and/or the REST-API then take a look at the xref:guides:javascript-udfs.adoc[JavaScript UDF Guides]. == Added Constructs -Javascript functions in Couchbase support most of the language constructs available in https://en.wikipedia.org/wiki/ECMAScript[ECMAScript], though there are a number of restrictions related to the Couchbase environment. +JavaScript functions in Couchbase support most of the language constructs available in https://en.wikipedia.org/wiki/ECMAScript[ECMAScript], though there are a number of restrictions related to the Couchbase environment. There are also additions that have been made to the language for working specifically with Couchbase. === {sqlpp} Embedded Statements @@ -29,7 +29,7 @@ Operations that return values such as SELECT are accessible through a returned i include::example$select-airline-inline.js[] ---- <1> The {sqlpp} is written directly into the JavaScript code without having to be used as part of a function call. -We can even provide parameters that can be used in the {sqlpp} statement. +You can even provide parameters that can be used in the {sqlpp} statement. <2> A standard JavaScript iterator is used to access the values returned from the {sqlpp} statement. include::partial$libraries-and-scopes.adoc[leveloffset=+2] @@ -49,13 +49,13 @@ include::example$illegal-global-variable.js[] ---- Along with global state, global https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions[arrow functions] are not supported. -Arrow functions local to individual javascript functions are supported. +Arrow functions local to individual JavaScript functions are supported. === Logging Logging using the `console.log(..)` function is not supported. -In the rest of this section, we're going to look at the concepts behind JavaScript User-Defined Functions: +In the rest of this section, you're going to look at the concepts behind JavaScript User-Defined Functions: * xref:calling-javascript-from-n1ql.adoc[] * xref:calling-n1ql-from-javascript.adoc[] diff --git a/modules/javascript-udfs/partials/diagrams.adoc b/modules/javascript-udfs/partials/diagrams.adoc index f726f5813..66229646d 100644 --- a/modules/javascript-udfs/partials/diagrams.adoc +++ b/modules/javascript-udfs/partials/diagrams.adoc @@ -30,7 +30,7 @@ include::diagrams/udf-scopes-diagram.puml[] include::diagrams/banking-scope-scenario.puml[] .... -.Javascript UDFs Structure +.JavaScript UDFs Structure [plantuml] .... include::diagrams/javascript-scopes.puml[] diff --git a/modules/javascript-udfs/partials/javascript-udf-introduction.adoc b/modules/javascript-udfs/partials/javascript-udf-introduction.adoc index 4457fed22..9642d4628 100644 --- a/modules/javascript-udfs/partials/javascript-udf-introduction.adoc +++ b/modules/javascript-udfs/partials/javascript-udf-introduction.adoc @@ -5,7 +5,7 @@ Shouldn't be too JavaScript specific. {sqlpp} includes a large number of xref:n1ql:n1ql-language-reference/index.adoc[operations and generic functions] that cover every aspect of data manipulation. In addition to the built-in functions, Couchbase also allows you to create your own extensions to the language. -Using User-Defined Functions, you can: +Using user-defined functions, you can: * Create reuseable, domain-specific functions for use in your applications. * Execute complex logic that may be difficult to do in {sqlpp}. diff --git a/modules/javascript-udfs/partials/libraries-and-scopes.adoc b/modules/javascript-udfs/partials/libraries-and-scopes.adoc index 05dfefbe2..2311f85cf 100644 --- a/modules/javascript-udfs/partials/libraries-and-scopes.adoc +++ b/modules/javascript-udfs/partials/libraries-and-scopes.adoc @@ -4,11 +4,11 @@ The libraries and scope section can be reused in the guides section [#libraries-and-scopes] = Libraries and Scopes -JavaScript functions are stored inside a _library_. +JavaScript functions can be stored inside a _library_. A library can contain one or more functions, and can also be assigned to a scope, which allows libraries to be partitioned for logical grouping. // tag::scoping-diagram[] -.Javascript UDFs Structure +.JavaScript UDFs Structure [plantuml#javascript-scopes,javascript-scopes,svg] .... include::partial$diagrams/javascript-scopes.puml[] @@ -20,7 +20,7 @@ As shown in xref:javascript-scopes[xrefstyle=short], a JavaScript function libra * A library accessible within a scope. // end::scoping-diagram[] -NOTE: You can find an introduction to scopes in our xref:tutorials:buckets-scopes-and-collections.adoc#scopes_and_collections[Couchbase Tutorials]. +NOTE: You can find an introduction to scopes in the xref:tutorials:buckets-scopes-and-collections.adoc#scopes_and_collections[Couchbase Tutorials]. Furthermore, access restrictions can be applied to scopes, so that only certain groups of users will be able to access collections and libraries within that scope. diff --git a/modules/n1ql/assets/images/n1ql-language-reference/create-function-external.png b/modules/n1ql/assets/images/n1ql-language-reference/create-function-external.png index 2dbfd3172..d8a611c09 100644 Binary files a/modules/n1ql/assets/images/n1ql-language-reference/create-function-external.png and b/modules/n1ql/assets/images/n1ql-language-reference/create-function-external.png differ diff --git a/modules/n1ql/assets/images/n1ql-language-reference/javascript.png b/modules/n1ql/assets/images/n1ql-language-reference/javascript.png new file mode 100644 index 000000000..42231623b Binary files /dev/null and b/modules/n1ql/assets/images/n1ql-language-reference/javascript.png differ diff --git a/modules/n1ql/pages/n1ql-language-reference/createfunction.adoc b/modules/n1ql/pages/n1ql-language-reference/createfunction.adoc index d6af47dab..57a89ccba 100644 --- a/modules/n1ql/pages/n1ql-language-reference/createfunction.adoc +++ b/modules/n1ql/pages/n1ql-language-reference/createfunction.adoc @@ -5,6 +5,10 @@ :imagesdir: ../../assets/images :page-partial: :page-toclevels: 2 +:keywords: library namespacing + +// TEMP +include::partial$n1ql-language-reference/horizontal-style.adoc[] [abstract] {description} @@ -13,13 +17,16 @@ There are two types of user-defined function: -* [def]_Inline functions_ are defined using {sqlpp} expressions, including subqueries. +* [def]_Inline functions_ are defined using {sqlpp} expressions. They enable you to name and reuse complex or repetitive expressions, including subqueries, in order to simplify your queries. * [def]_External functions_ are defined using an external language. They enable you to create functions that may be difficult or impossible to define using built-in {sqlpp} expressions. The only supported language is JavaScript. +External functions in {sqlpp} support most of the language constructs available in ECMAScript. +For more information about the restrictions and extensions that come with the Couchbase implementation, see xref:javascript-udfs:javascript-functions-with-couchbase.adoc[]. + [[context]] === Global Functions and Scoped Functions @@ -46,7 +53,11 @@ Finally, it is important to note that a global function is _not_ the same as a s === External Libraries (((library namespacing))) -External functions are stored in _libraries_. +You can store external functions in _libraries_. +This enables you to share external function code in more than one user-defined function. + +You must create the external library and the external function code using the xref:tools:udfs-ui.adoc[Query Workbench] or the {sqlpp} xref:n1ql-rest-api/functions.adoc[Functions REST API]. + Like user-defined functions, these libraries may also be scoped or global. This enables you to keep the code for external functions separate where required. @@ -56,21 +67,55 @@ Code which is stored in a _global library_ is available to users of all scopes. A global library may have the same name as a scoped library, and scoped libraries may have the same name as each other. For example, you may have a global `math` library, and a `math` library in each scope. -== RBAC Privileges +=== {sqlpp} Managed User-Defined Functions + +ifeval::['{page-component-version}' == '7.6'] +_(Introduced in Couchbase Server 7.6)_ +endif::[] + +In Couchbase Server 7.6 and later, you can create the code for an external function and the corresponding {sqlpp} user-defined function in a single operation. +This means that you don't have to specify an external library and create the code for the external function, before creating the {sqlpp} user-defined function. + +With a {sqlpp} managed user-defined function, the external function code is stored inline, along with the {sqlpp} user-defined function. +You cannot share this external function code with other user-defined functions, or access it from any external libraries. + +== Prerequisites + +[cols="2,3"] +|=== +| To manage ... | You must have ... + +| Global inline functions +| *Manage Global Functions* role. + +| Scoped inline functions +| *Manage Scope Functions* role, with permissions on the specified bucket and scope. -To manage global internal functions, you must have the *Manage Global Functions* role. -To manage scoped internal functions, you must have the *Manage Scope Functions* role, with permissions on the specified bucket and scope. +| Global external functions +| *Manage Global External Functions* role. -To manage global external functions, you must have the *Manage Global External Functions* role. -To manage scoped external functions, you must have the *Manage Scope External Functions* role, with permissions on the specified bucket and scope. +| Scoped external functions +| *Manage Scope External Functions* role, with permissions on the specified bucket and scope. +|=== Users with the *Manage Scope External Functions* role also have read-only access to any global external library. -To execute global internal functions, you must have the *Execute Global Functions* role. -To execute scoped internal functions, you must have the *Execute Scope Functions* role, with permissions on the specified bucket and scope. +[cols="2,3"] +|=== +| To execute ... | You must have ... -To execute global external functions, you must have the *Execute Global External Functions* role. -To execute scoped external functions, you must have the *Execute Scope External Functions* role, with permissions on the specified bucket and scope. +| Global inline functions +| *Execute Global Functions* role. + +| Scoped inline functions +| *Execute Scope Functions* role, with permissions on the specified bucket and scope. + +| Global external functions +| *Execute Global External Functions* role. + +| Scoped external functions +| *Execute Scope External Functions* role, with permissions on the specified bucket and scope. +|=== For more details about user roles, see xref:learn:security/authorization-overview.adoc[Authorization]. @@ -103,11 +148,30 @@ image::n1ql-language-reference/create-function-inline.png["Syntax diagram: refer // TODO: Automatic links in EBNF. -function:: (Required) Refer to <> below. +[horizontal.compact] +function:: <> icon:caret-down[] +params:: <> icon:caret-down[] +body:: <> icon:caret-down[] + +// tag::replace[] +[id='{section}-replace'] +==== OR REPLACE / IF NOT EXISTS + +The optional `OR REPLACE` clause enables you to redefine a user-defined function if it already exists, whereas the optional `IF NOT EXISTS` clause enables the statement to complete successfully without replacing the function. + +When a function with the same name already exists within the same context: +footnote:context[That is, you are creating a global function, and a function with the same name already exists within the same namespace; or, you are creating a scoped function, and a function with the same name already exists within the same scope.] + +* If the `OR REPLACE` clause is present, the existing function is replaced. -params:: (Optional) Refer to <> below. +* If the `IF NOT EXISTS` clause is present, the statement does nothing and completes without error. -body:: (Required) Refer to <> below. +* If neither of these two clauses is present, an error is generated. + +NOTE: These clauses are exclusive. +If the statement contains both the `OR REPLACE` clause and the `IF NOT EXISTS` clause, an error is generated. + +// end::replace[] // tag::arguments[] [id='{section}-name'] @@ -165,30 +229,12 @@ For inline functions, the result and type of the function are the result and typ If you need to return multiple values, construct an array. ==== -// tag::replace[] -[id='{section}-replace'] -==== OR REPLACE / IF NOT EXISTS - -The optional `OR REPLACE` clause enables you to redefine a user-defined function if it already exists, whereas the optional `IF NOT EXISTS` clause enables the statement to complete successfully without replacing the function. - -When a function with the same name already exists within the same context: -footnote:context[That is, you are creating a global function, and a function with the same name already exists within the same namespace; or, you are creating a scoped function, and a function with the same name already exists within the same scope.] - -* If the `OR REPLACE` clause is present, the existing function is replaced. - -* If the `IF NOT EXISTS` clause is present, the statement does nothing and completes without error. - -* If neither of these two clauses is present, an error is generated. - -NOTE: These clauses are exclusive. -If the statement contains both the `OR REPLACE` clause and the `IF NOT EXISTS` clause, an error is generated. - -// end::replace[] - [[create-function-external]] :section: external === External Functions +There are two alternative syntaxes for defining an external function: one where the function code is stored in an external library, and one for creating a {sqlpp} managed user-defined function. + [source,ebnf] ---- include::partial$grammar/ddl.ebnf[tag=create-function-external] @@ -198,36 +244,46 @@ image::n1ql-language-reference/create-function-external.png["Syntax diagram: ref // TODO: Automatic links in EBNF. -function:: (Required) Refer to <> below. +[horizontal.compact] +function:: <> icon:caret-down[] +params:: <> icon:caret-down[] +obj:: <> icon:caret-down[] +library:: <> icon:caret-down[] +javascript:: <> icon:caret-down[] -params:: (Optional) Refer to <> below. - -obj:: (Required) Refer to <> below. - -library:: (Required) Refer to <> below. +include::createfunction.adoc[tag=replace] include::createfunction.adoc[tag=arguments] [[external-object]] ==== External Object +[Optional] Use this parameter where the function code is stored in an external library. + The name of the JavaScript function that you want to use for the user-defined function. This parameter is a string and must be wrapped in quotes. -// FIXME: -External functions in {sqlpp} _only_ support plain JavaScript, without any of the xref:eventing:eventing-language-constructs.adoc#added-lang-features[added language features] supported by functions in the Eventing Service. [[external-library]] ==== External Library -The name of the JavaScript library that contains the function you want to use. +[Optional] Use this parameter where the function code is stored in an external library. + +The name of the JavaScript library that contains the JavaScript function you want to use. This parameter is a string and must be wrapped in quotes. -You must create the JavaScript library and the JavaScript function using the {sqlpp} Functions REST API. -For details, refer to xref:n1ql-rest-api/functions.adoc[Functions REST API]. The name of a scoped external library must include the bucket name, the scope name, and the library name, separated by slashes. For example, to refer to a scoped library called `my-library` located in the `inventory` scope within the `travel-sample` bucket, you would specify the library name as `travel-sample/inventory/my-library`. -include::createfunction.adoc[tag=replace] +[[javascript]] +==== Function Body + +[Optional] Use this parameter to create a {sqlpp} managed user-defined function. + +The external JavaScript function code. +This must contain a function with the same name and the same number of parameters as the {sqlpp} user-defined function. +This parameter is a string and must be wrapped in quotes. + +The JavaScript code can contain multiple function definitions, but these functions can only be referenced within the JavaScript code for this {sqlpp} user-defined function, and cannot be shared. == Examples @@ -425,6 +481,32 @@ EXECUTE FUNCTION phi(); ---- ==== +[[ex-managed]] +.{sqlpp} managed user-defined function +==== +The following statement creates external JavaScript function code and the corresponding {sqlpp} user-defined function in one operation. + +[source,sqlpp] +---- +CREATE FUNCTION add100(num) LANGUAGE JAVASCRIPT AS +"function add100(param1) {return param1+100;}"; +---- + +.Test +[source,sqlpp] +---- +EXECUTE FUNCTION add100(100); +---- + +.Result +[source,json] +---- +[ + 200 +] +---- +==== + [[ex-external]] .External functions ==== @@ -572,8 +654,10 @@ At this level of precision, the geohash should appear to be in almost exactly th == Related Links -* To manage external libraries of user-defined functions, refer to xref:n1ql-rest-api/functions.adoc[Functions REST API]. -* To execute user-defined functions, refer to xref:n1ql-language-reference/execfunction.adoc[EXECUTE FUNCTION]. -* To include user-defined functions in an expression, refer to xref:n1ql-language-reference/userfun.adoc[User-Defined Functions]. -* To view user-defined functions, refer to xref:manage:monitor/monitoring-n1ql-query.adoc#sys-functions[Monitor Queries]. -* To drop user-defined functions, refer to xref:n1ql-language-reference/dropfunction.adoc[DROP FUNCTION]. +* To manage user-defined functions in the Query Workbench, see xref:tools:udfs-ui.adoc[]. +* To manage external libraries and external functions, see xref:n1ql-rest-api/functions.adoc[]. +* To execute a user-defined function, see xref:n1ql-language-reference/execfunction.adoc[]. +* To see the execution plan for a user-defined function, see xref:n1ql-language-reference/explainfunction.adoc[]. +* To include a user-defined function in an expression, see xref:n1ql-language-reference/userfun.adoc[]. +* To monitor user-defined functions, see xref:manage:monitor/monitoring-n1ql-query.adoc#sys-functions[Monitor Functions]. +* To drop a user-defined function, see xref:n1ql-language-reference/dropfunction.adoc[]. diff --git a/modules/n1ql/pages/n1ql-language-reference/dropfunction.adoc b/modules/n1ql/pages/n1ql-language-reference/dropfunction.adoc index 21357a14b..8675c9e3f 100644 --- a/modules/n1ql/pages/n1ql-language-reference/dropfunction.adoc +++ b/modules/n1ql/pages/n1ql-language-reference/dropfunction.adoc @@ -5,16 +5,30 @@ :imagesdir: ../../assets/images :page-partial: +// TEMP +include::partial$n1ql-language-reference/horizontal-style.adoc[] + [abstract] {description} -== RBAC Privileges +== Prerequisites + +[cols="2,3"] +|=== +| To manage ... | You must have ... + +| Global inline functions +| *Manage Global Functions* role. -To manage global internal functions, you must have the *Manage Global Functions* role. -To manage scoped internal functions, you must have the *Manage Scope Functions* role, with permissions on the specified bucket and scope. +| Scoped inline functions +| *Manage Scope Functions* role, with permissions on the specified bucket and scope. -To manage global external functions, you must have the *Manage Global External Functions* role. -To manage scoped external functions, you must have the *Manage Scope External Functions* role, with permissions on the specified bucket and scope. +| Global external functions +| *Manage Global External Functions* role. + +| Scoped external functions +| *Manage Scope External Functions* role, with permissions on the specified bucket and scope. +|=== For more details about user roles, see xref:learn:security/authorization-overview.adoc[Authorization]. @@ -30,7 +44,8 @@ image::n1ql-language-reference/drop-function.png["Syntax diagram: refer to sourc // TODO: Automatic links in EBNF. -function:: (Required) Refer to <> below. +[horizontal.compact] +function:: <> icon:caret-down[] [[name]] === Function Name @@ -66,11 +81,12 @@ footnote:context[That is, you are dropping a global function, and the function d == Usage -When you drop an external user-defined function, the JavaScript library and function on which the user-defined function depended are not deleted. +When you drop a user-defined function whose definition is stored in an external library, the external library and function on which the user-defined function depended are not deleted. This enables you to create a new user-defined function with a different name, or a different number of parameters, using the same JavaScript library and function. -To change or delete the JavaScript library and the JavaScript function, you must use the {sqlpp} Functions REST API. -For details, refer to xref:n1ql-rest-api/functions.adoc[Functions REST API]. +To change or delete an external library or the external function code, you must use the xref:tools:udfs-ui.adoc[Query Workbench] or the {sqlpp} xref:n1ql-rest-api/functions.adoc[Functions REST API]. + +When you drop a {sqlpp} managed user-defined function, the associated external function code is deleted also. == Examples @@ -91,6 +107,23 @@ SELECT * FROM system:functions; ---- ==== +.Drop a {sqlpp} managed user-defined function +==== +This statement deletes a {sqlpp} managed user-defined function called `add100`. + +[source,sqlpp] +---- +DROP FUNCTION add100 IF EXISTS; +---- + +You can run the following query to check that the function is no longer available. + +[source,sqlpp] +---- +SELECT * FROM system:functions; +---- +==== + .Drop an external function ==== These statements delete two external functions: @@ -117,7 +150,10 @@ http://localhost:8093/evaluator/v1/libraries/geohash-js \ == Related Links -* To create user-defined functions, refer to xref:n1ql-language-reference/createfunction.adoc[CREATE FUNCTION]. -* To execute user-defined functions, refer to xref:n1ql-language-reference/execfunction.adoc[EXECUTE FUNCTION]. -* To include user-defined functions in an expression, refer to xref:n1ql-language-reference/userfun.adoc[User-Defined Functions]. -* To view user-defined functions, refer to xref:manage:monitor/monitoring-n1ql-query.adoc#sys-functions[Monitor Queries]. +* To create user-defined functions, refer to xref:n1ql-language-reference/createfunction.adoc[]. +* To manage user-defined functions in the Query Workbench, see xref:tools:udfs-ui.adoc[]. +* To manage external libraries and external functions, see xref:n1ql-rest-api/functions.adoc[]. +* To execute a user-defined function, see xref:n1ql-language-reference/execfunction.adoc[]. +* To see the execution plan for a user-defined function, see xref:n1ql-language-reference/explainfunction.adoc[]. +* To include a user-defined function in an expression, see xref:n1ql-language-reference/userfun.adoc[]. +* To monitor user-defined functions, see xref:manage:monitor/monitoring-n1ql-query.adoc#sys-functions[Monitor Functions]. diff --git a/modules/n1ql/pages/n1ql-language-reference/execfunction.adoc b/modules/n1ql/pages/n1ql-language-reference/execfunction.adoc index 260d5f904..0fadddf1c 100644 --- a/modules/n1ql/pages/n1ql-language-reference/execfunction.adoc +++ b/modules/n1ql/pages/n1ql-language-reference/execfunction.adoc @@ -11,17 +11,6 @@ include::partial$n1ql-language-reference/horizontal-style.adoc[] [abstract] The `EXECUTE FUNCTION` statement enables you to execute a user-defined function. -== RBAC Privileges - -To execute global internal functions, you must have the *Execute Global Functions* role. -To execute scoped internal functions, you must have the *Execute Scope Functions* role, with permissions on the specified bucket and scope. - -To execute global external functions, you must have the *Execute Global External Functions* role. -To execute scoped external functions, you must have the *Execute Scope External Functions* role, with permissions on the specified bucket and scope. - -For more details about user roles, see -xref:learn:security/authorization-overview.adoc[Authorization]. - == Purpose The `EXECUTE FUNCTION` statement enables you to execute a user-defined function. @@ -31,6 +20,28 @@ It also enables you to execute functions which have side effects, such as perfor You cannot use the `EXECUTE FUNCTION` statement to execute a built-in {sqlpp} function. If you do this, error `10101: Function not found` is generated. +== Prerequisites + +[cols="2,3"] +|=== +| To execute ... | You must have ... + +| Global inline functions +| *Execute Global Functions* role. + +| Scoped inline functions +| *Execute Scope Functions* role, with permissions on the specified bucket and scope. + +| Global external functions +| *Execute Global External Functions* role. + +| Scoped external functions +| *Execute Scope External Functions* role, with permissions on the specified bucket and scope. +|=== + +For more details about user roles, see +xref:learn:security/authorization-overview.adoc[Authorization]. + == Syntax [source,ebnf] @@ -81,7 +92,10 @@ For examples, refer to xref:n1ql-language-reference/createfunction.adoc#examples == Related Links -* To create user-defined functions, refer to xref:n1ql-language-reference/createfunction.adoc[CREATE FUNCTION]. -* To include user-defined functions in an expression, refer to xref:n1ql-language-reference/userfun.adoc[User-Defined Functions]. -* To view user-defined functions, refer to xref:manage:monitor/monitoring-n1ql-query.adoc#sys-functions[Monitor Queries]. -* To drop user-defined functions, refer to xref:n1ql-language-reference/dropfunction.adoc[DROP FUNCTION]. +* To create user-defined functions, refer to xref:n1ql-language-reference/createfunction.adoc[]. +* To manage user-defined functions in the Query Workbench, see xref:tools:udfs-ui.adoc[]. +* To manage external libraries and external functions, see xref:n1ql-rest-api/functions.adoc[]. +* To see the execution plan for a user-defined function, see xref:n1ql-language-reference/explainfunction.adoc[]. +* To include a user-defined function in an expression, see xref:n1ql-language-reference/userfun.adoc[]. +* To monitor user-defined functions, see xref:manage:monitor/monitoring-n1ql-query.adoc#sys-functions[Monitor Functions]. +* To drop a user-defined function, see xref:n1ql-language-reference/dropfunction.adoc[]. diff --git a/modules/n1ql/pages/n1ql-language-reference/explainfunction.adoc b/modules/n1ql/pages/n1ql-language-reference/explainfunction.adoc index ecd739a1c..6bedb21ae 100644 --- a/modules/n1ql/pages/n1ql-language-reference/explainfunction.adoc +++ b/modules/n1ql/pages/n1ql-language-reference/explainfunction.adoc @@ -4,12 +4,14 @@ :imagesdir: ../../assets/images // TEMP -include::partial$n1ql-language-reference/collapsible-style.adoc[] +include::partial$n1ql-language-reference/horizontal-style.adoc[] [abstract] {description} -You can supply the name of an inline or external user-defined function. +== Purpose + +You can request the execution plan for an inline or external user-defined function. * For an inline function, EXPLAIN FUNCTION returns the query plans for all of the subqueries present in the function body. + @@ -28,17 +30,22 @@ The following constraints apply: == Prerequisites -To execute EXPLAIN FUNCTION on an inline user-defined function, you must have the necessary execute function permission on that function. - -* For a global internal function, you must have the Execute Global Functions role. +[cols="2,3"] +|=== +| To execute EXPLAIN FUNCTION on ... | You must have ... -* For a scoped internal function, you must have the Execute Scope Functions role, with permissions on the specified bucket and scope. +| Global inline functions +| *Execute Global Functions* role. -To execute EXPLAIN FUNCTION on an external user-defined JavaScript function, you must have the necessary execute external function permission on that function. +| Scoped inline functions +| *Execute Scope Functions* role, with permissions on the specified bucket and scope. -* For a global JavaScript function, you must have the Execute Global External Functions role. +| Global external functions +| *Execute Global External Functions* role. -* For a scoped JavaScript function, you must have the Execute External Scope Functions role, with permissions on the specified bucket and scope. +| Scoped external functions +| *Execute Scope External Functions* role, with permissions on the specified bucket and scope. +|=== You must also have the necessary privileges required for the {sqlpp} statements inside the function. @@ -54,14 +61,33 @@ include::partial$grammar/utility.ebnf[tag=explain-function] image::n1ql-language-reference/explain-function.png["Syntax diagram: refer to source code listing", align=left] -The statement consists of the `EXPLAIN FUNCTION` keywords followed by the name of the user-defined function that has the execution plan you want to review. +[horizontal.compact] +function:: <> icon:caret-down[] + +[[name]] +=== Function Name + +[source,ebnf] +---- +include::partial$grammar/ddl.ebnf[tag=function] +---- + +image::n1ql-language-reference/function.png["Syntax diagram", align=left] -For more information about function name syntax and requirements, see xref:n1ql-language-reference/createfunction.adoc#inline-name[CREATE FUNCTION]. +The name of the function. +This is usually an unqualified identifier, such as `func1` or `{backtick}func-1{backtick}`. +In this case, the path to the function is determined by the current xref:n1ql:n1ql-intro/queriesandresults.adoc#query-context[query context]. + +To get the plan for a global function in a particular namespace, the function name must be a qualified identifier with a namespace, such as `default:func1`. +Similarly, to get the plan for a scoped function in a particular scope, the function name must be a qualified identifier with the full path to a scope, such as `default:{backtick}travel-sample{backtick}.inventory.func1`. +Refer to xref:n1ql-language-reference/createfunction.adoc#context[Global Functions and Scoped Functions] for more information. + +NOTE: The name of a user-defined function _is_ case-sensitive, unlike that of a built-in function. +You must get the plan for the user-defined function using the same case that was used when it was created. == Examples .Inline Function Example - ==== In this example, you create an inline function named `func1` and then request the plan for its subquery. @@ -78,7 +104,6 @@ include::n1ql:example$utility/explainfunction.jsonc[] ==== .External Function Example - ==== This example assumes that you have defined a JavaScript library named `lib1`. @@ -105,6 +130,16 @@ include::n1ql:example$utility/explainfunctionjs.n1ql[] include::n1ql:example$utility/explainfunctionjs.jsonc[] ---- -<.> The line number in the JavaScript function that includes a N1QL() call. +<.> The line number in the JavaScript function that includes a N1QL() call. <.> The query plan for the embedded {sqlpp} statement. -==== \ No newline at end of file +==== + +== Related Links + +* To create user-defined functions, refer to xref:n1ql-language-reference/createfunction.adoc[]. +* To manage user-defined functions in the Query Workbench, see xref:tools:udfs-ui.adoc[]. +* To manage external libraries and external functions, see xref:n1ql-rest-api/functions.adoc[]. +* To execute a user-defined function, see xref:n1ql-language-reference/execfunction.adoc[]. +* To include a user-defined function in an expression, see xref:n1ql-language-reference/userfun.adoc[]. +* To monitor user-defined functions, see xref:manage:monitor/monitoring-n1ql-query.adoc#sys-functions[Monitor Functions]. +* To drop a user-defined function, see xref:n1ql-language-reference/dropfunction.adoc[]. diff --git a/modules/n1ql/pages/n1ql-language-reference/userfun.adoc b/modules/n1ql/pages/n1ql-language-reference/userfun.adoc index acacc18e0..6aa54a14c 100644 --- a/modules/n1ql/pages/n1ql-language-reference/userfun.adoc +++ b/modules/n1ql/pages/n1ql-language-reference/userfun.adoc @@ -8,17 +8,6 @@ [abstract] {description} -== RBAC Privileges - -To execute global internal functions, you must have the *Execute Global Functions* role. -To execute scoped internal functions, you must have the *Execute Scope Functions* role, with permissions on the specified bucket and scope. - -To execute global external functions, you must have the *Execute Global External Functions* role. -To execute scoped external functions, you must have the *Execute Scope External Functions* role, with permissions on the specified bucket and scope. - -For more details about user roles, see -xref:learn:security/authorization-overview.adoc[Authorization]. - == Description When you have created a user-defined function, you can call it in any expression, just like a built-in function. @@ -37,6 +26,28 @@ You must call the user-defined function using the same case that was used when i It is not possible to call a user-defined function in an expression if the function has side effects, such as performing mutations. When you do this, an error is generated. +== Prerequisites + +[cols="2,3"] +|=== +| To execute ... | You must have ... + +| Global inline functions +| *Execute Global Functions* role. + +| Scoped inline functions +| *Execute Scope Functions* role, with permissions on the specified bucket and scope. + +| Global external functions +| *Execute Global External Functions* role. + +| Scoped external functions +| *Execute Scope External Functions* role, with permissions on the specified bucket and scope. +|=== + +For more details about user roles, see +xref:learn:security/authorization-overview.adoc[Authorization]. + == Arguments A user-defined function has zero, one, or more arguments, separated by commas, just like a built-in function. @@ -175,7 +186,10 @@ At the latitude of the selected hotel, each geohash represents an area of approx == Related Links -* To create user-defined functions, refer to xref:n1ql-language-reference/createfunction.adoc[CREATE FUNCTION]. -* To execute user-defined functions, refer to xref:n1ql-language-reference/execfunction.adoc[EXECUTE FUNCTION]. -* To view user-defined functions, refer to xref:manage:monitor/monitoring-n1ql-query.adoc#sys-functions[Monitor Queries]. -* To drop user-defined functions, refer to xref:n1ql-language-reference/dropfunction.adoc[DROP FUNCTION]. +* To create user-defined functions, refer to xref:n1ql-language-reference/createfunction.adoc[]. +* To manage user-defined functions in the Query Workbench, see xref:tools:udfs-ui.adoc[]. +* To manage external libraries and external functions, see xref:n1ql-rest-api/functions.adoc[]. +* To execute a user-defined function, see xref:n1ql-language-reference/execfunction.adoc[]. +* To see the execution plan for a user-defined function, see xref:n1ql-language-reference/explainfunction.adoc[]. +* To monitor user-defined functions, see xref:manage:monitor/monitoring-n1ql-query.adoc#sys-functions[Monitor Functions]. +* To drop a user-defined function, see xref:n1ql-language-reference/dropfunction.adoc[]. diff --git a/modules/n1ql/partials/grammar/ddl.ebnf b/modules/n1ql/partials/grammar/ddl.ebnf index 4938af0c6..827efc4b9 100644 --- a/modules/n1ql/partials/grammar/ddl.ebnf +++ b/modules/n1ql/partials/grammar/ddl.ebnf @@ -179,7 +179,7 @@ create-function-inline ::= 'CREATE' ( 'OR' 'REPLACE' )? 'FUNCTION' function '(' /* tag::create-function-external[] */ create-function-external ::= 'CREATE' ( 'OR' 'REPLACE' )? 'FUNCTION' function '(' params? ')' ( 'IF' 'NOT' 'EXISTS' )? - 'LANGUAGE' 'JAVASCRIPT' 'AS' obj 'AT' library + 'LANGUAGE' 'JAVASCRIPT' 'AS' ( obj 'AT' library | javascript ) /* end::create-function-external[] */ /* tag::function[] */ @@ -202,6 +202,10 @@ obj ::= string library ::= string /* end::library[] */ +/* tag::javascript[] */ +javascript ::= string +/* end::javascript[] */ + /* tag::drop-function[] */ drop-function ::= 'DROP' 'FUNCTION' function ( 'IF' 'EXISTS' )? /* end::drop-function[] */