Saturday, 30 September 2017

ES6 with SQLcl / JDK9

In JDK 8, the Nashorn engine was still on ES5. With the latest release (JDK9), they have included optional support for ES6, which can be enabled by way of an argument. So, to test out this functionality I will be trying with a new variable/constant construct called `const`.

Before developing my script for SQLcl, I sometimes like to use jjs to verify everything. jjs is an interactive shell that invokes the Nashorn engine. So by defualt it uses ES5, so we can write a script like so:

jjs> var a = Math.floor(Math.random()*100) * 55
jjs> print (a)
990
jjs>

With JDK9, we can invoke this tool with ES6 support via an optional argument `--language` where we can specifiy either es5 or es6.

$ jjs --language=es6
jjs> const a = Math.floor(Math.random()*100) * 55
jjs> a = 2
<shell>:1 TypeError: Assignment to constant "a"
jjs> print (a);
2695
jjs>


The above snippet shows I can use the new `const` construct that is a part of the ES6 spec within the Nashorn engine. See this article for more information about some of what's included: https://www.oracle.com/corporate/features/nashorn-javascript-engine-jdk9.html

This is good and all, but the question is, how do we get this working in SQLcl?

Well, thankfully, when invoking our Java programs we can set nashorn orguments with a command: `-Dnashorn.orgs=.`.

If you take a look at the SQLcl bash script, you will see that if you set some JAVA_OPTS values, that will get passed along to the call to SQLcl. So, if you want to run ES6 (which, why wouldn't you!) in your SQLcl scripts, simply set that variable accordingly.

export JAVA_OPTS="-Dnashorn.args=--language=es6"

So, to verify it works, I set up a little test script using `const` instead of `var` (which isn't supported in ES5). The script looks like:

print ("Set variable `unchangeableValue` to 55");
const unchangeableValue = 55;
try {
    print ("Trying to change variable to 0");
    unchangeableValue = 0;
} catch (e) {
    print ("Exception");
    print (e);
}


First pass, we will run using ES5 (the default), and the engine picks up on a unrecognized key word (const) and throws an exception:

$ sql /nolog

SQLcl: Release 17.3.0 Production on Sat Sep 30 16:27:27 2017

Copyright (c) 1982, 2017, Oracle.  All rights reserved.


SQL> script test.js
javax.script.ScriptException: :2:0 Expected an operand but found const
const unchangeableValue = 55;
^ in  at line number 2 at column number 0


Second pass, we set the JAVA_OPTS as specified above. The output then becomes:

$ JAVA_OPTS="-Dnashorn.args=--language=es6" sql /nolog

SQLcl: Release 17.3.0 Production on Sat Sep 30 16:29:17 2017

Copyright (c) 1982, 2017, Oracle.  All rights reserved.

SQL> script test.js
Set variable `unchangeableValue` to 55
Trying to change variable to 0
Exception
TypeError: Assignment to constant "unchangeableValue"
SQL>


And the script runs as we expect!