happy-sql 2.0.7 → 2.1.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.
Files changed (143) hide show
  1. package/ChangeLog +16 -0
  2. package/lib/happy-sql.js +5 -1
  3. package/lib/parser/fixture/comment-fix.js +6 -1
  4. package/lib/parser/fixture/section-multi-fix.js +22 -4
  5. package/lib/parser/fixture/select-fix.js +6 -1
  6. package/lib/parser/fixture/with-named-fix.js +41 -9
  7. package/lib/parser/fixture/with-named-insert-fix.js +42 -9
  8. package/lib/parser/parser.js +0 -1
  9. package/lib/parser/visitors/clause/count/fixture/count-fix.js +8 -1
  10. package/lib/parser/visitors/clause/count/fixture/count-one-fix.js +8 -1
  11. package/lib/parser/visitors/clause/create-sequence/fixture/create-sequence-fix.js +3 -1
  12. package/lib/parser/visitors/clause/create-table/fixture/create-table-autoincrement-fix.js +10 -3
  13. package/lib/parser/visitors/clause/create-table/fixture/create-table-default-fix.js +9 -3
  14. package/lib/parser/visitors/clause/create-table/fixture/create-table-identity-always-fix.js +10 -3
  15. package/lib/parser/visitors/clause/create-table/fixture/create-table-identity-by-default-fix.js +10 -3
  16. package/lib/parser/visitors/clause/create-table/fixture/create-table-nextval-fix.js +16 -4
  17. package/lib/parser/visitors/clause/create-table/fixture/create-table-not-null-fix.js +9 -3
  18. package/lib/parser/visitors/clause/create-table/fixture/create-table-serial-fix.js +9 -3
  19. package/lib/parser/visitors/clause/delete/fixture/delete-fix.js +8 -1
  20. package/lib/parser/visitors/clause/from/fixture/from-fix.js +6 -1
  21. package/lib/parser/visitors/clause/from/fixture/from-where-fix.js +10 -1
  22. package/lib/parser/visitors/clause/from/fixture/group-by-fix.js +14 -0
  23. package/lib/parser/visitors/clause/from/fixture/group-by-having-fix.js +22 -0
  24. package/lib/parser/visitors/clause/from/fixture/group-by-having.sql +1 -0
  25. package/lib/parser/visitors/clause/from/fixture/group-by-multi-fix.js +13 -0
  26. package/lib/parser/visitors/clause/from/fixture/group-by-multi.sql +1 -0
  27. package/lib/parser/visitors/clause/from/fixture/group-by.sql +1 -0
  28. package/lib/parser/visitors/clause/from/fixture/join-fix.js +12 -1
  29. package/lib/parser/visitors/clause/from/fixture/join-multi-fix.js +19 -1
  30. package/lib/parser/visitors/clause/from/fixture/join-on-in-fix.js +17 -1
  31. package/lib/parser/visitors/clause/from/fixture/join-on-is-not-null-fix.js +14 -1
  32. package/lib/parser/visitors/clause/from/fixture/join-on-is-null-fix.js +14 -1
  33. package/lib/parser/visitors/clause/from/fixture/join-on-like-fix.js +15 -1
  34. package/lib/parser/visitors/clause/from/fixture/join-on-not-eq-fix.js +12 -1
  35. package/lib/parser/visitors/clause/from/fixture/join-on-number-fix.js +12 -1
  36. package/lib/parser/visitors/clause/from/fixture/join-on-or-fix.js +12 -1
  37. package/lib/parser/visitors/clause/from/fixture/join-on-param-fix.js +12 -1
  38. package/lib/parser/visitors/clause/from/from.js +10 -27
  39. package/lib/parser/visitors/clause/from/group-by.js +6 -0
  40. package/lib/parser/visitors/clause/from/having.js +8 -0
  41. package/lib/parser/visitors/clause/index.js +12 -1
  42. package/lib/parser/visitors/clause/insert/fixture/insert-fix.js +9 -1
  43. package/lib/parser/visitors/clause/insert/fixture/insert-identifier-fix.js +15 -1
  44. package/lib/parser/visitors/clause/insert/fixture/insert-multi-fix.js +9 -1
  45. package/lib/parser/visitors/clause/insert/fixture/insert-number-fix.js +16 -1
  46. package/lib/parser/visitors/clause/insert/fixture/insert-returning-conflict-fix.js +18 -1
  47. package/lib/parser/visitors/clause/insert/fixture/insert-returning-fix.js +12 -5
  48. package/lib/parser/visitors/clause/insert/fixture/insert-returning-id-fix.js +12 -5
  49. package/lib/parser/visitors/clause/insert/fixture/insert-string-fix.js +15 -1
  50. package/lib/parser/visitors/clause/on-conflict/fixture/on-conflict-fix.js +15 -1
  51. package/lib/parser/visitors/clause/on-conflict/fixture/on-conflict-nothing-fix.js +12 -1
  52. package/lib/parser/visitors/clause/operand.js +4 -0
  53. package/lib/parser/visitors/clause/select/fixture/select-alias-fix.js +7 -1
  54. package/lib/parser/visitors/clause/select/fixture/select-alias-param-fix.js +6 -1
  55. package/lib/parser/visitors/clause/select/fixture/select-fix.js +6 -1
  56. package/lib/parser/visitors/clause/select/fixture/select-last-insert-rowid-fix.js +6 -1
  57. package/lib/parser/visitors/clause/select/fixture/select-lastval-fix.js +6 -1
  58. package/lib/parser/visitors/clause/select/fixture/select-number-fix.js +9 -1
  59. package/lib/parser/visitors/clause/select/fixture/select-param-fix.js +7 -1
  60. package/lib/parser/visitors/clause/select/select.js +16 -0
  61. package/lib/parser/visitors/clause/union/fixture/union-all-fix.js +10 -0
  62. package/lib/parser/visitors/clause/union/fixture/union-all.sql +1 -0
  63. package/lib/parser/visitors/clause/union/union.js +11 -0
  64. package/lib/parser/visitors/clause/update/fixture/update-fix.js +9 -1
  65. package/lib/parser/visitors/clause/update/fixture/update-identifier-fix.js +9 -1
  66. package/lib/parser/visitors/clause/update/fixture/update-no-where-fix.js +6 -1
  67. package/lib/parser/visitors/clause/update/fixture/update-number-fix.js +9 -1
  68. package/lib/parser/visitors/clause/update/fixture/update-string-fix.js +9 -1
  69. package/lib/parser/visitors/clause/update/fixture/update-where-and-fix.js +11 -0
  70. package/lib/parser/visitors/clause/update/fixture/update-where-and.sql +1 -0
  71. package/lib/parser/visitors/clause/update/fixture/update-where-in-fix.js +16 -0
  72. package/lib/parser/visitors/clause/update/fixture/update-where-in.sql +1 -0
  73. package/lib/parser/visitors/clause/update/fixture/update-where-is-not-null-fix.js +13 -0
  74. package/lib/parser/visitors/clause/update/fixture/update-where-is-not-null.sql +1 -0
  75. package/lib/parser/visitors/clause/update/fixture/update-where-is-null-fix.js +13 -0
  76. package/lib/parser/visitors/clause/update/fixture/update-where-is-null.sql +1 -0
  77. package/lib/parser/visitors/clause/update/fixture/update-where-like-fix.js +14 -0
  78. package/lib/parser/visitors/clause/update/fixture/update-where-like.sql +1 -0
  79. package/lib/parser/visitors/clause/update/fixture/update-where-or-fix.js +11 -0
  80. package/lib/parser/visitors/clause/update/fixture/update-where-or.sql +1 -0
  81. package/lib/parser/visitors/clause/where/fixture/where-boolean-fix.js +11 -0
  82. package/lib/parser/visitors/clause/where/fixture/where-boolean.sql +1 -0
  83. package/lib/parser/visitors/clause/where/fixture/where-compare-fix.js +9 -1
  84. package/lib/parser/visitors/clause/where/fixture/where-fix.js +9 -1
  85. package/lib/parser/visitors/clause/where/fixture/where-gte-fix.js +9 -1
  86. package/lib/parser/visitors/clause/where/fixture/where-in-fix.js +14 -1
  87. package/lib/parser/visitors/clause/where/fixture/where-is-not-null-fix.js +11 -1
  88. package/lib/parser/visitors/clause/where/fixture/where-is-null-fix.js +11 -1
  89. package/lib/parser/visitors/clause/where/fixture/where-like-fix.js +12 -1
  90. package/lib/parser/visitors/clause/where/fixture/where-member-fix.js +11 -0
  91. package/lib/parser/visitors/clause/where/fixture/where-member.sql +1 -0
  92. package/lib/parser/visitors/clause/where/fixture/where-not-eq-fix.js +9 -1
  93. package/lib/parser/visitors/clause/where/fixture/where-null-fix.js +11 -0
  94. package/lib/parser/visitors/clause/where/fixture/where-null.sql +1 -0
  95. package/lib/parser/visitors/clause/where/fixture/where-number-fix.js +9 -1
  96. package/lib/parser/visitors/clause/where/fixture/where-or-fix.js +9 -1
  97. package/lib/parser/visitors/clause/where/where.js +1 -1
  98. package/lib/parser/visitors/clause/with-named/fixture/with-named-select-fix.js +19 -0
  99. package/lib/parser/visitors/clause/with-named/fixture/with-named-select.sql +1 -0
  100. package/lib/parser/visitors/clause/with-named/fixture/with-recursive-fix.js +27 -0
  101. package/lib/parser/visitors/clause/with-named/fixture/with-recursive-multi-fix.js +38 -0
  102. package/lib/parser/visitors/clause/with-named/fixture/with-recursive-multi.sql +1 -0
  103. package/lib/parser/visitors/clause/with-named/fixture/with-recursive-no-columns-fix.js +20 -0
  104. package/lib/parser/visitors/clause/with-named/fixture/with-recursive-no-columns.sql +1 -0
  105. package/lib/parser/visitors/clause/with-named/fixture/with-recursive.sql +1 -0
  106. package/lib/parser/visitors/clause/with-named/with-named.js +15 -2
  107. package/lib/printer/visitors/array-expression.js +4 -2
  108. package/lib/printer/visitors/call-expression/clauses/clauses.js +8 -0
  109. package/lib/printer/visitors/call-expression/clauses/column/column.js +1 -1
  110. package/lib/printer/visitors/call-expression/clauses/create-table/create-table.js +7 -3
  111. package/lib/printer/visitors/call-expression/clauses/delete/delete.js +1 -1
  112. package/lib/printer/visitors/call-expression/clauses/from/fixture/group-by-having-fix.sql +5 -0
  113. package/lib/printer/visitors/call-expression/clauses/from/fixture/group-by-having.js +22 -0
  114. package/lib/printer/visitors/call-expression/clauses/from/from.js +13 -6
  115. package/lib/printer/visitors/call-expression/clauses/group-by/fixture/group-by-fix.sql +3 -0
  116. package/lib/printer/visitors/call-expression/clauses/group-by/fixture/group-by-multi-fix.sql +3 -0
  117. package/lib/printer/visitors/call-expression/clauses/group-by/fixture/group-by-multi.js +13 -0
  118. package/lib/printer/visitors/call-expression/clauses/group-by/fixture/group-by.js +14 -0
  119. package/lib/printer/visitors/call-expression/clauses/group-by/group-by.js +12 -0
  120. package/lib/printer/visitors/call-expression/clauses/having/fixture/having-fix.sql +3 -0
  121. package/lib/printer/visitors/call-expression/clauses/having/fixture/having.js +16 -0
  122. package/lib/printer/visitors/call-expression/clauses/having/having.js +4 -0
  123. package/lib/printer/visitors/call-expression/clauses/insert/insert.js +1 -1
  124. package/lib/printer/visitors/call-expression/clauses/into/into.js +1 -1
  125. package/lib/printer/visitors/call-expression/clauses/join/join.js +3 -2
  126. package/lib/printer/visitors/call-expression/clauses/select/select.js +1 -1
  127. package/lib/printer/visitors/call-expression/clauses/union-all/fixture/union-all-fix.sql +3 -0
  128. package/lib/printer/visitors/call-expression/clauses/union-all/fixture/union-all.js +1 -0
  129. package/lib/printer/visitors/call-expression/clauses/union-all/union-all.js +9 -0
  130. package/lib/printer/visitors/call-expression/clauses/update/update.js +2 -2
  131. package/lib/printer/visitors/call-expression/clauses/with-named/fixture/with-named-insert-fix.sql +3 -3
  132. package/lib/printer/visitors/call-expression/clauses/with-named/fixture/with-named-select-fix.sql +8 -0
  133. package/lib/printer/visitors/call-expression/clauses/with-named/fixture/with-named-select.js +19 -0
  134. package/lib/printer/visitors/call-expression/clauses/with-named/fixture/withNamed-fix.sql +3 -3
  135. package/lib/printer/visitors/call-expression/clauses/with-named/with-named.js +23 -6
  136. package/lib/printer/visitors/call-expression/clauses/with-recursive/fixture/with-recursive-fix.sql +10 -0
  137. package/lib/printer/visitors/call-expression/clauses/with-recursive/fixture/with-recursive-multi-fix.sql +14 -0
  138. package/lib/printer/visitors/call-expression/clauses/with-recursive/fixture/with-recursive-multi.js +38 -0
  139. package/lib/printer/visitors/call-expression/clauses/with-recursive/fixture/with-recursive-no-columns-fix.sql +8 -0
  140. package/lib/printer/visitors/call-expression/clauses/with-recursive/fixture/with-recursive-no-columns.js +20 -0
  141. package/lib/printer/visitors/call-expression/clauses/with-recursive/fixture/with-recursive.js +27 -0
  142. package/lib/printer/visitors/call-expression/clauses/with-recursive/with-recursive.js +57 -0
  143. package/package.json +2 -1
