pqb 0.4.6 → 0.4.8
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 +25 -11
- package/dist/index.esm.js +78 -40
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +79 -39
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/columnSchema/columnType.test.ts +220 -0
- package/src/columnSchema/columnType.ts +7 -0
- package/src/columnSchema/columnTypes.test.ts +55 -53
- package/src/columnSchema/dateTime.ts +11 -0
- package/src/columnSchema/timestamps.test.ts +3 -4
- package/src/columnSchema/timestamps.ts +1 -1
- package/src/columnsOperators.test.ts +18 -19
- package/src/columnsOperators.ts +1 -1
- package/src/common.ts +17 -30
- package/src/db.ts +23 -9
- package/src/errors.test.ts +2 -4
- package/src/index.ts +1 -1
- package/src/query.ts +7 -1
- package/src/queryMethods/aggregate.test.ts +9 -7
- package/src/queryMethods/create.test.ts +48 -5
- package/src/queryMethods/create.ts +28 -6
- package/src/queryMethods/for.test.ts +1 -2
- package/src/queryMethods/for.ts +1 -1
- package/src/queryMethods/from.test.ts +2 -3
- package/src/queryMethods/get.test.ts +5 -5
- package/src/queryMethods/having.test.ts +6 -5
- package/src/queryMethods/index.ts +1 -0
- package/src/queryMethods/json.ts +2 -2
- package/src/queryMethods/merge.test.ts +10 -4
- package/src/queryMethods/queryMethods.test.ts +10 -12
- package/src/queryMethods/queryMethods.ts +7 -4
- package/src/queryMethods/raw.test.ts +19 -0
- package/src/queryMethods/raw.ts +27 -0
- package/src/queryMethods/select.test.ts +4 -4
- package/src/queryMethods/then.test.ts +2 -4
- package/src/queryMethods/union.test.ts +11 -6
- package/src/queryMethods/update.test.ts +21 -3
- package/src/queryMethods/update.ts +11 -1
- package/src/queryMethods/where.test.ts +65 -56
- package/src/queryMethods/where.ts +1 -1
- package/src/queryMethods/with.test.ts +5 -6
- package/src/sql/common.ts +0 -1
- package/src/sql/fromAndAs.ts +1 -1
- package/src/sql/insert.ts +1 -1
- package/src/sql/join.ts +1 -1
- package/src/sql/orderBy.ts +1 -1
- package/src/sql/select.ts +1 -2
- package/src/sql/toSql.ts +1 -1
- package/src/sql/update.ts +1 -1
- package/src/sql/where.ts +1 -1
- package/src/sql/window.ts +3 -4
- package/src/sql/with.ts +1 -1
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
SetQueryReturnsOne,
|
|
9
9
|
} from '../query';
|
|
10
10
|
import { pushQueryArray } from '../queryDataUtils';
|
|
11
|
-
import { RawExpression } from '../common';
|
|
12
11
|
import {
|
|
13
12
|
BelongsToNestedInsert,
|
|
14
13
|
BelongsToRelation,
|
|
@@ -26,6 +25,9 @@ import { InsertQueryData, OnConflictItem, OnConflictMergeUpdate } from '../sql';
|
|
|
26
25
|
import { WhereArg } from './where';
|
|
27
26
|
import { parseResult, queryMethodByReturnType } from './then';
|
|
28
27
|
import { NotFoundError } from '../errors';
|
|
28
|
+
import { RawExpression } from '../common';
|
|
29
|
+
import { ColumnsShape } from '../columnSchema';
|
|
30
|
+
import { anyShape } from '../db';
|
|
29
31
|
|
|
30
32
|
export type CreateData<
|
|
31
33
|
T extends Query,
|
|
@@ -172,6 +174,8 @@ type CreateCtx = {
|
|
|
172
174
|
relations: Record<string, Relation>;
|
|
173
175
|
};
|
|
174
176
|
|
|
177
|
+
type Encoder = (input: unknown) => unknown;
|
|
178
|
+
|
|
175
179
|
const handleSelect = (q: Query) => {
|
|
176
180
|
const select = q.query.select?.[0];
|
|
177
181
|
const isCount =
|
|
@@ -191,7 +195,9 @@ const processCreateItem = (
|
|
|
191
195
|
rowIndex: number,
|
|
192
196
|
ctx: CreateCtx,
|
|
193
197
|
columns: string[],
|
|
198
|
+
encoders: Record<string, Encoder>,
|
|
194
199
|
columnsMap: Record<string, number>,
|
|
200
|
+
shape: ColumnsShape,
|
|
195
201
|
) => {
|
|
196
202
|
Object.keys(item).forEach((key) => {
|
|
197
203
|
if (ctx.relations[key]) {
|
|
@@ -222,8 +228,12 @@ const processCreateItem = (
|
|
|
222
228
|
item[key] as NestedInsertItem,
|
|
223
229
|
]);
|
|
224
230
|
}
|
|
225
|
-
} else if (
|
|
231
|
+
} else if (
|
|
232
|
+
columnsMap[key] === undefined &&
|
|
233
|
+
(shape[key] || shape === anyShape)
|
|
234
|
+
) {
|
|
226
235
|
columnsMap[key] = columns.length;
|
|
236
|
+
encoders[key] = shape[key]?.encodeFn as Encoder;
|
|
227
237
|
columns.push(key);
|
|
228
238
|
}
|
|
229
239
|
});
|
|
@@ -256,8 +266,19 @@ const getManyReturnType = (q: Query) => {
|
|
|
256
266
|
}
|
|
257
267
|
};
|
|
258
268
|
|
|
269
|
+
const mapColumnValues = (
|
|
270
|
+
columns: string[],
|
|
271
|
+
encoders: Record<string, Encoder>,
|
|
272
|
+
data: Record<string, unknown>,
|
|
273
|
+
) => {
|
|
274
|
+
return columns.map((key) =>
|
|
275
|
+
encoders[key] ? encoders[key](data[key]) : data[key],
|
|
276
|
+
);
|
|
277
|
+
};
|
|
278
|
+
|
|
259
279
|
const handleOneData = (q: Query, data: CreateData<Query>, ctx: CreateCtx) => {
|
|
260
280
|
const columns: string[] = [];
|
|
281
|
+
const encoders: Record<string, Encoder> = {};
|
|
261
282
|
const columnsMap: Record<string, number> = {};
|
|
262
283
|
const defaults = q.query.defaults;
|
|
263
284
|
|
|
@@ -265,9 +286,9 @@ const handleOneData = (q: Query, data: CreateData<Query>, ctx: CreateCtx) => {
|
|
|
265
286
|
data = { ...defaults, ...data };
|
|
266
287
|
}
|
|
267
288
|
|
|
268
|
-
processCreateItem(data, 0, ctx, columns, columnsMap);
|
|
289
|
+
processCreateItem(data, 0, ctx, columns, encoders, columnsMap, q.shape);
|
|
269
290
|
|
|
270
|
-
const values = [columns
|
|
291
|
+
const values = [mapColumnValues(columns, encoders, data)];
|
|
271
292
|
|
|
272
293
|
return { columns, values };
|
|
273
294
|
};
|
|
@@ -278,6 +299,7 @@ const handleManyData = (
|
|
|
278
299
|
ctx: CreateCtx,
|
|
279
300
|
) => {
|
|
280
301
|
const columns: string[] = [];
|
|
302
|
+
const encoders: Record<string, Encoder> = {};
|
|
281
303
|
const columnsMap: Record<string, number> = {};
|
|
282
304
|
const defaults = q.query.defaults;
|
|
283
305
|
|
|
@@ -286,13 +308,13 @@ const handleManyData = (
|
|
|
286
308
|
}
|
|
287
309
|
|
|
288
310
|
data.forEach((item, i) => {
|
|
289
|
-
processCreateItem(item, i, ctx, columns, columnsMap);
|
|
311
|
+
processCreateItem(item, i, ctx, columns, encoders, columnsMap, q.shape);
|
|
290
312
|
});
|
|
291
313
|
|
|
292
314
|
const values = Array(data.length);
|
|
293
315
|
|
|
294
316
|
data.forEach((item, i) => {
|
|
295
|
-
(values as unknown[][])[i] = columns
|
|
317
|
+
(values as unknown[][])[i] = mapColumnValues(columns, encoders, item);
|
|
296
318
|
});
|
|
297
319
|
|
|
298
320
|
return { columns, values };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { expectQueryNotMutated, expectSql, User } from '../test-utils';
|
|
2
|
-
import { raw } from '../common';
|
|
3
2
|
|
|
4
3
|
describe('for', () => {
|
|
5
4
|
describe.each`
|
|
@@ -30,7 +29,7 @@ describe('for', () => {
|
|
|
30
29
|
it('should accept raw sql', () => {
|
|
31
30
|
const q = User.all();
|
|
32
31
|
expectSql(
|
|
33
|
-
q[method as 'forUpdate'](raw('raw sql')).toSql(),
|
|
32
|
+
q[method as 'forUpdate'](User.raw('raw sql')).toSql(),
|
|
34
33
|
`SELECT * FROM "user" FOR ${sql} OF raw sql`,
|
|
35
34
|
);
|
|
36
35
|
expectQueryNotMutated(q);
|
package/src/queryMethods/for.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Query } from '../query';
|
|
2
|
-
import { RawExpression } from '../common';
|
|
3
2
|
import { SelectQueryData } from '../sql';
|
|
3
|
+
import { RawExpression } from '../common';
|
|
4
4
|
|
|
5
5
|
type ForQueryBuilder<Q extends Query> = Q & {
|
|
6
6
|
noWait<T extends ForQueryBuilder<Q>>(this: T): T;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { expectQueryNotMutated, expectSql, User } from '../test-utils';
|
|
2
|
-
import { raw } from '../common';
|
|
1
|
+
import { db, expectQueryNotMutated, expectSql, User } from '../test-utils';
|
|
3
2
|
|
|
4
3
|
describe('from', () => {
|
|
5
4
|
it('should accept string parameter', () => {
|
|
@@ -20,7 +19,7 @@ describe('from', () => {
|
|
|
20
19
|
it('should accept raw parameter', () => {
|
|
21
20
|
const q = User.all();
|
|
22
21
|
expectSql(
|
|
23
|
-
q.as('t').from(raw('profile')).toSql(),
|
|
22
|
+
q.as('t').from(db.raw('profile')).toSql(),
|
|
24
23
|
`SELECT * FROM profile AS "t"`,
|
|
25
24
|
);
|
|
26
25
|
expectQueryNotMutated(q);
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { assertType, User, userData, useTestDatabase } from '../test-utils';
|
|
2
|
-
import { NumberColumn } from '../columnSchema';
|
|
1
|
+
import { assertType, db, User, userData, useTestDatabase } from '../test-utils';
|
|
3
2
|
import { NotFoundError } from '../errors';
|
|
4
|
-
import { raw } from '../common';
|
|
5
3
|
|
|
6
4
|
describe('get', () => {
|
|
7
5
|
useTestDatabase();
|
|
@@ -18,7 +16,9 @@ describe('get', () => {
|
|
|
18
16
|
});
|
|
19
17
|
|
|
20
18
|
it('should select raw and return a single value', async () => {
|
|
21
|
-
const received = await User.get(
|
|
19
|
+
const received = await User.get(
|
|
20
|
+
db.raw((t) => t.integer(), 'count(*)::int'),
|
|
21
|
+
);
|
|
22
22
|
|
|
23
23
|
assertType<typeof received, number>();
|
|
24
24
|
|
|
@@ -43,7 +43,7 @@ describe('get', () => {
|
|
|
43
43
|
|
|
44
44
|
it('should select raw and return a single value when exists', async () => {
|
|
45
45
|
const received = await User.getOptional(
|
|
46
|
-
raw
|
|
46
|
+
db.raw((t) => t.integer(), 'count(*)::int'),
|
|
47
47
|
);
|
|
48
48
|
|
|
49
49
|
assertType<typeof received, number | undefined>();
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { expectQueryNotMutated, expectSql, User } from '../test-utils';
|
|
2
|
-
import { raw } from '../common';
|
|
1
|
+
import { db, expectQueryNotMutated, expectSql, User } from '../test-utils';
|
|
3
2
|
|
|
4
3
|
describe('having', () => {
|
|
5
4
|
it('should support { count: value } object', () => {
|
|
@@ -196,12 +195,12 @@ describe('having', () => {
|
|
|
196
195
|
`;
|
|
197
196
|
|
|
198
197
|
expectSql(
|
|
199
|
-
q.having(raw('count(*) = 1'), raw('sum(id) = 2')).toSql(),
|
|
198
|
+
q.having(db.raw('count(*) = 1'), db.raw('sum(id) = 2')).toSql(),
|
|
200
199
|
expectedSql,
|
|
201
200
|
);
|
|
202
201
|
expectQueryNotMutated(q);
|
|
203
202
|
|
|
204
|
-
q._having(raw('count(*) = 1'), raw('sum(id) = 2'));
|
|
203
|
+
q._having(db.raw('count(*) = 1'), db.raw('sum(id) = 2'));
|
|
205
204
|
expectSql(q.toSql({ clearCache: true }), expectedSql);
|
|
206
205
|
});
|
|
207
206
|
|
|
@@ -235,7 +234,9 @@ describe('having', () => {
|
|
|
235
234
|
it('should accept raw sql', () => {
|
|
236
235
|
const q = User.all();
|
|
237
236
|
expectSql(
|
|
238
|
-
q
|
|
237
|
+
q
|
|
238
|
+
.havingOr(db.raw('count(*) = 1 + 2'), db.raw('count(*) = 2 + 3'))
|
|
239
|
+
.toSql(),
|
|
239
240
|
`
|
|
240
241
|
SELECT * FROM "user"
|
|
241
242
|
HAVING count(*) = 1 + 2 OR count(*) = 2 + 3
|
package/src/queryMethods/json.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
import { pushQueryValue } from '../queryDataUtils';
|
|
8
8
|
import { ColumnType, StringColumn } from '../columnSchema';
|
|
9
9
|
import { JsonItem } from '../sql';
|
|
10
|
-
import {
|
|
10
|
+
import { StringKey } from '../common';
|
|
11
11
|
|
|
12
12
|
type JsonColumnName<T extends Pick<Query, 'selectable'>> = StringKey<
|
|
13
13
|
{
|
|
@@ -55,7 +55,7 @@ export class Json {
|
|
|
55
55
|
): SetQueryReturnsValueOptional<T, StringColumn> {
|
|
56
56
|
const q = this._wrap(this.__model.clone()) as T;
|
|
57
57
|
q._getOptional(
|
|
58
|
-
raw<StringColumn>(
|
|
58
|
+
this.raw<Query, StringColumn>(
|
|
59
59
|
queryTypeWithLimitOne[this.query.returnType]
|
|
60
60
|
? `row_to_json("t".*)`
|
|
61
61
|
: `COALESCE(json_agg(row_to_json("t".*)), '[]')`,
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
assertType,
|
|
3
|
+
db,
|
|
4
|
+
expectSql,
|
|
5
|
+
Message,
|
|
6
|
+
Profile,
|
|
7
|
+
User,
|
|
8
|
+
} from '../test-utils';
|
|
2
9
|
import { QueryReturnType } from '../query';
|
|
3
10
|
import { IntegerColumn, TextColumn } from '../columnSchema';
|
|
4
11
|
import { getValueKey } from './get';
|
|
@@ -11,7 +18,6 @@ import {
|
|
|
11
18
|
TruncateQueryData,
|
|
12
19
|
UpdateQueryData,
|
|
13
20
|
} from '../sql';
|
|
14
|
-
import { raw } from '../common';
|
|
15
21
|
|
|
16
22
|
describe('merge queries', () => {
|
|
17
23
|
describe('select', () => {
|
|
@@ -350,8 +356,8 @@ describe('merge queries', () => {
|
|
|
350
356
|
s2.having = [{ b: { b: 2 } }];
|
|
351
357
|
s1.havingOr = [[{ a: { a: 1 } }]];
|
|
352
358
|
s2.havingOr = [[{ b: { b: 2 } }]];
|
|
353
|
-
s1.union = [{ arg: raw('a'), kind: 'UNION' }];
|
|
354
|
-
s2.union = [{ arg: raw('b'), kind: 'EXCEPT' }];
|
|
359
|
+
s1.union = [{ arg: db.raw('a'), kind: 'UNION' }];
|
|
360
|
+
s2.union = [{ arg: db.raw('b'), kind: 'EXCEPT' }];
|
|
355
361
|
s1.order = [{ id: 'ASC' }];
|
|
356
362
|
s2.order = [{ name: 'DESC' }];
|
|
357
363
|
s1.limit = 1;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { raw } from '../common';
|
|
2
1
|
import {
|
|
3
2
|
expectQueryNotMutated,
|
|
4
3
|
adapter,
|
|
@@ -12,7 +11,6 @@ import {
|
|
|
12
11
|
assertType,
|
|
13
12
|
UserRecord,
|
|
14
13
|
} from '../test-utils';
|
|
15
|
-
import { NumberColumn } from '../columnSchema';
|
|
16
14
|
import { NotFoundError } from '../errors';
|
|
17
15
|
|
|
18
16
|
describe('queryMethods', () => {
|
|
@@ -126,7 +124,7 @@ describe('queryMethods', () => {
|
|
|
126
124
|
});
|
|
127
125
|
|
|
128
126
|
it('should support raw expression', async () => {
|
|
129
|
-
const result = await User.pluck(raw
|
|
127
|
+
const result = await User.pluck(db.raw((t) => t.integer(), '123'));
|
|
130
128
|
expect(result).toEqual([123, 123, 123]);
|
|
131
129
|
|
|
132
130
|
assertType<typeof result, number[]>();
|
|
@@ -206,7 +204,7 @@ describe('queryMethods', () => {
|
|
|
206
204
|
it('should add distinct on raw sql', () => {
|
|
207
205
|
const q = User.all();
|
|
208
206
|
expectSql(
|
|
209
|
-
q.distinct(raw('"user".id')).toSql(),
|
|
207
|
+
q.distinct(db.raw('"user".id')).toSql(),
|
|
210
208
|
`
|
|
211
209
|
SELECT DISTINCT ON ("user".id) * FROM "user"
|
|
212
210
|
`,
|
|
@@ -236,7 +234,7 @@ describe('queryMethods', () => {
|
|
|
236
234
|
|
|
237
235
|
it('should accept raw sql', () => {
|
|
238
236
|
const q = User.all();
|
|
239
|
-
const query = q.find(raw('$1 + $2', 1, 2));
|
|
237
|
+
const query = q.find(db.raw('$1 + $2', 1, 2));
|
|
240
238
|
|
|
241
239
|
assertType<Awaited<typeof query>, UserRecord>();
|
|
242
240
|
|
|
@@ -274,7 +272,7 @@ describe('queryMethods', () => {
|
|
|
274
272
|
|
|
275
273
|
it('should accept raw sql', () => {
|
|
276
274
|
const q = User.all();
|
|
277
|
-
const query = q.findOptional(raw('$1 + $2', 1, 2));
|
|
275
|
+
const query = q.findOptional(db.raw('$1 + $2', 1, 2));
|
|
278
276
|
|
|
279
277
|
assertType<Awaited<typeof query>, UserRecord | undefined>();
|
|
280
278
|
|
|
@@ -305,7 +303,7 @@ describe('queryMethods', () => {
|
|
|
305
303
|
it('should accept raw', () => {
|
|
306
304
|
const q = User.all();
|
|
307
305
|
expectSql(
|
|
308
|
-
q.findBy({ name: raw(`'string'`) }).toSql(),
|
|
306
|
+
q.findBy({ name: db.raw(`'string'`) }).toSql(),
|
|
309
307
|
`SELECT * FROM "user" WHERE "user"."name" = 'string' LIMIT $1`,
|
|
310
308
|
[1],
|
|
311
309
|
);
|
|
@@ -330,7 +328,7 @@ describe('queryMethods', () => {
|
|
|
330
328
|
|
|
331
329
|
it('should accept raw', () => {
|
|
332
330
|
const q = User.all();
|
|
333
|
-
const query = q.findByOptional({ name: raw(`'string'`) });
|
|
331
|
+
const query = q.findByOptional({ name: db.raw(`'string'`) });
|
|
334
332
|
|
|
335
333
|
assertType<Awaited<typeof query>, UserRecord | undefined>();
|
|
336
334
|
|
|
@@ -431,10 +429,10 @@ describe('queryMethods', () => {
|
|
|
431
429
|
SELECT * FROM "user"
|
|
432
430
|
GROUP BY id, name
|
|
433
431
|
`;
|
|
434
|
-
expectSql(q.group(raw('id'), raw('name')).toSql(), expectedSql);
|
|
432
|
+
expectSql(q.group(db.raw('id'), db.raw('name')).toSql(), expectedSql);
|
|
435
433
|
expectQueryNotMutated(q);
|
|
436
434
|
|
|
437
|
-
q._group(raw('id'), raw('name'));
|
|
435
|
+
q._group(db.raw('id'), db.raw('name'));
|
|
438
436
|
expectSql(q.toSql({ clearCache: true }), expectedSql);
|
|
439
437
|
});
|
|
440
438
|
});
|
|
@@ -471,7 +469,7 @@ describe('queryMethods', () => {
|
|
|
471
469
|
const windowSql = 'PARTITION BY id ORDER BY name DESC';
|
|
472
470
|
expectSql(
|
|
473
471
|
q
|
|
474
|
-
.window({ w: raw(windowSql) })
|
|
472
|
+
.window({ w: db.raw(windowSql) })
|
|
475
473
|
.selectAvg('id', {
|
|
476
474
|
over: 'w',
|
|
477
475
|
})
|
|
@@ -527,7 +525,7 @@ describe('queryMethods', () => {
|
|
|
527
525
|
it('adds order with raw sql', () => {
|
|
528
526
|
const q = User.all();
|
|
529
527
|
expectSql(
|
|
530
|
-
q.order(raw('id ASC NULLS FIRST')).toSql(),
|
|
528
|
+
q.order(db.raw('id ASC NULLS FIRST')).toSql(),
|
|
531
529
|
`
|
|
532
530
|
SELECT * FROM "user"
|
|
533
531
|
ORDER BY id ASC NULLS FIRST
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Expression,
|
|
1
|
+
import { Expression, RawExpression } from '../common';
|
|
2
2
|
import {
|
|
3
3
|
Query,
|
|
4
4
|
QueryBase,
|
|
@@ -48,6 +48,7 @@ import { QueryCallbacks } from './callbacks';
|
|
|
48
48
|
import { QueryUpsert } from './upsert';
|
|
49
49
|
import { QueryGet } from './get';
|
|
50
50
|
import { MergeQueryMethods } from './merge';
|
|
51
|
+
import { RawMethods } from './raw';
|
|
51
52
|
|
|
52
53
|
export type WindowArg<T extends Query> = Record<
|
|
53
54
|
string,
|
|
@@ -96,7 +97,8 @@ export interface QueryMethods
|
|
|
96
97
|
QueryCallbacks,
|
|
97
98
|
QueryUpsert,
|
|
98
99
|
QueryGet,
|
|
99
|
-
MergeQueryMethods
|
|
100
|
+
MergeQueryMethods,
|
|
101
|
+
RawMethods {}
|
|
100
102
|
|
|
101
103
|
export class QueryMethods {
|
|
102
104
|
windows!: EmptyObject;
|
|
@@ -309,7 +311,7 @@ export class QueryMethods {
|
|
|
309
311
|
return query
|
|
310
312
|
.as(as ?? 't')
|
|
311
313
|
._from(
|
|
312
|
-
raw(`(${sql.text})`, ...sql.values),
|
|
314
|
+
this.raw(`(${sql.text})`, ...sql.values),
|
|
313
315
|
) as unknown as SetQueryTableAlias<Q, As>;
|
|
314
316
|
}
|
|
315
317
|
|
|
@@ -344,7 +346,7 @@ export class QueryMethods {
|
|
|
344
346
|
}
|
|
345
347
|
|
|
346
348
|
_exists<T extends Query>(this: T): SetQueryReturnsValue<T, BooleanColumn> {
|
|
347
|
-
const q = this._getOptional(raw<BooleanColumn>('true'));
|
|
349
|
+
const q = this._getOptional(this.raw<Query, BooleanColumn>('true'));
|
|
348
350
|
q.query.notFoundDefault = false;
|
|
349
351
|
q.query.coalesceValue = false;
|
|
350
352
|
return q as unknown as SetQueryReturnsValue<T, BooleanColumn>;
|
|
@@ -397,4 +399,5 @@ applyMixins(QueryMethods, [
|
|
|
397
399
|
QueryUpsert,
|
|
398
400
|
QueryGet,
|
|
399
401
|
MergeQueryMethods,
|
|
402
|
+
RawMethods,
|
|
400
403
|
]);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ColumnType } from '../columnSchema';
|
|
2
|
+
import { createDb } from '../db';
|
|
3
|
+
import { adapter } from '../test-utils';
|
|
4
|
+
|
|
5
|
+
describe('raw', () => {
|
|
6
|
+
it('should use column types in callback from a db instance', () => {
|
|
7
|
+
const type = {} as unknown as ColumnType;
|
|
8
|
+
const db = createDb({
|
|
9
|
+
adapter,
|
|
10
|
+
columnTypes: {
|
|
11
|
+
type: () => type,
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const value = db.raw((t) => t.type(), 'sql');
|
|
16
|
+
|
|
17
|
+
expect(value.__column).toBe(type);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ColumnType, ColumnTypesBase } from '../columnSchema';
|
|
2
|
+
import { Query } from '../query';
|
|
3
|
+
import { RawExpression } from '../common';
|
|
4
|
+
|
|
5
|
+
type RawArgs<CT extends ColumnTypesBase, C extends ColumnType> =
|
|
6
|
+
| [column: (types: CT) => C, sql: string, ...values: unknown[]]
|
|
7
|
+
| [sql: string, ...values: unknown[]];
|
|
8
|
+
|
|
9
|
+
export class RawMethods {
|
|
10
|
+
raw<T extends Query, C extends ColumnType>(
|
|
11
|
+
this: T,
|
|
12
|
+
...args: RawArgs<T['columnTypes'], C>
|
|
13
|
+
): RawExpression<C> {
|
|
14
|
+
if (typeof args[0] === 'string') {
|
|
15
|
+
return {
|
|
16
|
+
__raw: args[0],
|
|
17
|
+
__values: args.slice(1),
|
|
18
|
+
} as RawExpression<C>;
|
|
19
|
+
} else {
|
|
20
|
+
return {
|
|
21
|
+
__column: args[0](this.columnTypes),
|
|
22
|
+
__raw: args[1],
|
|
23
|
+
__values: args.slice(2),
|
|
24
|
+
} as RawExpression<C>;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
assertType,
|
|
3
|
+
db,
|
|
3
4
|
expectQueryNotMutated,
|
|
4
5
|
expectSql,
|
|
5
6
|
Profile,
|
|
@@ -9,7 +10,6 @@ import {
|
|
|
9
10
|
UserRecord,
|
|
10
11
|
useTestDatabase,
|
|
11
12
|
} from '../test-utils';
|
|
12
|
-
import { raw } from '../common';
|
|
13
13
|
import { DateColumn } from '../columnSchema';
|
|
14
14
|
|
|
15
15
|
const insertUserAndProfile = async () => {
|
|
@@ -236,7 +236,7 @@ describe('selectMethods', () => {
|
|
|
236
236
|
|
|
237
237
|
it('can select raw', () => {
|
|
238
238
|
const q = User.all();
|
|
239
|
-
const query = q.select({ one: raw('1') });
|
|
239
|
+
const query = q.select({ one: db.raw('1') });
|
|
240
240
|
|
|
241
241
|
assertType<Awaited<typeof query>, { one: unknown }[]>();
|
|
242
242
|
|
|
@@ -345,8 +345,8 @@ describe('selectMethods', () => {
|
|
|
345
345
|
|
|
346
346
|
it('should parse raw column', async () => {
|
|
347
347
|
const q = User.select({
|
|
348
|
-
date: raw(
|
|
349
|
-
new DateColumn().parse((input) => new Date(input)),
|
|
348
|
+
date: db.raw(
|
|
349
|
+
() => new DateColumn().parse((input) => new Date(input)),
|
|
350
350
|
'"createdAt"',
|
|
351
351
|
),
|
|
352
352
|
});
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { assertType, User, useTestDatabase } from '../test-utils';
|
|
2
|
-
import { raw } from '../common';
|
|
3
|
-
import { columnTypes } from '../columnSchema';
|
|
1
|
+
import { assertType, db, User, useTestDatabase } from '../test-utils';
|
|
4
2
|
|
|
5
3
|
describe('then', () => {
|
|
6
4
|
useTestDatabase();
|
|
@@ -8,7 +6,7 @@ describe('then', () => {
|
|
|
8
6
|
describe('catch', () => {
|
|
9
7
|
it('should catch error', (done) => {
|
|
10
8
|
const query = User.select({
|
|
11
|
-
column: raw(
|
|
9
|
+
column: db.raw((t) => t.boolean(), 'koko'),
|
|
12
10
|
}).catch((err) => {
|
|
13
11
|
expect(err.message).toBe(`column "koko" does not exist`);
|
|
14
12
|
done();
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
Chat,
|
|
3
|
+
db,
|
|
4
|
+
expectQueryNotMutated,
|
|
5
|
+
expectSql,
|
|
6
|
+
User,
|
|
7
|
+
} from '../test-utils';
|
|
3
8
|
|
|
4
9
|
['union', 'intersect', 'except'].forEach((what) => {
|
|
5
10
|
const upper = what.toUpperCase();
|
|
@@ -7,10 +12,10 @@ import { raw } from '../common';
|
|
|
7
12
|
it(`adds ${what}`, () => {
|
|
8
13
|
const q = User.all();
|
|
9
14
|
let query = q.select('id');
|
|
10
|
-
query = query[what as 'union']([Chat.select('id'), raw('SELECT 1')]);
|
|
15
|
+
query = query[what as 'union']([Chat.select('id'), db.raw('SELECT 1')]);
|
|
11
16
|
query = query[
|
|
12
17
|
(what + 'All') as 'unionAll' | 'intersectAll' | 'exceptAll'
|
|
13
|
-
]([raw('SELECT 2')], true);
|
|
18
|
+
]([db.raw('SELECT 2')], true);
|
|
14
19
|
|
|
15
20
|
const wrapped = query.wrap(User.select('id'));
|
|
16
21
|
|
|
@@ -34,7 +39,7 @@ import { raw } from '../common';
|
|
|
34
39
|
|
|
35
40
|
it('has modifier', () => {
|
|
36
41
|
const q = User.select('id');
|
|
37
|
-
q[`_${what}` as '_union']([raw('SELECT 1')]);
|
|
42
|
+
q[`_${what}` as '_union']([db.raw('SELECT 1')]);
|
|
38
43
|
expectSql(
|
|
39
44
|
q.toSql(),
|
|
40
45
|
`
|
|
@@ -43,7 +48,7 @@ import { raw } from '../common';
|
|
|
43
48
|
SELECT 1
|
|
44
49
|
`,
|
|
45
50
|
);
|
|
46
|
-
q[`_${what}All` as '_unionAll']([raw('SELECT 2')], true);
|
|
51
|
+
q[`_${what}All` as '_unionAll']([db.raw('SELECT 2')], true);
|
|
47
52
|
expectSql(
|
|
48
53
|
q.toSql({ clearCache: true }),
|
|
49
54
|
`
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
assertType,
|
|
3
|
+
db,
|
|
3
4
|
expectQueryNotMutated,
|
|
4
5
|
expectSql,
|
|
5
6
|
User,
|
|
6
7
|
userData,
|
|
8
|
+
UserRecord,
|
|
7
9
|
useTestDatabase,
|
|
8
10
|
} from '../test-utils';
|
|
9
|
-
import { raw } from '../common';
|
|
10
11
|
|
|
11
12
|
describe('update', () => {
|
|
12
13
|
useTestDatabase();
|
|
@@ -37,7 +38,7 @@ describe('update', () => {
|
|
|
37
38
|
const count = 2;
|
|
38
39
|
const users = await User.select('id').createMany([userData, userData]);
|
|
39
40
|
|
|
40
|
-
const query = User.or(...users).updateRaw(raw(`name = 'name'`));
|
|
41
|
+
const query = User.or(...users).updateRaw(db.raw(`name = 'name'`));
|
|
41
42
|
expectSql(
|
|
42
43
|
query.toSql(),
|
|
43
44
|
`
|
|
@@ -254,7 +255,7 @@ describe('update', () => {
|
|
|
254
255
|
|
|
255
256
|
it('should support raw sql as a value', () => {
|
|
256
257
|
const query = User.where({ id: 1 }).update({
|
|
257
|
-
name: raw(`'raw sql'`),
|
|
258
|
+
name: db.raw(`'raw sql'`),
|
|
258
259
|
});
|
|
259
260
|
expectSql(
|
|
260
261
|
query.toSql(),
|
|
@@ -321,6 +322,23 @@ describe('update', () => {
|
|
|
321
322
|
});
|
|
322
323
|
});
|
|
323
324
|
|
|
325
|
+
it('should strip unknown keys', () => {
|
|
326
|
+
const query = User.find(1).update({
|
|
327
|
+
name: 'name',
|
|
328
|
+
unknown: 'should be stripped',
|
|
329
|
+
} as unknown as UserRecord);
|
|
330
|
+
|
|
331
|
+
expectSql(
|
|
332
|
+
query.toSql(),
|
|
333
|
+
`
|
|
334
|
+
UPDATE "user"
|
|
335
|
+
SET "name" = $1, "updatedAt" = now()
|
|
336
|
+
WHERE "user"."id" = $2
|
|
337
|
+
`,
|
|
338
|
+
['name', 1],
|
|
339
|
+
);
|
|
340
|
+
});
|
|
341
|
+
|
|
324
342
|
describe('increment', () => {
|
|
325
343
|
it('should not mutate query', () => {
|
|
326
344
|
const q = User.all();
|
|
@@ -16,6 +16,8 @@ import { EmptyObject, MaybeArray } from '../utils';
|
|
|
16
16
|
import { CreateData } from './create';
|
|
17
17
|
import { parseResult, queryMethodByReturnType } from './then';
|
|
18
18
|
import { UpdateQueryData } from '../sql';
|
|
19
|
+
import { ColumnsShape } from '../columnSchema';
|
|
20
|
+
import { anyShape } from '../db';
|
|
19
21
|
|
|
20
22
|
export type UpdateData<T extends Query> = {
|
|
21
23
|
[K in keyof T['type']]?: T['type'][K] | RawExpression;
|
|
@@ -174,7 +176,10 @@ export class Update {
|
|
|
174
176
|
const set: Record<string, unknown> = { ...data };
|
|
175
177
|
pushQueryValue(this, 'updateData', set);
|
|
176
178
|
|
|
177
|
-
const relations = this
|
|
179
|
+
const { relations, shape } = this as {
|
|
180
|
+
relations: Record<string, Relation>;
|
|
181
|
+
shape: ColumnsShape;
|
|
182
|
+
};
|
|
178
183
|
|
|
179
184
|
const prependRelations: Record<string, Record<string, unknown>> = {};
|
|
180
185
|
const appendRelations: Record<string, Record<string, unknown>> = {};
|
|
@@ -195,6 +200,11 @@ export class Update {
|
|
|
195
200
|
}
|
|
196
201
|
appendRelations[key] = data[key] as Record<string, unknown>;
|
|
197
202
|
}
|
|
203
|
+
} else if (!shape[key] && shape !== anyShape) {
|
|
204
|
+
delete set[key];
|
|
205
|
+
} else {
|
|
206
|
+
const encode = shape[key].encodeFn;
|
|
207
|
+
if (encode) set[key] = encode(set[key]);
|
|
198
208
|
}
|
|
199
209
|
}
|
|
200
210
|
|