remult 0.27.8-next.0 → 0.27.8-next.2
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/esm/remult-knex/index.js +7 -5
- package/esm/remult-mongo.js +93 -3
- package/esm/src/data-api.js +4 -3
- package/esm/src/data-providers/array-entity-data-provider.js +7 -7
- package/esm/src/data-providers/rest-data-provider.js +7 -3
- package/esm/src/data-providers/sql-database.js +105 -106
- package/esm/src/remult3/RepositoryImplementation.js +15 -6
- package/esm/src/remult3/remult3.js +0 -2
- package/package.json +1 -1
- package/remult-knex/index.js +17 -3
- package/remult-mongo.js +179 -20
- package/src/data-api.js +4 -3
- package/src/data-interfaces.d.ts +2 -2
- package/src/data-providers/array-entity-data-provider.js +12 -12
- package/src/data-providers/rest-data-provider.js +7 -3
- package/src/data-providers/sql-database.d.ts +2 -1
- package/src/data-providers/sql-database.js +220 -207
- package/src/remult3/RepositoryImplementation.js +17 -11
- package/src/remult3/remult3.d.ts +5 -3
- package/src/remult3/remult3.js +0 -2
package/esm/remult-knex/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { Sort } from '../src/sort.js';
|
|
|
7
7
|
import { ValueConverters } from '../src/valueConverters.js';
|
|
8
8
|
import { getRepositoryInternals } from '../src/remult3/repository-internals.js';
|
|
9
9
|
import { remultStatic } from '../src/remult-static.js';
|
|
10
|
-
import { getRowAfterUpdate } from '../src/data-providers/sql-database.js';
|
|
10
|
+
import { aggregateImpl, getRowAfterUpdate, } from '../src/data-providers/sql-database.js';
|
|
11
11
|
export class KnexDataProvider {
|
|
12
12
|
knex;
|
|
13
13
|
constructor(knex) {
|
|
@@ -70,7 +70,7 @@ export class KnexDataProvider {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
-
return new KnexEntityDataProvider(entity, this.knex, this.wrapIdentifier);
|
|
73
|
+
return new KnexEntityDataProvider(entity, this.knex, this.wrapIdentifier, this);
|
|
74
74
|
}
|
|
75
75
|
async transaction(action) {
|
|
76
76
|
let t = await this.knex.transaction();
|
|
@@ -110,13 +110,15 @@ class KnexEntityDataProvider {
|
|
|
110
110
|
entity;
|
|
111
111
|
knex;
|
|
112
112
|
rawSqlWrapIdentifier;
|
|
113
|
-
|
|
113
|
+
dp;
|
|
114
|
+
constructor(entity, knex, rawSqlWrapIdentifier, dp) {
|
|
114
115
|
this.entity = entity;
|
|
115
116
|
this.knex = knex;
|
|
116
117
|
this.rawSqlWrapIdentifier = rawSqlWrapIdentifier;
|
|
118
|
+
this.dp = dp;
|
|
117
119
|
}
|
|
118
|
-
aggregate(options) {
|
|
119
|
-
|
|
120
|
+
async aggregate(options) {
|
|
121
|
+
return aggregateImpl(options, await this.init(), this.dp.createCommand(), false, (limit, offset) => ' limit ' + limit + ' offset ' + offset);
|
|
120
122
|
}
|
|
121
123
|
async count(where) {
|
|
122
124
|
const e = await this.init();
|
package/esm/remult-mongo.js
CHANGED
|
@@ -5,6 +5,7 @@ import { remult as remultContext } from './src/remult-proxy.js';
|
|
|
5
5
|
import { getRepository } from './src/remult3/RepositoryImplementation.js';
|
|
6
6
|
import { getRepositoryInternals } from './src/remult3/repository-internals.js';
|
|
7
7
|
import { getRowAfterUpdate } from './src/data-providers/sql-database.js';
|
|
8
|
+
import { AggregateCountMember } from './src/remult3/remult3.js';
|
|
8
9
|
export class MongoDataProvider {
|
|
9
10
|
db;
|
|
10
11
|
client;
|
|
@@ -70,9 +71,6 @@ class MongoEntityDataProvider {
|
|
|
70
71
|
this.entity = entity;
|
|
71
72
|
this.session = session;
|
|
72
73
|
}
|
|
73
|
-
aggregate(options) {
|
|
74
|
-
throw new Error('Method not implemented.');
|
|
75
|
-
}
|
|
76
74
|
translateFromDb(row, nameProvider) {
|
|
77
75
|
let result = {};
|
|
78
76
|
for (const col of this.entity.fields) {
|
|
@@ -100,6 +98,98 @@ class MongoEntityDataProvider {
|
|
|
100
98
|
let w = await x.resolveWhere();
|
|
101
99
|
return await collection.countDocuments(w, { session: this.session });
|
|
102
100
|
}
|
|
101
|
+
async aggregate(options) {
|
|
102
|
+
let { collection, e } = await this.collection();
|
|
103
|
+
let x = new FilterConsumerBridgeToMongo(e);
|
|
104
|
+
const pipeLine = [];
|
|
105
|
+
if (options?.where) {
|
|
106
|
+
options.where.__applyToConsumer(x);
|
|
107
|
+
let where = await x.resolveWhere();
|
|
108
|
+
pipeLine.push({ $match: where });
|
|
109
|
+
}
|
|
110
|
+
const processResultRow = [];
|
|
111
|
+
const $group = {
|
|
112
|
+
__count: { $sum: 1 },
|
|
113
|
+
};
|
|
114
|
+
processResultRow.push((mongoRow, resultRow) => {
|
|
115
|
+
resultRow[AggregateCountMember] = mongoRow.__count;
|
|
116
|
+
});
|
|
117
|
+
pipeLine.push({ $group });
|
|
118
|
+
if (options?.groupBy) {
|
|
119
|
+
$group._id = {};
|
|
120
|
+
for (const element of options.groupBy) {
|
|
121
|
+
const name = e.$dbNameOf(element);
|
|
122
|
+
$group._id[name] = `$${name}`;
|
|
123
|
+
processResultRow.push((mongoRow, resultRow) => {
|
|
124
|
+
resultRow[element.key] = element.valueConverter.fromDb(mongoRow._id[name]);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
$group._id = null;
|
|
130
|
+
}
|
|
131
|
+
if (options?.sum) {
|
|
132
|
+
for (const element of options.sum) {
|
|
133
|
+
const name = e.$dbNameOf(element) + '_sum';
|
|
134
|
+
$group[name] = { $sum: `$${e.$dbNameOf(element)}` };
|
|
135
|
+
processResultRow.push((mongoRow, resultRow) => {
|
|
136
|
+
resultRow[element.key] = {
|
|
137
|
+
...resultRow[element.key],
|
|
138
|
+
sum: element.valueConverter.fromDb(mongoRow[name]),
|
|
139
|
+
};
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (options?.avg) {
|
|
144
|
+
for (const element of options.avg) {
|
|
145
|
+
const name = e.$dbNameOf(element) + '_avg';
|
|
146
|
+
$group[name] = { $avg: `$${e.$dbNameOf(element)}` };
|
|
147
|
+
processResultRow.push((mongoRow, resultRow) => {
|
|
148
|
+
resultRow[element.key] = {
|
|
149
|
+
...resultRow[element.key],
|
|
150
|
+
avg: element.valueConverter.fromDb(mongoRow[name]),
|
|
151
|
+
};
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (options?.orderBy) {
|
|
156
|
+
let sort = {};
|
|
157
|
+
for (const x of options.orderBy) {
|
|
158
|
+
const direction = x.isDescending ? -1 : 1;
|
|
159
|
+
switch (x.operation) {
|
|
160
|
+
case 'sum':
|
|
161
|
+
sort[e.$dbNameOf(x.field) + '_sum'] = direction;
|
|
162
|
+
break;
|
|
163
|
+
case 'avg':
|
|
164
|
+
sort[e.$dbNameOf(x.field) + '_avg'] = direction;
|
|
165
|
+
break;
|
|
166
|
+
case 'count':
|
|
167
|
+
sort['__count'] = direction;
|
|
168
|
+
break;
|
|
169
|
+
default:
|
|
170
|
+
sort['_id.' + e.$dbNameOf(x.field)] = direction;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
pipeLine.push({ $sort: sort });
|
|
174
|
+
}
|
|
175
|
+
if (options?.limit) {
|
|
176
|
+
pipeLine.push({ $limit: options.limit });
|
|
177
|
+
if (options.page) {
|
|
178
|
+
pipeLine.push({ $skip: (options.page - 1) * options.limit });
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const r = await collection
|
|
182
|
+
.aggregate(pipeLine, { session: this.session })
|
|
183
|
+
.toArray();
|
|
184
|
+
const r2 = r.map((x) => {
|
|
185
|
+
let resultRow = {};
|
|
186
|
+
for (const f of processResultRow) {
|
|
187
|
+
f(x, resultRow);
|
|
188
|
+
}
|
|
189
|
+
return resultRow;
|
|
190
|
+
});
|
|
191
|
+
return r2;
|
|
192
|
+
}
|
|
103
193
|
async find(options) {
|
|
104
194
|
let { collection, e } = await this.collection();
|
|
105
195
|
let x = new FilterConsumerBridgeToMongo(e);
|
package/esm/src/data-api.js
CHANGED
|
@@ -116,14 +116,15 @@ export class DataApi {
|
|
|
116
116
|
sum: direction,
|
|
117
117
|
};
|
|
118
118
|
break;
|
|
119
|
-
case '
|
|
119
|
+
case 'avg':
|
|
120
120
|
orderBy[element.field] = {
|
|
121
121
|
...orderBy[element.field],
|
|
122
|
-
|
|
122
|
+
avg: direction,
|
|
123
123
|
};
|
|
124
124
|
break;
|
|
125
125
|
case 'count':
|
|
126
126
|
orderBy[AggregateCountMember] = direction;
|
|
127
|
+
break;
|
|
127
128
|
default:
|
|
128
129
|
orderBy[element.field] = direction;
|
|
129
130
|
break;
|
|
@@ -136,7 +137,7 @@ export class DataApi {
|
|
|
136
137
|
page: findOptions.page,
|
|
137
138
|
groupBy: body?.groupBy?.filter((x) => this.repository.fields.find(x).includedInApi()),
|
|
138
139
|
sum: body?.sum?.filter((x) => this.repository.fields.find(x).includedInApi()),
|
|
139
|
-
|
|
140
|
+
avg: body?.avg?.filter((x) => this.repository.fields.find(x).includedInApi()),
|
|
140
141
|
orderBy: orderBy,
|
|
141
142
|
});
|
|
142
143
|
if (!Array.isArray(result)) {
|
|
@@ -50,8 +50,8 @@ export class ArrayEntityDataProvider {
|
|
|
50
50
|
aggregates.push(new Sum(element.key));
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
-
if (options?.
|
|
54
|
-
class
|
|
53
|
+
if (options?.avg) {
|
|
54
|
+
class Avg {
|
|
55
55
|
key;
|
|
56
56
|
constructor(key) {
|
|
57
57
|
this.key = key;
|
|
@@ -68,14 +68,14 @@ export class ArrayEntityDataProvider {
|
|
|
68
68
|
finishGroup(result) {
|
|
69
69
|
result[this.key] = {
|
|
70
70
|
...result[this.key],
|
|
71
|
-
|
|
71
|
+
avg: this.sum / this.count,
|
|
72
72
|
};
|
|
73
73
|
this.sum = 0;
|
|
74
74
|
this.count = 0;
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
-
for (const element of options.
|
|
78
|
-
aggregates.push(new
|
|
77
|
+
for (const element of options.avg) {
|
|
78
|
+
aggregates.push(new Avg(element.key));
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
function finishGroup() {
|
|
@@ -122,8 +122,8 @@ export class ArrayEntityDataProvider {
|
|
|
122
122
|
switch (x.operation) {
|
|
123
123
|
case 'sum':
|
|
124
124
|
return row[x.field.key].sum;
|
|
125
|
-
case '
|
|
126
|
-
return row[x.field.key].
|
|
125
|
+
case 'avg':
|
|
126
|
+
return row[x.field.key].avg;
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
return row[x.field.key];
|
|
@@ -110,7 +110,7 @@ export class RestEntityDataProvider {
|
|
|
110
110
|
const body = {
|
|
111
111
|
groupBy: options?.groupBy?.map((x) => x.key),
|
|
112
112
|
sum: options?.sum?.map((x) => x.key),
|
|
113
|
-
|
|
113
|
+
avg: options?.avg?.map((x) => x.key),
|
|
114
114
|
orderBy: options?.orderBy?.map((x) => ({ ...x, field: x.field?.key })),
|
|
115
115
|
};
|
|
116
116
|
const result = await run('aggregate', Object.keys(body).length > 0 ? body : undefined);
|
|
@@ -196,9 +196,13 @@ export class RestEntityDataProvider {
|
|
|
196
196
|
if (action)
|
|
197
197
|
u.add('__action', action);
|
|
198
198
|
if (filterObject) {
|
|
199
|
-
|
|
199
|
+
if (method === 'put') {
|
|
200
|
+
return this.http().post(u.url, { set: body, where: filterObject });
|
|
201
|
+
}
|
|
202
|
+
else
|
|
203
|
+
body = { ...body, where: filterObject };
|
|
200
204
|
}
|
|
201
|
-
if (body)
|
|
205
|
+
if (body && method != 'put')
|
|
202
206
|
return this.http().post(u.url, body);
|
|
203
207
|
else
|
|
204
208
|
return this.http()[method](u.url, body);
|
|
@@ -288,112 +288,7 @@ class ActualSQLEntityDataProvider {
|
|
|
288
288
|
});
|
|
289
289
|
}
|
|
290
290
|
async aggregate(options) {
|
|
291
|
-
|
|
292
|
-
let select = 'select count(*) as count';
|
|
293
|
-
let groupBy = '';
|
|
294
|
-
const processResultRow = [];
|
|
295
|
-
processResultRow.push((sqlVal, theResult) => {
|
|
296
|
-
theResult[AggregateCountMember] = Number(sqlVal);
|
|
297
|
-
});
|
|
298
|
-
if (options?.groupBy)
|
|
299
|
-
for (const x of options?.groupBy) {
|
|
300
|
-
if (x.isServerExpression) {
|
|
301
|
-
}
|
|
302
|
-
else {
|
|
303
|
-
select += ', ' + e.$dbNameOf(x);
|
|
304
|
-
if (x.options.sqlExpression)
|
|
305
|
-
select += ' as ' + x.key;
|
|
306
|
-
if (groupBy == '')
|
|
307
|
-
groupBy = ' group by ';
|
|
308
|
-
else
|
|
309
|
-
groupBy += ', ';
|
|
310
|
-
groupBy += e.$dbNameOf(x);
|
|
311
|
-
}
|
|
312
|
-
processResultRow.push((sqlResult, theResult) => {
|
|
313
|
-
theResult[x.key] = x.valueConverter.fromDb(sqlResult);
|
|
314
|
-
});
|
|
315
|
-
}
|
|
316
|
-
if (options?.sum)
|
|
317
|
-
for (const x of options?.sum) {
|
|
318
|
-
if (x.isServerExpression) {
|
|
319
|
-
}
|
|
320
|
-
else {
|
|
321
|
-
select += ', sum(' + e.$dbNameOf(x) + ') as ' + x.key + '_sum';
|
|
322
|
-
}
|
|
323
|
-
processResultRow.push((sqlResult, theResult) => {
|
|
324
|
-
theResult[x.key] = { ...theResult[x.key], sum: sqlResult };
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
if (options?.average)
|
|
328
|
-
for (const x of options?.average) {
|
|
329
|
-
if (x.isServerExpression) {
|
|
330
|
-
}
|
|
331
|
-
else {
|
|
332
|
-
select += ', avg(' + e.$dbNameOf(x) + ') as ' + x.key + '_average';
|
|
333
|
-
}
|
|
334
|
-
processResultRow.push((sqlResult, theResult) => {
|
|
335
|
-
theResult[x.key] = { ...theResult[x.key], average: sqlResult };
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
select += '\n from ' + e.$entityName;
|
|
339
|
-
let r = this.sql.createCommand();
|
|
340
|
-
if (options?.where) {
|
|
341
|
-
let where = new FilterConsumerBridgeToSqlRequest(r, e);
|
|
342
|
-
options?.where.__applyToConsumer(where);
|
|
343
|
-
select += await where.resolveWhere();
|
|
344
|
-
}
|
|
345
|
-
if (groupBy)
|
|
346
|
-
select += groupBy;
|
|
347
|
-
let orderBy = '';
|
|
348
|
-
if (options?.orderBy) {
|
|
349
|
-
for (const x of options?.orderBy) {
|
|
350
|
-
if (orderBy == '')
|
|
351
|
-
orderBy = ' order by ';
|
|
352
|
-
else
|
|
353
|
-
orderBy += ', ';
|
|
354
|
-
if (!x.field && x.operation == 'count') {
|
|
355
|
-
orderBy += x.operation + '(*)';
|
|
356
|
-
}
|
|
357
|
-
else {
|
|
358
|
-
let field = await e.$dbNameOf(x.field);
|
|
359
|
-
switch (x.operation) {
|
|
360
|
-
case 'sum':
|
|
361
|
-
field = 'sum(' + field + ')';
|
|
362
|
-
break;
|
|
363
|
-
case 'average':
|
|
364
|
-
field = 'avg(' + field + ')';
|
|
365
|
-
break;
|
|
366
|
-
}
|
|
367
|
-
orderBy += field;
|
|
368
|
-
}
|
|
369
|
-
if (x.isDescending)
|
|
370
|
-
orderBy += ' desc';
|
|
371
|
-
if (this.sql._getSourceSql().orderByNullsFirst) {
|
|
372
|
-
if (x.isDescending)
|
|
373
|
-
select += ' nulls last';
|
|
374
|
-
else
|
|
375
|
-
select += ' nulls first';
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
if (orderBy)
|
|
379
|
-
select += orderBy;
|
|
380
|
-
}
|
|
381
|
-
if (options?.limit) {
|
|
382
|
-
let page = 1;
|
|
383
|
-
if (options.page)
|
|
384
|
-
page = options.page;
|
|
385
|
-
if (page < 1)
|
|
386
|
-
page = 1;
|
|
387
|
-
select +=
|
|
388
|
-
' ' +
|
|
389
|
-
this.strategy.getLimitSqlSyntax(options.limit, (page - 1) * options.limit);
|
|
390
|
-
}
|
|
391
|
-
const result = await r.execute(select);
|
|
392
|
-
return result.rows.map((sql) => {
|
|
393
|
-
let theResult = {};
|
|
394
|
-
processResultRow.forEach((x, i) => x(sql[result.getColumnKeyInResultForIndexInSelect(i)], theResult));
|
|
395
|
-
return theResult;
|
|
396
|
-
});
|
|
291
|
+
return await aggregateImpl(options, await this.init(), this.sql.createCommand(), this.sql._getSourceSql().orderByNullsFirst, this.sql._getSourceSql().getLimitSqlSyntax);
|
|
397
292
|
}
|
|
398
293
|
async find(options) {
|
|
399
294
|
let e = await this.init();
|
|
@@ -646,3 +541,107 @@ export function getRowAfterUpdate(meta, dataProvider, data, id, operation) {
|
|
|
646
541
|
return r[0];
|
|
647
542
|
});
|
|
648
543
|
}
|
|
544
|
+
export async function aggregateImpl(options, e, r, orderByNullFirst, limitSyntax) {
|
|
545
|
+
let select = 'select count(*) as count';
|
|
546
|
+
let groupBy = '';
|
|
547
|
+
const processResultRow = [];
|
|
548
|
+
processResultRow.push((sqlVal, theResult) => {
|
|
549
|
+
theResult[AggregateCountMember] = Number(sqlVal);
|
|
550
|
+
});
|
|
551
|
+
if (options?.groupBy)
|
|
552
|
+
for (const x of options?.groupBy) {
|
|
553
|
+
if (x.isServerExpression) {
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
select += ', ' + e.$dbNameOf(x);
|
|
557
|
+
if (x.options.sqlExpression)
|
|
558
|
+
select += ' as ' + x.key;
|
|
559
|
+
if (groupBy == '')
|
|
560
|
+
groupBy = ' group by ';
|
|
561
|
+
else
|
|
562
|
+
groupBy += ', ';
|
|
563
|
+
groupBy += e.$dbNameOf(x);
|
|
564
|
+
}
|
|
565
|
+
processResultRow.push((sqlResult, theResult) => {
|
|
566
|
+
theResult[x.key] = x.valueConverter.fromDb(sqlResult);
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
if (options?.sum)
|
|
570
|
+
for (const x of options?.sum) {
|
|
571
|
+
if (x.isServerExpression) {
|
|
572
|
+
}
|
|
573
|
+
else {
|
|
574
|
+
select += ', sum(' + e.$dbNameOf(x) + ') as ' + x.key + '_sum';
|
|
575
|
+
}
|
|
576
|
+
processResultRow.push((sqlResult, theResult) => {
|
|
577
|
+
theResult[x.key] = { ...theResult[x.key], sum: sqlResult };
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
if (options?.avg)
|
|
581
|
+
for (const x of options?.avg) {
|
|
582
|
+
if (x.isServerExpression) {
|
|
583
|
+
}
|
|
584
|
+
else {
|
|
585
|
+
select += ', avg(' + e.$dbNameOf(x) + ') as ' + x.key + '_avg';
|
|
586
|
+
}
|
|
587
|
+
processResultRow.push((sqlResult, theResult) => {
|
|
588
|
+
theResult[x.key] = { ...theResult[x.key], avg: sqlResult };
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
select += '\n from ' + e.$entityName;
|
|
592
|
+
if (options?.where) {
|
|
593
|
+
let where = new FilterConsumerBridgeToSqlRequest(r, e);
|
|
594
|
+
options?.where.__applyToConsumer(where);
|
|
595
|
+
select += await where.resolveWhere();
|
|
596
|
+
}
|
|
597
|
+
if (groupBy)
|
|
598
|
+
select += groupBy;
|
|
599
|
+
let orderBy = '';
|
|
600
|
+
if (options?.orderBy) {
|
|
601
|
+
for (const x of options?.orderBy) {
|
|
602
|
+
if (orderBy == '')
|
|
603
|
+
orderBy = ' order by ';
|
|
604
|
+
else
|
|
605
|
+
orderBy += ', ';
|
|
606
|
+
if (!x.field && x.operation == 'count') {
|
|
607
|
+
orderBy += x.operation + '(*)';
|
|
608
|
+
}
|
|
609
|
+
else {
|
|
610
|
+
let field = await e.$dbNameOf(x.field);
|
|
611
|
+
switch (x.operation) {
|
|
612
|
+
case 'sum':
|
|
613
|
+
field = 'sum(' + field + ')';
|
|
614
|
+
break;
|
|
615
|
+
case 'avg':
|
|
616
|
+
field = 'avg(' + field + ')';
|
|
617
|
+
break;
|
|
618
|
+
}
|
|
619
|
+
orderBy += field;
|
|
620
|
+
}
|
|
621
|
+
if (x.isDescending)
|
|
622
|
+
orderBy += ' desc';
|
|
623
|
+
if (orderByNullFirst) {
|
|
624
|
+
if (x.isDescending)
|
|
625
|
+
select += ' nulls last';
|
|
626
|
+
else
|
|
627
|
+
select += ' nulls first';
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
if (orderBy)
|
|
631
|
+
select += orderBy;
|
|
632
|
+
}
|
|
633
|
+
if (options?.limit) {
|
|
634
|
+
let page = 1;
|
|
635
|
+
if (options.page)
|
|
636
|
+
page = options.page;
|
|
637
|
+
if (page < 1)
|
|
638
|
+
page = 1;
|
|
639
|
+
select += ' ' + limitSyntax(options.limit, (page - 1) * options.limit);
|
|
640
|
+
}
|
|
641
|
+
const result = await r.execute(select);
|
|
642
|
+
return result.rows.map((sql) => {
|
|
643
|
+
let theResult = {};
|
|
644
|
+
processResultRow.forEach((x, i) => x(sql[result.getColumnKeyInResultForIndexInSelect(i)], theResult));
|
|
645
|
+
return theResult;
|
|
646
|
+
});
|
|
647
|
+
}
|
|
@@ -131,13 +131,24 @@ export class RepositoryImplementation {
|
|
|
131
131
|
let findOptions = await this._buildEntityDataProviderFindOptions({
|
|
132
132
|
...options,
|
|
133
133
|
});
|
|
134
|
+
const getField = (key) => {
|
|
135
|
+
const r = this.metadata.fields.find(key);
|
|
136
|
+
if (r === undefined)
|
|
137
|
+
throw Error(`key "${key}" not found in entity`);
|
|
138
|
+
return r;
|
|
139
|
+
};
|
|
140
|
+
const getFieldNotInGroupBy = (key) => {
|
|
141
|
+
if (options?.groupBy?.includes(key))
|
|
142
|
+
throw Error(`field "${key}" cannot be used both in an aggregate and in group by`);
|
|
143
|
+
return getField(key);
|
|
144
|
+
};
|
|
134
145
|
var dpOptions = {
|
|
135
146
|
where: findOptions.where,
|
|
136
147
|
limit: findOptions.limit,
|
|
137
148
|
page: findOptions.page,
|
|
138
|
-
groupBy: options?.groupBy?.map(
|
|
139
|
-
sum: options?.sum?.map(
|
|
140
|
-
|
|
149
|
+
groupBy: options?.groupBy?.map(getField),
|
|
150
|
+
sum: options?.sum?.map(getFieldNotInGroupBy),
|
|
151
|
+
avg: options?.avg?.map(getFieldNotInGroupBy),
|
|
141
152
|
};
|
|
142
153
|
if (options?.orderBy) {
|
|
143
154
|
dpOptions.orderBy = [];
|
|
@@ -147,9 +158,7 @@ export class RepositoryImplementation {
|
|
|
147
158
|
if (element)
|
|
148
159
|
if (typeof element === 'string') {
|
|
149
160
|
dpOptions.orderBy.push({
|
|
150
|
-
field: key === '$count'
|
|
151
|
-
? undefined
|
|
152
|
-
: this.metadata.fields.find(key),
|
|
161
|
+
field: key === '$count' ? undefined : getField(key),
|
|
153
162
|
isDescending: element === 'desc',
|
|
154
163
|
operation: key === '$count' ? 'count' : undefined,
|
|
155
164
|
});
|
|
@@ -7,8 +7,6 @@ export const flags = {
|
|
|
7
7
|
//p1 - add not as an overload to not equal
|
|
8
8
|
/*p1 - min, max, avg, sum, countDistinct - noam come up with an api
|
|
9
9
|
p1 - handle relations
|
|
10
|
-
p1 - mongodb
|
|
11
|
-
p1 - knex
|
|
12
10
|
*/
|
|
13
11
|
/*p1 - add id and use uuid by default, but allow changes with Fields.id.defaultIdProvider NO but defaultProvider yes???
|
|
14
12
|
//p1 - replace uuid with crypto.randomUUID and allow custom fallback NO
|
package/package.json
CHANGED
package/remult-knex/index.js
CHANGED
|
@@ -112,7 +112,7 @@ var KnexDataProvider = /** @class */ (function () {
|
|
|
112
112
|
finally { if (e_2) throw e_2.error; }
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
-
return new KnexEntityDataProvider(entity, this.knex, this.wrapIdentifier);
|
|
115
|
+
return new KnexEntityDataProvider(entity, this.knex, this.wrapIdentifier, this);
|
|
116
116
|
};
|
|
117
117
|
KnexDataProvider.prototype.transaction = function (action) {
|
|
118
118
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
@@ -196,13 +196,27 @@ var KnexDataProvider = /** @class */ (function () {
|
|
|
196
196
|
}());
|
|
197
197
|
exports.KnexDataProvider = KnexDataProvider;
|
|
198
198
|
var KnexEntityDataProvider = /** @class */ (function () {
|
|
199
|
-
function KnexEntityDataProvider(entity, knex, rawSqlWrapIdentifier) {
|
|
199
|
+
function KnexEntityDataProvider(entity, knex, rawSqlWrapIdentifier, dp) {
|
|
200
200
|
this.entity = entity;
|
|
201
201
|
this.knex = knex;
|
|
202
202
|
this.rawSqlWrapIdentifier = rawSqlWrapIdentifier;
|
|
203
|
+
this.dp = dp;
|
|
203
204
|
}
|
|
204
205
|
KnexEntityDataProvider.prototype.aggregate = function (options) {
|
|
205
|
-
|
|
206
|
+
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
207
|
+
var _a, _b;
|
|
208
|
+
return tslib_1.__generator(this, function (_c) {
|
|
209
|
+
switch (_c.label) {
|
|
210
|
+
case 0:
|
|
211
|
+
_a = sql_database_js_1.aggregateImpl;
|
|
212
|
+
_b = [options];
|
|
213
|
+
return [4 /*yield*/, this.init()];
|
|
214
|
+
case 1: return [2 /*return*/, _a.apply(void 0, _b.concat([_c.sent(), this.dp.createCommand(),
|
|
215
|
+
false,
|
|
216
|
+
function (limit, offset) { return ' limit ' + limit + ' offset ' + offset; }]))];
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
});
|
|
206
220
|
};
|
|
207
221
|
KnexEntityDataProvider.prototype.count = function (where) {
|
|
208
222
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|