@sqb/postgres-dialect 5.0.6 → 6.0.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/README.md CHANGED
@@ -6,30 +6,25 @@
6
6
 
7
7
  [![NPM Version][npm-image]][npm-url]
8
8
  [![NPM Downloads][downloads-image]][downloads-url]
9
- [![Build Status][travis-image]][travis-url]
9
+ [![CI Tests][ci-test-image]][ci-test-url]
10
10
  [![Test Coverage][coveralls-image]][coveralls-url]
11
- [![Dependencies][dependencies-image]][dependencies-url]
12
- [![DevDependencies][devdependencies-image]][devdependencies-url]
13
- [![Package Quality][quality-image]][quality-url]
14
11
 
15
12
  ## About SQB
16
13
 
17
14
  SQB is an extensible, multi-dialect SQL query builder and Database connection wrapper for NodeJS.
18
15
 
19
- ## Main goals
16
+ ## About @sqb/postgres-dialect
20
17
 
21
- - Single code base for any sql based database
22
- - Powerful and simplified query coding scheme
23
- - Fast applications with low memory requirements
24
- - Let applications work with large data tables efficiently
25
- - Support latest JavaScript language standards
26
- - Lightweight and extensible framework.
18
+ This package registers the `postgres` SQL serialization dialect (a `SerializerExtension` for
19
+ [`@sqb/builder`](../builder)) used by [`@sqb/postgres`](../postgres). It is loaded automatically
20
+ when `@sqb/postgres` is imported, so you normally don't need to depend on it directly.
27
21
 
