SlideShare uma empresa Scribd logo
1 de 46
Baixar para ler offline
https://github.com/rpbouman/mysqlv8udfs
MySQL
User-Defined Functions
...in JavaScript!
https://github.com/rpbouman/mysqlv8udfs
Welcome!
● @rolandbouman
● roland.bouman@gmail.com
● http://rpbouman.blogspot.com/
● http://www.linkedin.com/in/rpbouman
● http://www.slideshare.net/rpbouman
● Ex-MySQL AB, Ex-Sun Microsystems
● Currently at http://www.pentaho.com/
https://github.com/rpbouman/mysqlv8udfs
MySQL Programmability
● SQL
● Persistent Stored Modules (Stored Routines)
● User-defined functions (UDFs)
https://github.com/rpbouman/mysqlv8udfs
MySQLv8UDFs:
JavaScript Programmability
● https://github.com/rpbouman/mysqlv8udfs
● Based on Google's V8
● More than just executing JavaScript:
– Scriptable front for MySQL's native UDF interface
https://github.com/rpbouman/mysqlv8udfs
MySQL stored routines
● “Standard” SQL/PSM syntax
– Scalar functions
– Procedures
– Triggers
– Events
● Stored in the data dictionary
● Interpreted
https://github.com/rpbouman/mysqlv8udfs
MySQL UDFs
● External binary library (typically C/C++):
– Scalar functions
– Aggregate functions
● Registered in the data dictionary
● Compiled Native code
https://github.com/rpbouman/mysqlv8udfs
JavaScript UDFs. Why?
● Started as a UDF example
● Inspired by drizzle's js() function
● Turned out to have real benefits:
– Convenient manipulation of JSON blobs
– Safer and easier than 'real' C/C++ UDFs
– More expressive than SQL/PSM
– Sometimes much faster than stored routines*
https://github.com/rpbouman/mysqlv8udfs
Intermezzo: Easter day
as stored SQL functionCREATE FUNCTION easter_day(dt DATETIME) RETURNS DATE
DETERMINISTIC NO SQL SQL SECURITY INVOKER
COMMENT 'Returns date of easter day for given year'
BEGIN
DECLARE p_year SMALLINT DEFAULT YEAR(dt);
DECLARE a SMALLINT DEFAULT p_year % 19;
DECLARE b SMALLINT DEFAULT p_year DIV 100;
DECLARE c SMALLINT DEFAULT p_year % 100;
DECLARE e SMALLINT DEFAULT b % 4;
DECLARE h SMALLINT DEFAULT (19*a + b - (b DIV 4) - (
(b - ((b + 8) DIV 25) + 1) DIV 3
) + 15) % 30;
DECLARE L SMALLINT DEFAULT (32 + 2*e + 2*(c DIV 4) - h - (c % 4)) % 7;
DECLARE v100 SMALLINT DEFAULT h + L - 7*((a + 11*h + 22*L) DIV 451) + 114;
RETURN STR_TO_DATE(
CONCAT(
p_year
, '-'
, v100 DIV 31
, '-'
, (v100 % 31) + 1
)
, '%Y-%c-%e'
);
END;
https://github.com/rpbouman/mysqlv8udfs
Intermezzo: Easter day
in JavaScript (js UDF)
mysql> SELECT js('
'> var y = parseInt(arguments[0].substr(0,4), 10),
'> a = y % 19, b = Math.floor(y / 100),
'> c = y % 100, d = Math.floor(b / 4),
'> e = b % 4, f = Math.floor((b + 8) / 25),
'> g = Math.floor((b - f + 1) / 3),
'> h = (19 * a + b - d - g + 15) % 30,
'> i = Math.floor(c / 4), k = c % 4,
'> L = (32 + 2 * e + 2 * i - h - k) % 7,
'> m = Math.floor((a + 11 * h + 22 * L) / 451),
'> n = h + L - 7 * m + 114,
'> M = Math.floor(n/31), D = (n%31)+1;
'> if (M < 10) M = "0" + M;
'> if (D < 10) D = "0" + D;
'>
'> y + "-" + M + "-" + D;
'>
'>', NOW());
https://github.com/rpbouman/mysqlv8udfs
Intermezzo: Easter day
as SQL expressionSTR_TO_DATE(CONCAT(YEAR(now()), '-', (((19*(YEAR(now()) % 19) + (YEAR(now()) DIV
100) - ((YEAR(now()) DIV 100) DIV 4) - (((YEAR(now()) DIV 100) - (((YEAR(now())
DIV 100) + 8) DIV 25) + 1) DIV 3) + 15) % 30) + ((32 + 2*((YEAR(now()) DIV 100) %
4) + 2*((YEAR(now()) % 100) DIV 4) - ((19*(YEAR(now()) % 19) + (YEAR(now()) DIV
100) - ((YEAR(now()) DIV 100) DIV 4) - (((YEAR(now()) DIV 100) - (((YEAR(now())
DIV 100) + 8) DIV 25) + 1) DIV 3) + 15) % 30) - ((YEAR(now()) % 100) % 4)) % 7) -
7*(((YEAR(now()) % 19) + 11*((19*(YEAR(now()) % 19) + (YEAR(now()) DIV 100) -
((YEAR(now()) DIV 100) DIV 4) - (((YEAR(now()) DIV 100) - (((YEAR(now()) DIV 100)
+ 8) DIV 25) + 1) DIV 3) + 15) % 30) + 22*((32 + 2*((YEAR(now()) DIV 100) % 4) +
2*((YEAR(now()) % 100) DIV 4) - ((19*(YEAR(now()) % 19) + (YEAR(now()) DIV 100) -
((YEAR(now()) DIV 100) DIV 4) - (((YEAR(now()) DIV 100) - (((YEAR(now()) DIV 100)
+ 8) DIV 25) + 1) DIV 3) + 15) % 30) - ((YEAR(now()) % 100) % 4)) % 7)) DIV 451) +
114) DIV 31, '-', ((((19*(YEAR(now()) % 19) + (YEAR(now()) DIV 100) -
((YEAR(now()) DIV 100) DIV 4) - (((YEAR(now()) DIV 100) - (((YEAR(now()) DIV 100)
+ 8) DIV 25) + 1) DIV 3) + 15) % 30) + ((32 + 2*((YEAR(now()) DIV 100) % 4) +
2*((YEAR(now()) % 100) DIV 4) - ((19*(YEAR(now()) % 19) + (YEAR(now()) DIV 100) -
((YEAR(now()) DIV 100) DIV 4) - (((YEAR(now()) DIV 100) - (((YEAR(now()) DIV 100)
+ 8) DIV 25) + 1) DIV 3) + 15) % 30) - ((YEAR(now()) % 100) % 4)) % 7) -
7*(((YEAR(now()) % 19) + 11*((19*(YEAR(now()) % 19) + (YEAR(now()) DIV 100) -
((YEAR(now()) DIV 100) DIV 4) - (((YEAR(now()) DIV 100) - (((YEAR(now()) DIV 100)
+ 8) DIV 25) + 1) DIV 3) + 15) % 30) + 22*((32 + 2*((YEAR(now()) DIV 100) % 4) +
2*((YEAR(now()) % 100) DIV 4) - ((19*(YEAR(now()) % 19) + (YEAR(now()) DIV 100) -
((YEAR(now()) DIV 100) DIV 4) - (((YEAR(now()) DIV 100) - (((YEAR(now()) DIV 100)
+ 8) DIV 25) + 1) DIV 3) + 15) % 30) - ((YEAR(now()) % 100) % 4)) % 7)) DIV 451) +
114) % 31) + 1), '%Y-%c-%e')
https://github.com/rpbouman/mysqlv8udfs
Intermezzo: Easter day
Performance comparison
SQL Expression SQL Stored Function JavaScript UDF
0
2
4
6
8
10
12
14
4.61
12.53
2.66
Easter Day Performance (1.000.000)
time(seconds)
https://github.com/rpbouman/mysqlv8udfs
The mysqlv8udfs project
● Scalar Functions:
– js()
– jsudf()
– jserr()
● Aggregate Functions:
– jsagg()
● Daemon plugin*:
– JS_DAEMON
https://github.com/rpbouman/mysqlv8udfs
The JS_DAEMON Plugin
mysql> SHOW VARIABLES LIKE 'js%';
+-----------------------+--------------------------------------+
| Variable_name | Value |
+-----------------------+--------------------------------------+
| js_daemon_module_path | /home/rbouman/mysql/mysql/lib/plugin |
+-----------------------+--------------------------------------+
1 row in set (0.03 sec)
mysql> SHOW STATUS LIKE 'js%';
+----------------------------------+-----------+
| Variable_name | Value |
+----------------------------------+-----------+
| js_daemon_version | 0.0.1 |
| js_v8_heap_size_limit | 2048 |
| js_v8_heap_size_total | 942944256 |
| js_v8_heap_size_total_executable | 959591424 |
| js_v8_heap_size_used | 892941672 |
| js_v8_is_dead | false |
| js_v8_is_execution_terminating | false |
| js_v8_is_profiler_paused | true |
| js_v8_version | 3.7.12.22 |
+----------------------------------+-----------+
9 rows in set (0.00 sec)
https://github.com/rpbouman/mysqlv8udfs
The js() UDF
● js(script[, arg1, …, argN])
– Execute script
– Return value (as string) of the last js expression
● Optional arguments arg1 … argN
– Accessible via the built-in arguments array
– arg1 accessible as arguments[0] (and so on)
● Script*
– if constant it is compiled only once
– executed for each row
https://github.com/rpbouman/mysqlv8udfs
The js() UDF: Example
mysql> SELECT js('
'> arguments[0] + arguments[1];
'> ', 1, 2) AS example
-> ;
+---------+
| example |
+---------+
| 3 |
+---------+
1 row in set (0.03 sec)
https://github.com/rpbouman/mysqlv8udfs
The MySQL UDF interface
● Simple functions (scalars) and aggregates
● Native library callbacks (calling sequence)
– Plugin directory
– mysql.func table
● Data structures
– Return value: struct UDF_INIT *initid
– Arguments: struct UDF_ARGS *args
CREATE [AGGREGATE] FUNCTION name
RETURNS (STRING | REAL | INTEGER)
SONAME 'libraryfile'
https://github.com/rpbouman/mysqlv8udfs
UDF JavaScript binding
● Scalars: jsudf(), Aggregates: jsagg()
– Return value is always a MySQL STRING
● Script argument:
– Constant. Compiled and immediately executed (1x)
– JavaScript callbacks defined in script are called during
the native UDF calling sequence
● UDF data structures scriptable at runtime:
– Members of struct UDF_INIT appear as js globals
– struct UDF_ARGS as global arguments object
https://github.com/rpbouman/mysqlv8udfs
The jsudf() UDF
● jsudf(script[, arg1, …, argN])
– Call the init() callback (optional)
– For each row, return the result of the udf() callback
– Call the deinit() callback (optional)
init() udf() deinit()More rows? No
Yes
https://github.com/rpbouman/mysqlv8udfs
jsudf() example:
running total
mysql> SELECT amount, jsudf('
-> var total;
-> function init(){
-> console.info("Init");
-> total = 0;
-> }
-> function udf(num){
-> console.info("processing row");
-> return total += num;
-> }
-> function deinit(){
-> console.info("Deinit");
-> }
-> ', amount) AS running_total
-> FROM sakila.payment ORDER BY payment_date
https://github.com/rpbouman/mysqlv8udfs
jsudf() example:
resultset and error log
+--------+--------------------+
| amount | running_total |
+--------+--------------------+
| 2.99 | 2.99 |
| 2.99 | 5.98 |
. ... . ... .
| 4.99 | 67416.5099999921 |
+--------+--------------------+
16049 rows in set (0.29 sec)
2013-09-16 14:31:44 JS_DAEMON [info]: Init
2013-09-16 14:31:44 JS_DAEMON [info]: processing row
.... .. .. .. .. .. .. ...... ...... ..............
2013-09-16 14:31:44 JS_DAEMON [info]: processing row
2013-09-16 14:31:44 JS_DAEMON [info]: Deinit
https://github.com/rpbouman/mysqlv8udfs
jsudf() Argument
processing
● Arguments beyond the initial script argument:
– Values passed to the udf() callback
– UDF_ARGS scriptable as global arguments array
– WARNING: In javascript functions, the local built-in
arguments object refers to actual arguments
– Local arguments mask the global arguments object.
– Use this.arguments to refer to the global array of
argument objects.
● Use init() to validate or pre-process arguments
https://github.com/rpbouman/mysqlv8udfs
jsudf() global arguments
mysql> SELECT jsudf('
-> function udf(){
-> //this.arguments describes the
-> //arguments passed to jsudf
->
-> return JSON.stringify(
-> this.arguments,
-> null, " "
-> );
-> }
-> ', 'string', PI() AS "real", 1, 2.3)
https://github.com/rpbouman/mysqlv8udfs
jsudf() global arguments
[
{
"name": "'string'",
"type": 0,
"max_length": 6,
"maybe_null": false,
"const_item": true,
"value": "string"
},
{
"name": "real",
"type": 1,
"max_length": 8,
"maybe_null": false,
"const_item": true,
"value": 3.141592653589793
},
{
"name": "1",
"type": 2,
"max_length": 1,
"maybe_null": false,
"const_item": true,
"value": 1
},
{
"name": "2.3",
"type": 4,
"max_length": 3,
"maybe_null": false,
"const_item": true,
"value": 2.3
}
]
https://github.com/rpbouman/mysqlv8udfs
jsudf() local arguments
(actual arguments)
mysql> SELECT jsudf('
-> function udf(){
-> //standard, built-in javascript arguments
-> //contains argument values passed to this function
-> return JSON.stringify(
-> arguments,
-> null, " "
-> );
-> }
-> ', 'string', PI() AS "real", 1, 2.3)
{
"0": "string",
"1": 3.141592653589793,
"2": 1,
"3": 2.3
}
https://github.com/rpbouman/mysqlv8udfs
jsudf() named
arguments
SELECT jsudf('
function udf( arg1, arg2, arg3, arg4 ){
//values of named argument are available
//as local variables
return "arg1: " + arg1 +
"n" + "arg2: " + arg2 +
"n" + "arg3: " + arg3 +
"n" + "arg4: " + arg4;
}
', 'string', PI() AS "real", 1, 2.3)
arg1: string
arg2: 3.141592653589793
arg3: 1
arg4: 2.3
https://github.com/rpbouman/mysqlv8udfs
The Argument object
● name: Expression text. If provided, the alias
● type: code indicating the runtime data type
– 0: STRING_RESULT, 1: REAL_RESULT,
4: DECIMAL_RESULT
● max_length: maximum string length
● maybe_null: true if nullable
● const_item: true if value is constant
● value: argument value
https://github.com/rpbouman/mysqlv8udfs
Argument Processing:
Validating count and types
function init(){
var args = this.arguments,
nargs = args.length
;
//validate the number of arguments:
if (nargs != 1) throw "Expected exactly 1 argument";
//validate argument type:
var arg = args[0];
switch (arg.type) {
case REAL_RESULT:
case INT_RESULT:
case DECIMAL_RESULT:
break;
default:
throw "Argument must be numeric";
}
}
https://github.com/rpbouman/mysqlv8udfs
Data type Mapping+------------------------+------------------------+---------------------+-------------+---------+
| Type family | MySQL column data type | MYSQL UDF data type | v8 type | JS Type |
+------------------------+------------------------+---------------------+-------------+---------+
| Integral numbers | BIGINT | INT_RESULT | v8::Integer | Number |
| | INT | | or | |
| | MEDIUMINT | | v8::Number | |
| | SMALLINT | | | |
| | TINYINT | | | |
+------------------------+------------------------+---------------------+-------------| |
| Floating point numbers | DOUBLE | REAL_RESULT | v8::Number | |
| | FLOAT | | | |
+------------------------+------------------------+---------------------+ | |
| Decimal numbers | DECIMAL | DECIMAL_RESULT | | |
+------------------------+------------------------+---------------------+-------------+---------+
| Binary String | BINARY | STRING_RESULT | v8::String | String |
| | BLOB | | | |
| | LONGBLOB | | | |
| | MEDIUMBLOB | | | |
| | VARBINARY | | | |
| | TINYBLOB | | | |
+------------------------+------------------------+ | | |
| Character String | CHAR | | | |
| | LONGTEXT | | | |
| | MEDIUMTEXT | | | |
| | VARCHAR | | | |
| | TEXT | | | |
| | TINYTEXT | | | |
+------------------------+------------------------+ | | |
| Structured String | ENUM | | | |
| | SET | | | |
+------------------------+------------------------+ | | |
| Temporal | DATE | | | |
| | DATETIME | | | |
| | TIME | | | |
| | TIMESTAMP | | | |
+------------------------+------------------------+---------------------+-------------+---------+
https://github.com/rpbouman/mysqlv8udfs
The jsagg() UDF
● jsagg(script[, arg1, …, argN])
– Call the init() callback (optional)
– Calls clear() before processing a group of rows
– For each row in a group, the udf() callback is called
– After processing a group, the agg() is called to return
the aggregate value
– Call the deinit() callback (optional)
https://github.com/rpbouman/mysqlv8udfs
The jsagg() UDF
init()
deinit()
More rows?
No
Yes
clear()
agg()
udf()
More groups?
Yes
No
https://github.com/rpbouman/mysqlv8udfs
jsagg() example:
JSON export
mysql> SELECT jsagg('
-> var rows, args = arguments, n = args.length;
-> function clear(){
-> console.info("clear");
-> rows = [];
-> }
-> function udf(){
-> console.info("udf");
-> var i, arg, row = {};
-> for (i = 0; i < n; i++){
-> arg = args[i];
-> row[arg.name] = arg.value;
-> }
-> rows.push(row);
-> }
-> function agg(){
-> console.info("agg");
-> return JSON.stringify(rows, null, " ");
-> }
-> ', film_id, title, release_year, description) AS json
-> FROM sakila.film GROUP BY rating;
https://github.com/rpbouman/mysqlv8udfs
jsagg() example:
result
[
{
"film_id": 1,
"title": "ACADEMY DINOSAUR",
"release_year": 2006,
"description": "A Epic Drama of ... in The Canadian Rockies"
},
...,
...,
{
"film_id": 1000,
"title": "ZORRO ARK",
"release_year": 2006,
"description": "A Intrepid Panorama of ... in A Monastery"
}
]
https://github.com/rpbouman/mysqlv8udfs
jsagg() example:
error log
2013-09-16 23:36:45 JS_DAEMON [info]: Clear
2013-09-16 23:36:45 JS_DAEMON [info]: Udf
.... .. .. .. .. .. .. ...... .... ...
2013-09-16 23:36:45 JS_DAEMON [info]: Udf
2013-09-16 23:36:45 JS_DAEMON [info]: Agg
2013-09-16 23:36:45 JS_DAEMON [info]: Clear
2013-09-16 23:36:45 JS_DAEMON [info]: Udf
.... .. .. .. .. .. .. ...... .... ...
2013-09-16 23:36:45 JS_DAEMON [info]: Udf
2013-09-16 23:36:45 JS_DAEMON [info]: Agg
.... .. .. .. .. .. .. ...... .... ...
.... .. .. .. .. .. .. ...... .... ...
2013-09-16 23:36:45 JS_DAEMON [info]: Clear
2013-09-16 23:36:45 JS_DAEMON [info]: Udf
.... .. .. .. .. .. .. ...... .... ...
2013-09-16 23:36:45 JS_DAEMON [info]: Udf
2013-09-16 23:36:45 JS_DAEMON [info]: Agg
https://github.com/rpbouman/mysqlv8udfs
JavaScript Environment
● JavaScript Standard built-ins:
– Constructors (Date, RegExp, String etc.)
– Static objects (JSON, Math)
– Misc. functions (decodeURI, parseInt etc.)
● Globals provided by mysqlv8udfs *
– arguments[] array
– Some UDF interface variables and constants
– require() function
– console object
– mysql object
https://github.com/rpbouman/mysqlv8udfs
The require() function
● Inspired by commonjs Module loading
● Signature: require(filename[, reload])
– Loads script file from the js_daemon_module_path
– Executes the script and returns the result
– Script is compiled and cached for reuse
– Pass true as 2nd argument to force reload from file
● js_daemon_module_path
– Read-only system variable of the JS_DAEMON plugin
– Specified at mysqld command line or option file
– Prevent loading arbitrary script files
https://github.com/rpbouman/mysqlv8udfs
require() example:
mysql> SELECT jsagg('
-> require("json_export.js")
-> ', category_id, name) AS json
-> FROM sakila.category
[
{
"category_id": 1,
"name": "Action"
},
...,
{
"category_id": 16,
"name": "Travel"
}
]
https://github.com/rpbouman/mysqlv8udfs
require() example:
json_export.js script
(function json_export(){
var rows, row, i, arg, args = this.arguments, n = args.length;
this.clear = function(){
rows = [];
}
this.udf = function() {
rows.push(row = {});
for (i = 0; i < n; i++) {
arg = args[i];
row[arg.name] = arg.value;
}
}
this.agg = function(){
return JSON.stringify(rows, null, " ");
}
})();
https://github.com/rpbouman/mysqlv8udfs
The console object
● Inspired by console object in web-browsers
● Methods:
– log([arg1, ..., argN])
– info([arg1, ..., argN])
– error([arg1, ..., argN])
– warn([arg1, ..., argN])
● Write arguments to a line on the standard error
stream
– Typically ends up in the mysql error log
● info(), error(), and warn() include a header:
– 2013­09­17 00:50:22 JS_DAEMON [info]: ...
https://github.com/rpbouman/mysqlv8udfs
The mysql object
● Namespace for interacting with MySQL
– Depends on libmysqlclient
mysql
client
  connect()
  
  version
connection
  close()
  commit()
  rollback()
  query()
  setAutocommit()
  charset
  connected
  hostInfo
  InsertId
  protocolVersion
  serverVersion
  statistics
  warnings
query
execute()
result()
done
sql resultset
buffered
done
fieldCount
type: "resultset"
field()
row()
resultinfo
done: true
rowCount
type: "resultinfo" 
types
    0: "decimal"
    1: "tinyint"
  .... .........
  255: "geometry"
https://github.com/rpbouman/mysqlv8udfs
Mysql client example:
inventory_held_by_customer
CREATE FUNCTION inventory_held_by_customer(p_inventory_id INT)
RETURNS INT
READS SQL DATA
BEGIN
DECLARE v_customer_id INT;
DECLARE EXIT HANDLER FOR NOT FOUND RETURN NULL;
SELECT customer_id INTO v_customer_id
FROM rental
WHERE return_date IS NULL
AND inventory_id = p_inventory_id;
RETURN v_customer_id;
END;
https://github.com/rpbouman/mysqlv8udfs
Mysql client example
(function(){
var conn;
this.init = function(){
var args = this.arguments;
if (args.length !== 1 || args[0].type !== INT_RESULT) {
throw "Single integer argument required";
}
conn = mysql.client.connect({
user: "sakila",
password: "sakila",
schema: "sakila"
});
}
this.udf = function(inventory_id){
var query = conn.query(
"SELECT customer_id FROM rental WHERE return_date IS NULL " +
"AND inventory_id = " + inventory_id
);
query.execute();
var result = query.result();
if (result.done) return null;
return result.row()[0];
}
this.deinit = function(){
conn.close();
}
})();
https://github.com/rpbouman/mysqlv8udfs
Oracle JSON functions
(Labs)
● JSON, not JavaScript
– Stick with this If you only need JSON manipulation
● That said....
– Mysqlv8udfs performance is typically slightly better, in
some cases substantially better
– JSON functions have a few bugs which can be easily
worked around using mysqlv8udfs
– Easy to emulate with mysqlv8udfs, see sample
implementations in the js project dir
https://github.com/rpbouman/mysqlv8udfs
JSON functions vs
mysqlV8UDFs example
mysql> SELECT json_append(
-> @json, 'menu', 'popup', 'menuitem', 3,
-> '{"value": "Help", "onclick": "ShowHelp()"}'
-> );
SET @json := '{
"menu": {
"id": "file", "value": "File", "popup": {
"menuitem": [
{"value": "New", "onclick": "CreateNewDoc()"},
{"value": "Open", "onclick": "OpenDoc()"},
{"value": "Close", "onclick": "CloseDoc()"}
]
}
}
}';
mysql> SELECT jsudf(
-> 'require("json_append.js");',
-> @json, 'menu', 'popup', 'menuitem', 3,
-> '{"value": "Help", "onclick": "ShowHelp()"}'
-> );
https://github.com/rpbouman/mysqlv8udfs
JSON functions vs MySQLv8UDFs
append contains key extract merge remove replace valid
0
2
4
6
8
10
12
14
json
v8
Seconds
https://github.com/rpbouman/mysqlv8udfs
Finally...
● Fork it on github. I appreciate your interest!
– https://github.com/rpbouman/mysqlv8udfs
– https://github.com/rpbouman/mysqlv8udfs/wiki
https://github.com/rpbouman/mysqlv8udfs
Questions?

Mais conteúdo relacionado

Mais procurados

Preparse Query Rewrite Plugins
Preparse Query Rewrite PluginsPreparse Query Rewrite Plugins
Preparse Query Rewrite PluginsSveta Smirnova
 
Why Use EXPLAIN FORMAT=JSON?
 Why Use EXPLAIN FORMAT=JSON?  Why Use EXPLAIN FORMAT=JSON?
Why Use EXPLAIN FORMAT=JSON? Sveta Smirnova
 
Flexviews materialized views for my sql
Flexviews materialized views for my sqlFlexviews materialized views for my sql
Flexviews materialized views for my sqlJustin Swanhart
 
Efficient Pagination Using MySQL
Efficient Pagination Using MySQLEfficient Pagination Using MySQL
Efficient Pagination Using MySQLEvan Weaver
 
11 Things About 11gr2
11 Things About 11gr211 Things About 11gr2
11 Things About 11gr2afa reg
 
New features in Performance Schema 5.7 in action
New features in Performance Schema 5.7 in actionNew features in Performance Schema 5.7 in action
New features in Performance Schema 5.7 in actionSveta Smirnova
 
MySQL Stored Procedures: Building High Performance Web Applications
MySQL Stored Procedures: Building High Performance Web ApplicationsMySQL Stored Procedures: Building High Performance Web Applications
MySQL Stored Procedures: Building High Performance Web ApplicationsOSSCube
 
MariaDB 10.5 new features for troubleshooting (mariadb server fest 2020)
MariaDB 10.5 new features for troubleshooting (mariadb server fest 2020)MariaDB 10.5 new features for troubleshooting (mariadb server fest 2020)
MariaDB 10.5 new features for troubleshooting (mariadb server fest 2020)Valeriy Kravchuk
 
Performance Schema for MySQL Troubleshooting
Performance Schema for MySQL TroubleshootingPerformance Schema for MySQL Troubleshooting
Performance Schema for MySQL TroubleshootingSveta Smirnova
 
Introducing new SQL syntax and improving performance with preparse Query Rewr...
Introducing new SQL syntax and improving performance with preparse Query Rewr...Introducing new SQL syntax and improving performance with preparse Query Rewr...
Introducing new SQL syntax and improving performance with preparse Query Rewr...Sveta Smirnova
 
Dynamic tracing of MariaDB on Linux - problems and solutions (MariaDB Server ...
Dynamic tracing of MariaDB on Linux - problems and solutions (MariaDB Server ...Dynamic tracing of MariaDB on Linux - problems and solutions (MariaDB Server ...
Dynamic tracing of MariaDB on Linux - problems and solutions (MariaDB Server ...Valeriy Kravchuk
 
Fosdem2012 replication-features-of-2011
Fosdem2012 replication-features-of-2011Fosdem2012 replication-features-of-2011
Fosdem2012 replication-features-of-2011Sergey Petrunya
 
MySQL 8.0 EXPLAIN ANALYZE
MySQL 8.0 EXPLAIN ANALYZEMySQL 8.0 EXPLAIN ANALYZE
MySQL 8.0 EXPLAIN ANALYZENorvald Ryeng
 
MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013
MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013
MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013Sergey Petrunya
 
12c Mini Lesson - Better Defaults
12c Mini Lesson - Better Defaults12c Mini Lesson - Better Defaults
12c Mini Lesson - Better DefaultsConnor McDonald
 
Moving to the NoSQL side: MySQL JSON functions
 Moving to the NoSQL side: MySQL JSON functions Moving to the NoSQL side: MySQL JSON functions
Moving to the NoSQL side: MySQL JSON functionsSveta Smirnova
 
12c Mini Lesson - Inline PLSQL from SQL
12c Mini Lesson - Inline PLSQL from SQL12c Mini Lesson - Inline PLSQL from SQL
12c Mini Lesson - Inline PLSQL from SQLConnor McDonald
 
New features-in-mariadb-and-mysql-optimizers
New features-in-mariadb-and-mysql-optimizersNew features-in-mariadb-and-mysql-optimizers
New features-in-mariadb-and-mysql-optimizersSergey Petrunya
 

Mais procurados (20)

Preparse Query Rewrite Plugins
Preparse Query Rewrite PluginsPreparse Query Rewrite Plugins
Preparse Query Rewrite Plugins
 
Why Use EXPLAIN FORMAT=JSON?
 Why Use EXPLAIN FORMAT=JSON?  Why Use EXPLAIN FORMAT=JSON?
Why Use EXPLAIN FORMAT=JSON?
 
Flexviews materialized views for my sql
Flexviews materialized views for my sqlFlexviews materialized views for my sql
Flexviews materialized views for my sql
 
Efficient Pagination Using MySQL
Efficient Pagination Using MySQLEfficient Pagination Using MySQL
Efficient Pagination Using MySQL
 
11 Things About 11gr2
11 Things About 11gr211 Things About 11gr2
11 Things About 11gr2
 
New features in Performance Schema 5.7 in action
New features in Performance Schema 5.7 in actionNew features in Performance Schema 5.7 in action
New features in Performance Schema 5.7 in action
 
MySQL Stored Procedures: Building High Performance Web Applications
MySQL Stored Procedures: Building High Performance Web ApplicationsMySQL Stored Procedures: Building High Performance Web Applications
MySQL Stored Procedures: Building High Performance Web Applications
 
Noinject
NoinjectNoinject
Noinject
 
MariaDB 10.5 new features for troubleshooting (mariadb server fest 2020)
MariaDB 10.5 new features for troubleshooting (mariadb server fest 2020)MariaDB 10.5 new features for troubleshooting (mariadb server fest 2020)
MariaDB 10.5 new features for troubleshooting (mariadb server fest 2020)
 
Performance Schema for MySQL Troubleshooting
Performance Schema for MySQL TroubleshootingPerformance Schema for MySQL Troubleshooting
Performance Schema for MySQL Troubleshooting
 
Introducing new SQL syntax and improving performance with preparse Query Rewr...
Introducing new SQL syntax and improving performance with preparse Query Rewr...Introducing new SQL syntax and improving performance with preparse Query Rewr...
Introducing new SQL syntax and improving performance with preparse Query Rewr...
 
Dynamic tracing of MariaDB on Linux - problems and solutions (MariaDB Server ...
Dynamic tracing of MariaDB on Linux - problems and solutions (MariaDB Server ...Dynamic tracing of MariaDB on Linux - problems and solutions (MariaDB Server ...
Dynamic tracing of MariaDB on Linux - problems and solutions (MariaDB Server ...
 
Fosdem2012 replication-features-of-2011
Fosdem2012 replication-features-of-2011Fosdem2012 replication-features-of-2011
Fosdem2012 replication-features-of-2011
 
MySQL 8.0 EXPLAIN ANALYZE
MySQL 8.0 EXPLAIN ANALYZEMySQL 8.0 EXPLAIN ANALYZE
MySQL 8.0 EXPLAIN ANALYZE
 
Stored procedure with cursor
Stored procedure with cursorStored procedure with cursor
Stored procedure with cursor
 
MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013
MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013
MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013
 
12c Mini Lesson - Better Defaults
12c Mini Lesson - Better Defaults12c Mini Lesson - Better Defaults
12c Mini Lesson - Better Defaults
 
Moving to the NoSQL side: MySQL JSON functions
 Moving to the NoSQL side: MySQL JSON functions Moving to the NoSQL side: MySQL JSON functions
Moving to the NoSQL side: MySQL JSON functions
 
12c Mini Lesson - Inline PLSQL from SQL
12c Mini Lesson - Inline PLSQL from SQL12c Mini Lesson - Inline PLSQL from SQL
12c Mini Lesson - Inline PLSQL from SQL
 
New features-in-mariadb-and-mysql-optimizers
New features-in-mariadb-and-mysql-optimizersNew features-in-mariadb-and-mysql-optimizers
New features-in-mariadb-and-mysql-optimizers
 

Destaque

PostgreSQL and JSON with Python - Przemek Lewandowski
PostgreSQL and JSON  with Python - Przemek Lewandowski PostgreSQL and JSON  with Python - Przemek Lewandowski
PostgreSQL and JSON with Python - Przemek Lewandowski Sunscrapers
 
LinkedIn TBC JavaScript 100: Functions
 LinkedIn TBC JavaScript 100: Functions LinkedIn TBC JavaScript 100: Functions
LinkedIn TBC JavaScript 100: FunctionsAdam Crabtree
 
Hcad competencies booklet (2) (1)
Hcad competencies booklet (2) (1)Hcad competencies booklet (2) (1)
Hcad competencies booklet (2) (1)Ngonde
 
JavaScript Conditional Statements
JavaScript Conditional StatementsJavaScript Conditional Statements
JavaScript Conditional StatementsMarlon Jamera
 
JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript FunctionsBrian Moschel
 
JavaScript Control Statements I
JavaScript Control Statements IJavaScript Control Statements I
JavaScript Control Statements IReem Alattas
 
Javascript conditional statements
Javascript conditional statementsJavascript conditional statements
Javascript conditional statementsnobel mujuji
 
Geek Sync | Using PowerShell with Python and SQL Server
Geek Sync | Using PowerShell with Python and SQL ServerGeek Sync | Using PowerShell with Python and SQL Server
Geek Sync | Using PowerShell with Python and SQL ServerIDERA Software
 
Javascript Function
Javascript FunctionJavascript Function
Javascript Functionxxbeta
 

Destaque (11)

PostgreSQL and JSON with Python - Przemek Lewandowski
PostgreSQL and JSON  with Python - Przemek Lewandowski PostgreSQL and JSON  with Python - Przemek Lewandowski
PostgreSQL and JSON with Python - Przemek Lewandowski
 
LinkedIn TBC JavaScript 100: Functions
 LinkedIn TBC JavaScript 100: Functions LinkedIn TBC JavaScript 100: Functions
LinkedIn TBC JavaScript 100: Functions
 
Hcad competencies booklet (2) (1)
Hcad competencies booklet (2) (1)Hcad competencies booklet (2) (1)
Hcad competencies booklet (2) (1)
 
JavaScript Conditional Statements
JavaScript Conditional StatementsJavaScript Conditional Statements
JavaScript Conditional Statements
 
JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript Functions
 
JavaScript Control Statements I
JavaScript Control Statements IJavaScript Control Statements I
JavaScript Control Statements I
 
Loops in JavaScript
Loops in JavaScriptLoops in JavaScript
Loops in JavaScript
 
Javascript conditional statements
Javascript conditional statementsJavascript conditional statements
Javascript conditional statements
 
Loops in java script
Loops in java scriptLoops in java script
Loops in java script
 
Geek Sync | Using PowerShell with Python and SQL Server
Geek Sync | Using PowerShell with Python and SQL ServerGeek Sync | Using PowerShell with Python and SQL Server
Geek Sync | Using PowerShell with Python and SQL Server
 
Javascript Function
Javascript FunctionJavascript Function
Javascript Function
 

Semelhante a Writing MySQL User-defined Functions in JavaScript

Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
Emerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the HorizonEmerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the HorizonAlex Payne
 
CS101- Introduction to Computing- Lecture 35
CS101- Introduction to Computing- Lecture 35CS101- Introduction to Computing- Lecture 35
CS101- Introduction to Computing- Lecture 35Bilal Ahmed
 
Introduction To PostGIS
Introduction To PostGISIntroduction To PostGIS
Introduction To PostGISmleslie
 
Python 101 language features and functional programming
Python 101 language features and functional programmingPython 101 language features and functional programming
Python 101 language features and functional programmingLukasz Dynowski
 
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak   CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak PROIDEA
 
C c++-meetup-1nov2017-autofdo
C c++-meetup-1nov2017-autofdoC c++-meetup-1nov2017-autofdo
C c++-meetup-1nov2017-autofdoKim Phillips
 
User Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love StoryUser Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love StoryDatabricks
 
User Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love StoryUser Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love StoryDatabricks
 
Php in 2013 (Web-5 2013 conference)
Php in 2013 (Web-5 2013 conference)Php in 2013 (Web-5 2013 conference)
Php in 2013 (Web-5 2013 conference)julien pauli
 
Swift for tensorflow
Swift for tensorflowSwift for tensorflow
Swift for tensorflow규영 허
 
(Almost) Serverless Analytics System with BigQuery & AppEngine
(Almost) Serverless Analytics System with BigQuery & AppEngine(Almost) Serverless Analytics System with BigQuery & AppEngine
(Almost) Serverless Analytics System with BigQuery & AppEngineGabriel PREDA
 
pg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQLpg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQLCommand Prompt., Inc
 
pg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQLpg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQLMark Wong
 
FS2 for Fun and Profit
FS2 for Fun and ProfitFS2 for Fun and Profit
FS2 for Fun and ProfitAdil Akhter
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015Michiel Borkent
 

Semelhante a Writing MySQL User-defined Functions in JavaScript (20)

Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Emerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the HorizonEmerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the Horizon
 
Pdxpugday2010 pg90
Pdxpugday2010 pg90Pdxpugday2010 pg90
Pdxpugday2010 pg90
 
CS101- Introduction to Computing- Lecture 35
CS101- Introduction to Computing- Lecture 35CS101- Introduction to Computing- Lecture 35
CS101- Introduction to Computing- Lecture 35
 
Introduction To PostGIS
Introduction To PostGISIntroduction To PostGIS
Introduction To PostGIS
 
Python 101 language features and functional programming
Python 101 language features and functional programmingPython 101 language features and functional programming
Python 101 language features and functional programming
 
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak   CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
 
C c++-meetup-1nov2017-autofdo
C c++-meetup-1nov2017-autofdoC c++-meetup-1nov2017-autofdo
C c++-meetup-1nov2017-autofdo
 
User Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love StoryUser Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love Story
 
User Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love StoryUser Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love Story
 
Php in 2013 (Web-5 2013 conference)
Php in 2013 (Web-5 2013 conference)Php in 2013 (Web-5 2013 conference)
Php in 2013 (Web-5 2013 conference)
 
Groovy
GroovyGroovy
Groovy
 
Swift for tensorflow
Swift for tensorflowSwift for tensorflow
Swift for tensorflow
 
(Almost) Serverless Analytics System with BigQuery & AppEngine
(Almost) Serverless Analytics System with BigQuery & AppEngine(Almost) Serverless Analytics System with BigQuery & AppEngine
(Almost) Serverless Analytics System with BigQuery & AppEngine
 
Writing MySQL UDFs
Writing MySQL UDFsWriting MySQL UDFs
Writing MySQL UDFs
 
Performance tests - it's a trap
Performance tests - it's a trapPerformance tests - it's a trap
Performance tests - it's a trap
 
pg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQLpg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQL
 
pg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQLpg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQL
 
FS2 for Fun and Profit
FS2 for Fun and ProfitFS2 for Fun and Profit
FS2 for Fun and Profit
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015
 

Mais de Roland Bouman

Beyond OData: Introducing the XML/A model for ui5
Beyond OData: Introducing the XML/A model for ui5Beyond OData: Introducing the XML/A model for ui5
Beyond OData: Introducing the XML/A model for ui5Roland Bouman
 
Moving and Transforming Data with Pentaho Data Integration 5.0 CE (aka Kettle)
Moving and Transforming Data with Pentaho Data Integration 5.0 CE (aka Kettle)Moving and Transforming Data with Pentaho Data Integration 5.0 CE (aka Kettle)
Moving and Transforming Data with Pentaho Data Integration 5.0 CE (aka Kettle)Roland Bouman
 
2. writing MySql plugins general
2. writing MySql plugins   general2. writing MySql plugins   general
2. writing MySql plugins generalRoland Bouman
 
Common schema my sql uc 2012
Common schema   my sql uc 2012Common schema   my sql uc 2012
Common schema my sql uc 2012Roland Bouman
 
Common schema my sql uc 2012
Common schema   my sql uc 2012Common schema   my sql uc 2012
Common schema my sql uc 2012Roland Bouman
 
Roland bouman modern_data_warehouse_architectures_data_vault_and_anchor_model...
Roland bouman modern_data_warehouse_architectures_data_vault_and_anchor_model...Roland bouman modern_data_warehouse_architectures_data_vault_and_anchor_model...
Roland bouman modern_data_warehouse_architectures_data_vault_and_anchor_model...Roland Bouman
 

Mais de Roland Bouman (9)

Beyond OData: Introducing the XML/A model for ui5
Beyond OData: Introducing the XML/A model for ui5Beyond OData: Introducing the XML/A model for ui5
Beyond OData: Introducing the XML/A model for ui5
 
Moving and Transforming Data with Pentaho Data Integration 5.0 CE (aka Kettle)
Moving and Transforming Data with Pentaho Data Integration 5.0 CE (aka Kettle)Moving and Transforming Data with Pentaho Data Integration 5.0 CE (aka Kettle)
Moving and Transforming Data with Pentaho Data Integration 5.0 CE (aka Kettle)
 
Xmla4js
Xmla4jsXmla4js
Xmla4js
 
Xml4js pentaho
Xml4js pentahoXml4js pentaho
Xml4js pentaho
 
2. writing MySql plugins general
2. writing MySql plugins   general2. writing MySql plugins   general
2. writing MySql plugins general
 
1. MySql plugins
1. MySql plugins1. MySql plugins
1. MySql plugins
 
Common schema my sql uc 2012
Common schema   my sql uc 2012Common schema   my sql uc 2012
Common schema my sql uc 2012
 
Common schema my sql uc 2012
Common schema   my sql uc 2012Common schema   my sql uc 2012
Common schema my sql uc 2012
 
Roland bouman modern_data_warehouse_architectures_data_vault_and_anchor_model...
Roland bouman modern_data_warehouse_architectures_data_vault_and_anchor_model...Roland bouman modern_data_warehouse_architectures_data_vault_and_anchor_model...
Roland bouman modern_data_warehouse_architectures_data_vault_and_anchor_model...
 

Último

New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 

Último (20)

New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 

Writing MySQL User-defined Functions in JavaScript

  • 2. https://github.com/rpbouman/mysqlv8udfs Welcome! ● @rolandbouman ● roland.bouman@gmail.com ● http://rpbouman.blogspot.com/ ● http://www.linkedin.com/in/rpbouman ● http://www.slideshare.net/rpbouman ● Ex-MySQL AB, Ex-Sun Microsystems ● Currently at http://www.pentaho.com/
  • 3. https://github.com/rpbouman/mysqlv8udfs MySQL Programmability ● SQL ● Persistent Stored Modules (Stored Routines) ● User-defined functions (UDFs)
  • 4. https://github.com/rpbouman/mysqlv8udfs MySQLv8UDFs: JavaScript Programmability ● https://github.com/rpbouman/mysqlv8udfs ● Based on Google's V8 ● More than just executing JavaScript: – Scriptable front for MySQL's native UDF interface
  • 5. https://github.com/rpbouman/mysqlv8udfs MySQL stored routines ● “Standard” SQL/PSM syntax – Scalar functions – Procedures – Triggers – Events ● Stored in the data dictionary ● Interpreted
  • 6. https://github.com/rpbouman/mysqlv8udfs MySQL UDFs ● External binary library (typically C/C++): – Scalar functions – Aggregate functions ● Registered in the data dictionary ● Compiled Native code
  • 7. https://github.com/rpbouman/mysqlv8udfs JavaScript UDFs. Why? ● Started as a UDF example ● Inspired by drizzle's js() function ● Turned out to have real benefits: – Convenient manipulation of JSON blobs – Safer and easier than 'real' C/C++ UDFs – More expressive than SQL/PSM – Sometimes much faster than stored routines*
  • 8. https://github.com/rpbouman/mysqlv8udfs Intermezzo: Easter day as stored SQL functionCREATE FUNCTION easter_day(dt DATETIME) RETURNS DATE DETERMINISTIC NO SQL SQL SECURITY INVOKER COMMENT 'Returns date of easter day for given year' BEGIN DECLARE p_year SMALLINT DEFAULT YEAR(dt); DECLARE a SMALLINT DEFAULT p_year % 19; DECLARE b SMALLINT DEFAULT p_year DIV 100; DECLARE c SMALLINT DEFAULT p_year % 100; DECLARE e SMALLINT DEFAULT b % 4; DECLARE h SMALLINT DEFAULT (19*a + b - (b DIV 4) - ( (b - ((b + 8) DIV 25) + 1) DIV 3 ) + 15) % 30; DECLARE L SMALLINT DEFAULT (32 + 2*e + 2*(c DIV 4) - h - (c % 4)) % 7; DECLARE v100 SMALLINT DEFAULT h + L - 7*((a + 11*h + 22*L) DIV 451) + 114; RETURN STR_TO_DATE( CONCAT( p_year , '-' , v100 DIV 31 , '-' , (v100 % 31) + 1 ) , '%Y-%c-%e' ); END;
  • 9. https://github.com/rpbouman/mysqlv8udfs Intermezzo: Easter day in JavaScript (js UDF) mysql> SELECT js(' '> var y = parseInt(arguments[0].substr(0,4), 10), '> a = y % 19, b = Math.floor(y / 100), '> c = y % 100, d = Math.floor(b / 4), '> e = b % 4, f = Math.floor((b + 8) / 25), '> g = Math.floor((b - f + 1) / 3), '> h = (19 * a + b - d - g + 15) % 30, '> i = Math.floor(c / 4), k = c % 4, '> L = (32 + 2 * e + 2 * i - h - k) % 7, '> m = Math.floor((a + 11 * h + 22 * L) / 451), '> n = h + L - 7 * m + 114, '> M = Math.floor(n/31), D = (n%31)+1; '> if (M < 10) M = "0" + M; '> if (D < 10) D = "0" + D; '> '> y + "-" + M + "-" + D; '> '>', NOW());
  • 10. https://github.com/rpbouman/mysqlv8udfs Intermezzo: Easter day as SQL expressionSTR_TO_DATE(CONCAT(YEAR(now()), '-', (((19*(YEAR(now()) % 19) + (YEAR(now()) DIV 100) - ((YEAR(now()) DIV 100) DIV 4) - (((YEAR(now()) DIV 100) - (((YEAR(now()) DIV 100) + 8) DIV 25) + 1) DIV 3) + 15) % 30) + ((32 + 2*((YEAR(now()) DIV 100) % 4) + 2*((YEAR(now()) % 100) DIV 4) - ((19*(YEAR(now()) % 19) + (YEAR(now()) DIV 100) - ((YEAR(now()) DIV 100) DIV 4) - (((YEAR(now()) DIV 100) - (((YEAR(now()) DIV 100) + 8) DIV 25) + 1) DIV 3) + 15) % 30) - ((YEAR(now()) % 100) % 4)) % 7) - 7*(((YEAR(now()) % 19) + 11*((19*(YEAR(now()) % 19) + (YEAR(now()) DIV 100) - ((YEAR(now()) DIV 100) DIV 4) - (((YEAR(now()) DIV 100) - (((YEAR(now()) DIV 100) + 8) DIV 25) + 1) DIV 3) + 15) % 30) + 22*((32 + 2*((YEAR(now()) DIV 100) % 4) + 2*((YEAR(now()) % 100) DIV 4) - ((19*(YEAR(now()) % 19) + (YEAR(now()) DIV 100) - ((YEAR(now()) DIV 100) DIV 4) - (((YEAR(now()) DIV 100) - (((YEAR(now()) DIV 100) + 8) DIV 25) + 1) DIV 3) + 15) % 30) - ((YEAR(now()) % 100) % 4)) % 7)) DIV 451) + 114) DIV 31, '-', ((((19*(YEAR(now()) % 19) + (YEAR(now()) DIV 100) - ((YEAR(now()) DIV 100) DIV 4) - (((YEAR(now()) DIV 100) - (((YEAR(now()) DIV 100) + 8) DIV 25) + 1) DIV 3) + 15) % 30) + ((32 + 2*((YEAR(now()) DIV 100) % 4) + 2*((YEAR(now()) % 100) DIV 4) - ((19*(YEAR(now()) % 19) + (YEAR(now()) DIV 100) - ((YEAR(now()) DIV 100) DIV 4) - (((YEAR(now()) DIV 100) - (((YEAR(now()) DIV 100) + 8) DIV 25) + 1) DIV 3) + 15) % 30) - ((YEAR(now()) % 100) % 4)) % 7) - 7*(((YEAR(now()) % 19) + 11*((19*(YEAR(now()) % 19) + (YEAR(now()) DIV 100) - ((YEAR(now()) DIV 100) DIV 4) - (((YEAR(now()) DIV 100) - (((YEAR(now()) DIV 100) + 8) DIV 25) + 1) DIV 3) + 15) % 30) + 22*((32 + 2*((YEAR(now()) DIV 100) % 4) + 2*((YEAR(now()) % 100) DIV 4) - ((19*(YEAR(now()) % 19) + (YEAR(now()) DIV 100) - ((YEAR(now()) DIV 100) DIV 4) - (((YEAR(now()) DIV 100) - (((YEAR(now()) DIV 100) + 8) DIV 25) + 1) DIV 3) + 15) % 30) - ((YEAR(now()) % 100) % 4)) % 7)) DIV 451) + 114) % 31) + 1), '%Y-%c-%e')
  • 11. https://github.com/rpbouman/mysqlv8udfs Intermezzo: Easter day Performance comparison SQL Expression SQL Stored Function JavaScript UDF 0 2 4 6 8 10 12 14 4.61 12.53 2.66 Easter Day Performance (1.000.000) time(seconds)
  • 12. https://github.com/rpbouman/mysqlv8udfs The mysqlv8udfs project ● Scalar Functions: – js() – jsudf() – jserr() ● Aggregate Functions: – jsagg() ● Daemon plugin*: – JS_DAEMON
  • 13. https://github.com/rpbouman/mysqlv8udfs The JS_DAEMON Plugin mysql> SHOW VARIABLES LIKE 'js%'; +-----------------------+--------------------------------------+ | Variable_name | Value | +-----------------------+--------------------------------------+ | js_daemon_module_path | /home/rbouman/mysql/mysql/lib/plugin | +-----------------------+--------------------------------------+ 1 row in set (0.03 sec) mysql> SHOW STATUS LIKE 'js%'; +----------------------------------+-----------+ | Variable_name | Value | +----------------------------------+-----------+ | js_daemon_version | 0.0.1 | | js_v8_heap_size_limit | 2048 | | js_v8_heap_size_total | 942944256 | | js_v8_heap_size_total_executable | 959591424 | | js_v8_heap_size_used | 892941672 | | js_v8_is_dead | false | | js_v8_is_execution_terminating | false | | js_v8_is_profiler_paused | true | | js_v8_version | 3.7.12.22 | +----------------------------------+-----------+ 9 rows in set (0.00 sec)
  • 14. https://github.com/rpbouman/mysqlv8udfs The js() UDF ● js(script[, arg1, …, argN]) – Execute script – Return value (as string) of the last js expression ● Optional arguments arg1 … argN – Accessible via the built-in arguments array – arg1 accessible as arguments[0] (and so on) ● Script* – if constant it is compiled only once – executed for each row
  • 15. https://github.com/rpbouman/mysqlv8udfs The js() UDF: Example mysql> SELECT js(' '> arguments[0] + arguments[1]; '> ', 1, 2) AS example -> ; +---------+ | example | +---------+ | 3 | +---------+ 1 row in set (0.03 sec)
  • 16. https://github.com/rpbouman/mysqlv8udfs The MySQL UDF interface ● Simple functions (scalars) and aggregates ● Native library callbacks (calling sequence) – Plugin directory – mysql.func table ● Data structures – Return value: struct UDF_INIT *initid – Arguments: struct UDF_ARGS *args CREATE [AGGREGATE] FUNCTION name RETURNS (STRING | REAL | INTEGER) SONAME 'libraryfile'
  • 17. https://github.com/rpbouman/mysqlv8udfs UDF JavaScript binding ● Scalars: jsudf(), Aggregates: jsagg() – Return value is always a MySQL STRING ● Script argument: – Constant. Compiled and immediately executed (1x) – JavaScript callbacks defined in script are called during the native UDF calling sequence ● UDF data structures scriptable at runtime: – Members of struct UDF_INIT appear as js globals – struct UDF_ARGS as global arguments object
  • 18. https://github.com/rpbouman/mysqlv8udfs The jsudf() UDF ● jsudf(script[, arg1, …, argN]) – Call the init() callback (optional) – For each row, return the result of the udf() callback – Call the deinit() callback (optional) init() udf() deinit()More rows? No Yes
  • 19. https://github.com/rpbouman/mysqlv8udfs jsudf() example: running total mysql> SELECT amount, jsudf(' -> var total; -> function init(){ -> console.info("Init"); -> total = 0; -> } -> function udf(num){ -> console.info("processing row"); -> return total += num; -> } -> function deinit(){ -> console.info("Deinit"); -> } -> ', amount) AS running_total -> FROM sakila.payment ORDER BY payment_date
  • 20. https://github.com/rpbouman/mysqlv8udfs jsudf() example: resultset and error log +--------+--------------------+ | amount | running_total | +--------+--------------------+ | 2.99 | 2.99 | | 2.99 | 5.98 | . ... . ... . | 4.99 | 67416.5099999921 | +--------+--------------------+ 16049 rows in set (0.29 sec) 2013-09-16 14:31:44 JS_DAEMON [info]: Init 2013-09-16 14:31:44 JS_DAEMON [info]: processing row .... .. .. .. .. .. .. ...... ...... .............. 2013-09-16 14:31:44 JS_DAEMON [info]: processing row 2013-09-16 14:31:44 JS_DAEMON [info]: Deinit
  • 21. https://github.com/rpbouman/mysqlv8udfs jsudf() Argument processing ● Arguments beyond the initial script argument: – Values passed to the udf() callback – UDF_ARGS scriptable as global arguments array – WARNING: In javascript functions, the local built-in arguments object refers to actual arguments – Local arguments mask the global arguments object. – Use this.arguments to refer to the global array of argument objects. ● Use init() to validate or pre-process arguments
  • 22. https://github.com/rpbouman/mysqlv8udfs jsudf() global arguments mysql> SELECT jsudf(' -> function udf(){ -> //this.arguments describes the -> //arguments passed to jsudf -> -> return JSON.stringify( -> this.arguments, -> null, " " -> ); -> } -> ', 'string', PI() AS "real", 1, 2.3)
  • 23. https://github.com/rpbouman/mysqlv8udfs jsudf() global arguments [ { "name": "'string'", "type": 0, "max_length": 6, "maybe_null": false, "const_item": true, "value": "string" }, { "name": "real", "type": 1, "max_length": 8, "maybe_null": false, "const_item": true, "value": 3.141592653589793 }, { "name": "1", "type": 2, "max_length": 1, "maybe_null": false, "const_item": true, "value": 1 }, { "name": "2.3", "type": 4, "max_length": 3, "maybe_null": false, "const_item": true, "value": 2.3 } ]
  • 24. https://github.com/rpbouman/mysqlv8udfs jsudf() local arguments (actual arguments) mysql> SELECT jsudf(' -> function udf(){ -> //standard, built-in javascript arguments -> //contains argument values passed to this function -> return JSON.stringify( -> arguments, -> null, " " -> ); -> } -> ', 'string', PI() AS "real", 1, 2.3) { "0": "string", "1": 3.141592653589793, "2": 1, "3": 2.3 }
  • 25. https://github.com/rpbouman/mysqlv8udfs jsudf() named arguments SELECT jsudf(' function udf( arg1, arg2, arg3, arg4 ){ //values of named argument are available //as local variables return "arg1: " + arg1 + "n" + "arg2: " + arg2 + "n" + "arg3: " + arg3 + "n" + "arg4: " + arg4; } ', 'string', PI() AS "real", 1, 2.3) arg1: string arg2: 3.141592653589793 arg3: 1 arg4: 2.3
  • 26. https://github.com/rpbouman/mysqlv8udfs The Argument object ● name: Expression text. If provided, the alias ● type: code indicating the runtime data type – 0: STRING_RESULT, 1: REAL_RESULT, 4: DECIMAL_RESULT ● max_length: maximum string length ● maybe_null: true if nullable ● const_item: true if value is constant ● value: argument value
  • 27. https://github.com/rpbouman/mysqlv8udfs Argument Processing: Validating count and types function init(){ var args = this.arguments, nargs = args.length ; //validate the number of arguments: if (nargs != 1) throw "Expected exactly 1 argument"; //validate argument type: var arg = args[0]; switch (arg.type) { case REAL_RESULT: case INT_RESULT: case DECIMAL_RESULT: break; default: throw "Argument must be numeric"; } }
  • 28. https://github.com/rpbouman/mysqlv8udfs Data type Mapping+------------------------+------------------------+---------------------+-------------+---------+ | Type family | MySQL column data type | MYSQL UDF data type | v8 type | JS Type | +------------------------+------------------------+---------------------+-------------+---------+ | Integral numbers | BIGINT | INT_RESULT | v8::Integer | Number | | | INT | | or | | | | MEDIUMINT | | v8::Number | | | | SMALLINT | | | | | | TINYINT | | | | +------------------------+------------------------+---------------------+-------------| | | Floating point numbers | DOUBLE | REAL_RESULT | v8::Number | | | | FLOAT | | | | +------------------------+------------------------+---------------------+ | | | Decimal numbers | DECIMAL | DECIMAL_RESULT | | | +------------------------+------------------------+---------------------+-------------+---------+ | Binary String | BINARY | STRING_RESULT | v8::String | String | | | BLOB | | | | | | LONGBLOB | | | | | | MEDIUMBLOB | | | | | | VARBINARY | | | | | | TINYBLOB | | | | +------------------------+------------------------+ | | | | Character String | CHAR | | | | | | LONGTEXT | | | | | | MEDIUMTEXT | | | | | | VARCHAR | | | | | | TEXT | | | | | | TINYTEXT | | | | +------------------------+------------------------+ | | | | Structured String | ENUM | | | | | | SET | | | | +------------------------+------------------------+ | | | | Temporal | DATE | | | | | | DATETIME | | | | | | TIME | | | | | | TIMESTAMP | | | | +------------------------+------------------------+---------------------+-------------+---------+
  • 29. https://github.com/rpbouman/mysqlv8udfs The jsagg() UDF ● jsagg(script[, arg1, …, argN]) – Call the init() callback (optional) – Calls clear() before processing a group of rows – For each row in a group, the udf() callback is called – After processing a group, the agg() is called to return the aggregate value – Call the deinit() callback (optional)
  • 30. https://github.com/rpbouman/mysqlv8udfs The jsagg() UDF init() deinit() More rows? No Yes clear() agg() udf() More groups? Yes No
  • 31. https://github.com/rpbouman/mysqlv8udfs jsagg() example: JSON export mysql> SELECT jsagg(' -> var rows, args = arguments, n = args.length; -> function clear(){ -> console.info("clear"); -> rows = []; -> } -> function udf(){ -> console.info("udf"); -> var i, arg, row = {}; -> for (i = 0; i < n; i++){ -> arg = args[i]; -> row[arg.name] = arg.value; -> } -> rows.push(row); -> } -> function agg(){ -> console.info("agg"); -> return JSON.stringify(rows, null, " "); -> } -> ', film_id, title, release_year, description) AS json -> FROM sakila.film GROUP BY rating;
  • 32. https://github.com/rpbouman/mysqlv8udfs jsagg() example: result [ { "film_id": 1, "title": "ACADEMY DINOSAUR", "release_year": 2006, "description": "A Epic Drama of ... in The Canadian Rockies" }, ..., ..., { "film_id": 1000, "title": "ZORRO ARK", "release_year": 2006, "description": "A Intrepid Panorama of ... in A Monastery" } ]
  • 33. https://github.com/rpbouman/mysqlv8udfs jsagg() example: error log 2013-09-16 23:36:45 JS_DAEMON [info]: Clear 2013-09-16 23:36:45 JS_DAEMON [info]: Udf .... .. .. .. .. .. .. ...... .... ... 2013-09-16 23:36:45 JS_DAEMON [info]: Udf 2013-09-16 23:36:45 JS_DAEMON [info]: Agg 2013-09-16 23:36:45 JS_DAEMON [info]: Clear 2013-09-16 23:36:45 JS_DAEMON [info]: Udf .... .. .. .. .. .. .. ...... .... ... 2013-09-16 23:36:45 JS_DAEMON [info]: Udf 2013-09-16 23:36:45 JS_DAEMON [info]: Agg .... .. .. .. .. .. .. ...... .... ... .... .. .. .. .. .. .. ...... .... ... 2013-09-16 23:36:45 JS_DAEMON [info]: Clear 2013-09-16 23:36:45 JS_DAEMON [info]: Udf .... .. .. .. .. .. .. ...... .... ... 2013-09-16 23:36:45 JS_DAEMON [info]: Udf 2013-09-16 23:36:45 JS_DAEMON [info]: Agg
  • 34. https://github.com/rpbouman/mysqlv8udfs JavaScript Environment ● JavaScript Standard built-ins: – Constructors (Date, RegExp, String etc.) – Static objects (JSON, Math) – Misc. functions (decodeURI, parseInt etc.) ● Globals provided by mysqlv8udfs * – arguments[] array – Some UDF interface variables and constants – require() function – console object – mysql object
  • 35. https://github.com/rpbouman/mysqlv8udfs The require() function ● Inspired by commonjs Module loading ● Signature: require(filename[, reload]) – Loads script file from the js_daemon_module_path – Executes the script and returns the result – Script is compiled and cached for reuse – Pass true as 2nd argument to force reload from file ● js_daemon_module_path – Read-only system variable of the JS_DAEMON plugin – Specified at mysqld command line or option file – Prevent loading arbitrary script files
  • 36. https://github.com/rpbouman/mysqlv8udfs require() example: mysql> SELECT jsagg(' -> require("json_export.js") -> ', category_id, name) AS json -> FROM sakila.category [ { "category_id": 1, "name": "Action" }, ..., { "category_id": 16, "name": "Travel" } ]
  • 37. https://github.com/rpbouman/mysqlv8udfs require() example: json_export.js script (function json_export(){ var rows, row, i, arg, args = this.arguments, n = args.length; this.clear = function(){ rows = []; } this.udf = function() { rows.push(row = {}); for (i = 0; i < n; i++) { arg = args[i]; row[arg.name] = arg.value; } } this.agg = function(){ return JSON.stringify(rows, null, " "); } })();
  • 38. https://github.com/rpbouman/mysqlv8udfs The console object ● Inspired by console object in web-browsers ● Methods: – log([arg1, ..., argN]) – info([arg1, ..., argN]) – error([arg1, ..., argN]) – warn([arg1, ..., argN]) ● Write arguments to a line on the standard error stream – Typically ends up in the mysql error log ● info(), error(), and warn() include a header: – 2013­09­17 00:50:22 JS_DAEMON [info]: ...
  • 39. https://github.com/rpbouman/mysqlv8udfs The mysql object ● Namespace for interacting with MySQL – Depends on libmysqlclient mysql client   connect()      version connection   close()   commit()   rollback()   query()   setAutocommit()   charset   connected   hostInfo   InsertId   protocolVersion   serverVersion   statistics   warnings query execute() result() done sql resultset buffered done fieldCount type: "resultset" field() row() resultinfo done: true rowCount type: "resultinfo"  types     0: "decimal"     1: "tinyint"   .... .........   255: "geometry"
  • 40. https://github.com/rpbouman/mysqlv8udfs Mysql client example: inventory_held_by_customer CREATE FUNCTION inventory_held_by_customer(p_inventory_id INT) RETURNS INT READS SQL DATA BEGIN DECLARE v_customer_id INT; DECLARE EXIT HANDLER FOR NOT FOUND RETURN NULL; SELECT customer_id INTO v_customer_id FROM rental WHERE return_date IS NULL AND inventory_id = p_inventory_id; RETURN v_customer_id; END;
  • 41. https://github.com/rpbouman/mysqlv8udfs Mysql client example (function(){ var conn; this.init = function(){ var args = this.arguments; if (args.length !== 1 || args[0].type !== INT_RESULT) { throw "Single integer argument required"; } conn = mysql.client.connect({ user: "sakila", password: "sakila", schema: "sakila" }); } this.udf = function(inventory_id){ var query = conn.query( "SELECT customer_id FROM rental WHERE return_date IS NULL " + "AND inventory_id = " + inventory_id ); query.execute(); var result = query.result(); if (result.done) return null; return result.row()[0]; } this.deinit = function(){ conn.close(); } })();
  • 42. https://github.com/rpbouman/mysqlv8udfs Oracle JSON functions (Labs) ● JSON, not JavaScript – Stick with this If you only need JSON manipulation ● That said.... – Mysqlv8udfs performance is typically slightly better, in some cases substantially better – JSON functions have a few bugs which can be easily worked around using mysqlv8udfs – Easy to emulate with mysqlv8udfs, see sample implementations in the js project dir
  • 43. https://github.com/rpbouman/mysqlv8udfs JSON functions vs mysqlV8UDFs example mysql> SELECT json_append( -> @json, 'menu', 'popup', 'menuitem', 3, -> '{"value": "Help", "onclick": "ShowHelp()"}' -> ); SET @json := '{ "menu": { "id": "file", "value": "File", "popup": { "menuitem": [ {"value": "New", "onclick": "CreateNewDoc()"}, {"value": "Open", "onclick": "OpenDoc()"}, {"value": "Close", "onclick": "CloseDoc()"} ] } } }'; mysql> SELECT jsudf( -> 'require("json_append.js");', -> @json, 'menu', 'popup', 'menuitem', 3, -> '{"value": "Help", "onclick": "ShowHelp()"}' -> );
  • 44. https://github.com/rpbouman/mysqlv8udfs JSON functions vs MySQLv8UDFs append contains key extract merge remove replace valid 0 2 4 6 8 10 12 14 json v8 Seconds
  • 45. https://github.com/rpbouman/mysqlv8udfs Finally... ● Fork it on github. I appreciate your interest! – https://github.com/rpbouman/mysqlv8udfs – https://github.com/rpbouman/mysqlv8udfs/wiki