happy-sql 2.3.0 → 2.4.0
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 +60 -0
- package/bin/convert.js +3 -9
- package/lib/parser/visitors/clause/alter-table/alter-table.js +21 -0
- package/lib/parser/visitors/clause/binary.js +30 -6
- package/lib/parser/visitors/clause/column-definition/column-definition.js +49 -8
- package/lib/parser/visitors/clause/count/count.js +5 -2
- package/lib/parser/visitors/clause/create-extension/create-extension.js +7 -0
- package/lib/parser/visitors/clause/create-index/create-index.js +36 -5
- package/lib/parser/visitors/clause/create-schema/create-schema.js +7 -0
- package/lib/parser/visitors/clause/create-table/create-table.js +58 -7
- package/lib/parser/visitors/clause/create-view/create-view.js +17 -0
- package/lib/parser/visitors/clause/drop-index/drop-index.js +3 -0
- package/lib/parser/visitors/clause/drop-view/drop-view.js +15 -0
- package/lib/parser/visitors/clause/explain/explain.js +16 -0
- package/lib/parser/visitors/clause/from/from.js +93 -4
- package/lib/parser/visitors/clause/from/limit.js +13 -0
- package/lib/parser/visitors/clause/from/order-by.js +14 -3
- package/lib/parser/visitors/clause/from/table-func.js +5 -18
- package/lib/parser/visitors/clause/grant/grant.js +26 -0
- package/lib/parser/visitors/clause/index.js +50 -2
- package/lib/parser/visitors/clause/insert/insert.js +39 -5
- package/lib/parser/visitors/clause/operand.js +55 -1
- package/lib/parser/visitors/clause/pragma/pragma.js +52 -2
- package/lib/parser/visitors/clause/select/select.js +139 -6
- package/lib/parser/visitors/clause/set-param/set-param.js +19 -0
- package/lib/parser/visitors/clause/table-constraint.js +27 -0
- package/lib/parser/visitors/clause/update/update.js +17 -0
- package/lib/parser/visitors/clause/where/where.js +17 -0
- package/lib/printer/visitors/call-expression/clauses/access-method/access-method.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/analyze/analyze.js +10 -0
- package/lib/printer/visitors/call-expression/clauses/array-type/array-type.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/clauses.js +132 -2
- package/lib/printer/visitors/call-expression/clauses/collate/collate.js +7 -0
- package/lib/printer/visitors/call-expression/clauses/concurrently/concurrently.js +2 -0
- package/lib/printer/visitors/call-expression/clauses/constraint/constraint.js +11 -0
- package/lib/printer/visitors/call-expression/clauses/count-distinct/count-distinct.js +13 -0
- package/lib/printer/visitors/call-expression/clauses/create-extension/create-extension.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/create-index/create-index.js +43 -9
- package/lib/printer/visitors/call-expression/clauses/create-index/create-unique-index.js +5 -19
- package/lib/printer/visitors/call-expression/clauses/create-materialized-view/create-materialized-view.js +8 -0
- package/lib/printer/visitors/call-expression/clauses/create-schema/create-schema.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/create-table/create-table.js +16 -1
- package/lib/printer/visitors/call-expression/clauses/create-table-as/create-table-as.js +8 -0
- package/lib/printer/visitors/call-expression/clauses/create-temp-table/create-temp-table.js +11 -0
- package/lib/printer/visitors/call-expression/clauses/create-view/create-view.js +8 -0
- package/lib/printer/visitors/call-expression/clauses/create-virtual-table/create-virtual-table.js +8 -0
- package/lib/printer/visitors/call-expression/clauses/{nextval/nextval.js → default-nextval/default-nextval.js} +2 -1
- package/lib/printer/visitors/call-expression/clauses/default-values/default-values.js +3 -0
- package/lib/printer/visitors/call-expression/clauses/detach/detach.js +6 -0
- package/lib/printer/visitors/call-expression/clauses/distinct-on/distinct-on.js +14 -0
- package/lib/printer/visitors/call-expression/clauses/do-block/do-block.js +5 -0
- package/lib/printer/visitors/call-expression/clauses/drop-index/drop-index.js +13 -1
- package/lib/printer/visitors/call-expression/clauses/drop-view/drop-view.js +24 -0
- package/lib/printer/visitors/call-expression/clauses/explain/explain.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/explain-analyze/explain-analyze.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/explain-query-plan/explain-query-plan.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/fetch-first/fetch-first.js +5 -0
- package/lib/printer/visitors/call-expression/clauses/filter/filter.js +8 -0
- package/lib/printer/visitors/call-expression/clauses/for-update/for-update.js +3 -0
- package/lib/printer/visitors/call-expression/clauses/from/from.js +34 -3
- package/lib/printer/visitors/call-expression/clauses/generated-always-as/generated-always-as.js +10 -0
- package/lib/printer/visitors/call-expression/clauses/grant/grant.js +10 -0
- package/lib/printer/visitors/call-expression/clauses/grant-on/grant-on.js +10 -0
- package/lib/printer/visitors/call-expression/clauses/if-not-exists/if-not-exists.js +2 -0
- package/lib/printer/visitors/call-expression/clauses/indexed-by/indexed-by.js +7 -0
- package/lib/printer/visitors/call-expression/clauses/into/into.js +30 -2
- package/lib/printer/visitors/call-expression/clauses/json-op.js +1 -0
- package/lib/printer/visitors/call-expression/clauses/lateral-join/lateral-join.js +26 -3
- package/lib/printer/visitors/call-expression/clauses/like/like.js +7 -0
- package/lib/printer/visitors/call-expression/clauses/limit-all/limit-all.js +3 -0
- package/lib/printer/visitors/call-expression/clauses/limit-clauses.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/named-window/named-window.js +16 -0
- package/lib/printer/visitors/call-expression/clauses/not/not.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/not-indexed/not-indexed.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/nulls-order/nulls-order.js +9 -0
- package/lib/printer/visitors/call-expression/clauses/offset/offset.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/on-conflict/on-conflict.js +16 -1
- package/lib/printer/visitors/call-expression/clauses/on-delete/on-delete.js +32 -0
- package/lib/printer/visitors/call-expression/clauses/or-abort/or-abort.js +3 -0
- package/lib/printer/visitors/call-expression/clauses/or-fail/or-fail.js +3 -0
- package/lib/printer/visitors/call-expression/clauses/over/over.js +12 -0
- package/lib/printer/visitors/call-expression/clauses/pragma/pragma.js +14 -5
- package/lib/printer/visitors/call-expression/clauses/privilege/privilege.js +10 -0
- package/lib/printer/visitors/call-expression/clauses/references/references.js +14 -4
- package/lib/printer/visitors/call-expression/clauses/reindex/reindex.js +10 -0
- package/lib/printer/visitors/call-expression/clauses/release-savepoint/release-savepoint.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/rename-table/rename-table.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/right-outer-join/right-outer-join.js +8 -0
- package/lib/printer/visitors/call-expression/clauses/row-level-security/row-level-security.js +7 -0
- package/lib/printer/visitors/call-expression/clauses/select/select.js +37 -9
- package/lib/printer/visitors/call-expression/clauses/set-param/set-param.js +14 -0
- package/lib/printer/visitors/call-expression/clauses/show-param/show-param.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/table-primary-key/table-primary-key.js +13 -0
- package/lib/printer/visitors/call-expression/clauses/table-unique/table-unique.js +13 -0
- package/lib/printer/visitors/call-expression/clauses/to/to.js +10 -0
- package/lib/printer/visitors/call-expression/clauses/truncate/truncate.js +12 -0
- package/lib/printer/visitors/call-expression/clauses/unary-minus/unary-minus.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/update/update.js +24 -3
- package/lib/printer/visitors/call-expression/clauses/using/using.js +13 -0
- package/lib/printer/visitors/call-expression/clauses/vacuum/vacuum.js +8 -1
- package/lib/printer/visitors/call-expression/clauses/window-frame/window-frame.js +38 -0
- package/lib/printer/visitors/call-expression/clauses/with-named/with-named.js +8 -20
- package/lib/printer/visitors/call-expression/clauses/without-rowid/without-rowid.js +1 -0
- package/lib/printer/visitors/member-expression.js +14 -0
- package/lib/printer/visitors/string-literal.js +9 -5
- package/package.json +9 -2
|
@@ -2,11 +2,20 @@ import {types} from '@putout/babel';
|
|
|
2
2
|
import {convertBetween} from '#parser/clause/where';
|
|
3
3
|
import {convertClause} from '#parser/clause';
|
|
4
4
|
import {convertBinary} from '#parser/clause/binary';
|
|
5
|
+
import {
|
|
6
|
+
convertOperand,
|
|
7
|
+
convertMemberExpr,
|
|
8
|
+
} from '#parser/clause/operand';
|
|
5
9
|
import {convertGroupBy} from './group-by.js';
|
|
6
10
|
import {convertHaving} from './having.js';
|
|
7
11
|
import {convertOrderBy} from './order-by.js';
|
|
8
|
-
import {convertLimit} from './limit.js';
|
|
9
12
|
import {convertTableFunc} from './table-func.js';
|
|
13
|
+
import {
|
|
14
|
+
convertLimit,
|
|
15
|
+
convertOffset,
|
|
16
|
+
convertFetch,
|
|
17
|
+
convertForUpdate,
|
|
18
|
+
} from './limit.js';
|
|
10
19
|
|
|
11
20
|
const {
|
|
12
21
|
identifier,
|
|
@@ -21,6 +30,20 @@ const isExists = (node) => node.type === 'prefix_op_expr' && node.operator.name
|
|
|
21
30
|
const isNotExists = (node) => node.type === 'prefix_op_expr' && node.operator.name === 'NOT' && isExists(node.expr);
|
|
22
31
|
const isParenExpr = (node) => node.type === 'paren_expr';
|
|
23
32
|
|
|
33
|
+
const POSTFIX_OP = {
|
|
34
|
+
ISNULL: 'isNull',
|
|
35
|
+
NOTNULL: 'isNotNull',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const convertPostfix = (node) => {
|
|
39
|
+
const {name} = node.operator;
|
|
40
|
+
const fn = POSTFIX_OP[name];
|
|
41
|
+
|
|
42
|
+
return callExpression(identifier(fn), [
|
|
43
|
+
convertOperand(node.expr),
|
|
44
|
+
]);
|
|
45
|
+
};
|
|
46
|
+
|
|
24
47
|
const convertCondition = (node) => {
|
|
25
48
|
if (node.operator && node.operator.name === 'AND')
|
|
26
49
|
return logicalExpression('&&', convertCondition(node.left), convertCondition(node.right));
|
|
@@ -31,6 +54,9 @@ const convertCondition = (node) => {
|
|
|
31
54
|
if (node.type === 'between_expr')
|
|
32
55
|
return convertBetween(node);
|
|
33
56
|
|
|
57
|
+
if (node.type === 'postfix_op_expr')
|
|
58
|
+
return convertPostfix(node);
|
|
59
|
+
|
|
34
60
|
if (isNotExists(node))
|
|
35
61
|
return callExpression(identifier('notExists'), [
|
|
36
62
|
convertClause(node.expr.expr.expr),
|
|
@@ -51,7 +77,30 @@ const convertOn = (spec) => callExpression(identifier('on'), [
|
|
|
51
77
|
convertCondition(spec.expr),
|
|
52
78
|
]);
|
|
53
79
|
|
|
80
|
+
const isJoinUsing = ({type}) => type === 'join_using_specification';
|
|
81
|
+
|
|
82
|
+
const convertSpecification = (spec) => {
|
|
83
|
+
if (isJoinUsing(spec))
|
|
84
|
+
return callExpression(identifier('using'), spec.expr.expr.items.map(({name}) => identifier(name)));
|
|
85
|
+
|
|
86
|
+
return convertOn(spec);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const isIndexedTable = ({type}) => type === 'indexed_table';
|
|
90
|
+
const isNotIndexedTable = ({type}) => type === 'not_indexed_table';
|
|
91
|
+
|
|
54
92
|
const convertAlias = (node) => {
|
|
93
|
+
if (isIndexedTable(node))
|
|
94
|
+
return callExpression(identifier('indexedBy'), [
|
|
95
|
+
identifier(node.table.name),
|
|
96
|
+
identifier(node.index.name),
|
|
97
|
+
]);
|
|
98
|
+
|
|
99
|
+
if (isNotIndexedTable(node))
|
|
100
|
+
return callExpression(identifier('notIndexed'), [
|
|
101
|
+
identifier(node.table.name),
|
|
102
|
+
]);
|
|
103
|
+
|
|
55
104
|
if (node.type !== 'alias')
|
|
56
105
|
return identifier(node.name);
|
|
57
106
|
|
|
@@ -75,6 +124,9 @@ const convertAlias = (node) => {
|
|
|
75
124
|
]), tsLiteralType(stringLiteral(aliasName)));
|
|
76
125
|
}
|
|
77
126
|
|
|
127
|
+
if (node.expr.type === 'func_call')
|
|
128
|
+
return tsAsExpression(convertTableFunc(node.expr), tsLiteralType(stringLiteral(node.alias.name)));
|
|
129
|
+
|
|
78
130
|
return tsAsExpression(identifier(node.expr.name), tsLiteralType(stringLiteral(node.alias.name)));
|
|
79
131
|
};
|
|
80
132
|
|
|
@@ -152,7 +204,7 @@ const flattenJoins = (node, joins = []) => {
|
|
|
152
204
|
else
|
|
153
205
|
joins.push(callExpression(identifier(fnName), [
|
|
154
206
|
convertAlias(node.right),
|
|
155
|
-
|
|
207
|
+
convertSpecification(node.specification),
|
|
156
208
|
]));
|
|
157
209
|
|
|
158
210
|
return joins;
|
|
@@ -163,7 +215,26 @@ const flattenJoins = (node, joins = []) => {
|
|
|
163
215
|
return joins;
|
|
164
216
|
};
|
|
165
217
|
|
|
166
|
-
|
|
218
|
+
const convertWindow = (node) => {
|
|
219
|
+
const {name} = node;
|
|
220
|
+
const {expr} = node.window;
|
|
221
|
+
|
|
222
|
+
const args = [
|
|
223
|
+
identifier(name.name),
|
|
224
|
+
];
|
|
225
|
+
|
|
226
|
+
const {partitionBy, orderBy} = expr;
|
|
227
|
+
|
|
228
|
+
if (partitionBy)
|
|
229
|
+
args.push(callExpression(identifier('partitionBy'), partitionBy.specifications.items.map(convertOperand)));
|
|
230
|
+
|
|
231
|
+
if (orderBy)
|
|
232
|
+
args.push(convertOrderBy(orderBy));
|
|
233
|
+
|
|
234
|
+
return callExpression(identifier('namedWindow'), args);
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
export const convertFrom = ({expr, whereClause, groupByClause, havingClause, orderByClause, windowClause, limitClause, offsetClause, fetchClause, forClause}) => {
|
|
167
238
|
const fromArgs = [];
|
|
168
239
|
|
|
169
240
|
if (whereClause)
|
|
@@ -177,12 +248,24 @@ export const convertFrom = ({expr, whereClause, groupByClause, havingClause, ord
|
|
|
177
248
|
if (havingClause)
|
|
178
249
|
fromArgs.push(convertHaving(havingClause));
|
|
179
250
|
|
|
251
|
+
if (windowClause)
|
|
252
|
+
fromArgs.push(...windowClause.namedWindows.items.map(convertWindow));
|
|
253
|
+
|
|
180
254
|
if (orderByClause)
|
|
181
255
|
fromArgs.push(convertOrderBy(orderByClause));
|
|
182
256
|
|
|
183
257
|
if (limitClause)
|
|
184
258
|
fromArgs.push(convertLimit(limitClause));
|
|
185
259
|
|
|
260
|
+
if (offsetClause)
|
|
261
|
+
fromArgs.push(convertOffset(offsetClause));
|
|
262
|
+
|
|
263
|
+
if (fetchClause)
|
|
264
|
+
fromArgs.push(convertFetch(fetchClause));
|
|
265
|
+
|
|
266
|
+
if (forClause)
|
|
267
|
+
fromArgs.push(convertForUpdate());
|
|
268
|
+
|
|
186
269
|
if (expr.type === 'join_expr') {
|
|
187
270
|
const parts = flattenJoins(expr);
|
|
188
271
|
return callExpression(identifier('from'), parts);
|
|
@@ -200,8 +283,14 @@ export const convertFrom = ({expr, whereClause, groupByClause, havingClause, ord
|
|
|
200
283
|
...fromArgs,
|
|
201
284
|
]);
|
|
202
285
|
|
|
286
|
+
if (expr.type === 'member_expr')
|
|
287
|
+
return callExpression(identifier('from'), [
|
|
288
|
+
convertMemberExpr(expr),
|
|
289
|
+
...fromArgs,
|
|
290
|
+
]);
|
|
291
|
+
|
|
203
292
|
return callExpression(identifier('from'), [
|
|
204
|
-
|
|
293
|
+
convertAlias(expr),
|
|
205
294
|
...fromArgs,
|
|
206
295
|
]);
|
|
207
296
|
};
|
|
@@ -7,6 +7,9 @@ const {
|
|
|
7
7
|
} = types;
|
|
8
8
|
|
|
9
9
|
export const convertLimit = (limitClause) => {
|
|
10
|
+
if (limitClause.count?.type === 'limit_all')
|
|
11
|
+
return callExpression(identifier('limitAll'), []);
|
|
12
|
+
|
|
10
13
|
const args = [
|
|
11
14
|
numericLiteral(limitClause.count.value),
|
|
12
15
|
];
|
|
@@ -16,3 +19,13 @@ export const convertLimit = (limitClause) => {
|
|
|
16
19
|
|
|
17
20
|
return callExpression(identifier('limit'), args);
|
|
18
21
|
};
|
|
22
|
+
|
|
23
|
+
export const convertOffset = (offsetClause) => callExpression(identifier('offset'), [
|
|
24
|
+
numericLiteral(offsetClause.offset.value),
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
export const convertFetch = (fetchClause) => callExpression(identifier('fetchFirst'), [
|
|
28
|
+
numericLiteral(fetchClause.count.value),
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
export const convertForUpdate = () => callExpression(identifier('forUpdate'), []);
|
|
@@ -3,15 +3,26 @@ import {convertOperand} from '#parser/clause/operand';
|
|
|
3
3
|
|
|
4
4
|
const {callExpression, identifier} = types;
|
|
5
5
|
|
|
6
|
+
const isDesc = ({type}) => type === 'sort_direction_desc';
|
|
7
|
+
|
|
8
|
+
const convertNullsOrder = (col, nullHandlingKw) => {
|
|
9
|
+
const isLast = nullHandlingKw.at(-1).name === 'LAST';
|
|
10
|
+
|
|
11
|
+
return callExpression(identifier(isLast ? 'nullsLast' : 'nullsFirst'), [col]);
|
|
12
|
+
};
|
|
13
|
+
|
|
6
14
|
const convertOrderItem = (item) => {
|
|
7
15
|
if (item.type !== 'sort_specification')
|
|
8
16
|
return convertOperand(item);
|
|
9
17
|
|
|
10
|
-
|
|
18
|
+
let col = convertOperand(item.expr);
|
|
11
19
|
const {direction} = item;
|
|
12
20
|
|
|
13
|
-
if (direction
|
|
14
|
-
|
|
21
|
+
if (direction && isDesc(direction))
|
|
22
|
+
col = callExpression(identifier('desc'), [col]);
|
|
23
|
+
|
|
24
|
+
if (item.nullHandlingKw)
|
|
25
|
+
return convertNullsOrder(col, item.nullHandlingKw);
|
|
15
26
|
|
|
16
27
|
// ASC is default — no wrapper
|
|
17
28
|
return col;
|
|
@@ -1,28 +1,15 @@
|
|
|
1
1
|
import {types} from '@putout/babel';
|
|
2
|
+
import {convertOperand} from '#parser/clause/operand';
|
|
2
3
|
|
|
3
|
-
const {
|
|
4
|
-
callExpression,
|
|
5
|
-
identifier,
|
|
6
|
-
numericLiteral,
|
|
7
|
-
stringLiteral,
|
|
8
|
-
} = types;
|
|
4
|
+
const {callExpression, identifier} = types;
|
|
9
5
|
|
|
10
6
|
const SNAKE_RE = /_([a-z])/g;
|
|
11
7
|
const toCamel = (s) => s.replace(SNAKE_RE, (_, c) => c.toUpperCase());
|
|
12
8
|
|
|
13
|
-
const convertArg = (arg) => {
|
|
14
|
-
if (arg.type === 'number_literal')
|
|
15
|
-
return numericLiteral(arg.value);
|
|
16
|
-
|
|
17
|
-
if (arg.type === 'string_literal')
|
|
18
|
-
return stringLiteral(arg.value);
|
|
19
|
-
|
|
20
|
-
return identifier(arg.name);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
9
|
export const convertTableFunc = (expr) => {
|
|
24
|
-
|
|
25
|
-
const
|
|
10
|
+
// multi-word snake_case names are lowercased first (GENERATE_SERIES → generateSeries)
|
|
11
|
+
const name = toCamel(expr.name.name.includes('_') ? expr.name.name.toLowerCase() : expr.name.name);
|
|
12
|
+
const args = expr.args.expr.args.items.map(convertOperand);
|
|
26
13
|
|
|
27
14
|
return callExpression(identifier(name), args);
|
|
28
15
|
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {types} from '@putout/babel';
|
|
2
|
+
|
|
3
|
+
const {identifier, callExpression} = types;
|
|
4
|
+
|
|
5
|
+
export const convertGrant = (stmt) => {
|
|
6
|
+
const privArgs = [];
|
|
7
|
+
|
|
8
|
+
for (const p of stmt.privileges.items)
|
|
9
|
+
privArgs.push(identifier(p.privilegeKw.name));
|
|
10
|
+
|
|
11
|
+
const tableArgs = [];
|
|
12
|
+
|
|
13
|
+
for (const t of stmt.resource.tables.items)
|
|
14
|
+
tableArgs.push(identifier(t.name));
|
|
15
|
+
|
|
16
|
+
const roleArgs = [];
|
|
17
|
+
|
|
18
|
+
for (const r of stmt.roles.items)
|
|
19
|
+
roleArgs.push(identifier(r.name));
|
|
20
|
+
|
|
21
|
+
return callExpression(identifier('grant'), [
|
|
22
|
+
callExpression(identifier('privilege'), privArgs),
|
|
23
|
+
callExpression(identifier('grantOn'), tableArgs),
|
|
24
|
+
callExpression(identifier('to'), roleArgs),
|
|
25
|
+
]);
|
|
26
|
+
};
|
|
@@ -12,8 +12,19 @@ import {convertDropTable} from '#parser/clause/drop-table';
|
|
|
12
12
|
import {convertDropIndex} from '#parser/clause/drop-index';
|
|
13
13
|
import {convertPragma} from '#parser/clause/pragma';
|
|
14
14
|
import {convertAttach} from '#parser/clause/attach';
|
|
15
|
+
import {convertExplain} from '#parser/clause/explain';
|
|
16
|
+
import {
|
|
17
|
+
convertSetParam,
|
|
18
|
+
convertShowParam,
|
|
19
|
+
} from '#parser/clause/set-param';
|
|
20
|
+
import {convertCreateView} from '#parser/clause/create-view';
|
|
21
|
+
import {convertDropView} from '#parser/clause/drop-view';
|
|
22
|
+
import {convertCreateExtension} from '#parser/clause/create-extension';
|
|
23
|
+
import {convertCreateSchema} from '#parser/clause/create-schema';
|
|
24
|
+
import {convertGrant} from '#parser/clause/grant';
|
|
15
25
|
import {convertUnion} from '#parser/clause/union';
|
|
16
26
|
import {findClause} from '#parser/clause/find';
|
|
27
|
+
import {convertMemberExpr} from '#parser/clause/operand';
|
|
17
28
|
import {
|
|
18
29
|
convertBegin,
|
|
19
30
|
convertCommit,
|
|
@@ -21,7 +32,20 @@ import {
|
|
|
21
32
|
convertSavepoint,
|
|
22
33
|
} from '#parser/clause/transaction';
|
|
23
34
|
|
|
24
|
-
const {
|
|
35
|
+
const {
|
|
36
|
+
identifier,
|
|
37
|
+
callExpression,
|
|
38
|
+
stringLiteral,
|
|
39
|
+
} = types;
|
|
40
|
+
|
|
41
|
+
const isMemberExpr = ({type}) => type === 'member_expr';
|
|
42
|
+
|
|
43
|
+
const convertTableName = (table) => {
|
|
44
|
+
if (isMemberExpr(table))
|
|
45
|
+
return convertMemberExpr(table);
|
|
46
|
+
|
|
47
|
+
return identifier(table.name);
|
|
48
|
+
};
|
|
25
49
|
|
|
26
50
|
export const convertClause = (stmt) => {
|
|
27
51
|
const {type} = stmt;
|
|
@@ -69,5 +93,29 @@ const clauseVisitors = {
|
|
|
69
93
|
pragma_stmt: convertPragma,
|
|
70
94
|
attach_database_stmt: convertAttach,
|
|
71
95
|
create_index_stmt: convertCreateIndex,
|
|
72
|
-
vacuum_stmt: () => callExpression(identifier('vacuum'), [
|
|
96
|
+
vacuum_stmt: ({file}) => callExpression(identifier('vacuum'), file ? [
|
|
97
|
+
stringLiteral(file.value),
|
|
98
|
+
] : []),
|
|
99
|
+
truncate_stmt: ({tables}) => callExpression(identifier('truncate'), tables.items.map(({name}) => identifier(name))),
|
|
100
|
+
detach_database_stmt: ({schema}) => callExpression(identifier('detach'), [
|
|
101
|
+
identifier(schema.name),
|
|
102
|
+
]),
|
|
103
|
+
explain_stmt: convertExplain,
|
|
104
|
+
set_parameter_stmt: convertSetParam,
|
|
105
|
+
show_parameter_stmt: convertShowParam,
|
|
106
|
+
create_view_stmt: convertCreateView,
|
|
107
|
+
drop_view_stmt: convertDropView,
|
|
108
|
+
create_extension_stmt: convertCreateExtension,
|
|
109
|
+
create_schema_stmt: convertCreateSchema,
|
|
110
|
+
grant_privilege_stmt: convertGrant,
|
|
111
|
+
reindex_stmt: (stmt) => callExpression(identifier('reindex'), stmt.name ? [
|
|
112
|
+
identifier(stmt.name.name),
|
|
113
|
+
] : []),
|
|
114
|
+
analyze_stmt: (stmt) => callExpression(identifier('analyze'), (stmt.tables?.items ?? []).map(convertTableName)),
|
|
115
|
+
release_savepoint_stmt: ({savepoint}) => callExpression(identifier('releaseSavepoint'), [
|
|
116
|
+
identifier(savepoint.name),
|
|
117
|
+
]),
|
|
118
|
+
do_stmt: (stmt) => callExpression(identifier('doBlock'), [
|
|
119
|
+
stringLiteral(stmt.body.value),
|
|
120
|
+
]),
|
|
73
121
|
};
|
|
@@ -3,12 +3,16 @@ import {convertOperand} from '#parser/clause/operand';
|
|
|
3
3
|
import {convertSet} from '#parser/clause/set';
|
|
4
4
|
import {convertSelect} from '#parser/clause/select';
|
|
5
5
|
import {convertReturning} from '#parser/clause/returning';
|
|
6
|
+
import {convertCondition} from '#parser/clause/where';
|
|
6
7
|
import {findClause} from '#parser/clause/find';
|
|
7
8
|
|
|
8
9
|
const {
|
|
9
10
|
identifier,
|
|
10
11
|
callExpression,
|
|
11
12
|
arrayExpression,
|
|
13
|
+
stringLiteral,
|
|
14
|
+
tsAsExpression,
|
|
15
|
+
tsLiteralType,
|
|
12
16
|
} = types;
|
|
13
17
|
|
|
14
18
|
const convertExprToIdentifier = ({expr}) => identifier(expr.name);
|
|
@@ -56,6 +60,11 @@ const convertUpsert = (upsertClause) => {
|
|
|
56
60
|
const targetArgs = target ? target.expr.items.map(convertExprToIdentifier) : [];
|
|
57
61
|
const actionNode = action.type === 'upsert_action_nothing' ? identifier('nothing') : convertSet(action.set);
|
|
58
62
|
|
|
63
|
+
if (upsertClause.where)
|
|
64
|
+
targetArgs.push(callExpression(identifier('where'), [
|
|
65
|
+
convertCondition(upsertClause.where.expr),
|
|
66
|
+
]));
|
|
67
|
+
|
|
59
68
|
return callExpression(identifier('onConflict'), [...targetArgs, actionNode]);
|
|
60
69
|
};
|
|
61
70
|
|
|
@@ -88,16 +97,16 @@ export const convertInsert = (stmt) => {
|
|
|
88
97
|
const [, vc] = clauses;
|
|
89
98
|
const uc = findClause(clauses, 'upsert_clause');
|
|
90
99
|
const rc = findClause(clauses, 'returning_clause');
|
|
100
|
+
const dc = findClause(clauses, 'default_values');
|
|
91
101
|
|
|
92
|
-
const
|
|
93
|
-
const
|
|
94
|
-
const source = convertSource(vc);
|
|
102
|
+
const colArgs = convertColumns(ic);
|
|
103
|
+
const source = dc ? callExpression(identifier('defaultValues'), []) : convertSource(vc);
|
|
95
104
|
|
|
96
105
|
const args = [
|
|
97
106
|
ic.orAction && convertOrAction(ic.orAction),
|
|
98
107
|
callExpression(identifier('into'), [
|
|
99
|
-
|
|
100
|
-
|
|
108
|
+
convertTable(ic),
|
|
109
|
+
...colArgs,
|
|
101
110
|
source,
|
|
102
111
|
]),
|
|
103
112
|
uc && convertUpsert(uc),
|
|
@@ -106,3 +115,28 @@ export const convertInsert = (stmt) => {
|
|
|
106
115
|
|
|
107
116
|
return callExpression(identifier('insert'), args);
|
|
108
117
|
};
|
|
118
|
+
|
|
119
|
+
const isAliasTable = ({table}) => table.type === 'alias';
|
|
120
|
+
|
|
121
|
+
const convertTable = (ic) => {
|
|
122
|
+
if (!isAliasTable(ic))
|
|
123
|
+
return identifier(ic.table.name);
|
|
124
|
+
|
|
125
|
+
const {expr, alias} = ic.table;
|
|
126
|
+
|
|
127
|
+
return tsAsExpression(identifier(expr.name), tsLiteralType(stringLiteral(alias.name)));
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const convertColumns = (ic) => {
|
|
131
|
+
const columns = ic.columns || ic.table.columnAliases;
|
|
132
|
+
|
|
133
|
+
if (!columns)
|
|
134
|
+
return [];
|
|
135
|
+
|
|
136
|
+
const cols = columns.expr.items;
|
|
137
|
+
const colArg = cols.length === 1 ? identifier(cols[0].name) : arrayExpression(cols.map(convertColToIdentifier));
|
|
138
|
+
|
|
139
|
+
return [
|
|
140
|
+
colArg,
|
|
141
|
+
];
|
|
142
|
+
};
|
|
@@ -2,6 +2,7 @@ import {types} from '@putout/babel';
|
|
|
2
2
|
import {convertCount, isCount} from '#parser/clause/count';
|
|
3
3
|
import {convertCaseWhen} from '#parser/clause/case-when';
|
|
4
4
|
import {convertClause} from '#parser/clause';
|
|
5
|
+
import {convertBinary} from '#parser/clause/binary';
|
|
5
6
|
|
|
6
7
|
const {
|
|
7
8
|
identifier,
|
|
@@ -13,17 +14,40 @@ const {
|
|
|
13
14
|
callExpression,
|
|
14
15
|
} = types;
|
|
15
16
|
|
|
17
|
+
const isString = (a) => typeof a === 'string';
|
|
18
|
+
|
|
16
19
|
export const convertMemberExpr = (node) => {
|
|
17
20
|
const object = identifier(node.object.name);
|
|
18
21
|
|
|
19
22
|
if (node.property.type === 'all_columns')
|
|
20
23
|
return memberExpression(object, stringLiteral('*'), true);
|
|
21
24
|
|
|
25
|
+
if (node.property.type === 'array_subscript')
|
|
26
|
+
return memberExpression(object, convertOperand(node.property.expr), true);
|
|
27
|
+
|
|
22
28
|
return memberExpression(object, identifier(node.property.name));
|
|
23
29
|
};
|
|
24
30
|
|
|
25
31
|
const isFuncCall = ({type}) => type === 'func_call';
|
|
26
32
|
|
|
33
|
+
const getDataTypeName = ({name}) => {
|
|
34
|
+
if (isString(name))
|
|
35
|
+
return name;
|
|
36
|
+
|
|
37
|
+
return name.text;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const isArrayDataType = ({type}) => type === 'array_data_type';
|
|
41
|
+
|
|
42
|
+
const convertDataType = (dataType) => {
|
|
43
|
+
if (!isArrayDataType(dataType))
|
|
44
|
+
return identifier(getDataTypeName(dataType));
|
|
45
|
+
|
|
46
|
+
return callExpression(identifier('arrayType'), [
|
|
47
|
+
identifier(getDataTypeName(dataType.dataType)),
|
|
48
|
+
]);
|
|
49
|
+
};
|
|
50
|
+
|
|
27
51
|
const convertQuantifier = (node) => {
|
|
28
52
|
const {name} = node.quantifierKw;
|
|
29
53
|
const inner = node.expr.expr;
|
|
@@ -42,6 +66,25 @@ const convertQuantifier = (node) => {
|
|
|
42
66
|
return callExpression(identifier(name), args);
|
|
43
67
|
};
|
|
44
68
|
|
|
69
|
+
const convertPrefix = (node) => {
|
|
70
|
+
const {operator} = node;
|
|
71
|
+
const name = operator?.name ?? operator;
|
|
72
|
+
|
|
73
|
+
if (name === 'EXISTS')
|
|
74
|
+
return callExpression(identifier('exists'), [
|
|
75
|
+
convertClause(node.expr.expr),
|
|
76
|
+
]);
|
|
77
|
+
|
|
78
|
+
if (name === 'NOT')
|
|
79
|
+
return callExpression(identifier('not'), [
|
|
80
|
+
convertOperand(node.expr),
|
|
81
|
+
]);
|
|
82
|
+
|
|
83
|
+
return callExpression(identifier('unaryMinus'), [
|
|
84
|
+
convertOperand(node.expr),
|
|
85
|
+
]);
|
|
86
|
+
};
|
|
87
|
+
|
|
45
88
|
export const convertOperand = (node) => {
|
|
46
89
|
if (isCount(node))
|
|
47
90
|
return convertCount(node);
|
|
@@ -74,7 +117,18 @@ export const convertOperand = (node) => {
|
|
|
74
117
|
if (node.type === 'cast_operator_expr')
|
|
75
118
|
return callExpression(identifier('pgCast'), [
|
|
76
119
|
convertOperand(node.left),
|
|
77
|
-
|
|
120
|
+
convertDataType(node.right),
|
|
121
|
+
]);
|
|
122
|
+
|
|
123
|
+
if (node.type === 'binary_expr')
|
|
124
|
+
return convertBinary(node);
|
|
125
|
+
|
|
126
|
+
if (node.type === 'prefix_op_expr')
|
|
127
|
+
return convertPrefix(node);
|
|
128
|
+
|
|
129
|
+
if (node.type === 'paren_expr' && node.expr.type === 'select_stmt')
|
|
130
|
+
return callExpression(identifier('subquery'), [
|
|
131
|
+
convertClause(node.expr),
|
|
78
132
|
]);
|
|
79
133
|
|
|
80
134
|
if (node.type === 'parameter')
|
|
@@ -1,12 +1,62 @@
|
|
|
1
1
|
import {types} from '@putout/babel';
|
|
2
|
+
import {convertMemberExpr} from '#parser/clause/operand';
|
|
2
3
|
|
|
3
|
-
const {
|
|
4
|
+
const {
|
|
5
|
+
identifier,
|
|
6
|
+
stringLiteral,
|
|
7
|
+
numericLiteral,
|
|
8
|
+
callExpression,
|
|
9
|
+
binaryExpression,
|
|
10
|
+
} = types;
|
|
11
|
+
|
|
12
|
+
const isPragmaFuncCall = ({type}) => type === 'pragma_func_call';
|
|
13
|
+
const isPragmaAssignment = ({type}) => type === 'pragma_assignment';
|
|
14
|
+
|
|
15
|
+
const convertName = (node) => {
|
|
16
|
+
if (node.type === 'member_expr')
|
|
17
|
+
return convertMemberExpr(node);
|
|
18
|
+
|
|
19
|
+
return identifier(node.name);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const convertValue = (node) => {
|
|
23
|
+
if (node.type === 'keyword' || node.type === 'identifier')
|
|
24
|
+
return identifier(node.name);
|
|
25
|
+
|
|
26
|
+
if (node.type === 'number_literal')
|
|
27
|
+
return numericLiteral(node.value);
|
|
28
|
+
|
|
29
|
+
return stringLiteral(node.value);
|
|
30
|
+
};
|
|
4
31
|
|
|
5
32
|
export const convertPragma = ({pragma}) => {
|
|
33
|
+
if (isPragmaAssignment(pragma))
|
|
34
|
+
return convertAssignment(pragma);
|
|
35
|
+
|
|
36
|
+
if (isPragmaFuncCall(pragma))
|
|
37
|
+
return convertFuncCall(pragma);
|
|
38
|
+
|
|
39
|
+
return callExpression(identifier('pragma'), [
|
|
40
|
+
convertName(pragma),
|
|
41
|
+
]);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const convertAssignment = ({name, value}) => callExpression(identifier('pragma'), [
|
|
45
|
+
binaryExpression('===', convertName(name), convertValue(value)),
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
const convertFuncCall = (pragma) => {
|
|
6
49
|
const arg = pragma.args.expr;
|
|
7
50
|
|
|
8
51
|
return callExpression(identifier('pragma'), [
|
|
9
52
|
identifier(pragma.name.name),
|
|
10
|
-
|
|
53
|
+
convertArg(arg),
|
|
11
54
|
]);
|
|
12
55
|
};
|
|
56
|
+
|
|
57
|
+
const convertArg = (arg) => {
|
|
58
|
+
if (arg.type === 'string_literal')
|
|
59
|
+
return stringLiteral(arg.value);
|
|
60
|
+
|
|
61
|
+
return identifier(arg.name.toLowerCase());
|
|
62
|
+
};
|