happy-sql 2.0.8 → 2.1.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 +17 -0
- package/lib/parser/visitors/clause/count/count.js +4 -0
- package/lib/parser/visitors/clause/delete/fixture/delete-where-between-fix.js +14 -0
- package/lib/parser/visitors/clause/delete/fixture/delete-where-between.sql +1 -0
- package/lib/parser/visitors/clause/from/fixture/generate-series-fix.js +12 -0
- package/lib/parser/visitors/clause/from/fixture/generate-series.sql +1 -0
- package/lib/parser/visitors/clause/from/fixture/group-by-fix.js +14 -0
- package/lib/parser/visitors/clause/from/fixture/group-by-having-fix.js +22 -0
- package/lib/parser/visitors/clause/from/fixture/group-by-having.sql +1 -0
- package/lib/parser/visitors/clause/from/fixture/group-by-multi-fix.js +13 -0
- package/lib/parser/visitors/clause/from/fixture/group-by-multi.sql +1 -0
- package/lib/parser/visitors/clause/from/fixture/group-by-order-by-fix.js +17 -0
- package/lib/parser/visitors/clause/from/fixture/group-by-order-by.sql +1 -0
- package/lib/parser/visitors/clause/from/fixture/group-by-sum-fix.js +14 -0
- package/lib/parser/visitors/clause/from/fixture/group-by-sum-having-fix.js +19 -0
- package/lib/parser/visitors/clause/from/fixture/group-by-sum-having.sql +1 -0
- package/lib/parser/visitors/clause/from/fixture/group-by-sum.sql +1 -0
- package/lib/parser/visitors/clause/from/fixture/group-by.sql +1 -0
- package/lib/parser/visitors/clause/from/fixture/json-each-fix.js +10 -0
- package/lib/parser/visitors/clause/from/fixture/json-each.sql +1 -0
- package/lib/parser/visitors/clause/from/fixture/limit-fix.js +11 -0
- package/lib/parser/visitors/clause/from/fixture/limit-offset-fix.js +12 -0
- package/lib/parser/visitors/clause/from/fixture/limit-offset.sql +1 -0
- package/lib/parser/visitors/clause/from/fixture/limit.sql +1 -0
- package/lib/parser/visitors/clause/from/fixture/order-by-desc-fix.js +13 -0
- package/lib/parser/visitors/clause/from/fixture/order-by-desc.sql +1 -0
- package/lib/parser/visitors/clause/from/fixture/order-by-fix.js +11 -0
- package/lib/parser/visitors/clause/from/fixture/order-by-multi-fix.js +14 -0
- package/lib/parser/visitors/clause/from/fixture/order-by-multi.sql +1 -0
- package/lib/parser/visitors/clause/from/fixture/order-by.sql +1 -0
- package/lib/parser/visitors/clause/from/fixture/unnest-fix.js +10 -0
- package/lib/parser/visitors/clause/from/fixture/unnest.sql +1 -0
- package/lib/parser/visitors/clause/from/from.js +37 -1
- package/lib/parser/visitors/clause/from/group-by.js +6 -0
- package/lib/parser/visitors/clause/from/having.js +8 -0
- package/lib/parser/visitors/clause/from/limit.js +18 -0
- package/lib/parser/visitors/clause/from/order-by.js +20 -0
- package/lib/parser/visitors/clause/from/table-func.js +28 -0
- package/lib/parser/visitors/clause/index.js +12 -1
- package/lib/parser/visitors/clause/operand.js +14 -0
- package/lib/parser/visitors/clause/select/fixture/select-abs-fix.js +8 -0
- package/lib/parser/visitors/clause/select/fixture/select-abs.sql +1 -0
- package/lib/parser/visitors/clause/select/fixture/select-avg-fix.js +10 -0
- package/lib/parser/visitors/clause/select/fixture/select-avg.sql +1 -0
- package/lib/parser/visitors/clause/select/fixture/select-count-col-fix.js +10 -0
- package/lib/parser/visitors/clause/select/fixture/select-count-col.sql +1 -0
- package/lib/parser/visitors/clause/select/fixture/select-distinct-fix.js +10 -0
- package/lib/parser/visitors/clause/select/fixture/select-distinct-multi-fix.js +11 -0
- package/lib/parser/visitors/clause/select/fixture/select-distinct-multi.sql +1 -0
- package/lib/parser/visitors/clause/select/fixture/select-distinct.sql +1 -0
- package/lib/parser/visitors/clause/select/fixture/select-min-max-fix.js +13 -0
- package/lib/parser/visitors/clause/select/fixture/select-min-max.sql +1 -0
- package/lib/parser/visitors/clause/select/fixture/select-sum-fix.js +10 -0
- package/lib/parser/visitors/clause/select/fixture/select-sum.sql +1 -0
- package/lib/parser/visitors/clause/select/select.js +47 -2
- package/lib/parser/visitors/clause/union/fixture/union-all-fix.js +10 -0
- package/lib/parser/visitors/clause/union/fixture/union-all.sql +1 -0
- package/lib/parser/visitors/clause/union/union.js +11 -0
- package/lib/parser/visitors/clause/update/fixture/update-where-not-in-fix.js +16 -0
- package/lib/parser/visitors/clause/update/fixture/update-where-not-in.sql +1 -0
- package/lib/parser/visitors/clause/where/fixture/where-between-fix.js +15 -0
- package/lib/parser/visitors/clause/where/fixture/where-between.sql +1 -0
- package/lib/parser/visitors/clause/where/fixture/where-not-in-fix.js +16 -0
- package/lib/parser/visitors/clause/where/fixture/where-not-in.sql +1 -0
- package/lib/parser/visitors/clause/where/where.js +19 -1
- package/lib/parser/visitors/clause/with-named/fixture/with-named-select-fix.js +19 -0
- package/lib/parser/visitors/clause/with-named/fixture/with-named-select.sql +1 -0
- package/lib/parser/visitors/clause/with-named/fixture/with-recursive-fix.js +27 -0
- package/lib/parser/visitors/clause/with-named/fixture/with-recursive-multi-fix.js +38 -0
- package/lib/parser/visitors/clause/with-named/fixture/with-recursive-multi.sql +1 -0
- package/lib/parser/visitors/clause/with-named/fixture/with-recursive-no-columns-fix.js +20 -0
- package/lib/parser/visitors/clause/with-named/fixture/with-recursive-no-columns.sql +1 -0
- package/lib/parser/visitors/clause/with-named/fixture/with-recursive.sql +1 -0
- package/lib/parser/visitors/clause/with-named/with-named.js +15 -2
- package/lib/printer/visitors/call-expression/clauses/avg/avg.js +5 -0
- package/lib/printer/visitors/call-expression/clauses/avg/fixture/avg-fix.sql +2 -0
- package/lib/printer/visitors/call-expression/clauses/avg/fixture/avg.js +1 -0
- package/lib/printer/visitors/call-expression/clauses/between/between.js +9 -0
- package/lib/printer/visitors/call-expression/clauses/between/fixture/between-fix.sql +3 -0
- package/lib/printer/visitors/call-expression/clauses/between/fixture/between.js +3 -0
- package/lib/printer/visitors/call-expression/clauses/clauses.js +28 -0
- package/lib/printer/visitors/call-expression/clauses/desc/desc.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/desc/fixture/desc-fix.sql +3 -0
- package/lib/printer/visitors/call-expression/clauses/desc/fixture/desc.js +13 -0
- package/lib/printer/visitors/call-expression/clauses/distinct/distinct.js +12 -0
- package/lib/printer/visitors/call-expression/clauses/distinct/fixture/distinct-fix.sql +2 -0
- package/lib/printer/visitors/call-expression/clauses/distinct/fixture/distinct-multi-fix.sql +2 -0
- package/lib/printer/visitors/call-expression/clauses/distinct/fixture/distinct-multi.js +11 -0
- package/lib/printer/visitors/call-expression/clauses/distinct/fixture/distinct.js +10 -0
- package/lib/printer/visitors/call-expression/clauses/from/fixture/generate-series-fix.sql +2 -0
- package/lib/printer/visitors/call-expression/clauses/from/fixture/generate-series.js +3 -0
- package/lib/printer/visitors/call-expression/clauses/from/fixture/group-by-having-fix.sql +5 -0
- package/lib/printer/visitors/call-expression/clauses/from/fixture/group-by-having.js +22 -0
- package/lib/printer/visitors/call-expression/clauses/from/from.js +58 -11
- package/lib/printer/visitors/call-expression/clauses/group-by/fixture/group-by-fix.sql +3 -0
- package/lib/printer/visitors/call-expression/clauses/group-by/fixture/group-by-multi-fix.sql +3 -0
- package/lib/printer/visitors/call-expression/clauses/group-by/fixture/group-by-multi.js +13 -0
- package/lib/printer/visitors/call-expression/clauses/group-by/fixture/group-by-sum-fix.sql +4 -0
- package/lib/printer/visitors/call-expression/clauses/group-by/fixture/group-by-sum.js +19 -0
- package/lib/printer/visitors/call-expression/clauses/group-by/fixture/group-by.js +14 -0
- package/lib/printer/visitors/call-expression/clauses/group-by/group-by.js +12 -0
- package/lib/printer/visitors/call-expression/clauses/having/fixture/having-fix.sql +3 -0
- package/lib/printer/visitors/call-expression/clauses/having/fixture/having.js +16 -0
- package/lib/printer/visitors/call-expression/clauses/having/having.js +4 -0
- package/lib/printer/visitors/call-expression/clauses/insert/insert.js +1 -1
- package/lib/printer/visitors/call-expression/clauses/join/join.js +6 -4
- package/lib/printer/visitors/call-expression/clauses/limit/fixture/limit-fix.sql +3 -0
- package/lib/printer/visitors/call-expression/clauses/limit/fixture/limit-offset-fix.sql +4 -0
- package/lib/printer/visitors/call-expression/clauses/limit/fixture/limit-offset.js +12 -0
- package/lib/printer/visitors/call-expression/clauses/limit/fixture/limit.js +11 -0
- package/lib/printer/visitors/call-expression/clauses/limit/limit.js +12 -0
- package/lib/printer/visitors/call-expression/clauses/max/fixture/max-fix.sql +2 -0
- package/lib/printer/visitors/call-expression/clauses/max/fixture/max.js +1 -0
- package/lib/printer/visitors/call-expression/clauses/max/max.js +5 -0
- package/lib/printer/visitors/call-expression/clauses/min/fixture/min-fix.sql +2 -0
- package/lib/printer/visitors/call-expression/clauses/min/fixture/min.js +1 -0
- package/lib/printer/visitors/call-expression/clauses/min/min.js +5 -0
- package/lib/printer/visitors/call-expression/clauses/not-in-list/fixture/not-in-list-fix.sql +3 -0
- package/lib/printer/visitors/call-expression/clauses/not-in-list/fixture/not-in-list.js +3 -0
- package/lib/printer/visitors/call-expression/clauses/not-in-list/not-in-list.js +15 -0
- package/lib/printer/visitors/call-expression/clauses/order-by/fixture/order-by-fix.sql +3 -0
- package/lib/printer/visitors/call-expression/clauses/order-by/fixture/order-by-multi-fix.sql +3 -0
- package/lib/printer/visitors/call-expression/clauses/order-by/fixture/order-by-multi.js +14 -0
- package/lib/printer/visitors/call-expression/clauses/order-by/fixture/order-by.js +11 -0
- package/lib/printer/visitors/call-expression/clauses/order-by/order-by.js +12 -0
- package/lib/printer/visitors/call-expression/clauses/returning/returning.js +5 -3
- package/lib/printer/visitors/call-expression/clauses/select/select.js +10 -9
- package/lib/printer/visitors/call-expression/clauses/sum/fixture/sum-fix.sql +2 -0
- package/lib/printer/visitors/call-expression/clauses/sum/fixture/sum.js +1 -0
- package/lib/printer/visitors/call-expression/clauses/sum/sum.js +5 -0
- package/lib/printer/visitors/call-expression/clauses/union-all/fixture/union-all-fix.sql +3 -0
- package/lib/printer/visitors/call-expression/clauses/union-all/fixture/union-all.js +1 -0
- package/lib/printer/visitors/call-expression/clauses/union-all/union-all.js +9 -0
- package/lib/printer/visitors/call-expression/clauses/with-named/fixture/with-named-insert-fix.sql +3 -3
- package/lib/printer/visitors/call-expression/clauses/with-named/fixture/with-named-select-fix.sql +8 -0
- package/lib/printer/visitors/call-expression/clauses/with-named/fixture/with-named-select.js +19 -0
- package/lib/printer/visitors/call-expression/clauses/with-named/fixture/withNamed-fix.sql +3 -3
- package/lib/printer/visitors/call-expression/clauses/with-recursive/fixture/with-recursive-fix.sql +10 -0
- package/lib/printer/visitors/call-expression/clauses/with-recursive/fixture/with-recursive-multi-fix.sql +14 -0
- package/lib/printer/visitors/call-expression/clauses/with-recursive/fixture/with-recursive-multi.js +38 -0
- package/lib/printer/visitors/call-expression/clauses/with-recursive/fixture/with-recursive-no-columns-fix.sql +8 -0
- package/lib/printer/visitors/call-expression/clauses/with-recursive/fixture/with-recursive-no-columns.js +20 -0
- package/lib/printer/visitors/call-expression/clauses/with-recursive/fixture/with-recursive.js +27 -0
- package/lib/printer/visitors/call-expression/clauses/with-recursive/with-recursive.js +57 -0
- package/package.json +2 -1
|
@@ -11,6 +11,8 @@ const {
|
|
|
11
11
|
tsLiteralType,
|
|
12
12
|
callExpression,
|
|
13
13
|
memberExpression,
|
|
14
|
+
numericLiteral,
|
|
15
|
+
binaryExpression,
|
|
14
16
|
} = types;
|
|
15
17
|
|
|
16
18
|
const convertColumn = (column) => {
|
|
@@ -32,16 +34,44 @@ const convertColumn = (column) => {
|
|
|
32
34
|
if (column.type === 'parameter')
|
|
33
35
|
return stringLiteral(column.text);
|
|
34
36
|
|
|
37
|
+
if (column.type === 'number_literal')
|
|
38
|
+
return numericLiteral(column.value);
|
|
39
|
+
|
|
40
|
+
if (column.type === 'binary_expr')
|
|
41
|
+
return binaryExpression(
|
|
42
|
+
column.operator,
|
|
43
|
+
convertOperand(column.left),
|
|
44
|
+
convertOperand(column.right),
|
|
45
|
+
);
|
|
46
|
+
|
|
35
47
|
return identifier(column.name);
|
|
36
48
|
};
|
|
37
49
|
|
|
50
|
+
const AGGREGATE_NAMES = new Set([
|
|
51
|
+
'sum',
|
|
52
|
+
'avg',
|
|
53
|
+
'min',
|
|
54
|
+
'max',
|
|
55
|
+
]);
|
|
56
|
+
|
|
38
57
|
const convertFuncCall = (column) => {
|
|
39
58
|
const {name} = column.name;
|
|
59
|
+
const lower = name.toLowerCase();
|
|
40
60
|
|
|
41
61
|
if (name === 'last_insert_rowid')
|
|
42
62
|
return callExpression(identifier('lastInsertRowid'), []);
|
|
43
63
|
|
|
44
|
-
|
|
64
|
+
if (name === 'lastval')
|
|
65
|
+
return callExpression(identifier('lastval'), []);
|
|
66
|
+
|
|
67
|
+
if (AGGREGATE_NAMES.has(lower)) {
|
|
68
|
+
const {items} = column.args.expr.args;
|
|
69
|
+
const args = items.map(convertOperand);
|
|
70
|
+
|
|
71
|
+
return callExpression(identifier(lower), args);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return callExpression(identifier(name), []);
|
|
45
75
|
};
|
|
46
76
|
|
|
47
77
|
const convertColumns = (columns) => {
|
|
@@ -53,16 +83,31 @@ const convertColumns = (columns) => {
|
|
|
53
83
|
return columns.items.map(convertColumn);
|
|
54
84
|
};
|
|
55
85
|
|
|
86
|
+
const isDistinct = (selectClause) => selectClause.modifiers.some(({type}) => type === 'select_distinct');
|
|
87
|
+
|
|
56
88
|
export const convertSelect = ({clauses}) => {
|
|
57
89
|
const selectClause = findClause(clauses, 'select_clause');
|
|
58
90
|
const fromClause = findClause(clauses, 'from_clause');
|
|
59
91
|
const whereClause = findClause(clauses, 'where_clause');
|
|
92
|
+
const groupByClause = findClause(clauses, 'group_by_clause');
|
|
93
|
+
const havingClause = findClause(clauses, 'having_clause');
|
|
94
|
+
const orderByClause = findClause(clauses, 'order_by_clause');
|
|
95
|
+
const limitClause = findClause(clauses, 'limit_clause');
|
|
96
|
+
|
|
97
|
+
const cols = convertColumns(selectClause.columns);
|
|
98
|
+
const selectArgs = isDistinct(selectClause) ? [
|
|
99
|
+
callExpression(identifier('distinct'), cols),
|
|
100
|
+
] : cols;
|
|
60
101
|
|
|
61
102
|
const args = [
|
|
62
|
-
...
|
|
103
|
+
...selectArgs,
|
|
63
104
|
fromClause && convertFrom({
|
|
64
105
|
expr: fromClause.expr,
|
|
65
106
|
whereClause,
|
|
107
|
+
groupByClause,
|
|
108
|
+
havingClause,
|
|
109
|
+
orderByClause,
|
|
110
|
+
limitClause,
|
|
66
111
|
}),
|
|
67
112
|
].filter(Boolean);
|
|
68
113
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
SELECT 1 UNION ALL SELECT 2
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {types} from '@putout/babel';
|
|
2
|
+
import {convertClause} from '#parser/clause';
|
|
3
|
+
|
|
4
|
+
const {callExpression, identifier} = types;
|
|
5
|
+
|
|
6
|
+
export const convertUnionAll = (stmt) => {
|
|
7
|
+
return callExpression(identifier('unionAll'), [
|
|
8
|
+
convertClause(stmt.left),
|
|
9
|
+
convertClause(stmt.right),
|
|
10
|
+
]);
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
UPDATE t SET x = 1 WHERE y NOT IN (1, 2, 3)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
SELECT * FROM users WHERE age BETWEEN 18 AND 65
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
SELECT * FROM users WHERE id NOT IN (1, 2, 3)
|
|
@@ -34,6 +34,12 @@ const SQL_TO_JS_OP = {
|
|
|
34
34
|
const convertAnd = (node) => logicalExpression('&&', convertCondition(node.left), convertCondition(node.right));
|
|
35
35
|
const convertOr = (node) => logicalExpression('||', convertCondition(node.left), convertCondition(node.right));
|
|
36
36
|
|
|
37
|
+
export const convertBetween = (node) => callExpression(identifier('between'), [
|
|
38
|
+
convertOperand(node.left),
|
|
39
|
+
convertOperand(node.begin),
|
|
40
|
+
convertOperand(node.end),
|
|
41
|
+
]);
|
|
42
|
+
|
|
37
43
|
const convertBinary = (node) => {
|
|
38
44
|
const op = opName(node.operator);
|
|
39
45
|
|
|
@@ -62,6 +68,15 @@ const convertBinary = (node) => {
|
|
|
62
68
|
]);
|
|
63
69
|
}
|
|
64
70
|
|
|
71
|
+
if (op === 'NOT IN') {
|
|
72
|
+
const items = node.right.expr.items.map(convertOperand);
|
|
73
|
+
|
|
74
|
+
return callExpression(identifier('notInList'), [
|
|
75
|
+
convertOperand(node.left),
|
|
76
|
+
...items,
|
|
77
|
+
]);
|
|
78
|
+
}
|
|
79
|
+
|
|
65
80
|
const jsOp = SQL_TO_JS_OP[op] ?? '===';
|
|
66
81
|
|
|
67
82
|
return binaryExpression(
|
|
@@ -71,13 +86,16 @@ const convertBinary = (node) => {
|
|
|
71
86
|
);
|
|
72
87
|
};
|
|
73
88
|
|
|
74
|
-
const convertCondition = (node) => {
|
|
89
|
+
export const convertCondition = (node) => {
|
|
75
90
|
if (node.operator?.name === 'AND')
|
|
76
91
|
return convertAnd(node);
|
|
77
92
|
|
|
78
93
|
if (node.operator?.name === 'OR')
|
|
79
94
|
return convertOr(node);
|
|
80
95
|
|
|
96
|
+
if (node.type === 'between_expr')
|
|
97
|
+
return convertBetween(node);
|
|
98
|
+
|
|
81
99
|
return convertBinary(node);
|
|
82
100
|
};
|
|
83
101
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
WITH recent AS (SELECT id FROM users WHERE kind = 'const') SELECT id FROM recent
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[
|
|
2
|
+
withRecursive(
|
|
3
|
+
numbers(
|
|
4
|
+
'value',
|
|
5
|
+
unionAll(
|
|
6
|
+
select(
|
|
7
|
+
1,
|
|
8
|
+
),
|
|
9
|
+
select(
|
|
10
|
+
value + 1,
|
|
11
|
+
from(
|
|
12
|
+
numbers,
|
|
13
|
+
where(
|
|
14
|
+
value < 10,
|
|
15
|
+
),
|
|
16
|
+
),
|
|
17
|
+
),
|
|
18
|
+
),
|
|
19
|
+
),
|
|
20
|
+
select(
|
|
21
|
+
value,
|
|
22
|
+
from(
|
|
23
|
+
numbers,
|
|
24
|
+
),
|
|
25
|
+
),
|
|
26
|
+
),
|
|
27
|
+
];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[
|
|
2
|
+
withRecursive(
|
|
3
|
+
t(
|
|
4
|
+
unionAll(
|
|
5
|
+
select(
|
|
6
|
+
1,
|
|
7
|
+
),
|
|
8
|
+
select(
|
|
9
|
+
2,
|
|
10
|
+
),
|
|
11
|
+
),
|
|
12
|
+
),
|
|
13
|
+
u(
|
|
14
|
+
'a',
|
|
15
|
+
'b',
|
|
16
|
+
unionAll(
|
|
17
|
+
select(
|
|
18
|
+
1,
|
|
19
|
+
2,
|
|
20
|
+
),
|
|
21
|
+
select(
|
|
22
|
+
a,
|
|
23
|
+
b,
|
|
24
|
+
from(
|
|
25
|
+
t,
|
|
26
|
+
),
|
|
27
|
+
),
|
|
28
|
+
),
|
|
29
|
+
),
|
|
30
|
+
select(
|
|
31
|
+
a,
|
|
32
|
+
b,
|
|
33
|
+
from(
|
|
34
|
+
u,
|
|
35
|
+
),
|
|
36
|
+
),
|
|
37
|
+
),
|
|
38
|
+
];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
WITH RECURSIVE t AS (SELECT 1 UNION ALL SELECT 2), u(a, b) AS (SELECT 1, 2 UNION ALL SELECT a, b FROM t) SELECT a, b FROM u
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
WITH RECURSIVE t AS (SELECT 1 UNION ALL SELECT 2) SELECT * FROM t
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
WITH RECURSIVE numbers(value) AS (SELECT 1 UNION ALL SELECT value + 1 FROM numbers WHERE value < 10) SELECT value FROM numbers
|
|
@@ -6,6 +6,7 @@ const {
|
|
|
6
6
|
identifier,
|
|
7
7
|
assignmentExpression,
|
|
8
8
|
callExpression,
|
|
9
|
+
stringLiteral,
|
|
9
10
|
} = types;
|
|
10
11
|
|
|
11
12
|
const isWithClause = (clause) => clause.type !== 'with_clause';
|
|
@@ -14,18 +15,30 @@ const convertTable = ({table, expr}) => {
|
|
|
14
15
|
return assignmentExpression('=', identifier(table.name), convertClause(expr.expr));
|
|
15
16
|
};
|
|
16
17
|
|
|
18
|
+
// recursive CTE: numbers('value', unionAll(...))
|
|
19
|
+
const convertRecursiveTable = ({table, columns, expr}) => {
|
|
20
|
+
const colArgs = columns ? columns.expr.items.map((column) => stringLiteral(column.name)) : [];
|
|
21
|
+
const body = convertClause(expr.expr);
|
|
22
|
+
|
|
23
|
+
return callExpression(identifier(table.name), [...colArgs, body]);
|
|
24
|
+
};
|
|
25
|
+
|
|
17
26
|
export const convertWithNamed = (stmt) => {
|
|
18
27
|
const withClause = findClause(stmt.clauses, 'with_clause');
|
|
28
|
+
const isRecursive = Boolean(withClause.recursiveKw);
|
|
29
|
+
const fnName = isRecursive ? 'withRecursive' : 'withNamed';
|
|
19
30
|
|
|
20
31
|
const finalStatement = convertClause({
|
|
21
32
|
...stmt,
|
|
22
33
|
clauses: stmt.clauses.filter(isWithClause),
|
|
23
34
|
});
|
|
24
35
|
|
|
36
|
+
const convertCte = isRecursive ? convertRecursiveTable : convertTable;
|
|
37
|
+
|
|
25
38
|
const args = [
|
|
26
|
-
...withClause.tables.items.map(
|
|
39
|
+
...withClause.tables.items.map(convertCte),
|
|
27
40
|
finalStatement,
|
|
28
41
|
];
|
|
29
42
|
|
|
30
|
-
return callExpression(identifier(
|
|
43
|
+
return callExpression(identifier(fnName), args);
|
|
31
44
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
select(avg(score), from(results));
|
|
@@ -14,6 +14,20 @@ import {section} from './section/section.js';
|
|
|
14
14
|
import {count} from './count/count.js';
|
|
15
15
|
import {returning} from './returning/returning.js';
|
|
16
16
|
import {withNamed} from './with-named/with-named.js';
|
|
17
|
+
import {withRecursive} from './with-recursive/with-recursive.js';
|
|
18
|
+
import {unionAll} from './union-all/union-all.js';
|
|
19
|
+
import {groupBy} from './group-by/group-by.js';
|
|
20
|
+
import {having} from './having/having.js';
|
|
21
|
+
import {sum} from './sum/sum.js';
|
|
22
|
+
import {avg} from './avg/avg.js';
|
|
23
|
+
import {min} from './min/min.js';
|
|
24
|
+
import {max} from './max/max.js';
|
|
25
|
+
import {orderBy} from './order-by/order-by.js';
|
|
26
|
+
import {desc} from './desc/desc.js';
|
|
27
|
+
import {limit} from './limit/limit.js';
|
|
28
|
+
import {distinct} from './distinct/distinct.js';
|
|
29
|
+
import {notInList} from './not-in-list/not-in-list.js';
|
|
30
|
+
import {between} from './between/between.js';
|
|
17
31
|
import {createTable} from './create-table/create-table.js';
|
|
18
32
|
import {createSequence} from './create-sequence/create-sequence.js';
|
|
19
33
|
import {column} from './column/column.js';
|
|
@@ -48,6 +62,20 @@ export const clauses = {
|
|
|
48
62
|
section,
|
|
49
63
|
returning,
|
|
50
64
|
withNamed,
|
|
65
|
+
withRecursive,
|
|
66
|
+
unionAll,
|
|
67
|
+
groupBy,
|
|
68
|
+
having,
|
|
69
|
+
sum,
|
|
70
|
+
avg,
|
|
71
|
+
min,
|
|
72
|
+
max,
|
|
73
|
+
orderBy,
|
|
74
|
+
desc,
|
|
75
|
+
limit,
|
|
76
|
+
distinct,
|
|
77
|
+
notInList,
|
|
78
|
+
between,
|
|
51
79
|
createTable,
|
|
52
80
|
createSequence,
|
|
53
81
|
column,
|
|
@@ -1,24 +1,70 @@
|
|
|
1
1
|
import {types} from '@putout/babel';
|
|
2
2
|
|
|
3
|
-
const {
|
|
3
|
+
const {
|
|
4
|
+
isTSAsExpression,
|
|
5
|
+
isCallExpression,
|
|
6
|
+
} = types;
|
|
4
7
|
|
|
5
8
|
const printAsExpression = (path, {write, traverse}) => {
|
|
6
9
|
traverse(path.get('expression'));
|
|
7
10
|
write(` AS ${path.node.typeAnnotation.literal.value}`);
|
|
8
11
|
};
|
|
9
12
|
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
const CLAUSE_NAMES = [
|
|
14
|
+
'where',
|
|
15
|
+
'groupBy',
|
|
16
|
+
'having',
|
|
17
|
+
'orderBy',
|
|
18
|
+
'limit',
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
const TABLE_ARG_NAMES = [
|
|
22
|
+
...CLAUSE_NAMES,
|
|
23
|
+
'join',
|
|
24
|
+
'on',
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const isClause = ({node}) => node.type === 'CallExpression' && CLAUSE_NAMES.includes(node.callee?.name);
|
|
28
|
+
|
|
29
|
+
const CAMEL_RE = /([A-Z])/g;
|
|
30
|
+
const toSnake = (a) => a.replace(CAMEL_RE, (_, c) => `_${c.toLowerCase()}`);
|
|
31
|
+
|
|
32
|
+
const isTableFunc = (node) => isCallExpression(node) && !TABLE_ARG_NAMES.includes(node.callee.name);
|
|
33
|
+
|
|
34
|
+
const printTableFunc = (path, {write, traverse}) => {
|
|
35
|
+
const {name} = path.node.callee;
|
|
36
|
+
const args = path.get('arguments');
|
|
13
37
|
|
|
14
|
-
|
|
38
|
+
write(toSnake(name));
|
|
39
|
+
write('(');
|
|
40
|
+
|
|
41
|
+
for (const [i, arg] of args.entries()) {
|
|
42
|
+
if (i > 0)
|
|
43
|
+
write(', ');
|
|
44
|
+
|
|
45
|
+
traverse(arg);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
write(')');
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const printArg = (path, printer) => {
|
|
52
|
+
const {node} = path;
|
|
53
|
+
const {traverse} = printer;
|
|
54
|
+
|
|
55
|
+
if (isTSAsExpression(node))
|
|
56
|
+
return printAsExpression(path, printer);
|
|
57
|
+
|
|
58
|
+
if (isTableFunc(node))
|
|
59
|
+
return printTableFunc(path, printer);
|
|
60
|
+
|
|
61
|
+
traverse(path);
|
|
15
62
|
};
|
|
16
63
|
|
|
17
64
|
export const from = (path, {write, traverse}) => {
|
|
18
65
|
const args = path.get('arguments');
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const tableArgs = hasWhere ? args.slice(0, -1) : args;
|
|
66
|
+
const tableArgs = args.filter((arg) => !isClause(arg));
|
|
67
|
+
const clauseArgs = args.filter(isClause);
|
|
22
68
|
|
|
23
69
|
write('FROM ');
|
|
24
70
|
printArg(tableArgs[0], {
|
|
@@ -32,8 +78,9 @@ export const from = (path, {write, traverse}) => {
|
|
|
32
78
|
traverse,
|
|
33
79
|
});
|
|
34
80
|
|
|
35
|
-
|
|
36
|
-
write.
|
|
37
|
-
traverse(
|
|
81
|
+
for (const clause of clauseArgs) {
|
|
82
|
+
write.breakline();
|
|
83
|
+
traverse(clause);
|
|
38
84
|
}
|
|
39
85
|
};
|
|
86
|
+
|