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
Original file line numberDiff line numberDiff line change
Expand Up@@ -436,6 +436,17 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
driver = undefined;
});

// ── Why the it() below carries an explicit 60_000 budget (#13902) ──
// It constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside its own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('hands back strings for `date` and `date[]`, and keeps `timestamptz` an instant', async () => {
driver = new SqlDriver(cell.config());
await underProcessZone('Asia/Shanghai', async () => {
Expand All@@ -456,6 +467,6 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
expect(row.ts instanceof Date).toBe(true);
expect((row.ts as Date).toISOString()).toBe(`${DAY}T00:00:00.000Z`);
});
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,12 +198,23 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
* the cell asserts the multiplier rather than assuming it, the same way the
* matrix asserts its zone skew instead of hoping for it.
*/
// ── Why the 6 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('runs on a 4-byte charset — the boundaries below are utf8mb4 numbers', async () => {
driver = new SqlDriver(cell.config());
const seen = await (driver as any).schemaBytesPerChar();
expect(seen).not.toBeNull();
expect(seen.bytesPerChar).toBe(4);
});
}, 60_000);

/**
* Both sides of the boundary, in one test, because only the pair means
Expand DownExpand Up@@ -245,7 +256,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
// ⛔ And nothing was left behind: the object is not registered half-built.
const exists = await (driver as any).knex.schema.hasTable('os11565_over');
expect(exists).toBe(false);
});
}, 60_000);

/** The card's second measured row, moved by the driver's own `id` column. */
it('creates 63 fields at maxLength 255 and refuses 64', async () => {
Expand All@@ -259,7 +270,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
await expect(driver.initObjects([wideObject('os11565_over255', 64, 255)])).rejects.toThrow(
/cannot create table "os11565_over255".*Its 64 varchar column\(s\) take 65408 bytes/s,
);
});
}, 60_000);

/**
* The path that is more likely than CREATE in a living app: a field added
Expand All@@ -275,7 +286,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
await expect(driver.initObjects([wideObject('os11565_grow', 16, 1024)])).rejects.toThrow(
/cannot add column\(s\) "f16" to "os11565_grow".*Its 16 varchar column\(s\)/s,
);
});
}, 60_000);

/**
* The SECOND limit, which the card's threshold table does not reach and a
Expand All@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
expect(message).toMatch(/InnoDB's per-PAGE limit of 8126 bytes/);
expect(message).not.toMatch(/65535-byte budget for one ROW/);
expect(message).toMatch(/"f1" varchar\(63\) = 253 bytes/);
});
}, 60_000);

/**
* The shape a diagnostic reading only DECLARED bounds would have nothing to
Expand All@@ -315,6 +326,6 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
const message = String(failure.message);
expect(message).toMatch(/"f1" varchar\(255\) = 1022 bytes/);
expect(message).toMatch(/a field declaring NO `maxLength` still takes varchar\(255\)/i);
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -132,6 +132,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
* The accept transition: schema creation MySQL REFUSED before this change
* now succeeds, and the constraint is carried on a full-width digest.
*/
// ── Why the 9 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('creates a UNIQUE index over a 1024-char column, on a varbinary(32) shadow', async () => {
driver = new SqlDriver(cell.config());
await driver.initObjects([uniqueOn('os11627_wide', 1024)]);
Expand All@@ -156,7 +167,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
// ⛔ The control that separates this from the REJECTED route: a prefix
// index reports a SUB_PART. The shadow index keys a whole column.
expect(carried[0].SUB_PART).toBeNull();
});
}, 60_000);

/**
* The boundary, both sides, read from the catalog: 768 characters is the
Expand All@@ -176,7 +187,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const over = await catalog('os11627_over');
expect(String(over.cols.find((c: any) => c.COLUMN_NAME === 'v').DATA_TYPE)).toBe('text');
expect(over.cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME)).length).toBe(1);
});
}, 60_000);

/**
* ⛔ The assertion a PREFIX index fails. Two distinct values sharing their
Expand All@@ -198,7 +209,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {

// …and the constraint is real: the same value twice is refused.
await expect(knex('os11627_sem').insert({ id: 'dup', v: `${shared}AAA` })).rejects.toThrow();
});
}, 60_000);

/**
* NULL must stay DISTINCT, exactly as under a direct UNIQUE index.
Expand All@@ -213,7 +224,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const knex = (driver as any).knex;
await knex('os11627_null').insert([{ id: 'n1', v: null }, { id: 'n2', v: null }, { id: 'n3', v: null }]);
expect((await knex('os11627_null').whereNull('v')).length).toBe(3);
});
}, 60_000);

/**
* A COMPOSITE unique hashes the tuple, and a tuple containing NULL must
Expand All@@ -239,7 +250,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await knex('os11627_comp').insert([{ id: 's1', a: 'xy', b: '' }, { id: 's2', a: 'x', b: 'y2' }]);
// …and the composite constraint still bites.
await expect(knex('os11627_comp').insert({ id: 'dup', a: 'x', b: 'y' })).rejects.toThrow();
});
}, 60_000);

/**
* The digest stored is the one this repo can independently recompute — the
Expand All@@ -257,7 +268,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const stored: Buffer = row[shadowCol];
expect(stored.length).toBe(32);
expect(stored.toString('hex')).toBe(createHash('sha256').update(value).digest('hex'));
});
}, 60_000);

/**
* The clause-② half: once uniqueness is enforced over a DIGEST, MySQL's
Expand All@@ -277,7 +288,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await expect(driver.create('os11627_dup', { v: 'T'.repeat(900) })).rejects.toThrow(
/duplicate value for the UNIQUE constraint 'uniq_os11627_dup_v'.*\(v\)/s,
);
});
}, 60_000);

/**
* ⛔ NON-UNIQUE indexes are deliberately NOT shadowed. An index over a
Expand All@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await expect(driver.initObjects([nonUnique])).rejects.toThrow(
/hash-shadow|cannot create index|BLOB\/TEXT/i,
);
});
}, 60_000);
});
});

Expand DownExpand Up@@ -327,6 +338,6 @@ declareDialectCell(PG_CELL, 'hash-shadow key (#11627)', (cell) => {
);
const defs = (idx.rows ?? []).map((r: any) => String(r.indexdef)).join('\n');
expect(defs).toMatch(/UNIQUE INDEX .*uniq_os11627_pg_v.*\(v\)/i);
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -236,6 +236,17 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
await driver?.disconnect().catch(() => {});
});

// ── Why the 3 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('accepts a >255-char richtext body, and the column really is TEXT (information_schema)', async () => {
driver = new SqlDriver(cell.config());
await driver.execute(`drop table if exists ${T}`).catch(() => {});
Expand DownExpand Up@@ -280,7 +291,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
expect(refusal).toBeInstanceOf(Error);
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
});
}, 60_000);

it('closes the formerly-open half (#11875): an oversized data-URI signature/qrcode is accepted and round-trips', async () => {
// The #11794 version of this case asserted the COST of leaving
Expand All@@ -299,7 +310,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
const [row] = await driver.find(T, { where: { id: 's1' } }, OPTS);
expect(row.body_sig).toBe(DATA_URI);
expect(row.body_qr).toBe(DATA_URI);
});
}, 60_000);

it('keeps #11374 keyed-and-bounded semantics live for the new members (#11875)', async () => {
// A KEYED bounded signature/qrcode column is varchar(maxLength) — the
Expand DownExpand Up@@ -348,7 +359,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
await driver.execute(`drop table if exists ${KT}`).catch(() => {});
});
}, 60_000);
});
});
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
* equivalence pin: the shadow enforces the SAME key the direct
* `COALESCE(organization_id, '__global__')` index would have.
*/
// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('collides two NULL-organization rows under an org-scoped shadow unique', async () => {
driver = new SqlDriver(cell.config());
await driver.initObjects([orgUniqueOn('os12998_org')]);
Expand DownExpand Up@@ -124,7 +135,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
await expect(
knex('os12998_org').insert({ id: 'f', v: V2, organization_id: null }),
).rejects.toThrow(/duplicate/i);
});
}, 60_000);

/**
* ⛔ The control, colocated: a PLAIN composite's expression must NOT gain a
Expand All@@ -151,7 +162,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
{ id: 'n2', a: 'x'.repeat(900), b: null },
]);
expect((await knex('os12998_plain').whereNull('b')).length).toBe(2);
});
}, 60_000);

/**
* Turning the constraint ON is data-dependent (ADR-0120 D4's exact shape):
Expand DownExpand Up@@ -196,7 +207,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
const { cols, idx } = await catalog('os12998_dirty');
expect(idx.some((i: any) => i.INDEX_NAME === 'uniq_os12998_dirty_org_v')).toBe(false);
expect(cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME))).toEqual([]);
});
}, 60_000);

/**
* The write-path half of ruling #11627 clause-②, now for the NULL-safe
Expand All@@ -220,6 +231,6 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
expect(msg).toMatch(/duplicate value for the UNIQUE constraint 'uniq_os12998_msg_org_v'/);
expect(msg).toContain("COALESCE(organization_id, '__global__')");
expect(msg).not.toContain('HASH COLLISION');
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -266,6 +266,17 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
);
};

// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('a freshly synced shadow-carried unique reports no destructive index drift', async () => {
driver = new SqlDriver(cell.config());
const obj = orgUniqueOn('os13015_fresh');
Expand All@@ -281,7 +292,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
// And the shadow COLUMN is still protected from the orphan-column pass —
// the half of the vocabulary that was already taught.
expect(drift.filter((d) => d.kind === 'unmapped_column')).toEqual([]);
});
}, 60_000);

/**
* The remedy pin. Even on a second boot — the runtime ledger empty again,
Expand DownExpand Up@@ -312,7 +323,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
await expect(
knex('os13015_apply').insert({ id: 'b', v: V, organization_id: null }),
).rejects.toThrow(/duplicate/i);
});
}, 60_000);

/**
* The surviving generated column, isolated: drop the index by name (exactly
Expand All@@ -335,7 +346,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>

await driver.initObjects([obj]);
expect(await carriedUniquePresent('os13015_survive', indexName)).toBe(true);
});
}, 60_000);

/**
* The direction a blind skip would have lost: a shadow hashing the RAW
Expand DownExpand Up@@ -376,6 +387,6 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
const after = await catalog('os13015_stale');
const fixed = after.cols.find((c: any) => c.COLUMN_NAME === shadow);
expect(String(fixed.GENERATION_EXPRESSION).toLowerCase()).toContain('coalesce');
});
}, 60_000);
});
});
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
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
Original file line numberDiff line numberDiff line change
Expand Up@@ -436,6 +436,17 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
driver = undefined;
});

// ── Why the it() below carries an explicit 60_000 budget (#13902) ──
// It constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside its own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('hands back strings for `date` and `date[]`, and keeps `timestamptz` an instant', async () => {
driver = new SqlDriver(cell.config());
await underProcessZone('Asia/Shanghai', async () => {
Expand All@@ -456,6 +467,6 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
expect(row.ts instanceof Date).toBe(true);
expect((row.ts as Date).toISOString()).toBe(`${DAY}T00:00:00.000Z`);
});
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,12 +198,23 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
* the cell asserts the multiplier rather than assuming it, the same way the
* matrix asserts its zone skew instead of hoping for it.
*/
// ── Why the 6 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('runs on a 4-byte charset — the boundaries below are utf8mb4 numbers', async () => {
driver = new SqlDriver(cell.config());
const seen = await (driver as any).schemaBytesPerChar();
expect(seen).not.toBeNull();
expect(seen.bytesPerChar).toBe(4);
});
}, 60_000);

