actn-db 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,444 @@
1
+ // Generated by CoffeeScript 1.6.3
2
+ (function() {
3
+ var Funcs, root;
4
+ root = this;
5
+ Funcs = (function() {
6
+ function Funcs() {}
7
+
8
+ Funcs.prototype.__json = function(_data, _key) {
9
+ var ret;
10
+ ret = actn.valueAt(_data, _key);
11
+ if (ret == null) {
12
+ return null;
13
+ }
14
+ return JSON.stringify(ret);
15
+ };
16
+
17
+ Funcs.prototype.__string = function(_data, _key) {
18
+ var ret;
19
+ ret = actn.valueAt(_data, _key);
20
+ if (ret == null) {
21
+ return null;
22
+ }
23
+ return ret.toString();
24
+ };
25
+
26
+ Funcs.prototype.__integer = function(_data, _key) {
27
+ var ret;
28
+ ret = actn.valueAt(_data, _key);
29
+ if (ret == null) {
30
+ return null;
31
+ }
32
+ return parseInt(ret);
33
+ };
34
+
35
+ Funcs.prototype.__integer_array = function(_data, _key) {
36
+ var ret;
37
+ ret = actn.valueAt(_data, _key);
38
+ if (ret == null) {
39
+ return null;
40
+ }
41
+ return (ret instanceof Array ? ret : [ret]);
42
+ };
43
+
44
+ Funcs.prototype.__float = function(_data, _key) {
45
+ var ret;
46
+ ret = actn.valueAt(_data, _key);
47
+ if (ret == null) {
48
+ return null;
49
+ }
50
+ return parseFloat(ret);
51
+ };
52
+
53
+ Funcs.prototype.__bool = function(_data, _key) {
54
+ var ret;
55
+ ret = actn.valueAt(_data, _key);
56
+ if (ret == null) {
57
+ return null;
58
+ }
59
+ return !!ret;
60
+ };
61
+
62
+ Funcs.prototype.__timestamp = function(_data, _key) {
63
+ var ret;
64
+ ret = actn.valueAt(_data, _key);
65
+ if (ret == null) {
66
+ return null;
67
+ }
68
+ return new Date(ret);
69
+ };
70
+
71
+ Funcs.prototype.__patch = function(_data, _value, _sync) {
72
+ var changes, data, defaults, isObject, k, sync;
73
+ data = _data;
74
+ changes = _value;
75
+ isObject = false;
76
+ sync = _sync != null ? _sync : true;
77
+ defaults = _.pick(data, _.keys(JSON.parse(plv8.find_function('__defaults')())));
78
+ for (k in changes) {
79
+ if (data.hasOwnProperty(k)) {
80
+ isObject = typeof data[k] === "object" && typeof changes[k] === "object";
81
+ data[k] = isObject && sync ? _.extend(data[k], changes[k]) : changes[k];
82
+ } else {
83
+ data[k] = changes[k];
84
+ }
85
+ }
86
+ if (!sync) {
87
+ for (k in data) {
88
+ if (changes[k] == null) {
89
+ delete data[k];
90
+ }
91
+ }
92
+ }
93
+ _.extend(data, defaults);
94
+ return JSON.stringify(data);
95
+ };
96
+
97
+ Funcs.prototype.__select = function(_data, _fields) {
98
+ var data, fields, ret;
99
+ data = _data;
100
+ fields = _fields;
101
+ ret = _.pick(data, fields.split(","));
102
+ return JSON.stringify(ret);
103
+ };
104
+
105
+ Funcs.prototype.__push = function(_data, _key, _value) {
106
+ var data, field, i, keys, last_field, len, value;
107
+ data = _data;
108
+ value = _value;
109
+ keys = _key.split(".");
110
+ len = keys.length;
111
+ last_field = data;
112
+ field = data;
113
+ i = 0;
114
+ while (i < len) {
115
+ last_field = field;
116
+ if (field) {
117
+ field = field[keys[i]];
118
+ }
119
+ ++i;
120
+ }
121
+ if (field) {
122
+ field.push(value);
123
+ } else {
124
+ if (!(value instanceof Array)) {
125
+ value = [value];
126
+ }
127
+ last_field[keys.pop()] = value;
128
+ }
129
+ return JSON.stringify(data);
130
+ };
131
+
132
+ Funcs.prototype.__uuid = function() {
133
+ var ary;
134
+ ary = plv8.execute('SELECT uuid_generate_v4() as uuid;');
135
+ return JSON.stringify(ary[0]);
136
+ };
137
+
138
+ Funcs.prototype.__defaults = function() {
139
+ var timestamp, uuid;
140
+ uuid = JSON.parse(plv8.find_function('__uuid')());
141
+ timestamp = new Date();
142
+ return JSON.stringify({
143
+ uuid: uuid.uuid,
144
+ created_at: timestamp,
145
+ updated_at: timestamp
146
+ });
147
+ };
148
+
149
+ Funcs.prototype.__create_table = function(schema_name, table_name) {
150
+ plv8.execute(" CREATE TABLE " + schema_name + "." + table_name + " (\n id serial NOT NULL,\n data json DEFAULT __uuid() NOT NULL,\n CONSTRAINT " + schema_name + "_" + table_name + "_pkey PRIMARY KEY (id));\n\n CREATE UNIQUE INDEX indx_" + schema_name + "_" + table_name + "_unique_uuid ON " + schema_name + "." + table_name + " (__string(data,'uuid'));");
151
+ return JSON.stringify(table_name);
152
+ };
153
+
154
+ Funcs.prototype.__drop_table = function(schema_name, table_name) {
155
+ plv8.execute("DROP TABLE IF EXISTS " + schema_name + "." + table_name + " CASCADE;");
156
+ return JSON.stringify(table_name);
157
+ };
158
+
159
+ Funcs.prototype.__create_index = function(schema_name, table_name, optns) {
160
+ var cols, index_name, meth, name, sql, type, _ref, _ref1;
161
+ index_name = "indx_" + schema_name + "_" + table_name;
162
+ _ref = optns.cols;
163
+ for (name in _ref) {
164
+ type = _ref[name];
165
+ index_name += "_" + name;
166
+ }
167
+ sql = ["CREATE"];
168
+ if (optns.unique) {
169
+ sql.push("UNIQUE");
170
+ }
171
+ sql.push("INDEX");
172
+ if (optns.concurrently) {
173
+ sql.push("CONCURRENTLY");
174
+ }
175
+ sql.push("" + index_name + " on " + schema_name + "." + table_name);
176
+ sql.push("(");
177
+ cols = [];
178
+ _ref1 = optns.cols;
179
+ for (name in _ref1) {
180
+ type = _ref1[name];
181
+ meth = "__" + (type === 'text' ? 'string' : type);
182
+ cols.push("" + meth + "(data,'" + name + "'::" + type + ")");
183
+ }
184
+ sql.push(cols.join(","));
185
+ sql.push(")");
186
+ sql = sql.join(" ");
187
+ plv8.execute(sql);
188
+ return JSON.stringify(index_name);
189
+ };
190
+
191
+ Funcs.prototype.__drop_index = function(schema_name, table_name, optns) {
192
+ var index_name, name, type, _ref;
193
+ index_name = "indx_" + schema_name + "_" + table_name;
194
+ _ref = optns.cols;
195
+ for (name in _ref) {
196
+ type = _ref[name];
197
+ index_name += "_" + name;
198
+ }
199
+ plv8.execute("DROP INDEX IF EXISTS " + index_name);
200
+ return JSON.stringify(index_name);
201
+ };
202
+
203
+ Funcs.prototype.__query = function(_schema_name, _table_name, _query) {
204
+ var builder, params, result, rows, search_path, sql, _ref, _ref1;
205
+ search_path = _schema_name === "public" ? _schema_name : "" + _schema_name + ", public";
206
+ builder = new actn.Builder(_schema_name, _table_name, search_path, _query);
207
+ _ref = builder.build_select(), sql = _ref[0], params = _ref[1];
208
+ rows = plv8.execute(sql, params);
209
+ builder = null;
210
+ if ((_query != null ? (_ref1 = _query.select) != null ? _ref1.indexOf('COUNT') : void 0 : void 0) > -1) {
211
+ result = rows;
212
+ } else {
213
+ result = _.pluck(rows, 'data');
214
+ }
215
+ return JSON.stringify(result);
216
+ };
217
+
218
+ Funcs.prototype.__upsert = function(_schema_name, _table_name, _data) {
219
+ var builder, data, params, query, result, rows, search_path, sql, _ref, _ref1;
220
+ if (_data.errors != null) {
221
+ return JSON.stringify(_data);
222
+ }
223
+ data = _data;
224
+ search_path = _schema_name === "public" ? _schema_name : "" + _schema_name + ",public";
225
+ if (data.uuid != null) {
226
+ query = {
227
+ where: {
228
+ uuid: data.uuid
229
+ }
230
+ };
231
+ builder = new actn.Builder(_schema_name, _table_name, search_path, query);
232
+ _ref = builder.build_update(data), sql = _ref[0], params = _ref[1];
233
+ } else {
234
+ builder = new actn.Builder(_schema_name, _table_name, search_path, {});
235
+ _ref1 = builder.build_insert(data), sql = _ref1[0], params = _ref1[1];
236
+ }
237
+ rows = plv8.execute(sql, params);
238
+ result = _.pluck(rows, 'data');
239
+ if (result.length === 1) {
240
+ result = result[0];
241
+ }
242
+ builder = null;
243
+ return JSON.stringify(result);
244
+ };
245
+
246
+ Funcs.prototype.__update = function(_schema_name, _table_name, _data, _cond) {
247
+ var builder, params, result, rows, search_path, sql, _ref;
248
+ if (_data.errors != null) {
249
+ return JSON.stringify(_data);
250
+ }
251
+ search_path = _schema_name === "public" ? _schema_name : "" + _schema_name + ",public";
252
+ builder = new actn.Builder(_schema_name, _table_name, search_path, {
253
+ where: _cond
254
+ });
255
+ _ref = builder.build_update(_data), sql = _ref[0], params = _ref[1];
256
+ rows = plv8.execute(sql, params);
257
+ result = _.pluck(rows, 'data');
258
+ if (result.length === 1) {
259
+ result = result[0];
260
+ }
261
+ builder = null;
262
+ return JSON.stringify(result);
263
+ };
264
+
265
+ Funcs.prototype.__delete = function(_schema_name, _table_name, _cond) {
266
+ var builder, params, result, rows, search_path, sql, _ref;
267
+ search_path = _schema_name === "public" ? _schema_name : "" + _schema_name + ",public";
268
+ builder = new actn.Builder(_schema_name, _table_name, search_path, {
269
+ where: _cond
270
+ });
271
+ _ref = builder.build_delete(), sql = _ref[0], params = _ref[1];
272
+ rows = plv8.execute(sql, params);
273
+ result = _.pluck(rows, 'data');
274
+ if (result.length === 1) {
275
+ result = result[0];
276
+ }
277
+ builder = null;
278
+ return JSON.stringify(result);
279
+ };
280
+
281
+ Funcs.prototype.__validate = function(_name, _data) {
282
+ var data, errors, found, model, uniq_attr, where, __query, _base, _i, _len, _ref, _schema, _table;
283
+ data = _data;
284
+ if (!(model = plv8.find_function('__find_model')(_name))) {
285
+ return data;
286
+ }
287
+ model = JSON.parse(model);
288
+ if ((model != null ? model.schema : void 0) != null) {
289
+ errors = actn.jjv.validate(model.schema, data);
290
+ if ((data.uuid != null) && (model.schema.readonly_attributes != null)) {
291
+ data = _.omit(data, model.schema.readonly_attributes);
292
+ } else if (model.schema.unique_attributes != null) {
293
+ _schema = _name === "Model" ? "core" : "public";
294
+ _table = model.name.tableize();
295
+ __query = plv8.find_function("__query");
296
+ _ref = model.schema.unique_attributes || [];
297
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
298
+ uniq_attr = _ref[_i];
299
+ if (data[uniq_attr] != null) {
300
+ where = {};
301
+ where[uniq_attr] = data[uniq_attr];
302
+ found = JSON.parse(__query(_schema, _table, {
303
+ where: where
304
+ }));
305
+ if (!_.isEmpty(found)) {
306
+ if (errors == null) {
307
+ errors = {
308
+ validation: {}
309
+ };
310
+ }
311
+ if ((_base = errors['validation'])[uniq_attr] == null) {
312
+ _base[uniq_attr] = {};
313
+ }
314
+ errors['validation'][uniq_attr]["has already been taken"] = true;
315
+ }
316
+ }
317
+ }
318
+ }
319
+ if (errors != null) {
320
+ data = {
321
+ errors: errors
322
+ };
323
+ }
324
+ }
325
+ return data;
326
+ };
327
+
328
+ Funcs.prototype.__find_model = function(_name) {
329
+ var result, rows;
330
+ rows = plv8.execute("SET search_path TO core,public; \nSELECT data FROM core.models \nWHERE __string(data,'name'::text) = $1::text", [_name]);
331
+ if (rows == null) {
332
+ return;
333
+ }
334
+ result = _.pluck(rows, 'data')[0];
335
+ return JSON.stringify(result);
336
+ };
337
+
338
+ Funcs.prototype.model_callbacks = function(TG_OP, NEW, OLD) {
339
+ var diff, differ, indopts, mapper, table_name, table_schema, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref10, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9, _results, _results1;
340
+ table_name = (_ref = (NEW != null ? (_ref1 = NEW.data) != null ? _ref1.name : void 0 : void 0) || (OLD != null ? (_ref2 = OLD.data) != null ? _ref2.name : void 0 : void 0)) != null ? _ref.tableize() : void 0;
341
+ table_schema = ((NEW != null ? (_ref3 = NEW.data) != null ? _ref3.table_schema : void 0 : void 0) || (OLD != null ? (_ref4 = OLD.data) != null ? _ref4.table_schema : void 0 : void 0)) || "public";
342
+ if (table_schema === "core") {
343
+ return;
344
+ }
345
+ mapper = function(ind) {
346
+ return _.keys(ind.cols);
347
+ };
348
+ differ = function(_ind) {
349
+ return function(ind) {
350
+ var _ref5;
351
+ return _.isEmpty(_.difference(_.keys(ind.cols), _.flatten(_.map((_ref5 = _ind.data) != null ? _ref5.indexes : void 0, mapper))));
352
+ };
353
+ };
354
+ switch (TG_OP) {
355
+ case "INSERT":
356
+ plv8.execute("SELECT __create_table($1,$2)", [table_schema, table_name]);
357
+ plv8.execute("SELECT __create_index($1,$2,$3)", [
358
+ table_schema, table_name, {
359
+ cols: {
360
+ path: "text"
361
+ }
362
+ }
363
+ ]);
364
+ _ref6 = (NEW != null ? (_ref5 = NEW.data) != null ? _ref5.indexes : void 0 : void 0) || [];
365
+ _results = [];
366
+ for (_i = 0, _len = _ref6.length; _i < _len; _i++) {
367
+ indopts = _ref6[_i];
368
+ _results.push(plv8.execute("SELECT __create_index($1,$2,$3)", [table_schema, table_name, indopts]));
369
+ }
370
+ return _results;
371
+ break;
372
+ case "UPDATE":
373
+ diff = _.reject(OLD != null ? (_ref7 = OLD.data) != null ? _ref7.indexes : void 0 : void 0, differ(NEW));
374
+ for (_j = 0, _len1 = diff.length; _j < _len1; _j++) {
375
+ indopts = diff[_j];
376
+ plv8.execute("SELECT __drop_index($1,$2,$3)", [table_schema, table_name, indopts]);
377
+ }
378
+ diff = _.reject(NEW != null ? (_ref8 = NEW.data) != null ? _ref8.indexes : void 0 : void 0, differ(OLD));
379
+ _results1 = [];
380
+ for (_k = 0, _len2 = diff.length; _k < _len2; _k++) {
381
+ indopts = diff[_k];
382
+ _results1.push(plv8.execute("SELECT __create_index($1,$2,$3)", [table_schema, table_name, indopts]));
383
+ }
384
+ return _results1;
385
+ break;
386
+ case "DELETE":
387
+ _ref10 = (typeof Old !== "undefined" && Old !== null ? (_ref9 = Old.data) != null ? _ref9.indexes : void 0 : void 0) || [];
388
+ for (_l = 0, _len3 = _ref10.length; _l < _len3; _l++) {
389
+ indopts = _ref10[_l];
390
+ plv8.execute("SELECT __drop_index($1,$2,$3)", [table_schema, table_name, indopts]);
391
+ }
392
+ return plv8.execute("SELECT __drop_table($1,$2)", [table_schema, table_name]);
393
+ }
394
+ };
395
+
396
+ Funcs.prototype.hook_trigger = function(TG_TABLE_NAME, TG_OP, NEW, OLD) {
397
+ var callback, hook, job, model, res, upsert_func, _i, _len, _ref, _ref1, _ref2, _ref3, _results;
398
+ upsert_func = plv8.find_function("__upsert");
399
+ model = JSON.parse(plv8.find_function("__find_model")(TG_TABLE_NAME.classify()));
400
+ callback = {
401
+ INSERT: "after_create",
402
+ UPDATE: "after_update",
403
+ DELETE: "after_destroy"
404
+ }[TG_OP];
405
+ _ref1 = (model != null ? (_ref = model.hooks) != null ? _ref[callback] : void 0 : void 0) || [];
406
+ _results = [];
407
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
408
+ hook = _ref1[_i];
409
+ if (hook.run_at == null) {
410
+ hook.run_at = new Date();
411
+ }
412
+ hook.callback = callback;
413
+ job = {
414
+ hook: hook,
415
+ table_name: TG_TABLE_NAME,
416
+ record_uuid: (NEW != null ? (_ref2 = NEW.data) != null ? _ref2.uuid : void 0 : void 0) || (OLD != null ? (_ref3 = OLD.data) != null ? _ref3.uuid : void 0 : void 0),
417
+ record: TG_OP === "DELETE" ? OLD.data : void 0
418
+ };
419
+ res = upsert_func("core", "jobs", JSON.stringify(job));
420
+ _results.push(plv8.execute("SELECT pg_notify('jobs', $1);", [res]));
421
+ }
422
+ return _results;
423
+ };
424
+
425
+ Funcs.prototype.jobs_model_callbacks = function(TG_TABLE_NAME, TG_OP, NEW, OLD) {
426
+ var table_name, table_schema, _ref, _ref1, _ref2, _ref3;
427
+ table_name = ((NEW != null ? (_ref = NEW.data) != null ? _ref.name : void 0 : void 0) || (OLD != null ? (_ref1 = OLD.data) != null ? _ref1.name : void 0 : void 0)).tableize();
428
+ table_schema = ((NEW != null ? (_ref2 = NEW.data) != null ? _ref2.table_schema : void 0 : void 0) || (OLD != null ? (_ref3 = OLD.data) != null ? _ref3.table_schema : void 0 : void 0)) || "public";
429
+ if (table_schema === "core") {
430
+ return;
431
+ }
432
+ if (TG_OP === "DELETE") {
433
+ plv8.execute("DELETE FROM core.jobs WHERE __string(data, 'table_name'::text) = $1;", [table_name]);
434
+ }
435
+ if (TG_OP === "INSERT" || TG_OP === "UPDATE" && (NEW.data.hooks != null) && (OLD.data.hooks == null)) {
436
+ return plv8.execute("CREATE TRIGGER " + table_schema + "_" + table_name + "_hook_trigger \nAFTER INSERT OR UPDATE OR DELETE ON " + table_schema + "." + table_name + " \nFOR EACH ROW EXECUTE PROCEDURE hook_trigger();");
437
+ }
438
+ };
439
+
440
+ return Funcs;
441
+
442
+ })();
443
+ return root.actn.funcs = new Funcs;
444
+ }).call(this);
@@ -0,0 +1,142 @@
1
+ (->
2
+ root = this
3
+
4
+ class Builder
5
+
6
+ constructor: (@schema_name, @table_name, @search_path, @query) ->
7
+ @query.select ?= "*"
8
+ @params = []
9
+ @i = 0
10
+
11
+ qm: -> "$#{@i += 1}"
12
+
13
+ make_select: ->
14
+ if @query?.select?.indexOf('COUNT') > -1
15
+ @query.select
16
+ else
17
+ if @query.select is "*"
18
+ "data"
19
+ else
20
+ @params.push _.flatten([@query.select]).join(".")
21
+ "__select(data, #{@qm()}) as data" #::text
22
+
23
+
24
+ make_where: (q, join_by = 'AND') ->
25
+ sql = []
26
+ for k, subquery of q
27
+ switch k
28
+ when 'and', 'AND', '&', '&&'
29
+ sql.push "(#{make_where(subquery, 'AND')})"
30
+ when 'or', 'OR', '|', '||'
31
+ sql.push "(#{make_where(subquery, 'OR')})"
32
+ when 'not', 'NOT', '!'
33
+ sql.push "NOT (#{make_where(subquery, 'AND')})"
34
+ else
35
+ if _.isArray(subquery)
36
+ @params.push k
37
+ @params.push subquery[1]
38
+ sql.push "#{@plv8_key(subquery[1])} #{subquery[0]} #{@plv8_qm(subquery[1])}"
39
+ else if _.isObject(subquery)
40
+ comparisons = []
41
+ for symbol, value in subquery
42
+ comparisons.push "#{symbol} #{@plv8_qm(value)}"
43
+ @params.push k
44
+ @params.push value
45
+ sql.push _.map(comparisons, (comparison) -> "#{@plv8_key(value)} #{comparison}").join(" AND ")
46
+ else
47
+ @params.push k
48
+ @params.push subquery
49
+ sql.push "#{@plv8_key(subquery)} = #{@plv8_qm(subquery)}"
50
+
51
+ sql.join "\n#{join_by} "
52
+
53
+
54
+ make_order_by: () ->
55
+ ord = @query.order_by
56
+ str = []
57
+ if _.isArray(ord)
58
+ @params.push ord[0]
59
+ str.push "#{@plv8_key(ord[1])} #{ord[1].toUpperCase()}"
60
+ else if _.isObject(ord)
61
+ for k,v in ord
62
+ @params.push v
63
+ str.push "#{@plv8_key(k)} #{k.toUpperCase()}"
64
+ else
65
+ @params.push ord
66
+ str.push @qm()
67
+ str.join(",")
68
+
69
+
70
+ make_limit: ->
71
+ @params.push @query.limit
72
+ @qm()
73
+
74
+
75
+ make_offset: ->
76
+ @params.push @query.offset
77
+ @qm()
78
+
79
+
80
+ build_select: ->
81
+ sql = []
82
+ sql.push "SET search_path TO #{@search_path};"
83
+ sql.push "SELECT #{@make_select()} FROM #{@schema_name}.#{@table_name}"
84
+ sql.push "WHERE #{@make_where(@query.where)}" unless _.isEmpty(@query.where)
85
+ sql.push "ORDER BY #{@make_order()}" if @query.order_by?
86
+ sql.push "LIMIT #{@make_limit()}" if @query.limit?
87
+ sql.push "OFFSET #{@make_offset()}" if @query.offset?
88
+ [sql.join("\n"), @params]
89
+
90
+ build_delete: ->
91
+ sql = []
92
+ sql.push "SET search_path TO #{@search_path};"
93
+ sql.push "DELETE FROM #{@schema_name}.#{@table_name}"
94
+ sql.push "WHERE #{@make_where(@query.where)}" unless _.isEmpty(@query.where)
95
+ sql.push "RETURNING data::json;"
96
+ [sql.join("\n"), @params]
97
+
98
+ build_update: (data, merge = true) ->
99
+
100
+ @params.push data
101
+ @params.push merge
102
+ sql = []
103
+ sql.push "SET search_path TO #{@search_path};"
104
+ sql.push "UPDATE #{@schema_name}.#{@table_name} SET data = __patch(data,#{@qm()},#{@qm()})"
105
+ sql.push "WHERE #{@make_where(@query.where)}" unless _.isEmpty(@query.where)
106
+ sql.push "RETURNING data::json;"
107
+ [sql.join("\n"), @params]
108
+
109
+ build_insert: (data, merge = true) ->
110
+ @params.push data
111
+ @params.push merge
112
+ sql = []
113
+ sql.push "SET search_path TO #{@search_path};"
114
+ sql.push "INSERT INTO #{@schema_name}.#{@table_name} (data) VALUES (__patch(__defaults(),#{@qm()},#{@qm()}))"
115
+ sql.push "RETURNING data::json;"
116
+ [sql.join("\n"), @params]
117
+
118
+ plv8_key: (value) -> "#{@typecast(value,true)}(data, #{@qm()}::text)" #::text
119
+
120
+ plv8_qm: (value) -> "#{@qm()}::#{@typecast(value)}"
121
+
122
+ typecast: (value, is_func = false) ->
123
+ type = if is_func then "__" else ""
124
+ if _.isBoolean(value)
125
+ type += "bool"
126
+ else if _.isDate(value)
127
+ type += "timestamp"
128
+ else if _.isNumber(value)
129
+ type += "integer"
130
+ else if _.isObject(value)
131
+ type += (if is_func then "text" else "json")
132
+ else if _.isArray(value)
133
+ type += (if is_func then "text" else "array")
134
+ else
135
+ type += (if is_func then "string" else "text")
136
+ type
137
+
138
+
139
+
140
+ root.actn.Builder = Builder
141
+
142
+ ).call this