pqb 0.32.0 → 0.33.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/dist/index.js CHANGED
@@ -881,6 +881,25 @@ const make = (_op) => {
881
881
  return setQueryOperators(this, boolean);
882
882
  },
883
883
  {
884
+ // function to turn the operator expression into SQL
885
+ _op
886
+ }
887
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
888
+ );
889
+ };
890
+ const makeVarArg = (_op) => {
891
+ return Object.assign(
892
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
893
+ function(...args) {
894
+ var _a, _b, _c;
895
+ ((_b = (_a = this.q).chain) != null ? _b : _a.chain = []).push(_op, args);
896
+ if ((_c = this.q.parsers) == null ? void 0 : _c[orchidCore.getValueKey]) {
897
+ this.q.parsers[orchidCore.getValueKey] = void 0;
898
+ }
899
+ return setQueryOperators(this, boolean);
900
+ },
901
+ {
902
+ // function to turn the operator expression into SQL
884
903
  _op
885
904
  }
886
905
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -963,15 +982,51 @@ const text = __spreadProps$7(__spreadValues$f({}, base), {
963
982
  (key, value, ctx, quotedAs) => `${key} LIKE '%' || ${quoteValue$1(value, ctx, quotedAs)}`
964
983
  )
965
984
  });
985
+ const encodeJsonPath = (ctx, path) => orchidCore.addValue(ctx.values, `{${Array.isArray(path) ? path.join(", ") : path}}`);
986
+ const jsonPathQueryOp = (key, [path, options], ctx) => `jsonb_path_query_first(${key}, ${orchidCore.addValue(ctx.values, path)}${(options == null ? void 0 : options.vars) ? `, ${orchidCore.addValue(ctx.values, JSON.stringify(options.vars))}${options.silent ? ", true" : ""}` : (options == null ? void 0 : options.silent) ? ", NULL, true" : ""})`;
966
987
  const json = __spreadProps$7(__spreadValues$f({}, base), {
967
- jsonPath: make(
968
- (key, [path, op, value], ctx, quotedAs) => `jsonb_path_query_first(${key}, '${path}') #>> '{}' ${op} ${value === null ? "null" : quoteValue$1(value, ctx, quotedAs, true)}`
988
+ jsonPathQueryFirst: Object.assign(
989
+ function(path, options) {
990
+ var _a, _b, _c, _d, _e;
991
+ ((_b = (_a = this.q).chain) != null ? _b : _a.chain = []).push(jsonPathQueryOp, [path, options]);
992
+ if ((_c = this.q.parsers) == null ? void 0 : _c[orchidCore.getValueKey]) {
993
+ this.q.parsers[orchidCore.getValueKey] = void 0;
994
+ }
995
+ if (options == null ? void 0 : options.type) {
996
+ const parse = options.type(this.columnTypes).parseFn;
997
+ if (parse)
998
+ ((_e = (_d = this.q).parsers) != null ? _e : _d.parsers = {})[orchidCore.getValueKey] = parse;
999
+ }
1000
+ return this;
1001
+ },
1002
+ { _op: jsonPathQueryOp }
969
1003
  ),
970
1004
  jsonSupersetOf: make(
971
1005
  (key, value, ctx, quotedAs) => `${key} @> ${quoteValue$1(value, ctx, quotedAs, true)}`
972
1006
  ),
973
1007
  jsonSubsetOf: make(
974
1008
  (key, value, ctx, quotedAs) => `${key} <@ ${quoteValue$1(value, ctx, quotedAs, true)}`
1009
+ ),
1010
+ jsonSet: makeVarArg(
1011
+ (key, [path, value], ctx) => `jsonb_set(${key}, ${encodeJsonPath(ctx, path)}, ${orchidCore.addValue(
1012
+ ctx.values,
1013
+ JSON.stringify(value)
1014
+ )})`
1015
+ ),
1016
+ jsonReplace: makeVarArg(
1017
+ (key, [path, value], ctx) => `jsonb_set(${key}, ${encodeJsonPath(ctx, path)}, ${orchidCore.addValue(
1018
+ ctx.values,
1019
+ JSON.stringify(value)
1020
+ )}, false)`
1021
+ ),
1022
+ jsonInsert: makeVarArg(
1023
+ (key, [path, value, options], ctx) => `jsonb_insert(${key}, ${encodeJsonPath(ctx, path)}, ${orchidCore.addValue(
1024
+ ctx.values,
1025
+ JSON.stringify(value)
1026
+ )}${(options == null ? void 0 : options.after) ? ", true" : ""})`
1027
+ ),
1028
+ jsonRemove: makeVarArg(
1029
+ (key, [path], ctx) => `(${key} #- ${encodeJsonPath(ctx, path)})`
975
1030
  )
976
1031
  });
977
1032
  const Operators = {
@@ -2077,9 +2132,13 @@ const processWhere = (ands, ctx, table, query, data, quotedAs) => {
2077
2132
  if ("prototype" in data || "baseQuery" in data) {
2078
2133
  const query2 = data;
2079
2134
  if (query2.q.expr) {
2080
- const q = joinSubQuery(table, query2);
2081
- q.q.select = [query2.q.expr];
2082
- ands.push(`(${getSqlText(makeSQL(q, ctx))})`);
2135
+ if (query2.q.subQuery === 1) {
2136
+ ands.push(selectToSql(ctx, table, query2.q, quotedAs));
2137
+ } else {
2138
+ const q = joinSubQuery(table, query2);
2139
+ q.q.select = [query2.q.expr];
2140
+ ands.push(`(${getSqlText(makeSQL(q, ctx))})`);
2141
+ }
2083
2142
  } else {
2084
2143
  pushWhereToSql(
2085
2144
  ands,
@@ -3610,7 +3669,7 @@ const processSelectArg = (q, as, arg, columnAs) => {
3610
3669
  (q2) => q2,
3611
3670
  key
3612
3671
  );
3613
- } else if (((_d = value.q) == null ? void 0 : _d.isSubQuery) && value.q.expr) {
3672
+ } else if (((_d = value.q) == null ? void 0 : _d.subQuery) && value.q.expr) {
3614
3673
  value = value.q.expr;
3615
3674
  }
3616
3675
  }
@@ -3785,7 +3844,7 @@ class SelectItemExpression extends orchidCore.Expression {
3785
3844
  // except that it will use non-aliasing `columnToSql` when `ctx.aliasValue` is true,
3786
3845
  // it is needed for relation sub-queries that returns a single column.
3787
3846
  makeSQL(ctx, quotedAs) {
3788
- return typeof this.item === "string" ? this.item === "*" ? selectAllSql(this.query, this.q, quotedAs) : ctx.aliasValue ? columnToSql(ctx, this.q, this.q.shape, this.item, quotedAs, true) : columnToSqlWithAs(ctx, this.q, this.item, quotedAs, true) : selectedObjectToSQL(ctx, this.query, quotedAs, this.item);
3847
+ return typeof this.item === "string" ? this.item === "*" ? selectAllSql(this.query, this.q, quotedAs) : ctx.aliasValue ? columnToSql(ctx, this.q, this.q.shape, this.item, quotedAs, true) : columnToSqlWithAs(ctx, this.q, this.item, quotedAs, true) : selectedObjectToSQL(ctx, quotedAs, this.item);
3789
3848
  }
3790
3849
  }
3791
3850
 
@@ -3993,50 +4052,6 @@ function queryJson(self, coalesce) {
3993
4052
  return q;
3994
4053
  }
3995
4054
 
3996
- const jsonColumnOrMethodToSql = (ctx, table, column, values, quotedAs) => {
3997
- return typeof column === "string" ? columnToSql(ctx, table.q, table.q.shape, column, quotedAs) : jsonToSql(ctx, table, column, values, quotedAs);
3998
- };
3999
- const jsonToSql = (ctx, table, item, values, quotedAs) => {
4000
- const json = item.__json;
4001
- if (json[0] === "pathQuery") {
4002
- const [, , , column, path, options] = json;
4003
- return `jsonb_path_query(${jsonColumnOrMethodToSql(
4004
- ctx,
4005
- table,
4006
- column,
4007
- values,
4008
- quotedAs
4009
- )}, ${orchidCore.addValue(values, path)}${(options == null ? void 0 : options.vars) ? `, ${orchidCore.addValue(values, options.vars)}` : ""}${(options == null ? void 0 : options.silent) ? ", true" : ""})`;
4010
- } else if (json[0] === "set") {
4011
- const [, , , column, path, value, options] = json;
4012
- return `jsonb_set(${jsonColumnOrMethodToSql(
4013
- ctx,
4014
- table,
4015
- column,
4016
- values,
4017
- quotedAs
4018
- )}, '{${path.join(", ")}}', ${orchidCore.addValue(values, JSON.stringify(value))}${(options == null ? void 0 : options.createIfMissing) ? ", true" : ""})`;
4019
- } else if (json[0] === "insert") {
4020
- const [, , , column, path, value, options] = json;
4021
- return `jsonb_insert(${jsonColumnOrMethodToSql(
4022
- ctx,
4023
- table,
4024
- column,
4025
- values,
4026
- quotedAs
4027
- )}, '{${path.join(", ")}}', ${orchidCore.addValue(values, JSON.stringify(value))}${(options == null ? void 0 : options.insertAfter) ? ", true" : ""})`;
4028
- } else if (json[0] === "remove") {
4029
- const [, , , column, path] = json;
4030
- return `${jsonColumnOrMethodToSql(
4031
- ctx,
4032
- table,
4033
- column,
4034
- values,
4035
- quotedAs
4036
- )} #- '{${path.join(", ")}}'`;
4037
- }
4038
- return "";
4039
- };
4040
4055
  const pushSelectSql = (ctx, table, query, quotedAs) => {
4041
4056
  ctx.sql.push(selectToSql(ctx, table, query, quotedAs));
4042
4057
  };
@@ -4070,7 +4085,7 @@ const selectToSql = (ctx, table, query, quotedAs) => {
4070
4085
  }
4071
4086
  }
4072
4087
  } else {
4073
- list.push(selectedObjectToSQL(ctx, table, quotedAs, item));
4088
+ list.push(selectedObjectToSQL(ctx, quotedAs, item));
4074
4089
  }
4075
4090
  }
4076
4091
  return list.join(", ");
@@ -4078,10 +4093,7 @@ const selectToSql = (ctx, table, query, quotedAs) => {
4078
4093
  return selectAllSql(table, query, quotedAs);
4079
4094
  };
4080
4095
  const selectedStringToSQL = (ctx, table, query, quotedAs, item) => item === "*" ? selectAllSql(table, query, quotedAs) : columnToSqlWithAs(ctx, table.q, item, quotedAs, true);
4081
- function selectedObjectToSQL(ctx, table, quotedAs, item) {
4082
- if ("__json" in item) {
4083
- return `${jsonToSql(ctx, table, item, ctx.values, quotedAs)} "${item.__json[1]}"`;
4084
- }
4096
+ function selectedObjectToSQL(ctx, quotedAs, item) {
4085
4097
  const sql = item.toSQL(ctx, quotedAs);
4086
4098
  return ctx.aliasValue ? `${sql} r` : sql;
4087
4099
  }
@@ -4771,11 +4783,12 @@ const processData = (ctx, table, set, data, quotedAs) => {
4771
4783
  };
4772
4784
  const processValue = (ctx, table, QueryClass, key, value, quotedAs) => {
4773
4785
  if (value && typeof value === "object") {
4774
- if (value.__json) {
4775
- return jsonToSql(ctx, table, value, ctx.values, quotedAs);
4776
- } else if (orchidCore.isExpression(value)) {
4786
+ if (orchidCore.isExpression(value)) {
4777
4787
  return value.toSQL(ctx, quotedAs);
4778
4788
  } else if (value instanceof QueryClass) {
4789
+ if (value.q.subQuery === 1) {
4790
+ return selectToSql(ctx, table, value.q, quotedAs);
4791
+ }
4779
4792
  return `(${getSqlText(
4780
4793
  joinSubQuery(table, value).toSQL(ctx)
4781
4794
  )})`;
@@ -5201,11 +5214,11 @@ const makeRegexToFindInSql = (value) => {
5201
5214
  return new RegExp(`${value}(?=(?:[^']*'[^']*')*[^']*$)`, "g");
5202
5215
  };
5203
5216
  const resolveSubQueryCallback = (q, cb) => {
5204
- const { isSubQuery, relChain } = q.q;
5205
- q.q.isSubQuery = true;
5217
+ const { subQuery, relChain } = q.q;
5218
+ q.q.subQuery = 1;
5206
5219
  q.q.relChain = void 0;
5207
5220
  const result = cb(q);
5208
- q.q.isSubQuery = isSubQuery;
5221
+ q.q.subQuery = subQuery;
5209
5222
  q.q.relChain = relChain;
5210
5223
  return result;
5211
5224
  };
@@ -6655,7 +6668,7 @@ class Create {
6655
6668
  * const createdCount = await db.table.insertMany([data, data, data]);
6656
6669
  * ```
6657
6670
  *
6658
- * Because of a limitation of Postgres protocol, queries having more than **65536** are going to fail in runtime.
6671
+ * Because of a limitation of Postgres protocol, queries having more than **65535** of values are going to fail in runtime.
6659
6672
  * To solve this seamlessly, OrchidORM will automatically batch such queries, and wrap them into a transaction, unless they are already in a transaction.
6660
6673
  *
6661
6674
  * ```ts
@@ -8277,183 +8290,6 @@ class OnMethods {
8277
8290
  }
8278
8291
  }
8279
8292
 
8280
- class JsonModifiers {
8281
- /**
8282
- * Return a JSON value/object/array where a given value is set at the given path.
8283
- * The path is an array of keys to access the value.
8284
- *
8285
- * Can be used in `update` callback.
8286
- *
8287
- * ```ts
8288
- * const result = await db.table.jsonSet('data', ['name'], 'new value').take();
8289
- *
8290
- * expect(result.data).toEqual({ name: 'new value' });
8291
- * ```
8292
- *
8293
- * Optionally takes parameters of type `{ as?: string, createIfMissing?: boolean }`
8294
- *
8295
- * ```ts
8296
- * await db.table.jsonSet('data', ['name'], 'new value', {
8297
- * as: 'alias', // select data as `alias`
8298
- * createIfMissing: true, // ignored if missing by default
8299
- * });
8300
- * ```
8301
- *
8302
- * @param column - name of JSON column, or a result of a nested json method
8303
- * @param path - path to value inside the json
8304
- * @param value - value to set into the json
8305
- * @param options - `as` to alias the json value when selecting, `createIfMissing: true` will create a new JSON property if it didn't exist before
8306
- */
8307
- jsonSet(column, path, value, options) {
8308
- var _a;
8309
- const q = this.clone();
8310
- const json = {
8311
- __json: [
8312
- "set",
8313
- (_a = options == null ? void 0 : options.as) != null ? _a : typeof column === "string" ? column : column.__json[1],
8314
- typeof column === "string" ? q.q.shape[column] : column.__json[2],
8315
- column,
8316
- path,
8317
- value,
8318
- options
8319
- ]
8320
- };
8321
- return Object.assign(pushQueryValue(q, "select", json), json);
8322
- }
8323
- /**
8324
- * Return a JSON value/object/array where a given value is inserted at the given JSON path. Value can be a single value or JSON object. If a value exists at the given path, the value is not replaced.
8325
- *
8326
- * Can be used in `update` callback.
8327
- *
8328
- * ```ts
8329
- * // imagine user has data = { tags: ['two'] }
8330
- * const result = await db.table.jsonInsert('data', ['tags', 0], 'one').take();
8331
- *
8332
- * // 'one' is inserted to 0 position
8333
- * expect(result.data).toEqual({ tags: ['one', 'two'] });
8334
- * ```
8335
- *
8336
- * Optionally takes parameters of type `{ as?: string, insertAfter?: boolean }`
8337
- *
8338
- * ```ts
8339
- * // imagine user has data = { tags: ['one'] }
8340
- * const result = await db.table
8341
- * .jsonInsert('data', ['tags', 0], 'two', {
8342
- * as: 'alias', // select as an alias
8343
- * insertAfter: true, // insert after the specified position
8344
- * })
8345
- * .take();
8346
- *
8347
- * // 'one' is inserted to 0 position
8348
- * expect(result.alias).toEqual({ tags: ['one', 'two'] });
8349
- * ```
8350
- * @param column - name of JSON column, or a result of a nested json method
8351
- * @param path - path to the array inside the json, last path element is index to insert into
8352
- * @param value - value to insert into the json array
8353
- * @param options - `as` to alias the json value when selecting, `insertAfter: true` to insert after the specified position
8354
- */
8355
- jsonInsert(column, path, value, options) {
8356
- var _a;
8357
- const q = this.clone();
8358
- const json = {
8359
- __json: [
8360
- "insert",
8361
- (_a = options == null ? void 0 : options.as) != null ? _a : typeof column === "string" ? column : column.__json[1],
8362
- typeof column === "string" ? q.q.shape[column] : column.__json[2],
8363
- column,
8364
- path,
8365
- value,
8366
- options
8367
- ]
8368
- };
8369
- return Object.assign(pushQueryValue(q, "select", json), json);
8370
- }
8371
- /**
8372
- * Return a JSON value/object/array where a given value is removed at the given JSON path.
8373
- *
8374
- * Can be used in `update` callback.
8375
- *
8376
- * ```ts
8377
- * // imagine a user has data = { tags: ['one', 'two'] }
8378
- * const result = await db.table
8379
- * .jsonRemove(
8380
- * 'data',
8381
- * ['tags', 0],
8382
- * // optional parameters:
8383
- * {
8384
- * as: 'alias', // select as an alias
8385
- * },
8386
- * )
8387
- * .take();
8388
- *
8389
- * expect(result.alias).toEqual({ tags: ['two'] });
8390
- * ```
8391
- *
8392
- * @param column - name of JSON column, or a result of a nested json method
8393
- * @param path - path to the array inside the json, last path element is index to remove this element
8394
- * @param options - `as` to alias the json value when selecting
8395
- */
8396
- jsonRemove(column, path, options) {
8397
- var _a;
8398
- const q = this.clone();
8399
- const json = {
8400
- __json: [
8401
- "remove",
8402
- (_a = options == null ? void 0 : options.as) != null ? _a : typeof column === "string" ? column : column.__json[1],
8403
- typeof column === "string" ? q.q.shape[column] : column.__json[2],
8404
- column,
8405
- path
8406
- ]
8407
- };
8408
- return Object.assign(pushQueryValue(q, "select", json), json);
8409
- }
8410
- /**
8411
- * Selects a value from JSON data using a JSON path.
8412
- *
8413
- * ```ts
8414
- * import { columnTypes } from 'orchid-orm';
8415
- *
8416
- * db.table.jsonPathQuery(
8417
- * columnTypes.text(3, 100), // type of the value
8418
- * 'data', // name of the JSON column
8419
- * '$.name', // JSON path
8420
- * 'name', // select value as name
8421
- *
8422
- * // Optionally supports `vars` and `silent` options
8423
- * // check Postgres docs for jsonb_path_query for details
8424
- * {
8425
- * vars: 'vars',
8426
- * silent: true,
8427
- * },
8428
- * );
8429
- * ```
8430
- *
8431
- * Nested JSON operations can be used in place of JSON column name:
8432
- *
8433
- * ```ts
8434
- * db.table.jsonPathQuery(
8435
- * columnTypes.text(3, 100),
8436
- * // Available: .jsonSet, .jsonInsert, .jsonRemove
8437
- * db.table.jsonSet('data', ['key'], 'value'),
8438
- * '$.name',
8439
- * 'name',
8440
- * );
8441
- * ```
8442
- *
8443
- * @param type - provide a column type to have a correct result type
8444
- * @param column - name of JSON column, or a result of a nested json method
8445
- * @param path - special JSON path string to reference a JSON value
8446
- * @param as - optional alias for the selected value
8447
- * @param options - supports `vars` and `silent`, check Postgres docs of `json_path_query` for these
8448
- */
8449
- jsonPathQuery(type, column, path, as, options) {
8450
- const q = this.clone();
8451
- const json = {
8452
- __json: ["pathQuery", as, type, column, path, options]
8453
- };
8454
- return Object.assign(pushQueryValue(q, "select", json), json);
8455
- }
8456
- }
8457
8293
  class JsonMethods {
8458
8294
  /**
8459
8295
  * Wraps the query in a way to select a single JSON string.
@@ -8829,7 +8665,7 @@ const resolveCallbacksInArgs = (q, args) => {
8829
8665
  const qb = Object.create(q);
8830
8666
  qb.q = getClonedQueryData(q.q);
8831
8667
  qb.q.and = qb.q.or = qb.q.scopes = void 0;
8832
- qb.q.isSubQuery = true;
8668
+ qb.q.subQuery = 1;
8833
8669
  args[i] = resolveSubQueryCallback(qb, arg);
8834
8670
  }
8835
8671
  }
@@ -11542,7 +11378,6 @@ orchidCore.applyMixins(QueryMethods, [
11542
11378
  OnMethods,
11543
11379
  WithMethods,
11544
11380
  Union,
11545
- JsonModifiers,
11546
11381
  JsonMethods,
11547
11382
  Create,
11548
11383
  Update,
@@ -12181,7 +12016,6 @@ exports.JSONColumn = JSONColumn;
12181
12016
  exports.JSONTextColumn = JSONTextColumn;
12182
12017
  exports.Join = Join;
12183
12018
  exports.JsonMethods = JsonMethods;
12184
- exports.JsonModifiers = JsonModifiers;
12185
12019
  exports.LimitedTextBaseColumn = LimitedTextBaseColumn;
12186
12020
  exports.LineColumn = LineColumn;
12187
12021
  exports.LsegColumn = LsegColumn;