/**
* Both sides of the boundary, in one test, because only the pair means
Expand DownExpand Up@@ -245,7 +256,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
// ⛔ And nothing was left behind: the object is not registered half-built.
const exists = await (driver as any).knex.schema.hasTable('os11565_over');
expect(exists).toBe(false);
});
}, 60_000);

/** The card's second measured row, moved by the driver's own `id` column. */
it('creates 63 fields at maxLength 255 and refuses 64', async () => {
Expand All@@ -259,7 +270,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
await expect(driver.initObjects([wideObject('os11565_over255', 64, 255)])).rejects.toThrow(
/cannot create table "os11565_over255".*Its 64 varchar column\(s\) take 65408 bytes/s,
);
});
}, 60_000);

/**
* The path that is more likely than CREATE in a living app: a field added
Expand All@@ -275,7 +286,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
await expect(driver.initObjects([wideObject('os11565_grow', 16, 1024)])).rejects.toThrow(
/cannot add column\(s\) "f16" to "os11565_grow".*Its 16 varchar column\(s\)/s,
);
});
}, 60_000);

/**
* The SECOND limit, which the card's threshold table does not reach and a
Expand All@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
expect(message).toMatch(/InnoDB's per-PAGE limit of 8126 bytes/);
expect(message).not.toMatch(/65535-byte budget for one ROW/);
expect(message).toMatch(/"f1" varchar\(63\) = 253 bytes/);
});
}, 60_000);

/**
* The shape a diagnostic reading only DECLARED bounds would have nothing to
Expand All@@ -315,6 +326,6 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
const message = String(failure.message);
expect(message).toMatch(/"f1" varchar\(255\) = 1022 bytes/);
expect(message).toMatch(/a field declaring NO `maxLength` still takes varchar\(255\)/i);
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -132,6 +132,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
* The accept transition: schema creation MySQL REFUSED before this change
* now succeeds, and the constraint is carried on a full-width digest.
*/
// ── Why the 9 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('creates a UNIQUE index over a 1024-char column, on a varbinary(32) shadow', async () => {
driver = new SqlDriver(cell.config());
await driver.initObjects([uniqueOn('os11627_wide', 1024)]);
Expand All@@ -156,7 +167,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
// ⛔ The control that separates this from the REJECTED route: a prefix
// index reports a SUB_PART. The shadow index keys a whole column.
expect(carried[0].SUB_PART).toBeNull();
});
}, 60_000);

/**
* The boundary, both sides, read from the catalog: 768 characters is the
Expand All@@ -176,7 +187,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const over = await catalog('os11627_over');
expect(String(over.cols.find((c: any) => c.COLUMN_NAME === 'v').DATA_TYPE)).toBe('text');
expect(over.cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME)).length).toBe(1);
});
}, 60_000);

/**
* ⛔ The assertion a PREFIX index fails. Two distinct values sharing their
Expand All@@ -198,7 +209,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {

// …and the constraint is real: the same value twice is refused.
await expect(knex('os11627_sem').insert({ id: 'dup', v: `${shared}AAA` })).rejects.toThrow();
});
}, 60_000);

/**
* NULL must stay DISTINCT, exactly as under a direct UNIQUE index.
Expand All@@ -213,7 +224,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const knex = (driver as any).knex;
await knex('os11627_null').insert([{ id: 'n1', v: null }, { id: 'n2', v: null }, { id: 'n3', v: null }]);
expect((await knex('os11627_null').whereNull('v')).length).toBe(3);
});
}, 60_000);

/**
* A COMPOSITE unique hashes the tuple, and a tuple containing NULL must
Expand All@@ -239,7 +250,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await knex('os11627_comp').insert([{ id: 's1', a: 'xy', b: '' }, { id: 's2', a: 'x', b: 'y2' }]);
// …and the composite constraint still bites.
await expect(knex('os11627_comp').insert({ id: 'dup', a: 'x', b: 'y' })).rejects.toThrow();
});
}, 60_000);

/**
* The digest stored is the one this repo can independently recompute — the
Expand All@@ -257,7 +268,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const stored: Buffer = row[shadowCol];
expect(stored.length).toBe(32);
expect(stored.toString('hex')).toBe(createHash('sha256').update(value).digest('hex'));
});
}, 60_000);

/**
* The clause-② half: once uniqueness is enforced over a DIGEST, MySQL's
Expand All@@ -277,7 +288,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await expect(driver.create('os11627_dup', { v: 'T'.repeat(900) })).rejects.toThrow(
/duplicate value for the UNIQUE constraint 'uniq_os11627_dup_v'.*\(v\)/s,
);
});
}, 60_000);

/**
* ⛔ NON-UNIQUE indexes are deliberately NOT shadowed. An index over a
Expand All@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await expect(driver.initObjects([nonUnique])).rejects.toThrow(
/hash-shadow|cannot create index|BLOB\/TEXT/i,
);
});
}, 60_000);
});
});

Expand DownExpand Up@@ -327,6 +338,6 @@ declareDialectCell(PG_CELL, 'hash-shadow key (#11627)', (cell) => {
);
const defs = (idx.rows ?? []).map((r: any) => String(r.indexdef)).join('\n');
expect(defs).toMatch(/UNIQUE INDEX .*uniq_os11627_pg_v.*\(v\)/i);
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -236,6 +236,17 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
await driver?.disconnect().catch(() => {});
});

// ── Why the 3 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('accepts a >255-char richtext body, and the column really is TEXT (information_schema)', async () => {
driver = new SqlDriver(cell.config());
await driver.execute(`drop table if exists ${T}`).catch(() => {});
Expand DownExpand Up@@ -280,7 +291,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
expect(refusal).toBeInstanceOf(Error);
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
});
}, 60_000);

it('closes the formerly-open half (#11875): an oversized data-URI signature/qrcode is accepted and round-trips', async () => {
// The #11794 version of this case asserted the COST of leaving
Expand All@@ -299,7 +310,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
const [row] = await driver.find(T, { where: { id: 's1' } }, OPTS);
expect(row.body_sig).toBe(DATA_URI);
expect(row.body_qr).toBe(DATA_URI);
});
}, 60_000);

it('keeps #11374 keyed-and-bounded semantics live for the new members (#11875)', async () => {
// A KEYED bounded signature/qrcode column is varchar(maxLength) — the
Expand DownExpand Up@@ -348,7 +359,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
await driver.execute(`drop table if exists ${KT}`).catch(() => {});
});
}, 60_000);
});
});
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
* equivalence pin: the shadow enforces the SAME key the direct
* `COALESCE(organization_id, '__global__')` index would have.
*/
// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('collides two NULL-organization rows under an org-scoped shadow unique', async () => {
driver = new SqlDriver(cell.config());
await driver.initObjects([orgUniqueOn('os12998_org')]);
Expand DownExpand Up@@ -124,7 +135,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
await expect(
knex('os12998_org').insert({ id: 'f', v: V2, organization_id: null }),
).rejects.toThrow(/duplicate/i);
});
}, 60_000);

/**
* ⛔ The control, colocated: a PLAIN composite's expression must NOT gain a
Expand All@@ -151,7 +162,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
{ id: 'n2', a: 'x'.repeat(900), b: null },
]);
expect((await knex('os12998_plain').whereNull('b')).length).toBe(2);
});
}, 60_000);

/**
* Turning the constraint ON is data-dependent (ADR-0120 D4's exact shape):
Expand DownExpand Up@@ -196,7 +207,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
const { cols, idx } = await catalog('os12998_dirty');
expect(idx.some((i: any) => i.INDEX_NAME === 'uniq_os12998_dirty_org_v')).toBe(false);
expect(cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME))).toEqual([]);
});
}, 60_000);

/**
* The write-path half of ruling #11627 clause-②, now for the NULL-safe
Expand All@@ -220,6 +231,6 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
expect(msg).toMatch(/duplicate value for the UNIQUE constraint 'uniq_os12998_msg_org_v'/);
expect(msg).toContain("COALESCE(organization_id, '__global__')");
expect(msg).not.toContain('HASH COLLISION');
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -266,6 +266,17 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
);
};

// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('a freshly synced shadow-carried unique reports no destructive index drift', async () => {
driver = new SqlDriver(cell.config());
const obj = orgUniqueOn('os13015_fresh');
Expand All@@ -281,7 +292,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
// And the shadow COLUMN is still protected from the orphan-column pass —
// the half of the vocabulary that was already taught.
expect(drift.filter((d) => d.kind === 'unmapped_column')).toEqual([]);
});
}, 60_000);

/**
* The remedy pin. Even on a second boot — the runtime ledger empty again,
Expand DownExpand Up@@ -312,7 +323,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
await expect(
knex('os13015_apply').insert({ id: 'b', v: V, organization_id: null }),
).rejects.toThrow(/duplicate/i);
});
}, 60_000);

/**
* The surviving generated column, isolated: drop the index by name (exactly
Expand All@@ -335,7 +346,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>

await driver.initObjects([obj]);
expect(await carriedUniquePresent('os13015_survive', indexName)).toBe(true);
});
}, 60_000);

/**
* The direction a blind skip would have lost: a shadow hashing the RAW
Expand DownExpand Up@@ -376,6 +387,6 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
const after = await catalog('os13015_stale');
const fixed = after.cols.find((c: any) => c.COLUMN_NAME === shadow);
expect(String(fixed.GENERATION_EXPRESSION).toLowerCase()).toContain('coalesce');
});
}, 60_000);
});
});
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
Original file line numberDiff line numberDiff line change
Expand Up@@ -436,6 +436,17 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
driver = undefined;
});

// ── Why the it() below carries an explicit 60_000 budget (#13902) ──
// It constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside its own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('hands back strings for `date` and `date[]`, and keeps `timestamptz` an instant', async () => {
driver = new SqlDriver(cell.config());
await underProcessZone('Asia/Shanghai', async () => {
Expand All@@ -456,6 +467,6 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
expect(row.ts instanceof Date).toBe(true);
expect((row.ts as Date).toISOString()).toBe(`${DAY}T00:00:00.000Z`);
});
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,12 +198,23 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
* the cell asserts the multiplier rather than assuming it, the same way the
* matrix asserts its zone skew instead of hoping for it.
*/
// ── Why the 6 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('runs on a 4-byte charset — the boundaries below are utf8mb4 numbers', async () => {
driver = new SqlDriver(cell.config());
const seen = await (driver as any).schemaBytesPerChar();
expect(seen).not.toBeNull();
expect(seen.bytesPerChar).toBe(4);
});
}, 60_000);

