nodester 0.2.3 → 0.2.5
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.
- package/Readme.md +4 -4
- package/lib/factories/responses/rest.js +7 -11
- package/lib/middlewares/ql/sequelize/interpreter/QueryLexer.js +118 -43
- package/lib/query/traverse.js +63 -48
- package/lib/tools/nql.tool.js +34 -21
- package/package.json +1 -1
- package/tests/{ast.test.js → ast.js} +4 -2
- package/tests/nql.test.js +442 -224
package/tests/nql.test.js
CHANGED
|
@@ -10,285 +10,503 @@ const {
|
|
|
10
10
|
const { ModelsTree } = require('../lib/middlewares/ql/sequelize/interpreter/ModelsTree');
|
|
11
11
|
const QueryLexer = require('../lib/middlewares/ql/sequelize/interpreter/QueryLexer');
|
|
12
12
|
|
|
13
|
+
|
|
14
|
+
|
|
13
15
|
describe('nodester Query Language', () => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
'
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
// Like simple.
|
|
51
|
-
'title=like(some_text)',
|
|
52
|
-
|
|
53
|
-
// Subinclude and isolated Horizontal.
|
|
54
|
-
'in=comments.user,likes',
|
|
55
|
-
];
|
|
56
|
-
|
|
57
|
-
it('query "Simple where"', () => {
|
|
58
|
-
const lexer = new QueryLexer( queryStrings[0] );
|
|
59
|
-
const result = lexer.query;
|
|
60
|
-
|
|
61
|
-
const tree = new ModelsTree();
|
|
62
|
-
tree.node.addWhere({ id: ['10'] });
|
|
63
|
-
const expected = tree.root.toObject();
|
|
64
|
-
|
|
65
|
-
expect(result).toMatchObject(expected);
|
|
16
|
+
describe('flat', () => {
|
|
17
|
+
const queryStrings = [
|
|
18
|
+
// Simple where.
|
|
19
|
+
'id=10',
|
|
20
|
+
// All possible params.
|
|
21
|
+
'id=10&position=4&limit=3&skip=10&order=desc&order_by=index&fields=id,content,position,created_at',
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
it('Simple where', () => {
|
|
25
|
+
const lexer = new QueryLexer( queryStrings[0] );
|
|
26
|
+
const result = lexer.query;
|
|
27
|
+
|
|
28
|
+
const tree = new ModelsTree();
|
|
29
|
+
tree.node.addWhere({ id: ['10'] });
|
|
30
|
+
const expected = tree.root.toObject();
|
|
31
|
+
|
|
32
|
+
expect(result).toMatchObject(expected);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('All possible params', () => {
|
|
36
|
+
const lexer = new QueryLexer( queryStrings[1] );
|
|
37
|
+
const result = lexer.query;
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
const tree = new ModelsTree();
|
|
41
|
+
tree.node.addWhere({ id: ['10'], position: ['4'] });
|
|
42
|
+
tree.node.fields = [ 'id', 'content', 'position', 'created_at' ];
|
|
43
|
+
tree.node.limit = 3;
|
|
44
|
+
tree.node.skip = 10;
|
|
45
|
+
tree.node.order = 'desc';
|
|
46
|
+
tree.node.order_by = 'index';
|
|
47
|
+
const expected = tree.root.toObject();
|
|
48
|
+
|
|
49
|
+
expect(result).toMatchObject(expected);
|
|
50
|
+
});
|
|
66
51
|
});
|
|
67
52
|
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
|
|
53
|
+
describe('includes', () => {
|
|
54
|
+
const queryStrings = [
|
|
55
|
+
// Simple includes.
|
|
56
|
+
'includes=comments&id=7',
|
|
57
|
+
// Include with All possible params.
|
|
58
|
+
'includes=comments(id=10&position=4&limit=3&skip=10&order=desc&order_by=index&fields=id,content,position)',
|
|
59
|
+
|
|
60
|
+
// 2 horizontals
|
|
61
|
+
'includes=comments,users&id=1000',
|
|
62
|
+
|
|
63
|
+
// Horizontals queried.
|
|
64
|
+
'includes=comments(order=desc),users,likes(order=rand),reposts&id=1000',
|
|
65
|
+
// Horizontals queried №2.
|
|
66
|
+
'in=reactions,comments(user_id=gte(4)&skip=10&limit=2).users,likes,reposts',
|
|
67
|
+
|
|
68
|
+
// Separated includes.
|
|
69
|
+
'includes=comments(order=rand)&id=7&limit=3&includes=users(fields=id,content)',
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
test('Simple includes', () => {
|
|
73
|
+
const lexer = new QueryLexer( queryStrings[0] );
|
|
74
|
+
const result = lexer.query;
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
const tree = new ModelsTree();
|
|
78
|
+
tree.node.addWhere({ id: ['7'] });
|
|
79
|
+
tree.include('comments');
|
|
80
|
+
const expected = tree.root.toObject();
|
|
81
|
+
|
|
82
|
+
expect(result).toMatchObject(expected);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('Include with all possible params', () => {
|
|
86
|
+
const lexer = new QueryLexer( queryStrings[1] );
|
|
87
|
+
const result = lexer.query;
|
|
88
|
+
|
|
89
|
+
const tree = new ModelsTree();
|
|
90
|
+
tree.include('comments').use('comments');
|
|
91
|
+
tree.node.addWhere({ id: ['10'], position: ['4'] });
|
|
92
|
+
tree.node.fields = [ 'id', 'content', 'position' ];
|
|
93
|
+
tree.node.limit = 3;
|
|
94
|
+
tree.node.skip = 10;
|
|
95
|
+
tree.node.order = 'desc';
|
|
96
|
+
tree.node.order_by = 'index';
|
|
97
|
+
const expected = tree.root.toObject();
|
|
98
|
+
|
|
99
|
+
expect(result).toMatchObject(expected);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('2 horizontals', () => {
|
|
103
|
+
const lexer = new QueryLexer( queryStrings[2] );
|
|
104
|
+
const result = lexer.query;
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
const tree = new ModelsTree();
|
|
108
|
+
tree.node.addWhere({ id: ['1000'] });
|
|
109
|
+
tree.include('comments');
|
|
110
|
+
tree.include('users');
|
|
111
|
+
const expected = tree.root.toObject();
|
|
112
|
+
|
|
113
|
+
expect(result).toMatchObject(expected);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test('Horizontals queried', () => {
|
|
117
|
+
const lexer = new QueryLexer( queryStrings[3] );
|
|
118
|
+
const result = lexer.query;
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
const tree = new ModelsTree();
|
|
122
|
+
tree.node.addWhere({ id: ['1000'] });
|
|
123
|
+
tree.include('comments').use('comments');
|
|
124
|
+
tree.node.order = 'desc';
|
|
125
|
+
tree.up();
|
|
126
|
+
tree.include('users');
|
|
127
|
+
tree.include('likes') && tree.use('likes');
|
|
128
|
+
tree.node.order = 'rand';
|
|
129
|
+
tree.up();
|
|
130
|
+
tree.include('reposts');
|
|
131
|
+
const expected = tree.root.toObject();
|
|
132
|
+
|
|
133
|
+
expect(result).toMatchObject(expected);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('Horizontals queried №2', () => {
|
|
137
|
+
const lexer = new QueryLexer( queryStrings[4] );
|
|
138
|
+
const result = lexer.query;
|
|
139
|
+
|
|
140
|
+
const tree = new ModelsTree();
|
|
141
|
+
tree.include('reactions');
|
|
142
|
+
|
|
143
|
+
tree.include('comments').use('comments');
|
|
144
|
+
tree.node.addWhere({
|
|
145
|
+
user_id: {
|
|
146
|
+
gte: ['4']
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
tree.node.skip = 10;
|
|
150
|
+
tree.node.limit = 2;
|
|
151
|
+
|
|
152
|
+
tree.include('users');
|
|
153
|
+
tree.up();
|
|
154
|
+
|
|
155
|
+
tree.include('likes');
|
|
156
|
+
tree.include('reposts');
|
|
157
|
+
|
|
158
|
+
const expected = tree.root.toObject();
|
|
159
|
+
|
|
160
|
+
expect(result).toMatchObject(expected);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test('Separated includes"', () => {
|
|
164
|
+
const lexer = new QueryLexer( queryStrings[5] );
|
|
165
|
+
const result = lexer.query;
|
|
166
|
+
|
|
167
|
+
const tree = new ModelsTree();
|
|
168
|
+
tree.node.addWhere({ id: ['7'] });
|
|
169
|
+
tree.node.limit = 3;
|
|
170
|
+
tree.include('comments').use('comments');
|
|
171
|
+
tree.node.order = 'rand';
|
|
172
|
+
tree.up();
|
|
173
|
+
tree.include('users').use('users');
|
|
174
|
+
tree.node.fields = [ 'id', 'content' ];
|
|
175
|
+
const expected = tree.root.toObject();
|
|
176
|
+
|
|
177
|
+
expect(result).toMatchObject(expected);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
71
180
|
|
|
181
|
+
describe('subincludes', () => {
|
|
182
|
+
const queryStrings = [
|
|
183
|
+
// Simple subinclude.
|
|
184
|
+
'includes=comments.users',
|
|
72
185
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
tree.node.fields = [ 'id', 'content', 'position', 'created_at' ];
|
|
76
|
-
tree.node.limit = 3;
|
|
77
|
-
tree.node.skip = 10;
|
|
78
|
-
tree.node.order = 'desc';
|
|
79
|
-
tree.node.order_by = 'index';
|
|
80
|
-
const expected = tree.root.toObject();
|
|
186
|
+
// Deep subincludes.
|
|
187
|
+
'in=posts.comments.users.avatars.sizes&position=200',
|
|
81
188
|
|
|
82
|
-
|
|
83
|
-
|
|
189
|
+
// Simple horizontal subinclude, "+" syntaxis.
|
|
190
|
+
'includes=comments.users+likes',
|
|
84
191
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const result = lexer.query;
|
|
192
|
+
// Subinclude query.
|
|
193
|
+
'includes=comments.users(order=rand&order_by=position)',
|
|
88
194
|
|
|
195
|
+
// Complex subincludes query, "+" syntaxis.
|
|
196
|
+
'includes=comments(order=desc).users+likes(order=rand&order_by=position)&id=1000',
|
|
197
|
+
];
|
|
89
198
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const expected = tree.root.toObject();
|
|
199
|
+
test('Simple subinclude', () => {
|
|
200
|
+
const lexer = new QueryLexer( queryStrings[0] );
|
|
201
|
+
const result = lexer.query;
|
|
94
202
|
|
|
95
|
-
expect(result).toMatchObject(expected);
|
|
96
|
-
});
|
|
97
203
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const tree = new ModelsTree();
|
|
103
|
-
tree.include('comments').use('comments');
|
|
104
|
-
tree.node.addWhere({ id: ['10'], position: ['4'] });
|
|
105
|
-
tree.node.fields = [ 'id', 'content', 'position' ];
|
|
106
|
-
tree.node.limit = 3;
|
|
107
|
-
tree.node.skip = 10;
|
|
108
|
-
tree.node.order = 'desc';
|
|
109
|
-
tree.node.order_by = 'index';
|
|
110
|
-
const expected = tree.root.toObject();
|
|
111
|
-
|
|
112
|
-
expect(result).toMatchObject(expected);
|
|
113
|
-
});
|
|
204
|
+
const tree = new ModelsTree();
|
|
205
|
+
tree.include('comments').use('comments');
|
|
206
|
+
tree.include('users');
|
|
207
|
+
const expected = tree.root.toObject();
|
|
114
208
|
|
|
209
|
+
expect(result).toMatchObject(expected);
|
|
210
|
+
});
|
|
115
211
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
212
|
+
test('Deep subincludes', () => {
|
|
213
|
+
const lexer = new QueryLexer( queryStrings[1] );
|
|
214
|
+
const result = lexer.query;
|
|
119
215
|
|
|
120
216
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
217
|
+
const tree = new ModelsTree();
|
|
218
|
+
tree.include('posts').use('posts');
|
|
219
|
+
tree.include('comments').use('comments');
|
|
220
|
+
tree.include('users').use('users');
|
|
221
|
+
tree.include('avatars').use('avatars');
|
|
222
|
+
tree.include('sizes').use('sizes');
|
|
223
|
+
const expected = tree.root.toObject();
|
|
126
224
|
|
|
127
|
-
|
|
128
|
-
|
|
225
|
+
expect(result).toMatchObject(expected);
|
|
226
|
+
});
|
|
129
227
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
228
|
+
test('Simple horizontal subinclude, "+" syntaxis"', () => {
|
|
229
|
+
const lexer = new QueryLexer( queryStrings[2] );
|
|
230
|
+
const result = lexer.query;
|
|
133
231
|
|
|
134
232
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
233
|
+
const tree = new ModelsTree();
|
|
234
|
+
tree.include('comments').use('comments');
|
|
235
|
+
tree.include('users');
|
|
236
|
+
tree.include('likes');
|
|
237
|
+
const expected = tree.root.toObject();
|
|
238
|
+
|
|
239
|
+
expect(result).toMatchObject(expected);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test('Subinclude query', () => {
|
|
243
|
+
const lexer = new QueryLexer( queryStrings[3] );
|
|
244
|
+
const result = lexer.query;
|
|
146
245
|
|
|
147
|
-
expect(result).toMatchObject(expected);
|
|
148
|
-
});
|
|
149
246
|
|
|
247
|
+
const tree = new ModelsTree();
|
|
248
|
+
tree.include('comments').use('comments');
|
|
249
|
+
tree.include('users').use('users');
|
|
250
|
+
tree.node.order = 'rand';
|
|
251
|
+
tree.node.order_by = 'position';
|
|
252
|
+
const expected = tree.root.toObject();
|
|
150
253
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const result = lexer.query;
|
|
254
|
+
expect(result).toMatchObject(expected);
|
|
255
|
+
});
|
|
154
256
|
|
|
257
|
+
test('Complex subincludes query, "+" syntaxis', () => {
|
|
258
|
+
const lexer = new QueryLexer( queryStrings[4] );
|
|
259
|
+
const result = lexer.query;
|
|
155
260
|
|
|
156
|
-
const tree = new ModelsTree();
|
|
157
|
-
tree.node.addWhere({ id: ['1000'] });
|
|
158
|
-
tree.include('comments').use('comments');
|
|
159
|
-
tree.node.order = 'desc';
|
|
160
|
-
tree.include('users');
|
|
161
|
-
tree.include('likes') && tree.use('likes');
|
|
162
|
-
tree.node.order = 'rand';
|
|
163
|
-
tree.node.order_by = 'position';
|
|
164
|
-
tree.up();
|
|
165
|
-
const expected = tree.root.toObject();
|
|
166
261
|
|
|
167
|
-
|
|
262
|
+
const tree = new ModelsTree();
|
|
263
|
+
tree.node.addWhere({ id: ['1000'] });
|
|
264
|
+
tree.include('comments').use('comments');
|
|
265
|
+
tree.node.order = 'desc';
|
|
266
|
+
tree.include('users');
|
|
267
|
+
tree.include('likes') && tree.use('likes');
|
|
268
|
+
tree.node.order = 'rand';
|
|
269
|
+
tree.node.order_by = 'position';
|
|
270
|
+
tree.up();
|
|
271
|
+
const expected = tree.root.toObject();
|
|
272
|
+
|
|
273
|
+
expect(result).toMatchObject(expected);
|
|
274
|
+
});
|
|
168
275
|
});
|
|
169
276
|
|
|
277
|
+
describe('operators:or', () => {
|
|
278
|
+
const queryStrings = [
|
|
279
|
+
// OR simple.
|
|
280
|
+
'or(index=2,position=5)',
|
|
281
|
+
// OR short.
|
|
282
|
+
'|(index=2,position=5)',
|
|
283
|
+
];
|
|
284
|
+
|
|
285
|
+
test('"OR" simple', () => {
|
|
286
|
+
const lexer = new QueryLexer( queryStrings[0] );
|
|
287
|
+
const result = lexer.query;
|
|
288
|
+
|
|
289
|
+
const tree = new ModelsTree();
|
|
290
|
+
tree.node.addWhere({ or: [ { index: ['2'] }, { position: ['5'] } ] });
|
|
291
|
+
const expected = tree.root.toObject();
|
|
170
292
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const result = lexer.query;
|
|
293
|
+
expect(result).toMatchObject(expected);
|
|
294
|
+
});
|
|
174
295
|
|
|
296
|
+
test('"OR" short', () => {
|
|
297
|
+
const lexer = new QueryLexer( queryStrings[1] );
|
|
298
|
+
const result = lexer.query;
|
|
175
299
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
tree.include('users');
|
|
180
|
-
const expected = tree.root.toObject();
|
|
300
|
+
const tree = new ModelsTree();
|
|
301
|
+
tree.node.addWhere({ or: [ { index: ['2'] }, { position: ['5'] } ] });
|
|
302
|
+
const expected = tree.root.toObject();
|
|
181
303
|
|
|
182
|
-
|
|
304
|
+
expect(result).toMatchObject(expected);
|
|
305
|
+
});
|
|
183
306
|
});
|
|
184
307
|
|
|
185
|
-
|
|
186
|
-
const
|
|
187
|
-
|
|
308
|
+
describe('operators:not', () => {
|
|
309
|
+
const queryStrings = [
|
|
310
|
+
// Not simple.
|
|
311
|
+
'key=not(main)',
|
|
312
|
+
// Not short.
|
|
313
|
+
'key=!(main)',
|
|
314
|
+
// NOT inside include.
|
|
315
|
+
'includes=comments(id=not(7))'
|
|
316
|
+
];
|
|
188
317
|
|
|
318
|
+
test('"NOT" simple', () => {
|
|
319
|
+
const lexer = new QueryLexer( queryStrings[0] );
|
|
320
|
+
const result = lexer.query;
|
|
189
321
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
tree.include('users').use('users');
|
|
194
|
-
tree.include('avatars').use('avatars');
|
|
195
|
-
tree.include('sizes').use('sizes');
|
|
196
|
-
const expected = tree.root.toObject();
|
|
322
|
+
const tree = new ModelsTree();
|
|
323
|
+
tree.node.addWhere({ key: { not: ['main'] } });
|
|
324
|
+
const expected = tree.root.toObject();
|
|
197
325
|
|
|
198
|
-
|
|
199
|
-
|
|
326
|
+
expect(result).toMatchObject(expected);
|
|
327
|
+
});
|
|
200
328
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
const tree = new ModelsTree();
|
|
206
|
-
tree.node.addWhere({ id: ['7'] });
|
|
207
|
-
tree.node.limit = 3;
|
|
208
|
-
tree.include('comments').use('comments');
|
|
209
|
-
tree.include('users').use('users');
|
|
210
|
-
tree.include('avatars').use('avatars');
|
|
211
|
-
tree.node.fields = [ 'id', 'content' ];
|
|
212
|
-
tree.node.order = 'rand';
|
|
213
|
-
const expected = tree.root.toObject();
|
|
214
|
-
|
|
215
|
-
expect(result).toMatchObject(expected);
|
|
216
|
-
});
|
|
329
|
+
test('"NOT" short', () => {
|
|
330
|
+
const lexer = new QueryLexer( queryStrings[1] );
|
|
331
|
+
const result = lexer.query;
|
|
217
332
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
tree.node.limit = 3;
|
|
225
|
-
tree.include('comments').use('comments');
|
|
226
|
-
tree.node.order = 'rand';
|
|
227
|
-
tree.up();
|
|
228
|
-
tree.include('users').use('users');
|
|
229
|
-
tree.node.fields = [ 'id', 'content' ];
|
|
230
|
-
const expected = tree.root.toObject();
|
|
231
|
-
|
|
232
|
-
expect(result).toMatchObject(expected);
|
|
233
|
-
});
|
|
333
|
+
const tree = new ModelsTree();
|
|
334
|
+
tree.node.addWhere({ key: { not: ['main'] } });
|
|
335
|
+
const expected = tree.root.toObject();
|
|
336
|
+
|
|
337
|
+
expect(result).toMatchObject(expected);
|
|
338
|
+
});
|
|
234
339
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
340
|
+
test('"NOT" inside includes', () => {
|
|
341
|
+
const lexer = new QueryLexer( queryStrings[2] );
|
|
342
|
+
const result = lexer.query;
|
|
238
343
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
344
|
+
const tree = new ModelsTree();
|
|
345
|
+
tree.include('comments').use('comments');
|
|
346
|
+
tree.node.addWhere({ id: { not: ['7'] }});
|
|
347
|
+
const expected = tree.root.toObject();
|
|
348
|
+
|
|
349
|
+
expect(result).toMatchObject(expected);
|
|
350
|
+
});
|
|
242
351
|
|
|
243
|
-
expect(result).toMatchObject(expected);
|
|
244
352
|
});
|
|
245
353
|
|
|
246
|
-
|
|
247
|
-
const
|
|
248
|
-
|
|
354
|
+
describe('operators:like', () => {
|
|
355
|
+
const queryStrings = [
|
|
356
|
+
// Like simple.
|
|
357
|
+
'title=like(some_text)',
|
|
249
358
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
359
|
+
// Not like simple.
|
|
360
|
+
'title=notLike(some_text)',
|
|
361
|
+
// Not like short.
|
|
362
|
+
'title=!like(some_text)',
|
|
363
|
+
];
|
|
253
364
|
|
|
254
|
-
|
|
255
|
-
|
|
365
|
+
test('"Like" simple', () => {
|
|
366
|
+
const lexer = new QueryLexer( queryStrings[0] );
|
|
367
|
+
const result = lexer.query;
|
|
256
368
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
369
|
+
const tree = new ModelsTree();
|
|
370
|
+
tree.node.addWhere({ title: { like: ['some_text'] }});
|
|
371
|
+
const expected = tree.root.toObject();
|
|
260
372
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
tree.node.addWhere({ id: { not: ['7'] }});
|
|
264
|
-
const expected = tree.root.toObject();
|
|
373
|
+
expect(result).toMatchObject(expected);
|
|
374
|
+
});
|
|
265
375
|
|
|
266
|
-
|
|
267
|
-
|
|
376
|
+
test('"NotLike" simple', () => {
|
|
377
|
+
const lexer = new QueryLexer( queryStrings[1] );
|
|
378
|
+
const result = lexer.query;
|
|
268
379
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
380
|
+
const tree = new ModelsTree();
|
|
381
|
+
tree.node.addWhere({ title: { notLike: ['some_text'] }});
|
|
382
|
+
const expected = tree.root.toObject();
|
|
272
383
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
const expected = tree.root.toObject();
|
|
384
|
+
expect(result).toMatchObject(expected);
|
|
385
|
+
});
|
|
276
386
|
|
|
277
|
-
|
|
387
|
+
test('"NotLike" short', () => {
|
|
388
|
+
const lexer = new QueryLexer( queryStrings[2] );
|
|
389
|
+
const result = lexer.query;
|
|
390
|
+
|
|
391
|
+
const tree = new ModelsTree();
|
|
392
|
+
tree.node.addWhere({ title: { notLike: ['some_text'] }});
|
|
393
|
+
const expected = tree.root.toObject();
|
|
394
|
+
|
|
395
|
+
expect(result).toMatchObject(expected);
|
|
396
|
+
});
|
|
278
397
|
});
|
|
279
398
|
|
|
280
|
-
|
|
281
|
-
const
|
|
282
|
-
|
|
399
|
+
describe('operators:in', () => {
|
|
400
|
+
const queryStrings = [
|
|
401
|
+
// IN simple.
|
|
402
|
+
'status=[REVIEWED,ANSWERED]',
|
|
403
|
+
|
|
404
|
+
// IN and limit clause.
|
|
405
|
+
'status=[REVIEWED,ANSWERED]&limit=3',
|
|
406
|
+
];
|
|
407
|
+
|
|
408
|
+
test('"IN" simple', () => {
|
|
409
|
+
const lexer = new QueryLexer( queryStrings[0] );
|
|
410
|
+
const result = lexer.query;
|
|
411
|
+
|
|
412
|
+
const tree = new ModelsTree();
|
|
413
|
+
tree.node.addWhere({ status: { in: ['REVIEWED', 'ANSWERED'] }});
|
|
414
|
+
const expected = tree.root.toObject();
|
|
415
|
+
|
|
416
|
+
expect(result).toMatchObject(expected);
|
|
417
|
+
});
|
|
283
418
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
tree.up();
|
|
288
|
-
tree.include('likes');
|
|
289
|
-
const expected = tree.root.toObject();
|
|
419
|
+
test('"IN" and "limit" clause', () => {
|
|
420
|
+
const lexer = new QueryLexer( queryStrings[1] );
|
|
421
|
+
const result = lexer.query;
|
|
290
422
|
|
|
291
|
-
|
|
423
|
+
const tree = new ModelsTree();
|
|
424
|
+
tree.node.limit = 3;
|
|
425
|
+
tree.node.addWhere({ status: { in: ['REVIEWED', 'ANSWERED'] }});
|
|
426
|
+
const expected = tree.root.toObject();
|
|
427
|
+
|
|
428
|
+
expect(result).toMatchObject(expected);
|
|
429
|
+
});
|
|
292
430
|
});
|
|
293
431
|
|
|
432
|
+
describe('operators:inequality', () => {
|
|
433
|
+
const queryStrings = [
|
|
434
|
+
// Greater than.
|
|
435
|
+
'created_at=gt(2022)',
|
|
436
|
+
|
|
437
|
+
// Greater than or equal to.
|
|
438
|
+
'created_at=gte(2023-12-08)',
|
|
439
|
+
|
|
440
|
+
// Lower than.
|
|
441
|
+
'index=lt(10)',
|
|
442
|
+
|
|
443
|
+
// Lower than or equal to.
|
|
444
|
+
'index=lte(9)',
|
|
445
|
+
|
|
446
|
+
// Greater than in subinclude.
|
|
447
|
+
'in=comments.likes(index=gt(60))'
|
|
448
|
+
];
|
|
449
|
+
|
|
450
|
+
test('Greater than', () => {
|
|
451
|
+
const lexer = new QueryLexer( queryStrings[0] );
|
|
452
|
+
const result = lexer.query;
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
const tree = new ModelsTree();
|
|
456
|
+
tree.node.addWhere({ created_at: { gt: ['2022'] }});
|
|
457
|
+
const expected = tree.root.toObject();
|
|
458
|
+
|
|
459
|
+
expect(result).toMatchObject(expected);
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
test('Greater than or equal to', () => {
|
|
463
|
+
const lexer = new QueryLexer( queryStrings[1] );
|
|
464
|
+
const result = lexer.query;
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
const tree = new ModelsTree();
|
|
468
|
+
tree.node.addWhere({ created_at: { gte: ['2023-12-08'] }});
|
|
469
|
+
const expected = tree.root.toObject();
|
|
470
|
+
|
|
471
|
+
expect(result).toMatchObject(expected);
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
test('Lower than', () => {
|
|
475
|
+
const lexer = new QueryLexer( queryStrings[2] );
|
|
476
|
+
const result = lexer.query;
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
const tree = new ModelsTree();
|
|
480
|
+
tree.node.addWhere({ index: { lt: ['10'] }});
|
|
481
|
+
const expected = tree.root.toObject();
|
|
482
|
+
|
|
483
|
+
expect(result).toMatchObject(expected);
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
test('Lower than or equal to', () => {
|
|
487
|
+
const lexer = new QueryLexer( queryStrings[3] );
|
|
488
|
+
const result = lexer.query;
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
const tree = new ModelsTree();
|
|
492
|
+
tree.node.addWhere({ index: { lte: ['9'] }});
|
|
493
|
+
const expected = tree.root.toObject();
|
|
494
|
+
|
|
495
|
+
expect(result).toMatchObject(expected);
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
test('Greater than in subinclude', () => {
|
|
499
|
+
const lexer = new QueryLexer( queryStrings[4] );
|
|
500
|
+
const result = lexer.query;
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
const tree = new ModelsTree();
|
|
504
|
+
tree.include('comments').use('comments');
|
|
505
|
+
tree.include('likes').use('likes');
|
|
506
|
+
tree.node.addWhere({ index: { gt: ['60'] }});
|
|
507
|
+
const expected = tree.root.toObject();
|
|
508
|
+
|
|
509
|
+
expect(result).toMatchObject(expected);
|
|
510
|
+
});
|
|
511
|
+
});
|
|
294
512
|
});
|