pqb 0.7.13 → 0.8.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.
Files changed (91) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.d.ts +618 -563
  3. package/dist/index.esm.js +1011 -402
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/index.js +1014 -401
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/columnSchema/array.test.ts +67 -0
  9. package/src/columnSchema/array.ts +39 -13
  10. package/src/columnSchema/boolean.test.ts +17 -0
  11. package/src/columnSchema/boolean.ts +5 -1
  12. package/src/columnSchema/columnType.test.ts +230 -107
  13. package/src/columnSchema/columnType.ts +198 -28
  14. package/src/columnSchema/columnTypes.ts +28 -15
  15. package/src/columnSchema/columnsSchema.ts +6 -4
  16. package/src/columnSchema/commonMethods.ts +11 -4
  17. package/src/columnSchema/dateTime.test.ts +298 -0
  18. package/src/columnSchema/dateTime.ts +59 -2
  19. package/src/columnSchema/enum.test.ts +33 -0
  20. package/src/columnSchema/enum.ts +11 -1
  21. package/src/columnSchema/json/array.test.ts +21 -0
  22. package/src/columnSchema/json/array.ts +27 -13
  23. package/src/columnSchema/json/discriminatedUnion.test.ts +32 -0
  24. package/src/columnSchema/json/discriminatedUnion.ts +17 -2
  25. package/src/columnSchema/json/enum.test.ts +9 -0
  26. package/src/columnSchema/json/enum.ts +9 -1
  27. package/src/columnSchema/json/index.ts +19 -19
  28. package/src/columnSchema/json/instanceOf.test.ts +8 -0
  29. package/src/columnSchema/json/instanceOf.ts +4 -1
  30. package/src/columnSchema/json/intersection.test.ts +19 -0
  31. package/src/columnSchema/json/intersection.ts +9 -1
  32. package/src/columnSchema/json/lazy.test.ts +22 -0
  33. package/src/columnSchema/json/lazy.ts +22 -1
  34. package/src/columnSchema/json/literal.test.ts +7 -0
  35. package/src/columnSchema/json/literal.ts +12 -1
  36. package/src/columnSchema/json/map.test.ts +10 -0
  37. package/src/columnSchema/json/map.ts +21 -1
  38. package/src/columnSchema/json/nativeEnum.test.ts +10 -0
  39. package/src/columnSchema/json/nativeEnum.ts +4 -1
  40. package/src/columnSchema/json/nullable.test.ts +18 -0
  41. package/src/columnSchema/json/nullish.test.ts +18 -0
  42. package/src/columnSchema/json/object.test.ts +77 -0
  43. package/src/columnSchema/json/object.ts +31 -3
  44. package/src/columnSchema/json/optional.test.ts +18 -0
  45. package/src/columnSchema/json/record.test.ts +14 -0
  46. package/src/columnSchema/json/record.ts +12 -1
  47. package/src/columnSchema/json/scalarTypes.test.ts +133 -0
  48. package/src/columnSchema/json/scalarTypes.ts +90 -1
  49. package/src/columnSchema/json/set.test.ts +29 -0
  50. package/src/columnSchema/json/set.ts +26 -7
  51. package/src/columnSchema/json/tuple.test.ts +17 -0
  52. package/src/columnSchema/json/tuple.ts +16 -1
  53. package/src/columnSchema/json/typeBase.test.ts +123 -0
  54. package/src/columnSchema/json/typeBase.ts +52 -13
  55. package/src/columnSchema/json/union.test.ts +10 -0
  56. package/src/columnSchema/json/union.ts +18 -1
  57. package/src/columnSchema/json.test.ts +17 -0
  58. package/src/columnSchema/json.ts +10 -2
  59. package/src/columnSchema/number.test.ts +176 -0
  60. package/src/columnSchema/number.ts +48 -1
  61. package/src/columnSchema/string.test.ts +412 -0
  62. package/src/columnSchema/string.ts +126 -15
  63. package/src/columnSchema/timestamps.test.ts +6 -6
  64. package/src/columnSchema/virtual.ts +4 -0
  65. package/src/db.ts +1 -1
  66. package/src/query.ts +1 -1
  67. package/src/queryMethods/create.ts +6 -6
  68. package/src/queryMethods/for.ts +3 -3
  69. package/src/queryMethods/having.ts +1 -1
  70. package/src/queryMethods/join.ts +4 -4
  71. package/src/queryMethods/json.ts +1 -1
  72. package/src/queryMethods/queryMethods.ts +2 -2
  73. package/src/queryMethods/select.ts +3 -3
  74. package/src/queryMethods/update.ts +17 -17
  75. package/src/queryMethods/where.test.ts +1 -1
  76. package/src/queryMethods/where.ts +4 -4
  77. package/src/relations.ts +1 -1
  78. package/src/sql/aggregate.ts +2 -2
  79. package/src/sql/copy.ts +3 -3
  80. package/src/sql/delete.ts +5 -5
  81. package/src/sql/fromAndAs.ts +4 -4
  82. package/src/sql/having.ts +7 -7
  83. package/src/sql/insert.ts +5 -5
  84. package/src/sql/join.ts +16 -16
  85. package/src/sql/select.ts +6 -6
  86. package/src/sql/toSql.ts +24 -24
  87. package/src/sql/update.ts +4 -4
  88. package/src/sql/where.ts +18 -18
  89. package/src/utils.test.ts +9 -0
  90. package/src/utils.ts +3 -0
  91. package/src/columnSchema/columnTypes.test.ts +0 -527
