SQL Databases are good to store and retrieve information stored in tables. SQL in it's purist form is not a programming language. It is a query language. So in many cases we need a procedural language to do computation on database data.

DBStudio includes a poliglot script engine to extend database operations with procedural languages like JavaScript or R or Phyton.

1 Scripts catalog

With DBStudio we can have script code acting like database stored procedures or functions running on server side. But where do we store this code ?

  • We can load scripts from remote http reposirories but this makes no sense for high speed database processing.
  • We can load script code from local files but what if you have multiple dbstudio running as application servers ?
  • Or we can use the scripts catalog tables that can server as code repository for a specific sccript language.

1.1 The scripts tables

Each script language is stored in an specific table named dbscripts_[lang]. You can create the scripts table catalog for the appropriate language using DBStudio explorer.

  1. Select a database where you plan to store scripts.
  2. Select the scripts node and expand it. Click on the selected language.
  3. Right click on the desired language and confirm to create the scripts table.
  4. Right click again on the selected language to create your first script.
  5. Enter the script name and the code (or leave code blank as you can edit it later)
  6. Select the new script created to review the code. You have successfully stored your first script in a database table. Not we can try to run our first script.

2 Loading and calling scripts

Let's see how to call the previously stored javascript sum function. We can do it by using two different methods.

  1. Using the load function to eval the code inline. The code should return the object or function it wishes to expose to the calling script. Then from declared function in the current context.

    This is the common method in JavaScript programming. You first import (load) the code you need and run with functions declared in a single context.

  2. Using a direct call to function using a new context.

    This option is more time expensive but provide better isolation.

Let's see the two examples using a simple sum function that we store with name sum in our database scripts library.

2.1 Loading a script from library

Now, you can run a script in SQL editor and import the library using the Nashorn load command. To resolve the script we will use the database script resolver function that will load the named script from current database instance.

Libraries must return something

Libraries loaded via the load command must return the object that the library wishes to expose to the caller

For instance, let suppose we want to a library with formatting utils

Copy
return {
    
    
    mask: function(value, pattern) {
        var i = 0,
            v = value.toString();
            
        return pattern.replace(/#/g, _ => v[i++]);
    },
    
    formatNumber: function(value) {
        if (value) 
            return value.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
        return "";    
    }
    
    
}

Then we could use the library

Copy
<script>
var formLib = Ax.db.load("format_lib");
console.log("MASK" ,  formLib.mask("746298", "###-##/#"))
console.log("NUMBER", formLib.formatNumber(746298.12))
</script>

data

"MASK", "746-29/8"
"NUMBER", "746,298.12"

You have successfully executed a script using a library stored in database library.

The script resolver can take an optional parameter with the database name where we store the scripts library. If omitted, it's assumed the scripts will be search in current database.

Copy
<script>
load(db.script("db1", "sum"));
return sum(1,2,3);
</script>

data

6

2.2 Calling a function from catalog

An optional way to invoke a script is to use the call function.

Function definition

Catalogued functions called via the call command must be wrapped in a function definition.

Let's suppose we have sum function defined in our library:

Copy
function sum(a,b) {
    return a + b;
}

The function can be invoked using the call command:

Copy
<script>
   return Ax.db.call("sum", 1,2,3);
</script>
6

Or using apply and passing an object array with arguments.

Copy
<script>
   return Ax.db.appply("sum", [1,2,3]);
</script>
6

Both methods load the function from database table and executes it. Only difference between call and apply function is how arguments is passed to the function. Using call, arguments are appended after the function name to load and execute. Using apply, all arguments are passed as a single array argument to the function.

Call and Apply are interchangeable. You can decide whether it’s easier to send in an array or a comma separated list of arguments.