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.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Rakefile +1 -1
- data/db/1_db.sql +1 -3
- data/db/__functions.sql +10 -92
- data/db/__setup.sql +7 -16
- data/db/lib/{_1_underscore.js → _0_underscore.js} +0 -0
- data/db/lib/{_3_inflections.js → _1_inflections.js} +0 -0
- data/db/lib/_2_jjv.js +2 -3
- data/db/lib/_3_actn.js +31 -0
- data/db/lib/_4_functions.coffee +387 -0
- data/db/lib/_4_functions.js +444 -0
- data/db/lib/_5_builder.coffee +142 -0
- data/db/lib/{_4_builder.js → _5_builder.js} +3 -5
- data/lib/actn/db/tasks/db.rake +24 -11
- data/lib/actn/db/version.rb +1 -1
- data/test/actn/test_model.rb +1 -1
- data/test/minitest_helper.rb +2 -2
- metadata +9 -7
- data/db/lib/_0_actn.js +0 -23
- data/db/lib/_4_builder.coffee +0 -136
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dd259d933b75cb3242fb249565474fc0148dd845
|
|
4
|
+
data.tar.gz: d62618f10c7f70e88666f1b3a92d3b11c7a8441f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 87e5f43fb7a3e59e4c5f38fd0f58f8de1e19444602d1f5d09d3a7608577f95d944884d01a38811654da271bc0a4e8a8f275b666411a393a55124134a4596f7b1
|
|
7
|
+
data.tar.gz: 4b40c257fa8b7a2ed85401f8013742fe99ff16f462098bebd2eb8ab55d14dabc975d07ce783815ec8109d4232d3053a10e5f0e336550a223059d6f5deede406e
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
data/db/1_db.sql
CHANGED
|
@@ -7,10 +7,8 @@ SELECT __create_table('core','models');
|
|
|
7
7
|
SELECT __create_index('core','models', '{"cols": {"name": "text"},"unique": true}');
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
CREATE or REPLACE FUNCTION model_callbacks() RETURNS trigger AS
|
|
11
|
-
$$
|
|
10
|
+
CREATE or REPLACE FUNCTION model_callbacks() RETURNS trigger AS $$
|
|
12
11
|
actn.funcs.model_callbacks(TG_OP, NEW, OLD);
|
|
13
|
-
|
|
14
12
|
$$ LANGUAGE plv8 STABLE STRICT;
|
|
15
13
|
|
|
16
14
|
CREATE TRIGGER core_models_callback_trigger
|
data/db/__functions.sql
CHANGED
|
@@ -6,232 +6,150 @@ $$ LANGUAGE plv8 STABLE STRICT;
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
9
|
CREATE or REPLACE FUNCTION __string(_data json, _key text) RETURNS TEXT AS $$
|
|
12
10
|
return actn.funcs.__string(_data, _key);
|
|
13
|
-
|
|
14
11
|
$$ LANGUAGE plv8 IMMUTABLE STRICT;
|
|
15
12
|
|
|
16
13
|
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
|
|
20
15
|
CREATE or REPLACE FUNCTION __integer(_data json, _key text) RETURNS INT AS $$
|
|
21
16
|
return actn.funcs.__integer(_data, _key);
|
|
22
|
-
|
|
23
17
|
$$ LANGUAGE plv8 IMMUTABLE STRICT;
|
|
24
18
|
|
|
25
19
|
|
|
26
20
|
|
|
27
|
-
|
|
28
|
-
|
|
29
21
|
CREATE or REPLACE FUNCTION __integer_array(_data json, _key text) RETURNS INT[] AS $$
|
|
30
22
|
return actn.funcs.__integer_array(_data, _key);
|
|
31
|
-
|
|
32
23
|
$$ LANGUAGE plv8 IMMUTABLE STRICT;
|
|
33
24
|
|
|
34
25
|
|
|
35
26
|
|
|
36
|
-
|
|
37
|
-
|
|
38
27
|
CREATE or REPLACE FUNCTION __float(_data json, _key text) RETURNS DOUBLE PRECISION AS $$
|
|
39
28
|
return actn.funcs.__float(_data, _key);
|
|
40
|
-
|
|
41
29
|
$$ LANGUAGE plv8 IMMUTABLE STRICT;
|
|
42
30
|
|
|
43
31
|
|
|
44
32
|
|
|
45
|
-
|
|
46
|
-
|
|
47
33
|
CREATE or REPLACE FUNCTION __bool(_data json, _key text) RETURNS BOOLEAN AS $$
|
|
48
34
|
return actn.funcs.__bool(_data, _key);
|
|
49
|
-
|
|
50
35
|
$$ LANGUAGE plv8 IMMUTABLE STRICT;
|
|
51
36
|
|
|
52
37
|
|
|
53
38
|
|
|
54
|
-
|
|
55
|
-
|
|
56
39
|
CREATE or REPLACE FUNCTION __timestamp(_data json, _key text) RETURNS TIMESTAMP AS $$
|
|
57
40
|
return actn.funcs.__timestamp(_data, _key);
|
|
58
|
-
|
|
59
41
|
$$ LANGUAGE plv8 IMMUTABLE STRICT;
|
|
60
42
|
|
|
61
43
|
|
|
62
44
|
|
|
63
|
-
|
|
64
|
-
|
|
65
45
|
CREATE or REPLACE FUNCTION __patch(_data json, _value json, _sync boolean) RETURNS JSON AS $$
|
|
66
46
|
return actn.funcs.__patch(_data, _value, _sync);
|
|
67
|
-
|
|
68
47
|
$$ LANGUAGE plv8 STABLE STRICT;
|
|
69
48
|
|
|
70
49
|
|
|
71
50
|
|
|
72
|
-
|
|
73
|
-
|
|
74
51
|
CREATE or REPLACE FUNCTION __select(_data json, _fields text) RETURNS JSON AS $$
|
|
75
|
-
return actn.funcs.__select(_data, _fields);
|
|
76
|
-
|
|
52
|
+
return actn.funcs.__select(_data, _fields);
|
|
77
53
|
$$ LANGUAGE plv8 STABLE STRICT;
|
|
78
54
|
|
|
79
55
|
|
|
80
56
|
|
|
81
|
-
|
|
82
|
-
|
|
83
57
|
CREATE or REPLACE FUNCTION __push(_data json, _key text, _value json) RETURNS JSON AS $$
|
|
84
58
|
return actn.funcs.__push(_data, _key, _value);
|
|
85
|
-
|
|
86
|
-
|
|
87
59
|
$$ LANGUAGE plv8 STABLE STRICT;
|
|
88
60
|
|
|
89
61
|
|
|
90
62
|
|
|
91
|
-
|
|
92
|
-
|
|
93
63
|
CREATE or REPLACE FUNCTION __uuid() RETURNS JSON AS $$
|
|
94
|
-
return actn.funcs.__uuid();
|
|
95
|
-
|
|
96
|
-
|
|
64
|
+
return actn.funcs.__uuid();
|
|
97
65
|
$$ LANGUAGE plv8 STABLE STRICT;
|
|
98
66
|
|
|
99
67
|
|
|
100
68
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
69
|
CREATE or REPLACE FUNCTION __defaults() RETURNS JSON AS $$
|
|
105
70
|
return actn.funcs.__defaults();
|
|
106
|
-
|
|
107
71
|
$$ LANGUAGE plv8 STABLE STRICT;
|
|
108
72
|
|
|
109
73
|
|
|
110
74
|
|
|
111
|
-
|
|
112
|
-
|
|
113
75
|
CREATE or REPLACE FUNCTION __create_table(schema_name text, table_name text) RETURNS JSON AS $$
|
|
114
|
-
return actn.funcs.__create_table(schema_name, table_name);
|
|
115
|
-
|
|
116
|
-
|
|
76
|
+
return actn.funcs.__create_table(schema_name, table_name);
|
|
117
77
|
$$ LANGUAGE plv8 STABLE STRICT;
|
|
118
78
|
|
|
119
79
|
|
|
120
80
|
|
|
121
|
-
|
|
122
|
-
|
|
123
81
|
CREATE or REPLACE FUNCTION __drop_table(schema_name text, table_name text) RETURNS JSON AS $$
|
|
124
|
-
return actn.funcs.__drop_table(schema_name, table_name);
|
|
125
|
-
|
|
82
|
+
return actn.funcs.__drop_table(schema_name, table_name);
|
|
126
83
|
$$ LANGUAGE plv8 STABLE STRICT;
|
|
127
84
|
|
|
128
85
|
|
|
129
86
|
|
|
130
|
-
|
|
131
|
-
|
|
132
87
|
CREATE or REPLACE FUNCTION __create_index(schema_name text, table_name text, optns json) RETURNS JSON AS $$
|
|
133
|
-
|
|
134
88
|
return actn.funcs.__create_index(schema_name, table_name, optns);
|
|
135
|
-
|
|
136
89
|
$$ LANGUAGE plv8 STABLE STRICT;
|
|
137
90
|
|
|
138
91
|
|
|
139
92
|
|
|
140
|
-
|
|
141
|
-
|
|
142
93
|
CREATE or REPLACE FUNCTION __drop_index(schema_name text, table_name text, optns json) RETURNS JSON AS $$
|
|
143
|
-
return actn.funcs.__drop_index(schema_name, table_name, optns);
|
|
144
|
-
|
|
145
|
-
|
|
94
|
+
return actn.funcs.__drop_index(schema_name, table_name, optns);
|
|
146
95
|
$$ LANGUAGE plv8 STABLE STRICT;
|
|
147
96
|
|
|
148
97
|
|
|
149
98
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
99
|
-- ##
|
|
154
100
|
-- # Select data
|
|
155
101
|
-- # SELECT query(_schema_name, _table_name, {where: {uuid: "12345"}});
|
|
156
102
|
|
|
157
103
|
CREATE or REPLACE FUNCTION __query(_schema_name text, _table_name text, _query json) RETURNS json AS $$
|
|
158
104
|
return actn.funcs.__query(_schema_name, _table_name, _query);
|
|
159
|
-
|
|
160
|
-
|
|
161
105
|
$$ LANGUAGE plv8 STABLE;
|
|
162
106
|
|
|
163
107
|
|
|
164
108
|
|
|
165
|
-
|
|
166
|
-
|
|
167
109
|
-- ##
|
|
168
110
|
-- # Insert ot update row through validation!
|
|
169
111
|
-- # SELECT upsert(validate('User', '{"name":"foo"}'));
|
|
170
112
|
|
|
171
113
|
CREATE or REPLACE FUNCTION __upsert(_schema_name text, _table_name text, _data json) RETURNS json AS $$
|
|
172
|
-
return actn.funcs.__upsert(_schema_name, _table_name, _data);
|
|
173
|
-
|
|
114
|
+
return actn.funcs.__upsert(_schema_name, _table_name, _data);
|
|
174
115
|
$$ LANGUAGE plv8 STABLE STRICT;
|
|
175
116
|
|
|
176
117
|
|
|
177
118
|
|
|
178
|
-
|
|
179
|
-
|
|
180
119
|
-- ##
|
|
181
120
|
-- # Delete single row by uuid
|
|
182
121
|
-- # SELECT remove('users',uuid-1234567);
|
|
183
122
|
|
|
184
123
|
CREATE or REPLACE FUNCTION __update(_schema_name text, _table_name text, _data json, _cond json) RETURNS json AS $$
|
|
185
|
-
return actn.funcs.__update(_schema_name, _table_name, _data, _cond);
|
|
186
|
-
|
|
124
|
+
return actn.funcs.__update(_schema_name, _table_name, _data, _cond);
|
|
187
125
|
$$ LANGUAGE plv8 STABLE STRICT;
|
|
188
126
|
|
|
189
127
|
|
|
190
128
|
|
|
191
|
-
|
|
192
|
-
|
|
193
129
|
-- ##
|
|
194
130
|
-- # Delete single row by uuid
|
|
195
131
|
-- # SELECT remove('users',uuid-1234567);
|
|
196
132
|
|
|
197
133
|
CREATE or REPLACE FUNCTION __delete(_schema_name text, _table_name text, _cond json) RETURNS json AS $$
|
|
198
|
-
return actn.funcs.__delete(_schema_name, _table_name, _cond);
|
|
199
|
-
|
|
200
|
-
|
|
134
|
+
return actn.funcs.__delete(_schema_name, _table_name, _cond);
|
|
201
135
|
$$ LANGUAGE plv8 STABLE STRICT;
|
|
202
136
|
|
|
203
137
|
|
|
204
138
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
139
|
-- ##
|
|
210
140
|
-- # Validate data by json schema
|
|
211
141
|
-- # SELECT validate(model_name, data);
|
|
212
142
|
|
|
213
143
|
CREATE or REPLACE FUNCTION __validate(_name text, _data json) RETURNS json AS $$
|
|
214
|
-
return actn.funcs.__validate(_name, _data);
|
|
215
|
-
|
|
216
|
-
|
|
144
|
+
return actn.funcs.__validate(_name, _data);
|
|
217
145
|
$$ LANGUAGE plv8 STABLE STRICT;
|
|
218
146
|
|
|
219
147
|
|
|
220
148
|
|
|
221
|
-
|
|
222
|
-
|
|
223
149
|
-- ##
|
|
224
150
|
-- # finds model with given name
|
|
225
151
|
-- # SELECT __find_model(model_name);
|
|
226
152
|
|
|
227
153
|
CREATE or REPLACE FUNCTION __find_model(_name text) RETURNS json AS $$
|
|
228
|
-
return actn.funcs.__find_model(_name);
|
|
229
|
-
|
|
230
|
-
|
|
154
|
+
return actn.funcs.__find_model(_name);
|
|
231
155
|
$$ LANGUAGE plv8 STABLE STRICT;
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
data/db/__setup.sql
CHANGED
|
@@ -6,34 +6,25 @@ CREATE EXTENSION IF NOT EXISTS "plv8";
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
-- Js Libs
|
|
11
10
|
|
|
12
11
|
CREATE TABLE plv8_modules(modname text primary key, load_on_start boolean, code text);
|
|
13
12
|
|
|
14
13
|
CREATE OR REPLACE FUNCTION plv8_startup() RETURNS void AS $$
|
|
15
14
|
|
|
16
|
-
var code,
|
|
17
|
-
|
|
18
|
-
load_module = function(modname) {
|
|
19
|
-
var code, r, rows;
|
|
20
|
-
rows = plv8.execute("SELECT code from public.plv8_modules " + " where modname = $1", [modname]);
|
|
21
|
-
r = 0;
|
|
22
|
-
while (r < rows.length) {
|
|
23
|
-
code = rows[r].code;
|
|
24
|
-
eval("(function(){" + code + "})")();
|
|
25
|
-
r++;
|
|
26
|
-
}
|
|
27
|
-
};
|
|
15
|
+
var code, r, rows;
|
|
28
16
|
|
|
29
|
-
|
|
17
|
+
code = "";
|
|
18
|
+
|
|
19
|
+
rows = plv8.execute("SELECT modname, code from public.plv8_modules order by modname");
|
|
30
20
|
|
|
31
21
|
r = 0;
|
|
32
22
|
|
|
33
23
|
while (r < rows.length) {
|
|
34
|
-
code
|
|
35
|
-
eval("(function(){" + code + "})")();
|
|
24
|
+
code += rows[r].code;
|
|
36
25
|
r++;
|
|
37
26
|
}
|
|
27
|
+
|
|
28
|
+
eval("(function(){" + code + "})")();
|
|
38
29
|
|
|
39
30
|
$$ LANGUAGE plv8 STABLE STRICT;
|
|
File without changes
|
|
File without changes
|
data/db/lib/_2_jjv.js
CHANGED
data/db/lib/_3_actn.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// global = (function() {
|
|
2
|
+
// return this;
|
|
3
|
+
// }).call(null);
|
|
4
|
+
|
|
5
|
+
(function(){
|
|
6
|
+
|
|
7
|
+
var root = this,
|
|
8
|
+
|
|
9
|
+
Actn = (function() {
|
|
10
|
+
function Actn() {}
|
|
11
|
+
|
|
12
|
+
Actn.prototype.valueAt = function(data, key) {
|
|
13
|
+
var i, keys;
|
|
14
|
+
keys = key.split(".");
|
|
15
|
+
for (i in keys) {
|
|
16
|
+
if (data != null) {
|
|
17
|
+
data = data[keys[i]];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return data;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
return Actn;
|
|
24
|
+
|
|
25
|
+
})();
|
|
26
|
+
|
|
27
|
+
root.actn = new Actn();
|
|
28
|
+
|
|
29
|
+
root.actn.jjv = jjv();
|
|
30
|
+
|
|
31
|
+
}).call(this);
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
(->
|
|
2
|
+
root = this
|
|
3
|
+
|
|
4
|
+
class Funcs
|
|
5
|
+
|
|
6
|
+
__json: (_data, _key) ->
|
|
7
|
+
ret = actn.valueAt(_data,_key)
|
|
8
|
+
return null unless ret?
|
|
9
|
+
return JSON.stringify(ret)
|
|
10
|
+
|
|
11
|
+
__string: (_data, _key) ->
|
|
12
|
+
ret = actn.valueAt(_data,_key)
|
|
13
|
+
return null unless ret?
|
|
14
|
+
return ret.toString()
|
|
15
|
+
|
|
16
|
+
__integer: (_data, _key) ->
|
|
17
|
+
ret = actn.valueAt(_data,_key)
|
|
18
|
+
return null unless ret?
|
|
19
|
+
return parseInt(ret)
|
|
20
|
+
|
|
21
|
+
__integer_array: (_data, _key) ->
|
|
22
|
+
ret = actn.valueAt(_data,_key)
|
|
23
|
+
return null unless ret?
|
|
24
|
+
return (if ret instanceof Array then ret else [ret])
|
|
25
|
+
|
|
26
|
+
__float: (_data, _key) ->
|
|
27
|
+
ret = actn.valueAt(_data,_key)
|
|
28
|
+
return null unless ret?
|
|
29
|
+
return parseFloat(ret)
|
|
30
|
+
|
|
31
|
+
__bool: (_data, _key) ->
|
|
32
|
+
ret = actn.valueAt(_data,_key)
|
|
33
|
+
return null unless ret?
|
|
34
|
+
return !!ret
|
|
35
|
+
|
|
36
|
+
__timestamp: (_data, _key) ->
|
|
37
|
+
ret = actn.valueAt(_data,_key)
|
|
38
|
+
return null unless ret?
|
|
39
|
+
return new Date(ret)
|
|
40
|
+
|
|
41
|
+
__patch: (_data, _value, _sync) ->
|
|
42
|
+
|
|
43
|
+
data = _data
|
|
44
|
+
changes = _value
|
|
45
|
+
isObject = false
|
|
46
|
+
|
|
47
|
+
sync = if _sync? then _sync else true
|
|
48
|
+
|
|
49
|
+
defaults = _.pick( data, _.keys( JSON.parse( plv8.find_function('__defaults')() ) ) )
|
|
50
|
+
|
|
51
|
+
for k of changes
|
|
52
|
+
if data.hasOwnProperty(k)
|
|
53
|
+
isObject = typeof (data[k]) is "object" and typeof (changes[k]) is "object"
|
|
54
|
+
data[k] = if isObject and sync then _.extend(data[k], changes[k]) else changes[k]
|
|
55
|
+
else
|
|
56
|
+
data[k] = changes[k]
|
|
57
|
+
|
|
58
|
+
unless sync
|
|
59
|
+
for k of data
|
|
60
|
+
delete data[k] unless changes[k]?
|
|
61
|
+
|
|
62
|
+
_.extend(data, defaults)
|
|
63
|
+
|
|
64
|
+
return JSON.stringify(data)
|
|
65
|
+
|
|
66
|
+
__select: (_data, _fields) ->
|
|
67
|
+
data = _data
|
|
68
|
+
fields = _fields
|
|
69
|
+
ret = _.pick(data,fields.split(","))
|
|
70
|
+
|
|
71
|
+
return JSON.stringify(ret)
|
|
72
|
+
|
|
73
|
+
__push: (_data, _key, _value) ->
|
|
74
|
+
data = _data
|
|
75
|
+
value = _value
|
|
76
|
+
keys = _key.split(".")
|
|
77
|
+
len = keys.length
|
|
78
|
+
last_field = data
|
|
79
|
+
field = data
|
|
80
|
+
i = 0
|
|
81
|
+
|
|
82
|
+
while i < len
|
|
83
|
+
last_field = field
|
|
84
|
+
field = field[keys[i]] if field
|
|
85
|
+
++i
|
|
86
|
+
if field
|
|
87
|
+
field.push value
|
|
88
|
+
else
|
|
89
|
+
value = [value] unless value instanceof Array
|
|
90
|
+
last_field[keys.pop()] = value
|
|
91
|
+
|
|
92
|
+
return JSON.stringify(data)
|
|
93
|
+
|
|
94
|
+
__uuid: () ->
|
|
95
|
+
ary = plv8.execute 'SELECT uuid_generate_v4() as uuid;'
|
|
96
|
+
return JSON.stringify(ary[0])
|
|
97
|
+
|
|
98
|
+
__defaults: () ->
|
|
99
|
+
uuid = JSON.parse(plv8.find_function('__uuid')())
|
|
100
|
+
timestamp = new Date()
|
|
101
|
+
return JSON.stringify({uuid: uuid.uuid, created_at: timestamp, updated_at: timestamp})
|
|
102
|
+
|
|
103
|
+
__create_table: (schema_name, table_name) ->
|
|
104
|
+
plv8.execute """
|
|
105
|
+
CREATE TABLE #{schema_name}.#{table_name} (
|
|
106
|
+
id serial NOT NULL,
|
|
107
|
+
data json DEFAULT __uuid() NOT NULL,
|
|
108
|
+
CONSTRAINT #{schema_name}_#{table_name}_pkey PRIMARY KEY (id));
|
|
109
|
+
|
|
110
|
+
CREATE UNIQUE INDEX indx_#{schema_name}_#{table_name}_unique_uuid ON #{schema_name}.#{table_name} (__string(data,'uuid'));
|
|
111
|
+
"""
|
|
112
|
+
return JSON.stringify(table_name)
|
|
113
|
+
|
|
114
|
+
__drop_table: (schema_name, table_name) ->
|
|
115
|
+
plv8.execute "DROP TABLE IF EXISTS #{schema_name}.#{table_name} CASCADE;"
|
|
116
|
+
return JSON.stringify(table_name)
|
|
117
|
+
|
|
118
|
+
__create_index: (schema_name, table_name, optns) ->
|
|
119
|
+
index_name = "indx_#{schema_name}_#{table_name}"
|
|
120
|
+
for name, type of optns.cols
|
|
121
|
+
index_name += "_#{name}"
|
|
122
|
+
|
|
123
|
+
sql = ["CREATE"]
|
|
124
|
+
sql.push "UNIQUE" if optns.unique
|
|
125
|
+
sql.push "INDEX"
|
|
126
|
+
sql.push "CONCURRENTLY" if optns.concurrently
|
|
127
|
+
sql.push "#{index_name} on #{schema_name}.#{table_name}"
|
|
128
|
+
sql.push "("
|
|
129
|
+
cols = []
|
|
130
|
+
for name, type of optns.cols
|
|
131
|
+
meth = "__#{if type is 'text' then 'string' else type}"
|
|
132
|
+
cols.push "#{meth}(data,'#{name}'::#{type})"
|
|
133
|
+
sql.push cols.join(",")
|
|
134
|
+
sql.push ")"
|
|
135
|
+
|
|
136
|
+
sql = sql.join(" ")
|
|
137
|
+
|
|
138
|
+
plv8.execute(sql)
|
|
139
|
+
|
|
140
|
+
return JSON.stringify(index_name)
|
|
141
|
+
|
|
142
|
+
__drop_index: (schema_name, table_name, optns) ->
|
|
143
|
+
index_name = "indx_#{schema_name}_#{table_name}"
|
|
144
|
+
for name, type of optns.cols
|
|
145
|
+
index_name += "_#{name}"
|
|
146
|
+
|
|
147
|
+
plv8.execute("DROP INDEX IF EXISTS #{index_name}")
|
|
148
|
+
|
|
149
|
+
return JSON.stringify(index_name)
|
|
150
|
+
|
|
151
|
+
__query: (_schema_name, _table_name, _query) ->
|
|
152
|
+
search_path = if _schema_name is "public" then _schema_name else "#{_schema_name}, public"
|
|
153
|
+
|
|
154
|
+
builder = new actn.Builder(_schema_name, _table_name, search_path, _query)
|
|
155
|
+
|
|
156
|
+
[sql,params] = builder.build_select()
|
|
157
|
+
|
|
158
|
+
rows = plv8.execute(sql,params)
|
|
159
|
+
|
|
160
|
+
builder = null
|
|
161
|
+
|
|
162
|
+
if _query?.select?.indexOf('COUNT') > -1
|
|
163
|
+
result = rows
|
|
164
|
+
else
|
|
165
|
+
result = _.pluck(rows,'data')
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
return JSON.stringify(result)
|
|
169
|
+
|
|
170
|
+
__upsert: (_schema_name, _table_name, _data) ->
|
|
171
|
+
# plv8.elog(NOTICE,"UPSERT",JSON.stringify(_data))
|
|
172
|
+
|
|
173
|
+
return JSON.stringify(_data) if _data.errors?
|
|
174
|
+
|
|
175
|
+
data = _data
|
|
176
|
+
|
|
177
|
+
search_path = if _schema_name is "public" then _schema_name else "#{_schema_name},public"
|
|
178
|
+
|
|
179
|
+
if data.uuid?
|
|
180
|
+
|
|
181
|
+
query = { where: { uuid: data.uuid } }
|
|
182
|
+
|
|
183
|
+
builder = new actn.Builder(_schema_name, _table_name, search_path, query )
|
|
184
|
+
|
|
185
|
+
[sql,params] = builder.build_update(data)
|
|
186
|
+
|
|
187
|
+
else
|
|
188
|
+
|
|
189
|
+
builder = new actn.Builder(_schema_name, _table_name, search_path, {})
|
|
190
|
+
|
|
191
|
+
[sql,params] = builder.build_insert(data)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
# plan = plv8.prepare(sql, ['json','bool','text'])
|
|
195
|
+
|
|
196
|
+
# plv8.elog(NOTICE,sql,JSON.stringify(params))
|
|
197
|
+
|
|
198
|
+
rows = plv8.execute(sql, params)
|
|
199
|
+
|
|
200
|
+
result = _.pluck(rows,'data')
|
|
201
|
+
|
|
202
|
+
result = result[0] if result.length is 1
|
|
203
|
+
|
|
204
|
+
builder = null
|
|
205
|
+
|
|
206
|
+
return JSON.stringify(result)
|
|
207
|
+
|
|
208
|
+
__update: (_schema_name, _table_name, _data, _cond) ->
|
|
209
|
+
return JSON.stringify(_data) if _data.errors?
|
|
210
|
+
|
|
211
|
+
search_path = if _schema_name is "public" then _schema_name else "#{_schema_name},public"
|
|
212
|
+
|
|
213
|
+
builder = new actn.Builder(_schema_name, _table_name, search_path, {where: _cond})
|
|
214
|
+
|
|
215
|
+
[sql,params] = builder.build_update(_data)
|
|
216
|
+
|
|
217
|
+
rows = plv8.execute(sql,params)
|
|
218
|
+
result = _.pluck(rows,'data')
|
|
219
|
+
result = result[0] if result.length is 1
|
|
220
|
+
|
|
221
|
+
builder = null
|
|
222
|
+
|
|
223
|
+
return JSON.stringify(result)
|
|
224
|
+
|
|
225
|
+
__delete: (_schema_name, _table_name, _cond) ->
|
|
226
|
+
search_path = if _schema_name is "public" then _schema_name else "#{_schema_name},public"
|
|
227
|
+
|
|
228
|
+
builder = new actn.Builder(_schema_name, _table_name, search_path, {where: _cond})
|
|
229
|
+
|
|
230
|
+
[sql,params] = builder.build_delete()
|
|
231
|
+
|
|
232
|
+
# plv8.elog(NOTICE,"DELETE",sql,params)
|
|
233
|
+
|
|
234
|
+
rows = plv8.execute(sql,params)
|
|
235
|
+
result = _.pluck(rows,'data')
|
|
236
|
+
result = result[0] if result.length is 1
|
|
237
|
+
|
|
238
|
+
builder = null
|
|
239
|
+
|
|
240
|
+
return JSON.stringify(result)
|
|
241
|
+
|
|
242
|
+
__validate: (_name, _data) ->
|
|
243
|
+
data = _data
|
|
244
|
+
|
|
245
|
+
# plv8.elog(NOTICE,"__VALIDATE",_name,JSON.stringify(_data))
|
|
246
|
+
|
|
247
|
+
return data unless model = plv8.find_function('__find_model')(_name)
|
|
248
|
+
|
|
249
|
+
model = JSON.parse(model)
|
|
250
|
+
|
|
251
|
+
# plv8.elog(NOTICE,"__VALIDATE MODEL",_name,JSON.stringify(model))
|
|
252
|
+
|
|
253
|
+
if model?.schema?
|
|
254
|
+
|
|
255
|
+
errors = actn.jjv.validate(model.schema,data)
|
|
256
|
+
|
|
257
|
+
# plv8.elog(NOTICE,"VALVAL",JSON.stringify(model.schema))
|
|
258
|
+
|
|
259
|
+
if data.uuid? and model.schema.readonly_attributes?
|
|
260
|
+
|
|
261
|
+
data = _.omit(data,model.schema.readonly_attributes)
|
|
262
|
+
|
|
263
|
+
# plv8.elog(NOTICE,"VALIDATE READONLY",JSON.stringify(data),JSON.stringify(model.schema.readonly_attributes))
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
else if model.schema.unique_attributes?
|
|
267
|
+
|
|
268
|
+
_schema = if _name is "Model" then "core" else "public"
|
|
269
|
+
_table = model.name.tableize()
|
|
270
|
+
__query = plv8.find_function("__query")
|
|
271
|
+
|
|
272
|
+
for uniq_attr in model.schema.unique_attributes or []
|
|
273
|
+
if data[uniq_attr]?
|
|
274
|
+
where = {}
|
|
275
|
+
where[uniq_attr] = data[uniq_attr]
|
|
276
|
+
# plv8.elog(NOTICE,"VALIDATE WHERE",JSON.stringify({where: where}))
|
|
277
|
+
found = JSON.parse(__query(_schema,_table,{where: where}))
|
|
278
|
+
# plv8.elog(NOTICE,"VALIDATE FOUND",JSON.stringify(found))
|
|
279
|
+
unless _.isEmpty(found)
|
|
280
|
+
errors ?= {validation: {}}
|
|
281
|
+
errors['validation'][uniq_attr] ?= {}
|
|
282
|
+
errors['validation'][uniq_attr]["has already been taken"] = true
|
|
283
|
+
|
|
284
|
+
data = {errors: errors} if errors?
|
|
285
|
+
|
|
286
|
+
# plv8.elog(NOTICE,"__VALIDATE DATA",_name,JSON.stringify(data))
|
|
287
|
+
|
|
288
|
+
return data
|
|
289
|
+
|
|
290
|
+
__find_model: (_name) ->
|
|
291
|
+
rows = plv8.execute("""SET search_path TO core,public;
|
|
292
|
+
SELECT data FROM core.models
|
|
293
|
+
WHERE __string(data,'name'::text) = $1::text""", [_name])
|
|
294
|
+
|
|
295
|
+
return unless rows?
|
|
296
|
+
|
|
297
|
+
result = _.pluck(rows,'data')[0]
|
|
298
|
+
|
|
299
|
+
return JSON.stringify(result)
|
|
300
|
+
|
|
301
|
+
model_callbacks: (TG_OP, NEW, OLD) ->
|
|
302
|
+
table_name = (NEW?.data?.name or OLD?.data?.name)?.tableize()
|
|
303
|
+
table_schema = (NEW?.data?.table_schema or OLD?.data?.table_schema) or "public"
|
|
304
|
+
|
|
305
|
+
return if table_schema is "core"
|
|
306
|
+
|
|
307
|
+
# plv8.elog(NOTICE,"MODEL CALLBACKS",table_schema,JSON.stringify(NEW?.data or OLD?.data))
|
|
308
|
+
|
|
309
|
+
mapper = (ind) -> _.keys(ind.cols)
|
|
310
|
+
differ = (_ind) ->
|
|
311
|
+
(ind) ->
|
|
312
|
+
_.isEmpty( _.difference( _.keys(ind.cols), _.flatten( _.map( _ind.data?.indexes, mapper ) ) ) )
|
|
313
|
+
|
|
314
|
+
switch TG_OP
|
|
315
|
+
when "INSERT"
|
|
316
|
+
plv8.execute "SELECT __create_table($1,$2)",[table_schema , table_name]
|
|
317
|
+
|
|
318
|
+
plv8.execute "SELECT __create_index($1,$2,$3)", [table_schema, table_name, {cols: {path: "text" }}]
|
|
319
|
+
|
|
320
|
+
for indopts in NEW?.data?.indexes or []
|
|
321
|
+
plv8.execute "SELECT __create_index($1,$2,$3)", [table_schema, table_name, indopts]
|
|
322
|
+
|
|
323
|
+
when "UPDATE"
|
|
324
|
+
|
|
325
|
+
diff = _.reject( OLD?.data?.indexes, differ(NEW) )
|
|
326
|
+
|
|
327
|
+
for indopts in diff
|
|
328
|
+
plv8.execute "SELECT __drop_index($1,$2,$3)", [table_schema, table_name, indopts]
|
|
329
|
+
|
|
330
|
+
diff = _.reject( NEW?.data?.indexes, differ(OLD) )
|
|
331
|
+
|
|
332
|
+
for indopts in diff
|
|
333
|
+
plv8.execute "SELECT __create_index($1,$2,$3)", [table_schema, table_name, indopts]
|
|
334
|
+
|
|
335
|
+
when "DELETE"
|
|
336
|
+
for indopts in Old?.data?.indexes or []
|
|
337
|
+
plv8.execute "SELECT __drop_index($1,$2,$3)", [table_schema, table_name, indopts]
|
|
338
|
+
plv8.execute "SELECT __drop_table($1,$2)",[table_schema , table_name]
|
|
339
|
+
|
|
340
|
+
hook_trigger: (TG_TABLE_NAME, TG_OP, NEW, OLD) ->
|
|
341
|
+
upsert_func = plv8.find_function("__upsert")
|
|
342
|
+
model = JSON.parse(plv8.find_function("__find_model")(TG_TABLE_NAME.classify()))
|
|
343
|
+
|
|
344
|
+
callback = {
|
|
345
|
+
INSERT: "after_create"
|
|
346
|
+
UPDATE: "after_update"
|
|
347
|
+
DELETE: "after_destroy"
|
|
348
|
+
}[TG_OP]
|
|
349
|
+
|
|
350
|
+
# plv8.elog(NOTICE,"HOOK TRIGGER",JSON.stringify(model))
|
|
351
|
+
|
|
352
|
+
for hook in model?.hooks?[callback] or []
|
|
353
|
+
hook.run_at ?= new Date()
|
|
354
|
+
hook.callback = callback
|
|
355
|
+
|
|
356
|
+
job =
|
|
357
|
+
hook: hook
|
|
358
|
+
table_name: TG_TABLE_NAME
|
|
359
|
+
record_uuid: NEW?.data?.uuid or OLD?.data?.uuid
|
|
360
|
+
record: OLD.data if TG_OP is "DELETE"
|
|
361
|
+
|
|
362
|
+
res = upsert_func "core", "jobs", JSON.stringify(job)
|
|
363
|
+
plv8.execute "SELECT pg_notify('jobs', $1);", [res]
|
|
364
|
+
|
|
365
|
+
jobs_model_callbacks: (TG_TABLE_NAME, TG_OP, NEW, OLD) ->
|
|
366
|
+
table_name = (NEW?.data?.name or OLD?.data?.name).tableize()
|
|
367
|
+
|
|
368
|
+
table_schema = (NEW?.data?.table_schema or OLD?.data?.table_schema) or "public"
|
|
369
|
+
|
|
370
|
+
return if table_schema is "core"
|
|
371
|
+
|
|
372
|
+
if TG_OP is "DELETE"
|
|
373
|
+
plv8.execute "DELETE FROM core.jobs WHERE __string(data, 'table_name'::text) = $1;", [table_name]
|
|
374
|
+
|
|
375
|
+
# if TG_OP is "DELETE" and OLD.data.hooks? or TG_OP is "UPDATE" and NEW.data.hooks?
|
|
376
|
+
# plv8.execute "DROP TRIGGER IF EXISTS #{table_schema}_#{table_name}_hook_trigger ON #{table_schema}.#{table_name}"
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
if TG_OP is "INSERT" or TG_OP is "UPDATE" and NEW.data.hooks? and not OLD.data.hooks?
|
|
380
|
+
plv8.execute """CREATE TRIGGER #{table_schema}_#{table_name}_hook_trigger
|
|
381
|
+
AFTER INSERT OR UPDATE OR DELETE ON #{table_schema}.#{table_name}
|
|
382
|
+
FOR EACH ROW EXECUTE PROCEDURE hook_trigger();"""
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
root.actn.funcs = new Funcs
|
|
386
|
+
|
|
387
|
+
).call this
|