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.mjs CHANGED
@@ -147,7 +147,7 @@ const toPascalCase = (str) => {
147
147
  * @param str - string to translate
148
148
  */
149
149
  const toSnakeCase = (str) => {
150
- return str.replace(/[A-Z]/g, (a) => `_${a.toLowerCase()}`);
150
+ return str.replace(/[A-Z]/g, (a, i) => `${i ? "_" : ""}${a.toLowerCase()}`);
151
151
  };
152
152
  /**
153
153
  * Compare two values deeply.
@@ -6602,12 +6602,12 @@ const processJoinItem = (ctx, table, query, args, quotedAs) => {
6602
6602
  ctx.aliasValue = aliasValue;
6603
6603
  } else if ("j" in args) {
6604
6604
  const { j, s, r } = args;
6605
- const tableName = typeof j.q.from === "string" ? j.q.from : j.table;
6606
- const joinTable = requireTableOrStringFrom(j);
6605
+ const joinTable = j.q.nameInDb || requireTableOrStringFrom(j);
6607
6606
  target = quoteFromWithSchema(getQuerySchema$1(j), joinTable);
6608
6607
  const as = j.q.as;
6609
6608
  const joinAs = `"${as}"`;
6610
- if (as !== tableName) target += ` ${joinAs}`;
6609
+ const alias = getQueryRelationAliasForAs(j, as);
6610
+ if (alias) target += ` ${alias}`;
6611
6611
  if (r && s) target = subJoinToSql(ctx, j, `"${joinTable}"`, !forbidLateral, joinAs, true);
6612
6612
  else on = whereToSql(ctx, j, j.q, joinAs);
6613
6613
  } else if ("w" in args) {
@@ -6665,16 +6665,16 @@ const getArgQueryTarget = (ctx, first, lateral, joinSubQuery, cloned) => {
6665
6665
  const quotedFrom = typeof joinQuery.from === "string" ? `"${joinQuery.from}"` : void 0;
6666
6666
  let joinAs = quotedFrom || `"${first.table}"`;
6667
6667
  const qAs = joinQuery.as ? `"${joinQuery.as}"` : void 0;
6668
- const addAs = qAs && qAs !== joinAs;
6668
+ const aliasToAdd = getQueryRelationAliasForAs(first, joinQuery.as);
6669
6669
  if (joinSubQuery) return {
6670
6670
  target: subJoinToSql(ctx, first, joinAs, lateral, qAs, cloned),
6671
- joinAs: addAs ? qAs : joinAs
6671
+ joinAs: qAs || joinAs
6672
6672
  };
6673
6673
  else {
6674
6674
  let target = quotedFrom || quoteTableWithSchema(first);
6675
- if (addAs) {
6676
- joinAs = qAs;
6677
- target += ` ${qAs}`;
6675
+ if (aliasToAdd) {
6676
+ joinAs = aliasToAdd;
6677
+ target += ` ${aliasToAdd}`;
6678
6678
  }
6679
6679
  return {
6680
6680
  target,
@@ -7432,14 +7432,18 @@ const makeInsertSql = (ctx, q, query, quotedAs, isSubSql) => {
7432
7432
  }
7433
7433
  }
7434
7434
  const hasNonSelect = ctx.hasNonSelect;
7435
+ const returningQuotedAs = query.as ? `"${query.as}"` : quotedAs;
7436
+ const insertAlias = getQueryRelationAliasForAs(q, query.as);
7437
+ quotedAs = insertAlias || quotedAs;
7435
7438
  const sqlState = {
7436
7439
  ctx,
7437
7440
  q,
7438
7441
  query,
7439
7442
  quotedAs,
7443
+ returningQuotedAs,
7440
7444
  isSubSql,
7441
7445
  returningPos: 0,
7442
- insertSql: `INSERT INTO ${quoteTableWithSchema(q)}${quotedColumns.length ? "(" + quotedColumns.join(", ") + ")" : ""}`
7446
+ insertSql: `INSERT INTO ${quoteTableWithSchema(q)}${insertAlias ? ` AS ${insertAlias}` : ""}${quotedColumns.length ? "(" + quotedColumns.join(", ") + ")" : ""}`
7443
7447
  };
7444
7448
  ctx.sql.push(null, null);
7445
7449
  const hasOnConflictWhere = pushOnConflictSql(ctx, q, query, quotedAs, columns, quotedColumns, runtimeDefaultColumns);
@@ -7552,7 +7556,7 @@ const applySqlState = (sqlState) => {
7552
7556
  const insertSql = sqlState.selectFromSql ? sqlState.insertSql + sqlState.selectFromSql : sqlState.insertSql;
7553
7557
  const wrapInCte = getShouldWrapMainQueryInCte(ctx, sqlState.query, "insert", sqlState.isSubSql);
7554
7558
  if ("valuesSql" in sqlState) ctx.sql[1] = sqlState.valuesPrepend + sqlState.valuesSql.join(", ") + sqlState.valuesAppend;
7555
- const returning = makeReturningSql(ctx, sqlState.q, sqlState.query, sqlState.quotedAs, sqlState.relationSelectState, "Create", void 0, sqlState.isSubSql || !!ctx.topCtx.cteHooks);
7559
+ const returning = makeReturningSql(ctx, sqlState.q, sqlState.query, sqlState.returningQuotedAs, sqlState.relationSelectState, "Create", void 0, sqlState.isSubSql || !!ctx.topCtx.cteHooks);
7556
7560
  if (returning) ctx.sql[sqlState.returningPos] = "RETURNING " + returning;
7557
7561
  ctx.sql[0] = insertSql;
7558
7562
  if (wrapInCte) wrapMainQueryInCte(ctx, sqlState.query);
@@ -7713,8 +7717,9 @@ const pushUpdateSql = (ctx, query, q, quotedAs, isSubSql) => {
7713
7717
  }
7714
7718
  };
7715
7719
  const pushUpdateSqlWithoutValuesJoinedAs = (ctx, query, q, quotedAs, isSubSql) => {
7716
- const quotedTable = `"${query.table || q.from}"`;
7717
7720
  const from = quoteTableWithSchema(query);
7721
+ const alias = getQueryRelationAliasForAs(query, q.as);
7722
+ quotedAs = alias || quotedAs;
7718
7723
  const set = [];
7719
7724
  const hookSet = q.hookUpdateSet ? Object.fromEntries(q.hookUpdateSet.flatMap((item) => Object.entries(item))) : emptyObject;
7720
7725
  const relationSelectState = newMutativeQueriesSelectRelationsSqlState(query);
@@ -7729,7 +7734,7 @@ const pushUpdateSqlWithoutValuesJoinedAs = (ctx, query, q, quotedAs, isSubSql) =
7729
7734
  if (!set.length) pushSelectForEmptySet(ctx, query, q, quotedAs, from, isSubSql, updateManyValuesSql, relationSelectState);
7730
7735
  else {
7731
7736
  ctx.sql.push(`UPDATE ${from}`);
7732
- if (quotedTable !== quotedAs) ctx.sql.push(quotedAs);
7737
+ if (alias) ctx.sql.push(alias);
7733
7738
  ctx.sql.push("SET", set.join(", "));
7734
7739
  let fromWhereSql;
7735
7740
  if (updateManyValuesSql) {
@@ -7746,6 +7751,8 @@ const pushSelectForEmptySet = (ctx, query, q, quotedAs, from, isSubSql, updateMa
7746
7751
  if (!q.select) q.select = countSelect;
7747
7752
  pushUpdateReturning(ctx, query, q, quotedAs, "SELECT", relationSelectState, isSubSql);
7748
7753
  let fromSql = `FROM ${from}`;
7754
+ const alias = getQueryRelationAliasForAs(query, q.as);
7755
+ if (alias) fromSql += ` ${alias}`;
7749
7756
  if (updateManyValuesSql) fromSql += `, ${updateManyValuesSql}`;
7750
7757
  ctx.sql.push(fromSql);
7751
7758
  pushWhereStatementSql(ctx, query, q, quotedAs);
@@ -7860,7 +7867,8 @@ const throwOnDifferentColumns = (query, keysSet, row, i) => {
7860
7867
  const pushDeleteSql = (ctx, query, q, quotedAs, isSubSql) => {
7861
7868
  const from = quoteTableWithSchema(query);
7862
7869
  ctx.sql.push(`DELETE FROM ${from}`);
7863
- if (q.as && query.table !== q.as) ctx.sql.push(quotedAs);
7870
+ const alias = getQueryRelationAliasForAs(query, q.as);
7871
+ if (alias) ctx.sql.push(alias);
7864
7872
  const relationSelectState = newMutativeQueriesSelectRelationsSqlState(query);
7865
7873
  let returning = makeReturningSql(ctx, query, q, quotedAs, relationSelectState, "Delete", void 0, isSubSql);
7866
7874
  const selectRelations = handleDeleteSelectRelationsSqlState(ctx, query, relationSelectState);
@@ -8029,22 +8037,6 @@ const numericResultColumn = (q, arg) => {
8029
8037
  return (typeof arg === "string" ? _getSelectableColumn(q, arg) : arg.result.value) instanceof NumberBaseColumn ? floatNullable : stringAsNumberNullable;
8030
8038
  };
8031
8039
  var AggregateMethods = class {
8032
- /**
8033
- * Use `exists()` to check if there is at least one record-matching condition.
8034
- *
8035
- * It will discard previous `select` statements if any. Returns a boolean.
8036
- *
8037
- * ```ts
8038
- * const exists: boolean = await db.table.where(...conditions).exists();
8039
- * ```
8040
- */
8041
- exists() {
8042
- const q = _queryGetOptional(_clone(this), new RawSql("true"));
8043
- q.q.notFoundDefault = false;
8044
- q.q.coalesceValue = new RawSql("false");
8045
- q.q.getColumn = BooleanColumn.instanceSkipValueToArray;
8046
- return q;
8047
- }
8048
8040
  /**
8049
8041
  * Count records with the `count` function:
8050
8042
  *
@@ -9461,7 +9453,8 @@ const getFrom = (ctx, query, data, quotedAs) => {
9461
9453
  return fromToSql(ctx, query, data, from, quotedAs);
9462
9454
  }
9463
9455
  let sql = quoteTableWithSchema(query);
9464
- if (data.as && query.table !== data.as) sql += ` ${quotedAs}`;
9456
+ const alias = getQueryRelationAliasForAs(query, data.as);
9457
+ if (alias) sql += ` ${alias}`;
9465
9458
  if (data.only) sql = `ONLY ${sql}`;
9466
9459
  return sql;
9467
9460
  };
@@ -9473,7 +9466,7 @@ const fromToSql = (ctx, query, data, from, quotedAs) => {
9473
9466
  only = from.q.only;
9474
9467
  if (!from.table) sql = `(${moveMutativeQueryToCte(ctx, from)})`;
9475
9468
  else if (!checkIfASimpleQuery(from)) sql = `(${moveMutativeQueryToCte(ctx, from)}) ${quotedAs || `"${getQueryAs(from)}"`}`;
9476
- else sql = quoteTableWithSchema(from);
9469
+ else sql = quoteTableWithSchemaAndAlias(from);
9477
9470
  fromQuery = from;
9478
9471
  }
9479
9472
  else sql = quoteFromWithSchema(getQuerySchema$1(query), from);
@@ -9774,7 +9767,18 @@ const requireTableOrStringFrom = (query) => {
9774
9767
  if (!table) throw new OrchidOrmInternalError(query, "The query object does not have a table and doesn't define a `from` string");
9775
9768
  return table;
9776
9769
  };
9777
- const quoteTableWithSchema = (query) => quoteFromWithSchema(getQuerySchema$1(query), requireTableOrStringFrom(query));
9770
+ const getQueryRelationAlias = (query) => query.table && query.q.nameInDb && query.table !== query.q.nameInDb ? `"${query.table}"` : void 0;
9771
+ const getQueryRelationAliasForAs = (query, as) => {
9772
+ if (!as) return getQueryRelationAlias(query);
9773
+ const nameInDb = query.q.nameInDb || requireTableOrStringFrom(query);
9774
+ return nameInDb && as !== nameInDb ? `"${as}"` : void 0;
9775
+ };
9776
+ const quoteTableWithSchema = (query) => quoteFromWithSchema(getQuerySchema$1(query), query.q.nameInDb || requireTableOrStringFrom(query));
9777
+ const quoteTableWithSchemaAndAlias = (query) => {
9778
+ const table = quoteTableWithSchema(query);
9779
+ const alias = getQueryRelationAlias(query);
9780
+ return alias ? `${table} ${alias}` : table;
9781
+ };
9778
9782
  const quoteFromWithSchema = (schema, table) => {
9779
9783
  const s = typeof schema === "function" ? schema() : schema;
9780
9784
  return s ? `"${s}"."${table}"` : `"${table}"`;
@@ -10042,7 +10046,7 @@ const _joinLateral = (self, type, joinQuery, as, innerJoinLateral) => {
10042
10046
  const joinedAs = getQueryAs(query);
10043
10047
  setObjectValueImmutable(joinQuery.q, "joinedShapes", joinedAs, query.q.selectShape);
10044
10048
  }
10045
- const shape = getShapeFromSelect(joinQuery, true);
10049
+ const shape = joinQuery.table && joinQuery.q.joinedShapes?.[joinQuery.table] || joinQuery.q.joinedShapes?.[joinAs] || getShapeFromSelect(joinQuery, true);
10046
10050
  setObjectValueImmutable(query.q, "joinedShapes", joinAs, shape);
10047
10051
  if (joinValue) setObjectValueImmutable(query.q, "valuesJoinedAs", joinAs, joinValueAs);
10048
10052
  setObjectValueImmutable(query.q, "joinedParsers", joinValueAs || joinAs, getQueryParsers(joinQuery));
@@ -13265,6 +13269,39 @@ var QueryWindow = class {
13265
13269
  return pushQueryValueImmutable(_clone(this), "window", arg);
13266
13270
  }
13267
13271
  };
13272
+ const _exists = (query, value) => {
13273
+ const q = _queryGetOptional(_clone(query), new RawSql(String(value)));
13274
+ q.q.notFoundDefault = !value;
13275
+ q.q.coalesceValue = new RawSql(String(!value));
13276
+ q.q.getColumn = BooleanColumn.instanceSkipValueToArray;
13277
+ return q;
13278
+ };
13279
+ var QueryExistsMethods = class {
13280
+ /**
13281
+ * Use `exists()` to check if there is at least one record-matching condition.
13282
+ *
13283
+ * It will discard previous `select` statements if any. Returns a boolean.
13284
+ *
13285
+ * ```ts
13286
+ * const exists: boolean = await db.table.where(...conditions).exists();
13287
+ * ```
13288
+ */
13289
+ exists() {
13290
+ return _exists(this, true);
13291
+ }
13292
+ /**
13293
+ * Use `notExists()` to check if there are no matching records.
13294
+ *
13295
+ * It will discard previous `select` statements if any. Returns a boolean.
13296
+ *
13297
+ * ```ts
13298
+ * const exists: boolean = await db.table.where(...conditions).notExists();
13299
+ * ```
13300
+ */
13301
+ notExists() {
13302
+ return _exists(this, false);
13303
+ }
13304
+ };
13268
13305
  var QueryMethods = class {
13269
13306
  /**
13270
13307
  * `.all` is a default behavior, that returns an array of objects:
@@ -13338,6 +13375,30 @@ var QueryMethods = class {
13338
13375
  return _queryExec(_clone(this));
13339
13376
  }
13340
13377
  /**
13378
+ * For relation selects, `require` changes LEFT JOIN LATERAL to JOIN LATERAL.
13379
+ *
13380
+ * ```ts
13381
+ * // only the records that have `related` will be loaded:
13382
+ * await db.table.select({ related: (q) => q.related.required() });
13383
+ * ```
13384
+ */
13385
+ require() {
13386
+ const query = _clone(this);
13387
+ switch (query.q.returnType) {
13388
+ case void 0:
13389
+ case "all":
13390
+ case "valueOrThrow":
13391
+ case "pluck":
13392
+ case "void": break;
13393
+ case "value":
13394
+ query.q.returnType = "valueOrThrow";
13395
+ break;
13396
+ default: query.q.returnType = "oneOrThrow";
13397
+ }
13398
+ query.q.innerJoinLateral = true;
13399
+ return query;
13400
+ }
13401
+ /**
13341
13402
  * Call `toSQL` on a query to get an object with a `text` SQL string and a `values` array of binding values:
13342
13403
  *
13343
13404
  * ```ts
@@ -13541,7 +13602,7 @@ var QueryMethods = class {
13541
13602
  * // all the following queries will resolve into empty arrays
13542
13603
  *
13543
13604
  * await db.user.select({
13544
- * pets: (q) => q.pets.join().none(),
13605
+ * pets: (q) => q.pets.require().none(),
13545
13606
  * });
13546
13607
  *
13547
13608
  * await db.user.join((q) => q.pets.none());
@@ -13791,7 +13852,8 @@ applyMixins(QueryMethods, [
13791
13852
  SoftDeleteMethods,
13792
13853
  QueryExpressions,
13793
13854
  QueryWrap,
13794
- QueryWindow
13855
+ QueryWindow,
13856
+ QueryExistsMethods
13795
13857
  ]);
13796
13858
  const performQuery = async (q, args, method) => {
13797
13859
  const trx = q.internal.asyncStorage.getStore();
@@ -13830,6 +13892,7 @@ const performQuery = async (q, args, method) => {
13830
13892
  throw err;
13831
13893
  }
13832
13894
  };
13895
+ const getTableNameInDb = (table, nameInDb, snakeCase) => table && (nameInDb || (snakeCase ? toSnakeCase(table) : table));
13833
13896
  var Db = class extends QueryMethods {
13834
13897
  constructor(adapterNotInTransaction, qb, table = void 0, shape, columnTypes, asyncStorage, options, tableData = {}, viewData) {
13835
13898
  super();
@@ -13907,6 +13970,7 @@ var Db = class extends QueryMethods {
13907
13970
  this.q = {
13908
13971
  adapter: adapterNotInTransaction,
13909
13972
  selectShape: shape,
13973
+ nameInDb: getTableNameInDb(table, options.nameInDb, snakeCase),
13910
13974
  handleResult,
13911
13975
  logger,
13912
13976
  log: logParamToLogObject(logger, options.log),
@@ -14243,7 +14307,7 @@ const _initQueryBuilder = (adapter, columnTypes, asyncStorage, commonOptions, op
14243
14307
  const makeColumnInfoSql = (query, column) => {
14244
14308
  const values = [];
14245
14309
  const schema = getQuerySchema(query);
14246
- 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()"}`;
14310
+ 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()"}`;
14247
14311
  if (column) text += ` AND column_name = ${addValue(values, query.shape[column]?.data.name || column)}`;
14248
14312
  return {
14249
14313
  text,