Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 49 additions & 1 deletion packages/drivers/driver-sql/src/sql-driver-introspection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@
* `schema-drift.ts`, where they live; `sql-driver.ts` no longer reads the two
* functions and dropped them from its import.
*
* [#25521 cut 7] `resolveHashShadowKeys` moved here too, beside its only
* caller. `introspectIndexes`' body still reaches it through the host
* closure above, which calls the class method on the driver, which hands this
* body its host; so a subclass override or a test spy on the instance is
* still the one reached. It reads only `knex`. `isHashShadowCarrier` and
* `parseHashShadowKeyParts` are imported from `schema-drift.ts`, where they
* live; `sql-driver.ts` still reads `parseHashShadowKeyParts` and dropped
* `isHashShadowCarrier` from its import.
*
* A MOVE, not a redesign. Each function below is the body of the `SqlDriver`
* method of the same name as it stood, re-indented one level and otherwise
* unedited: the same catalog statements, the same dialect arms, the same
Expand Down Expand Up @@ -81,7 +90,13 @@ import type {
UniqueConstraintMember,
} from './sql-driver.js';
import { postgresTableNameCollisionError, singleColumnUniqueColumns } from './sql-driver.js';
import { applyIndexKeyParts, parseIndexDdl, type PhysicalIndex } from './schema-drift.js';
import {
applyIndexKeyParts,
isHashShadowCarrier,
parseHashShadowKeyParts,
parseIndexDdl,
type PhysicalIndex,
} from './schema-drift.js';

/**
* The `SqlDriver` members the functions below read — every one of them, and
Expand Down Expand Up @@ -925,3 +940,36 @@ export async function introspectIndexes(
}
return [...byName.values()];
}

/** The body of `SqlDriver#resolveHashShadowKeys`; the method's docblock there is its contract. */
export async function resolveHashShadowKeys(
this: Pick<IntrospectionHost, 'knex'>,
tableName: string,
indexes: PhysicalIndex[],
): Promise<void> {
const carriers = indexes.filter((i) => isHashShadowCarrier(i));
if (carriers.length === 0) return;
try {
const rows: Array<Record<string, unknown>> = await this.knex
.select('COLUMN_NAME', 'GENERATION_EXPRESSION')
.from('information_schema.COLUMNS')
.where({ TABLE_SCHEMA: this.knex.client.database(), TABLE_NAME: tableName })
.whereIn(
'COLUMN_NAME',
carriers.map((i) => i.columns[0]!),
);
const exprByColumn = new Map<string, string>();
for (const r of rows) {
const column = String(r.COLUMN_NAME ?? r.column_name ?? '');
if (column) {
exprByColumn.set(column, String(r.GENERATION_EXPRESSION ?? r.generation_expression ?? ''));
}
}
for (const i of carriers) {
const parts = parseHashShadowKeyParts(exprByColumn.get(i.columns[0]!) ?? '');
if (parts.length > 0) i.shadowKey = parts;
}
} catch {
/* see the head note: an unresolved carrier degrades to "no finding". */
}
}
40 changes: 11 additions & 29 deletions packages/drivers/driver-sql/src/sql-driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ import {
ceremonyOwnedDropFinding,
isCeremonyOwnedColumnDrop,
hashShadowColumnFor,
isHashShadowCarrier,
parseHashShadowKeyParts,
indexedKeyColumns,
isIndexDriftOp,
Expand Down Expand Up @@ -161,8 +160,9 @@ import { withUpsertConflictClause } from './upsert-conflict-clause.js';
// [#25521 cut 1] The catalog-introspection helpers (`introspectColumnOrder`,
// `introspectColumns` and the foreign-key, primary-key and unique-constraint reads),
// [cut 4] `introspectSchema`, the whole-schema read built on them, and [cut 5]
// `introspectIndexes`, the per-table index read schema sync is built on; the methods
// of the same names below hand each body the members it reads (`IntrospectionHost`).
// `introspectIndexes`, the per-table index read schema sync is built on, and [cut 7]
// `resolveHashShadowKeys`, its MySQL hash-shadow enrichment; the methods of the
// same names below hand each body the members it reads (`IntrospectionHost`).
import {
introspectColumnOrder,
introspectColumns,
Expand All @@ -171,6 +171,7 @@ import {
introspectPrimaryKeys,
introspectSchema,
introspectUniqueConstraints,
resolveHashShadowKeys,
} from './sql-driver-introspection.js';
// [#25521 cut 2] The raw-execution path (`execute`, its refusal terminal
// `rawStatementFault`, and `noteRuntimeIndexDdl`, which keeps the ledger of the
Expand Down Expand Up @@ -15131,35 +15132,16 @@ export class SqlDriver implements IDataDriver {
* rather than proposing a rebuild it cannot reason about. The degraded
* outcome is a missing finding, never a dropped constraint.
*/
protected async resolveHashShadowKeys(
protected resolveHashShadowKeys(
tableName: string,
indexes: PhysicalIndex[],
): Promise<void> {
const carriers = indexes.filter((i) => isHashShadowCarrier(i));
if (carriers.length === 0) return;
try {
const rows: Array<Record<string, unknown>> = await this.knex
.select('COLUMN_NAME', 'GENERATION_EXPRESSION')
.from('information_schema.COLUMNS')
.where({ TABLE_SCHEMA: this.knex.client.database(), TABLE_NAME: tableName })
.whereIn(
'COLUMN_NAME',
carriers.map((i) => i.columns[0]!),
);
const exprByColumn = new Map<string, string>();
for (const r of rows) {
const column = String(r.COLUMN_NAME ?? r.column_name ?? '');
if (column) {
exprByColumn.set(column, String(r.GENERATION_EXPRESSION ?? r.generation_expression ?? ''));
}
}
for (const i of carriers) {
const parts = parseHashShadowKeyParts(exprByColumn.get(i.columns[0]!) ?? '');
if (parts.length > 0) i.shadowKey = parts;
}
} catch {
/* see the head note: an unresolved carrier degrades to "no finding". */
}
// [#25521 cut 7] The body moved to `sql-driver-introspection.ts` (see `IntrospectionHost`).
const readKnex = () => this.knex;
const host: ThisParameterType<typeof resolveHashShadowKeys> = {
get knex() { return readKnex(); },
};
return resolveHashShadowKeys.call(host, tableName, indexes);
}

/**
Expand Down
Loading