/**
* Both sides of the boundary, in one test, because only the pair means
Expand DownExpand Up@@ -245,7 +256,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
// ⛔ And nothing was left behind: the object is not registered half-built.
const exists = await (driver as any).knex.schema.hasTable('os11565_over');
expect(exists).toBe(false);
});
}, 60_000);

/** The card's second measured row, moved by the driver's own `id` column. */
it('creates 63 fields at maxLength 255 and refuses 64', async () => {
Expand All@@ -259,7 +270,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
await expect(driver.initObjects([wideObject('os11565_over255', 64, 255)])).rejects.toThrow(
/cannot create table "os11565_over255".*Its 64 varchar column\(s\) take 65408 bytes/s,
);
});
}, 60_000);

/**
* The path that is more likely than CREATE in a living app: a field added
Expand All@@ -275,7 +286,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
await expect(driver.initObjects([wideObject('os11565_grow', 16, 1024)])).rejects.toThrow(
/cannot add column\(s\) "f16" to "os11565_grow".*Its 16 varchar column\(s\)/s,
);
});
}, 60_000);

/**
* The SECOND limit, which the card's threshold table does not reach and a
Expand All@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
expect(message).toMatch(/InnoDB's per-PAGE limit of 8126 bytes/);
expect(message).not.toMatch(/65535-byte budget for one ROW/);
expect(message).toMatch(/"f1" varchar\(63\) = 253 bytes/);
});
}, 60_000);

/**
* The shape a diagnostic reading only DECLARED bounds would have nothing to
Expand All@@ -315,6 +326,6 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
const message = String(failure.message);
expect(message).toMatch(/"f1" varchar\(255\) = 1022 bytes/);
expect(message).toMatch(/a field declaring NO `maxLength` still takes varchar\(255\)/i);
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -132,6 +132,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
* The accept transition: schema creation MySQL REFUSED before this change
* now succeeds, and the constraint is carried on a full-width digest.
*/
// ── Why the 9 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('creates a UNIQUE index over a 1024-char column, on a varbinary(32) shadow', async () => {
driver = new SqlDriver(cell.config());
await driver.initObjects([uniqueOn('os11627_wide', 1024)]);
Expand All@@ -156,7 +167,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
// ⛔ The control that separates this from the REJECTED route: a prefix
// index reports a SUB_PART. The shadow index keys a whole column.
expect(carried[0].SUB_PART).toBeNull();
});
}, 60_000);

/**
* The boundary, both sides, read from the catalog: 768 characters is the
Expand All@@ -176,7 +187,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const over = await catalog('os11627_over');
expect(String(over.cols.find((c: any) => c.COLUMN_NAME === 'v').DATA_TYPE)).toBe('text');
expect(over.cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME)).length).toBe(1);
});
}, 60_000);

/**
* ⛔ The assertion a PREFIX index fails. Two distinct values sharing their
Expand All@@ -198,7 +209,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {

// …and the constraint is real: the same value twice is refused.
await expect(knex('os11627_sem').insert({ id: 'dup', v: `${shared}AAA` })).rejects.toThrow();
});
}, 60_000);

/**
* NULL must stay DISTINCT, exactly as under a direct UNIQUE index.
Expand All@@ -213,7 +224,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const knex = (driver as any).knex;
await knex('os11627_null').insert([{ id: 'n1', v: null }, { id: 'n2', v: null }, { id: 'n3', v: null }]);
expect((await knex('os11627_null').whereNull('v')).length).toBe(3);
});
}, 60_000);

/**
* A COMPOSITE unique hashes the tuple, and a tuple containing NULL must
Expand All@@ -239,7 +250,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await knex('os11627_comp').insert([{ id: 's1', a: 'xy', b: '' }, { id: 's2', a: 'x', b: 'y2' }]);
// …and the composite constraint still bites.
await expect(knex('os11627_comp').insert({ id: 'dup', a: 'x', b: 'y' })).rejects.toThrow();
});
}, 60_000);

/**
* The digest stored is the one this repo can independently recompute — the
Expand All@@ -257,7 +268,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const stored: Buffer = row[shadowCol];
expect(stored.length).toBe(32);
expect(stored.toString('hex')).toBe(createHash('sha256').update(value).digest('hex'));
});
}, 60_000);

/**
* The clause-② half: once uniqueness is enforced over a DIGEST, MySQL's
Expand All@@ -277,7 +288,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await expect(driver.create('os11627_dup', { v: 'T'.repeat(900) })).rejects.toThrow(
/duplicate value for the UNIQUE constraint 'uniq_os11627_dup_v'.*\(v\)/s,
);
});
}, 60_000);

/**
* ⛔ NON-UNIQUE indexes are deliberately NOT shadowed. An index over a
Expand All@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await expect(driver.initObjects([nonUnique])).rejects.toThrow(
/hash-shadow|cannot create index|BLOB\/TEXT/i,
);
});
}, 60_000);
});
});

Expand DownExpand Up@@ -327,6 +338,6 @@ declareDialectCell(PG_CELL, 'hash-shadow key (#11627)', (cell) => {
);
const defs = (idx.rows ?? []).map((r: any) => String(r.indexdef)).join('\n');
expect(defs).toMatch(/UNIQUE INDEX .*uniq_os11627_pg_v.*\(v\)/i);
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -236,6 +236,17 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
await driver?.disconnect().catch(() => {});
});

// ── Why the 3 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('accepts a >255-char richtext body, and the column really is TEXT (information_schema)', async () => {
driver = new SqlDriver(cell.config());
await driver.execute(`drop table if exists ${T}`).catch(() => {});
Expand DownExpand Up@@ -280,7 +291,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
expect(refusal).toBeInstanceOf(Error);
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
});
}, 60_000);

it('closes the formerly-open half (#11875): an oversized data-URI signature/qrcode is accepted and round-trips', async () => {
// The #11794 version of this case asserted the COST of leaving
Expand All@@ -299,7 +310,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
const [row] = await driver.find(T, { where: { id: 's1' } }, OPTS);
expect(row.body_sig).toBe(DATA_URI);
expect(row.body_qr).toBe(DATA_URI);
});
}, 60_000);

it('keeps #11374 keyed-and-bounded semantics live for the new members (#11875)', async () => {
// A KEYED bounded signature/qrcode column is varchar(maxLength) — the
Expand DownExpand Up@@ -348,7 +359,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
await driver.execute(`drop table if exists ${KT}`).catch(() => {});
});
}, 60_000);
});
});
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
* equivalence pin: the shadow enforces the SAME key the direct
* `COALESCE(organization_id, '__global__')` index would have.
*/
// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('collides two NULL-organization rows under an org-scoped shadow unique', async () => {
driver = new SqlDriver(cell.config());
await driver.initObjects([orgUniqueOn('os12998_org')]);
Expand DownExpand Up@@ -124,7 +135,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
await expect(
knex('os12998_org').insert({ id: 'f', v: V2, organization_id: null }),
).rejects.toThrow(/duplicate/i);
});
}, 60_000);

/**
* ⛔ The control, colocated: a PLAIN composite's expression must NOT gain a
Expand All@@ -151,7 +162,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
{ id: 'n2', a: 'x'.repeat(900), b: null },
]);
expect((await knex('os12998_plain').whereNull('b')).length).toBe(2);
});
}, 60_000);

/**
* Turning the constraint ON is data-dependent (ADR-0120 D4's exact shape):
Expand DownExpand Up@@ -196,7 +207,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
const { cols, idx } = await catalog('os12998_dirty');
expect(idx.some((i: any) => i.INDEX_NAME === 'uniq_os12998_dirty_org_v')).toBe(false);
expect(cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME))).toEqual([]);
});
}, 60_000);

/**
* The write-path half of ruling #11627 clause-②, now for the NULL-safe
Expand All@@ -220,6 +231,6 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
expect(msg).toMatch(/duplicate value for the UNIQUE constraint 'uniq_os12998_msg_org_v'/);
expect(msg).toContain("COALESCE(organization_id, '__global__')");
expect(msg).not.toContain('HASH COLLISION');
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -266,6 +266,17 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
);
};

// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('a freshly synced shadow-carried unique reports no destructive index drift', async () => {
driver = new SqlDriver(cell.config());
const obj = orgUniqueOn('os13015_fresh');
Expand All@@ -281,7 +292,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
// And the shadow COLUMN is still protected from the orphan-column pass —
// the half of the vocabulary that was already taught.
expect(drift.filter((d) => d.kind === 'unmapped_column')).toEqual([]);
});
}, 60_000);

/**
* The remedy pin. Even on a second boot — the runtime ledger empty again,
Expand DownExpand Up@@ -312,7 +323,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
await expect(
knex('os13015_apply').insert({ id: 'b', v: V, organization_id: null }),
).rejects.toThrow(/duplicate/i);
});
}, 60_000);

/**
* The surviving generated column, isolated: drop the index by name (exactly
Expand All@@ -335,7 +346,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>

await driver.initObjects([obj]);
expect(await carriedUniquePresent('os13015_survive', indexName)).toBe(true);
});
}, 60_000);

/**
* The direction a blind skip would have lost: a shadow hashing the RAW
Expand DownExpand Up@@ -376,6 +387,6 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
const after = await catalog('os13015_stale');
const fixed = after.cols.find((c: any) => c.COLUMN_NAME === shadow);
expect(String(fixed.GENERATION_EXPRESSION).toLowerCase()).toContain('coalesce');
});
}, 60_000);
});
});
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
Original file line numberDiff line numberDiff line change
Expand Up@@ -436,6 +436,17 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
driver = undefined;
});

// ── Why the it() below carries an explicit 60_000 budget (#13902) ──
// It constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside its own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('hands back strings for `date` and `date[]`, and keeps `timestamptz` an instant', async () => {
driver = new SqlDriver(cell.config());
await underProcessZone('Asia/Shanghai', async () => {
Expand All@@ -456,6 +467,6 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
expect(row.ts instanceof Date).toBe(true);
expect((row.ts as Date).toISOString()).toBe(`${DAY}T00:00:00.000Z`);
});
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,12 +198,23 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
* the cell asserts the multiplier rather than assuming it, the same way the
* matrix asserts its zone skew instead of hoping for it.
*/
// ── Why the 6 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('runs on a 4-byte charset — the boundaries below are utf8mb4 numbers', async () => {
driver = new SqlDriver(cell.config());
const seen = await (driver as any).schemaBytesPerChar();
expect(seen).not.toBeNull();
expect(seen.bytesPerChar).toBe(4);
});
}, 60_000);

