* Fix migration 0008 parser stack overflow on macOS bun:sqlite Migration 0008 inlined a 41-deep nested replace() chain (8 dash-collapse replaces wrapping lower(33 single-char replaces wrapping the raw input)) to slugify header names into slot_keys. Bun's lemon SQL parser stack overflows at PREPARE time on the compiled CLI binary on macOS, so users upgrading on Mac couldn't start the CLI at all (the Linux test matrix in CI never exercised the failing path). Replace the deep chain with a temp __slug_norm table populated once at the top of the migration via a series of shallow UPDATE statements (one per replacement), then reference the precomputed slug via flat scalar subqueries everywhere. Semantics verified equivalent against 25 inputs covering case, punctuation, whitespace, dashes-only and unicode. Add structural lint that scans every drizzle migration file and rejects any nested-function call > 20 deep. Catches the regression class on Linux CI without needing macOS in the matrix. * Drop changeset, swap throw for typed expect to satisfy oxlint - Remove .changeset/fix-migration-0008-parser-overflow.md: the existing .changeset/executor-1.4.16.md (still in main, consumed when the open Version Packages PR merges) is enough to ship 1.4.16 with this fix included. - Replace throw new Error(...) in migration-nesting.test.ts with a shaped expect(...).toEqual({...}) that prints file/line/fn/depth in the diff. Satisfies oxlint's no-error-constructor / no-try-catch-or-throw rules without losing the diagnostic.
Unified · Split
| @@ -1,3 +1,86 @@ | ||
| 1 | +-- | |
| 2 | +-- Slug-normalization staging table. | |
| 3 | +-- | |
| 4 | +-- 0008 originally inlined a 41-deep `replace(replace(... lower(...) ...))` | |
| 5 | +-- chain everywhere it derived a slot_key from a header / param / oauth | |
| 6 | +-- scheme name. bun:sqlite's lemon parser stack overflows on that depth on | |
| 7 | +-- platforms with smaller thread stacks (notably the compiled CLI binary on | |
| 8 | +-- macOS), so we precompute slugs once into a temp table and reference them | |
| 9 | +-- via flat scalar subqueries below. | |
| 10 | +-- | |
| 11 | +CREATE TEMP TABLE `__slug_norm` ( | |
| 12 | + `raw` text PRIMARY KEY, | |
| 13 | + `slug` text NOT NULL DEFAULT '' | |
| 14 | +);--> statement-breakpoint | |
| 15 | + | |
| 16 | +INSERT OR IGNORE INTO `__slug_norm` (`raw`) | |
| 17 | +SELECT DISTINCT `raw` FROM ( | |
| 18 | + SELECT h.`key` AS `raw` FROM `openapi_source` s, json_each(s.`headers`) h | |
| 19 | + WHERE s.`headers` IS NOT NULL AND h.`type` = 'object' | |
| 20 | + UNION | |
| 21 | + SELECT json_extract(s.`oauth2`, '$.securitySchemeName') FROM `openapi_source` s | |
| 22 | + WHERE s.`oauth2` IS NOT NULL | |
| 23 | + UNION | |
| 24 | + SELECT `name` FROM `openapi_source_query_param` WHERE `name` IS NOT NULL | |
| 25 | + UNION | |
| 26 | + SELECT `name` FROM `openapi_source_spec_fetch_header` WHERE `name` IS NOT NULL | |
| 27 | + UNION | |
| 28 | + SELECT `name` FROM `openapi_source_spec_fetch_query_param` WHERE `name` IS NOT NULL | |
| 29 | + UNION | |
| 30 | + SELECT `name` FROM `graphql_source_header` WHERE `name` IS NOT NULL | |
| 31 | + UNION | |
| 32 | + SELECT `name` FROM `graphql_source_query_param` WHERE `name` IS NOT NULL | |
| 33 | + UNION | |
| 34 | + SELECT `name` FROM `mcp_source_header` WHERE `name` IS NOT NULL | |
| 35 | + UNION | |
| 36 | + SELECT `name` FROM `mcp_source_query_param` WHERE `name` IS NOT NULL | |
| 37 | +) WHERE `raw` IS NOT NULL AND `raw` != '';--> statement-breakpoint | |
| 38 | + | |
| 39 | +UPDATE `__slug_norm` SET `slug` = lower(trim(`raw`));--> statement-breakpoint | |
| 40 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, char(9), '-');--> statement-breakpoint | |
| 41 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, char(10), '-');--> statement-breakpoint | |
| 42 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, char(13), '-');--> statement-breakpoint | |
| 43 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, ' ', '-');--> statement-breakpoint | |
| 44 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '_', '-');--> statement-breakpoint | |
| 45 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '.', '-');--> statement-breakpoint | |
| 46 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, ':', '-');--> statement-breakpoint | |
| 47 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '/', '-');--> statement-breakpoint | |
| 48 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '@', '-');--> statement-breakpoint | |
| 49 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '+', '-');--> statement-breakpoint | |
| 50 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '&', '-');--> statement-breakpoint | |
| 51 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '?', '-');--> statement-breakpoint | |
| 52 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '#', '-');--> statement-breakpoint | |
| 53 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '%', '-');--> statement-breakpoint | |
| 54 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '$', '-');--> statement-breakpoint | |
| 55 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, ',', '-');--> statement-breakpoint | |
| 56 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, ';', '-');--> statement-breakpoint | |
| 57 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '(', '-');--> statement-breakpoint | |
| 58 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, ')', '-');--> statement-breakpoint | |
| 59 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '[', '-');--> statement-breakpoint | |
| 60 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, ']', '-');--> statement-breakpoint | |
| 61 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '{', '-');--> statement-breakpoint | |
| 62 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '}', '-');--> statement-breakpoint | |
| 63 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '=', '-');--> statement-breakpoint | |
| 64 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '~', '-');--> statement-breakpoint | |
| 65 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '!', '-');--> statement-breakpoint | |
| 66 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, char(34), '-');--> statement-breakpoint | |
| 67 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, char(39), '-');--> statement-breakpoint | |
| 68 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, char(92), '-');--> statement-breakpoint | |
| 69 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '|', '-');--> statement-breakpoint | |
| 70 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '*', '-');--> statement-breakpoint | |
| 71 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '<', '-');--> statement-breakpoint | |
| 72 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '>', '-');--> statement-breakpoint | |
| 73 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '--', '-');--> statement-breakpoint | |
| 74 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '--', '-');--> statement-breakpoint | |
| 75 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '--', '-');--> statement-breakpoint | |
| 76 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '--', '-');--> statement-breakpoint | |
| 77 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '--', '-');--> statement-breakpoint | |
| 78 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '--', '-');--> statement-breakpoint | |
| 79 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '--', '-');--> statement-breakpoint | |
| 80 | +UPDATE `__slug_norm` SET `slug` = replace(`slug`, '--', '-');--> statement-breakpoint | |
| 81 | +UPDATE `__slug_norm` SET `slug` = trim(`slug`, '-');--> statement-breakpoint | |
| 82 | +UPDATE `__slug_norm` SET `slug` = CASE WHEN `slug` = '' THEN 'default' ELSE `slug` END;--> statement-breakpoint | |
| 83 | + | |
| 1 | 84 | -- local scoped credential/source-slot/OAuth cutover. |
| 2 | 85 | -- Squashes the PR-local migration chain into one runtime schema transition. |
| 3 | 86 | -- 0008_add_credential_binding.sql |
| @@ -101,7 +184,7 @@ INSERT INTO `__openapi_header_slot_preflight` (`scope_id`, `source_id`, `slot_ke · 97 unmodified lines | ||
| 101 | 184 | SELECT |
| 102 | 185 | s.`scope_id`, |
| 103 | 186 | s.`id`, |
| 104 | − 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`key`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key` | |
| 187 | + 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`key`), 'default') AS `slot_key` | |
| 105 | 188 | FROM `openapi_source` s, json_each(s.`headers`) h |
| 106 | 189 | WHERE s.`headers` IS NOT NULL |
| 107 | 190 | AND h.`type` = 'object' |
| @@ -115,7 +198,7 @@ WITH header_rows AS ( · 7 unmodified lines | ||
| 115 | 198 | s.`scope_id`, |
| 116 | 199 | s.`id` AS `source_id`, |
| 117 | 200 | h.`key` AS `name`, |
| 118 | − 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`key`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`, | |
| 201 | + 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`key`), 'default') AS `slot_key`, | |
| 119 | 202 | json_extract(h.`value`, '$.secretId') AS `secret_id` |
| 120 | 203 | FROM `openapi_source` s, json_each(s.`headers`) h |
| 121 | 204 | WHERE s.`headers` IS NOT NULL |
| @@ -161,7 +244,7 @@ SET `headers` = ( · 39 unmodified lines | ||
| 161 | 244 | AND json_extract(h.`value`, '$.prefix') IS NOT NULL |
| 162 | 245 | THEN json_object( |
| 163 | 246 | 'kind', 'binding', |
| 164 | − 'slot', 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`key`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default'), | |
| 247 | + 'slot', 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`key`), 'default'), | |
| 165 | 248 | 'prefix', json_extract(h.`value`, '$.prefix') |
| 166 | 249 | ) |
| 167 | 250 | WHEN h.`type` = 'object' |
| @@ -169,7 +252,7 @@ SET `headers` = ( · 1 unmodified line | ||
| 169 | 252 | AND json_extract(h.`value`, '$.secretId') IS NOT NULL |
| 170 | 253 | THEN json_object( |
| 171 | 254 | 'kind', 'binding', |
| 172 | − 'slot', 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`key`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') | |
| 255 | + 'slot', 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`key`), 'default') | |
| 173 | 256 | ) |
| 174 | 257 | WHEN h.`type` IN ('object', 'array') THEN json(h.`value`) |
| 175 | 258 | ELSE h.`value` |
| @@ -186,7 +269,7 @@ WITH oauth_rows AS ( · 10 unmodified lines | ||
| 186 | 269 | s.`scope_id`, |
| 187 | 270 | s.`id` AS `source_id`, |
| 188 | 271 | json_extract(s.`oauth2`, '$.securitySchemeName') AS `security_scheme_name`, |
| 189 | − 'oauth2:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(json_extract(s.`oauth2`, '$.securitySchemeName')), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') || ':client-id' AS `client_id_slot`, | |
| 272 | + 'oauth2:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = json_extract(s.`oauth2`, '$.securitySchemeName')), 'default') || ':client-id' AS `client_id_slot`, | |
| 190 | 273 | json_extract(s.`oauth2`, '$.clientIdSecretId') AS `client_id_secret_id`, |
| 191 | 274 | json_extract(s.`oauth2`, '$.connectionId') AS `connection_id` |
| 192 | 275 | FROM `openapi_source` s |
| @@ -225,7 +308,7 @@ WITH oauth_rows AS ( · 32 unmodified lines | ||
| 225 | 308 | SELECT |
| 226 | 309 | s.`scope_id`, |
| 227 | 310 | s.`id` AS `source_id`, |
| 228 | − 'oauth2:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(json_extract(s.`oauth2`, '$.securitySchemeName')), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') || ':client-secret' AS `client_secret_slot`, | |
| 311 | + 'oauth2:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = json_extract(s.`oauth2`, '$.securitySchemeName')), 'default') || ':client-secret' AS `client_secret_slot`, | |
| 229 | 312 | json_extract(s.`oauth2`, '$.clientSecretSecretId') AS `client_secret_secret_id` |
| 230 | 313 | FROM `openapi_source` s |
| 231 | 314 | WHERE s.`oauth2` IS NOT NULL |
| @@ -263,7 +346,7 @@ WITH oauth_rows AS ( · 31 unmodified lines | ||
| 263 | 346 | SELECT |
| 264 | 347 | s.`scope_id`, |
| 265 | 348 | s.`id` AS `source_id`, |
| 266 | − 'oauth2:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(json_extract(s.`oauth2`, '$.securitySchemeName')), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') || ':connection' AS `connection_slot`, | |
| 349 | + 'oauth2:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = json_extract(s.`oauth2`, '$.securitySchemeName')), 'default') || ':connection' AS `connection_slot`, | |
| 267 | 350 | json_extract(s.`oauth2`, '$.connectionId') AS `connection_id` |
| 268 | 351 | FROM `openapi_source` s |
| 269 | 352 | WHERE s.`oauth2` IS NOT NULL |
| @@ -304,13 +387,13 @@ SET `oauth2` = json_object( · 34 unmodified lines | ||
| 304 | 387 | 'tokenUrl', json_extract(`oauth2`, '$.tokenUrl'), |
| 305 | 388 | 'authorizationUrl', json_extract(`oauth2`, '$.authorizationUrl'), |
| 306 | 389 | 'issuerUrl', json_extract(`oauth2`, '$.issuerUrl'), |
| 307 | − 'clientIdSlot', 'oauth2:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(json_extract(`oauth2`, '$.securitySchemeName')), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') || ':client-id', | |
| 390 | + 'clientIdSlot', 'oauth2:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = json_extract(`oauth2`, '$.securitySchemeName')), 'default') || ':client-id', | |
| 308 | 391 | 'clientSecretSlot', |
| 309 | 392 | CASE |
| 310 | 393 | WHEN json_extract(`oauth2`, '$.clientSecretSecretId') IS NULL THEN NULL |
| 311 | − ELSE 'oauth2:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(json_extract(`oauth2`, '$.securitySchemeName')), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') || ':client-secret' | |
| 394 | + ELSE 'oauth2:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = json_extract(`oauth2`, '$.securitySchemeName')), 'default') || ':client-secret' | |
| 312 | 395 | END, |
| 313 | − 'connectionSlot', 'oauth2:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(json_extract(`oauth2`, '$.securitySchemeName')), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') || ':connection', | |
| 396 | + 'connectionSlot', 'oauth2:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = json_extract(`oauth2`, '$.securitySchemeName')), 'default') || ':connection', | |
| 314 | 397 | 'scopes', json(COALESCE(json_extract(`oauth2`, '$.scopes'), '[]')) |
| 315 | 398 | ) |
| 316 | 399 | WHERE `oauth2` IS NOT NULL |
| @@ -328,7 +411,7 @@ INSERT INTO `__openapi_query_param_slot_preflight` (`scope_id`, `source_id`, `sl · 11 unmodified lines | ||
| 328 | 411 | SELECT |
| 329 | 412 | r.`scope_id`, |
| 330 | 413 | r.`source_id`, |
| 331 | − 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(r.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key` | |
| 414 | + 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = r.`name`), 'default') AS `slot_key` | |
| 332 | 415 | FROM `openapi_source_query_param` r |
| 333 | 416 | WHERE r.`kind` = 'secret' AND r.`secret_id` IS NOT NULL;--> statement-breakpoint |
| 334 | 417 | |
| @@ -338,7 +421,7 @@ WITH rows AS ( · 3 unmodified lines | ||
| 338 | 421 | SELECT |
| 339 | 422 | r.`scope_id`, |
| 340 | 423 | r.`source_id`, |
| 341 | − 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(r.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`, | |
| 424 | + 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = r.`name`), 'default') AS `slot_key`, | |
| 342 | 425 | r.`secret_id` |
| 343 | 426 | FROM `openapi_source_query_param` r |
| 344 | 427 | WHERE r.`kind` = 'secret' AND r.`secret_id` IS NOT NULL |
| @@ -374,7 +457,7 @@ ALTER TABLE `openapi_source_query_param` ADD `slot_key` text;--> statement-break · 29 unmodified lines | ||
| 374 | 457 | ALTER TABLE `openapi_source_query_param` ADD `prefix` text;--> statement-breakpoint |
| 375 | 458 | UPDATE `openapi_source_query_param` |
| 376 | 459 | SET |
| 377 | − `slot_key` = 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default'), | |
| 460 | + `slot_key` = 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = `name`), 'default'), | |
| 378 | 461 | `prefix` = `secret_prefix`, |
| 379 | 462 | `kind` = 'binding' |
| 380 | 463 | WHERE `kind` = 'secret';--> statement-breakpoint |
| @@ -393,7 +476,7 @@ INSERT INTO `__openapi_spec_fetch_header_slot_preflight` (`scope_id`, `source_id · 12 unmodified lines | ||
| 393 | 476 | SELECT |
| 394 | 477 | r.`scope_id`, |
| 395 | 478 | r.`source_id`, |
| 396 | − 'spec_fetch_header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(r.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key` | |
| 479 | + 'spec_fetch_header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = r.`name`), 'default') AS `slot_key` | |
| 397 | 480 | FROM `openapi_source_spec_fetch_header` r |
| 398 | 481 | WHERE r.`kind` = 'secret' AND r.`secret_id` IS NOT NULL;--> statement-breakpoint |
| 399 | 482 | |
| @@ -403,7 +486,7 @@ WITH rows AS ( · 3 unmodified lines | ||
| 403 | 486 | SELECT |
| 404 | 487 | r.`scope_id`, |
| 405 | 488 | r.`source_id`, |
| 406 | − 'spec_fetch_header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(r.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`, | |
| 489 | + 'spec_fetch_header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = r.`name`), 'default') AS `slot_key`, | |
| 407 | 490 | r.`secret_id` |
| 408 | 491 | FROM `openapi_source_spec_fetch_header` r |
| 409 | 492 | WHERE r.`kind` = 'secret' AND r.`secret_id` IS NOT NULL |
| @@ -439,7 +522,7 @@ ALTER TABLE `openapi_source_spec_fetch_header` ADD `slot_key` text;--> statement · 29 unmodified lines | ||
| 439 | 522 | ALTER TABLE `openapi_source_spec_fetch_header` ADD `prefix` text;--> statement-breakpoint |
| 440 | 523 | UPDATE `openapi_source_spec_fetch_header` |
| 441 | 524 | SET |
| 442 | − `slot_key` = 'spec_fetch_header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default'), | |
| 525 | + `slot_key` = 'spec_fetch_header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = `name`), 'default'), | |
| 443 | 526 | `prefix` = `secret_prefix`, |
| 444 | 527 | `kind` = 'binding' |
| 445 | 528 | WHERE `kind` = 'secret';--> statement-breakpoint |
| @@ -458,7 +541,7 @@ INSERT INTO `__openapi_spec_fetch_query_param_slot_preflight` (`scope_id`, `sour · 12 unmodified lines | ||
| 458 | 541 | SELECT |
| 459 | 542 | r.`scope_id`, |
| 460 | 543 | r.`source_id`, |
| 461 | − 'spec_fetch_query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(r.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key` | |
| 544 | + 'spec_fetch_query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = r.`name`), 'default') AS `slot_key` | |
| 462 | 545 | FROM `openapi_source_spec_fetch_query_param` r |
| 463 | 546 | WHERE r.`kind` = 'secret' AND r.`secret_id` IS NOT NULL;--> statement-breakpoint |
| 464 | 547 | |
| @@ -468,7 +551,7 @@ WITH rows AS ( · 3 unmodified lines | ||
| 468 | 551 | SELECT |
| 469 | 552 | r.`scope_id`, |
| 470 | 553 | r.`source_id`, |
| 471 | − 'spec_fetch_query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(r.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`, | |
| 554 | + 'spec_fetch_query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = r.`name`), 'default') AS `slot_key`, | |
| 472 | 555 | r.`secret_id` |
| 473 | 556 | FROM `openapi_source_spec_fetch_query_param` r |
| 474 | 557 | WHERE r.`kind` = 'secret' AND r.`secret_id` IS NOT NULL |
| @@ -504,7 +587,7 @@ ALTER TABLE `openapi_source_spec_fetch_query_param` ADD `slot_key` text;--> stat · 29 unmodified lines | ||
| 504 | 587 | ALTER TABLE `openapi_source_spec_fetch_query_param` ADD `prefix` text;--> statement-breakpoint |
| 505 | 588 | UPDATE `openapi_source_spec_fetch_query_param` |
| 506 | 589 | SET |
| 507 | − `slot_key` = 'spec_fetch_query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default'), | |
| 590 | + `slot_key` = 'spec_fetch_query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = `name`), 'default'), | |
| 508 | 591 | `prefix` = `secret_prefix`, |
| 509 | 592 | `kind` = 'binding' |
| 510 | 593 | WHERE `kind` = 'secret';--> statement-breakpoint |
| @@ -562,7 +645,7 @@ INSERT INTO `__graphql_header_slot_preflight` (`scope_id`, `source_id`, `slot_ke · 51 unmodified lines | ||
| 562 | 645 | SELECT |
| 563 | 646 | h.`scope_id`, |
| 564 | 647 | h.`source_id`, |
| 565 | − 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key` | |
| 648 | + 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`name`), 'default') AS `slot_key` | |
| 566 | 649 | FROM `graphql_source_header` h |
| 567 | 650 | WHERE h.`kind` = 'secret' |
| 568 | 651 | AND h.`secret_id` IS NOT NULL;--> statement-breakpoint |
| @@ -574,7 +657,7 @@ WITH header_rows AS ( · 5 unmodified lines | ||
| 574 | 657 | h.`scope_id`, |
| 575 | 658 | h.`source_id`, |
| 576 | 659 | h.`name`, |
| 577 | − 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`, | |
| 660 | + 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`name`), 'default') AS `slot_key`, | |
| 578 | 661 | h.`secret_id`, |
| 579 | 662 | h.`secret_prefix` |
| 580 | 663 | FROM `graphql_source_header` h |
| @@ -603,7 +686,7 @@ FROM header_rows r;--> statement-breakpoint · 22 unmodified lines | ||
| 603 | 686 | UPDATE `graphql_source_header` |
| 604 | 687 | SET |
| 605 | 688 | `kind` = 'binding', |
| 606 | − `slot_key` = 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default'), | |
| 689 | + `slot_key` = 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = `name`), 'default'), | |
| 607 | 690 | `prefix` = `secret_prefix`, |
| 608 | 691 | `text_value` = NULL |
| 609 | 692 | WHERE `kind` = 'secret' |
| @@ -627,7 +710,7 @@ INSERT INTO `__graphql_query_param_slot_preflight` (`scope_id`, `source_id`, `sl · 17 unmodified lines | ||
| 627 | 710 | SELECT |
| 628 | 711 | q.`scope_id`, |
| 629 | 712 | q.`source_id`, |
| 630 | − 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(q.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key` | |
| 713 | + 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = q.`name`), 'default') AS `slot_key` | |
| 631 | 714 | FROM `graphql_source_query_param` q |
| 632 | 715 | WHERE q.`kind` = 'secret' |
| 633 | 716 | AND q.`secret_id` IS NOT NULL;--> statement-breakpoint |
| @@ -639,7 +722,7 @@ WITH query_param_rows AS ( · 5 unmodified lines | ||
| 639 | 722 | q.`scope_id`, |
| 640 | 723 | q.`source_id`, |
| 641 | 724 | q.`name`, |
| 642 | − 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(q.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`, | |
| 725 | + 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = q.`name`), 'default') AS `slot_key`, | |
| 643 | 726 | q.`secret_id`, |
| 644 | 727 | q.`secret_prefix` |
| 645 | 728 | FROM `graphql_source_query_param` q |
| @@ -668,7 +751,7 @@ FROM query_param_rows r;--> statement-breakpoint · 22 unmodified lines | ||
| 668 | 751 | UPDATE `graphql_source_query_param` |
| 669 | 752 | SET |
| 670 | 753 | `kind` = 'binding', |
| 671 | − `slot_key` = 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default'), | |
| 754 | + `slot_key` = 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = `name`), 'default'), | |
| 672 | 755 | `prefix` = `secret_prefix`, |
| 673 | 756 | `text_value` = NULL |
| 674 | 757 | WHERE `kind` = 'secret' |
| @@ -818,7 +901,7 @@ INSERT INTO `__mcp_header_slot_preflight` (`scope_id`, `source_id`, `slot_key`) · 143 unmodified lines | ||
| 818 | 901 | SELECT |
| 819 | 902 | h.`scope_id`, |
| 820 | 903 | h.`source_id`, |
| 821 | − 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key` | |
| 904 | + 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`name`), 'default') AS `slot_key` | |
| 822 | 905 | FROM `mcp_source_header` h |
| 823 | 906 | WHERE h.`kind` = 'secret' |
| 824 | 907 | AND h.`secret_id` IS NOT NULL;--> statement-breakpoint |
| @@ -830,7 +913,7 @@ WITH header_rows AS ( · 5 unmodified lines | ||
| 830 | 913 | h.`scope_id`, |
| 831 | 914 | h.`source_id`, |
| 832 | 915 | h.`name`, |
| 833 | − 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`, | |
| 916 | + 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`name`), 'default') AS `slot_key`, | |
| 834 | 917 | h.`secret_id`, |
| 835 | 918 | h.`secret_prefix` |
| 836 | 919 | FROM `mcp_source_header` h |
| @@ -859,7 +942,7 @@ FROM header_rows r;--> statement-breakpoint · 22 unmodified lines | ||
| 859 | 942 | UPDATE `mcp_source_header` |
| 860 | 943 | SET |
| 861 | 944 | `kind` = 'binding', |
| 862 | − `slot_key` = 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default'), | |
| 945 | + `slot_key` = 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = `name`), 'default'), | |
| 863 | 946 | `prefix` = `secret_prefix`, |
| 864 | 947 | `text_value` = NULL |
| 865 | 948 | WHERE `kind` = 'secret' |
| @@ -883,7 +966,7 @@ INSERT INTO `__mcp_query_param_slot_preflight` (`scope_id`, `source_id`, `slot_k · 17 unmodified lines | ||
| 883 | 966 | SELECT |
| 884 | 967 | q.`scope_id`, |
| 885 | 968 | q.`source_id`, |
| 886 | − 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(q.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key` | |
| 969 | + 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = q.`name`), 'default') AS `slot_key` | |
| 887 | 970 | FROM `mcp_source_query_param` q |
| 888 | 971 | WHERE q.`kind` = 'secret' |
| 889 | 972 | AND q.`secret_id` IS NOT NULL;--> statement-breakpoint |
| @@ -895,7 +978,7 @@ WITH query_param_rows AS ( · 5 unmodified lines | ||
| 895 | 978 | q.`scope_id`, |
| 896 | 979 | q.`source_id`, |
| 897 | 980 | q.`name`, |
| 898 | − 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(q.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`, | |
| 981 | + 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = q.`name`), 'default') AS `slot_key`, | |
| 899 | 982 | q.`secret_id`, |
| 900 | 983 | q.`secret_prefix` |
| 901 | 984 | FROM `mcp_source_query_param` q |
| @@ -924,7 +1007,7 @@ FROM query_param_rows r;--> statement-breakpoint · 22 unmodified lines | ||
| 924 | 1007 | UPDATE `mcp_source_query_param` |
| 925 | 1008 | SET |
| 926 | 1009 | `kind` = 'binding', |
| 927 | − `slot_key` = 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default'), | |
| 1010 | + `slot_key` = 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = `name`), 'default'), | |
| 928 | 1011 | `prefix` = `secret_prefix`, |
| 929 | 1012 | `text_value` = NULL |
| 930 | 1013 | WHERE `kind` = 'secret' |
| @@ -1038,7 +1121,7 @@ INSERT INTO `__openapi_header_row_slot_preflight` (`scope_id`, `source_id`, `slo · 107 unmodified lines | ||
| 1038 | 1121 | SELECT |
| 1039 | 1122 | s.`scope_id`, |
| 1040 | 1123 | s.`id`, |
| 1041 | − 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`key`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key` | |
| 1124 | + 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`key`), 'default') AS `slot_key` | |
| 1042 | 1125 | FROM `openapi_source` s, json_each(s.`headers`) h |
| 1043 | 1126 | WHERE s.`headers` IS NOT NULL |
| 1044 | 1127 | AND h.`type` = 'object' |
| @@ -1052,7 +1135,7 @@ WITH header_rows AS ( · 7 unmodified lines | ||
| 1052 | 1135 | s.`scope_id`, |
| 1053 | 1136 | s.`id` AS `source_id`, |
| 1054 | 1137 | h.`key` AS `name`, |
| 1055 | − 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`key`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`, | |
| 1138 | + 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`key`), 'default') AS `slot_key`, | |
| 1056 | 1139 | json_extract(h.`value`, '$.secretId') AS `secret_id` |
| 1057 | 1140 | FROM `openapi_source` s, json_each(s.`headers`) h |
| 1058 | 1141 | WHERE s.`headers` IS NOT NULL |
| @@ -1110,7 +1193,7 @@ SELECT · 51 unmodified lines | ||
| 1110 | 1193 | WHEN h.`type` = 'object' AND json_extract(h.`value`, '$.kind') = 'binding' |
| 1111 | 1194 | THEN json_extract(h.`value`, '$.slot') |
| 1112 | 1195 | WHEN h.`type` = 'object' AND json_extract(h.`value`, '$.secretId') IS NOT NULL |
| 1113 | − THEN 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`key`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') | |
| 1196 | + THEN 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`key`), 'default') | |
| 1114 | 1197 | ELSE NULL |
| 1115 | 1198 | END, |
| 1116 | 1199 | CASE |
| @@ -1132,3 +1215,6 @@ WHERE s.`headers` IS NOT NULL · 15 unmodified lines | ||
| 1132 | 1215 | );--> statement-breakpoint |
| 1133 | 1216 | |
| 1134 | 1217 | ALTER TABLE `openapi_source` DROP COLUMN `headers`; |
| 1218 | + | |
| 1219 | +--> statement-breakpoint | |
| 1220 | +DROP TABLE `__slug_norm`; | |
| @@ -0,0 +1,108 @@ | ||
| 1 | +// Lint: reject migration SQL that nests a single function call too deeply. | |
| 2 | +// | |
| 3 | +// bun:sqlite's lemon parser stack overflows at PREPARE time when an | |
| 4 | +// expression nests too deep, and the limit is platform-dependent — the | |
| 5 | +// macOS-built compiled CLI binary trips around ~40 levels while Linux can | |
| 6 | +// go further. Our test matrix only runs on Linux today, so a regression | |
| 7 | +// won't surface in CI; this lint catches the class of bug structurally | |
| 8 | +// instead. Cap is 20 (well above any legitimate nested-function call we | |
| 9 | +// have today, well below the macOS bun:sqlite parser limit). | |
| 10 | +import { describe, expect, it } from "@effect/vitest"; | |
| 11 | +import { readdirSync, readFileSync } from "node:fs"; | |
| 12 | +import { join } from "node:path"; | |
| 13 | + | |
| 14 | +const MIGRATIONS_FOLDER = join(import.meta.dirname, "../../drizzle"); | |
| 15 | +const MAX_NESTING = 20; | |
| 16 | + | |
| 17 | +// Walk the SQL char-by-char tracking the call-stack of nested function | |
| 18 | +// names. A "function call" is any IDENT immediately followed by `(`. | |
| 19 | +// Returns { fn, depth } for the deepest single-name nest found, or null. | |
| 20 | +const findDeepestNest = (sql: string) => { | |
| 21 | + const stack: string[] = []; | |
| 22 | + let worst: { fn: string; depth: number; offset: number } | null = null; | |
| 23 | + let i = 0; | |
| 24 | + while (i < sql.length) { | |
| 25 | + const ch = sql[i]; | |
| 26 | + // Skip line comments | |
| 27 | + if (ch === "-" && sql[i + 1] === "-") { | |
| 28 | + const eol = sql.indexOf("\n", i); | |
| 29 | + i = eol < 0 ? sql.length : eol + 1; | |
| 30 | + continue; | |
| 31 | + } | |
| 32 | + // Skip string literals (single- and double-quoted, backtick identifiers) | |
| 33 | + if (ch === "'" || ch === '"' || ch === "`") { | |
| 34 | + const quote = ch; | |
| 35 | + i++; | |
| 36 | + while (i < sql.length) { | |
| 37 | + if (sql[i] === quote) { | |
| 38 | + if (sql[i + 1] === quote) { | |
| 39 | + i += 2; | |
| 40 | + continue; | |
| 41 | + } | |
| 42 | + i++; | |
| 43 | + break; | |
| 44 | + } | |
| 45 | + i++; | |
| 46 | + } | |
| 47 | + continue; | |
| 48 | + } | |
| 49 | + if (ch === "(") { | |
| 50 | + // Walk back to find an IDENT immediately preceding this paren | |
| 51 | + let j = i - 1; | |
| 52 | + while (j >= 0 && /\s/u.test(sql[j])) j--; | |
| 53 | + let end = j; | |
| 54 | + while (j >= 0 && /[A-Za-z0-9_]/u.test(sql[j])) j--; | |
| 55 | + const name = sql.slice(j + 1, end + 1).toLowerCase(); | |
| 56 | + stack.push(name || "("); | |
| 57 | + // Count consecutive same-name frames in the stack | |
| 58 | + let same = 0; | |
| 59 | + for (let k = stack.length - 1; k >= 0; k--) { | |
| 60 | + if (stack[k] === stack[stack.length - 1]) same++; | |
| 61 | + else break; | |
| 62 | + } | |
| 63 | + if (name && (worst === null || same > worst.depth)) { | |
| 64 | + worst = { fn: name, depth: same, offset: i }; | |
| 65 | + } | |
| 66 | + i++; | |
| 67 | + continue; | |
| 68 | + } | |
| 69 | + if (ch === ")") { | |
| 70 | + stack.pop(); | |
| 71 | + i++; | |
| 72 | + continue; | |
| 73 | + } | |
| 74 | + i++; | |
| 75 | + } | |
| 76 | + return worst; | |
| 77 | +}; | |
| 78 | + | |
| 79 | +describe("drizzle migration SQL structural lint", () => { | |
| 80 | + const files = readdirSync(MIGRATIONS_FOLDER) | |
| 81 | + .filter((f) => f.endsWith(".sql")) | |
| 82 | + .sort(); | |
| 83 | + | |
| 84 | + for (const f of files) { | |
| 85 | + it(`${f} keeps nested-function depth under ${MAX_NESTING}`, () => { | |
| 86 | + const sql = readFileSync(join(MIGRATIONS_FOLDER, f), "utf-8"); | |
| 87 | + const worst = findDeepestNest(sql); | |
| 88 | + const summary = | |
| 89 | + worst === null | |
| 90 | + ? { ok: true as const } | |
| 91 | + : { | |
| 92 | + ok: worst.depth < MAX_NESTING, | |
| 93 | + file: f, | |
| 94 | + line: sql.slice(0, worst.offset).split("\n").length, | |
| 95 | + fn: worst.fn, | |
| 96 | + depth: worst.depth, | |
| 97 | + }; | |
| 98 | + // The expectation is `summary.ok === true`. The full `summary` object is | |
| 99 | + // matched (not just `.ok`) so the failure diff prints file/line/fn/depth | |
| 100 | + // — bun:sqlite's lemon parser stack overflows on the compiled macOS CLI | |
| 101 | + // binary around depth 40, and the project's test matrix is Linux-only, | |
| 102 | + // so the diff is the breadcrumb that tells you which migration to | |
| 103 | + // refactor (precompute into a temp table à la 0008's __slug_norm, or | |
| 104 | + // split the expression into multiple shallow steps). | |
| 105 | + expect(summary).toEqual({ ...summary, ok: true }); | |
| 106 | + }); | |
| 107 | + } | |
| 108 | +}); | |