diff --git a/src/main/asciidoc/sql/SQL-Custom-Functions.adoc b/src/main/asciidoc/sql/SQL-Custom-Functions.adoc new file mode 100644 index 00000000..8184ed20 --- /dev/null +++ b/src/main/asciidoc/sql/SQL-Custom-Functions.adoc @@ -0,0 +1,107 @@ +[[Custom-Functions]] +=== Custom Functions + +The SQL engine can be extended with custom functions written with a scripting language or via Java. + +[discrete] + +==== Database's function + +Look at the <> page. + + +[discrete] + +==== Custom Functions in SQL + +Custom functions can be defined via SQL using the following command: + +---- +DEFINE FUNCTION . "" [PARAMETERS [,*]] LANGUAGE +---- + +* `` A name space to group functions. +* `` The function's name. +* `` The function's body encapsuled in a string in the chosen language's syntax. +* `[,*]` A list of parameter identifiers used in the function body. For functions without parameters omit the `PARAMETERS []` block instead of supplying an empty array. +* `` Either `js` (Javascript) or `sql`. + +NOTE: To invoke a custom function, the function identifier (`library.function`) must be enclosed with back ticks. + +NOTE: The return value in a custom SQL function is determined by the projection named `'result'`. + +*Examples* + +[source,sql] +---- +DEFINE FUNCTION my.fma 'return a + b * c' PARAMETERS [a,b,c] LANGUAGE js; +SELECT `my.fma`(1,2,3); +---- + +[source,sql] +---- +DEFINE FUNCTION the.answer 'SELECT "fourty-two" AS result' LANGUAGE sql; +SELECT `the.answer`(); +---- + +''' + +A custom function can be deleted via SQL using the following command: + +---- +DELETE FUNCTION . +---- + +* `` A name space to group functions. +* `` The function's name. + +*Example* + +[source,sql] +---- +DELETE FUNCTION extra.tsum +---- + +[discrete] + +==== Custom Functions in Java + +Before to use them in your queries you need to register: + +[source,java] +---- +// REGISTER 'BIGGER' FUNCTION WITH FIXED 2 PARAMETERS (MIN/MAX=2) +SQLEngine.getInstance().registerFunction("bigger", + new SQLFunctionAbstract("bigger", 2, 2) { + public String getSyntax() { + return "bigger(, )"; + } + + public Object execute(Object[] iParameters) { + if (iParameters[0] == null || iParameters[1] == null) + // CHECK BOTH EXPECTED PARAMETERS + return null; + + if (!(iParameters[0] instanceof Number) || !(iParameters[1] instanceof Number)) + // EXCLUDE IT FROM THE RESULT SET + return null; + + // USE DOUBLE TO AVOID LOSS OF PRECISION + final double v1 = ((Number) iParameters[0]).doubleValue(); + final double v2 = ((Number) iParameters[1]).doubleValue(); + + return Math.max(v1, v2); + } + + public boolean aggregateResults() { + return false; + } +}); +---- + +Now you can execute it: + +[source,java] +---- +Resultset result = database.command("sql", "SELECT FROM Account WHERE bigger( salary, 10 ) > 10"); +---- diff --git a/src/main/asciidoc/sql/SQL-Functions.adoc b/src/main/asciidoc/sql/SQL-Functions.adoc index 836b4302..8a5faf9a 100644 --- a/src/main/asciidoc/sql/SQL-Functions.adoc +++ b/src/main/asciidoc/sql/SQL-Functions.adoc @@ -1341,59 +1341,3 @@ SELECT vectorNeighbors('Word[name,vector]','Life',10) ---- ''' - -[[Custom-Functions]] - -==== Custom functions - -The SQL engine can be extended with custom functions written with a scripting language or via Java. - -[discrete] - -===== Database's function - -Look at the <> page. - -[discrete] - -===== Custom functions in Java - -Before to use them in your queries you need to register: - -[source,java] ----- -// REGISTER 'BIGGER' FUNCTION WITH FIXED 2 PARAMETERS (MIN/MAX=2) -SQLEngine.getInstance().registerFunction("bigger", - new SQLFunctionAbstract("bigger", 2, 2) { - public String getSyntax() { - return "bigger(, )"; - } - - public Object execute(Object[] iParameters) { - if (iParameters[0] == null || iParameters[1] == null) - // CHECK BOTH EXPECTED PARAMETERS - return null; - - if (!(iParameters[0] instanceof Number) || !(iParameters[1] instanceof Number)) - // EXCLUDE IT FROM THE RESULT SET - return null; - - // USE DOUBLE TO AVOID LOSS OF PRECISION - final double v1 = ((Number) iParameters[0]).doubleValue(); - final double v2 = ((Number) iParameters[1]).doubleValue(); - - return Math.max(v1, v2); - } - - public boolean aggregateResults() { - return false; - } -}); ----- - -Now you can execute it: - -[source,java] ----- -Resultset result = database.command("sql", "SELECT FROM Account WHERE bigger( salary, 10 ) > 10"); ----- diff --git a/src/main/asciidoc/sql/SQL-Insert.adoc b/src/main/asciidoc/sql/SQL-Insert.adoc index 2e71e127..5d07bf60 100644 --- a/src/main/asciidoc/sql/SQL-Insert.adoc +++ b/src/main/asciidoc/sql/SQL-Insert.adoc @@ -21,7 +21,7 @@ INSERT INTO [TYPE:]|BUCKET:|INDEX: ---- * *`SET`* Abbreviated syntax to set field values. -* *`CONTENT`* Defines JSON data as an option to set field values of one or multiple records. +* *`CONTENT`* Defines JSON data as an option to set field values of one (object) or multiple (in an array of objects) records. * *`RETURN`* Defines an expression to return instead of the number of inserted records. You can use any valid SQL expression. The most common use-cases, ** `@rid` Returns the Record ID of the new record. ** `@this` Returns the entire new record. @@ -29,6 +29,9 @@ INSERT INTO [TYPE:]|BUCKET:|INDEX: NOTE: To insert only documents, vertices, or edges with a certain *unique* property, use a <>. +NOTE: If multiple documents are inserted as JSON "CONTENT", and one document causes an error, +for example due to a schema error, the remaining documents in the JSON array are not inserted. + *Examples* * Inserts a new record with the name `Jay` and surname `Miner`. diff --git a/src/main/asciidoc/sql/SQL-Pagination.adoc b/src/main/asciidoc/sql/SQL-Pagination.adoc index f23575c3..9f7f608d 100644 --- a/src/main/asciidoc/sql/SQL-Pagination.adoc +++ b/src/main/asciidoc/sql/SQL-Pagination.adoc @@ -1,5 +1,5 @@ -[[SQL-Pagination]] [discrete] +[[SQL-Pagination]] === Pagination image:../images/edit.png[link="https://github.com/ArcadeData/arcadedb-docs/blob/main/src/main/asciidoc/sql/SQL-Pagination.adoc" float=right] diff --git a/src/main/asciidoc/sql/SQL-Profile.adoc b/src/main/asciidoc/sql/SQL-Profile.adoc index 2911df03..09169d5b 100644 --- a/src/main/asciidoc/sql/SQL-Profile.adoc +++ b/src/main/asciidoc/sql/SQL-Profile.adoc @@ -5,7 +5,7 @@ image:../images/edit.png[link="https://github.com/ArcadeData/arcadedb-docs/blob/main/src/main/asciidoc/sql/SQL-Profile.adoc" float=right] -PROFILE SQL command returns information about query execution planning and statistics for a specific statement. +The `PROFILE` SQL command returns information about query execution planning and statistics for a specific statement. The statement is actually executed to provide the execution stats. The result is the execution plan of the query (like for <> ) with additional information about execution time spent on each step, in microseconds. diff --git a/src/main/asciidoc/sql/SQL-Projections.adoc b/src/main/asciidoc/sql/SQL-Projections.adoc index f19c5d7c..ee081959 100644 --- a/src/main/asciidoc/sql/SQL-Projections.adoc +++ b/src/main/asciidoc/sql/SQL-Projections.adoc @@ -1,4 +1,3 @@ -[[SQL-Projections]] [discrete] [[SQL-Projections]] === Projections @@ -22,7 +21,7 @@ has three projections: [discrete] -===== Syntax +==== Syntax *A projection* has the following syntax: @@ -39,7 +38,7 @@ A projection block has the following syntax: [discrete] -===== Query result +==== Query result By default, a query returns a different result-set based on the projections it has: @@ -154,7 +153,7 @@ Result: `[{"items[4]": "John Smith"}]` [discrete] -===== Nested projections +==== Nested projections *Syntax*: diff --git a/src/main/asciidoc/sql/SQL-Select-Execution.adoc b/src/main/asciidoc/sql/SQL-Select-Execution.adoc index cf8b2e44..61050fa6 100644 --- a/src/main/asciidoc/sql/SQL-Select-Execution.adoc +++ b/src/main/asciidoc/sql/SQL-Select-Execution.adoc @@ -1,6 +1,6 @@ [discrete] -=== SQL SELECT Statements Execution +==== SQL SELECT Statements Execution image:../images/edit.png[link="https://github.com/ArcadeData/arcadedb-docs/blob/main/src/main/asciidoc/sql/SQL-Select-Execution.adoc" float=right] The execution flow of a SELECT statement is made of many steps. @@ -14,7 +14,7 @@ The SELECT query execution, at a very high level, is made of three steps: [discrete] -==== Query optimization +===== Query optimization The first step for the query executor is to run a query optimizer. This operation can change the internal structure of the SQL statement to make it more efficient, preserving the same semantics of the original query. @@ -63,7 +63,7 @@ SELECT FROM Person WHERE father in (SELECT FROM Person WHERE name = 'John' and s ---- [discrete] -==== Refactoring of the WHERE conditions +===== Refactoring of the WHERE conditions eg. consider the following: diff --git a/src/main/asciidoc/sql/chapter.adoc b/src/main/asciidoc/sql/chapter.adoc index e8b95424..98cdd434 100644 --- a/src/main/asciidoc/sql/chapter.adoc +++ b/src/main/asciidoc/sql/chapter.adoc @@ -71,9 +71,7 @@ include::SQL-Introduction.adoc[] include::SQL-Projections.adoc[] -include::SQL-Functions.adoc[] - -include::SQL-Methods.adoc[] +include::SQL-Pagination.adoc[] include::SQL-Where.adoc[] @@ -124,14 +122,14 @@ include::SQL-Insert.adoc[] include::SQL-Match.adoc[] +include::SQL-Profile.adoc[] + include::SQL-Rebuild-Index.adoc[] include::SQL-Select.adoc[] include::SQL-Select-Execution.adoc[] -include::SQL-Pagination.adoc[] - include::SQL-Traverse.adoc[] include::SQL-Truncate-Bucket.adoc[] @@ -140,6 +138,10 @@ include::SQL-Truncate-Type.adoc[] include::SQL-Update.adoc[] -include::SQL-Profile.adoc[] +include::SQL-Functions.adoc[] + +include::SQL-Methods.adoc[] include::SQL-Script.adoc[] + +include::SQL-Custom-Functions.adoc[]