28
- You can report bugs and discuss features on the [GitHub issues](https://github.com/sqbjs/sqb/issues) page
29
-
30
- Thanks to all of the great [contributions](https://github.com/sqbjs/sqb/graphs/contributors) to the project.
31
-
32
- You may want to check detailed [DOCUMENTATION](https://sqbjs.github.io/sqb/)
22
+ PostgreSQL already speaks close to standard SQL, so this dialect makes fewer changes than most:
23
+ `LIMIT`/`OFFSET` for pagination, `= NULL`/`!= NULL` rewritten to `IS [NOT] NULL`, and Postgres's
24
+ own reserved-word list. It also rewrites the builder's default `:name` named placeholders into
25
+ Postgres's positional `$1, $2, ...` parameter syntax. `RETURNING` is left untouched — Postgres
26
+ supports it natively on `INSERT`, `UPDATE` and `DELETE`, so `@sqb/postgres` reads affected rows
27
+ straight from the statement response with no follow-up query needed.
33
28
 
34
29
  ## Installation
35
30
 
@@ -39,7 +34,7 @@ $ npm install @sqb/postgres-dialect --save
39
34
 
40
35
  ## Node Compatibility
41
36
 
42
- - node >= 16.x
37
+ - node >= 20.x
43
38
 
44
39
  ### License
45
40
 
@@ -47,17 +42,9 @@ SQB is available under [MIT](LICENSE) license.
47
42
 
48
43
  [npm-image]: https://img.shields.io/npm/v/@sqb/postgres-dialect.svg
49
44
  [npm-url]: https://npmjs.org/package/@sqb/postgres-dialect
50
- [travis-image]: https://img.shields.io/travis/sqbjs/@sqb/postgres-dialect/master.svg
51
- [travis-url]: https://travis-ci.org/sqbjs/@sqb/postgres-dialect
52
- [coveralls-image]: https://img.shields.io/coveralls/sqbjs/@sqb/postgres-dialect/master.svg
53
- [coveralls-url]: https://coveralls.io/r/sqbjs/@sqb/postgres-dialect
54
45
  [downloads-image]: https://img.shields.io/npm/dm/@sqb/postgres-dialect.svg
55
46
  [downloads-url]: https://npmjs.org/package/@sqb/postgres-dialect
56
- [gitter-image]: https://badges.gitter.im/sqbjs/@sqb/postgres-dialect.svg
57
- [gitter-url]: https://gitter.im/sqbjs/@sqb/postgres-dialect?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
58
- [dependencies-image]: https://david-dm.org/sqbjs/@sqb/postgres-dialect/status.svg
59
- [dependencies-url]: https://david-dm.org/sqbjs/@sqb/postgres-dialect
60
- [devdependencies-image]: https://david-dm.org/sqbjs/@sqb/postgres-dialect/dev-status.svg
61
- [devdependencies-url]: https://david-dm.org/sqbjs/@sqb/postgres-dialect?type=dev
62
- [quality-image]: http://npm.packagequality.com/shield/@sqb/postgres-dialect.png
63
- [quality-url]: http://packagequality.com/#?package=@sqb/postgres-dialect
47
+ [ci-test-image]: https://github.com/panates/sqb/actions/workflows/test.yml/badge.svg
48
+ [ci-test-url]: https://github.com/panates/sqb/actions/workflows/test.yml
49
+ [coveralls-image]: https://coveralls.io/repos/github/sqbjs/sqb/badge.svg?branch=master
50
+ [coveralls-url]: https://coveralls.io/github/sqbjs/sqb?branch=master
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@sqb/postgres-dialect",
3
3
  "description": "SQB serialization extension for PostgreSQL database",
4
- "version": "5.0.6",
4
+ "version": "6.0.0",
5
5
  "author": "Panates",
6
6
  "license": "Apache-2.0",
7
7
  "dependencies": {
8
8
  "tslib": "^2.8.1"
9
9
  },
10
10
  "peerDependencies": {
11
- "@sqb/builder": "^5.0.6"
11
+ "@sqb/builder": "^6.0.0"
12
12
  },
13
13
  "type": "module",
14
14
  "module": "./index.js",
@@ -1,7 +1,8 @@
1
1
  import { type DefaultSerializeFunction, SerializationType, SerializeContext, type SerializerExtension } from '@sqb/builder';
2
2
  export declare class PostgresSerializer implements SerializerExtension {
3
3
  dialect: string;
4
- isReservedWord(ctx: any, s: any): any;
4
+ reservedWords: Set<string>;
5
+ isReservedWord(_: any, s: any): boolean;
5
6
  serialize(ctx: SerializeContext, type: SerializationType | string, o: any, defFn: DefaultSerializeFunction): string | undefined;
6
7
  private _serializeSelect;
7
8
  private _serializeComparison;
@@ -1,9 +1,69 @@
1
1
  import { OperatorType, SerializationType, SerializeContext, } from '@sqb/builder';
2
- const reservedWords = ['comment'];
2
+ // PostgreSQL "reserved" and "reserved (can be function or type)" keywords
3
+ // (https://www.postgresql.org/docs/current/sql-keywords-appendix.html)
4
+ // that are not already covered by SerializeContext's base reservedWords list.
5
+ // Keywords common to all SQL dialects (case, check, union, ...) live in
6
+ // SerializeContext.reservedWords instead of being duplicated here.
7
+ const reservedWords = new Set([
8
+ 'analyse',
9
+ 'analyze',
10
+ 'any',
11
+ 'array',
12
+ 'asymmetric',
13
+ 'binary',
14
+ 'both',
15
+ 'collate',
16
+ 'collation',
17
+ 'comment',
18
+ 'concurrently',
19
+ 'cross',
20
+ 'current_catalog',
21
+ 'current_date',
22
+ 'current_role',
23
+ 'current_schema',
24
+ 'current_time',
25
+ 'current_timestamp',
26
+ 'current_user',
27
+ 'deferrable',
28
+ 'do',
29
+ 'except',
30
+ 'false',
31
+ 'fetch',
32
+ 'freeze',
33
+ 'grant',
34
+ 'initially',
35
+ 'intersect',
36
+ 'isnull',
37
+ 'lateral',
38
+ 'leading',
39
+ 'limit',
40
+ 'localtime',
41
+ 'localtimestamp',
42
+ 'natural',
43
+ 'notnull',
44
+ 'offset',
45
+ 'only',
46
+ 'overlaps',
47
+ 'placing',
48
+ 'returning',
49
+ 'session_user',
50
+ 'similar',
51
+ 'some',
52
+ 'symmetric',
53
+ 'system_user',
54
+ 'tablesample',
55
+ 'trailing',
56
+ 'true',
57
+ 'using',
58
+ 'variadic',
59
+ 'verbose',
60
+ 'window',
61
+ ]);
3
62
  export class PostgresSerializer {
4
63
  dialect = 'postgres';
5
- isReservedWord(ctx, s) {
6
- return (s && typeof s === 'string' && reservedWords.includes(s.toLowerCase()));
64
+ reservedWords = reservedWords;
65
+ isReservedWord(_, s) {
66
+ return s && typeof s === 'string' && reservedWords.has(s.toLowerCase());
7
67
  }
8
68
  serialize(ctx, type, o, defFn) {
9
69
  switch (type) {
@@ -48,7 +108,7 @@ export class PostgresSerializer {
48
108
  o.right.expression = 'null';
49
109
  o.right.isParam = false;
50
110
  }
51
- if (o.operatorType === 'eq')
111
+ if (o.operatorType === OperatorType.eq)
52
112
  return defFn(ctx, {
53
113
  ...o,
54
114
  operatorType: OperatorType.is,
@@ -73,7 +133,8 @@ export class PostgresSerializer {
73
133
  !Array.isArray(o.right.value)) {
74
134
  o.right.value = [o.right.value];
75
135
  }
76
- if (o.operatorType === 'in' || o.operatorType === 'notIn') {
136
+ if (o.operatorType === OperatorType.in ||
137
+ o.operatorType === OperatorType.notIn) {
77
138
  if (o.left.isArray && !o.right.isArray && o.right.isParam) {
78
139
  const left = o.left;
79
140
  const right = o.right;
@@ -81,13 +142,13 @@ export class PostgresSerializer {
81
142
  return defFn(ctx, {
82
143
  ...o,
83
144
  operatorType: OperatorType.eq,
84
- symbol: o.operatorType === 'notIn' ? '!=' : '=',
145
+ symbol: o.operatorType === OperatorType.notIn ? '!=' : '=',
85
146
  left: right,
86
147
  right: left,
87
148
  });
88
149
  }
89
150
  if (o.left.isArray && o.right.isArray) {
90
- if (o.operatorType === 'notIn')
151
+ if (o.operatorType === OperatorType.notIn)
91
152
  o.left.expression = 'not ' + o.left.expression;
92
153
  return defFn(ctx, { ...o, symbol: '&&' });
93
154
  }
@@ -96,10 +157,20 @@ export class PostgresSerializer {
96
157
  return defFn(ctx, {
97
158
  ...o,
98
159
  operatorType: OperatorType.eq,
99
- symbol: o.operatorType === 'notIn' ? '!=' : '=',
160
+ symbol: o.operatorType === OperatorType.notIn ? '!=' : '=',
100
161
  });
101
162
  }
102
163
  }
164
+ if (o.operatorType === OperatorType.match) {
165
+ const config = o.customArgs
166
+ ? typeof o.customArgs === 'object'
167
+ ? o.customArgs
168
+ : String(o.customArgs)
169
+ : undefined;
170
+ o.symbol = '@@';
171
+ o.right.expression = `plainto_tsquery('${(config || 'simple').replace(/'/g, '"')}', ${o.right.expression})`;
172
+ return defFn(ctx, o);
173
+ }
103
174
  }
104
175
  return defFn(ctx, o);
105
176
  }