/**
* Both sides of the boundary, in one test, because only the pair means
Expand DownExpand Up@@ -245,7 +256,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
// ⛔ And nothing was left behind: the object is not registered half-built.
const exists = await (driver as any).knex.schema.hasTable('os11565_over');
expect(exists).toBe(false);
});
}, 60_000);

/** The card's second measured row, moved by the driver's own `id` column. */
it('creates 63 fields at maxLength 255 and refuses 64', async () => {
Expand All@@ -259,7 +270,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
await expect(driver.initObjects([wideObject('os11565_over255', 64, 255)])).rejects.toThrow(
/cannot create table "os11565_over255".*Its 64 varchar column\(s\) take 65408 bytes/s,
);
});
}, 60_000);

/**
* The path that is more likely than CREATE in a living app: a field added
Expand All@@ -275,7 +286,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
await expect(driver.initObjects([wideObject('os11565_grow', 16, 1024)])).rejects.toThrow(
/cannot add column\(s\) "f16" to "os11565_grow".*Its 16 varchar column\(s\)/s,
);
});
}, 60_000);

/**
* The SECOND limit, which the card's threshold table does not reach and a
Expand All@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
expect(message).toMatch(/InnoDB's per-PAGE limit of 8126 bytes/);
expect(message).not.toMatch(/65535-byte budget for one ROW/);
expect(message).toMatch(/"f1" varchar\(63\) = 253 bytes/);
});
}, 60_000);

/**
* The shape a diagnostic reading only DECLARED bounds would have nothing to
Expand All@@ -315,6 +326,6 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
const message = String(failure.message);
expect(message).toMatch(/"f1" varchar\(255\) = 1022 bytes/);
expect(message).toMatch(/a field declaring NO `maxLength` still takes varchar\(255\)/i);
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -132,6 +132,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
* The accept transition: schema creation MySQL REFUSED before this change
* now succeeds, and the constraint is carried on a full-width digest.
*/
// ── Why the 9 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('creates a UNIQUE index over a 1024-char column, on a varbinary(32) shadow', async () => {
driver = new SqlDriver(cell.config());
await driver.initObjects([uniqueOn('os11627_wide', 1024)]);
Expand All@@ -156,7 +167,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
// ⛔ The control that separates this from the REJECTED route: a prefix
// index reports a SUB_PART. The shadow index keys a whole column.
expect(carried[0].SUB_PART).toBeNull();
});
}, 60_000);

/**
* The boundary, both sides, read from the catalog: 768 characters is the
Expand All@@ -176,7 +187,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const over = await catalog('os11627_over');
expect(String(over.cols.find((c: any) => c.COLUMN_NAME === 'v').DATA_TYPE)).toBe('text');
expect(over.cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME)).length).toBe(1);
});
}, 60_000);

/**
* ⛔ The assertion a PREFIX index fails. Two distinct values sharing their
Expand All@@ -198,7 +209,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {

// …and the constraint is real: the same value twice is refused.
await expect(knex('os11627_sem').insert({ id: 'dup', v: `${shared}AAA` })).rejects.toThrow();
});
}, 60_000);

/**
* NULL must stay DISTINCT, exactly as under a direct UNIQUE index.
Expand All@@ -213,7 +224,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const knex = (driver as any).knex;
await knex('os11627_null').insert([{ id: 'n1', v: null }, { id: 'n2', v: null }, { id: 'n3', v: null }]);
expect((await knex('os11627_null').whereNull('v')).length).toBe(3);
});
}, 60_000);

/**
* A COMPOSITE unique hashes the tuple, and a tuple containing NULL must
Expand All@@ -239,7 +250,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await knex('os11627_comp').insert([{ id: 's1', a: 'xy', b: '' }, { id: 's2', a: 'x', b: 'y2' }]);
// …and the composite constraint still bites.
await expect(knex('os11627_comp').insert({ id: 'dup', a: 'x', b: 'y' })).rejects.toThrow();
});
}, 60_000);

/**
* The digest stored is the one this repo can independently recompute — the
Expand All@@ -257,7 +268,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const stored: Buffer = row[shadowCol];
expect(stored.length).toBe(32);
expect(stored.toString('hex')).toBe(createHash('sha256').update(value).digest('hex'));
});
}, 60_000);

/**
* The clause-② half: once uniqueness is enforced over a DIGEST, MySQL's
Expand All@@ -277,7 +288,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await expect(driver.create('os11627_dup', { v: 'T'.repeat(900) })).rejects.toThrow(
/duplicate value for the UNIQUE constraint 'uniq_os11627_dup_v'.*\(v\)/s,
);
});
}, 60_000);

/**
* ⛔ NON-UNIQUE indexes are deliberately NOT shadowed. An index over a
Expand All@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await expect(driver.initObjects([nonUnique])).rejects.toThrow(
/hash-shadow|cannot create index|BLOB\/TEXT/i,
);
});
}, 60_000);
});
});

Expand DownExpand Up@@ -327,6 +338,6 @@ declareDialectCell(PG_CELL, 'hash-shadow key (#11627)', (cell) => {
);
const defs = (idx.rows ?? []).map((r: any) => String(r.indexdef)).join('\n');
expect(defs).toMatch(/UNIQUE INDEX .*uniq_os11627_pg_v.*\(v\)/i);
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -236,6 +236,17 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
await driver?.disconnect().catch(() => {});
});

// ── Why the 3 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('accepts a >255-char richtext body, and the column really is TEXT (information_schema)', async () => {
driver = new SqlDriver(cell.config());
await driver.execute(`drop table if exists ${T}`).catch(() => {});
Expand DownExpand Up@@ -280,7 +291,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
expect(refusal).toBeInstanceOf(Error);
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
});
}, 60_000);

it('closes the formerly-open half (#11875): an oversized data-URI signature/qrcode is accepted and round-trips', async () => {
// The #11794 version of this case asserted the COST of leaving
Expand All@@ -299,7 +310,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
const [row] = await driver.find(T, { where: { id: 's1' } }, OPTS);
expect(row.body_sig).toBe(DATA_URI);
expect(row.body_qr).toBe(DATA_URI);
});
}, 60_000);

it('keeps #11374 keyed-and-bounded semantics live for the new members (#11875)', async () => {
// A KEYED bounded signature/qrcode column is varchar(maxLength) — the
Expand DownExpand Up@@ -348,7 +359,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
await driver.execute(`drop table if exists ${KT}`).catch(() => {});
});
}, 60_000);
});
});
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
* equivalence pin: the shadow enforces the SAME key the direct
* `COALESCE(organization_id, '__global__')` index would have.
*/
// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('collides two NULL-organization rows under an org-scoped shadow unique', async () => {
driver = new SqlDriver(cell.config());
await driver.initObjects([orgUniqueOn('os12998_org')]);
Expand DownExpand Up@@ -124,7 +135,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
await expect(
knex('os12998_org').insert({ id: 'f', v: V2, organization_id: null }),
).rejects.toThrow(/duplicate/i);
});
}, 60_000);

/**
* ⛔ The control, colocated: a PLAIN composite's expression must NOT gain a
Expand All@@ -151,7 +162,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
{ id: 'n2', a: 'x'.repeat(900), b: null },
]);
expect((await knex('os12998_plain').whereNull('b')).length).toBe(2);
});
}, 60_000);

/**
* Turning the constraint ON is data-dependent (ADR-0120 D4's exact shape):
Expand DownExpand Up@@ -196,7 +207,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
const { cols, idx } = await catalog('os12998_dirty');
expect(idx.some((i: any) => i.INDEX_NAME === 'uniq_os12998_dirty_org_v')).toBe(false);
expect(cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME))).toEqual([]);
});
}, 60_000);

/**
* The write-path half of ruling #11627 clause-②, now for the NULL-safe
Expand All@@ -220,6 +231,6 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
expect(msg).toMatch(/duplicate value for the UNIQUE constraint 'uniq_os12998_msg_org_v'/);
expect(msg).toContain("COALESCE(organization_id, '__global__')");
expect(msg).not.toContain('HASH COLLISION');
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -266,6 +266,17 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
);
};

// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('a freshly synced shadow-carried unique reports no destructive index drift', async () => {
driver = new SqlDriver(cell.config());
const obj = orgUniqueOn('os13015_fresh');
Expand All@@ -281,7 +292,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
// And the shadow COLUMN is still protected from the orphan-column pass —
// the half of the vocabulary that was already taught.
expect(drift.filter((d) => d.kind === 'unmapped_column')).toEqual([]);
});
}, 60_000);

/**
* The remedy pin. Even on a second boot — the runtime ledger empty again,
Expand DownExpand Up@@ -312,7 +323,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
await expect(
knex('os13015_apply').insert({ id: 'b', v: V, organization_id: null }),
).rejects.toThrow(/duplicate/i);
});
}, 60_000);

/**
* The surviving generated column, isolated: drop the index by name (exactly
Expand All@@ -335,7 +346,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>

await driver.initObjects([obj]);
expect(await carriedUniquePresent('os13015_survive', indexName)).toBe(true);
});
}, 60_000);

/**
* The direction a blind skip would have lost: a shadow hashing the RAW
Expand DownExpand Up@@ -376,6 +387,6 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
const after = await catalog('os13015_stale');
const fixed = after.cols.find((c: any) => c.COLUMN_NAME === shadow);
expect(String(fixed.GENERATION_EXPRESSION).toLowerCase()).toContain('coalesce');
});
}, 60_000);
});
});
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
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
Original file line numberDiff line numberDiff line change
Expand Up@@ -436,6 +436,17 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
driver = undefined;
});

// ── Why the it() below carries an explicit 60_000 budget (#13902) ──
// It constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside its own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('hands back strings for `date` and `date[]`, and keeps `timestamptz` an instant', async () => {
driver = new SqlDriver(cell.config());
await underProcessZone('Asia/Shanghai', async () => {
Expand All@@ -456,6 +467,6 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
expect(row.ts instanceof Date).toBe(true);
expect((row.ts as Date).toISOString()).toBe(`${DAY}T00:00:00.000Z`);
});
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,12 +198,23 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
* the cell asserts the multiplier rather than assuming it, the same way the
* matrix asserts its zone skew instead of hoping for it.
*/
// ── Why the 6 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('runs on a 4-byte charset — the boundaries below are utf8mb4 numbers', async () => {
driver = new SqlDriver(cell.config());
const seen = await (driver as any).schemaBytesPerChar();
expect(seen).not.toBeNull();
expect(seen.bytesPerChar).toBe(4);
});
}, 60_000);

