pqb 0.3.2 → 0.3.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.
- package/dist/index.d.ts +1239 -1342
- package/dist/index.esm.js +482 -432
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +484 -434
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/columnSchema/columnType.test.ts +2 -1
- package/src/columnSchema/columnsSchema.ts +20 -60
- package/src/db.test.ts +1 -1
- package/src/db.ts +27 -20
- package/src/query.ts +36 -32
- package/src/queryDataUtils.ts +0 -7
- package/src/queryMethods/aggregate.ts +2 -3
- package/src/queryMethods/clear.ts +3 -4
- package/src/queryMethods/delete.ts +3 -3
- package/src/queryMethods/from.test.ts +2 -3
- package/src/queryMethods/get.ts +0 -1
- package/src/queryMethods/index.ts +1 -0
- package/src/queryMethods/insert.ts +14 -13
- package/src/queryMethods/json.ts +7 -3
- package/src/queryMethods/merge.test.ts +471 -0
- package/src/queryMethods/merge.ts +67 -0
- package/src/queryMethods/queryMethods.test.ts +14 -59
- package/src/queryMethods/queryMethods.ts +18 -33
- package/src/queryMethods/select.test.ts +4 -0
- package/src/queryMethods/select.ts +4 -2
- package/src/queryMethods/then.ts +3 -3
- package/src/queryMethods/update.ts +21 -14
- package/src/sql/fromAndAs.ts +2 -3
- package/src/sql/select.ts +1 -2
- package/src/sql/toSql.ts +4 -3
- package/src/sql/types.ts +7 -3
- package/src/sql/window.ts +1 -1
- package/src/sql/with.ts +25 -20
- package/src/utils.test.ts +0 -18
- package/src/utils.ts +0 -40
- package/src/columnSchema/columnsSchema.test.ts +0 -32
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { raw } from '../common';
|
|
2
|
-
import { SelectQueryData } from '../sql';
|
|
3
2
|
import {
|
|
4
3
|
expectQueryNotMutated,
|
|
5
4
|
adapter,
|
|
6
5
|
User,
|
|
7
6
|
Profile,
|
|
8
|
-
AssertEqual,
|
|
9
7
|
useTestDatabase,
|
|
10
8
|
db,
|
|
11
9
|
expectSql,
|
|
12
10
|
userData,
|
|
13
11
|
now,
|
|
14
12
|
assertType,
|
|
13
|
+
UserRecord,
|
|
15
14
|
} from '../test-utils';
|
|
16
15
|
import { NumberColumn } from '../columnSchema';
|
|
17
16
|
import { NotFoundError } from '../errors';
|
|
@@ -26,8 +25,7 @@ describe('queryMethods', () => {
|
|
|
26
25
|
expect(cloned.table).toBe(User.table);
|
|
27
26
|
expect(cloned.shape).toBe(User.shape);
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
expect(eq).toBe(true);
|
|
28
|
+
assertType<typeof User, typeof cloned>();
|
|
31
29
|
});
|
|
32
30
|
});
|
|
33
31
|
|
|
@@ -36,19 +34,11 @@ describe('queryMethods', () => {
|
|
|
36
34
|
const sql = User.toSql();
|
|
37
35
|
expectSql(sql, `SELECT * FROM "user"`);
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
true;
|
|
41
|
-
expect(eq).toBe(true);
|
|
37
|
+
assertType<typeof sql, { text: string; values: unknown[] }>();
|
|
42
38
|
});
|
|
43
39
|
});
|
|
44
40
|
|
|
45
41
|
describe('.all', () => {
|
|
46
|
-
it('should remove `take` from query if it is set', () => {
|
|
47
|
-
const q = User.take();
|
|
48
|
-
expect((q.query as SelectQueryData)?.take).toBe(true);
|
|
49
|
-
expect((q.all().query as SelectQueryData)?.take).toBe(undefined);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
42
|
it('should produce correct sql', () => {
|
|
53
43
|
expectSql(User.all().toSql(), `SELECT * FROM "user"`);
|
|
54
44
|
});
|
|
@@ -67,8 +57,7 @@ describe('queryMethods', () => {
|
|
|
67
57
|
.then((res) => res.rows[0]);
|
|
68
58
|
|
|
69
59
|
const user = await q.take();
|
|
70
|
-
|
|
71
|
-
expect(eq).toBe(true);
|
|
60
|
+
assertType<typeof user, UserRecord>();
|
|
72
61
|
|
|
73
62
|
expect(user).toEqual({
|
|
74
63
|
...expected,
|
|
@@ -95,8 +84,7 @@ describe('queryMethods', () => {
|
|
|
95
84
|
.then((res) => res.rows[0]);
|
|
96
85
|
|
|
97
86
|
const user = await q.takeOptional();
|
|
98
|
-
|
|
99
|
-
expect(eq).toBe(true);
|
|
87
|
+
assertType<typeof user, UserRecord | undefined>();
|
|
100
88
|
|
|
101
89
|
expect(user).toEqual({
|
|
102
90
|
...expected,
|
|
@@ -107,8 +95,7 @@ describe('queryMethods', () => {
|
|
|
107
95
|
|
|
108
96
|
it('should return undefined if not found', async () => {
|
|
109
97
|
const user = await User.takeOptional();
|
|
110
|
-
|
|
111
|
-
expect(eq).toBe(true);
|
|
98
|
+
assertType<typeof user, UserRecord | undefined>();
|
|
112
99
|
|
|
113
100
|
expect(user).toBe(undefined);
|
|
114
101
|
});
|
|
@@ -122,12 +109,6 @@ describe('queryMethods', () => {
|
|
|
122
109
|
const received = await User.rows();
|
|
123
110
|
expect(received).toEqual(expected);
|
|
124
111
|
});
|
|
125
|
-
|
|
126
|
-
it('removes `take` from query data', () => {
|
|
127
|
-
expect((User.take().rows().query as SelectQueryData)?.take).toBe(
|
|
128
|
-
undefined,
|
|
129
|
-
);
|
|
130
|
-
});
|
|
131
112
|
});
|
|
132
113
|
|
|
133
114
|
describe('pluck', () => {
|
|
@@ -141,16 +122,14 @@ describe('queryMethods', () => {
|
|
|
141
122
|
const result = await User.pluck('createdAt');
|
|
142
123
|
expect(result).toEqual([now, now, now]);
|
|
143
124
|
|
|
144
|
-
|
|
145
|
-
expect(eq).toBe(true);
|
|
125
|
+
assertType<typeof result, Date[]>();
|
|
146
126
|
});
|
|
147
127
|
|
|
148
128
|
it('should support raw expression', async () => {
|
|
149
129
|
const result = await User.pluck(raw<NumberColumn>('123'));
|
|
150
130
|
expect(result).toEqual([123, 123, 123]);
|
|
151
131
|
|
|
152
|
-
|
|
153
|
-
expect(eq).toBe(true);
|
|
132
|
+
assertType<typeof result, number[]>();
|
|
154
133
|
});
|
|
155
134
|
});
|
|
156
135
|
|
|
@@ -159,12 +138,6 @@ describe('queryMethods', () => {
|
|
|
159
138
|
const received = await User.exec();
|
|
160
139
|
expect(received).toEqual(undefined);
|
|
161
140
|
});
|
|
162
|
-
|
|
163
|
-
it('removes `take` from query data', () => {
|
|
164
|
-
expect((User.take().exec().query as SelectQueryData)?.take).toBe(
|
|
165
|
-
undefined,
|
|
166
|
-
);
|
|
167
|
-
});
|
|
168
141
|
});
|
|
169
142
|
|
|
170
143
|
describe('distinct', () => {
|
|
@@ -247,8 +220,7 @@ describe('queryMethods', () => {
|
|
|
247
220
|
const q = User.all();
|
|
248
221
|
const query = q.find(1);
|
|
249
222
|
|
|
250
|
-
|
|
251
|
-
expect(eq).toBe(true);
|
|
223
|
+
assertType<Awaited<typeof query>, UserRecord>();
|
|
252
224
|
|
|
253
225
|
expectSql(
|
|
254
226
|
query.toSql(),
|
|
@@ -266,8 +238,7 @@ describe('queryMethods', () => {
|
|
|
266
238
|
const q = User.all();
|
|
267
239
|
const query = q.find(raw('$1 + $2', 1, 2));
|
|
268
240
|
|
|
269
|
-
|
|
270
|
-
expect(eq).toBe(true);
|
|
241
|
+
assertType<Awaited<typeof query>, UserRecord>();
|
|
271
242
|
|
|
272
243
|
expectSql(
|
|
273
244
|
query.toSql(),
|
|
@@ -287,11 +258,7 @@ describe('queryMethods', () => {
|
|
|
287
258
|
const q = User.all();
|
|
288
259
|
const query = q.findOptional(1);
|
|
289
260
|
|
|
290
|
-
|
|
291
|
-
Awaited<typeof query>,
|
|
292
|
-
typeof User.type | undefined
|
|
293
|
-
> = true;
|
|
294
|
-
expect(eq).toBe(true);
|
|
261
|
+
assertType<Awaited<typeof query>, UserRecord | undefined>();
|
|
295
262
|
|
|
296
263
|
expectSql(
|
|
297
264
|
query.toSql(),
|
|
@@ -309,11 +276,7 @@ describe('queryMethods', () => {
|
|
|
309
276
|
const q = User.all();
|
|
310
277
|
const query = q.findOptional(raw('$1 + $2', 1, 2));
|
|
311
278
|
|
|
312
|
-
|
|
313
|
-
Awaited<typeof query>,
|
|
314
|
-
typeof User.type | undefined
|
|
315
|
-
> = true;
|
|
316
|
-
expect(eq).toBe(true);
|
|
279
|
+
assertType<Awaited<typeof query>, UserRecord | undefined>();
|
|
317
280
|
|
|
318
281
|
expectSql(
|
|
319
282
|
query.toSql(),
|
|
@@ -355,11 +318,7 @@ describe('queryMethods', () => {
|
|
|
355
318
|
const q = User.all();
|
|
356
319
|
const query = q.findByOptional({ name: 's' });
|
|
357
320
|
|
|
358
|
-
|
|
359
|
-
Awaited<typeof query>,
|
|
360
|
-
typeof User.type | undefined
|
|
361
|
-
> = true;
|
|
362
|
-
expect(eq).toBe(true);
|
|
321
|
+
assertType<Awaited<typeof query>, UserRecord | undefined>();
|
|
363
322
|
|
|
364
323
|
expectSql(
|
|
365
324
|
query.toSql(),
|
|
@@ -373,11 +332,7 @@ describe('queryMethods', () => {
|
|
|
373
332
|
const q = User.all();
|
|
374
333
|
const query = q.findByOptional({ name: raw(`'string'`) });
|
|
375
334
|
|
|
376
|
-
|
|
377
|
-
Awaited<typeof query>,
|
|
378
|
-
typeof User.type | undefined
|
|
379
|
-
> = true;
|
|
380
|
-
expect(eq).toBe(true);
|
|
335
|
+
assertType<Awaited<typeof query>, UserRecord | undefined>();
|
|
381
336
|
|
|
382
337
|
expectSql(
|
|
383
338
|
query.toSql(),
|
|
@@ -13,12 +13,7 @@ import {
|
|
|
13
13
|
SetQueryTableAlias,
|
|
14
14
|
SetQueryWindows,
|
|
15
15
|
} from '../query';
|
|
16
|
-
import {
|
|
17
|
-
applyMixins,
|
|
18
|
-
getClonedQueryData,
|
|
19
|
-
GetTypesOrRaw,
|
|
20
|
-
PropertyKeyUnionToArray,
|
|
21
|
-
} from '../utils';
|
|
16
|
+
import { applyMixins, EmptyObject, getClonedQueryData } from '../utils';
|
|
22
17
|
import {
|
|
23
18
|
SelectItem,
|
|
24
19
|
SelectQueryData,
|
|
@@ -28,11 +23,7 @@ import {
|
|
|
28
23
|
ToSqlOptions,
|
|
29
24
|
TruncateQueryData,
|
|
30
25
|
} from '../sql';
|
|
31
|
-
import {
|
|
32
|
-
pushQueryArray,
|
|
33
|
-
pushQueryValue,
|
|
34
|
-
removeFromQuery,
|
|
35
|
-
} from '../queryDataUtils';
|
|
26
|
+
import { pushQueryArray, pushQueryValue } from '../queryDataUtils';
|
|
36
27
|
import { Then } from './then';
|
|
37
28
|
import { BooleanColumn } from '../columnSchema';
|
|
38
29
|
import { Aggregate } from './aggregate';
|
|
@@ -56,6 +47,7 @@ import { QueryLog } from './log';
|
|
|
56
47
|
import { QueryCallbacks } from './callbacks';
|
|
57
48
|
import { QueryUpsert } from './upsert';
|
|
58
49
|
import { QueryGet } from './get';
|
|
50
|
+
import { MergeQueryMethods } from './merge';
|
|
59
51
|
|
|
60
52
|
export type WindowArg<T extends Query> = Record<
|
|
61
53
|
string,
|
|
@@ -69,7 +61,7 @@ export type WindowArgDeclaration<T extends Query = Query> = {
|
|
|
69
61
|
|
|
70
62
|
type WindowResult<T extends Query, W extends WindowArg<T>> = SetQueryWindows<
|
|
71
63
|
T,
|
|
72
|
-
|
|
64
|
+
Record<keyof W, true>
|
|
73
65
|
>;
|
|
74
66
|
|
|
75
67
|
export type OrderArg<T extends Query> =
|
|
@@ -103,10 +95,11 @@ export interface QueryMethods
|
|
|
103
95
|
QueryLog,
|
|
104
96
|
QueryCallbacks,
|
|
105
97
|
QueryUpsert,
|
|
106
|
-
QueryGet
|
|
98
|
+
QueryGet,
|
|
99
|
+
MergeQueryMethods {}
|
|
107
100
|
|
|
108
101
|
export class QueryMethods {
|
|
109
|
-
windows!:
|
|
102
|
+
windows!: EmptyObject;
|
|
110
103
|
__model!: Query;
|
|
111
104
|
|
|
112
105
|
all<T extends Query>(this: T): SetQueryReturnsAll<T> {
|
|
@@ -115,7 +108,6 @@ export class QueryMethods {
|
|
|
115
108
|
|
|
116
109
|
_all<T extends Query>(this: T): SetQueryReturnsAll<T> {
|
|
117
110
|
this.query.returnType = 'all';
|
|
118
|
-
removeFromQuery(this, 'take');
|
|
119
111
|
return this as unknown as SetQueryReturnsAll<T>;
|
|
120
112
|
}
|
|
121
113
|
|
|
@@ -125,7 +117,6 @@ export class QueryMethods {
|
|
|
125
117
|
|
|
126
118
|
_take<T extends Query>(this: T): SetQueryReturnsOne<T> {
|
|
127
119
|
this.query.returnType = 'oneOrThrow';
|
|
128
|
-
this.query.take = true;
|
|
129
120
|
return this as unknown as SetQueryReturnsOne<T>;
|
|
130
121
|
}
|
|
131
122
|
|
|
@@ -135,7 +126,6 @@ export class QueryMethods {
|
|
|
135
126
|
|
|
136
127
|
_takeOptional<T extends Query>(this: T): SetQueryReturnsOneOptional<T> {
|
|
137
128
|
this.query.returnType = 'one';
|
|
138
|
-
this.query.take = true;
|
|
139
129
|
return this as unknown as SetQueryReturnsOneOptional<T>;
|
|
140
130
|
}
|
|
141
131
|
|
|
@@ -145,7 +135,6 @@ export class QueryMethods {
|
|
|
145
135
|
|
|
146
136
|
_rows<T extends Query>(this: T): SetQueryReturnsRows<T> {
|
|
147
137
|
this.query.returnType = 'rows';
|
|
148
|
-
removeFromQuery(this, 'take');
|
|
149
138
|
return this as unknown as SetQueryReturnsRows<T>;
|
|
150
139
|
}
|
|
151
140
|
|
|
@@ -161,7 +150,6 @@ export class QueryMethods {
|
|
|
161
150
|
select: S,
|
|
162
151
|
): SetQueryReturnsPluck<T, S> {
|
|
163
152
|
this.query.returnType = 'pluck';
|
|
164
|
-
removeFromQuery(this, 'take');
|
|
165
153
|
(this.query as SelectQueryData).select = [select as SelectItem];
|
|
166
154
|
addParserForSelectItem(this, this.query.as || this.table, 'pluck', select);
|
|
167
155
|
return this as unknown as SetQueryReturnsPluck<T, S>;
|
|
@@ -173,7 +161,6 @@ export class QueryMethods {
|
|
|
173
161
|
|
|
174
162
|
_exec<T extends Query>(this: T): SetQueryReturnsVoid<T> {
|
|
175
163
|
this.query.returnType = 'void';
|
|
176
|
-
removeFromQuery(this, 'take');
|
|
177
164
|
return this as unknown as SetQueryReturnsVoid<T>;
|
|
178
165
|
}
|
|
179
166
|
|
|
@@ -197,35 +184,33 @@ export class QueryMethods {
|
|
|
197
184
|
|
|
198
185
|
find<T extends Query>(
|
|
199
186
|
this: T,
|
|
200
|
-
|
|
187
|
+
value: T['shape'][T['singlePrimaryKey']]['type'] | RawExpression,
|
|
201
188
|
): SetQueryReturnsOne<WhereResult<T>> {
|
|
202
|
-
return this.clone()._find(
|
|
189
|
+
return this.clone()._find(value);
|
|
203
190
|
}
|
|
204
191
|
|
|
205
192
|
_find<T extends Query>(
|
|
206
193
|
this: T,
|
|
207
|
-
|
|
194
|
+
value: T['shape'][T['singlePrimaryKey']]['type'] | RawExpression,
|
|
208
195
|
): SetQueryReturnsOne<WhereResult<T>> {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
});
|
|
213
|
-
return this._where(conditions as WhereArg<T>)._take();
|
|
196
|
+
return this._where({
|
|
197
|
+
[this.singlePrimaryKey]: value,
|
|
198
|
+
} as WhereArg<T>)._take();
|
|
214
199
|
}
|
|
215
200
|
|
|
216
201
|
findOptional<T extends Query>(
|
|
217
202
|
this: T,
|
|
218
|
-
|
|
203
|
+
value: T['shape'][T['singlePrimaryKey']]['type'] | RawExpression,
|
|
219
204
|
): SetQueryReturnsOneOptional<WhereResult<T>> {
|
|
220
|
-
return this.clone()._findOptional(
|
|
205
|
+
return this.clone()._findOptional(value);
|
|
221
206
|
}
|
|
222
207
|
|
|
223
208
|
_findOptional<T extends Query>(
|
|
224
209
|
this: T,
|
|
225
|
-
|
|
210
|
+
value: T['shape'][T['singlePrimaryKey']]['type'] | RawExpression,
|
|
226
211
|
): SetQueryReturnsOneOptional<WhereResult<T>> {
|
|
227
212
|
return this._find(
|
|
228
|
-
|
|
213
|
+
value,
|
|
229
214
|
).takeOptional() as unknown as SetQueryReturnsOneOptional<WhereResult<T>>;
|
|
230
215
|
}
|
|
231
216
|
|
|
@@ -362,7 +347,6 @@ export class QueryMethods {
|
|
|
362
347
|
const q = this._getOptional(raw<BooleanColumn>('true'));
|
|
363
348
|
q.query.notFoundDefault = false;
|
|
364
349
|
q.query.coalesceValue = false;
|
|
365
|
-
delete q.query.take;
|
|
366
350
|
return q as unknown as SetQueryReturnsValue<T, BooleanColumn>;
|
|
367
351
|
}
|
|
368
352
|
|
|
@@ -412,4 +396,5 @@ applyMixins(QueryMethods, [
|
|
|
412
396
|
QueryCallbacks,
|
|
413
397
|
QueryUpsert,
|
|
414
398
|
QueryGet,
|
|
399
|
+
MergeQueryMethods,
|
|
415
400
|
]);
|
|
@@ -29,6 +29,10 @@ const insertUserAndProfile = async () => {
|
|
|
29
29
|
describe('selectMethods', () => {
|
|
30
30
|
useTestDatabase();
|
|
31
31
|
|
|
32
|
+
it('table should have all columns selected if select was not applied', () => {
|
|
33
|
+
assertType<Awaited<typeof User>, UserRecord[]>();
|
|
34
|
+
});
|
|
35
|
+
|
|
32
36
|
describe('select', () => {
|
|
33
37
|
it('should have no effect if no columns provided', () => {
|
|
34
38
|
const q = User.all();
|
|
@@ -4,7 +4,9 @@ import {
|
|
|
4
4
|
ColumnsParsers,
|
|
5
5
|
Query,
|
|
6
6
|
QueryBase,
|
|
7
|
+
QueryReturnsAll,
|
|
7
8
|
QuerySelectAll,
|
|
9
|
+
queryTypeWithLimitOne,
|
|
8
10
|
} from '../query';
|
|
9
11
|
import {
|
|
10
12
|
ArrayOfColumnsObjects,
|
|
@@ -75,7 +77,7 @@ type SelectResult<
|
|
|
75
77
|
|
|
76
78
|
type SelectSubQueryResult<
|
|
77
79
|
Arg extends Query & { [isRequiredRelationKey]?: boolean },
|
|
78
|
-
> = Arg['returnType'] extends
|
|
80
|
+
> = QueryReturnsAll<Arg['returnType']> extends true
|
|
79
81
|
? ArrayOfColumnsObjects<Arg['result']>
|
|
80
82
|
: Arg['returnType'] extends 'valueOrThrow'
|
|
81
83
|
? Arg['result']['value']
|
|
@@ -107,7 +109,7 @@ export const addParserForSelectItem = <T extends Query>(
|
|
|
107
109
|
const rel = arg(q);
|
|
108
110
|
const parsers = getQueryParsers(rel);
|
|
109
111
|
if (parsers) {
|
|
110
|
-
if (rel.query.
|
|
112
|
+
if (queryTypeWithLimitOne[rel.query.returnType]) {
|
|
111
113
|
addParserToQuery(q.query, key, (item) => parseRecord(parsers, item));
|
|
112
114
|
} else {
|
|
113
115
|
addParserToQuery(q.query, key, (items) =>
|
package/src/queryMethods/then.ts
CHANGED
|
@@ -49,7 +49,7 @@ export const handleResult: CommonQueryData['handleResult'] = async (
|
|
|
49
49
|
q,
|
|
50
50
|
result: QueryResult,
|
|
51
51
|
) => {
|
|
52
|
-
return parseResult(q, q.query.returnType, result);
|
|
52
|
+
return parseResult(q, q.query.returnType || 'all', result);
|
|
53
53
|
};
|
|
54
54
|
|
|
55
55
|
const then = async (
|
|
@@ -89,7 +89,7 @@ const then = async (
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
const queryResult = await q.query.adapter[
|
|
92
|
-
queryMethodByReturnType[q.query.returnType] as 'query'
|
|
92
|
+
queryMethodByReturnType[q.query.returnType || 'all'] as 'query'
|
|
93
93
|
](sql);
|
|
94
94
|
|
|
95
95
|
if (q.query.log) {
|
|
@@ -119,7 +119,7 @@ const then = async (
|
|
|
119
119
|
|
|
120
120
|
export const parseResult = (
|
|
121
121
|
q: Query,
|
|
122
|
-
returnType: QueryReturnType,
|
|
122
|
+
returnType: QueryReturnType | undefined = 'all',
|
|
123
123
|
result: QueryResult,
|
|
124
124
|
): unknown => {
|
|
125
125
|
switch (returnType) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Query, SetQueryReturnsRowCount } from '../query';
|
|
1
|
+
import { Query, QueryReturnsAll, SetQueryReturnsRowCount } from '../query';
|
|
2
2
|
import { pushQueryArray, pushQueryValue } from '../queryDataUtils';
|
|
3
3
|
import { isRaw, RawExpression, StringKey } from '../common';
|
|
4
4
|
import {
|
|
@@ -43,7 +43,7 @@ type UpdateBelongsToData<T extends Query, Rel extends BelongsToRelation> =
|
|
|
43
43
|
| {
|
|
44
44
|
create: InsertData<Rel['nestedCreateQuery']>;
|
|
45
45
|
}
|
|
46
|
-
| (T['returnType'] extends
|
|
46
|
+
| (QueryReturnsAll<T['returnType']> extends true
|
|
47
47
|
? never
|
|
48
48
|
: {
|
|
49
49
|
upsert: {
|
|
@@ -56,7 +56,7 @@ type UpdateHasOneData<T extends Query, Rel extends HasOneRelation> =
|
|
|
56
56
|
| { disconnect: boolean }
|
|
57
57
|
| { delete: boolean }
|
|
58
58
|
| { update: UpdateData<Rel['model']> }
|
|
59
|
-
| (T['returnType'] extends
|
|
59
|
+
| (QueryReturnsAll<T['returnType']> extends true
|
|
60
60
|
? never
|
|
61
61
|
:
|
|
62
62
|
| { set: WhereArg<Rel['model']> }
|
|
@@ -77,7 +77,7 @@ type UpdateHasManyData<T extends Query, Rel extends HasManyRelation> = {
|
|
|
77
77
|
where: MaybeArray<WhereArg<Rel['model']>>;
|
|
78
78
|
data: UpdateData<Rel['model']>;
|
|
79
79
|
};
|
|
80
|
-
} & (T['returnType'] extends
|
|
80
|
+
} & (QueryReturnsAll<T['returnType']> extends true
|
|
81
81
|
? EmptyObject
|
|
82
82
|
: {
|
|
83
83
|
set?: MaybeArray<WhereArg<Rel['model']>>;
|
|
@@ -107,9 +107,9 @@ type UpdateRawArgs<T extends Query, ForceAll extends boolean> = (
|
|
|
107
107
|
? [update: RawExpression]
|
|
108
108
|
: [update: RawExpression, forceAll: true];
|
|
109
109
|
|
|
110
|
-
type UpdateResult<T extends Query> = T['hasSelect'] extends
|
|
111
|
-
?
|
|
112
|
-
: T
|
|
110
|
+
type UpdateResult<T extends Query> = T['hasSelect'] extends true
|
|
111
|
+
? T
|
|
112
|
+
: SetQueryReturnsRowCount<T>;
|
|
113
113
|
|
|
114
114
|
type ChangeCountArg<T extends Query> =
|
|
115
115
|
| keyof T['shape']
|
|
@@ -179,7 +179,7 @@ export class Update {
|
|
|
179
179
|
const prependRelations: Record<string, Record<string, unknown>> = {};
|
|
180
180
|
const appendRelations: Record<string, Record<string, unknown>> = {};
|
|
181
181
|
|
|
182
|
-
const originalReturnType = query.returnType;
|
|
182
|
+
const originalReturnType = query.returnType || 'all';
|
|
183
183
|
|
|
184
184
|
for (const key in data) {
|
|
185
185
|
if (relations[key]) {
|
|
@@ -232,11 +232,13 @@ export class Update {
|
|
|
232
232
|
query.returnType = 'all';
|
|
233
233
|
|
|
234
234
|
if (state?.updateLater) {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
235
|
+
if (!query.select?.includes('*')) {
|
|
236
|
+
this.primaryKeys.forEach((key) => {
|
|
237
|
+
if (!query.select?.includes(key)) {
|
|
238
|
+
this._select(key as StringKey<keyof T['selectable']>);
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
}
|
|
240
242
|
}
|
|
241
243
|
|
|
242
244
|
const { handleResult } = query;
|
|
@@ -250,7 +252,7 @@ export class Update {
|
|
|
250
252
|
await Promise.all(state.updateLaterPromises as Promise<void>[]);
|
|
251
253
|
|
|
252
254
|
const t = this.__model.clone().transacting(q);
|
|
253
|
-
const keys = this.
|
|
255
|
+
const keys = this.primaryKeys;
|
|
254
256
|
(
|
|
255
257
|
t._whereIn as unknown as (
|
|
256
258
|
keys: string[],
|
|
@@ -287,6 +289,11 @@ export class Update {
|
|
|
287
289
|
appendRelationKeys.map((relationName) => {
|
|
288
290
|
return (q: Query, result: Record<string, unknown>[]) => {
|
|
289
291
|
const all = resultOfTypeAll || result;
|
|
292
|
+
|
|
293
|
+
if (q.query.returnType !== originalReturnType) {
|
|
294
|
+
q.query.returnType = originalReturnType;
|
|
295
|
+
}
|
|
296
|
+
|
|
290
297
|
return (
|
|
291
298
|
relations[relationName].nestedUpdate as HasOneNestedUpdate
|
|
292
299
|
)?.(q, all, appendRelations[relationName] as NestedUpdateOneItem);
|
package/src/sql/fromAndAs.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getRaw, isRaw } from '../common';
|
|
2
2
|
import { quoteSchemaAndTable } from './common';
|
|
3
3
|
import { QueryBase } from '../query';
|
|
4
|
-
import {
|
|
4
|
+
import { checkIfASimpleQuery, SelectQueryData } from './types';
|
|
5
5
|
import { ToSqlCtx } from './toSql';
|
|
6
6
|
|
|
7
7
|
export const pushFromAndAs = (
|
|
@@ -38,9 +38,8 @@ const getFrom = (
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
const q = query.from.query;
|
|
41
|
-
const keys = Object.keys(q) as (keyof SelectQueryData)[];
|
|
42
41
|
// if query contains more than just schema return (SELECT ...)
|
|
43
|
-
if (
|
|
42
|
+
if (!checkIfASimpleQuery(q)) {
|
|
44
43
|
const sql = query.from.toSql({ values });
|
|
45
44
|
return `(${sql.text})`;
|
|
46
45
|
}
|
package/src/sql/select.ts
CHANGED
|
@@ -142,7 +142,7 @@ const pushSubQuerySql = (
|
|
|
142
142
|
values: unknown[],
|
|
143
143
|
list: string[],
|
|
144
144
|
) => {
|
|
145
|
-
const { returnType } = query.query;
|
|
145
|
+
const { returnType = 'all' } = query.query;
|
|
146
146
|
switch (returnType) {
|
|
147
147
|
case 'all':
|
|
148
148
|
case 'one':
|
|
@@ -160,7 +160,6 @@ const pushSubQuerySql = (
|
|
|
160
160
|
select[0] = { selectAs: { c: first } } as SelectItem;
|
|
161
161
|
query = query._wrap(query.__model.clone()) as unknown as typeof query;
|
|
162
162
|
query._getOptional(raw<StringColumn>(`COALESCE(json_agg("c"), '[]')`));
|
|
163
|
-
delete query.query.take;
|
|
164
163
|
break;
|
|
165
164
|
}
|
|
166
165
|
case 'rows':
|
package/src/sql/toSql.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getRaw, isRaw } from '../common';
|
|
2
|
-
import { Query } from '../query';
|
|
2
|
+
import { Query, queryTypeWithLimitOne } from '../query';
|
|
3
3
|
import { addValue, q, qc } from './common';
|
|
4
4
|
import { JoinItem, QueryData, Sql } from './types';
|
|
5
5
|
import { pushDistinctSql } from './distinct';
|
|
@@ -156,8 +156,9 @@ const makeSql = (model: Query, { values = [] }: ToSqlOptions = {}): Sql => {
|
|
|
156
156
|
pushOrderBySql(ctx, quotedAs, query.order);
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
|
|
160
|
-
|
|
159
|
+
const limit = queryTypeWithLimitOne[query.returnType] ? 1 : query.limit;
|
|
160
|
+
if (limit) {
|
|
161
|
+
sql.push(`LIMIT ${addValue(values, limit)}`);
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
if (query.offset) {
|
package/src/sql/types.ts
CHANGED
|
@@ -21,8 +21,13 @@ export type Sql = {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
// used in `from` logic to decide if convert query to sql or just write table name
|
|
24
|
-
export const
|
|
25
|
-
'
|
|
24
|
+
export const checkIfASimpleQuery = (q: QueryData) => {
|
|
25
|
+
if (q.returnType && q.returnType !== 'all') return false;
|
|
26
|
+
const keys = Object.keys(q) as (keyof SelectQueryData)[];
|
|
27
|
+
return !keys.some((key) => queryKeysOfNotSimpleQuery.includes(key));
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const queryKeysOfNotSimpleQuery: (keyof SelectQueryData)[] = [
|
|
26
31
|
'with',
|
|
27
32
|
'as',
|
|
28
33
|
'from',
|
|
@@ -51,7 +56,6 @@ export type CommonQueryData = {
|
|
|
51
56
|
inTransaction?: boolean;
|
|
52
57
|
wrapInTransaction?: boolean;
|
|
53
58
|
throwOnNotFound?: boolean;
|
|
54
|
-
take?: boolean;
|
|
55
59
|
with?: WithItem[];
|
|
56
60
|
withShapes?: Record<string, ColumnsShape>;
|
|
57
61
|
schema?: string;
|
package/src/sql/window.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { expressionToSql, q } from './common';
|
|
|
5
5
|
import { orderByToSql } from './orderBy';
|
|
6
6
|
|
|
7
7
|
export const windowToSql = <T extends Query>(
|
|
8
|
-
window: T['windows']
|
|
8
|
+
window: keyof T['windows'] | WindowDeclaration | RawExpression,
|
|
9
9
|
values: unknown[],
|
|
10
10
|
quotedAs?: string,
|
|
11
11
|
) => {
|
package/src/sql/with.ts
CHANGED
|
@@ -7,26 +7,31 @@ export const pushWithSql = (
|
|
|
7
7
|
ctx: ToSqlCtx,
|
|
8
8
|
withData: Exclude<QueryData['with'], undefined>,
|
|
9
9
|
) => {
|
|
10
|
-
withData.
|
|
11
|
-
const [name, options, query] = withItem;
|
|
10
|
+
if (!withData.length) return;
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
12
|
+
ctx.sql.push(
|
|
13
|
+
'WITH',
|
|
14
|
+
withData
|
|
15
|
+
.map((withItem) => {
|
|
16
|
+
const [name, options, query] = withItem;
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
: ''
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
18
|
+
let inner: string;
|
|
19
|
+
if (isRaw(query)) {
|
|
20
|
+
inner = getRaw(query, ctx.values);
|
|
21
|
+
} else {
|
|
22
|
+
inner = query.toSql({ values: ctx.values }).text;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return `${options.recursive ? 'RECURSIVE ' : ''}${q(name)}${
|
|
26
|
+
options.columns ? `(${options.columns.map(q).join(', ')})` : ''
|
|
27
|
+
} AS ${
|
|
28
|
+
options.materialized
|
|
29
|
+
? 'MATERIALIZED '
|
|
30
|
+
: options.notMaterialized
|
|
31
|
+
? 'NOT MATERIALIZED '
|
|
32
|
+
: ''
|
|
33
|
+
}(${inner})`;
|
|
34
|
+
})
|
|
35
|
+
.join(', '),
|
|
36
|
+
);
|
|
32
37
|
};
|