@vibeorm/sql 5.3.0 → 5.4.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/ast.d.ts CHANGED
@@ -868,10 +868,21 @@ export type SelectStatement = {
868
868
  * The lock a locking read takes: one strength, one wait policy. Both members
869
869
  * are REQUIRED here — defaulting happens once, in the query builder, so the
870
870
  * rendered SQL is a function of the AST alone.
871
+ *
872
+ * `of` narrows the lock to named FROM items (`FOR UPDATE OF "Parent"`). The
873
+ * join relation strategy needs it: its statement also reads child rows through
874
+ * `LEFT JOIN LATERAL` subqueries, and an unnarrowed clause is refused by
875
+ * postgres ("FOR UPDATE is not allowed with aggregate functions", from the
876
+ * children's `json_agg`). With `of` naming the statement's own table only the
877
+ * parent rows are locked. Each name must be the statement's table alias, or its
878
+ * unqualified table name when it has no alias — the only FROM item the AST
879
+ * names; the renderer refuses anything else. Dialects without a locking-read
880
+ * clause render nothing, as for a lock without `of`.
871
881
  */
872
882
  export type RowLock = {
873
883
  readonly strength: RowLockStrength;
874
884
  readonly wait: RowLockWaitPolicy;
885
+ readonly of?: readonly string[];
875
886
  };
876
887
  /**
877
888
  * Sentinel VALUES cell: render the `DEFAULT` keyword instead of a placeholder
package/dist/index.js CHANGED
@@ -2960,6 +2960,12 @@ function renderRowLockClause(params) {
2960
2960
  hint: `${dialect.name} can express: ${Object.keys(syntax.wait).join(", ")}`
2961
2961
  });
2962
2962
  }
2963
+ if (lock.of !== undefined) {
2964
+ if (lock.of.length === 0)
2965
+ throw internalError({ message: "a row lock's `of` list cannot be empty" });
2966
+ const tables = lock.of.map((name) => dialect.quoteIdent({ name })).join(", ");
2967
+ return `${strengthText} OF ${tables}${waitText}`;
2968
+ }
2963
2969
  return `${strengthText}${waitText}`;
2964
2970
  }
2965
2971
  var ADVISORY_KEY_BOUNDS = Object.freeze({
@@ -5136,6 +5142,13 @@ function renderSelect(params) {
5136
5142
  text += ` OFFSET ${statement.offset}`;
5137
5143
  }
5138
5144
  if (statement.rowLock !== undefined) {
5145
+ const target = statement.table.alias ?? statement.table.name;
5146
+ if (statement.rowLock.of !== undefined && statement.rowLock.of.some((name) => name !== target)) {
5147
+ throw internalError4({ message: `a row lock's \`of\` list may name only the statement's own table "${target}"` });
5148
+ }
5149
+ if (statement.rowLock.of !== undefined && (statement.fromSelect !== undefined || statement.keyPage !== undefined)) {
5150
+ throw internalError4({ message: "a row lock's `of` list cannot name a derived table" });
5151
+ }
5139
5152
  const clause = renderRowLockClause({ dialect, lock: statement.rowLock });
5140
5153
  if (clause !== null)
5141
5154
  text += ` ${clause}`;
@@ -6445,4 +6458,4 @@ export {
6445
6458
  toPgArrayLiteral
6446
6459
  };
6447
6460
 
6448
- //# debugId=A6FF0AC9CFF5903864756E2164756E21
6461
+ //# debugId=11C29D1889ACA76B64756E2164756E21