/**
* Both sides of the boundary, in one test, because only the pair means
Expand DownExpand Up@@ -245,7 +256,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
// ⛔ And nothing was left behind: the object is not registered half-built.
const exists = await (driver as any).knex.schema.hasTable('os11565_over');
expect(exists).toBe(false);
});
}, 60_000);

/** The card's second measured row, moved by the driver's own `id` column. */
it('creates 63 fields at maxLength 255 and refuses 64', async () => {
Expand All@@ -259,7 +270,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
await expect(driver.initObjects([wideObject('os11565_over255', 64, 255)])).rejects.toThrow(
/cannot create table "os11565_over255".*Its 64 varchar column\(s\) take 65408 bytes/s,
);
});
}, 60_000);

/**
* The path that is more likely than CREATE in a living app: a field added
Expand All@@ -275,7 +286,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
await expect(driver.initObjects([wideObject('os11565_grow', 16, 1024)])).rejects.toThrow(
/cannot add column\(s\) "f16" to "os11565_grow".*Its 16 varchar column\(s\)/s,
);
});
}, 60_000);

/**
* The SECOND limit, which the card's threshold table does not reach and a
Expand All@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
expect(message).toMatch(/InnoDB's per-PAGE limit of 8126 bytes/);
expect(message).not.toMatch(/65535-byte budget for one ROW/);
expect(message).toMatch(/"f1" varchar\(63\) = 253 bytes/);
});
}, 60_000);

/**
* The shape a diagnostic reading only DECLARED bounds would have nothing to
Expand All@@ -315,6 +326,6 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
const message = String(failure.message);
expect(message).toMatch(/"f1" varchar\(255\) = 1022 bytes/);
expect(message).toMatch(/a field declaring NO `maxLength` still takes varchar\(255\)/i);
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -132,6 +132,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
* The accept transition: schema creation MySQL REFUSED before this change
* now succeeds, and the constraint is carried on a full-width digest.
*/
// ── Why the 9 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('creates a UNIQUE index over a 1024-char column, on a varbinary(32) shadow', async () => {
driver = new SqlDriver(cell.config());
await driver.initObjects([uniqueOn('os11627_wide', 1024)]);
Expand All@@ -156,7 +167,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
// ⛔ The control that separates this from the REJECTED route: a prefix
// index reports a SUB_PART. The shadow index keys a whole column.
expect(carried[0].SUB_PART).toBeNull();
});
}, 60_000);

/**
* The boundary, both sides, read from the catalog: 768 characters is the
Expand All@@ -176,7 +187,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const over = await catalog('os11627_over');
expect(String(over.cols.find((c: any) => c.COLUMN_NAME === 'v').DATA_TYPE)).toBe('text');
expect(over.cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME)).length).toBe(1);
});
}, 60_000);

/**
* ⛔ The assertion a PREFIX index fails. Two distinct values sharing their
Expand All@@ -198,7 +209,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {

// …and the constraint is real: the same value twice is refused.
await expect(knex('os11627_sem').insert({ id: 'dup', v: `${shared}AAA` })).rejects.toThrow();
});
}, 60_000);

/**
* NULL must stay DISTINCT, exactly as under a direct UNIQUE index.
Expand All@@ -213,7 +224,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const knex = (driver as any).knex;
await knex('os11627_null').insert([{ id: 'n1', v: null }, { id: 'n2', v: null }, { id: 'n3', v: null }]);
expect((await knex('os11627_null').whereNull('v')).length).toBe(3);
});
}, 60_000);

/**
* A COMPOSITE unique hashes the tuple, and a tuple containing NULL must
Expand All@@ -239,7 +250,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await knex('os11627_comp').insert([{ id: 's1', a: 'xy', b: '' }, { id: 's2', a: 'x', b: 'y2' }]);
// …and the composite constraint still bites.
await expect(knex('os11627_comp').insert({ id: 'dup', a: 'x', b: 'y' })).rejects.toThrow();
});
}, 60_000);

/**
* The digest stored is the one this repo can independently recompute — the
Expand All@@ -257,7 +268,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const stored: Buffer = row[shadowCol];
expect(stored.length).toBe(32);
expect(stored.toString('hex')).toBe(createHash('sha256').update(value).digest('hex'));
});
}, 60_000);

/**
* The clause-② half: once uniqueness is enforced over a DIGEST, MySQL's
Expand All@@ -277,7 +288,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await expect(driver.create('os11627_dup', { v: 'T'.repeat(900) })).rejects.toThrow(
/duplicate value for the UNIQUE constraint 'uniq_os11627_dup_v'.*\(v\)/s,
);
});
}, 60_000);

/**
* ⛔ NON-UNIQUE indexes are deliberately NOT shadowed. An index over a
Expand All@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await expect(driver.initObjects([nonUnique])).rejects.toThrow(
/hash-shadow|cannot create index|BLOB\/TEXT/i,
);
});
}, 60_000);
});
});

Expand DownExpand Up@@ -327,6 +338,6 @@ declareDialectCell(PG_CELL, 'hash-shadow key (#11627)', (cell) => {
);
const defs = (idx.rows ?? []).map((r: any) => String(r.indexdef)).join('\n');
expect(defs).toMatch(/UNIQUE INDEX .*uniq_os11627_pg_v.*\(v\)/i);
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -236,6 +236,17 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
await driver?.disconnect().catch(() => {});
});

// ── Why the 3 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('accepts a >255-char richtext body, and the column really is TEXT (information_schema)', async () => {
driver = new SqlDriver(cell.config());
await driver.execute(`drop table if exists ${T}`).catch(() => {});
Expand DownExpand Up@@ -280,7 +291,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
expect(refusal).toBeInstanceOf(Error);
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
});
}, 60_000);

it('closes the formerly-open half (#11875): an oversized data-URI signature/qrcode is accepted and round-trips', async () => {
// The #11794 version of this case asserted the COST of leaving
Expand All@@ -299,7 +310,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
const [row] = await driver.find(T, { where: { id: 's1' } }, OPTS);
expect(row.body_sig).toBe(DATA_URI);
expect(row.body_qr).toBe(DATA_URI);
});
}, 60_000);

it('keeps #11374 keyed-and-bounded semantics live for the new members (#11875)', async () => {
// A KEYED bounded signature/qrcode column is varchar(maxLength) — the
Expand DownExpand Up@@ -348,7 +359,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
await driver.execute(`drop table if exists ${KT}`).catch(() => {});
});
}, 60_000);
});
});
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
* equivalence pin: the shadow enforces the SAME key the direct
* `COALESCE(organization_id, '__global__')` index would have.
*/
// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('collides two NULL-organization rows under an org-scoped shadow unique', async () => {
driver = new SqlDriver(cell.config());
await driver.initObjects([orgUniqueOn('os12998_org')]);
Expand DownExpand Up@@ -124,7 +135,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
await expect(
knex('os12998_org').insert({ id: 'f', v: V2, organization_id: null }),
).rejects.toThrow(/duplicate/i);
});
}, 60_000);

/**
* ⛔ The control, colocated: a PLAIN composite's expression must NOT gain a
Expand All@@ -151,7 +162,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
{ id: 'n2', a: 'x'.repeat(900), b: null },
]);
expect((await knex('os12998_plain').whereNull('b')).length).toBe(2);
});
}, 60_000);

/**
* Turning the constraint ON is data-dependent (ADR-0120 D4's exact shape):
Expand DownExpand Up@@ -196,7 +207,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
const { cols, idx } = await catalog('os12998_dirty');
expect(idx.some((i: any) => i.INDEX_NAME === 'uniq_os12998_dirty_org_v')).toBe(false);
expect(cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME))).toEqual([]);
});
}, 60_000);

/**
* The write-path half of ruling #11627 clause-②, now for the NULL-safe
Expand All@@ -220,6 +231,6 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
expect(msg).toMatch(/duplicate value for the UNIQUE constraint 'uniq_os12998_msg_org_v'/);
expect(msg).toContain("COALESCE(organization_id, '__global__')");
expect(msg).not.toContain('HASH COLLISION');
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -266,6 +266,17 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
);
};

// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('a freshly synced shadow-carried unique reports no destructive index drift', async () => {
driver = new SqlDriver(cell.config());
const obj = orgUniqueOn('os13015_fresh');
Expand All@@ -281,7 +292,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
// And the shadow COLUMN is still protected from the orphan-column pass —
// the half of the vocabulary that was already taught.
expect(drift.filter((d) => d.kind === 'unmapped_column')).toEqual([]);
});
}, 60_000);

/**
* The remedy pin. Even on a second boot — the runtime ledger empty again,
Expand DownExpand Up@@ -312,7 +323,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
await expect(
knex('os13015_apply').insert({ id: 'b', v: V, organization_id: null }),
).rejects.toThrow(/duplicate/i);
});
}, 60_000);

/**
* The surviving generated column, isolated: drop the index by name (exactly
Expand All@@ -335,7 +346,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>

await driver.initObjects([obj]);
expect(await carriedUniquePresent('os13015_survive', indexName)).toBe(true);
});
}, 60_000);

/**
* The direction a blind skip would have lost: a shadow hashing the RAW
Expand DownExpand Up@@ -376,6 +387,6 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
const after = await catalog('os13015_stale');
const fixed = after.cols.find((c: any) => c.COLUMN_NAME === shadow);
expect(String(fixed.GENERATION_EXPRESSION).toLowerCase()).toContain('coalesce');
});
}, 60_000);
});
});
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
Original file line numberDiff line numberDiff line change
Expand Up@@ -436,6 +436,17 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
driver = undefined;
});

// ── Why the it() below carries an explicit 60_000 budget (#13902) ──
// It constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside its own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('hands back strings for `date` and `date[]`, and keeps `timestamptz` an instant', async () => {
driver = new SqlDriver(cell.config());
await underProcessZone('Asia/Shanghai', async () => {
Expand All@@ -456,6 +467,6 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
expect(row.ts instanceof Date).toBe(true);
expect((row.ts as Date).toISOString()).toBe(`${DAY}T00:00:00.000Z`);
});
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,12 +198,23 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
* the cell asserts the multiplier rather than assuming it, the same way the
* matrix asserts its zone skew instead of hoping for it.
*/
// ── Why the 6 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('runs on a 4-byte charset — the boundaries below are utf8mb4 numbers', async () => {
driver = new SqlDriver(cell.config());
const seen = await (driver as any).schemaBytesPerChar();
expect(seen).not.toBeNull();
expect(seen.bytesPerChar).toBe(4);
});
}, 60_000);

