Uh oh!
There was an error while loading. Please reload this page.
') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })();
There was an error while loading. Please reload this page.
Porting a real 800-action BigQuery Dataform project (acuantia) to Supabase produced a catalogue of BigQuery→PostgreSQL rewrites. Almost all of them are deterministic, and almost none are in
SQL_RULES. Every one is a rule the next customer will otherwise rediscover by hand.Fix first: SAFE_CAST is actively harmful
This silently strips the safety and leaves a note asking the user to verify. What it actually produces is a run that fails hours later, in a different file, with
invalid input syntax for type bigint: "0750069967 "— and the failing SQL is code the converter itself wrote. In acuantia the NULL-on-bad-input behaviour was load-bearing: the sources carry Excel error strings (#DIV/0!,#N/A), SAP identifiers with stray characters, and non-numeric HubSpot team ids.PostgreSQL 16 added
pg_input_is_valid(text, type), which asks exactly the question SAFE_CAST asks:Guard on the text form, cast x itself, so an already-numeric value converts normally. Rewrite to this rather than flagging — it is exact, not approximate. (One divergence to note in the docs: for a fractional numeric cast to an integer type, BigQuery rounds where this yields NULL.)
Rules to add as
kind: "rewrite"All deterministic, all verified against a real project and a live PostgreSQL:
SAFE_DIVIDE(a, b)a / nullif(b, 0)REGEXP_EXTRACT(x, p)substring(x from p)DATE_SUB/ADD(d, INTERVAL n u)(d -/+ interval 'n u')DATE_DIFF(a, b, DAY)(a::date - b::date)DATE_DIFF(a, b, HOUR)arr[OFFSET(n)]/[SAFE_OFFSET(n)]arr[n + 1]SPLIT(x, d)string_to_array(x, d)SPLIT(x, '')string_to_array(x, NULL)EXTRACT(DAYOFWEEK FROM x)(extract(dow from x) + 1)dow0-basedCOLLATE(x, '')/x COLLATE ''xCAST(… AS DATETIME)… as timestamp`ident`"ident"project.dataset.tableand interpolated tokensr'…''…'ras a type name# comment-- comment"literal"in value position'literal'GROUP BY ALLgroup by 1, 2, 5SELECT * EXCEPT (…)… NOT ENFORCEDTwo of these need more than lexical matching, and are worth it — they were the two largest classes in acuantia:
SELECT * EXCEPT(141 sites / 132 files) needs the star's relation resolved: a ref to a declaration givescolumnTypes; a ref to a project view resolves recursively; CTEs and subqueries resolve in-file; a qualified star binds through the FROM/JOIN chain. It must sweep to a fixpoint, since a star over a view is only knowable once that view names its own columns. 126 of 141 resolved automatically.Identifier casing — the extract creates columns with
quoteIdent(), so BigQuery's casing survives, while PostgreSQL folds unquoted identifiers to lowercase AND BigQuery matched case-insensitively. SoEmailmust be quoted,emailreferring to it must become"Email", and a bare quoted column in a select list should alias back to lowercase so the case-folding stops at the source boundary instead of propagating through the graph. ~700 references in acuantia. Needs a real parser, not regex — my regex version was bitten twice by aliases shadowing source column names.Keep as
kind: "flag"— these need intent, not syntaxSTRUCT(jsonb vs composite vs restructure depends on downstream),QUALIFY,FARM_FINGERPRINT(no equivalent; whether values must match BigQuery's is a business question),PARSE_DATE/FORMAT_DATE(format tokens are translatable but silently wrong-on-some-rows if mismatched),UNNEST. Their notes should point at a documented worked example rather than "consider jsonb".Two structural findings
The converter must also rewrite
includes/. Shared JS helpers emit SQL, and being template literals they are invisible to a.sqlxscan. In acuantia,split(x, d)[SAFE_OFFSET(n)]inside four helper functions failed two views on every single run while looking like an unfixed tail item. The file has aSQLANVIL-MIGRATEheader comment listing findings, so the converter knows they exist — it just cannot act on them.A
--reportoutput would carry more weight than any single rule. What made acuantia tractable was not knowing the rewrites; it was a classified inventory — every remaining construct grouped by class, with counts, file lists and a recommended treatment. That converts an unbounded slog into a finite list someone can work or descope. The information already exists in the findings pass; it just needs emitting as structured output rather than only as inline markers.