happy-sql 2.0.2 → 2.0.4

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 (47) hide show
  1. package/ChangeLog +10 -0
  2. package/lib/parser/visitors/clause/from/from.js +10 -3
  3. package/lib/parser/visitors/clause/select/fixture/select-number-fix.js +1 -1
  4. package/lib/parser/visitors/clause/select/select.js +5 -4
  5. package/lib/parser/visitors/clause/where/fixture/where-compare-fix.js +1 -1
  6. package/lib/parser/visitors/clause/where/fixture/where-fix.js +1 -1
  7. package/lib/parser/visitors/clause/where/fixture/where-gte-fix.js +1 -1
  8. package/lib/parser/visitors/clause/where/fixture/where-in-fix.js +1 -1
  9. package/lib/parser/visitors/clause/where/fixture/where-is-not-null-fix.js +1 -1
  10. package/lib/parser/visitors/clause/where/fixture/where-is-null-fix.js +1 -1
  11. package/lib/parser/visitors/clause/where/fixture/where-like-fix.js +1 -1
  12. package/lib/parser/visitors/clause/where/fixture/where-not-eq-fix.js +1 -1
  13. package/lib/parser/visitors/clause/where/fixture/where-number-fix.js +1 -1
  14. package/lib/parser/visitors/clause/where/fixture/where-or-fix.js +1 -1
  15. package/lib/printer/visitors/array-expression.js +1 -1
  16. package/lib/printer/visitors/call-expression/clauses/create-table/create-table.js +2 -2
  17. package/lib/printer/visitors/call-expression/clauses/create-table/fixture/createTable-fix.sql +2 -1
  18. package/lib/printer/visitors/call-expression/clauses/create-table/fixture/createTableIdentity-fix.sql +2 -1
  19. package/lib/printer/visitors/call-expression/clauses/create-table/fixture/createTableIdentityByDefault-fix.sql +2 -1
  20. package/lib/printer/visitors/call-expression/clauses/create-table/fixture/createTableSerial-fix.sql +2 -1
  21. package/lib/printer/visitors/call-expression/clauses/from/from.js +11 -3
  22. package/lib/printer/visitors/call-expression/clauses/insert/insert.js +1 -1
  23. package/lib/printer/visitors/call-expression/clauses/into/into.js +6 -2
  24. package/lib/printer/visitors/call-expression/clauses/join/fixture/join-bare-fix.sql +3 -0
  25. package/lib/printer/visitors/call-expression/clauses/join/fixture/join-bare.js +1 -0
  26. package/lib/printer/visitors/call-expression/clauses/nextval/fixture/nextval-fix.sql +3 -1
  27. package/lib/printer/visitors/call-expression/clauses/on-conflict/fixture/on-conflict-fix.sql +2 -1
  28. package/lib/printer/visitors/call-expression/clauses/on-conflict/fixture/on-conflict-multi-fix.sql +2 -1
  29. package/lib/printer/visitors/call-expression/clauses/returning/fixture/returning-conflict-fix.sql +3 -1
  30. package/lib/printer/visitors/call-expression/clauses/returning/fixture/returning-fix.sql +2 -1
  31. package/lib/printer/visitors/call-expression/clauses/returning/fixture/returning-id-fix.sql +2 -1
  32. package/lib/printer/visitors/call-expression/clauses/returning/fixture/returning-multi-fix.sql +2 -1
  33. package/lib/printer/visitors/call-expression/clauses/section/fixture/section-multi-fix.sql +1 -0
  34. package/lib/printer/visitors/call-expression/clauses/section/section.js +1 -1
  35. package/lib/printer/visitors/call-expression/clauses/select/fixture/string-fix.sql +1 -1
  36. package/lib/printer/visitors/call-expression/clauses/select/select.js +8 -16
  37. package/lib/printer/visitors/call-expression/clauses/where/fixture/where-fix.sql +1 -3
  38. package/lib/printer/visitors/call-expression/clauses/where/fixture/where-gte-fix.sql +1 -3
  39. package/lib/printer/visitors/call-expression/clauses/where/fixture/where-in-fix.sql +1 -3
  40. package/lib/printer/visitors/call-expression/clauses/where/fixture/where-is-not-null-fix.sql +1 -3
  41. package/lib/printer/visitors/call-expression/clauses/where/fixture/where-is-null-fix.sql +1 -3
  42. package/lib/printer/visitors/call-expression/clauses/where/fixture/where-like-fix.sql +1 -3
  43. package/lib/printer/visitors/call-expression/clauses/where/fixture/where-ne-fix.sql +1 -3
  44. package/lib/printer/visitors/call-expression/clauses/with-named/fixture/with-named-insert-fix.sql +4 -2
  45. package/lib/printer/visitors/call-expression/clauses/with-named/fixture/withNamed-fix.sql +4 -2
  46. package/lib/printer/visitors/fixture/binary-expression-fix.sql +1 -3
  47. package/package.json +1 -1
