@sqb/builder 4.25.0 → 4.26.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.
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@sqb/builder",
3
3
  "description": "Extensible multi-dialect SQL query builder written with TypeScript",
4
- "version": "4.25.0",
4
+ "version": "4.26.1",
5
5
  "author": "Panates",
6
6
  "license": "Apache-2.0",
7
7
  "dependencies": {
8
8
  "debug": "^4.4.3",
9
+ "fast-tokenizer": "^1.9.0",
9
10
  "putil-flattentext": "^2.1.1",
10
11
  "putil-isplainobject": "^1.1.5",
11
12
  "putil-merge": "^3.13.0",
@@ -7,7 +7,7 @@ import { Query } from './query.js';
7
7
  export declare class DeleteQuery extends Query {
8
8
  _table: TableName | RawStatement;
9
9
  _where?: LogicalOperator;
10
- constructor(tableName: string | RawStatement);
10
+ constructor(tableName: string | TableName | RawStatement);
11
11
  get _type(): SerializationType;
12
12
  /**
13
13
  * Defines "where" part of query
@@ -8,12 +8,18 @@ export class DeleteQuery extends Query {
8
8
  _where;
9
9
  constructor(tableName) {
10
10
  super();
11
- if (!tableName ||
12
- !(typeof tableName === 'string' || isRawStatement(tableName))) {
11
+ if (!(tableName &&
12
+ (tableName instanceof TableName ||
13
+ typeof tableName === 'string' ||
14
+ isRawStatement(tableName)))) {
13
15
  throw new TypeError('String or Raw instance required as first argument (tableName) for UpdateQuery');
14
16
  }
15
17
  this._table =
16
- typeof tableName === 'string' ? new TableName(tableName) : tableName;
18
+ tableName instanceof TableName
19
+ ? tableName
20
+ : typeof tableName === 'string'
21
+ ? new TableName(tableName)
22
+ : tableName;
17
23
  }
18
24
  get _type() {
19
25
  return SerializationType.DELETE_QUERY;
@@ -33,8 +39,6 @@ export class DeleteQuery extends Query {
33
39
  const o = {
34
40
  table: this._table._serialize(ctx),
35
41
  where: this._serializeWhere(ctx),
36
- indexHint: this._indexHint.filter(x => !ctx.dialect || !x.dialect?.length || x.dialect.includes(ctx.dialect)),
37
- noIndexHint: this._noIndexHint.filter(x => !ctx.dialect || !x.dialect?.length || x.dialect.includes(ctx.dialect)),
38
42
  };
39
43
  return ctx.serialize(this._type, o, () => this.__defaultSerialize(ctx, o));
40
44
  }
@@ -32,8 +32,6 @@ export class InsertQuery extends ReturningQuery {
32
32
  columns: this.__serializeColumns(ctx),
33
33
  values: this.__serializeValues(ctx),
34
34
  returning: this.__serializeReturning(ctx),
35
- indexHint: this._indexHint.filter(x => !ctx.dialect || !x.dialect?.length || x.dialect.includes(ctx.dialect)),
36
- noIndexHint: this._noIndexHint.filter(x => !ctx.dialect || !x.dialect?.length || x.dialect.includes(ctx.dialect)),
37
35
  };
38
36
  let out = 'insert into ' +
39
37
  o.table +
package/query/query.d.ts CHANGED
@@ -13,8 +13,6 @@ export interface QueryIndexHintArgs {
13
13
  }
14
14
  export declare abstract class Query extends Serializable {
15
15
  protected _comment: QueryCommentArgs[];
16
- protected _indexHint: QueryIndexHintArgs[];
17
- protected _noIndexHint: QueryIndexHintArgs[];
18
16
  protected _params?: Record<string, any>;
19
17
  constructor();
20
18
  /**
@@ -24,8 +22,4 @@ export declare abstract class Query extends Serializable {
24
22
  values(obj: any): this;
25
23
  comment(args: QueryCommentArgs): this;
26
24
  comment(text: string, dialect?: string[]): this;
27
- indexHint(args: QueryIndexHintArgs): this;
28
- indexHint(index: string | string[], dialect?: string[]): this;
29
- noIndexHint(args: QueryIndexHintArgs): this;
30
- noIndexHint(index: string | string[], dialect?: string[]): this;
31
25
  }
package/query/query.js CHANGED
@@ -5,8 +5,6 @@ import { Serializable } from '../serializable.js';
5
5
  import { SerializeContext } from '../serialize-context.js';
6
6
  export class Query extends Serializable {
7
7
  _comment = [];
8
- _indexHint = [];
9
- _noIndexHint = [];
10
8
  _params;
11
9
  constructor() {
12
10
  super();
@@ -60,33 +58,5 @@ export class Query extends Serializable {
60
58
  });
61
59
  return this;
62
60
  }
63
- indexHint(arg0, dialect) {
64
- if (typeof arg0 === 'object' && !Array.isArray(arg0))
65
- this._indexHint.push({
66
- index: Array.isArray(arg0.index) ? arg0.index : [arg0.index],
67
- dialect: Array.isArray(arg0.dialect) ? arg0.dialect : undefined,
68
- });
69
- else {
70
- this._indexHint.push({
71
- index: Array.isArray(arg0) ? arg0 : [arg0],
72
- dialect: Array.isArray(dialect) ? dialect : undefined,
73
- });
74
- }
75
- return this;
76
- }
77
- noIndexHint(arg0, dialect) {
78
- if (typeof arg0 === 'object' && !Array.isArray(arg0))
79
- this._noIndexHint.push({
80
- index: Array.isArray(arg0.index) ? arg0.index : [arg0.index],
81
- dialect: Array.isArray(arg0.dialect) ? arg0.dialect : undefined,
82
- });
83
- else {
84
- this._noIndexHint.push({
85
- index: Array.isArray(arg0) ? arg0 : [arg0],
86
- dialect: Array.isArray(dialect) ? dialect : undefined,
87
- });
88
- }
89
- return this;
90
- }
91
61
  }
92
62
  merge(Query.prototype, EventEmitter.prototype, { descriptor: true });
@@ -6,6 +6,7 @@ import { JoinStatement } from '../sql-objects/join-statement.js';
6
6
  import { LogicalOperator } from '../sql-objects/operators/logical-operator.js';
7
7
  import { OrderColumn } from '../sql-objects/order-column.js';
8
8
  import { RawStatement } from '../sql-objects/raw-statement.js';
9
+ import { TableName } from '../sql-objects/table-name.js';
9
10
  import { Query } from './query.js';
10
11
  import type { UnionQuery } from './union-query.js';
11
12
  export declare class SelectQuery extends Query {
@@ -28,7 +29,7 @@ export declare class SelectQuery extends Query {
28
29
  /**
29
30
  * Defines "from" part of query.
30
31
  */
31
- from(...table: (string | RawStatement | SelectQuery | UnionQuery)[]): this;
32
+ from(...table: (string | TableName | RawStatement | SelectQuery | UnionQuery)[]): this;
32
33
  /**
33
34
  * Adds "join" statements to query
34
35
  */
@@ -1,3 +1,4 @@
1
+ import { splitString } from 'fast-tokenizer';
1
2
  import { coerceToInt } from 'putil-varhelpers';
2
3
  import { SerializationType } from '../enums.js';
3
4
  import { printArray } from '../helpers.js';
@@ -6,7 +7,7 @@ import { GroupColumn } from '../sql-objects/group-column.js';
6
7
  import { OpAnd } from '../sql-objects/operators/op-and.js';
7
8
  import { OrderColumn } from '../sql-objects/order-column.js';
8
9
  import { TableName } from '../sql-objects/table-name.js';
9
- import { isJoinStatement, isSerializable } from '../typeguards.js';
10
+ import { isJoinStatement } from '../typeguards.js';
10
11
  import { Query } from './query.js';
11
12
  export class SelectQuery extends Query {
12
13
  _tables;
@@ -38,8 +39,22 @@ export class SelectQuery extends Query {
38
39
  continue;
39
40
  if (Array.isArray(arg))
40
41
  self.addColumn(...arg);
41
- else
42
- this._columns.push(isSerializable(arg) ? arg : new FieldExpression(arg));
42
+ else {
43
+ if (typeof arg === 'string') {
44
+ const items = splitString(arg, {
45
+ brackets: true,
46
+ delimiters: ',',
47
+ quotes: true,
48
+ keepQuotes: true,
49
+ keepBrackets: true,
50
+ });
51
+ items.forEach(item => {
52
+ this._columns.push(new FieldExpression(item));
53
+ });
54
+ }
55
+ else
56
+ this._columns.push(arg);
57
+ }
43
58
  }
44
59
  return this;
45
60
  }
@@ -51,7 +66,11 @@ export class SelectQuery extends Query {
51
66
  for (const arg of table) {
52
67
  if (!arg)
53
68
  continue;
54
- this._tables.push(typeof arg === 'string' ? new TableName(arg) : arg);
69
+ this._tables.push(arg instanceof TableName
70
+ ? arg
71
+ : typeof arg === 'string'
72
+ ? new TableName(arg)
73
+ : arg);
55
74
  }
56
75
  return this;
57
76
  }
@@ -142,6 +161,7 @@ export class SelectQuery extends Query {
142
161
  */
143
162
  _serialize(ctx) {
144
163
  const o = {
164
+ query: this,
145
165
  columns: this.__serializeSelectColumns(ctx),
146
166
  from: this.__serializeFrom(ctx),
147
167
  join: this.__serializeJoins(ctx),
@@ -150,13 +170,14 @@ export class SelectQuery extends Query {
150
170
  orderBy: this.__serializeOrderColumns(ctx),
151
171
  limit: this._limit,
152
172
  offset: this._offset,
153
- indexHint: this._indexHint.filter(x => !ctx.dialect || !x.dialect?.length || x.dialect.includes(ctx.dialect)),
154
- noIndexHint: this._noIndexHint.filter(x => !ctx.dialect || !x.dialect?.length || x.dialect.includes(ctx.dialect)),
173
+ optimizerHint: '',
155
174
  };
156
175
  return ctx.serialize(this._type, o, () => {
157
176
  let out = 'select';
158
177
  if (this._distinct)
159
178
  out += ' distinct';
179
+ if (o.optimizerHint)
180
+ out += ' ' + o.optimizerHint;
160
181
  // columns part
161
182
  /* istanbul ignore else */
162
183
  if (o.columns) {
@@ -221,15 +242,21 @@ export class SelectQuery extends Query {
221
242
  if (t instanceof SelectQuery) {
222
243
  if (!t._alias)
223
244
  throw new TypeError('Alias required for sub-select in "from"');
224
- arr.push('\n\t(' + s + ') ' + t._alias);
245
+ arr.push({
246
+ source: t,
247
+ text: '\n\t(' + s + ') ' + t._alias,
248
+ });
225
249
  }
226
250
  else
227
- arr.push(s);
251
+ arr.push({
252
+ source: t,
253
+ text: s,
254
+ });
228
255
  }
229
256
  }
230
257
  }
231
258
  return ctx.serialize(SerializationType.SELECT_QUERY_FROM, arr, () => {
232
- const s = arr.join(',');
259
+ const s = arr.map(x => x.text).join(',');
233
260
  return s ? 'from' + (s.substring(0, 1) !== '\n' ? ' ' : '') + s : '';
234
261
  });
235
262
  }
@@ -8,7 +8,7 @@ export declare class UpdateQuery extends ReturningQuery {
8
8
  _table: TableName | RawStatement;
9
9
  _input: any;
10
10
  _where?: LogicalOperator;
11
- constructor(tableName: string | RawStatement, input: any);
11
+ constructor(tableName: string | TableName | RawStatement, input: any);
12
12
  get _type(): SerializationType;
13
13
  /**
14
14
  * Defines "where" part of query
@@ -10,8 +10,10 @@ export class UpdateQuery extends ReturningQuery {
10
10
  _where;
11
11
  constructor(tableName, input) {
12
12
  super();
13
- if (!tableName ||
14
- !(typeof tableName === 'string' || isRawStatement(tableName))) {
13
+ if (!(tableName &&
14
+ (tableName instanceof TableName ||
15
+ typeof tableName === 'string' ||
16
+ isRawStatement(tableName)))) {
15
17
  throw new TypeError('String or Raw instance required as first argument (tableName) for UpdateQuery');
16
18
  }
17
19
  if (!input ||
@@ -19,7 +21,11 @@ export class UpdateQuery extends ReturningQuery {
19
21
  throw new TypeError('Object or Raw instance required as second argument (input) for UpdateQuery');
20
22
  }
21
23
  this._table =
22
- typeof tableName === 'string' ? new TableName(tableName) : tableName;
24
+ tableName instanceof TableName
25
+ ? tableName
26
+ : typeof tableName === 'string'
27
+ ? new TableName(tableName)
28
+ : tableName;
23
29
  this._input = input;
24
30
  }
25
31
  get _type() {
@@ -42,8 +48,6 @@ export class UpdateQuery extends ReturningQuery {
42
48
  values: this.__serializeValues(ctx),
43
49
  where: this.__serializeWhere(ctx),
44
50
  returning: this.__serializeReturning(ctx),
45
- indexHint: this._indexHint.filter(x => !ctx.dialect || !x.dialect?.length || x.dialect.includes(ctx.dialect)),
46
- noIndexHint: this._noIndexHint.filter(x => !ctx.dialect || !x.dialect?.length || x.dialect.includes(ctx.dialect)),
47
51
  };
48
52
  let out = 'update ' + o.table + ' set \n\t' + o.values + '\b';
49
53
  if (o.where)
@@ -1,11 +1,22 @@
1
1
  import { SerializationType } from '../enums.js';
2
2
  import { Serializable } from '../serializable.js';
3
3
  import { SerializeContext } from '../serialize-context.js';
4
+ export interface OptimizerHintArgs {
5
+ hint: string;
6
+ dialect?: string[];
7
+ }
8
+ export interface TableNameArgs {
9
+ schema?: string;
10
+ table: string;
11
+ alias?: string;
12
+ optimizerHint?: string | string[] | OptimizerHintArgs | OptimizerHintArgs[];
13
+ }
4
14
  export declare class TableName extends Serializable {
5
15
  schema?: string;
6
16
  table?: string;
7
17
  alias?: string;
8
- constructor(tableName: string);
18
+ optimizerHint?: OptimizerHintArgs[];
19
+ constructor(tableName: string | TableNameArgs);
9
20
  get _type(): SerializationType;
10
21
  _serialize(ctx: SerializeContext): string;
11
22
  }
@@ -4,17 +4,40 @@ export class TableName extends Serializable {
4
4
  schema;
5
5
  table;
6
6
  alias;
7
+ optimizerHint;
7
8
  constructor(tableName) {
8
9
  super();
9
- const m = tableName.match(/^(?:([a-zA-Z][\w$]*)\.)? *([a-zA-Z][\w$]*) *(?:as)? *(\w+)?$/);
10
- if (!m)
11
- throw new TypeError(`(${tableName}) does not match table name format`);
12
- if (m[1])
13
- this.schema = m[1];
14
- if (m[2])
15
- this.table = m[2];
16
- if (m[3])
17
- this.alias = m[3];
10
+ if (typeof tableName === 'string') {
11
+ const m = tableName.match(/^(?:([a-zA-Z][\w$]*)\.)? *([a-zA-Z][\w$]*) *(?:as)? *(\w+)?$/);
12
+ if (!m)
13
+ throw new TypeError(`(${tableName}) does not match table name format`);
14
+ if (m[1])
15
+ this.schema = m[1];
16
+ if (m[2])
17
+ this.table = m[2];
18
+ if (m[3])
19
+ this.alias = m[3];
20
+ }
21
+ else {
22
+ this.schema = tableName.schema;
23
+ this.table = tableName.table;
24
+ this.alias = tableName.alias;
25
+ if (tableName.optimizerHint) {
26
+ const arg0 = tableName.optimizerHint;
27
+ this.optimizerHint = [];
28
+ if (typeof arg0 === 'object' && !Array.isArray(arg0)) {
29
+ this.optimizerHint.push({
30
+ hint: String(arg0.hint),
31
+ dialect: Array.isArray(arg0.dialect) ? arg0.dialect : undefined,
32
+ });
33
+ }
34
+ else {
35
+ this.optimizerHint.push({
36
+ hint: String(arg0),
37
+ });
38
+ }
39
+ }
40
+ }
18
41
  }
19
42
  get _type() {
20
43
  return SerializationType.TABLE_NAME;
@@ -24,6 +47,7 @@ export class TableName extends Serializable {
24
47
  schema: this.schema,
25
48
  table: this.table,
26
49
  alias: this.alias,
50
+ optimizerHint: this.optimizerHint,
27
51
  }, () => (this.schema ? this.schema + '.' : '') +
28
52
  this.table +
29
53
  (this.alias ? ' ' + this.alias : ''));
@@ -18,14 +18,16 @@ import { ParamExpression } from './sql-objects/param-expression.js';
18
18
  import { RawStatement } from './sql-objects/raw-statement.js';
19
19
  import { SequenceGetterStatement } from './sql-objects/sequence-getter-statement.js';
20
20
  import { StringAGGStatement } from './sql-objects/string-agg-statement.js';
21
+ import { TableName as TableNameClass, TableNameArgs } from './sql-objects/table-name.js';
21
22
  import { UpperStatement } from './sql-objects/upper-statement.js';
22
23
  export declare function Raw(text: string): RawStatement;
23
24
  export declare function Select(...column: (string | string[] | Serializable)[]): SelectQuery;
24
25
  export declare function Insert(tableName: string | RawStatement, input: any): InsertQuery;
25
- export declare function Update(tableName: string | RawStatement, input: any): UpdateQuery;
26
- export declare function Delete(tableName: string | RawStatement): DeleteQuery;
26
+ export declare function Update(tableName: string | TableNameClass | RawStatement, input: any): UpdateQuery;
27
+ export declare function Delete(tableName: string | TableNameClass | RawStatement): DeleteQuery;
27
28
  export declare function Union(...queries: Query[]): UnionQuery;
28
29
  export declare function UnionAll(...queries: Query[]): UnionQuery;
30
+ export declare function TableName(tableName: string | TableNameArgs): TableNameClass;
29
31
  export declare function Join(table: string | SelectQuery | RawStatement): JoinStatement;
30
32
  export declare function InnerJoin(table: string | SelectQuery | RawStatement): JoinStatement;
31
33
  export declare function LeftJoin(table: string | SelectQuery | RawStatement): JoinStatement;
@@ -16,6 +16,7 @@ import { ParamExpression } from './sql-objects/param-expression.js';
16
16
  import { RawStatement } from './sql-objects/raw-statement.js';
17
17
  import { SequenceGetterStatement } from './sql-objects/sequence-getter-statement.js';
18
18
  import { StringAGGStatement } from './sql-objects/string-agg-statement.js';
19
+ import { TableName as TableNameClass, } from './sql-objects/table-name.js';
19
20
  import { UpperStatement } from './sql-objects/upper-statement.js';
20
21
  export function Raw(text) {
21
22
  return new RawStatement(text);
@@ -38,6 +39,9 @@ export function Union(...queries) {
38
39
  export function UnionAll(...queries) {
39
40
  return new UnionQuery(queries, 'all');
40
41
  }
42
+ export function TableName(tableName) {
43
+ return new TableNameClass(tableName);
44
+ }
41
45
  export function Join(table) {
42
46
  return new JoinStatement(JoinType.INNER, table);
43
47
  }