/**
* Both sides of the boundary, in one test, because only the pair means
Expand DownExpand Up@@ -245,7 +256,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
// ⛔ And nothing was left behind: the object is not registered half-built.
const exists = await (driver as any).knex.schema.hasTable('os11565_over');
expect(exists).toBe(false);
});
}, 60_000);

/** The card's second measured row, moved by the driver's own `id` column. */
it('creates 63 fields at maxLength 255 and refuses 64', async () => {
Expand All@@ -259,7 +270,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
await expect(driver.initObjects([wideObject('os11565_over255', 64, 255)])).rejects.toThrow(
/cannot create table "os11565_over255".*Its 64 varchar column\(s\) take 65408 bytes/s,
);
});
}, 60_000);

/**
* The path that is more likely than CREATE in a living app: a field added
Expand All@@ -275,7 +286,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
await expect(driver.initObjects([wideObject('os11565_grow', 16, 1024)])).rejects.toThrow(
/cannot add column\(s\) "f16" to "os11565_grow".*Its 16 varchar column\(s\)/s,
);
});
}, 60_000);

/**
* The SECOND limit, which the card's threshold table does not reach and a
Expand All@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
expect(message).toMatch(/InnoDB's per-PAGE limit of 8126 bytes/);
expect(message).not.toMatch(/65535-byte budget for one ROW/);
expect(message).toMatch(/"f1" varchar\(63\) = 253 bytes/);
});
}, 60_000);

/**
* The shape a diagnostic reading only DECLARED bounds would have nothing to
Expand All@@ -315,6 +326,6 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
const message = String(failure.message);
expect(message).toMatch(/"f1" varchar\(255\) = 1022 bytes/);
expect(message).toMatch(/a field declaring NO `maxLength` still takes varchar\(255\)/i);
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -132,6 +132,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
* The accept transition: schema creation MySQL REFUSED before this change
* now succeeds, and the constraint is carried on a full-width digest.
*/
// ── Why the 9 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('creates a UNIQUE index over a 1024-char column, on a varbinary(32) shadow', async () => {
driver = new SqlDriver(cell.config());
await driver.initObjects([uniqueOn('os11627_wide', 1024)]);
Expand All@@ -156,7 +167,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
// ⛔ The control that separates this from the REJECTED route: a prefix
// index reports a SUB_PART. The shadow index keys a whole column.
expect(carried[0].SUB_PART).toBeNull();
});
}, 60_000);

/**
* The boundary, both sides, read from the catalog: 768 characters is the
Expand All@@ -176,7 +187,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const over = await catalog('os11627_over');
expect(String(over.cols.find((c: any) => c.COLUMN_NAME === 'v').DATA_TYPE)).toBe('text');
expect(over.cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME)).length).toBe(1);
});
}, 60_000);

/**
* ⛔ The assertion a PREFIX index fails. Two distinct values sharing their
Expand All@@ -198,7 +209,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {

// …and the constraint is real: the same value twice is refused.
await expect(knex('os11627_sem').insert({ id: 'dup', v: `${shared}AAA` })).rejects.toThrow();
});
}, 60_000);

/**
* NULL must stay DISTINCT, exactly as under a direct UNIQUE index.
Expand All@@ -213,7 +224,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const knex = (driver as any).knex;
await knex('os11627_null').insert([{ id: 'n1', v: null }, { id: 'n2', v: null }, { id: 'n3', v: null }]);
expect((await knex('os11627_null').whereNull('v')).length).toBe(3);
});
}, 60_000);

/**
* A COMPOSITE unique hashes the tuple, and a tuple containing NULL must
Expand All@@ -239,7 +250,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await knex('os11627_comp').insert([{ id: 's1', a: 'xy', b: '' }, { id: 's2', a: 'x', b: 'y2' }]);
// …and the composite constraint still bites.
await expect(knex('os11627_comp').insert({ id: 'dup', a: 'x', b: 'y' })).rejects.toThrow();
});
}, 60_000);

/**
* The digest stored is the one this repo can independently recompute — the
Expand All@@ -257,7 +268,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const stored: Buffer = row[shadowCol];
expect(stored.length).toBe(32);
expect(stored.toString('hex')).toBe(createHash('sha256').update(value).digest('hex'));
});
}, 60_000);

/**
* The clause-② half: once uniqueness is enforced over a DIGEST, MySQL's
Expand All@@ -277,7 +288,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await expect(driver.create('os11627_dup', { v: 'T'.repeat(900) })).rejects.toThrow(
/duplicate value for the UNIQUE constraint 'uniq_os11627_dup_v'.*\(v\)/s,
);
});
}, 60_000);

/**
* ⛔ NON-UNIQUE indexes are deliberately NOT shadowed. An index over a
Expand All@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await expect(driver.initObjects([nonUnique])).rejects.toThrow(
/hash-shadow|cannot create index|BLOB\/TEXT/i,
);
});
}, 60_000);
});
});

Expand DownExpand Up@@ -327,6 +338,6 @@ declareDialectCell(PG_CELL, 'hash-shadow key (#11627)', (cell) => {
);
const defs = (idx.rows ?? []).map((r: any) => String(r.indexdef)).join('\n');
expect(defs).toMatch(/UNIQUE INDEX .*uniq_os11627_pg_v.*\(v\)/i);
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -236,6 +236,17 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
await driver?.disconnect().catch(() => {});
});

// ── Why the 3 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('accepts a >255-char richtext body, and the column really is TEXT (information_schema)', async () => {
driver = new SqlDriver(cell.config());
await driver.execute(`drop table if exists ${T}`).catch(() => {});
Expand DownExpand Up@@ -280,7 +291,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
expect(refusal).toBeInstanceOf(Error);
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
});
}, 60_000);

it('closes the formerly-open half (#11875): an oversized data-URI signature/qrcode is accepted and round-trips', async () => {
// The #11794 version of this case asserted the COST of leaving
Expand All@@ -299,7 +310,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
const [row] = await driver.find(T, { where: { id: 's1' } }, OPTS);
expect(row.body_sig).toBe(DATA_URI);
expect(row.body_qr).toBe(DATA_URI);
});
}, 60_000);

it('keeps #11374 keyed-and-bounded semantics live for the new members (#11875)', async () => {
// A KEYED bounded signature/qrcode column is varchar(maxLength) — the
Expand DownExpand Up@@ -348,7 +359,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
await driver.execute(`drop table if exists ${KT}`).catch(() => {});
});
}, 60_000);
});
});
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
* equivalence pin: the shadow enforces the SAME key the direct
* `COALESCE(organization_id, '__global__')` index would have.
*/
// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('collides two NULL-organization rows under an org-scoped shadow unique', async () => {
driver = new SqlDriver(cell.config());
await driver.initObjects([orgUniqueOn('os12998_org')]);
Expand DownExpand Up@@ -124,7 +135,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
await expect(
knex('os12998_org').insert({ id: 'f', v: V2, organization_id: null }),
).rejects.toThrow(/duplicate/i);
});
}, 60_000);

/**
* ⛔ The control, colocated: a PLAIN composite's expression must NOT gain a
Expand All@@ -151,7 +162,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
{ id: 'n2', a: 'x'.repeat(900), b: null },
]);
expect((await knex('os12998_plain').whereNull('b')).length).toBe(2);
});
}, 60_000);

/**
* Turning the constraint ON is data-dependent (ADR-0120 D4's exact shape):
Expand DownExpand Up@@ -196,7 +207,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
const { cols, idx } = await catalog('os12998_dirty');
expect(idx.some((i: any) => i.INDEX_NAME === 'uniq_os12998_dirty_org_v')).toBe(false);
expect(cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME))).toEqual([]);
});
}, 60_000);

/**
* The write-path half of ruling #11627 clause-②, now for the NULL-safe
Expand All@@ -220,6 +231,6 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
expect(msg).toMatch(/duplicate value for the UNIQUE constraint 'uniq_os12998_msg_org_v'/);
expect(msg).toContain("COALESCE(organization_id, '__global__')");
expect(msg).not.toContain('HASH COLLISION');
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -266,6 +266,17 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
);
};

// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('a freshly synced shadow-carried unique reports no destructive index drift', async () => {
driver = new SqlDriver(cell.config());
const obj = orgUniqueOn('os13015_fresh');
Expand All@@ -281,7 +292,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
// And the shadow COLUMN is still protected from the orphan-column pass —
// the half of the vocabulary that was already taught.
expect(drift.filter((d) => d.kind === 'unmapped_column')).toEqual([]);
});
}, 60_000);

/**
* The remedy pin. Even on a second boot — the runtime ledger empty again,
Expand DownExpand Up@@ -312,7 +323,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
await expect(
knex('os13015_apply').insert({ id: 'b', v: V, organization_id: null }),
).rejects.toThrow(/duplicate/i);
});
}, 60_000);

/**
* The surviving generated column, isolated: drop the index by name (exactly
Expand All@@ -335,7 +346,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>

await driver.initObjects([obj]);
expect(await carriedUniquePresent('os13015_survive', indexName)).toBe(true);
});
}, 60_000);

/**
* The direction a blind skip would have lost: a shadow hashing the RAW
Expand DownExpand Up@@ -376,6 +387,6 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
const after = await catalog('os13015_stale');
const fixed = after.cols.find((c: any) => c.COLUMN_NAME === shadow);
expect(String(fixed.GENERATION_EXPRESSION).toLowerCase()).toContain('coalesce');
});
}, 60_000);
});
});
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
Original file line numberDiff line numberDiff line change
Expand Up@@ -436,6 +436,17 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
driver = undefined;
});

// ── Why the it() below carries an explicit 60_000 budget (#13902) ──
// It constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside its own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('hands back strings for `date` and `date[]`, and keeps `timestamptz` an instant', async () => {
driver = new SqlDriver(cell.config());
await underProcessZone('Asia/Shanghai', async () => {
Expand All@@ -456,6 +467,6 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
expect(row.ts instanceof Date).toBe(true);
expect((row.ts as Date).toISOString()).toBe(`${DAY}T00:00:00.000Z`);
});
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,12 +198,23 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
* the cell asserts the multiplier rather than assuming it, the same way the
* matrix asserts its zone skew instead of hoping for it.
*/
// ── Why the 6 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('runs on a 4-byte charset — the boundaries below are utf8mb4 numbers', async () => {
driver = new SqlDriver(cell.config());
const seen = await (driver as any).schemaBytesPerChar();
expect(seen).not.toBeNull();
expect(seen.bytesPerChar).toBe(4);
});
}, 60_000);

