pqb 0.7.13 → 0.8.1
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/CHANGELOG.md +12 -0
- package/dist/index.d.ts +618 -563
- package/dist/index.esm.js +1011 -402
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1014 -401
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/columnSchema/array.test.ts +67 -0
- package/src/columnSchema/array.ts +39 -13
- package/src/columnSchema/boolean.test.ts +17 -0
- package/src/columnSchema/boolean.ts +5 -1
- package/src/columnSchema/columnType.test.ts +230 -107
- package/src/columnSchema/columnType.ts +198 -28
- package/src/columnSchema/columnTypes.ts +28 -15
- package/src/columnSchema/columnsSchema.ts +6 -4
- package/src/columnSchema/commonMethods.ts +11 -4
- package/src/columnSchema/dateTime.test.ts +298 -0
- package/src/columnSchema/dateTime.ts +59 -2
- package/src/columnSchema/enum.test.ts +33 -0
- package/src/columnSchema/enum.ts +11 -1
- package/src/columnSchema/json/array.test.ts +21 -0
- package/src/columnSchema/json/array.ts +27 -13
- package/src/columnSchema/json/discriminatedUnion.test.ts +32 -0
- package/src/columnSchema/json/discriminatedUnion.ts +17 -2
- package/src/columnSchema/json/enum.test.ts +9 -0
- package/src/columnSchema/json/enum.ts +9 -1
- package/src/columnSchema/json/index.ts +19 -19
- package/src/columnSchema/json/instanceOf.test.ts +8 -0
- package/src/columnSchema/json/instanceOf.ts +4 -1
- package/src/columnSchema/json/intersection.test.ts +19 -0
- package/src/columnSchema/json/intersection.ts +9 -1
- package/src/columnSchema/json/lazy.test.ts +22 -0
- package/src/columnSchema/json/lazy.ts +22 -1
- package/src/columnSchema/json/literal.test.ts +7 -0
- package/src/columnSchema/json/literal.ts +12 -1
- package/src/columnSchema/json/map.test.ts +10 -0
- package/src/columnSchema/json/map.ts +21 -1
- package/src/columnSchema/json/nativeEnum.test.ts +10 -0
- package/src/columnSchema/json/nativeEnum.ts +4 -1
- package/src/columnSchema/json/nullable.test.ts +18 -0
- package/src/columnSchema/json/nullish.test.ts +18 -0
- package/src/columnSchema/json/object.test.ts +77 -0
- package/src/columnSchema/json/object.ts +31 -3
- package/src/columnSchema/json/optional.test.ts +18 -0
- package/src/columnSchema/json/record.test.ts +14 -0
- package/src/columnSchema/json/record.ts +12 -1
- package/src/columnSchema/json/scalarTypes.test.ts +133 -0
- package/src/columnSchema/json/scalarTypes.ts +90 -1
- package/src/columnSchema/json/set.test.ts +29 -0
- package/src/columnSchema/json/set.ts +26 -7
- package/src/columnSchema/json/tuple.test.ts +17 -0
- package/src/columnSchema/json/tuple.ts +16 -1
- package/src/columnSchema/json/typeBase.test.ts +123 -0
- package/src/columnSchema/json/typeBase.ts +52 -13
- package/src/columnSchema/json/union.test.ts +10 -0
- package/src/columnSchema/json/union.ts +18 -1
- package/src/columnSchema/json.test.ts +17 -0
- package/src/columnSchema/json.ts +10 -2
- package/src/columnSchema/number.test.ts +176 -0
- package/src/columnSchema/number.ts +48 -1
- package/src/columnSchema/string.test.ts +412 -0
- package/src/columnSchema/string.ts +126 -15
- package/src/columnSchema/timestamps.test.ts +6 -6
- package/src/columnSchema/virtual.ts +4 -0
- package/src/db.ts +1 -1
- package/src/query.ts +1 -1
- package/src/queryMethods/create.ts +6 -6
- package/src/queryMethods/for.ts +3 -3
- package/src/queryMethods/having.ts +1 -1
- package/src/queryMethods/join.ts +4 -4
- package/src/queryMethods/json.ts +1 -1
- package/src/queryMethods/queryMethods.ts +2 -2
- package/src/queryMethods/select.ts +3 -3
- package/src/queryMethods/update.ts +17 -17
- package/src/queryMethods/where.test.ts +1 -1
- package/src/queryMethods/where.ts +4 -4
- package/src/relations.ts +1 -1
- package/src/sql/aggregate.ts +2 -2
- package/src/sql/copy.ts +3 -3
- package/src/sql/delete.ts +5 -5
- package/src/sql/fromAndAs.ts +4 -4
- package/src/sql/having.ts +7 -7
- package/src/sql/insert.ts +5 -5
- package/src/sql/join.ts +16 -16
- package/src/sql/select.ts +6 -6
- package/src/sql/toSql.ts +24 -24
- package/src/sql/update.ts +4 -4
- package/src/sql/where.ts +18 -18
- package/src/utils.test.ts +9 -0
- package/src/utils.ts +3 -0
- package/src/columnSchema/columnTypes.test.ts +0 -527
package/src/sql/aggregate.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { ToSqlCtx } from './toSql';
|
|
|
9
9
|
|
|
10
10
|
export const aggregateToSql = (
|
|
11
11
|
ctx: ToSqlCtx,
|
|
12
|
-
|
|
12
|
+
table: QueryBase,
|
|
13
13
|
item: AggregateItem,
|
|
14
14
|
quotedAs?: string,
|
|
15
15
|
) => {
|
|
@@ -58,7 +58,7 @@ export const aggregateToSql = (
|
|
|
58
58
|
if (options.filter || options.filterOr) {
|
|
59
59
|
const whereSql = whereToSql(
|
|
60
60
|
ctx,
|
|
61
|
-
|
|
61
|
+
table,
|
|
62
62
|
{
|
|
63
63
|
and: options.filter ? [options.filter] : undefined,
|
|
64
64
|
or: options.filterOr?.map((item) => [item]),
|
package/src/sql/copy.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { pushWhereStatementSql } from './where';
|
|
|
7
7
|
|
|
8
8
|
export const pushCopySql = (
|
|
9
9
|
ctx: ToSqlCtx,
|
|
10
|
-
|
|
10
|
+
table: Query,
|
|
11
11
|
query: CopyQueryData,
|
|
12
12
|
quotedAs?: string,
|
|
13
13
|
) => {
|
|
@@ -19,7 +19,7 @@ export const pushCopySql = (
|
|
|
19
19
|
const target = 'from' in copy ? copy.from : copy.to;
|
|
20
20
|
|
|
21
21
|
sql.push(
|
|
22
|
-
`COPY ${q(
|
|
22
|
+
`COPY ${q(table.table as string)}${columns} ${
|
|
23
23
|
'from' in copy ? 'FROM' : 'TO'
|
|
24
24
|
} ${
|
|
25
25
|
typeof target === 'string'
|
|
@@ -55,5 +55,5 @@ export const pushCopySql = (
|
|
|
55
55
|
sql.push(`WITH (${options.join(', ')})`);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
pushWhereStatementSql(ctx,
|
|
58
|
+
pushWhereStatementSql(ctx, table, query, quotedAs);
|
|
59
59
|
};
|
package/src/sql/delete.ts
CHANGED
|
@@ -8,11 +8,11 @@ import { DeleteQueryData } from './data';
|
|
|
8
8
|
|
|
9
9
|
export const pushDeleteSql = (
|
|
10
10
|
ctx: ToSqlCtx,
|
|
11
|
-
|
|
11
|
+
table: QueryBase,
|
|
12
12
|
query: DeleteQueryData,
|
|
13
13
|
quotedAs: string,
|
|
14
14
|
) => {
|
|
15
|
-
const from = q(
|
|
15
|
+
const from = q(table.table as string);
|
|
16
16
|
ctx.sql.push(`DELETE FROM ${from}`);
|
|
17
17
|
|
|
18
18
|
if (from !== quotedAs) {
|
|
@@ -22,7 +22,7 @@ export const pushDeleteSql = (
|
|
|
22
22
|
let conditions: string | undefined;
|
|
23
23
|
if (query.join?.length) {
|
|
24
24
|
const items = query.join.map((item) =>
|
|
25
|
-
processJoinItem(ctx,
|
|
25
|
+
processJoinItem(ctx, table, item.args, quotedAs),
|
|
26
26
|
);
|
|
27
27
|
|
|
28
28
|
ctx.sql.push(`USING ${items.map((item) => item.target).join(', ')}`);
|
|
@@ -33,7 +33,7 @@ export const pushDeleteSql = (
|
|
|
33
33
|
.join(' AND ');
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
pushWhereStatementSql(ctx,
|
|
36
|
+
pushWhereStatementSql(ctx, table, query, quotedAs);
|
|
37
37
|
|
|
38
38
|
if (conditions?.length) {
|
|
39
39
|
if (query.and?.length || query.or?.length) {
|
|
@@ -43,5 +43,5 @@ export const pushDeleteSql = (
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
pushReturningSql(ctx,
|
|
46
|
+
pushReturningSql(ctx, table, query, quotedAs);
|
|
47
47
|
};
|
package/src/sql/fromAndAs.ts
CHANGED
|
@@ -7,14 +7,14 @@ import { SelectQueryData } from './data';
|
|
|
7
7
|
|
|
8
8
|
export const pushFromAndAs = (
|
|
9
9
|
ctx: ToSqlCtx,
|
|
10
|
-
|
|
10
|
+
table: QueryBase,
|
|
11
11
|
query: SelectQueryData,
|
|
12
12
|
quotedAs?: string,
|
|
13
13
|
) => {
|
|
14
14
|
ctx.sql.push('FROM');
|
|
15
15
|
if (query.fromOnly) ctx.sql.push('ONLY');
|
|
16
16
|
|
|
17
|
-
const from = getFrom(
|
|
17
|
+
const from = getFrom(table, query, ctx.values);
|
|
18
18
|
ctx.sql.push(from);
|
|
19
19
|
|
|
20
20
|
if (query.as && quotedAs && quotedAs !== from) {
|
|
@@ -23,7 +23,7 @@ export const pushFromAndAs = (
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
const getFrom = (
|
|
26
|
-
|
|
26
|
+
table: QueryBase,
|
|
27
27
|
query: SelectQueryData,
|
|
28
28
|
values: unknown[],
|
|
29
29
|
) => {
|
|
@@ -51,5 +51,5 @@ const getFrom = (
|
|
|
51
51
|
return quoteSchemaAndTable(query.schema, query.from);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
return quoteSchemaAndTable(query.schema,
|
|
54
|
+
return quoteSchemaAndTable(query.schema, table.table as string);
|
|
55
55
|
};
|
package/src/sql/having.ts
CHANGED
|
@@ -17,17 +17,17 @@ const aggregateOptionNames: (keyof AggregateItemOptions)[] = [
|
|
|
17
17
|
|
|
18
18
|
export const pushHavingSql = (
|
|
19
19
|
ctx: ToSqlCtx,
|
|
20
|
-
|
|
20
|
+
table: QueryBase,
|
|
21
21
|
query: SelectQueryData,
|
|
22
22
|
quotedAs?: string,
|
|
23
23
|
) => {
|
|
24
|
-
const conditions = havingToSql(ctx,
|
|
24
|
+
const conditions = havingToSql(ctx, table, query, quotedAs);
|
|
25
25
|
if (conditions.length) ctx.sql.push('HAVING', conditions);
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
export const havingToSql = (
|
|
29
29
|
ctx: ToSqlCtx,
|
|
30
|
-
|
|
30
|
+
table: QueryBase,
|
|
31
31
|
query: SelectQueryData,
|
|
32
32
|
quotedAs?: string,
|
|
33
33
|
): string => {
|
|
@@ -43,7 +43,7 @@ export const havingToSql = (
|
|
|
43
43
|
or.forEach((and) => {
|
|
44
44
|
const ands: string[] = [];
|
|
45
45
|
and.forEach((item) => {
|
|
46
|
-
if ('prototype' in item || '
|
|
46
|
+
if ('prototype' in item || '__table' in item) {
|
|
47
47
|
const query = item as QueryBase;
|
|
48
48
|
const sql = havingToSql(
|
|
49
49
|
ctx,
|
|
@@ -76,7 +76,7 @@ export const havingToSql = (
|
|
|
76
76
|
op as keyof AggregateItemOptions,
|
|
77
77
|
)
|
|
78
78
|
) {
|
|
79
|
-
const operator =
|
|
79
|
+
const operator = table.shape[column].operators[
|
|
80
80
|
op
|
|
81
81
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
82
82
|
] as Operator<any>;
|
|
@@ -89,7 +89,7 @@ export const havingToSql = (
|
|
|
89
89
|
|
|
90
90
|
const expression = aggregateToSql(
|
|
91
91
|
ctx,
|
|
92
|
-
|
|
92
|
+
table,
|
|
93
93
|
{
|
|
94
94
|
function: key,
|
|
95
95
|
arg: column,
|
|
@@ -111,7 +111,7 @@ export const havingToSql = (
|
|
|
111
111
|
ands.push(
|
|
112
112
|
`${aggregateToSql(
|
|
113
113
|
ctx,
|
|
114
|
-
|
|
114
|
+
table,
|
|
115
115
|
{
|
|
116
116
|
function: key,
|
|
117
117
|
arg: column,
|
package/src/sql/insert.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { InsertQueryData, QueryData } from './data';
|
|
|
9
9
|
|
|
10
10
|
export const pushInsertSql = (
|
|
11
11
|
ctx: ToSqlCtx,
|
|
12
|
-
|
|
12
|
+
table: QueryBase,
|
|
13
13
|
query: InsertQueryData,
|
|
14
14
|
quotedAs: string,
|
|
15
15
|
) => {
|
|
@@ -87,8 +87,8 @@ export const pushInsertSql = (
|
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
pushWhereStatementSql(ctx,
|
|
91
|
-
pushReturningSql(ctx,
|
|
90
|
+
pushWhereStatementSql(ctx, table, query, quotedAs);
|
|
91
|
+
pushReturningSql(ctx, table, query, quotedAs);
|
|
92
92
|
};
|
|
93
93
|
|
|
94
94
|
const encodeRow = (ctx: ToSqlCtx, row: unknown[]) => {
|
|
@@ -101,11 +101,11 @@ const encodeRow = (ctx: ToSqlCtx, row: unknown[]) => {
|
|
|
101
101
|
|
|
102
102
|
export const pushReturningSql = (
|
|
103
103
|
ctx: ToSqlCtx,
|
|
104
|
-
|
|
104
|
+
table: QueryBase,
|
|
105
105
|
query: QueryData,
|
|
106
106
|
quotedAs: string,
|
|
107
107
|
) => {
|
|
108
108
|
if (query.select) {
|
|
109
|
-
ctx.sql.push(`RETURNING ${selectToSql(ctx,
|
|
109
|
+
ctx.sql.push(`RETURNING ${selectToSql(ctx, table, query, quotedAs)}`);
|
|
110
110
|
}
|
|
111
111
|
};
|
package/src/sql/join.ts
CHANGED
|
@@ -22,7 +22,7 @@ type ItemOf3Or4Length =
|
|
|
22
22
|
|
|
23
23
|
export const processJoinItem = (
|
|
24
24
|
ctx: ToSqlCtx,
|
|
25
|
-
|
|
25
|
+
table: QueryBase,
|
|
26
26
|
args: JoinItem['args'],
|
|
27
27
|
quotedAs?: string,
|
|
28
28
|
): { target: string; conditions?: string } => {
|
|
@@ -31,25 +31,25 @@ export const processJoinItem = (
|
|
|
31
31
|
|
|
32
32
|
const [first] = args;
|
|
33
33
|
if (typeof first === 'string') {
|
|
34
|
-
if (first in
|
|
34
|
+
if (first in table.relations) {
|
|
35
35
|
const {
|
|
36
36
|
key,
|
|
37
37
|
query: toQuery,
|
|
38
38
|
joinQuery,
|
|
39
|
-
} = (
|
|
39
|
+
} = (table.relations as Record<string, Relation>)[first];
|
|
40
40
|
|
|
41
|
-
const jq = joinQuery(
|
|
41
|
+
const jq = joinQuery(table, toQuery);
|
|
42
42
|
const { query } = jq;
|
|
43
43
|
|
|
44
|
-
const
|
|
44
|
+
const tableName = (
|
|
45
45
|
typeof query.from === 'string' ? query.from : jq.table
|
|
46
46
|
) as string;
|
|
47
47
|
|
|
48
|
-
target = quoteSchemaAndTable(query.schema,
|
|
48
|
+
target = quoteSchemaAndTable(query.schema, tableName);
|
|
49
49
|
|
|
50
50
|
const as = query.as || key;
|
|
51
51
|
const joinAs = q(as as string);
|
|
52
|
-
if (as !==
|
|
52
|
+
if (as !== tableName) {
|
|
53
53
|
target += ` AS ${joinAs}`;
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -60,7 +60,7 @@ export const processJoinItem = (
|
|
|
60
60
|
|
|
61
61
|
if (args[1]) {
|
|
62
62
|
const arg = (args[1] as (q: unknown) => QueryBase)(
|
|
63
|
-
new ctx.onQueryBuilder(jq, jq.shape,
|
|
63
|
+
new ctx.onQueryBuilder(jq, jq.shape, table),
|
|
64
64
|
).query;
|
|
65
65
|
|
|
66
66
|
if (arg.and) queryData.and.push(...arg.and);
|
|
@@ -70,7 +70,7 @@ export const processJoinItem = (
|
|
|
70
70
|
conditions = whereToSql(ctx, jq, queryData, joinAs);
|
|
71
71
|
} else {
|
|
72
72
|
target = q(first);
|
|
73
|
-
conditions = processArgs(args, ctx,
|
|
73
|
+
conditions = processArgs(args, ctx, table, first, target, quotedAs);
|
|
74
74
|
}
|
|
75
75
|
} else {
|
|
76
76
|
const query = first.query;
|
|
@@ -89,9 +89,9 @@ export const processJoinItem = (
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
conditions = processArgs(args, ctx,
|
|
92
|
+
conditions = processArgs(args, ctx, table, first, joinAs, quotedAs);
|
|
93
93
|
|
|
94
|
-
const whereSql = whereToSql(ctx,
|
|
94
|
+
const whereSql = whereToSql(ctx, table, query, joinAs);
|
|
95
95
|
if (whereSql) {
|
|
96
96
|
if (conditions) conditions += ` AND ${whereSql}`;
|
|
97
97
|
else conditions = whereSql;
|
|
@@ -104,7 +104,7 @@ export const processJoinItem = (
|
|
|
104
104
|
const processArgs = (
|
|
105
105
|
args: JoinItem['args'],
|
|
106
106
|
ctx: ToSqlCtx,
|
|
107
|
-
|
|
107
|
+
table: QueryBase,
|
|
108
108
|
first: string | QueryWithTable,
|
|
109
109
|
joinAs: string,
|
|
110
110
|
quotedAs?: string,
|
|
@@ -114,7 +114,7 @@ const processArgs = (
|
|
|
114
114
|
if (typeof arg === 'function') {
|
|
115
115
|
let shape;
|
|
116
116
|
if (typeof first === 'string') {
|
|
117
|
-
shape =
|
|
117
|
+
shape = table.query.withShapes?.[first];
|
|
118
118
|
if (!shape) {
|
|
119
119
|
throw new Error('Cannot get shape of `with` statement');
|
|
120
120
|
}
|
|
@@ -122,7 +122,7 @@ const processArgs = (
|
|
|
122
122
|
shape = first.shape;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
const jq = arg(new ctx.onQueryBuilder(first, shape,
|
|
125
|
+
const jq = arg(new ctx.onQueryBuilder(first, shape, table));
|
|
126
126
|
return whereToSql(ctx, jq, jq.query, joinAs);
|
|
127
127
|
} else {
|
|
128
128
|
return getObjectOrRawConditions(arg, ctx.values, quotedAs, joinAs);
|
|
@@ -189,7 +189,7 @@ const getObjectOrRawConditions = (
|
|
|
189
189
|
|
|
190
190
|
export const pushJoinSql = (
|
|
191
191
|
ctx: ToSqlCtx,
|
|
192
|
-
|
|
192
|
+
table: QueryBase,
|
|
193
193
|
query: QueryData & {
|
|
194
194
|
join: JoinItem[];
|
|
195
195
|
},
|
|
@@ -198,7 +198,7 @@ export const pushJoinSql = (
|
|
|
198
198
|
query.join.forEach((item) => {
|
|
199
199
|
const { target, conditions } = processJoinItem(
|
|
200
200
|
ctx,
|
|
201
|
-
|
|
201
|
+
table,
|
|
202
202
|
item.args,
|
|
203
203
|
quotedAs,
|
|
204
204
|
);
|
package/src/sql/select.ts
CHANGED
|
@@ -65,16 +65,16 @@ const jsonToSql = (
|
|
|
65
65
|
|
|
66
66
|
export const pushSelectSql = (
|
|
67
67
|
ctx: ToSqlCtx,
|
|
68
|
-
|
|
68
|
+
table: QueryBase,
|
|
69
69
|
query: Pick<SelectQueryData, 'select' | 'join'>,
|
|
70
70
|
quotedAs?: string,
|
|
71
71
|
) => {
|
|
72
|
-
ctx.sql.push(selectToSql(ctx,
|
|
72
|
+
ctx.sql.push(selectToSql(ctx, table, query, quotedAs));
|
|
73
73
|
};
|
|
74
74
|
|
|
75
75
|
export const selectToSql = (
|
|
76
76
|
ctx: ToSqlCtx,
|
|
77
|
-
|
|
77
|
+
table: QueryBase,
|
|
78
78
|
query: Pick<SelectQueryData, 'select' | 'join'>,
|
|
79
79
|
quotedAs?: string,
|
|
80
80
|
): string => {
|
|
@@ -116,13 +116,13 @@ export const selectToSql = (
|
|
|
116
116
|
list.push(
|
|
117
117
|
`${(item as SelectFunctionItem).function}(${selectToSql(
|
|
118
118
|
ctx,
|
|
119
|
-
|
|
119
|
+
table,
|
|
120
120
|
{ select: item.arguments },
|
|
121
121
|
quotedAs,
|
|
122
122
|
)})${item.as ? ` AS ${q((item as { as: string }).as)}` : ''}`,
|
|
123
123
|
);
|
|
124
124
|
} else {
|
|
125
|
-
list.push(aggregateToSql(ctx,
|
|
125
|
+
list.push(aggregateToSql(ctx, table, item, quotedAs));
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
});
|
|
@@ -160,7 +160,7 @@ const pushSubQuerySql = (
|
|
|
160
160
|
|
|
161
161
|
select.length = 0;
|
|
162
162
|
select[0] = { selectAs: { c: first } } as SelectItem;
|
|
163
|
-
query = query._wrap(query.
|
|
163
|
+
query = query._wrap(query.__table.clone()) as unknown as typeof query;
|
|
164
164
|
query._getOptional(raw(`COALESCE(json_agg("c"), '[]')`));
|
|
165
165
|
break;
|
|
166
166
|
}
|
package/src/sql/toSql.ts
CHANGED
|
@@ -35,22 +35,22 @@ export type ToSqlOptions = {
|
|
|
35
35
|
values?: unknown[];
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
export const toSql = (
|
|
38
|
+
export const toSql = (table: Query, options?: ToSqlOptions): Sql => {
|
|
39
39
|
return (
|
|
40
|
-
(!options?.clearCache &&
|
|
41
|
-
(
|
|
40
|
+
(!options?.clearCache && table.query[toSqlCacheKey]) ||
|
|
41
|
+
(table.query[toSqlCacheKey] = makeSql(table, options))
|
|
42
42
|
);
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
export const makeSql = (
|
|
46
|
-
|
|
46
|
+
table: Query,
|
|
47
47
|
{ values = [] }: ToSqlOptions = {},
|
|
48
48
|
): Sql => {
|
|
49
|
-
const query =
|
|
49
|
+
const query = table.query;
|
|
50
50
|
const sql: string[] = [];
|
|
51
51
|
const ctx: ToSqlCtx = {
|
|
52
|
-
whereQueryBuilder:
|
|
53
|
-
onQueryBuilder:
|
|
52
|
+
whereQueryBuilder: table.whereQueryBuilder,
|
|
53
|
+
onQueryBuilder: table.onQueryBuilder,
|
|
54
54
|
sql,
|
|
55
55
|
values,
|
|
56
56
|
};
|
|
@@ -61,45 +61,45 @@ export const makeSql = (
|
|
|
61
61
|
|
|
62
62
|
if (query.type) {
|
|
63
63
|
if (query.type === 'truncate') {
|
|
64
|
-
if (!
|
|
64
|
+
if (!table.table) throw new Error('Table is missing for truncate');
|
|
65
65
|
|
|
66
|
-
pushTruncateSql(ctx,
|
|
66
|
+
pushTruncateSql(ctx, table.table, query);
|
|
67
67
|
return { text: sql.join(' '), values };
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
if (query.type === 'columnInfo') {
|
|
71
|
-
if (!
|
|
71
|
+
if (!table.table) throw new Error('Table is missing for truncate');
|
|
72
72
|
|
|
73
|
-
pushColumnInfoSql(ctx,
|
|
73
|
+
pushColumnInfoSql(ctx, table.table, query);
|
|
74
74
|
return { text: sql.join(' '), values };
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
if (!
|
|
77
|
+
if (!table.table) throw new Error(`Table is missing for ${query.type}`);
|
|
78
78
|
|
|
79
|
-
const quotedAs = q(query.as ||
|
|
79
|
+
const quotedAs = q(query.as || table.table);
|
|
80
80
|
|
|
81
81
|
if (query.type === 'insert') {
|
|
82
|
-
pushInsertSql(ctx,
|
|
82
|
+
pushInsertSql(ctx, table, query, q(table.table));
|
|
83
83
|
return { text: sql.join(' '), values };
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
if (query.type === 'update') {
|
|
87
|
-
pushUpdateSql(ctx,
|
|
87
|
+
pushUpdateSql(ctx, table, query, quotedAs);
|
|
88
88
|
return { text: sql.join(' '), values };
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
if (query.type === 'delete') {
|
|
92
|
-
pushDeleteSql(ctx,
|
|
92
|
+
pushDeleteSql(ctx, table, query, quotedAs);
|
|
93
93
|
return { text: sql.join(' '), values };
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
if (query.type === 'copy') {
|
|
97
|
-
pushCopySql(ctx,
|
|
97
|
+
pushCopySql(ctx, table, query, quotedAs);
|
|
98
98
|
return { text: sql.join(' '), values };
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
const quotedAs =
|
|
102
|
+
const quotedAs = table.table && q(query.as || table.table);
|
|
103
103
|
|
|
104
104
|
sql.push('SELECT');
|
|
105
105
|
|
|
@@ -107,23 +107,23 @@ export const makeSql = (
|
|
|
107
107
|
pushDistinctSql(ctx, query.distinct, quotedAs);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
pushSelectSql(ctx,
|
|
110
|
+
pushSelectSql(ctx, table, query, quotedAs);
|
|
111
111
|
|
|
112
|
-
if (
|
|
113
|
-
pushFromAndAs(ctx,
|
|
112
|
+
if (table.table || query.from) {
|
|
113
|
+
pushFromAndAs(ctx, table, query, quotedAs);
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
if (query.join) {
|
|
117
117
|
pushJoinSql(
|
|
118
118
|
ctx,
|
|
119
|
-
|
|
119
|
+
table,
|
|
120
120
|
query as QueryData & { join: JoinItem[] },
|
|
121
121
|
quotedAs,
|
|
122
122
|
);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
if (query.and || query.or) {
|
|
126
|
-
pushWhereStatementSql(ctx,
|
|
126
|
+
pushWhereStatementSql(ctx, table, query, quotedAs);
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
if (query.group) {
|
|
@@ -136,7 +136,7 @@ export const makeSql = (
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
if (query.having || query.havingOr) {
|
|
139
|
-
pushHavingSql(ctx,
|
|
139
|
+
pushHavingSql(ctx, table, query, quotedAs);
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
if (query.window) {
|
package/src/sql/update.ts
CHANGED
|
@@ -13,11 +13,11 @@ import {
|
|
|
13
13
|
|
|
14
14
|
export const pushUpdateSql = (
|
|
15
15
|
ctx: ToSqlCtx,
|
|
16
|
-
|
|
16
|
+
table: QueryBase,
|
|
17
17
|
query: UpdateQueryData,
|
|
18
18
|
quotedAs: string,
|
|
19
19
|
) => {
|
|
20
|
-
const quotedTable = quoteSchemaAndTable(query.schema,
|
|
20
|
+
const quotedTable = quoteSchemaAndTable(query.schema, table.table as string);
|
|
21
21
|
ctx.sql.push(`UPDATE ${quotedTable}`);
|
|
22
22
|
|
|
23
23
|
if (quotedTable !== quotedAs) {
|
|
@@ -30,8 +30,8 @@ export const pushUpdateSql = (
|
|
|
30
30
|
processData(ctx, set, query.updateData);
|
|
31
31
|
ctx.sql.push(set.join(', '));
|
|
32
32
|
|
|
33
|
-
pushWhereStatementSql(ctx,
|
|
34
|
-
pushReturningSql(ctx,
|
|
33
|
+
pushWhereStatementSql(ctx, table, query, quotedAs);
|
|
34
|
+
pushReturningSql(ctx, table, query, quotedAs);
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
const processData = (
|
package/src/sql/where.ts
CHANGED
|
@@ -16,11 +16,11 @@ import { QueryData } from './data';
|
|
|
16
16
|
|
|
17
17
|
export const pushWhereStatementSql = (
|
|
18
18
|
ctx: ToSqlCtx,
|
|
19
|
-
|
|
19
|
+
table: QueryBase,
|
|
20
20
|
query: Pick<QueryData, 'and' | 'or'>,
|
|
21
21
|
quotedAs?: string,
|
|
22
22
|
) => {
|
|
23
|
-
const res = whereToSql(ctx,
|
|
23
|
+
const res = whereToSql(ctx, table, query, quotedAs, false);
|
|
24
24
|
if (res) {
|
|
25
25
|
ctx.sql.push('WHERE', res);
|
|
26
26
|
}
|
|
@@ -29,12 +29,12 @@ export const pushWhereStatementSql = (
|
|
|
29
29
|
export const pushWhereToSql = (
|
|
30
30
|
sql: string[],
|
|
31
31
|
ctx: ToSqlCtx,
|
|
32
|
-
|
|
32
|
+
table: QueryBase,
|
|
33
33
|
query: Pick<QueryData, 'and' | 'or'>,
|
|
34
34
|
quotedAs?: string,
|
|
35
35
|
not?: boolean,
|
|
36
36
|
) => {
|
|
37
|
-
const res = whereToSql(ctx,
|
|
37
|
+
const res = whereToSql(ctx, table, query, quotedAs, not);
|
|
38
38
|
if (res) {
|
|
39
39
|
sql.push(res);
|
|
40
40
|
}
|
|
@@ -42,7 +42,7 @@ export const pushWhereToSql = (
|
|
|
42
42
|
|
|
43
43
|
export const whereToSql = (
|
|
44
44
|
ctx: ToSqlCtx,
|
|
45
|
-
|
|
45
|
+
table: QueryBase,
|
|
46
46
|
query: Pick<QueryData, 'and' | 'or'>,
|
|
47
47
|
quotedAs?: string,
|
|
48
48
|
not?: boolean,
|
|
@@ -50,10 +50,10 @@ export const whereToSql = (
|
|
|
50
50
|
if (query.or) {
|
|
51
51
|
const ors = query.and ? [query.and, ...query.or] : query.or;
|
|
52
52
|
return ors
|
|
53
|
-
.map((and) => processAnds(and, ctx,
|
|
53
|
+
.map((and) => processAnds(and, ctx, table, quotedAs, not))
|
|
54
54
|
.join(' OR ');
|
|
55
55
|
} else if (query.and) {
|
|
56
|
-
return processAnds(query.and, ctx,
|
|
56
|
+
return processAnds(query.and, ctx, table, quotedAs, not);
|
|
57
57
|
} else {
|
|
58
58
|
return undefined;
|
|
59
59
|
}
|
|
@@ -62,19 +62,19 @@ export const whereToSql = (
|
|
|
62
62
|
const processAnds = (
|
|
63
63
|
and: WhereItem[],
|
|
64
64
|
ctx: ToSqlCtx,
|
|
65
|
-
|
|
65
|
+
table: QueryBase,
|
|
66
66
|
quotedAs?: string,
|
|
67
67
|
not?: boolean,
|
|
68
68
|
): string => {
|
|
69
69
|
const ands: string[] = [];
|
|
70
|
-
and.forEach((data) => processWhere(ands, ctx,
|
|
70
|
+
and.forEach((data) => processWhere(ands, ctx, table, data, quotedAs, not));
|
|
71
71
|
return ands.join(' AND ');
|
|
72
72
|
};
|
|
73
73
|
|
|
74
74
|
const processWhere = (
|
|
75
75
|
ands: string[],
|
|
76
76
|
ctx: ToSqlCtx,
|
|
77
|
-
|
|
77
|
+
table: QueryBase,
|
|
78
78
|
data: WhereItem,
|
|
79
79
|
quotedAs?: string,
|
|
80
80
|
not?: boolean,
|
|
@@ -82,12 +82,12 @@ const processWhere = (
|
|
|
82
82
|
const prefix = not ? 'NOT ' : '';
|
|
83
83
|
|
|
84
84
|
if (typeof data === 'function') {
|
|
85
|
-
const qb = data(new ctx.whereQueryBuilder(
|
|
85
|
+
const qb = data(new ctx.whereQueryBuilder(table, table.shape));
|
|
86
86
|
pushWhereToSql(ands, ctx, qb, qb.query, quotedAs, not);
|
|
87
87
|
return;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
if ('prototype' in data || '
|
|
90
|
+
if ('prototype' in data || '__table' in data) {
|
|
91
91
|
const query = data as Query;
|
|
92
92
|
const sql = whereToSql(
|
|
93
93
|
ctx,
|
|
@@ -110,17 +110,17 @@ const processWhere = (
|
|
|
110
110
|
const value = (data as Record<string, unknown>)[key];
|
|
111
111
|
if (key === 'AND') {
|
|
112
112
|
const arr = toArray(value as MaybeArray<WhereItem>);
|
|
113
|
-
ands.push(processAnds(arr, ctx,
|
|
113
|
+
ands.push(processAnds(arr, ctx, table, quotedAs, not));
|
|
114
114
|
} else if (key === 'OR') {
|
|
115
115
|
const arr = (value as MaybeArray<WhereItem>[]).map(toArray);
|
|
116
116
|
ands.push(
|
|
117
117
|
arr
|
|
118
|
-
.map((and) => processAnds(and, ctx,
|
|
118
|
+
.map((and) => processAnds(and, ctx, table, quotedAs, not))
|
|
119
119
|
.join(' OR '),
|
|
120
120
|
);
|
|
121
121
|
} else if (key === 'NOT') {
|
|
122
122
|
const arr = toArray(value as MaybeArray<WhereItem>);
|
|
123
|
-
ands.push(processAnds(arr, ctx,
|
|
123
|
+
ands.push(processAnds(arr, ctx, table, quotedAs, !not));
|
|
124
124
|
} else if (key === 'ON') {
|
|
125
125
|
if (Array.isArray(value)) {
|
|
126
126
|
const item = value as WhereJsonPathEqualsItem;
|
|
@@ -129,7 +129,7 @@ const processWhere = (
|
|
|
129
129
|
const rightColumn = quoteFullColumn(
|
|
130
130
|
item[2],
|
|
131
131
|
getQueryAs({
|
|
132
|
-
table:
|
|
132
|
+
table: table.table,
|
|
133
133
|
query: { as: quotedAs },
|
|
134
134
|
}),
|
|
135
135
|
);
|
|
@@ -171,7 +171,7 @@ const processWhere = (
|
|
|
171
171
|
(joinItems as JoinItem['args'][]).forEach((item) => {
|
|
172
172
|
const { target, conditions } = processJoinItem(
|
|
173
173
|
ctx,
|
|
174
|
-
|
|
174
|
+
table,
|
|
175
175
|
item,
|
|
176
176
|
quotedAs,
|
|
177
177
|
);
|
|
@@ -193,7 +193,7 @@ const processWhere = (
|
|
|
193
193
|
)}`,
|
|
194
194
|
);
|
|
195
195
|
} else {
|
|
196
|
-
const column =
|
|
196
|
+
const column = table.shape[key];
|
|
197
197
|
if (!column) {
|
|
198
198
|
// TODO: custom error classes
|
|
199
199
|
throw new Error(`Unknown column ${key} provided to condition`);
|
package/src/utils.test.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
pushOrNewArray,
|
|
6
6
|
pushOrNewArrayToObject,
|
|
7
7
|
SetOptional,
|
|
8
|
+
singleQuote,
|
|
8
9
|
SomeIsTrue,
|
|
9
10
|
} from './utils';
|
|
10
11
|
|
|
@@ -90,4 +91,12 @@ describe('utils', () => {
|
|
|
90
91
|
expect(pushOrNewArray(arr, 123)).toEqual([123]);
|
|
91
92
|
});
|
|
92
93
|
});
|
|
94
|
+
|
|
95
|
+
describe('singleQuote', () => {
|
|
96
|
+
it('should put string into single quotes, escape single quotes and backslashes', () => {
|
|
97
|
+
expect(singleQuote(`ko`)).toBe(`'ko'`);
|
|
98
|
+
expect(singleQuote(`k'o`)).toBe(`'k\\'o'`);
|
|
99
|
+
expect(singleQuote(`k\\'o`)).toBe(`'k\\\\\\'o'`);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
93
102
|
});
|