@@ -1,3 +1,11 @@
1
1
  [
2
- select('*', from(t, where(x > 1 && y < 2))),
2
+ select(
3
+ '*',
4
+ from(
5
+ t,
6
+ where(
7
+ x > 1 && y < 2,
8
+ ),
9
+ ),
10
+ ),
3
11
  ];
@@ -1,3 +1,11 @@
1
1
  [
2
- select('*', from(users, where(id === ':id'))),
2
+ select(
3
+ '*',
4
+ from(
5
+ users,
6
+ where(
7
+ id === ':id',
8
+ ),
9
+ ),
10
+ ),
3
11
  ];
@@ -1,3 +1,11 @@
1
1
  [
2
- select('*', from(t, where(x >= 1))),
2
+ select(
3
+ '*',
4
+ from(
5
+ t,
6
+ where(
7
+ x >= 1,
8
+ ),
9
+ ),
10
+ ),
3
11
  ];
@@ -1,3 +1,16 @@
1
1
  [
2
- select('*', from(t, where(inList(x, 1, 2, 3)))),
2
+ select(
3
+ '*',
4
+ from(
5
+ t,
6
+ where(
7
+ inList(
8
+ x,
9
+ 1,
10
+ 2,
11
+ 3,
12
+ ),
13
+ ),
14
+ ),
15
+ ),
3
16
  ];
