~drizzle-trunk/drizzle/development

2457.1.1 by Henrik Ingo
Fixes to the new documentation in lp:~daniel-nichter/drizzle/7.1-docs
1
.. _js_plugin:
2
2370.2.17 by Henrik Ingo
Wrote end user documentation for JS().
3
JS
4
===========
5
6
.. code-block:: mysql
7
8
	JS(javascript_code [, arg1 [AS arg_name]] [, ...]) 
9
10
``JS()`` executes a JavaScript code snippet and returns the value of the last executed statement. Additional arguments are passed to the JavaScript environment and are available in the ``arguments[]`` array. If the optional ``AS arg_name`` is used, the same argument value is made available as a global variable with that name.
11
12
13
.. _js_loading:
14
15
Loading
16
-------
17
18
This plugin is loaded by default.
19
20
If you want to prevent the loading of this plugin, start :program:`drizzled` with::
21
22
   --plugin-remove=js
23
24
.. _js_examples:
25
26
Examples
27
--------
28
29
The first argument is required and should be a string of valid JavaScript code. The value of the last statement is returned, note that you should not use a ``return`` keyword. This is a top level JavaScript code snippet, not a JavaScript function.
30
31
.. code-block:: mysql
32
33
	SELECT JS('var d = new Date(); "Drizzle started running JavaScript at: " + d;');
34
35
Will output
36
37
+----------------------------------------------------------------------------------+
38
| JS('var d = new Date(); "Drizzle started running JavaScript at: " + d;')         |
39
+==================================================================================+
40
| Drizzle started running JavaScript at: Mon Aug 29 2011 00:23:31 GMT+0300 (EEST)  |
41
+----------------------------------------------------------------------------------+
42
43
44
Additional arguments are passed to the JavaScript environment and are available in the ``arguments[]`` array. 
45
46
.. code-block:: mysql
47
48
	SELECT JS("arguments[0] + arguments[1] + arguments[2];", 1, 2, 3) AS 'JS(...)';
49
50
Will output
51
52
+--------------+
53
| JS(...)      |
54
+==============+
55
| 6            |
56
+--------------+
57
58
59
60
If the optional ``AS arg_name`` is used, the same argument value is made available as a global variable with that name.
61
62
.. code-block:: mysql
63
64
	SELECT JS("first + second + third;", 1 AS 'first', 2.0 AS 'second', 3.5 AS 'third') AS 'JS(...)';
65
66
Will output
67
68
+--------------+
69
| JS(...)      |
70
+==============+
71
| 6.5          |
72
+--------------+
73
74
.. _json_parse:
75
76
Using JS() to parse JSON documents
77
-----------------------------------
78
79
JavaScript includes a JSON parser. This means you can use ``JS()`` as a JSON parser, and optionally use JavaScript to manipulate or select fragments of the JSON document. To do this, pass your JSON document as an argument, and use the ``JSON.parse()`` method to return it as a JavaScript object:
80
81
.. code-block:: mysql
82
83
	SELECT JS("var jsondoc = JSON.parse(arguments[0]); jsondoc['name']['firstname'];", 
84
	          '{ "name" : {"firstname" : "Henrik", "lastname" : "Ingo"} }') AS 'JS(...)';
85
86
Will output
87
88
+--------------+
89
| JS(...)      |
90
+==============+
91
| Henrik       |
92
+--------------+
93
94
95
To return a JSON document from JavaScript, use ``JSON.stringify()``:
96
97
.. code-block:: mysql
98
99
	SELECT JS("var jsondoc = JSON.parse(arguments[0]); 
100
	           JSON.stringify(jsondoc['name']);", 
101
	          '{ "name" : {"firstname" : "Henrik", "lastname" : "Ingo"} }') AS 'JS(...)';
102
103
104
Will output
105
106
+------------------------------------------+
107
| JS(...)                                  |
108
+==========================================+
109
| {"firstname":"Henrik","lastname":"Ingo"} |
110
+------------------------------------------+
111
112
Note that since a Drizzle function can only return scalar values, if you want to return arrays or objects from your JavaScript, JSON is a recommended way of doing that.
113
114
.. _js_queries:
115
116
Using JS in queries, passing columns as arguments
117
-------------------------------------------------
118
119
Naturally, the arguments can also be columns in a query. For instance in the case of JSON data, if you have stored JSON documents as TEXT or BLOB in a table, you can now use ``JSON.parse()`` to select individual fields out of it:
120
121
.. code-block:: mysql
122
123
	CREATE TABLE t (k INT PRIMARY KEY auto_increment, v TEXT);
124
	INSERT INTO t (v) VALUES ('{ "person" : { "firstname" : "Roland", "lastname" : "Bouman" } }');
125
	INSERT INTO t (v) VALUES ('{ "person" : { "firstname" : "Henrik", "lastname" : "Ingo" } }');