package/ChangeLog CHANGED
@@ -1,3 +1,13 @@
1
+ 2026.08.20, v2.0.4
2
+
3
+ fix:
4
+ - 743d5c6 happy-sql: ";"
5
+
6
+ 2026.08.20, v2.0.3
7
+
8
+ feature:
9
+ - 894a345 from
10
+
1
11
  2026.08.20, v2.0.2
2
12
 
3
13
  fix:
@@ -133,7 +133,7 @@ const flattenJoins = (node, joins = []) => {
133
133
  return joins;
134
134
  };
135
135
 
136
- export const convertFrom = ({expr}) => {
136
+ export const convertFrom = ({expr, whereClause}) => {
137
137
  if (expr.type === 'join_expr') {
138
138
  const parts = flattenJoins(expr);
139
139
  return callExpression(identifier('from'), parts);
@@ -144,7 +144,14 @@ export const convertFrom = ({expr}) => {
144
144
  convertAlias(expr),
145
145
  ]);
146
146
 
147
- return callExpression(identifier('from'), [
147
+ const fromArgs = [
148
148
  identifier(expr.name),
149
- ]);
149
+ ];
150
+
151
+ if (whereClause)
152
+ fromArgs.push(callExpression(identifier('where'), [
153
+ convertCondition(whereClause.expr),
154
+ ]));
155
+
156
+ return callExpression(identifier('from'), fromArgs);
150
157
  };
@@ -1,3 +1,3 @@
1
1
  [
2
- select('*', from(t), where(num === 42)),
2
+ select('*', from(t, where(num === 42))),
3
3
  ];
@@ -1,9 +1,8 @@
1
1
  import {types} from '@putout/babel';
2
2
  import {convertOperand} from '#parser/clause/operand';
3
3
  import {convertFrom} from '#parser/clause/from';
4
- import {convertWhere} from '#parser/clause/where';
5
- import {findClause} from '#parser/clause/find';
6
4
  import {convertCount, isCount} from '#parser/clause/count';
5
+ import {findClause} from '#parser/clause/find';
7
6
 
8
7
  const {
9
8
  identifier,
@@ -61,8 +60,10 @@ export const convertSelect = ({clauses}) => {
61
60
 
62
61
  const args = [
63
62
  ...convertColumns(selectClause.columns),
64
- fromClause && convertFrom(fromClause),
65
- whereClause && convertWhere(whereClause),
63
+ fromClause && convertFrom({
64
+ expr: fromClause.expr,
65
+ whereClause,
66
+ }),
66
67
  ].filter(Boolean);
67
68
 
68
69
  return callExpression(identifier('select'), args);
@@ -1,3 +1,3 @@
1
1
  [
2
- select('*', from(t), where(x > 1 && y < 2)),
2
+ select('*', from(t, where(x > 1 && y < 2))),
3
3
  ];
@@ -1,3 +1,3 @@
1
1
  [
2
- select('*', from(users), where(id === ':id')),
2
+ select('*', from(users, where(id === ':id'))),
3
3
  ];
@@ -1,3 +1,3 @@
1
1
  [
2
- select('*', from(t), where(x >= 1)),
2
+ select('*', from(t, where(x >= 1))),
3
3
  ];
@@ -1,3 +1,3 @@
1
1
  [
2
- select('*', from(t), where(inList(x, 1, 2, 3))),
2
+ select('*', from(t, where(inList(x, 1, 2, 3)))),
3
3
  ];
@@ -1,3 +1,3 @@
1
1
  [
2
- select('*', from(t), where(isNotNull(x))),
2
+ select('*', from(t, where(isNotNull(x)))),
3
3
  ];
@@ -1,3 +1,3 @@
1
1
  [
2
- select('*', from(t), where(isNull(x))),
2
+ select('*', from(t, where(isNull(x)))),
3
3
  ];
@@ -1,3 +1,3 @@
1
1
  [
2
- select('*', from(t), where(like(x, ':pattern'))),
2
+ select('*', from(t, where(like(x, ':pattern')))),
3
3
  ];
@@ -1,3 +1,3 @@
1
1
  [
2
- select('*', from(t), where(x !== ':y')),
2
+ select('*', from(t, where(x !== ':y'))),
3
3
  ];
@@ -1,3 +1,3 @@
1
1
  [
2
- select('*', from(t), where(id === 42)),
2
+ select('*', from(t, where(id === 42))),
3
3
  ];
@@ -1,3 +1,3 @@
1
1
  [
2
- select('*', from(t), where(x === ':x' || y === ':y')),
2
+ select('*', from(t, where(x === ':x' || y === ':y'))),
3
3
  ];
@@ -6,6 +6,6 @@ export const ArrayExpression = (path, {write, traverse}) => {
6
6
  traverse(el);
7
7
 
8
8
  if (i < n)
9
- write(';\n');
9
+ write('\n\n');
10
10
  }
11
11
  };
@@ -3,13 +3,13 @@ export const createTable = (path, {write, traverse}) => {
3
3
 
4
4
  write('CREATE TABLE ');
5
5
  traverse(name);
6
- write(' (');
6
+ write(' (\n');
7
7
 
8
8
  const elements = columns.get('elements');
9
9
 
10
10
  for (const [i, element] of elements.entries()) {
11
11
  if (i > 0)
12
- write(', ');
12
+ write(',\n');
13
13
 
14
14
  traverse(element);
15
15
  }
@@ -1 +1,2 @@
1
- CREATE TABLE t (id INTEGER PRIMARY KEY AUTOINCREMENT)
1
+ CREATE TABLE t (
2
+ id INTEGER PRIMARY KEY AUTOINCREMENT)
@@ -1 +1,2 @@
1
- CREATE TABLE t (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY)
1
+ CREATE TABLE t (
2
+ id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY)
@@ -1 +1,2 @@
1
- CREATE TABLE t (id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY)
1
+ CREATE TABLE t (
2
+ id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY)
@@ -1 +1,2 @@
1
- CREATE TABLE t (id SERIAL PRIMARY KEY)
1
+ CREATE TABLE t (
2
+ id SERIAL PRIMARY KEY)
@@ -16,16 +16,24 @@ const printArg = (path, ctx) => {
16
16
 
17
17
  export const from = (path, {write, traverse}) => {
18
18
  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;
19
22
 
20
23
  write('FROM ');
21
- printArg(args[0], {
24
+ printArg(tableArgs[0], {
22
25
  write,
23
26
  traverse,
24
27
  });
25
28
 
26
- for (let i = 1; i < args.length; i++)
27
- printArg(args[i], {
29
+ for (let i = 1; i < tableArgs.length; i++)
30
+ printArg(tableArgs[i], {
28
31
  write,
29
32
  traverse,
30
33
  });
34
+
35
+ if (hasWhere) {
36
+ write('\n');
37
+ traverse(lastArg);
38
+ }
31
39
  };
@@ -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(' ');
9
+ write('\n');
10
10
  traverse(arg);
11
11
  }
12
12
  };
@@ -21,6 +21,10 @@ export const into = (path, {write, traverse}) => {
21
21
  traverse(columns);
22
22
  }
23
23
 
24
- write(') ');
25
- traverse(values);
24
+ write(')');
25
+
26
+ if (values) {
27
+ write(' ');
28
+ traverse(values);
29
+ }
26
30
  };
@@ -0,0 +1,3 @@
1
+ SELECT id
2
+ FROM Users
3
+ JOIN Orders ON Orders.user_id = Users.id
@@ -0,0 +1 @@
1
+ [select(id, from(Users, join(Orders, on(Orders.user_id === Users.id))))];
@@ -1 +1,3 @@
1
- CREATE TABLE users (id INTEGER DEFAULT nextval('users_id_seq') PRIMARY KEY, name TEXT)
1
+ CREATE TABLE users (
2
+ id INTEGER DEFAULT nextval('users_id_seq') PRIMARY KEY,
3
+ name TEXT)
@@ -1 +1,2 @@
1
- INSERT INTO t (x) VALUES (:x) ON CONFLICT (x) DO UPDATE SET x = :x
1
+ INSERT INTO t (x) VALUES (:x)
2
+ ON CONFLICT (x) DO UPDATE SET x = :x
@@ -1 +1,2 @@
1
- INSERT INTO t (x) VALUES (:x) ON CONFLICT (x, y) DO UPDATE SET x = :x
1
+ INSERT INTO t (x) VALUES (:x)
2
+ ON CONFLICT (x, y) DO UPDATE SET x = :x
@@ -1 +1,3 @@
1
- INSERT INTO t (x) VALUES (:x) ON CONFLICT (x) DO UPDATE SET y = :y RETURNING id
1
+ INSERT INTO t (x) VALUES (:x)
2
+ ON CONFLICT (x) DO UPDATE SET y = :y
3
+ RETURNING id
@@ -1 +1,2 @@
1
- INSERT INTO CallExpression (parent_id) VALUES (:parent_id) RETURNING id AS call_id
1
+ INSERT INTO CallExpression (parent_id) VALUES (:parent_id)
2
+ RETURNING id AS call_id
@@ -1 +1,2 @@
1
- INSERT INTO CallExpression (parent_id) VALUES (:parent_id) RETURNING id
1
+ INSERT INTO CallExpression (parent_id) VALUES (:parent_id)
2
+ RETURNING id
@@ -1 +1,2 @@
1
- INSERT INTO t (x) VALUES (:x) RETURNING id, created_at
1
+ INSERT INTO t (x) VALUES (:x)
2
+ RETURNING id, created_at
@@ -2,6 +2,7 @@
2
2
  UPDATE Identifier
3
3
  SET name = 'isNaN'
4
4
  WHERE id = :nan_id;
5
+
5
6
  UPDATE BinaryExpression
6
7
  SET operator = '==='
7
8
  WHERE id = :id;
@@ -8,7 +8,7 @@ export const section = (path, {write, traverse}) => {
8
8
 
9
9
  for (const [i, element] of elements.entries()) {
10
10
  traverse(element);
11
- write(i < lastIndex ? ';\n' : ';');
11
+ write(i < lastIndex ? ';\n\n' : ';');
12
12
  }
13
13
 
14
14
  return;
@@ -1 +1 @@
1
- SELECT 'hello';
1
+ SELECT 'hello'
@@ -1,9 +1,6 @@
1
1
  import {types} from '@putout/babel';
2
2
 
3
- const {
4
- isTSAsExpression,
5
- isStringLiteral,
6
- } = types;
3
+ const {isTSAsExpression} = types;
7
4
 
8
5
  const printAsExpression = (path, {write, traverse}) => {
9
6
  traverse(path.get('expression'));
@@ -19,11 +16,13 @@ const printItem = (path, ctx) => {
19
16
 
20
17
  export const select = (path, {write, traverse}) => {
21
18
  const args = path.get('arguments');
22
- const fromIdx = args.findIndex((a) => a.node.callee?.name === 'from');
23
- const cols = args.slice(0, fromIdx);
24
- const rest = args.slice(fromIdx);
19
+ const lastArg = args.at(-1);
20
+ const hasFrom = lastArg?.node?.callee?.name === 'from';
21
+ const fromArg = hasFrom ? lastArg : null;
22
+ const cols = hasFrom ? args.slice(0, -1) : args;
25
23
 
26
24
  write('SELECT ');
25
+
27
26
  for (let i = 0; i < cols.length; i++) {
28
27
  if (i > 0)
29
28
  write(', ');
@@ -34,15 +33,8 @@ export const select = (path, {write, traverse}) => {
34
33
  });
35
34
  }
36
35
 
37
- if (rest.length === 1 && isStringLiteral(rest[0])) {
38
- traverse(rest[0]);
39
- write(';');
40
-
41
- return;
42
- }
43
-
44
- for (const arg of rest) {
36
+ if (fromArg) {
45
37
  write('\n');
46
- traverse(arg);
38
+ traverse(fromArg);
47
39
  }
48
40
  };
@@ -1,3 +1 @@
1
- SELECT *
2
- FROM users
3
- WHERE id = :id
1
+ SELECT *, FROM users, WHERE id = :id
@@ -1,3 +1 @@
1
- SELECT *
2
- FROM t
3
- WHERE x >= 1
1
+ SELECT *, FROM t, WHERE x >= 1
@@ -1,3 +1 @@
1
- SELECT *
2
- FROM t
3
- WHERE x IN (1, 2, 3)
1
+ SELECT *, FROM t, WHERE x IN (1, 2, 3)
@@ -1,3 +1 @@
1
- SELECT *
2
- FROM t
3
- WHERE x IS NOT NULL
1
+ SELECT *, FROM t, WHERE x IS NOT NULL
@@ -1,3 +1 @@
1
- SELECT *
2
- FROM t
3
- WHERE x IS NULL
1
+ SELECT *, FROM t, WHERE x IS NULL
@@ -1,3 +1 @@
1
- SELECT *
2
- FROM t
3
- WHERE x LIKE :pattern
1
+ SELECT *, FROM t, WHERE x LIKE :pattern
@@ -1,3 +1 @@
1
- SELECT *
2
- FROM t
3
- WHERE x != :y
1
+ SELECT *, FROM t, WHERE x != :y
@@ -1,10 +1,12 @@
1
1
  WITH
2
2
  call AS (
3
- INSERT INTO CallExpression (file, parent_id) VALUES (:file, :parent_id) RETURNING id
3
+ INSERT INTO CallExpression (file, parent_id) VALUES (:file, :parent_id)
4
+ RETURNING id
4
5
  ),
5
6
  member AS (
6
7
  INSERT INTO MemberExpression (file, parent_id) SELECT :file, id
7
- FROM call RETURNING id
8
+ FROM call
9
+ RETURNING id
8
10
  )
9
11
  INSERT INTO Identifier (file, name, parent_id) SELECT :file, 'isNaN', id
10
12
  FROM member
@@ -1,10 +1,12 @@
1
1
  WITH
2
2
  call AS (
3
- INSERT INTO CallExpression (parent_id) VALUES (:parent_id) RETURNING id
3
+ INSERT INTO CallExpression (parent_id) VALUES (:parent_id)
4
+ RETURNING id
4
5
  ),
5
6
  member AS (
6
7
  INSERT INTO MemberExpression (parent_id) SELECT id
7
- FROM call RETURNING id
8
+ FROM call
9
+ RETURNING id
8
10
  )
9
11
  INSERT INTO Identifier (name, parent_id) SELECT 'x', id
10
12
  FROM member
@@ -1,3 +1 @@
1
- SELECT *
2
- FROM t
3
- WHERE x % 2
1
+ SELECT *, FROM t, WHERE x % 2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "happy-sql",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "type": "module",
5
5
  "description": "sql to js ast parser and printer",
6
6
  "exports": {