@@ -1,3 +1,13 @@
1
1
  [
2
- select('*', from(t, where(isNotNull(x)))),
2
+ select(
3
+ '*',
4
+ from(
5
+ t,
6
+ where(
7
+ isNotNull(
8
+ x,
9
+ ),
10
+ ),
11
+ ),
12
+ ),
3
13
  ];
@@ -1,3 +1,13 @@
1
1
  [
2
- select('*', from(t, where(isNull(x)))),
2
+ select(
3
+ '*',
4
+ from(
5
+ t,
6
+ where(
7
+ isNull(
8
+ x,
9
+ ),
10
+ ),
11
+ ),
12
+ ),
3
13
  ];
@@ -1,3 +1,14 @@
1
1
  [
2
- select('*', from(t, where(like(x, ':pattern')))),
2
+ select(
3
+ '*',
4
+ from(
5
+ t,
6
+ where(
7
+ like(
8
+ x,
9
+ ':pattern',
10
+ ),
11
+ ),
12
+ ),
13
+ ),
3
14
  ];
@@ -0,0 +1,11 @@
1
+ [
2
+ select(
3
+ '*',
4
+ from(
5
+ t,
6
+ where(
7
+ a.b === 1,
8
+ ),
9
+ ),
10
+ ),
11
+ ];
@@ -0,0 +1 @@
1
+ SELECT * FROM t WHERE a.b = 1
@@ -1,3 +1,11 @@
1
1
  [
2
- select('*', from(t, where(x !== ':y'))),
2
+ select(
3
+ '*',
4
+ from(
5
+ t,
6
+ where(
7
+ x !== ':y',
8
+ ),
9
+ ),
10
+ ),
3
11
  ];