/**
* Both sides of the boundary, in one test, because only the pair means
Expand DownExpand Up@@ -245,7 +256,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
// ⛔ And nothing was left behind: the object is not registered half-built.
const exists = await (driver as any).knex.schema.hasTable('os11565_over');
expect(exists).toBe(false);
});
}, 60_000);

/** The card's second measured row, moved by the driver's own `id` column. */
it('creates 63 fields at maxLength 255 and refuses 64', async () => {
Expand All@@ -259,7 +270,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
await expect(driver.initObjects([wideObject('os11565_over255', 64, 255)])).rejects.toThrow(
/cannot create table "os11565_over255".*Its 64 varchar column\(s\) take 65408 bytes/s,
);
});
}, 60_000);

/**
* The path that is more likely than CREATE in a living app: a field added
Expand All@@ -275,7 +286,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
await expect(driver.initObjects([wideObject('os11565_grow', 16, 1024)])).rejects.toThrow(
/cannot add column\(s\) "f16" to "os11565_grow".*Its 16 varchar column\(s\)/s,
);
});
}, 60_000);

/**
* The SECOND limit, which the card's threshold table does not reach and a
Expand All@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
expect(message).toMatch(/InnoDB's per-PAGE limit of 8126 bytes/);
expect(message).not.toMatch(/65535-byte budget for one ROW/);
expect(message).toMatch(/"f1" varchar\(63\) = 253 bytes/);
});
}, 60_000);

/**
* The shape a diagnostic reading only DECLARED bounds would have nothing to
Expand All@@ -315,6 +326,6 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
const message = String(failure.message);
expect(message).toMatch(/"f1" varchar\(255\) = 1022 bytes/);
expect(message).toMatch(/a field declaring NO `maxLength` still takes varchar\(255\)/i);
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -132,6 +132,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
* The accept transition: schema creation MySQL REFUSED before this change
* now succeeds, and the constraint is carried on a full-width digest.
*/
// ── Why the 9 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('creates a UNIQUE index over a 1024-char column, on a varbinary(32) shadow', async () => {
driver = new SqlDriver(cell.config());
await driver.initObjects([uniqueOn('os11627_wide', 1024)]);
Expand All@@ -156,7 +167,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
// ⛔ The control that separates this from the REJECTED route: a prefix
// index reports a SUB_PART. The shadow index keys a whole column.
expect(carried[0].SUB_PART).toBeNull();
});
}, 60_000);

/**
* The boundary, both sides, read from the catalog: 768 characters is the
Expand All@@ -176,7 +187,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const over = await catalog('os11627_over');
expect(String(over.cols.find((c: any) => c.COLUMN_NAME === 'v').DATA_TYPE)).toBe('text');
expect(over.cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME)).length).toBe(1);
});
}, 60_000);

/**
* ⛔ The assertion a PREFIX index fails. Two distinct values sharing their
Expand All@@ -198,7 +209,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {

// …and the constraint is real: the same value twice is refused.
await expect(knex('os11627_sem').insert({ id: 'dup', v: `${shared}AAA` })).rejects.toThrow();
});
}, 60_000);

/**
* NULL must stay DISTINCT, exactly as under a direct UNIQUE index.
Expand All@@ -213,7 +224,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const knex = (driver as any).knex;
await knex('os11627_null').insert([{ id: 'n1', v: null }, { id: 'n2', v: null }, { id: 'n3', v: null }]);
expect((await knex('os11627_null').whereNull('v')).length).toBe(3);
});
}, 60_000);

/**
* A COMPOSITE unique hashes the tuple, and a tuple containing NULL must
Expand All@@ -239,7 +250,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await knex('os11627_comp').insert([{ id: 's1', a: 'xy', b: '' }, { id: 's2', a: 'x', b: 'y2' }]);
// …and the composite constraint still bites.
await expect(knex('os11627_comp').insert({ id: 'dup', a: 'x', b: 'y' })).rejects.toThrow();
});
}, 60_000);

/**
* The digest stored is the one this repo can independently recompute — the
Expand All@@ -257,7 +268,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const stored: Buffer = row[shadowCol];
expect(stored.length).toBe(32);
expect(stored.toString('hex')).toBe(createHash('sha256').update(value).digest('hex'));
});
}, 60_000);

/**
* The clause-② half: once uniqueness is enforced over a DIGEST, MySQL's
Expand All@@ -277,7 +288,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await expect(driver.create('os11627_dup', { v: 'T'.repeat(900) })).rejects.toThrow(
/duplicate value for the UNIQUE constraint 'uniq_os11627_dup_v'.*\(v\)/s,
);
});
}, 60_000);

/**
* ⛔ NON-UNIQUE indexes are deliberately NOT shadowed. An index over a
Expand All@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await expect(driver.initObjects([nonUnique])).rejects.toThrow(
/hash-shadow|cannot create index|BLOB\/TEXT/i,
);
});
}, 60_000);
});
});

Expand DownExpand Up@@ -327,6 +338,6 @@ declareDialectCell(PG_CELL, 'hash-shadow key (#11627)', (cell) => {
);
const defs = (idx.rows ?? []).map((r: any) => String(r.indexdef)).join('\n');
expect(defs).toMatch(/UNIQUE INDEX .*uniq_os11627_pg_v.*\(v\)/i);
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -236,6 +236,17 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
await driver?.disconnect().catch(() => {});
});

// ── Why the 3 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('accepts a >255-char richtext body, and the column really is TEXT (information_schema)', async () => {
driver = new SqlDriver(cell.config());
await driver.execute(`drop table if exists ${T}`).catch(() => {});
Expand DownExpand Up@@ -280,7 +291,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
expect(refusal).toBeInstanceOf(Error);
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
});
}, 60_000);

it('closes the formerly-open half (#11875): an oversized data-URI signature/qrcode is accepted and round-trips', async () => {
// The #11794 version of this case asserted the COST of leaving
Expand All@@ -299,7 +310,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
const [row] = await driver.find(T, { where: { id: 's1' } }, OPTS);
expect(row.body_sig).toBe(DATA_URI);
expect(row.body_qr).toBe(DATA_URI);
});
}, 60_000);

it('keeps #11374 keyed-and-bounded semantics live for the new members (#11875)', async () => {
// A KEYED bounded signature/qrcode column is varchar(maxLength) — the
Expand DownExpand Up@@ -348,7 +359,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
await driver.execute(`drop table if exists ${KT}`).catch(() => {});
});
}, 60_000);
});
});
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
* equivalence pin: the shadow enforces the SAME key the direct
* `COALESCE(organization_id, '__global__')` index would have.
*/
// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('collides two NULL-organization rows under an org-scoped shadow unique', async () => {
driver = new SqlDriver(cell.config());
await driver.initObjects([orgUniqueOn('os12998_org')]);
Expand DownExpand Up@@ -124,7 +135,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
await expect(
knex('os12998_org').insert({ id: 'f', v: V2, organization_id: null }),
).rejects.toThrow(/duplicate/i);
});
}, 60_000);

/**
* ⛔ The control, colocated: a PLAIN composite's expression must NOT gain a
Expand All@@ -151,7 +162,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
{ id: 'n2', a: 'x'.repeat(900), b: null },
]);
expect((await knex('os12998_plain').whereNull('b')).length).toBe(2);
});
}, 60_000);

/**
* Turning the constraint ON is data-dependent (ADR-0120 D4's exact shape):
Expand DownExpand Up@@ -196,7 +207,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
const { cols, idx } = await catalog('os12998_dirty');
expect(idx.some((i: any) => i.INDEX_NAME === 'uniq_os12998_dirty_org_v')).toBe(false);
expect(cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME))).toEqual([]);
});
}, 60_000);

/**
* The write-path half of ruling #11627 clause-②, now for the NULL-safe
Expand All@@ -220,6 +231,6 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
expect(msg).toMatch(/duplicate value for the UNIQUE constraint 'uniq_os12998_msg_org_v'/);
expect(msg).toContain("COALESCE(organization_id, '__global__')");
expect(msg).not.toContain('HASH COLLISION');
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -266,6 +266,17 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
);
};

// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('a freshly synced shadow-carried unique reports no destructive index drift', async () => {
driver = new SqlDriver(cell.config());
const obj = orgUniqueOn('os13015_fresh');
Expand All@@ -281,7 +292,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
// And the shadow COLUMN is still protected from the orphan-column pass —
// the half of the vocabulary that was already taught.
expect(drift.filter((d) => d.kind === 'unmapped_column')).toEqual([]);
});
}, 60_000);

/**
* The remedy pin. Even on a second boot — the runtime ledger empty again,
Expand DownExpand Up@@ -312,7 +323,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
await expect(
knex('os13015_apply').insert({ id: 'b', v: V, organization_id: null }),
).rejects.toThrow(/duplicate/i);
});
}, 60_000);

/**
* The surviving generated column, isolated: drop the index by name (exactly
Expand All@@ -335,7 +346,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>

await driver.initObjects([obj]);
expect(await carriedUniquePresent('os13015_survive', indexName)).toBe(true);
});
}, 60_000);

/**
* The direction a blind skip would have lost: a shadow hashing the RAW
Expand DownExpand Up@@ -376,6 +387,6 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
const after = await catalog('os13015_stale');
const fixed = after.cols.find((c: any) => c.COLUMN_NAME === shadow);
expect(String(fixed.GENERATION_EXPRESSION).toLowerCase()).toContain('coalesce');
});
}, 60_000);
});
});
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
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
Original file line numberDiff line numberDiff line change
Expand Up@@ -436,6 +436,17 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
driver = undefined;
});

// ── Why the it() below carries an explicit 60_000 budget (#13902) ──
// It constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside its own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('hands back strings for `date` and `date[]`, and keeps `timestamptz` an instant', async () => {
driver = new SqlDriver(cell.config());
await underProcessZone('Asia/Shanghai', async () => {
Expand All@@ -456,6 +467,6 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
expect(row.ts instanceof Date).toBe(true);
expect((row.ts as Date).toISOString()).toBe(`${DAY}T00:00:00.000Z`);
});
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,12 +198,23 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
* the cell asserts the multiplier rather than assuming it, the same way the
* matrix asserts its zone skew instead of hoping for it.
*/
// ── Why the 6 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('runs on a 4-byte charset — the boundaries below are utf8mb4 numbers', async () => {
driver = new SqlDriver(cell.config());
const seen = await (driver as any).schemaBytesPerChar();
expect(seen).not.toBeNull();
expect(seen.bytesPerChar).toBe(4);
});
}, 60_000);

