pqb 0.69.0 → 0.71.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
@@ -170,7 +170,7 @@ const toPascalCase = (str) => {
170
170
  * @param str - string to translate
171
171
  */
172
172
  const toSnakeCase = (str) => {
173
- return str.replace(/[A-Z]/g, (a) => `_${a.toLowerCase()}`);
173
+ return str.replace(/[A-Z]/g, (a, i) => `${i ? "_" : ""}${a.toLowerCase()}`);
174
174
  };
175
175
  /**
176
176
  * Compare two values deeply.
@@ -6625,12 +6625,12 @@ const processJoinItem = (ctx, table, query, args, quotedAs) => {
6625
6625
  ctx.aliasValue = aliasValue;
6626
6626
  } else if ("j" in args) {
6627
6627
  const { j, s, r } = args;
6628
- const tableName = typeof j.q.from === "string" ? j.q.from : j.table;
6629
- const joinTable = requireTableOrStringFrom(j);
6628
+ const joinTable = j.q.nameInDb || requireTableOrStringFrom(j);
6630
6629
  target = quoteFromWithSchema(getQuerySchema$1(j), joinTable);
6631
6630
  const as = j.q.as;
6632
6631
  const joinAs = `"${as}"`;
6633
- if (as !== tableName) target += ` ${joinAs}`;
6632
+ const alias = getQueryRelationAliasForAs(j, as);
6633
+ if (alias) target += ` ${alias}`;
6634
6634
  if (r && s) target = subJoinToSql(ctx, j, `"${joinTable}"`, !forbidLateral, joinAs, true);
6635
6635
  else on = whereToSql(ctx, j, j.q, joinAs);
6636
6636
  } else if ("w" in args) {
@@ -6688,16 +6688,16 @@ const getArgQueryTarget = (ctx, first, lateral, joinSubQuery, cloned) => {
6688
6688
  const quotedFrom = typeof joinQuery.from === "string" ? `"${joinQuery.from}"` : void 0;
6689
6689
  let joinAs = quotedFrom || `"${first.table}"`;
6690
6690
  const qAs = joinQuery.as ? `"${joinQuery.as}"` : void 0;
6691
- const addAs = qAs && qAs !== joinAs;
6691
+ const aliasToAdd = getQueryRelationAliasForAs(first, joinQuery.as);
6692
6692
  if (joinSubQuery) return {
6693
6693
  target: subJoinToSql(ctx, first, joinAs, lateral, qAs, cloned),
6694
- joinAs: addAs ? qAs : joinAs
6694
+ joinAs: qAs || joinAs
6695
6695
  };
6696
6696
  else {
6697
6697
  let target = quotedFrom || quoteTableWithSchema(first);
6698
- if (addAs) {
6699
- joinAs = qAs;
6700
- target += ` ${qAs}`;
6698
+ if (aliasToAdd) {
6699
+ joinAs = aliasToAdd;
6700
+ target += ` ${aliasToAdd}`;
6701
6701
  }
6702
6702
  return {
6703
6703
  target,
@@ -7455,14 +7455,18 @@ const makeInsertSql = (ctx, q, query, quotedAs, isSubSql) => {
7455
7455
  }
7456
7456
  }
7457
7457
  const hasNonSelect = ctx.hasNonSelect;
7458
+ const returningQuotedAs = query.as ? `"${query.as}"` : quotedAs;
7459
+ const insertAlias = getQueryRelationAliasForAs(q, query.as);
7460
+ quotedAs = insertAlias || quotedAs;
7458
7461
  const sqlState = {
7459
7462
  ctx,
7460
7463
  q,
7461
7464
  query,
7462
7465
  quotedAs,
7466
+ returningQuotedAs,
7463
7467
  isSubSql,
7464
7468
  returningPos: 0,
7465
- insertSql: `INSERT INTO ${quoteTableWithSchema(q)}${quotedColumns.length ? "(" + quotedColumns.join(", ") + ")" : ""}`
7469
+ insertSql: `INSERT INTO ${quoteTableWithSchema(q)}${insertAlias ? ` AS ${insertAlias}` : ""}${quotedColumns.length ? "(" + quotedColumns.join(", ") + ")" : ""}`
7466
7470
  };
7467
7471
  ctx.sql.push(null, null);
7468
7472
  const hasOnConflictWhere = pushOnConflictSql(ctx, q, query, quotedAs, columns, quotedColumns, runtimeDefaultColumns);
@@ -7575,7 +7579,7 @@ const applySqlState = (sqlState) => {
7575
7579
  const insertSql = sqlState.selectFromSql ? sqlState.insertSql + sqlState.selectFromSql : sqlState.insertSql;
7576
7580
  const wrapInCte = getShouldWrapMainQueryInCte(ctx, sqlState.query, "insert", sqlState.isSubSql);
7577
7581
  if ("valuesSql" in sqlState) ctx.sql[1] = sqlState.valuesPrepend + sqlState.valuesSql.join(", ") + sqlState.valuesAppend;
7578
- const returning = makeReturningSql(ctx, sqlState.q, sqlState.query, sqlState.quotedAs, sqlState.relationSelectState, "Create", void 0, sqlState.isSubSql || !!ctx.topCtx.cteHooks);
7582
+ const returning = makeReturningSql(ctx, sqlState.q, sqlState.query, sqlState.returningQuotedAs, sqlState.relationSelectState, "Create", void 0, sqlState.isSubSql || !!ctx.topCtx.cteHooks);
7579
7583
  if (returning) ctx.sql[sqlState.returningPos] = "RETURNING " + returning;
7580
7584
  ctx.sql[0] = insertSql;
7581
7585
  if (wrapInCte) wrapMainQueryInCte(ctx, sqlState.query);
@@ -7736,8 +7740,9 @@ const pushUpdateSql = (ctx, query, q, quotedAs, isSubSql) => {
7736
7740
  }
7737
7741
  };
7738
7742
  const pushUpdateSqlWithoutValuesJoinedAs = (ctx, query, q, quotedAs, isSubSql) => {
7739
- const quotedTable = `"${query.table || q.from}"`;
7740
7743
  const from = quoteTableWithSchema(query);
7744
+ const alias = getQueryRelationAliasForAs(query, q.as);
7745
+ quotedAs = alias || quotedAs;
7741
7746
  const set = [];
7742
7747
  const hookSet = q.hookUpdateSet ? Object.fromEntries(q.hookUpdateSet.flatMap((item) => Object.entries(item))) : emptyObject;
7743
7748
  const relationSelectState = newMutativeQueriesSelectRelationsSqlState(query);
@@ -7752,7 +7757,7 @@ const pushUpdateSqlWithoutValuesJoinedAs = (ctx, query, q, quotedAs, isSubSql) =
7752
7757
  if (!set.length) pushSelectForEmptySet(ctx, query, q, quotedAs, from, isSubSql, updateManyValuesSql, relationSelectState);
7753
7758
  else {
7754
7759
  ctx.sql.push(`UPDATE ${from}`);
7755
- if (quotedTable !== quotedAs) ctx.sql.push(quotedAs);
7760
+ if (alias) ctx.sql.push(alias);
7756
7761
  ctx.sql.push("SET", set.join(", "));
7757
7762
  let fromWhereSql;
7758
7763
  if (updateManyValuesSql) {
@@ -7769,6 +7774,8 @@ const pushSelectForEmptySet = (ctx, query, q, quotedAs, from, isSubSql, updateMa
7769
7774
  if (!q.select) q.select = countSelect;
7770
7775
  pushUpdateReturning(ctx, query, q, quotedAs, "SELECT", relationSelectState, isSubSql);
7771
7776
  let fromSql = `FROM ${from}`;
7777
+ const alias = getQueryRelationAliasForAs(query, q.as);
7778
+ if (alias) fromSql += ` ${alias}`;
7772
7779
  if (updateManyValuesSql) fromSql += `, ${updateManyValuesSql}`;
7773
7780
  ctx.sql.push(fromSql);
7774
7781
  pushWhereStatementSql(ctx, query, q, quotedAs);
@@ -7883,7 +7890,8 @@ const throwOnDifferentColumns = (query, keysSet, row, i) => {
7883
7890
  const pushDeleteSql = (ctx, query, q, quotedAs, isSubSql) => {
7884
7891
  const from = quoteTableWithSchema(query);
7885
7892
  ctx.sql.push(`DELETE FROM ${from}`);
7886
- if (q.as && query.table !== q.as) ctx.sql.push(quotedAs);
7893
+ const alias = getQueryRelationAliasForAs(query, q.as);
7894
+ if (alias) ctx.sql.push(alias);
7887
7895
  const relationSelectState = newMutativeQueriesSelectRelationsSqlState(query);
7888
7896
  let returning = makeReturningSql(ctx, query, q, quotedAs, relationSelectState, "Delete", void 0, isSubSql);
7889
7897
  const selectRelations = handleDeleteSelectRelationsSqlState(ctx, query, relationSelectState);
@@ -8052,22 +8060,6 @@ const numericResultColumn = (q, arg) => {
8052
8060
  return (typeof arg === "string" ? _getSelectableColumn(q, arg) : arg.result.value) instanceof NumberBaseColumn ? floatNullable : stringAsNumberNullable;
8053
8061
  };
8054
8062
  var AggregateMethods = class {
8055
- /**
8056
- * Use `exists()` to check if there is at least one record-matching condition.
8057
- *
8058
- * It will discard previous `select` statements if any. Returns a boolean.
8059
- *
8060
- * ```ts
8061
- * const exists: boolean = await db.table.where(...conditions).exists();
8062
- * ```
8063
- */
8064
- exists() {
8065
- const q = _queryGetOptional(_clone(this), new RawSql("true"));
8066
- q.q.notFoundDefault = false;
8067
- q.q.coalesceValue = new RawSql("false");
8068
- q.q.getColumn = BooleanColumn.instanceSkipValueToArray;
8069
- return q;
8070
- }
8071
8063
  /**
8072
8064
  * Count records with the `count` function:
8073
8065
  *
@@ -9484,7 +9476,8 @@ const getFrom = (ctx, query, data, quotedAs) => {
9484
9476
  return fromToSql(ctx, query, data, from, quotedAs);
9485
9477
  }
9486
9478
  let sql = quoteTableWithSchema(query);
9487
- if (data.as && query.table !== data.as) sql += ` ${quotedAs}`;
9479
+ const alias = getQueryRelationAliasForAs(query, data.as);
9480
+ if (alias) sql += ` ${alias}`;
9488
9481
  if (data.only) sql = `ONLY ${sql}`;
9489
9482
  return sql;
9490
9483
  };
@@ -9496,7 +9489,7 @@ const fromToSql = (ctx, query, data, from, quotedAs) => {
9496
9489
  only = from.q.only;
9497
9490
  if (!from.table) sql = `(${moveMutativeQueryToCte(ctx, from)})`;
9498
9491
  else if (!checkIfASimpleQuery(from)) sql = `(${moveMutativeQueryToCte(ctx, from)}) ${quotedAs || `"${getQueryAs(from)}"`}`;
9499
- else sql = quoteTableWithSchema(from);
9492
+ else sql = quoteTableWithSchemaAndAlias(from);
9500
9493
  fromQuery = from;
9501
9494
  }
9502
9495
  else sql = quoteFromWithSchema(getQuerySchema$1(query), from);
@@ -9797,7 +9790,18 @@ const requireTableOrStringFrom = (query) => {
9797
9790
  if (!table) throw new OrchidOrmInternalError(query, "The query object does not have a table and doesn't define a `from` string");
9798
9791
  return table;
9799
9792
  };
9800
- const quoteTableWithSchema = (query) => quoteFromWithSchema(getQuerySchema$1(query), requireTableOrStringFrom(query));
9793
+ const getQueryRelationAlias = (query) => query.table && query.q.nameInDb && query.table !== query.q.nameInDb ? `"${query.table}"` : void 0;
9794
+ const getQueryRelationAliasForAs = (query, as) => {
9795
+ if (!as) return getQueryRelationAlias(query);
9796
+ const nameInDb = query.q.nameInDb || requireTableOrStringFrom(query);
9797
+ return nameInDb && as !== nameInDb ? `"${as}"` : void 0;
9798
+ };
9799
+ const quoteTableWithSchema = (query) => quoteFromWithSchema(getQuerySchema$1(query), query.q.nameInDb || requireTableOrStringFrom(query));
9800
+ const quoteTableWithSchemaAndAlias = (query) => {
9801
+ const table = quoteTableWithSchema(query);
9802
+ const alias = getQueryRelationAlias(query);
9803
+ return alias ? `${table} ${alias}` : table;
9804
+ };
9801
9805
  const quoteFromWithSchema = (schema, table) => {
9802
9806
  const s = typeof schema === "function" ? schema() : schema;
9803
9807
  return s ? `"${s}"."${table}"` : `"${table}"`;
@@ -10065,7 +10069,7 @@ const _joinLateral = (self, type, joinQuery, as, innerJoinLateral) => {
10065
10069
  const joinedAs = getQueryAs(query);
10066
10070
  setObjectValueImmutable(joinQuery.q, "joinedShapes", joinedAs, query.q.selectShape);
10067
10071
  }
10068
- const shape = getShapeFromSelect(joinQuery, true);
10072
+ const shape = joinQuery.table && joinQuery.q.joinedShapes?.[joinQuery.table] || joinQuery.q.joinedShapes?.[joinAs] || getShapeFromSelect(joinQuery, true);
10069
10073
  setObjectValueImmutable(query.q, "joinedShapes", joinAs, shape);
10070
10074
  if (joinValue) setObjectValueImmutable(query.q, "valuesJoinedAs", joinAs, joinValueAs);
10071
10075
  setObjectValueImmutable(query.q, "joinedParsers", joinValueAs || joinAs, getQueryParsers(joinQuery));
@@ -13288,6 +13292,39 @@ var QueryWindow = class {
13288
13292
  return pushQueryValueImmutable(_clone(this), "window", arg);
13289
13293
  }
13290
13294
  };
13295
+ const _exists = (query, value) => {
13296
+ const q = _queryGetOptional(_clone(query), new RawSql(String(value)));
13297
+ q.q.notFoundDefault = !value;
13298
+ q.q.coalesceValue = new RawSql(String(!value));
13299
+ q.q.getColumn = BooleanColumn.instanceSkipValueToArray;
13300
+ return q;
13301
+ };
13302
+ var QueryExistsMethods = class {
13303
+ /**
13304
+ * Use `exists()` to check if there is at least one record-matching condition.
13305
+ *
13306
+ * It will discard previous `select` statements if any. Returns a boolean.
13307
+ *
13308
+ * ```ts
13309
+ * const exists: boolean = await db.table.where(...conditions).exists();
13310
+ * ```
13311
+ */
13312
+ exists() {
13313
+ return _exists(this, true);
13314
+ }
13315
+ /**
13316
+ * Use `notExists()` to check if there are no matching records.
13317
+ *
13318
+ * It will discard previous `select` statements if any. Returns a boolean.
13319
+ *
13320
+ * ```ts
13321
+ * const exists: boolean = await db.table.where(...conditions).notExists();
13322
+ * ```
13323
+ */
13324
+ notExists() {
13325
+ return _exists(this, false);
13326
+ }
13327
+ };
13291
13328
  var QueryMethods = class {
13292
13329
  /**
13293
13330
  * `.all` is a default behavior, that returns an array of objects:
@@ -13361,6 +13398,30 @@ var QueryMethods = class {
13361
13398
  return _queryExec(_clone(this));
13362
13399
  }
13363
13400
  /**
13401
+ * For relation selects, `require` changes LEFT JOIN LATERAL to JOIN LATERAL.
13402
+ *
13403
+ * ```ts
13404
+ * // only the records that have `related` will be loaded:
13405
+ * await db.table.select({ related: (q) => q.related.required() });
13406
+ * ```
13407
+ */
13408
+ require() {
13409
+ const query = _clone(this);
13410
+ switch (query.q.returnType) {
13411
+ case void 0:
13412
+ case "all":
13413
+ case "valueOrThrow":
13414
+ case "pluck":
13415
+ case "void": break;
13416
+ case "value":
13417
+ query.q.returnType = "valueOrThrow";
13418
+ break;
13419
+ default: query.q.returnType = "oneOrThrow";
13420
+ }
13421
+ query.q.innerJoinLateral = true;
13422
+ return query;
13423
+ }
13424
+ /**
13364
13425
  * Call `toSQL` on a query to get an object with a `text` SQL string and a `values` array of binding values:
13365
13426
  *
13366
13427
  * ```ts
@@ -13564,7 +13625,7 @@ var QueryMethods = class {
13564
13625
  * // all the following queries will resolve into empty arrays
13565
13626
  *
13566
13627
  * await db.user.select({
13567
- * pets: (q) => q.pets.join().none(),
13628
+ * pets: (q) => q.pets.require().none(),
13568
13629
  * });
13569
13630
  *
13570
13631
  * await db.user.join((q) => q.pets.none());
@@ -13814,7 +13875,8 @@ applyMixins(QueryMethods, [
13814
13875
  SoftDeleteMethods,
13815
13876
  QueryExpressions,
13816
13877
  QueryWrap,
13817
- QueryWindow
13878
+ QueryWindow,
13879
+ QueryExistsMethods
13818
13880
  ]);
13819
13881
  const performQuery = async (q, args, method) => {
13820
13882
  const trx = q.internal.asyncStorage.getStore();
@@ -13853,6 +13915,7 @@ const performQuery = async (q, args, method) => {
13853
13915
  throw err;
13854
13916
  }
13855
13917
  };
13918
+ const getTableNameInDb = (table, nameInDb, snakeCase) => table && (nameInDb || (snakeCase ? toSnakeCase(table) : table));
13856
13919
  var Db = class extends QueryMethods {
13857
13920
  constructor(adapterNotInTransaction, qb, table = void 0, shape, columnTypes, asyncStorage, options, tableData = {}, viewData) {
13858
13921
  super();
@@ -13930,6 +13993,7 @@ var Db = class extends QueryMethods {
13930
13993
  this.q = {
13931
13994
  adapter: adapterNotInTransaction,
13932
13995
  selectShape: shape,
13996
+ nameInDb: getTableNameInDb(table, options.nameInDb, snakeCase),
13933
13997
  handleResult,
13934
13998
  logger,
13935
13999
  log: logParamToLogObject(logger, options.log),
@@ -14266,7 +14330,7 @@ const _initQueryBuilder = (adapter, columnTypes, asyncStorage, commonOptions, op
14266
14330
  const makeColumnInfoSql = (query, column) => {
14267
14331
  const values = [];
14268
14332
  const schema = getQuerySchema(query);
14269
- let text = `SELECT * FROM information_schema.columns WHERE table_name = ${addValue(values, query.table)} AND table_catalog = current_database() AND table_schema = ${schema ? addValue(values, schema) : "current_schema()"}`;
14333
+ let text = `SELECT * FROM information_schema.columns WHERE table_name = ${addValue(values, query.q.nameInDb || query.table)} AND table_catalog = current_database() AND table_schema = ${schema ? addValue(values, schema) : "current_schema()"}`;
14270
14334
  if (column) text += ` AND column_name = ${addValue(values, query.shape[column]?.data.name || column)}`;
14271
14335
  return {
14272
14336
  text,