@@ -0,0 +1,11 @@
1
+ [
2
+ select(
3
+ '*',
4
+ from(
5
+ t,
6
+ where(
7
+ x === null,
8
+ ),
9
+ ),
10
+ ),
11
+ ];
@@ -0,0 +1 @@
1
+ SELECT * FROM t WHERE x = NULL
@@ -1,3 +1,11 @@
1
1
  [
2
- select('*', from(t, where(id === 42))),
2
+ select(
3
+ '*',
4
+ from(
5
+ t,
6
+ where(
7
+ id === 42,
8
+ ),
9
+ ),
10
+ ),
3
11
  ];
@@ -1,3 +1,11 @@
1
1
  [
2
- select('*', from(t, where(x === ':x' || y === ':y'))),
2
+ select(
3
+ '*',
4
+ from(
5
+ t,
6
+ where(
7
+ x === ':x' || y === ':y',
8
+ ),
9
+ ),
10
+ ),
3
11
  ];
@@ -71,7 +71,7 @@ const convertBinary = (node) => {
71
71
  );
72
72
  };
73
73
 
74
- const convertCondition = (node) => {
74
+ export const convertCondition = (node) => {
75
75
  if (node.operator?.name === 'AND')
76
76
  return convertAnd(node);
77
77
 
@@ -0,0 +1,19 @@
1
+ [
2
+ withNamed(
3
+ recent = select(
4
+ id,
5
+ from(
6
+ users,
7
+ where(
8
+ kind === 'const',
9
+ ),
10
+ ),
11
+ ),
12
+ select(
13
+ id,
14
+ from(
15
+ recent,
16
+ ),
17
+ ),
18
+ ),
19
+ ];
@@ -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,20 @@
1
+ [
2
+ withRecursive(
3
+ t(
4
+ unionAll(
5
+ select(
6
+ 1,
7
+ ),
8
+ select(
9
+ 2,
10
+ ),
11
+ ),
12
+ ),
13
+ select(
14
+ '*',
15
+ from(
16
+ t,
17
+ ),
18
+ ),
19
+ ),
20
+ ];
@@ -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(convertTable),
39
+ ...withClause.tables.items.map(convertCte),
27
40
  finalStatement,
28
41
  ];
29
42
 
30
- return callExpression(identifier('withNamed'), args);
43
+ return callExpression(identifier(fnName), args);
31
44
  };