/**
* Both sides of the boundary, in one test, because only the pair means
Expand DownExpand Up@@ -245,7 +256,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
// ⛔ And nothing was left behind: the object is not registered half-built.
const exists = await (driver as any).knex.schema.hasTable('os11565_over');
expect(exists).toBe(false);
});
}, 60_000);

/** The card's second measured row, moved by the driver's own `id` column. */
it('creates 63 fields at maxLength 255 and refuses 64', async () => {
Expand All@@ -259,7 +270,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
await expect(driver.initObjects([wideObject('os11565_over255', 64, 255)])).rejects.toThrow(
/cannot create table "os11565_over255".*Its 64 varchar column\(s\) take 65408 bytes/s,
);
});
}, 60_000);

/**
* The path that is more likely than CREATE in a living app: a field added
Expand All@@ -275,7 +286,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
await expect(driver.initObjects([wideObject('os11565_grow', 16, 1024)])).rejects.toThrow(
/cannot add column\(s\) "f16" to "os11565_grow".*Its 16 varchar column\(s\)/s,
);
});
}, 60_000);

/**
* The SECOND limit, which the card's threshold table does not reach and a
Expand All@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
expect(message).toMatch(/InnoDB's per-PAGE limit of 8126 bytes/);
expect(message).not.toMatch(/65535-byte budget for one ROW/);
expect(message).toMatch(/"f1" varchar\(63\) = 253 bytes/);
});
}, 60_000);

/**
* The shape a diagnostic reading only DECLARED bounds would have nothing to
Expand All@@ -315,6 +326,6 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
const message = String(failure.message);
expect(message).toMatch(/"f1" varchar\(255\) = 1022 bytes/);
expect(message).toMatch(/a field declaring NO `maxLength` still takes varchar\(255\)/i);
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -132,6 +132,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
* The accept transition: schema creation MySQL REFUSED before this change
* now succeeds, and the constraint is carried on a full-width digest.
*/
// ── Why the 9 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('creates a UNIQUE index over a 1024-char column, on a varbinary(32) shadow', async () => {
driver = new SqlDriver(cell.config());
await driver.initObjects([uniqueOn('os11627_wide', 1024)]);
Expand All@@ -156,7 +167,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
// ⛔ The control that separates this from the REJECTED route: a prefix
// index reports a SUB_PART. The shadow index keys a whole column.
expect(carried[0].SUB_PART).toBeNull();
});
}, 60_000);

/**
* The boundary, both sides, read from the catalog: 768 characters is the
Expand All@@ -176,7 +187,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const over = await catalog('os11627_over');
expect(String(over.cols.find((c: any) => c.COLUMN_NAME === 'v').DATA_TYPE)).toBe('text');
expect(over.cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME)).length).toBe(1);
});
}, 60_000);

/**
* ⛔ The assertion a PREFIX index fails. Two distinct values sharing their
Expand All@@ -198,7 +209,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {

// …and the constraint is real: the same value twice is refused.
await expect(knex('os11627_sem').insert({ id: 'dup', v: `${shared}AAA` })).rejects.toThrow();
});
}, 60_000);

/**
* NULL must stay DISTINCT, exactly as under a direct UNIQUE index.
Expand All@@ -213,7 +224,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const knex = (driver as any).knex;
await knex('os11627_null').insert([{ id: 'n1', v: null }, { id: 'n2', v: null }, { id: 'n3', v: null }]);
expect((await knex('os11627_null').whereNull('v')).length).toBe(3);
});
}, 60_000);

/**
* A COMPOSITE unique hashes the tuple, and a tuple containing NULL must
Expand All@@ -239,7 +250,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await knex('os11627_comp').insert([{ id: 's1', a: 'xy', b: '' }, { id: 's2', a: 'x', b: 'y2' }]);
// …and the composite constraint still bites.
await expect(knex('os11627_comp').insert({ id: 'dup', a: 'x', b: 'y' })).rejects.toThrow();
});
}, 60_000);

/**
* The digest stored is the one this repo can independently recompute — the
Expand All@@ -257,7 +268,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
const stored: Buffer = row[shadowCol];
expect(stored.length).toBe(32);
expect(stored.toString('hex')).toBe(createHash('sha256').update(value).digest('hex'));
});
}, 60_000);

/**
* The clause-② half: once uniqueness is enforced over a DIGEST, MySQL's
Expand All@@ -277,7 +288,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await expect(driver.create('os11627_dup', { v: 'T'.repeat(900) })).rejects.toThrow(
/duplicate value for the UNIQUE constraint 'uniq_os11627_dup_v'.*\(v\)/s,
);
});
}, 60_000);

/**
* ⛔ NON-UNIQUE indexes are deliberately NOT shadowed. An index over a
Expand All@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
await expect(driver.initObjects([nonUnique])).rejects.toThrow(
/hash-shadow|cannot create index|BLOB\/TEXT/i,
);
});
}, 60_000);
});
});

Expand DownExpand Up@@ -327,6 +338,6 @@ declareDialectCell(PG_CELL, 'hash-shadow key (#11627)', (cell) => {
);
const defs = (idx.rows ?? []).map((r: any) => String(r.indexdef)).join('\n');
expect(defs).toMatch(/UNIQUE INDEX .*uniq_os11627_pg_v.*\(v\)/i);
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -236,6 +236,17 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
await driver?.disconnect().catch(() => {});
});

// ── Why the 3 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('accepts a >255-char richtext body, and the column really is TEXT (information_schema)', async () => {
driver = new SqlDriver(cell.config());
await driver.execute(`drop table if exists ${T}`).catch(() => {});
Expand DownExpand Up@@ -280,7 +291,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
expect(refusal).toBeInstanceOf(Error);
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
});
}, 60_000);

it('closes the formerly-open half (#11875): an oversized data-URI signature/qrcode is accepted and round-trips', async () => {
// The #11794 version of this case asserted the COST of leaving
Expand All@@ -299,7 +310,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
const [row] = await driver.find(T, { where: { id: 's1' } }, OPTS);
expect(row.body_sig).toBe(DATA_URI);
expect(row.body_qr).toBe(DATA_URI);
});
}, 60_000);

it('keeps #11374 keyed-and-bounded semantics live for the new members (#11875)', async () => {
// A KEYED bounded signature/qrcode column is varchar(maxLength) — the
Expand DownExpand Up@@ -348,7 +359,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
await driver.execute(`drop table if exists ${KT}`).catch(() => {});
});
}, 60_000);
});
});
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
* equivalence pin: the shadow enforces the SAME key the direct
* `COALESCE(organization_id, '__global__')` index would have.
*/
// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('collides two NULL-organization rows under an org-scoped shadow unique', async () => {
driver = new SqlDriver(cell.config());
await driver.initObjects([orgUniqueOn('os12998_org')]);
Expand DownExpand Up@@ -124,7 +135,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
await expect(
knex('os12998_org').insert({ id: 'f', v: V2, organization_id: null }),
).rejects.toThrow(/duplicate/i);
});
}, 60_000);

/**
* ⛔ The control, colocated: a PLAIN composite's expression must NOT gain a
Expand All@@ -151,7 +162,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
{ id: 'n2', a: 'x'.repeat(900), b: null },
]);
expect((await knex('os12998_plain').whereNull('b')).length).toBe(2);
});
}, 60_000);

/**
* Turning the constraint ON is data-dependent (ADR-0120 D4's exact shape):
Expand DownExpand Up@@ -196,7 +207,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
const { cols, idx } = await catalog('os12998_dirty');
expect(idx.some((i: any) => i.INDEX_NAME === 'uniq_os12998_dirty_org_v')).toBe(false);
expect(cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME))).toEqual([]);
});
}, 60_000);

/**
* The write-path half of ruling #11627 clause-②, now for the NULL-safe
Expand All@@ -220,6 +231,6 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
expect(msg).toMatch(/duplicate value for the UNIQUE constraint 'uniq_os12998_msg_org_v'/);
expect(msg).toContain("COALESCE(organization_id, '__global__')");
expect(msg).not.toContain('HASH COLLISION');
});
}, 60_000);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -266,6 +266,17 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
);
};

// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
// server inside their own body — so the live connect cycle, and the
// schema-sync DDL and catalog read-back that all but the cheapest of these
// drive through it, are paid PER TEST rather than once in a beforeAll.
// With no third argument vitest applies its own 5000ms default — a number
// nobody chose for that work, and one that reddens unrelated PRs when the
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
// no MySQL error in the logs, on a diff that touched no driver). Sized like
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
// an assertion that these tests are normally anywhere near that slow.
it('a freshly synced shadow-carried unique reports no destructive index drift', async () => {
driver = new SqlDriver(cell.config());
const obj = orgUniqueOn('os13015_fresh');
Expand All@@ -281,7 +292,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
// And the shadow COLUMN is still protected from the orphan-column pass —
// the half of the vocabulary that was already taught.
expect(drift.filter((d) => d.kind === 'unmapped_column')).toEqual([]);
});
}, 60_000);

/**
* The remedy pin. Even on a second boot — the runtime ledger empty again,
Expand DownExpand Up@@ -312,7 +323,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
await expect(
knex('os13015_apply').insert({ id: 'b', v: V, organization_id: null }),
).rejects.toThrow(/duplicate/i);
});
}, 60_000);

/**
* The surviving generated column, isolated: drop the index by name (exactly
Expand All@@ -335,7 +346,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>

await driver.initObjects([obj]);
expect(await carriedUniquePresent('os13015_survive', indexName)).toBe(true);
});
}, 60_000);

/**
* The direction a blind skip would have lost: a shadow hashing the RAW
Expand DownExpand Up@@ -376,6 +387,6 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
const after = await catalog('os13015_stale');
const fixed = after.cols.find((c: any) => c.COLUMN_NAME === shadow);
expect(String(fixed.GENERATION_EXPRESSION).toLowerCase()).toContain('coalesce');
});
}, 60_000);
});
});
Loading
Loading