@@ -9,7 +9,7 @@ import { ToSqlCtx } from './toSql';
9
9
 
10
10
  export const aggregateToSql = (
11
11
  ctx: ToSqlCtx,
12
- model: QueryBase,
12
+ table: QueryBase,
13
13
  item: AggregateItem,
14
14
  quotedAs?: string,
15
15
  ) => {
@@ -58,7 +58,7 @@ export const aggregateToSql = (
58
58
  if (options.filter || options.filterOr) {
59
59
  const whereSql = whereToSql(
60
60
  ctx,
61
- model,
61
+ table,
62
62
  {
63
63
  and: options.filter ? [options.filter] : undefined,
64
64
  or: options.filterOr?.map((item) => [item]),
package/src/sql/copy.ts CHANGED
@@ -7,7 +7,7 @@ import { pushWhereStatementSql } from './where';
7
7
 
8
8
  export const pushCopySql = (
9
9
  ctx: ToSqlCtx,
10
- model: Query,
10
+ table: Query,
11
11
  query: CopyQueryData,
12
12
  quotedAs?: string,
13
13
  ) => {
@@ -19,7 +19,7 @@ export const pushCopySql = (
19
19
  const target = 'from' in copy ? copy.from : copy.to;
20
20
 
21
21
  sql.push(
22
- `COPY ${q(model.table as string)}${columns} ${
22
+ `COPY ${q(table.table as string)}${columns} ${
23
23
  'from' in copy ? 'FROM' : 'TO'
24
24
  } ${
25
25
  typeof target === 'string'
@@ -55,5 +55,5 @@ export const pushCopySql = (
55
55
  sql.push(`WITH (${options.join(', ')})`);
56
56
  }
57
57
 
58
- pushWhereStatementSql(ctx, model, query, quotedAs);
58
+ pushWhereStatementSql(ctx, table, query, quotedAs);
59
59
  };
package/src/sql/delete.ts CHANGED
@@ -8,11 +8,11 @@ import { DeleteQueryData } from './data';
8
8
 
9
9
  export const pushDeleteSql = (
10
10
  ctx: ToSqlCtx,
11
- model: QueryBase,
11
+ table: QueryBase,
12
12
  query: DeleteQueryData,
13
13
  quotedAs: string,
14
14
  ) => {
15
- const from = q(model.table as string);
15
+ const from = q(table.table as string);
16
16
  ctx.sql.push(`DELETE FROM ${from}`);
17
17
 
18
18
  if (from !== quotedAs) {
@@ -22,7 +22,7 @@ export const pushDeleteSql = (
22
22
  let conditions: string | undefined;
23
23
  if (query.join?.length) {
24
24
  const items = query.join.map((item) =>
25
- processJoinItem(ctx, model, item.args, quotedAs),
25
+ processJoinItem(ctx, table, item.args, quotedAs),
26
26
  );
27
27
 
28
28
  ctx.sql.push(`USING ${items.map((item) => item.target).join(', ')}`);
@@ -33,7 +33,7 @@ export const pushDeleteSql = (
33
33
  .join(' AND ');
34
34
  }
35
35
 
36
- pushWhereStatementSql(ctx, model, query, quotedAs);
36
+ pushWhereStatementSql(ctx, table, query, quotedAs);
37
37
 
38
38
  if (conditions?.length) {
39
39
  if (query.and?.length || query.or?.length) {
@@ -43,5 +43,5 @@ export const pushDeleteSql = (
43
43
  }
44
44
  }
45
45
 
46
- pushReturningSql(ctx, model, query, quotedAs);
46
+ pushReturningSql(ctx, table, query, quotedAs);
47
47
  };
@@ -7,14 +7,14 @@ import { SelectQueryData } from './data';
7
7
 
8
8
  export const pushFromAndAs = (
9
9
  ctx: ToSqlCtx,
10
- model: QueryBase,
10
+ table: QueryBase,
11
11
  query: SelectQueryData,
12
12
  quotedAs?: string,
13
13
  ) => {
14
14
  ctx.sql.push('FROM');
15
15
  if (query.fromOnly) ctx.sql.push('ONLY');
16
16
 
17
- const from = getFrom(model, query, ctx.values);
17
+ const from = getFrom(table, query, ctx.values);
18
18
  ctx.sql.push(from);
19
19
 
20
20
  if (query.as && quotedAs && quotedAs !== from) {
@@ -23,7 +23,7 @@ export const pushFromAndAs = (
23
23
  };
24
24
 
25
25
  const getFrom = (
26
- model: QueryBase,
26
+ table: QueryBase,
27
27
  query: SelectQueryData,
28
28
  values: unknown[],
29
29
  ) => {
@@ -51,5 +51,5 @@ const getFrom = (
51
51
  return quoteSchemaAndTable(query.schema, query.from);
52
52
  }
53
53
 
54
- return quoteSchemaAndTable(query.schema, model.table as string);
54
+ return quoteSchemaAndTable(query.schema, table.table as string);
55
55
  };
package/src/sql/having.ts CHANGED
@@ -17,17 +17,17 @@ const aggregateOptionNames: (keyof AggregateItemOptions)[] = [
17
17
 
18
18
  export const pushHavingSql = (
19
19
  ctx: ToSqlCtx,
20
- model: QueryBase,
20
+ table: QueryBase,
21
21
  query: SelectQueryData,
22
22
  quotedAs?: string,
23
23
  ) => {
24
- const conditions = havingToSql(ctx, model, query, quotedAs);
24
+ const conditions = havingToSql(ctx, table, query, quotedAs);
25
25
  if (conditions.length) ctx.sql.push('HAVING', conditions);
26
26
  };
27
27
 
28
28
  export const havingToSql = (
29
29
  ctx: ToSqlCtx,
30
- model: QueryBase,
30
+ table: QueryBase,
31
31
  query: SelectQueryData,
32
32
  quotedAs?: string,
33
33
  ): string => {
@@ -43,7 +43,7 @@ export const havingToSql = (
43
43
  or.forEach((and) => {
44
44
  const ands: string[] = [];
45
45
  and.forEach((item) => {
46
- if ('prototype' in item || '__model' in item) {
46
+ if ('prototype' in item || '__table' in item) {
47
47
  const query = item as QueryBase;
48
48
  const sql = havingToSql(
49
49
  ctx,
@@ -76,7 +76,7 @@ export const havingToSql = (
76
76
  op as keyof AggregateItemOptions,
77
77
  )
78
78
  ) {
79
- const operator = model.shape[column].operators[
79
+ const operator = table.shape[column].operators[
80
80
  op
81
81
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
82
82
  ] as Operator<any>;
@@ -89,7 +89,7 @@ export const havingToSql = (
89
89
 
90
90
  const expression = aggregateToSql(
91
91
  ctx,
92
- model,
92
+ table,
93
93
  {
94
94
  function: key,
95
95
  arg: column,
@@ -111,7 +111,7 @@ export const havingToSql = (
111
111
  ands.push(
112
112
  `${aggregateToSql(
113
113
  ctx,
114
- model,
114
+ table,
115
115
  {
116
116
  function: key,
117
117
  arg: column,
package/src/sql/insert.ts CHANGED
@@ -9,7 +9,7 @@ import { InsertQueryData, QueryData } from './data';
9
9
 
10
10
  export const pushInsertSql = (
11
11
  ctx: ToSqlCtx,
12
- model: QueryBase,
12
+ table: QueryBase,
13
13
  query: InsertQueryData,
14
14
  quotedAs: string,
15
15
  ) => {
@@ -87,8 +87,8 @@ export const pushInsertSql = (
87
87
  }
88
88
  }
89
89
 
90
- pushWhereStatementSql(ctx, model, query, quotedAs);
91
- pushReturningSql(ctx, model, query, quotedAs);
90
+ pushWhereStatementSql(ctx, table, query, quotedAs);
91
+ pushReturningSql(ctx, table, query, quotedAs);
92
92
  };
93
93
 
94
94
  const encodeRow = (ctx: ToSqlCtx, row: unknown[]) => {
@@ -101,11 +101,11 @@ const encodeRow = (ctx: ToSqlCtx, row: unknown[]) => {
101
101
 
102
102
  export const pushReturningSql = (
103
103
  ctx: ToSqlCtx,
104
- model: QueryBase,
104
+ table: QueryBase,
105
105
  query: QueryData,
106
106
  quotedAs: string,
107
107
  ) => {
108
108
  if (query.select) {
109
- ctx.sql.push(`RETURNING ${selectToSql(ctx, model, query, quotedAs)}`);
109
+ ctx.sql.push(`RETURNING ${selectToSql(ctx, table, query, quotedAs)}`);
110
110
  }
111
111
  };
package/src/sql/join.ts CHANGED
@@ -22,7 +22,7 @@ type ItemOf3Or4Length =
22
22
 
23
23
  export const processJoinItem = (
24
24
  ctx: ToSqlCtx,
25
- model: QueryBase,
25
+ table: QueryBase,
26
26
  args: JoinItem['args'],
27
27
  quotedAs?: string,
28
28
  ): { target: string; conditions?: string } => {
@@ -31,25 +31,25 @@ export const processJoinItem = (
31
31
 
32
32
  const [first] = args;
33
33
  if (typeof first === 'string') {
34
- if (first in model.relations) {
34
+ if (first in table.relations) {
35
35
  const {
36
36
  key,
37
37
  query: toQuery,
38
38
  joinQuery,
39
- } = (model.relations as Record<string, Relation>)[first];
39
+ } = (table.relations as Record<string, Relation>)[first];
40
40
 
41
- const jq = joinQuery(model, toQuery);
41
+ const jq = joinQuery(table, toQuery);
42
42
  const { query } = jq;
43
43
 
44
- const table = (
44
+ const tableName = (
45
45
  typeof query.from === 'string' ? query.from : jq.table
46
46
  ) as string;
47
47
 
48
- target = quoteSchemaAndTable(query.schema, table);
48
+ target = quoteSchemaAndTable(query.schema, tableName);
49
49
 
50
50
  const as = query.as || key;
51
51
  const joinAs = q(as as string);
52
- if (as !== table) {
52
+ if (as !== tableName) {
53
53
  target += ` AS ${joinAs}`;
54
54
  }
55
55
 
@@ -60,7 +60,7 @@ export const processJoinItem = (
60
60
 
61
61
  if (args[1]) {
62
62
  const arg = (args[1] as (q: unknown) => QueryBase)(
63
- new ctx.onQueryBuilder(jq, jq.shape, model),
63
+ new ctx.onQueryBuilder(jq, jq.shape, table),
64
64
  ).query;
65
65
 
66
66
  if (arg.and) queryData.and.push(...arg.and);
@@ -70,7 +70,7 @@ export const processJoinItem = (
70
70
  conditions = whereToSql(ctx, jq, queryData, joinAs);
71
71
  } else {
72
72
  target = q(first);
73
- conditions = processArgs(args, ctx, model, first, target, quotedAs);
73
+ conditions = processArgs(args, ctx, table, first, target, quotedAs);
74
74
  }
75
75
  } else {
76
76
  const query = first.query;
@@ -89,9 +89,9 @@ export const processJoinItem = (
89
89
  }
90
90
  }
91
91
 
92
- conditions = processArgs(args, ctx, model, first, joinAs, quotedAs);
92
+ conditions = processArgs(args, ctx, table, first, joinAs, quotedAs);
93
93
 
94
- const whereSql = whereToSql(ctx, model, query, joinAs);
94
+ const whereSql = whereToSql(ctx, table, query, joinAs);
95
95
  if (whereSql) {
96
96
  if (conditions) conditions += ` AND ${whereSql}`;
97
97
  else conditions = whereSql;
@@ -104,7 +104,7 @@ export const processJoinItem = (
104
104
  const processArgs = (
105
105
  args: JoinItem['args'],
106
106
  ctx: ToSqlCtx,
107
- model: QueryBase,
107
+ table: QueryBase,
108
108
  first: string | QueryWithTable,
109
109
  joinAs: string,
110
110
  quotedAs?: string,
@@ -114,7 +114,7 @@ const processArgs = (
114
114
  if (typeof arg === 'function') {
115
115
  let shape;
116
116
  if (typeof first === 'string') {
117
- shape = model.query.withShapes?.[first];
117
+ shape = table.query.withShapes?.[first];
118
118
  if (!shape) {
119
119
  throw new Error('Cannot get shape of `with` statement');
120
120
  }
@@ -122,7 +122,7 @@ const processArgs = (
122
122
  shape = first.shape;
123
123
  }
124
124
 
125
- const jq = arg(new ctx.onQueryBuilder(first, shape, model));
125
+ const jq = arg(new ctx.onQueryBuilder(first, shape, table));
126
126
  return whereToSql(ctx, jq, jq.query, joinAs);
127
127
  } else {
128
128
  return getObjectOrRawConditions(arg, ctx.values, quotedAs, joinAs);
@@ -189,7 +189,7 @@ const getObjectOrRawConditions = (
189
189
 
190
190
  export const pushJoinSql = (
191
191
  ctx: ToSqlCtx,
192
- model: QueryBase,
192
+ table: QueryBase,
193
193
  query: QueryData & {
194
194
  join: JoinItem[];
195
195
  },
@@ -198,7 +198,7 @@ export const pushJoinSql = (
198
198
  query.join.forEach((item) => {
199
199
  const { target, conditions } = processJoinItem(
200
200
  ctx,
201
- model,
201
+ table,
202
202
  item.args,
203
203
  quotedAs,
204
204
  );
package/src/sql/select.ts CHANGED
@@ -65,16 +65,16 @@ const jsonToSql = (
65
65
 
66
66
  export const pushSelectSql = (
67
67
  ctx: ToSqlCtx,
68
- model: QueryBase,
68
+ table: QueryBase,
69
69
  query: Pick<SelectQueryData, 'select' | 'join'>,
70
70
  quotedAs?: string,
71
71
  ) => {
72
- ctx.sql.push(selectToSql(ctx, model, query, quotedAs));
72
+ ctx.sql.push(selectToSql(ctx, table, query, quotedAs));
73
73
  };
74
74
 
75
75
  export const selectToSql = (
76
76
  ctx: ToSqlCtx,
77
- model: QueryBase,
77
+ table: QueryBase,
78
78
  query: Pick<SelectQueryData, 'select' | 'join'>,
79
79
  quotedAs?: string,
80
80
  ): string => {
@@ -116,13 +116,13 @@ export const selectToSql = (
116
116
  list.push(
117
117
  `${(item as SelectFunctionItem).function}(${selectToSql(
118
118
  ctx,
119
- model,
119
+ table,
120
120
  { select: item.arguments },
121
121
  quotedAs,
122
122
  )})${item.as ? ` AS ${q((item as { as: string }).as)}` : ''}`,
123
123
  );
124
124
  } else {
125
- list.push(aggregateToSql(ctx, model, item, quotedAs));
125
+ list.push(aggregateToSql(ctx, table, item, quotedAs));
126
126
  }
127
127
  }
128
128
  });
@@ -160,7 +160,7 @@ const pushSubQuerySql = (
160
160
 
161
161
  select.length = 0;
162
162
  select[0] = { selectAs: { c: first } } as SelectItem;
163
- query = query._wrap(query.__model.clone()) as unknown as typeof query;
163
+ query = query._wrap(query.__table.clone()) as unknown as typeof query;
164
164
  query._getOptional(raw(`COALESCE(json_agg("c"), '[]')`));
165
165
  break;
166
166
  }
package/src/sql/toSql.ts CHANGED
@@ -35,22 +35,22 @@ export type ToSqlOptions = {
35
35
  values?: unknown[];
36
36
  };
37
37
 
38
- export const toSql = (model: Query, options?: ToSqlOptions): Sql => {
38
+ export const toSql = (table: Query, options?: ToSqlOptions): Sql => {
39
39
  return (
40
- (!options?.clearCache && model.query[toSqlCacheKey]) ||
41
- (model.query[toSqlCacheKey] = makeSql(model, options))
40
+ (!options?.clearCache && table.query[toSqlCacheKey]) ||
41
+ (table.query[toSqlCacheKey] = makeSql(table, options))
42
42
  );
43
43
  };
44
44
 
45
45
  export const makeSql = (
46
- model: Query,
46
+ table: Query,
47
47
  { values = [] }: ToSqlOptions = {},
48
48
  ): Sql => {
49
- const query = model.query;
49
+ const query = table.query;
50
50
  const sql: string[] = [];
51
51
  const ctx: ToSqlCtx = {
52
- whereQueryBuilder: model.whereQueryBuilder,
53
- onQueryBuilder: model.onQueryBuilder,
52
+ whereQueryBuilder: table.whereQueryBuilder,
53
+ onQueryBuilder: table.onQueryBuilder,
54
54
  sql,
55
55
  values,
56
56
  };
@@ -61,45 +61,45 @@ export const makeSql = (
61
61
 
62
62
  if (query.type) {
63
63
  if (query.type === 'truncate') {
64
- if (!model.table) throw new Error('Table is missing for truncate');
64
+ if (!table.table) throw new Error('Table is missing for truncate');
65
65
 
66
- pushTruncateSql(ctx, model.table, query);
66
+ pushTruncateSql(ctx, table.table, query);
67
67
  return { text: sql.join(' '), values };
68
68
  }
69
69
 
70
70
  if (query.type === 'columnInfo') {
71
- if (!model.table) throw new Error('Table is missing for truncate');
71
+ if (!table.table) throw new Error('Table is missing for truncate');
72
72
 
73
- pushColumnInfoSql(ctx, model.table, query);
73
+ pushColumnInfoSql(ctx, table.table, query);
74
74
  return { text: sql.join(' '), values };
75
75
  }
76
76
 
77
- if (!model.table) throw new Error(`Table is missing for ${query.type}`);
77
+ if (!table.table) throw new Error(`Table is missing for ${query.type}`);
78
78
 
79
- const quotedAs = q(query.as || model.table);
79
+ const quotedAs = q(query.as || table.table);
80
80
 
81
81
  if (query.type === 'insert') {
82
- pushInsertSql(ctx, model, query, q(model.table));
82
+ pushInsertSql(ctx, table, query, q(table.table));
83
83
  return { text: sql.join(' '), values };
84
84
  }
85
85
 
86
86
  if (query.type === 'update') {
87
- pushUpdateSql(ctx, model, query, quotedAs);
87
+ pushUpdateSql(ctx, table, query, quotedAs);
88
88
  return { text: sql.join(' '), values };
89
89
  }
90
90
 
91
91
  if (query.type === 'delete') {
92
- pushDeleteSql(ctx, model, query, quotedAs);
92
+ pushDeleteSql(ctx, table, query, quotedAs);
93
93
  return { text: sql.join(' '), values };
94
94
  }
95
95
 
96
96
  if (query.type === 'copy') {
97
- pushCopySql(ctx, model, query, quotedAs);
97
+ pushCopySql(ctx, table, query, quotedAs);
98
98
  return { text: sql.join(' '), values };
99
99
  }
100
100
  }
101
101
 
102
- const quotedAs = model.table && q(query.as || model.table);
102
+ const quotedAs = table.table && q(query.as || table.table);
103
103
 
104
104
  sql.push('SELECT');
105
105
 
@@ -107,23 +107,23 @@ export const makeSql = (
107
107
  pushDistinctSql(ctx, query.distinct, quotedAs);
108
108
  }
109
109
 
110
- pushSelectSql(ctx, model, query, quotedAs);
110
+ pushSelectSql(ctx, table, query, quotedAs);
111
111
 
112
- if (model.table || query.from) {
113
- pushFromAndAs(ctx, model, query, quotedAs);
112
+ if (table.table || query.from) {
113
+ pushFromAndAs(ctx, table, query, quotedAs);
114
114
  }
115
115
 
116
116
  if (query.join) {
117
117
  pushJoinSql(
118
118
  ctx,
119
- model,
119
+ table,
120
120
  query as QueryData & { join: JoinItem[] },
121
121
  quotedAs,
122
122
  );
123
123
  }
124
124
 
125
125
  if (query.and || query.or) {
126
- pushWhereStatementSql(ctx, model, query, quotedAs);
126
+ pushWhereStatementSql(ctx, table, query, quotedAs);
127
127
  }
128
128
 
129
129
  if (query.group) {
@@ -136,7 +136,7 @@ export const makeSql = (
136
136
  }
137
137
 
138
138
  if (query.having || query.havingOr) {
139
- pushHavingSql(ctx, model, query, quotedAs);
139
+ pushHavingSql(ctx, table, query, quotedAs);
140
140
  }
141
141
 
142
142
  if (query.window) {
package/src/sql/update.ts CHANGED
@@ -13,11 +13,11 @@ import {
13
13
 
14
14
  export const pushUpdateSql = (
15
15
  ctx: ToSqlCtx,
16
- model: QueryBase,
16
+ table: QueryBase,
17
17
  query: UpdateQueryData,
18
18
  quotedAs: string,
19
19
  ) => {
20
- const quotedTable = quoteSchemaAndTable(query.schema, model.table as string);
20
+ const quotedTable = quoteSchemaAndTable(query.schema, table.table as string);
21
21
  ctx.sql.push(`UPDATE ${quotedTable}`);
22
22
 
23
23
  if (quotedTable !== quotedAs) {
@@ -30,8 +30,8 @@ export const pushUpdateSql = (
30
30
  processData(ctx, set, query.updateData);
31
31
  ctx.sql.push(set.join(', '));
32
32
 
33
- pushWhereStatementSql(ctx, model, query, quotedAs);
34
- pushReturningSql(ctx, model, query, quotedAs);
33
+ pushWhereStatementSql(ctx, table, query, quotedAs);
34
+ pushReturningSql(ctx, table, query, quotedAs);
35
35
  };
36
36
 
37
37
  const processData = (
package/src/sql/where.ts CHANGED
@@ -16,11 +16,11 @@ import { QueryData } from './data';
16
16
 
17
17
  export const pushWhereStatementSql = (
18
18
  ctx: ToSqlCtx,
19
- model: QueryBase,
19
+ table: QueryBase,
20
20
  query: Pick<QueryData, 'and' | 'or'>,
21
21
  quotedAs?: string,
22
22
  ) => {
23
- const res = whereToSql(ctx, model, query, quotedAs, false);
23
+ const res = whereToSql(ctx, table, query, quotedAs, false);
24
24
  if (res) {
25
25
  ctx.sql.push('WHERE', res);
26
26
  }
@@ -29,12 +29,12 @@ export const pushWhereStatementSql = (
29
29
  export const pushWhereToSql = (
30
30
  sql: string[],
31
31
  ctx: ToSqlCtx,
32
- model: QueryBase,
32
+ table: QueryBase,
33
33
  query: Pick<QueryData, 'and' | 'or'>,
34
34
  quotedAs?: string,
35
35
  not?: boolean,
36
36
  ) => {
37
- const res = whereToSql(ctx, model, query, quotedAs, not);
37
+ const res = whereToSql(ctx, table, query, quotedAs, not);
38
38
  if (res) {
39
39
  sql.push(res);
40
40
  }
@@ -42,7 +42,7 @@ export const pushWhereToSql = (
42
42
 
43
43
  export const whereToSql = (
44
44
  ctx: ToSqlCtx,
45
- model: QueryBase,
45
+ table: QueryBase,
46
46
  query: Pick<QueryData, 'and' | 'or'>,
47
47
  quotedAs?: string,
48
48
  not?: boolean,
@@ -50,10 +50,10 @@ export const whereToSql = (
50
50
  if (query.or) {
51
51
  const ors = query.and ? [query.and, ...query.or] : query.or;
52
52
  return ors
53
- .map((and) => processAnds(and, ctx, model, quotedAs, not))
53
+ .map((and) => processAnds(and, ctx, table, quotedAs, not))
54
54
  .join(' OR ');
55
55
  } else if (query.and) {
56
- return processAnds(query.and, ctx, model, quotedAs, not);
56
+ return processAnds(query.and, ctx, table, quotedAs, not);
57
57
  } else {
58
58
  return undefined;
59
59
  }
@@ -62,19 +62,19 @@ export const whereToSql = (
62
62
  const processAnds = (
63
63
  and: WhereItem[],
64
64
  ctx: ToSqlCtx,
65
- model: QueryBase,
65
+ table: QueryBase,
66
66
  quotedAs?: string,
67
67
  not?: boolean,
68
68
  ): string => {
69
69
  const ands: string[] = [];
70
- and.forEach((data) => processWhere(ands, ctx, model, data, quotedAs, not));
70
+ and.forEach((data) => processWhere(ands, ctx, table, data, quotedAs, not));
71
71
  return ands.join(' AND ');
72
72
  };
73
73
 
74
74
  const processWhere = (
75
75
  ands: string[],
76
76
  ctx: ToSqlCtx,
77
- model: QueryBase,
77
+ table: QueryBase,
78
78
  data: WhereItem,
79
79
  quotedAs?: string,
80
80
  not?: boolean,
@@ -82,12 +82,12 @@ const processWhere = (
82
82
  const prefix = not ? 'NOT ' : '';
83
83
 
84
84
  if (typeof data === 'function') {
85
- const qb = data(new ctx.whereQueryBuilder(model, model.shape));
85
+ const qb = data(new ctx.whereQueryBuilder(table, table.shape));
86
86
  pushWhereToSql(ands, ctx, qb, qb.query, quotedAs, not);
87
87
  return;
88
88
  }
89
89
 
90
- if ('prototype' in data || '__model' in data) {
90
+ if ('prototype' in data || '__table' in data) {
91
91
  const query = data as Query;
92
92
  const sql = whereToSql(
93
93
  ctx,
@@ -110,17 +110,17 @@ const processWhere = (
110
110
  const value = (data as Record<string, unknown>)[key];
111
111
  if (key === 'AND') {
112
112
  const arr = toArray(value as MaybeArray<WhereItem>);
113
- ands.push(processAnds(arr, ctx, model, quotedAs, not));
113
+ ands.push(processAnds(arr, ctx, table, quotedAs, not));
114
114
  } else if (key === 'OR') {
115
115
  const arr = (value as MaybeArray<WhereItem>[]).map(toArray);
116
116
  ands.push(
117
117
  arr
118
- .map((and) => processAnds(and, ctx, model, quotedAs, not))
118
+ .map((and) => processAnds(and, ctx, table, quotedAs, not))
119
119
  .join(' OR '),
120
120
  );
121
121
  } else if (key === 'NOT') {
122
122
  const arr = toArray(value as MaybeArray<WhereItem>);
123
- ands.push(processAnds(arr, ctx, model, quotedAs, !not));
123
+ ands.push(processAnds(arr, ctx, table, quotedAs, !not));
124
124
  } else if (key === 'ON') {
125
125
  if (Array.isArray(value)) {
126
126
  const item = value as WhereJsonPathEqualsItem;
@@ -129,7 +129,7 @@ const processWhere = (
129
129
  const rightColumn = quoteFullColumn(
130
130
  item[2],
131
131
  getQueryAs({
132
- table: model.table,
132
+ table: table.table,
133
133
  query: { as: quotedAs },
134
134
  }),
135
135
  );
@@ -171,7 +171,7 @@ const processWhere = (
171
171
  (joinItems as JoinItem['args'][]).forEach((item) => {
172
172
  const { target, conditions } = processJoinItem(
173
173
  ctx,
174
- model,
174
+ table,
175
175
  item,
176
176
  quotedAs,
177
177
  );
@@ -193,7 +193,7 @@ const processWhere = (
193
193
  )}`,
194
194
  );
195
195
  } else {
196
- const column = model.shape[key];
196
+ const column = table.shape[key];
197
197
  if (!column) {
198
198
  // TODO: custom error classes
199
199
  throw new Error(`Unknown column ${key} provided to condition`);
package/src/utils.test.ts CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  pushOrNewArray,
6
6
  pushOrNewArrayToObject,
7
7
  SetOptional,
8
+ singleQuote,
8
9
  SomeIsTrue,
9
10
  } from './utils';
10
11
 
@@ -90,4 +91,12 @@ describe('utils', () => {
90
91
  expect(pushOrNewArray(arr, 123)).toEqual([123]);
91
92
  });
92
93
  });
94
+
95
+ describe('singleQuote', () => {
96
+ it('should put string into single quotes, escape single quotes and backslashes', () => {
97
+ expect(singleQuote(`ko`)).toBe(`'ko'`);
98
+ expect(singleQuote(`k'o`)).toBe(`'k\\'o'`);
99
+ expect(singleQuote(`k\\'o`)).toBe(`'k\\\\\\'o'`);
100
+ });
101
+ });
93
102
  });
package/src/utils.ts CHANGED
@@ -134,3 +134,6 @@ export const pushOrNewArray = <Arr extends unknown[]>(
134
134
  return [value] as Arr;
135
135
  }
136
136
  };
137
+
138
+ export const singleQuote = (s: string) =>
139
+ `'${s.replaceAll('\\', '\\\\').replaceAll("'", "\\'")}'`;