@@ -5,7 +5,9 @@ export const ArrayExpression = (path, {write, traverse}) => {
5
5
  for (const [i, el] of elements.entries()) {
6
6
  traverse(el);
7
7
 
8
- if (i < n)
9
- write('\n\n');
8
+ if (i < n) {
9
+ write.newline();
10
+ write.newline();
11
+ }
10
12
  }
11
13
  };
@@ -14,6 +14,10 @@ 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';
17
21
  import {createTable} from './create-table/create-table.js';
18
22
  import {createSequence} from './create-sequence/create-sequence.js';
19
23
  import {column} from './column/column.js';
@@ -48,6 +52,10 @@ export const clauses = {
48
52
  section,
49
53
  returning,
50
54
  withNamed,
55
+ withRecursive,
56
+ unionAll,
57
+ groupBy,
58
+ having,
51
59
  createTable,
52
60
  createSequence,
53
61
  column,
@@ -3,7 +3,7 @@ export const column = (path, {write, traverse}) => {
3
3
 
4
4
  for (const [i, arg] of args.entries()) {
5
5
  if (i > 0)
6
- write(' ');
6
+ write.space();
7
7
 
8
8
  traverse(arg);
9
9
  }
@@ -3,13 +3,17 @@ export const createTable = (path, {write, traverse}) => {
3
3
 
4
4
  write('CREATE TABLE ');
5
5
  traverse(name);
6
- write(' (\n');
6
+ write.space();
7
+ write('(');
8
+ write.newline();
7
9
 
8
10
  const elements = columns.get('elements');
9
11
 
10
12
  for (const [i, element] of elements.entries()) {
11
- if (i > 0)
12
- write(',\n');
13
+ if (i > 0) {
14
+ write(',');
15
+ write.newline();
16
+ }
13
17
 
14
18
  traverse(element);
15
19
  }
@@ -7,7 +7,7 @@ export const deleteFrom = (path, {write, traverse}) => {
7
7
  traverse(fromArg);
8
8
 
9
9
  if (whereArg) {
10
- write('\n');
10
+ write.newline();
11
11
  traverse(whereArg);
12
12
  }
13
13
  };
@@ -0,0 +1,5 @@
1
+ SELECT kind, COUNT(*)
2
+ FROM VariableDeclaration
3
+ WHERE kind = 'const'
4
+ GROUP BY kind
5
+ HAVING COUNT(*) > 1
@@ -0,0 +1,22 @@
1
+ [
2
+ select(
3
+ kind,
4
+ count(
5
+ '*',
6
+ ),
7
+ from(
8
+ VariableDeclaration,
9
+ where(
10
+ kind === 'const',
11
+ ),
12
+ groupBy(
13
+ kind,
14
+ ),
15
+ having(
16
+ count(
17
+ '*',
18
+ ) > 1,
19
+ ),
20
+ ),
21
+ ),
22
+ ];
@@ -7,6 +7,14 @@ const printAsExpression = (path, {write, traverse}) => {
7
7
  write(` AS ${path.node.typeAnnotation.literal.value}`);
8
8
  };
9
9
 
10
+ const CLAUSE_NAMES = [
11
+ 'where',
12
+ 'groupBy',
13
+ 'having',
14
+ ];
15
+
16
+ const isClause = ({node}) => node.type === 'CallExpression' && CLAUSE_NAMES.includes(node.callee?.name);
17
+
10
18
  const printArg = (path, ctx) => {
11
19
  if (isTSAsExpression(path.node))
12
20
  return printAsExpression(path, ctx);
@@ -16,9 +24,8 @@ const printArg = (path, ctx) => {
16
24
 
17
25
  export const from = (path, {write, traverse}) => {
18
26
  const args = path.get('arguments');
19
- const lastArg = args.at(-1);
20
- const hasWhere = lastArg?.node?.callee?.name === 'where';
21
- const tableArgs = hasWhere ? args.slice(0, -1) : args;
27
+ const tableArgs = args.filter((arg) => !isClause(arg));
28
+ const clauseArgs = args.filter(isClause);
22
29
 
23
30
  write('FROM ');
24
31
  printArg(tableArgs[0], {
@@ -32,8 +39,8 @@ export const from = (path, {write, traverse}) => {
32
39
  traverse,
33
40
  });
34
41
 
35
- if (hasWhere) {
36
- write('\n');
37
- traverse(lastArg);
42
+ for (const clause of clauseArgs) {
43
+ write.breakline();
44
+ traverse(clause);
38
45
  }
39
46
  };
@@ -0,0 +1,3 @@
1
+ SELECT kind, COUNT(*)
2
+ FROM VariableDeclaration
3
+ GROUP BY kind
@@ -0,0 +1,3 @@
1
+ SELECT kind, name
2
+ FROM VariableDeclaration
3
+ GROUP BY kind, name
@@ -0,0 +1,13 @@
1
+ [
2
+ select(
3
+ kind,
4
+ name,
5
+ from(
6
+ VariableDeclaration,
7
+ groupBy(
8
+ kind,
9
+ name,
10
+ ),
11
+ ),
12
+ ),
13
+ ];
@@ -0,0 +1,14 @@
1
+ [
2
+ select(
3
+ kind,
4
+ count(
5
+ '*',
6
+ ),
7
+ from(
8
+ VariableDeclaration,
9
+ groupBy(
10
+ kind,
11
+ ),
12
+ ),
13
+ ),
14
+ ];
@@ -0,0 +1,12 @@
1
+ export const groupBy = (path, {write, traverse}) => {
2
+ const args = path.get('arguments');
3
+
4
+ write('GROUP BY ');
5
+
6
+ for (const [i, arg] of args.entries()) {
7
+ if (i > 0)
8
+ write(', ');
9
+
10
+ traverse(arg);
11
+ }
12
+ };
@@ -0,0 +1,3 @@
1
+ SELECT kind, COUNT(*)
2
+ FROM VariableDeclaration
3
+ HAVING COUNT(*) > 1
@@ -0,0 +1,16 @@
1
+ [
2
+ select(
3
+ kind,
4
+ count(
5
+ '*',
6
+ ),
7
+ from(
8
+ VariableDeclaration,
9
+ having(
10
+ count(
11
+ '*',
12
+ ) > 1,
13
+ ),
14
+ ),
15
+ ),
16
+ ];
@@ -0,0 +1,4 @@
1
+ export const having = (path, {write, traverse}) => {
2
+ write('HAVING ');
3
+ traverse(path.get('arguments')[0]);
4
+ };
@@ -6,7 +6,7 @@ export const insert = (path, {write, traverse}) => {
6
6
  traverse(intoArg);
7
7
 
8
8
  for (const arg of rest) {
9
- write('\n');
9
+ write.breakline();
10
10
  traverse(arg);
11
11
  }
12
12
  };
@@ -24,7 +24,7 @@ export const into = (path, {write, traverse}) => {
24
24
  write(')');
25
25
 
26
26
  if (values) {
27
- write(' ');
27
+ write.space();
28
28
  traverse(values);
29
29
  }
30
30
  };
@@ -17,11 +17,12 @@ const printTable = (path, ctx) => {
17
17
  export const join = (path, {write, traverse}) => {
18
18
  const [table, onClause] = path.get('arguments');
19
19
 
20
- write('\nJOIN ');
20
+ write.breakline();
21
+ write('JOIN ');
21
22
  printTable(table, {
22
23
  write,
23
24
  traverse,
24
25
  });
25
- write(' ');
26
+ write.space();
26
27
  traverse(onClause);
27
28
  };
@@ -34,7 +34,7 @@ export const select = (path, {write, traverse}) => {
34
34
  }
35
35
 
36
36
  if (fromArg) {
37
- write('\n');
37
+ write.breakline();
38
38
  traverse(fromArg);
39
39
  }
40
40
  };
@@ -0,0 +1 @@
1
+ [unionAll(select(1), select(2))];
@@ -0,0 +1,9 @@
1
+ export const unionAll = (path, {write, traverse}) => {
2
+ const [left, right] = path.get('arguments');
3
+
4
+ traverse(left);
5
+ write.breakline();
6
+ write('UNION ALL');
7
+ write.breakline();
8
+ traverse(right);
9
+ };
@@ -6,11 +6,11 @@ export const update = (path, {write, traverse}) => {
6
6
 
7
7
  write('UPDATE ');
8
8
  traverse(table);
9
- write('\n');
9
+ write.newline();
10
10
  traverse(set);
11
11
 
12
12
  if (where) {
13
- write('\n');
13
+ write.newline();
14
14
  traverse(where);
15
15
  }
16
16
  };