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
package/ChangeLog
CHANGED
|
@@ -1,3 +1,63 @@
|
|
|
1
|
+
2026.08.27, v2.4.0
|
|
2
|
+
|
|
3
|
+
fix:
|
|
4
|
+
- 044050d nextval: scope DEFAULT nextval conversion to column defaults
|
|
5
|
+
- 6f9d707 from: rightOuterJoin missing from printer imports
|
|
6
|
+
- ba06223 over: window frame ROWS BETWEEN support
|
|
7
|
+
- 6c35624 create-table: TEMP keyword and WITHOUT ROWID
|
|
8
|
+
- 038cac6 references: ON DELETE and ON UPDATE actions
|
|
9
|
+
- 6cd9a75 drop-view: IF EXISTS support
|
|
10
|
+
- d5bd976 create-index: column sort order and index method
|
|
11
|
+
- 1a6dc5f over: window frame ROWS BETWEEN support
|
|
12
|
+
- e8c9ba6 column-definition: GENERATED ALWAYS AS expression
|
|
13
|
+
- dbaea87 count: preserve DISTINCT modifier
|
|
14
|
+
- 5d9ce53 like: ESCAPE clause support
|
|
15
|
+
- e8322bc analyze: qualified table names
|
|
16
|
+
- d0446af update: SQLite OR ABORT and OR FAIL
|
|
17
|
+
- 1ffd47d order-by: ordinals and NULLS FIRST/LAST
|
|
18
|
+
- 48c9aed alter-table: rename table, add constraint, RLS actions
|
|
19
|
+
- 297b46a create-table: table-level primary key and unique constraints
|
|
20
|
+
- 8f3d71f insert: optional column list, DEFAULT VALUES, table alias
|
|
21
|
+
- 1609515 from: JOIN USING support
|
|
22
|
+
- 4c0bc85 pragma: support get/set/qualified/string forms
|
|
23
|
+
- 3ed2c4f select: support full expression set in select columns
|
|
24
|
+
- 44bf5d7 happy-sql: from: UNNEST and func_call alias support
|
|
25
|
+
- fedfc86 happy-sql: ANALYZE and REINDEX preserve table name
|
|
26
|
+
- fbb7ce6 from: SQLite INDEXED BY and NOT INDEXED table hints
|
|
27
|
+
- 923c7bb vacuum: VACUUM INTO file support
|
|
28
|
+
- d00c4d2 update: SQLite OR REPLACE and OR IGNORE
|
|
29
|
+
- 196eae8 drop-index: IF EXISTS support
|
|
30
|
+
- 0cf9caf create-index: IF NOT EXISTS, CONCURRENTLY, WHERE partial index
|
|
31
|
+
- 15cf3bb with-named: remove extra indentation from CTE body
|
|
32
|
+
- 018e921 lateral-join: alias without AS for subquery
|
|
33
|
+
- e3f4ae8 detach database statement
|
|
34
|
+
- c070d03 window: named WINDOW clause
|
|
35
|
+
- 9792a5e from: subquery alias without AS keyword
|
|
36
|
+
- 4868889 where: ISNULL/NOTNULL postfix
|
|
37
|
+
- 3bea77a create-table: AS SELECT form
|
|
38
|
+
- d5ff74b values: standalone VALUES statement
|
|
39
|
+
- 6f27346 truncate: add statement
|
|
40
|
+
- 5a07d99 select: DISTINCT ON
|
|
41
|
+
- 964f8e6 func-call: FILTER (WHERE ...)
|
|
42
|
+
- 407ff5e binary-expression: || concat
|
|
43
|
+
- ed2b211 operand: :: cast_operator_expr
|
|
44
|
+
- b08cc9f binary-expression: ?? → ?
|
|
45
|
+
|
|
46
|
+
feature:
|
|
47
|
+
- 3fff1e3 happy-sql: putout_processor_sql
|
|
48
|
+
- 97f890f USING
|
|
49
|
+
- 8ccaa46 RIGHT OUTER JOIN
|
|
50
|
+
- 29a5510 happy-sql: DO block
|
|
51
|
+
- a18ac59 reindex, analyze, release-savepoint: add trivial statement types
|
|
52
|
+
- f0fef07 create-virtual-table: SQLite CREATE VIRTUAL TABLE USING
|
|
53
|
+
- dfe2b2c grant: GRANT privilege ON table TO role
|
|
54
|
+
- 2a29916 create-schema: CREATE SCHEMA
|
|
55
|
+
- f272f3b create-extension: CREATE EXTENSION
|
|
56
|
+
- cd61021 drop-view: DROP VIEW
|
|
57
|
+
- aef8f2a create-view: CREATE VIEW and CREATE MATERIALIZED VIEW
|
|
58
|
+
- d2585b8 set-param: SET and SHOW parameter statements
|
|
59
|
+
- 0e734a4 explain: EXPLAIN and EXPLAIN ANALYZE
|
|
60
|
+
|
|
1
61
|
2026.08.24, v2.3.0
|
|
2
62
|
|
|
3
63
|
fix:
|
package/bin/convert.js
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
__markdown_name,
|
|
3
|
-
fromJS,
|
|
4
|
-
} from '@putout/operator-json';
|
|
1
|
+
import {__sql_name, fromJS} from '@putout/operator-json';
|
|
5
2
|
import {convertJsToSql, convertSqlToJs} from '#happy-sql';
|
|
6
3
|
|
|
7
4
|
export function convert(source) {
|
|
8
|
-
if (source.startsWith(
|
|
9
|
-
return convertJsToSql(fromJS(
|
|
10
|
-
source,
|
|
11
|
-
__markdown_name,
|
|
12
|
-
));
|
|
5
|
+
if (source.startsWith(__sql_name))
|
|
6
|
+
return convertJsToSql(fromJS(source, __sql_name));
|
|
13
7
|
|
|
14
8
|
if (source.startsWith('['))
|
|
15
9
|
return convertJsToSql(source);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {types} from '@putout/babel';
|
|
2
2
|
import {convertColumnDefinition} from '#parser/clause/column-definition';
|
|
3
|
+
import {convertTableConstraint} from '../table-constraint.js';
|
|
3
4
|
|
|
4
5
|
const {identifier, callExpression} = types;
|
|
5
6
|
|
|
@@ -7,6 +8,22 @@ const convertAddColumn = (action) => callExpression(identifier('addColumn'), [
|
|
|
7
8
|
convertColumnDefinition(action.column),
|
|
8
9
|
]);
|
|
9
10
|
|
|
11
|
+
const convertRenameTable = (action) => callExpression(identifier('renameTable'), [
|
|
12
|
+
identifier(action.newName.name),
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
const convertAddConstraint = ({name, constraint}) => {
|
|
16
|
+
const node = convertTableConstraint(constraint);
|
|
17
|
+
|
|
18
|
+
if (!name)
|
|
19
|
+
return node;
|
|
20
|
+
|
|
21
|
+
return callExpression(identifier('constraint'), [
|
|
22
|
+
identifier(name.name.name),
|
|
23
|
+
node,
|
|
24
|
+
]);
|
|
25
|
+
};
|
|
26
|
+
|
|
10
27
|
const convertDropColumn = (action) => callExpression(identifier('dropColumn'), [
|
|
11
28
|
identifier(action.column.name),
|
|
12
29
|
]);
|
|
@@ -26,6 +43,10 @@ const ACTION_CONVERTERS = {
|
|
|
26
43
|
alter_action_drop_column: convertDropColumn,
|
|
27
44
|
alter_action_rename_column: convertRenameColumn,
|
|
28
45
|
alter_action_alter_column: convertAlterColumnType,
|
|
46
|
+
alter_action_rename: convertRenameTable,
|
|
47
|
+
alter_action_add_constraint: convertAddConstraint,
|
|
48
|
+
alter_action_enable: () => callExpression(identifier('enableRowLevelSecurity'), []),
|
|
49
|
+
alter_action_disable: () => callExpression(identifier('disableRowLevelSecurity'), []),
|
|
29
50
|
};
|
|
30
51
|
|
|
31
52
|
export const convertAlterTable = ({table, actions}) => {
|
|
@@ -31,10 +31,20 @@ export const opName = (op) => {
|
|
|
31
31
|
return op.name;
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
const isEscape = (node) => node?.type === 'binary_expr' && opName(node.operator) === 'ESCAPE';
|
|
35
|
+
|
|
36
|
+
const convertLike = (node) => {
|
|
37
|
+
const args = [
|
|
38
|
+
convertOperand(node.left),
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
if (isEscape(node.right))
|
|
42
|
+
args.push(convertOperand(node.right.left), convertOperand(node.right.right));
|
|
43
|
+
else
|
|
44
|
+
args.push(convertOperand(node.right));
|
|
45
|
+
|
|
46
|
+
return callExpression(identifier('like'), args);
|
|
47
|
+
};
|
|
38
48
|
|
|
39
49
|
const convertNotLike = (node) => callExpression(identifier('notLike'), [
|
|
40
50
|
convertOperand(node.left),
|
|
@@ -56,9 +66,16 @@ const convertIsDistinctFrom = (node) => callExpression(identifier('isDistinctFro
|
|
|
56
66
|
convertOperand(node.right),
|
|
57
67
|
]);
|
|
58
68
|
|
|
69
|
+
const convertConcatOperand = (node) => {
|
|
70
|
+
if (node.operator && opName(node.operator) === '||')
|
|
71
|
+
return convertConcat(node);
|
|
72
|
+
|
|
73
|
+
return convertOperand(node);
|
|
74
|
+
};
|
|
75
|
+
|
|
59
76
|
const convertConcat = (node) => callExpression(identifier('concat'), [
|
|
60
|
-
|
|
61
|
-
|
|
77
|
+
convertConcatOperand(node.left),
|
|
78
|
+
convertConcatOperand(node.right),
|
|
62
79
|
]);
|
|
63
80
|
|
|
64
81
|
const convertJsonTuple = (op) => (node) => arrayExpression([
|
|
@@ -67,6 +84,11 @@ const convertJsonTuple = (op) => (node) => arrayExpression([
|
|
|
67
84
|
convertOperand(node.right),
|
|
68
85
|
]);
|
|
69
86
|
|
|
87
|
+
const convertCollate = (node) => callExpression(identifier('collate'), [
|
|
88
|
+
convertOperand(node.left),
|
|
89
|
+
convertOperand(node.right),
|
|
90
|
+
]);
|
|
91
|
+
|
|
70
92
|
const convertIsNull = (node) => callExpression(identifier('isNull'), [
|
|
71
93
|
convertOperand(node.left),
|
|
72
94
|
]);
|
|
@@ -118,6 +140,7 @@ const OP_CONVERTERS = {
|
|
|
118
140
|
'?': convertJsonTuple('?'),
|
|
119
141
|
'?|': convertJsonTuple('?|'),
|
|
120
142
|
'?&': convertJsonTuple('?&'),
|
|
143
|
+
'??': convertJsonTuple('??'),
|
|
121
144
|
'@>': convertJsonTuple('@>'),
|
|
122
145
|
'<@': convertJsonTuple('<@'),
|
|
123
146
|
'||': convertConcat,
|
|
@@ -125,6 +148,7 @@ const OP_CONVERTERS = {
|
|
|
125
148
|
'IS NOT': convertIsNotNull,
|
|
126
149
|
'IN': convertIn,
|
|
127
150
|
'NOT IN': convertNotIn,
|
|
151
|
+
'COLLATE': convertCollate,
|
|
128
152
|
};
|
|
129
153
|
|
|
130
154
|
export const SQL_TO_JS_OP = {
|
|
@@ -31,14 +31,25 @@ const convertGenerated = (constraint) => {
|
|
|
31
31
|
return callExpression(identifier('identity'), []);
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
+
const isGeneratedExpr = ({expr}) => expr?.type === 'paren_expr';
|
|
35
|
+
|
|
36
|
+
const convertGeneratedExpr = (constraint) => callExpression(identifier('generatedAlwaysAs'), [
|
|
37
|
+
convertBinary(constraint.expr.expr),
|
|
38
|
+
booleanLiteral(constraint.storageKw?.name === 'STORED'),
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
const convertDefaultNextval = (expr) => {
|
|
42
|
+
const [seq] = expr.args.expr.args.items;
|
|
43
|
+
const seqName = seq.value ?? seq.name;
|
|
44
|
+
|
|
45
|
+
return callExpression(identifier('defaultNextval'), [
|
|
46
|
+
identifier(seqName),
|
|
47
|
+
]);
|
|
48
|
+
};
|
|
49
|
+
|
|
34
50
|
const convertDefault = ({expr}) => {
|
|
35
|
-
if (expr.type === 'func_call' && expr.name.name === 'nextval')
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return callExpression(identifier('nextval'), [
|
|
39
|
-
identifier(seqName),
|
|
40
|
-
]);
|
|
41
|
-
}
|
|
51
|
+
if (expr.type === 'func_call' && expr.name.name === 'nextval')
|
|
52
|
+
return convertDefaultNextval(expr);
|
|
42
53
|
|
|
43
54
|
if (expr.type === 'number_literal')
|
|
44
55
|
return callExpression(identifier('default_'), [
|
|
@@ -69,6 +80,28 @@ const convertCheck = (constraint) => callExpression(identifier('check'), [
|
|
|
69
80
|
convertBinary(constraint.expr.expr),
|
|
70
81
|
]);
|
|
71
82
|
|
|
83
|
+
const ACTION_NAMES = {
|
|
84
|
+
CASCADE: true,
|
|
85
|
+
RESTRICT: true,
|
|
86
|
+
SET_NULL: true,
|
|
87
|
+
SET_DEFAULT: true,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const convertReferentialAction = ({eventKw, actionKw}) => {
|
|
91
|
+
const event = eventKw.name === 'DELETE' ? 'onDelete' : 'onUpdate';
|
|
92
|
+
const action = Array.isArray(actionKw) ? actionKw
|
|
93
|
+
.map(({name}) => name)
|
|
94
|
+
.join(' ') : actionKw.name;
|
|
95
|
+
|
|
96
|
+
const name = ACTION_NAMES[action] ? action : action
|
|
97
|
+
.replace(/\s+/g, '_')
|
|
98
|
+
.toUpperCase();
|
|
99
|
+
|
|
100
|
+
return callExpression(identifier(event), [
|
|
101
|
+
identifier(name),
|
|
102
|
+
]);
|
|
103
|
+
};
|
|
104
|
+
|
|
72
105
|
const convertReferences = (constraint) => {
|
|
73
106
|
const refTable = identifier(constraint.table.name);
|
|
74
107
|
const cols = constraint.columns.expr.items;
|
|
@@ -77,12 +110,20 @@ const convertReferences = (constraint) => {
|
|
|
77
110
|
for (const col of cols)
|
|
78
111
|
args.push(identifier(col.name));
|
|
79
112
|
|
|
113
|
+
for (const option of constraint.options)
|
|
114
|
+
args.push(convertReferentialAction(option));
|
|
115
|
+
|
|
80
116
|
return callExpression(identifier('references'), args);
|
|
81
117
|
};
|
|
82
118
|
|
|
83
119
|
const CONSTRAINT_VISITORS = {
|
|
84
120
|
constraint_primary_key: () => callExpression(identifier('primaryKey'), []),
|
|
85
|
-
constraint_generated:
|
|
121
|
+
constraint_generated: (constraint) => {
|
|
122
|
+
if (isGeneratedExpr(constraint))
|
|
123
|
+
return convertGeneratedExpr(constraint);
|
|
124
|
+
|
|
125
|
+
return convertGenerated(constraint);
|
|
126
|
+
},
|
|
86
127
|
constraint_not_null: () => callExpression(identifier('notNull'), []),
|
|
87
128
|
constraint_default: convertDefault,
|
|
88
129
|
constraint_unique: convertUnique,
|
|
@@ -15,7 +15,8 @@ export const isCount = (column) => {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
export const convertCount = (column) => {
|
|
18
|
-
const
|
|
18
|
+
const funcArgs = column.args.expr;
|
|
19
|
+
const {items} = funcArgs.args;
|
|
19
20
|
const args = [];
|
|
20
21
|
|
|
21
22
|
for (const item of items) {
|
|
@@ -34,5 +35,7 @@ export const convertCount = (column) => {
|
|
|
34
35
|
args.push(identifier(item.name));
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
const name = funcArgs.distinctKw ? 'countDistinct' : 'count';
|
|
39
|
+
|
|
40
|
+
return callExpression(identifier(name), args);
|
|
38
41
|
};
|
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
import {types} from '@putout/babel';
|
|
2
|
+
import {convertCondition} from '#parser/clause/where';
|
|
3
|
+
import {findClause} from '#parser/clause/find';
|
|
2
4
|
|
|
3
5
|
const {identifier, callExpression} = types;
|
|
4
6
|
|
|
7
|
+
const isDesc = (item) => item.direction?.type === 'sort_direction_desc';
|
|
8
|
+
|
|
5
9
|
const convertColumns = (columns) => {
|
|
6
10
|
const {items} = columns.expr;
|
|
7
11
|
const cols = [];
|
|
8
12
|
|
|
9
|
-
for (const item of items)
|
|
10
|
-
|
|
13
|
+
for (const item of items) {
|
|
14
|
+
if (isDesc(item))
|
|
15
|
+
cols.push(callExpression(identifier('desc'), [
|
|
16
|
+
identifier(item.expr.name),
|
|
17
|
+
]));
|
|
18
|
+
else
|
|
19
|
+
cols.push(identifier(item.expr.name));
|
|
20
|
+
}
|
|
11
21
|
|
|
12
22
|
return cols;
|
|
13
23
|
};
|
|
@@ -21,9 +31,30 @@ export const convertCreateIndex = (stmt) => {
|
|
|
21
31
|
|
|
22
32
|
const isUnique = stmt.indexTypeKw && stmt.indexTypeKw.name === 'UNIQUE';
|
|
23
33
|
|
|
24
|
-
|
|
34
|
+
const args = [
|
|
25
35
|
identifier(name.name),
|
|
26
36
|
identifier(table.name),
|
|
27
|
-
|
|
28
|
-
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
if (stmt.using)
|
|
40
|
+
args.push(callExpression(identifier('accessMethod'), [
|
|
41
|
+
identifier(stmt.using.method.name),
|
|
42
|
+
]));
|
|
43
|
+
|
|
44
|
+
args.push(...convertColumns(columns));
|
|
45
|
+
|
|
46
|
+
const whereClause = findClause(stmt.clauses, 'where_clause');
|
|
47
|
+
|
|
48
|
+
if (stmt.ifNotExistsKw)
|
|
49
|
+
args.push(callExpression(identifier('ifNotExists'), []));
|
|
50
|
+
|
|
51
|
+
if (stmt.concurrentlyKw)
|
|
52
|
+
args.push(callExpression(identifier('concurrently'), []));
|
|
53
|
+
|
|
54
|
+
if (whereClause)
|
|
55
|
+
args.push(callExpression(identifier('where'), [
|
|
56
|
+
convertCondition(whereClause.expr),
|
|
57
|
+
]));
|
|
58
|
+
|
|
59
|
+
return callExpression(identifier(isUnique ? 'createUniqueIndex' : 'createIndex'), args);
|
|
29
60
|
};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {types} from '@putout/babel';
|
|
2
2
|
import {convertColumnDefinition} from '#parser/clause/column-definition';
|
|
3
|
+
import {convertClause} from '#parser/clause';
|
|
4
|
+
import {convertTableConstraint} from '../table-constraint.js';
|
|
3
5
|
|
|
4
6
|
const {
|
|
5
7
|
identifier,
|
|
@@ -7,15 +9,64 @@ const {
|
|
|
7
9
|
arrayExpression,
|
|
8
10
|
} = types;
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const isAsClause = ({type}) => type === 'as_clause';
|
|
13
|
+
const isVirtual = (stmt) => stmt.kind && stmt.kind.kindKw.name === 'VIRTUAL';
|
|
14
|
+
const isColumnDefinition = ({type}) => type === 'column_definition';
|
|
15
|
+
const isTemp = (stmt) => ['TEMP', 'TEMPORARY'].includes(stmt.kind?.kindKw.name);
|
|
16
|
+
|
|
17
|
+
const convertColumnListItem = (item) => {
|
|
18
|
+
if (isColumnDefinition(item))
|
|
19
|
+
return convertColumnDefinition(item);
|
|
20
|
+
|
|
21
|
+
return convertTableConstraint(item);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const isWithoutRowid = (options) => options?.items.some(({name}) => name?.some?.(({name}) => name === 'WITHOUT'));
|
|
25
|
+
|
|
26
|
+
const convertTableArgs = (stmt) => {
|
|
27
|
+
const colNodes = stmt.columns.expr.items.map(convertColumnListItem);
|
|
28
|
+
|
|
29
|
+
if (isWithoutRowid(stmt.options))
|
|
30
|
+
colNodes.push(callExpression(identifier('withoutRowid'), []));
|
|
31
|
+
|
|
32
|
+
return [
|
|
33
|
+
identifier(stmt.name.name),
|
|
14
34
|
arrayExpression(colNodes),
|
|
15
35
|
];
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const convertUsing = ({module}) => {
|
|
39
|
+
const args = [];
|
|
40
|
+
|
|
41
|
+
for (const item of module.args.expr.args.items)
|
|
42
|
+
args.push(identifier(item.name));
|
|
43
|
+
|
|
44
|
+
return callExpression(identifier(module.name.name), args);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const convertCreateTable = (stmt) => {
|
|
48
|
+
if (isVirtual(stmt)) {
|
|
49
|
+
const [usingClause] = stmt.clauses;
|
|
50
|
+
|
|
51
|
+
return callExpression(identifier('createVirtualTable'), [
|
|
52
|
+
identifier(stmt.name.name),
|
|
53
|
+
convertUsing(usingClause),
|
|
54
|
+
]);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const asClause = stmt.clauses?.find(isAsClause);
|
|
58
|
+
|
|
59
|
+
if (asClause)
|
|
60
|
+
return callExpression(identifier('createTableAs'), [
|
|
61
|
+
identifier(stmt.name.name),
|
|
62
|
+
convertClause(asClause.expr),
|
|
63
|
+
]);
|
|
64
|
+
|
|
65
|
+
const fnName = isTemp(stmt) ? 'createTempTable' : 'createTable';
|
|
66
|
+
const tableArgs = convertTableArgs(stmt);
|
|
16
67
|
|
|
17
|
-
if (ifNotExistsKw)
|
|
18
|
-
return callExpression(identifier(
|
|
68
|
+
if (stmt.ifNotExistsKw)
|
|
69
|
+
return callExpression(identifier(`${fnName}IfNotExists`), tableArgs);
|
|
19
70
|
|
|
20
|
-
return callExpression(identifier(
|
|
71
|
+
return callExpression(identifier(fnName), tableArgs);
|
|
21
72
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {types} from '@putout/babel';
|
|
2
|
+
import {convertClause} from '#parser/clause';
|
|
3
|
+
|
|
4
|
+
const {identifier, callExpression} = types;
|
|
5
|
+
|
|
6
|
+
const isMaterialized = (stmt) => stmt.kinds.some(({kindKw}) => kindKw.name === 'MATERIALIZED');
|
|
7
|
+
|
|
8
|
+
export const convertCreateView = (stmt) => {
|
|
9
|
+
const [asClause] = stmt.clauses;
|
|
10
|
+
const inner = convertClause(asClause.expr);
|
|
11
|
+
const fnName = isMaterialized(stmt) ? 'createMaterializedView' : 'createView';
|
|
12
|
+
|
|
13
|
+
return callExpression(identifier(fnName), [
|
|
14
|
+
identifier(stmt.name.name),
|
|
15
|
+
inner,
|
|
16
|
+
]);
|
|
17
|
+
};
|
|
@@ -5,6 +5,9 @@ const {identifier, callExpression} = types;
|
|
|
5
5
|
export const convertDropIndex = (stmt) => {
|
|
6
6
|
const args = [];
|
|
7
7
|
|
|
8
|
+
if (stmt.ifExistsKw)
|
|
9
|
+
args.push(callExpression(identifier('ifExists'), []));
|
|
10
|
+
|
|
8
11
|
for (const idx of stmt.indexes.items)
|
|
9
12
|
args.push(identifier(idx.name));
|
|
10
13
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {types} from '@putout/babel';
|
|
2
|
+
|
|
3
|
+
const {identifier, callExpression} = types;
|
|
4
|
+
|
|
5
|
+
export const convertDropView = (stmt) => {
|
|
6
|
+
const args = [];
|
|
7
|
+
|
|
8
|
+
if (stmt.ifExistsKw)
|
|
9
|
+
args.push(callExpression(identifier('ifExists'), []));
|
|
10
|
+
|
|
11
|
+
for (const view of stmt.views.items)
|
|
12
|
+
args.push(identifier(view.name));
|
|
13
|
+
|
|
14
|
+
return callExpression(identifier('dropView'), args);
|
|
15
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {types} from '@putout/babel';
|
|
2
|
+
import {convertClause} from '#parser/clause';
|
|
3
|
+
|
|
4
|
+
const {identifier, callExpression} = types;
|
|
5
|
+
|
|
6
|
+
export const convertExplain = (stmt) => {
|
|
7
|
+
const inner = convertClause(stmt.statement);
|
|
8
|
+
|
|
9
|
+
if (stmt.analyzeKw)
|
|
10
|
+
return callExpression(identifier('explainAnalyze'), [inner]);
|
|
11
|
+
|
|
12
|
+
if (stmt.queryPlanKw)
|
|
13
|
+
return callExpression(identifier('explainQueryPlan'), [inner]);
|
|
14
|
+
|
|
15
|
+
return callExpression(identifier('explain'), [inner]);
|
|
16
|
+
};
|