pqb 0.3.0 → 0.3.2

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/src/sql/update.ts CHANGED
@@ -1,10 +1,15 @@
1
1
  import { QueryBase } from '../query';
2
- import { UpdateQueryData } from './types';
2
+ import {
3
+ UpdateQueryData,
4
+ UpdateQueryDataItem,
5
+ UpdateQueryDataObject,
6
+ } from './types';
3
7
  import { addValue, q, quoteSchemaAndTable } from './common';
4
- import { getRaw, isRaw, RawExpression } from '../common';
8
+ import { getRaw, isRaw } from '../common';
5
9
  import { pushReturningSql } from './insert';
6
10
  import { pushWhereStatementSql } from './where';
7
11
  import { ToSqlCtx } from './toSql';
12
+ import { pushOrNewArray } from '../utils';
8
13
 
9
14
  export const pushUpdateSql = (
10
15
  ctx: ToSqlCtx,
@@ -22,8 +27,24 @@ export const pushUpdateSql = (
22
27
  ctx.sql.push('SET');
23
28
 
24
29
  const set: string[] = [];
25
- query.data.forEach((item) => {
26
- if (isRaw(item)) {
30
+ processData(ctx, set, query.updateData);
31
+ ctx.sql.push(set.join(', '));
32
+
33
+ pushWhereStatementSql(ctx, model, query, quotedAs);
34
+ pushReturningSql(ctx, model, query, quotedAs);
35
+ };
36
+
37
+ const processData = (
38
+ ctx: ToSqlCtx,
39
+ set: string[],
40
+ data: UpdateQueryDataItem[],
41
+ ) => {
42
+ let append: UpdateQueryDataItem[] | undefined;
43
+ data.forEach((item) => {
44
+ if (typeof item === 'function') {
45
+ const result = item(data);
46
+ if (result) append = pushOrNewArray(append, result);
47
+ } else if (isRaw(item)) {
27
48
  set.push(getRaw(item, ctx.values));
28
49
  } else {
29
50
  for (const key in item) {
@@ -34,16 +55,14 @@ export const pushUpdateSql = (
34
55
  }
35
56
  }
36
57
  });
37
- ctx.sql.push(set.join(', '));
38
58
 
39
- pushWhereStatementSql(ctx, model, query, quotedAs);
40
- pushReturningSql(ctx, model, query, quotedAs);
59
+ if (append) processData(ctx, set, append);
41
60
  };
42
61
 
43
62
  const processValue = (
44
63
  values: unknown[],
45
64
  key: string,
46
- value: Exclude<UpdateQueryData['data'][number], RawExpression>[string],
65
+ value: UpdateQueryDataObject[string],
47
66
  ) => {
48
67
  if (value && typeof value === 'object') {
49
68
  if (isRaw(value)) {
package/src/sql/where.ts CHANGED
@@ -252,7 +252,7 @@ const pushIn = (
252
252
  } else if (isRaw(arg.values)) {
253
253
  value = getRaw(arg.values, values);
254
254
  } else {
255
- const sql = arg.values.toSql(values);
255
+ const sql = arg.values.toSql({ values });
256
256
  value = `(${sql.text})`;
257
257
  }
258
258
 
package/src/sql/with.ts CHANGED
@@ -14,7 +14,7 @@ export const pushWithSql = (
14
14
  if (isRaw(query)) {
15
15
  inner = getRaw(query, ctx.values);
16
16
  } else {
17
- inner = query.toSql(ctx.values).text;
17
+ inner = query.toSql({ values: ctx.values }).text;
18
18
  }
19
19
 
20
20
  ctx.sql.push(
package/src/utils.test.ts CHANGED
@@ -1,5 +1,15 @@
1
1
  import { assertType } from './test-utils';
2
- import { MaybeArray, SetOptional, SomeIsTrue } from './utils';
2
+ import {
3
+ GetTypeOrRaw,
4
+ GetTypesOrRaw,
5
+ makeRegexToFindInSql,
6
+ MaybeArray,
7
+ pushOrNewArray,
8
+ pushOrNewArrayToObject,
9
+ SetOptional,
10
+ SomeIsTrue,
11
+ } from './utils';
12
+ import { RawExpression } from './common';
3
13
 
4
14
  describe('utils', () => {
5
15
  describe('SomeIsTrue', () => {
@@ -22,7 +32,7 @@ describe('utils', () => {
22
32
  });
23
33
  });
24
34
 
25
- describe('setOptional', () => {
35
+ describe('SetOptional', () => {
26
36
  it('should make specified keys optional', () => {
27
37
  assertType<
28
38
  SetOptional<{ a: number; b: string; c: boolean }, 'b' | 'c'>,
@@ -34,4 +44,68 @@ describe('utils', () => {
34
44
  >();
35
45
  });
36
46
  });
47
+
48
+ describe('GetTypesOrRaw', () => {
49
+ it('should add each element to union with RawExpression', () => {
50
+ assertType<
51
+ GetTypesOrRaw<[number, string]>,
52
+ [number | RawExpression, string | RawExpression]
53
+ >();
54
+ });
55
+ });
56
+
57
+ describe('GetTypeOrRaw', () => {
58
+ it('should add type to union with RawExpression', () => {
59
+ assertType<GetTypeOrRaw<number>, number | RawExpression>();
60
+ });
61
+ });
62
+
63
+ describe('makeRegexToFindWordInSql', () => {
64
+ it('should return a proper regex', () => {
65
+ const regex = makeRegexToFindInSql('\\bupdatedAt\\b');
66
+
67
+ expect('koupdatedAtko'.match(regex)).toBe(null);
68
+ expect('updatedAtko'.match(regex)).toBe(null);
69
+ expect('koupdatedAt'.match(regex)).toBe(null);
70
+ expect('updatedAt'.match(regex)).toEqual(['updatedAt']);
71
+ expect(' updatedAt '.match(regex)).toEqual(['updatedAt']);
72
+ expect("'updatedAt'".match(regex)).toEqual(null);
73
+ });
74
+ });
75
+
76
+ describe('pushOrNewArrayToObject', () => {
77
+ it('should define new array with value when object has no array by provided key', () => {
78
+ const obj: { ko?: number[] } = {};
79
+
80
+ pushOrNewArrayToObject(obj, 'ko', 123);
81
+
82
+ expect(obj).toEqual({
83
+ ko: [123],
84
+ });
85
+ });
86
+
87
+ it('should push value to array when obj has array by provided key', () => {
88
+ const obj = { ko: [] as number[] };
89
+
90
+ pushOrNewArrayToObject(obj, 'ko', 123);
91
+
92
+ expect(obj).toEqual({
93
+ ko: [123],
94
+ });
95
+ });
96
+ });
97
+
98
+ describe('pushOrNewArray', () => {
99
+ it('should return new array with value when array is not provided', () => {
100
+ const arr: number[] | undefined = undefined;
101
+
102
+ expect(pushOrNewArray(arr, 123)).toEqual([123]);
103
+ });
104
+
105
+ it('should push value to array when array is provided', () => {
106
+ const arr: number[] | undefined = [];
107
+
108
+ expect(pushOrNewArray(arr, 123)).toEqual([123]);
109
+ });
110
+ });
37
111
  });
package/src/utils.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { RawExpression } from './common';
2
- import { QueryData } from './sql';
2
+ import { QueryData, toSqlCacheKey } from './sql';
3
3
 
4
4
  export type SomeIsTrue<T extends unknown[]> = T extends [
5
5
  infer Head,
@@ -124,7 +124,7 @@ export const joinTruthy = (...strings: (string | false | undefined)[]) => {
124
124
  };
125
125
 
126
126
  export const getClonedQueryData = (query: QueryData): QueryData => {
127
- const cloned = { ...query };
127
+ const cloned = { ...query, [toSqlCacheKey]: undefined };
128
128
 
129
129
  for (const key in query) {
130
130
  if (Array.isArray(query[key as keyof QueryData])) {
@@ -150,3 +150,33 @@ export const noop = () => {};
150
150
 
151
151
  export type EmptyObject = typeof emptyObject;
152
152
  export const emptyObject = {};
153
+
154
+ export const makeRegexToFindInSql = (value: string) => {
155
+ return new RegExp(`${value}(?=(?:[^']*'[^']*')*[^']*$)`, 'g');
156
+ };
157
+
158
+ export const pushOrNewArrayToObject = <
159
+ Obj extends EmptyObject,
160
+ Key extends keyof Obj,
161
+ >(
162
+ obj: Obj,
163
+ key: Key,
164
+ value: Exclude<Obj[Key], undefined> extends unknown[]
165
+ ? Exclude<Obj[Key], undefined>[number]
166
+ : never,
167
+ ) => {
168
+ if (obj[key]) (obj[key] as unknown as unknown[]).push(value);
169
+ else (obj[key] as unknown as unknown[]) = [value];
170
+ };
171
+
172
+ export const pushOrNewArray = <Arr extends unknown[]>(
173
+ arr: Arr | undefined,
174
+ value: Arr[number],
175
+ ): Arr => {
176
+ if (arr) {
177
+ arr.push(value);
178
+ return arr;
179
+ } else {
180
+ return [value] as Arr;
181
+ }
182
+ };