126
	INSERT INTO t (v) VALUES ('{ "person" : { "firstname" : "Brian", "lastname" : "Aker" } }');
127
	SELECT JS('var person = JSON.parse(jsondoc); person["person"]["firstname"];', 
128
	          v as jsondoc) AS 'JS(...)' 
129
	FROM t WHERE k=2;
130
131
132
Will output
133
134
+--------------+
135
| JS(...)      |
136
+==============+
137
| Henrik       |
138
+--------------+
139
140
141
And
142
143
.. code-block:: mysql
144
145
	SELECT k, JS('var person = JSON.parse(jsondoc); person["person"]["firstname"];', 
146
	             v as jsondoc) AS 'firstname', 
147
	          JS('var person = JSON.parse(jsondoc); person["person"]["lastname"];', 
148
	             v as jsondoc) AS 'lastname' 
149
	FROM t;
150
151
Will break your unstructured JSON data back into a relational table:
152
153
+---+-----------+----------+
154
| k | firstname | lastname |
155
+===+===========+==========+
156
| 1 | Roland    | Bouman   |
157
+---+-----------+----------+
158
| 2 | Henrik    | Ingo     |
159
+---+-----------+----------+
160
| 3 | Brian     | Aker     |
161
+---+-----------+----------+
162
163
.. _js_stored_procedure_surrogate:
164
165
Using JS as surrogate for stored procedures:
166
--------------------------------------------
167
168
Especially if the JavaScript you want to use is more complex, it might be a good idea to store the javascript itself in a table in Drizzle, or alternatively a variable. This simplifies queries that use the script:
169
170
.. code-block:: mysql
171
172
	CREATE TABLE sp (name VARCHAR(255) PRIMARY KEY, script TEXT);
173
	INSERT INTO sp (name, script) VALUES ('get_person_property', 'var person = JSON.parse(jsondoc); person["person"][property];');
174
	SELECT k, JS( (SELECT script FROM sp WHERE name='get_person_property'), 
175
	             v as jsondoc, 'firstname' as 'property') AS 'firstname', 
176
	          JS( (SELECT script FROM sp WHERE name='get_person_property'), 
177
	             v as jsondoc, 'lastname' as 'property') AS 'lastname' 
178
	FROM t;
179
180
181
Will output the same result as above:
182
183
+---+-----------+----------+
184
| k | firstname | lastname |
185
+===+===========+==========+
186
| 1 | Roland    | Bouman   |
187
+---+-----------+----------+
188
| 2 | Henrik    | Ingo     |
189
+---+-----------+----------+
190
| 3 | Brian     | Aker     |
191
+---+-----------+----------+
192
193
.. _js_future_work:
194
195
Limitations and future work
196
---------------------------
197
198
The current version of ``JS()`` is complete in the sense that any type of arguments (integer, real, decimal, string, date) can be used, JavaScript code can be of arbitrary complexity and scalar values of any type can be returned. However, apart from the input parameters and the return value, there is no way to interact with Drizzle from the JavaScript environment. The plan is that in a future version ``JS()`` will expose some Drizzle API's, such as the ``Execute()`` API, so that one could query Drizzle tables and call other Drizzle functions from the JavaScript environment. This would essentially make JS() a form of JavaScript stored procedures. Of course, a next step after that could be to actually support ``STORED PROCEDURE`` syntax and permissions.
199
200
Values of type ``DECIMAL`` will be passed as JavaScript ``Double`` values. This may lead to loss of precision. If you want to keep the precision, you must explicitly cast ``DECIMAL`` values into ``CHAR`` when you pass them as arguments. Note that this will affect how the JavaScript ``+`` operator works on the value (string concatenation instead of addition).
201
202
The current version lacks several obvious performance optimizations. Most importantly the v8 JavaScript engine is single threaded, so heavy use of ``JS()`` on busy production servers is not recommended. A future version will use the v8 Isolate class to run several instances of the single threaded v8 engine.
203
204
.. _js_authors:
205
206
Authors
207
-------
208
209
Henrik Ingo
210
211
Thanks to Roland Bouman for suggesting to use v8 engine instead of just a JSON parser and for review and comments on JavaScript and JSON conventions.
212
213
.. _js_version:
214
215
Version
216
-------
217
218
This documentation applies to **js 0.9**.
219
220
To see which version of the plugin a Drizzle server is running, execute:
221
222
.. code-block:: mysql
223
224
   SELECT MODULE_VERSION FROM DATA_DICTIONARY.MODULES WHERE MODULE_NAME='js'
225
226
227
Changelog
228
---------
229
230
v0.9
231
^^^^
232
* First release. Complete JS() functionality, but no APIs back to Drizzle are exposed yet and several performance optimizations were left for later release.