@lunora/sql-store 1.0.0-alpha.178 → 1.0.0-alpha.179
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/OCC_VERSION_COLUMN-ByC64Jgx.mjs +1 -0
- package/dist/packem_shared/{SEARCH_STATE_TABLE-CcO9w8T0.mjs → SEARCH_STATE_TABLE-DElP9QMz.mjs} +1 -1
- package/dist/packem_shared/backfillSqlSearchIndexes-CAtI2baI.mjs +1 -0
- package/dist/packem_shared/{createSqlCtxDb-CAYdeMaI.mjs → createSqlCtxDb-BZcAKgBB.mjs} +2 -2
- package/dist/packem_shared/ctx-db-search-C9wuVQA-.mjs +1 -0
- package/dist/packem_shared/{ctx-db-search-state-C3IGyBzm.mjs → ctx-db-search-state-BhAPGj25.mjs} +1 -1
- package/dist/packem_shared/decodeGlobalRow-CsaeCqGa.mjs +1 -0
- package/dist/packem_shared/{runSqlAggregateMigrations-CI_j5mbt.mjs → runSqlAggregateMigrations-vjt5RZB2.mjs} +1 -1
- package/dist/packem_shared/{runSqlGlobalTableMigrations-BpJNlH1x.mjs → runSqlGlobalTableMigrations-BgbvoKxI.mjs} +1 -1
- package/dist/packem_shared/sql-exec-BfJ_rWEB.mjs +1 -0
- package/package.json +2 -2
- package/dist/packem_shared/backfillSqlSearchIndexes-By4M4zhm.mjs +0 -1
- package/dist/packem_shared/ctx-db-search-Cc4WXyGR.mjs +0 -1
- package/dist/packem_shared/decodeGlobalRow-C8AG-YP1.mjs +0 -1
- package/dist/packem_shared/sql-exec-BmMqDIi8.mjs +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createSqlCtxDb as a,readSqlCdcChangedTables as o,readSqlCdcChanges as t,readSqlCdcFloor as l,runSqlCdcMigration as s,sweepSqlCdcRetention as n}from"./packem_shared/createSqlCtxDb-
|
|
1
|
+
import{createSqlCtxDb as a,readSqlCdcChangedTables as o,readSqlCdcChanges as t,readSqlCdcFloor as l,runSqlCdcMigration as s,sweepSqlCdcRetention as n}from"./packem_shared/createSqlCtxDb-BZcAKgBB.mjs";import{runSqlGlobalTableMigrations as i}from"./packem_shared/runSqlGlobalTableMigrations-BgbvoKxI.mjs";import{runSqlAggregateMigrations as c,runSqlRankMigrations as q}from"./packem_shared/runSqlAggregateMigrations-vjt5RZB2.mjs";import{d as f,r as m}from"./packem_shared/ctx-db-search-C9wuVQA-.mjs";import{S as x,m as p}from"./packem_shared/ctx-db-search-state-BhAPGj25.mjs";import{h,a as u,d as M,s as T,t as A}from"./packem_shared/value-codec-DPoUomF-.mjs";import{z as R}from"./packem_shared/sql-exec-BfJ_rWEB.mjs";export{x as SEARCH_STATE_TABLE,f as backfillSqlSearchIndexes,a as createSqlCtxDb,h as decodeBigint,R as decodeGlobalRow,u as effectiveColumnKind,p as migrateSearchState,o as readSqlCdcChangedTables,t as readSqlCdcChanges,l as readSqlCdcFloor,c as runSqlAggregateMigrations,s as runSqlCdcMigration,i as runSqlGlobalTableMigrations,q as runSqlRankMigrations,m as runSqlSearchMigrations,M as sqliteDecode,T as sqliteEncode,n as sweepSqlCdcRetention,A as tryJsonParse};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const o="_version";export{o as OCC_VERSION_COLUMN};
|
package/dist/packem_shared/{SEARCH_STATE_TABLE-CcO9w8T0.mjs → SEARCH_STATE_TABLE-DElP9QMz.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{S as t,a as S,m as c,r as l,b as i,w as s}from"./ctx-db-search-state-
|
|
1
|
+
import{S as t,a as S,m as c,r as l,b as i,w as s}from"./ctx-db-search-state-BhAPGj25.mjs";import"./sql-exec-BfJ_rWEB.mjs";export{t as SEARCH_STATE_TABLE,S as clearSearchBackfillState,c as migrateSearchState,l as readSearchBackfillState,i as readSearchIndexCoverage,s as writeSearchBackfillState};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./ctx-db-search-state-BhAPGj25.mjs";import{d as S,c as s,a as i,r as l}from"./ctx-db-search-C9wuVQA-.mjs";import"./sql-exec-BfJ_rWEB.mjs";export{S as backfillSqlSearchIndexes,s as createSearchSync,i as runSqlSearch,l as runSqlSearchMigrations};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{LunoraError as T}from"@lunora/errors";import{m as tn,D as nn}from"./ctx-db-search-state-
|
|
1
|
+
import{LunoraError as T}from"@lunora/errors";import{m as tn,D as nn}from"./ctx-db-search-state-BhAPGj25.mjs";import{c as on,r as rn,A as sn,C as an,R as cn,u as dn,a as ln,T as un,x as fn,b as wn}from"./ctx-db-search-C9wuVQA-.mjs";import{throwingScheduler as $n,describeRelationWrites as hn,CDC_LOG_TABLE as K,cdcForkedError as _n,cursorBelowRetainedFloor as En,cdcTrimmedError as pn,serverInList as yn,assertNoExplicitUndefined as Fe,hasTrigger as Rn,runRowValidators as We,assertFlatPredicate as at,mergeWhere as F,rankTableName as he,sortColumnName as pe,resolveRankPartition as ct,encodePartitionKey as Ce,resolveRankSeekTuple as Sn,RANK_TIEBREAK as ye,CountRlsUnsupportedError as dt,compileWhereSql as X,ConflictError as oe,patchDependsOnRow as Tn,normalizeIdStructurally as gn,assertValidClientId as vn,aggregateSqlFunction as _e,softDeleteScope as Le,renderSql as lt,resolveWith as ut,relationHooks as ft,applySelect as wt,encodeCursor as mn,NotFoundError as An,applyOnDelete as In,normalizeCountArgument as Cn,selectIndexForCount as Ln,encodeAggregateKey as Q,aggregateTableName as te,selectIndexForAggregate as bn,readAggregateValue as Ue,runTriggers as Mn,matchesRankStaticWhere as $t,nullsOrderSuffix as ht,nullsFirstOf as _t,rankPivotConditionSql as qt,CURSOR_PREFIX as Nn,resolvePatch as qn,stripReservedPatchFields as kn,assertPatchAllowed as Dn,resolveRelationPredicates as On,selectIndexForGroupBy as Bn,composeReadPredicate as Fn,fanOutScalarCounts as Wn,matchesStaticWhere as xe,foldAggregateTally as Et,coerceAggregateNumber as Pe,whereOfFilter as Un,isPushableWhere as xn,tiebreakDirectionFor as Pn,CDC_LOG_TABLE_SEQ_INDEX as Hn,NotUniqueError as Kn,WORKERD_SQLITE_LIMITS as jn}from"@lunora/shard-engine";import{sql as e,SQL as Gn}from"drizzle-orm";import{p as pt,m as yt,q as A,a as q,c as Vn,o as Yn,f as z,s as ne,b as x,h as Rt,t as kt,j as He,u as St,l as Tt,B as Ke,v as Me,n as Qe,e as gt,w as vt,x as mt,y as Xn}from"./sql-exec-BfJ_rWEB.mjs";import{z as Xi}from"./sql-exec-BfJ_rWEB.mjs";import{f as Dt,d as Ot,n as Bt,g as Ft,a as Wt}from"./value-codec-DPoUomF-.mjs";import{runSqlGlobalTableMigrations as Qn}from"./runSqlGlobalTableMigrations-BgbvoKxI.mjs";import{runSqlAggregateMigrations as zn,runSqlRankMigrations as Jn}from"./runSqlAggregateMigrations-vjt5RZB2.mjs";import{OCC_VERSION_COLUMN as Ee}from"./OCC_VERSION_COLUMN-ByC64Jgx.mjs";const Zn=(s,c)=>{if(s.size<c)return;const $=s.keys().next().value;$!==void 0&&s.delete($)},At=50,ei=(s,c={})=>{const $=c.maxBatch??At,o=Number.isInteger($)&&$>0?$:At,R=new Map;let f=!1;const d=async(g,m)=>{const C=[...m.keys()];for(let L=0;L<C.length;L+=o){const b=C.slice(L,L+o);try{const B=await s(g,b);for(const V of b){const Y=B.get(V);for(const J of m.get(V)??[])J.resolve(Y)}}catch(B){for(const V of b)for(const Y of m.get(V)??[])Y.reject(B)}}},N=()=>{f=!1;const g=[...R.entries()];R.clear();for(const[m,C]of g)d(m,C).catch(()=>{})};return{async load(g,m){return new Promise((C,L)=>{let b=R.get(g);b||(b=new Map,R.set(g,b));const B=b.get(m);B?B.push({reject:L,resolve:C}):b.set(m,[{reject:L,resolve:C}]),f||(f=!0,queueMicrotask(N))})}}},ti=new Set(["_id","id"]),ni=s=>{throw new T("INTERNAL",`no ORDER BY NULL placement for dialect "${String(s)}"`)},Ut=(s,c)=>{const $=c.direction==="desc"?"DESC":"ASC",o=c.nullable===!0,R=f=>e`${Me(s,c.field)} ${e.raw(`${$}${f}`)}`;switch(s.name){case"mysql":{const f=R("");return!o||c.nulls===void 0?[f]:[e`(${Me(s,c.field)} IS NULL) ${e.raw(c.nulls==="first"?"DESC":"ASC")}`,f]}case"postgres":return[R(o?ht(_t(c)):"")];case"sqlite":return[R(o&&c.nulls!==void 0?ht(_t(c)):"")];default:return ni(s.name)}},ii=(s,c)=>{const $=s.flatMap(o=>Ut(c,o));if(!s.some(o=>ti.has(o.field))){const o=Pn(s);$.push(e`${x("id")} ${e.raw(o==="desc"?"DESC":"ASC")}`)}return e.join($,e`, `)},It=50,oi=(s,c,$)=>{const o={...c};for(const[R,f]of kt(s)){if(f.serverDefault){o[R]=f.serverDefault({auth:$});continue}o[R]===void 0&&(f.defaultFn?o[R]=f.defaultFn():"defaultValue"in f&&(o[R]=f.defaultValue))}return o},ri=s=>{const c=s.detail??s["QUERY PLAN"];return typeof c=="string"?c:Object.values(s).map(String).join(" | ")},je=(s,c,$,o)=>{for(const[R,f]of kt(s)){if(f.serverDefault){R in c&&($[R]=f.serverDefault({auth:o}));continue}f.onUpdateFn&&!(R in c)&&($[R]=f.onUpdateFn())}},si=128,ai=()=>{const s=new Map;return{delete:c=>{s.delete(c)},get:c=>{const $=s.get(c);if($!==void 0)return s.delete(c),s.set(c,$),$},set:(c,$)=>{s.has(c)?s.delete(c):Zn(s,si),s.set(c,$)}}},ci=async(s,c,$,o,R)=>{const f=R.get(o);if(f!==void 0)return f;const d=Object.entries($.tables).filter(([,g])=>g.shardMode===void 0||g.shardMode.kind==="global").map(([g])=>g),N=await Promise.all(d.map(async g=>({found:(await A(s,c,e`SELECT 1 FROM ${e.identifier(g)} WHERE ${e.identifier("id")} = ${o} LIMIT 1`)).length>0,tableName:g})));for(const g of N)if(g.found)return R.set(o,g.tableName),g.tableName},re=s=>s==null?null:Number(s),di=(s,c,$)=>$.map(o=>{const R={};for(const f of c){const d=s.shape[f];R[f]=Ot(o[f]??null,d&&Wt(d))}return{key:R,value:re(o.value)}}),li=(s,c,$)=>[...s.partitionBy??[],...s.sortBy.map(R=>R.field),...s.where?Object.keys(s.where):[]].every(R=>vt(c,R)===vt($,R)),xt=s=>s.length===1?s[0]:e`(${e.join(s,e` AND `)})`,ie=s=>e.join(s.map(c=>e`${e.identifier(c)}`),e`, `),se=s=>e.join(s.map(c=>e`${c}`),e`, `),be=(s,c)=>{if(s==="postgres"){for(const[$,o]of Object.entries(c))if(typeof o=="string"&&o.includes("\0"))throw new T("BAD_REQUEST",`"${$}" holds a NUL character (U+0000), which a Postgres text column cannot store`)}},Ne=s=>s instanceof ArrayBuffer?new Uint8Array(s):Array.isArray(s)?Uint8Array.from(s):s,ui=(s,c,$,o,R)=>{const f=[];for(let d=0;d<$.length+1;d+=1){const N=$[d],g=c.sortBy[d],m=d<$.length&&N!==void 0&&g!==void 0,C=g?.direction==="desc"?"desc":"asc",L=m?qt(N,Ne(o[N]),C,!1):e`${e.identifier(ye)} < ${R}`;if(L===void 0)continue;const b=$.slice(0,d).map(B=>Qe(s,e`${e.identifier(B)}`,Ne(o[B])));b.push(L),f.push(xt(b))}return f.length>0?e.join(f,e` OR `):e`1 = 0`},fi=(s,c,$)=>{if($.length!==c.length)return;const o=[];for(const[R,f]of c.entries()){const d=qt(f.column,Ne($[R]),f.direction,!0);if(d===void 0)continue;const N=[];for(let g=0;g<R;g+=1){const m=c[g];m!==void 0&&N.push(Qe(s,e`${e.identifier(m.column)}`,Ne($[g])))}N.push(d),o.push(xt(N))}return o.length===0?e`(1 = 0)`:e`(${e.join(o,e` OR `)})`},wi=(s,c)=>{if(s.sortBy.length===0)throw new T("INTERNAL",`rankIndex "${s.name}" requires at least one "sortBy" column for stable pagination`);const $=[{column:"__partition__",direction:"asc",nullable:!1}];for(const[o,R]of s.sortBy.entries())$.push({column:c[o]??pe(o),direction:R.direction,nullable:!0});return $.push({column:ye,direction:"asc",nullable:!1}),$},$i=async(s,c,$,o,R)=>{const d=[];for(let C=0;C<R.length;C+=50)d.push(R.slice(C,C+50));const N=await Promise.all(d.map(async C=>A(s,c,e`SELECT * FROM ${e.identifier(o)} WHERE ${e.identifier("id")} IN (${se(C)})`))),g=new Map;for(const C of N)for(const L of C)g.set(L.id,L);const m=[];for(const C of R){const L=z($,g.get(C));L&&m.push(L)}return m},hi=s=>{const c=s.map(f=>Ot(f,"bytes")),$=JSON.stringify(Bt(c)?Ft(c):c),o=new TextEncoder().encode($);let R="";for(const f of o)R+=String.fromCodePoint(f);return Nn+btoa(R)},Pt=s=>{if(s===void 0)return!1;const c=Wt(s);return c==="any"||c==="bigint"||c==="from"||c==="union"},Ye=(s,c,$)=>{if(Pt(s.shape[c]))throw new T("BAD_REQUEST",`${$}: "${c}" may hold an order-preserving key rather than a value SQL can reduce or group — declare an aggregateIndex covering this (by, field, op) so the maintained companion answers it instead (its running total is a REAL, so it stays exact only while the total is inside 2^53)`)},_i=(s,c,$,o)=>{for(const R of $)Ye(s,R,`groupBy(${c}, { by: [..."${R}"] })`);o.field!==void 0&&Ye(s,o.field,`groupBy(${c}, { agg: { op: "${o.op}", field: "${o.field}" } })`)},Xe="__cdc_sweep",Ht="global",Ei=6e4,pi=1e4,yi=3e4;let Ct=0;const Ri=async(s,c)=>{const{autoincrementPrimaryKey:$,key:o,real:R,text:f}=c.companionTypes;await q(s,c,e`CREATE TABLE IF NOT EXISTS ${e.identifier(K)} (${e.identifier("seq")} ${e.raw($)}, ${e.identifier("ts")} ${e.raw(R)} NOT NULL, ${e.identifier("table")} ${e.raw(o)} NOT NULL, ${e.identifier("id")} ${e.raw(o)} NOT NULL, ${e.identifier("op")} ${e.raw(o)} NOT NULL, ${e.identifier("doc")} ${e.raw(f)})`);const d=c.indexKeyPrefix?.("string");await Vn(s,c,{columns:e`${d===void 0?e`${e.identifier("table")}`:e`${e.identifier("table")}(${e.raw(String(d))})`}, ${e.identifier("seq")}`,name:Hn,table:K,unique:!1}),await q(s,c,e`CREATE TABLE IF NOT EXISTS ${e.identifier(Xe)} (${e.identifier("id")} ${e.raw(o)} NOT NULL PRIMARY KEY, ${e.identifier("lease_until")} ${e.raw(R)} NOT NULL)`),await q(s,c,e`INSERT INTO ${e.identifier(Xe)} (${e.identifier("id")}, ${e.identifier("lease_until")}) VALUES (${Ht}, ${0}) ${c.name==="mysql"?e`ON DUPLICATE KEY UPDATE ${e.identifier("id")} = ${e.identifier("id")}`:e`ON CONFLICT(${e.identifier("id")}) DO NOTHING`}`)},Si=async(s,c,$)=>{const o=e`UPDATE ${e.identifier(Xe)} SET ${e.identifier("lease_until")} = ${$+Ei} WHERE ${e.identifier("id")} = ${Ht} AND ${e.identifier("lease_until")} <= ${$}`;if(c.supportsReturning)return(await A(s,c,e`${o} RETURNING ${e.identifier("id")}`)).length>0;const R=await q(s,c,o);return(c.affectedRows?c.affectedRows(R??{rowsAffected:0}):0)>0},Ti=async(s,c,$,o)=>{if(!await Si(s,c,o))return;const R=o-$;await q(s,c,e`
|
|
2
2
|
DELETE FROM ${e.identifier(K)} WHERE ${e.identifier("seq")} IN (
|
|
3
3
|
SELECT ${e.identifier("seq")} FROM (
|
|
4
4
|
SELECT ${e.identifier("seq")} FROM ${e.identifier(K)} WHERE ${e.identifier("ts")} <= ${R} ORDER BY ${e.identifier("seq")} ASC LIMIT ${e.raw(String(pi))}
|
|
5
5
|
) AS ${e.identifier("expired")}
|
|
6
6
|
)
|
|
7
|
-
`)},Kt=async(s,c)=>{const $=await A(s,c,e`SELECT MIN(${e.identifier("seq")}) AS ${e.identifier("seq")} FROM ${e.identifier(K)}`),o=Number($[0]?.seq??Number.NaN);return Number.isFinite(o)?o:void 0},gi=async(s,c)=>{if(c.name!=="sqlite")return;const $=await A(s,c,e`SELECT ${e.identifier("seq")} AS ${e.identifier("seq")} FROM ${e.identifier("sqlite_sequence")} WHERE ${e.identifier("name")} = ${K}`),o=Number($[0]?.seq??Number.NaN);return Number.isFinite(o)?o:0},vi=s=>JSON.stringify(Bt(s)?Ft(s):s),mi=async(s,c,$,o,R,f,d)=>{await q(s,d,e`INSERT INTO ${e.identifier(K)} (${e.identifier("ts")}, ${e.identifier("table")}, ${e.identifier("id")}, ${e.identifier("op")}, ${e.identifier("doc")}) VALUES (${c}, ${$}, ${o}, ${R}, ${f===void 0?null:vi(f)})`)},Ki=async(s,c,$)=>{const o=c.sinceSeq??0,R=Math.max(1,Math.min(c.limit??1e3,1e4)),f=await Kt(s,$),d=await gi(s,$);if(d!==void 0&&o>d)throw _n(d,o,"global");if(f!==void 0&&En(f,o))throw pn(f,o,"global");const g=(await A(s,$,e`SELECT seq, ts, ${e.identifier("table")}, id, op, doc FROM ${e.identifier(K)} WHERE seq > ${o} ORDER BY seq ASC LIMIT ${e.raw(String(R))}`)).map(m=>{const{doc:C}=m,L={id:String(m.id),op:String(m.op),seq:Number(m.seq),table:String(m.table),ts:Number(m.ts)};return typeof C=="string"?{...L,doc:Dt(JSON.parse(C))}:L});return{changes:g,cursor:g.at(-1)?.seq??o}},Ai=1e4,Ii=1e3,Lt=(s,c)=>{const $=e.identifier(K),o=e`(SELECT MIN(v.seq) FROM ${$} v WHERE v.seq > ${s} AND v.seq - 1 > ${s} AND v.ts > ${c} AND NOT EXISTS (SELECT 1 FROM ${$} p WHERE p.seq = v.seq - 1))`;return e`${o} AS ${e.identifier("gap")}, (SELECT MAX(q.seq) FROM ${$} q WHERE q.seq > ${s} AND q.seq < ${o}) AS ${e.identifier("below")}`},bt=(s,c,$)=>{const o=Number(c?.gap??Number.NaN);if(!Number.isFinite(o))return s;const R=Number(c?.below??Number.NaN);return Math.min(s,Number.isFinite(R)?R:$)},Ci=async(s,c,$,o={})=>{const R=e.identifier(K),f=$.name!=="sqlite",d=(o.now??Date.now())-Ai;if(o.cursorOnly){const L=e`GREATEST((SELECT MAX(seq) FROM ${R}) - ${e.raw(String(Ii))}, ${c})`,b=await A(s,$,e`SELECT MAX(seq) AS seq${f?e`, ${Lt(L,d)}`:e``} FROM ${R}`),B=Number(b[0]?.seq??c);return{cursor:bt(Number.isFinite(B)?B:c,b[0],c),tables:[]}}const N=await A(s,$,e`SELECT ${e.identifier("table")} AS ${e.identifier("table")}, MAX(seq) AS seq${f?e`, ${Lt(e`${c}`,d)}`:e``} FROM ${R} WHERE seq > ${c} GROUP BY ${e.identifier("table")}`);let g=c;const m=[];for(const L of N){const b=Number(L.seq);Number.isFinite(b)&&b>g&&(g=b),m.push(String(L.table))}g=bt(g,N[0],c);const C=o.retained===!0?await Kt(s,$):void 0;return{cursor:g,tables:m,...C===void 0?{}:{floor:C}}},Li=/string or blob too big/iu,bi=/row is too big/iu,Mi=(s,c)=>{const{code:$,errno:o}=c,R=c instanceof Error?c.message:"";switch(s.name){case"mysql":return o===1118||$==="ER_TOO_BIG_ROWSIZE"?"InnoDB's per-row ceiling — roughly 8 KB, half a 16 KB page, for the part of the row stored inline":void 0;case"postgres":return bi.test(R)?"the 8 KB heap page a tuple must fit once its wide columns have been TOASTed out":void 0;default:return Li.test(R)?"the storage engine's per-row ceiling (2 MB on D1)":void 0}},Ni=(s,c,$)=>{const o=Mi(s,c);if(o!==void 0)throw new T("PAYLOAD_TOO_LARGE",`document is too large to store in "${$}": a single row cannot exceed ${o}. The limit is on the STORED bytes, which are UTF-8. Keep the payload in R2 (ctx.storage) and store a reference on the row.`)},Ge=16,Mt="__lunora_patch_if_match__",Nt=(s,c,$)=>{throw s.isUniqueViolation(c)?new oe(`unique constraint violation on "${$}"`,"unique"):(Ni(s,c,$),c)},Ve=new WeakMap,qi=s=>{const c=yn(s);return($,o,R,f)=>o.some(d=>d instanceof Gn)?Yn(s,$,o,R):c($,o,R,f)},ji=s=>{const{crossShardCounter:c,crossShardReader:$,exec:o,maxRelationKeys:R,schema:f}=s,{dialect:d}=s,N={fieldRef:t=>Me(d,t),rangeTypeGuard:(t,n)=>Xn(d,t,n),...d.name==="mysql"?{containsExpr:(t,n)=>{const i=pt(t);return i===void 0?e`LOCATE(${n}, ${t}) > 0`:e`LOCATE(${yt("mysql",n)}, ${i}) > 0`}}:{},...d.name==="postgres"?{containsExpr:(t,n)=>{const i=pt(t);return i===void 0?e`strpos(${t}, ${n}) > 0`:e`strpos(${i}, ${yt("postgres",n)}) > 0`}}:{},...d.name==="sqlite"?{}:{inList:qi(d.name)}},g=new WeakMap,m=t=>{const n=g.get(t);if(n!==void 0)return n;const i={...N,serialize:(a,r)=>mt(d,r,a,l=>ne(t,r,l))};return g.set(t,i),i},C=(t,n)=>Qe(d.name,t,n),L=t=>{const n=ie(t.columns),i=se(t.values),a=h=>d.name==="mysql"?e`VALUES(${e.identifier(h)})`:e`excluded.${e.identifier(h)}`,r=h=>d.name==="postgres"?e`${e.identifier(t.table)}.${e.identifier(h)}`:e`${e.identifier(h)}`,l=e.join(Object.entries(t.set(a,r)).map(([h,E])=>e`${e.identifier(h)} = ${E}`),e`, `),_=d.name==="mysql"?e`ON DUPLICATE KEY UPDATE ${l}`:e`ON CONFLICT(${e.identifier(t.conflictKey)}) DO UPDATE SET ${l}`;return e`INSERT INTO ${e.identifier(t.table)} (${n}) VALUES (${i}) ${_}`},b=s.clock??(()=>Date.now()),B=s.idGenerator??(()=>crypto.randomUUID()),V=s.cdc??!1,Y=typeof s.cdcRetentionMs=="number"&&Number.isFinite(s.cdcRetentionMs)&&s.cdcRetentionMs>0?s.cdcRetentionMs:void 0,J=s.auth??{identity:null,userId:null},ae=async(t,n,i,a)=>{if(!V||(await mi(o,b(),t,n,i,a,d),Y===void 0))return;const r=b();if(!(r-Ct<yi)){Ct=r;try{await Ti(o,d,Y,r)}catch{}}},jt=s.scheduler??$n,qe=ai();let Re=0;const ke=s.provisionScope??{},W=async()=>{const t=Ve.get(ke);if(t)return t;const n=(async()=>{await Qn(o,f,d),await zn(o,f,d),await Jn(o,f,d),await tn(o,d),await rn(o,f,d),V&&await Ri(o,d)})().catch(i=>{throw Ve.delete(ke),i});return Ve.set(ke,n),n},ce=async(t,n)=>{await W();const i=await ci(o,d,f,t,qe);if(!(n!==void 0&&i!==n))return i},de=new Map,ze=async(t,n)=>{const i=te(t,n);return(await A(o,d,d.tableExists(i))).length>0},Se=async(t,n)=>{const i=`${t}::${n.name}`,a=de.get(i);if(a!==void 0)return a;if(!await ze(t,n.name))return de.set(i,!1),!1;const l=f.tables[t];if(!l)return de.set(i,!1),!1;const _=n.by??[],h=new Map;await Tt(o,d,l,t,p=>{if(n.where&&!xe(p,n.where))return;const w=Q(_,p);Et(h,w,n,p)});const E=te(t,n.name);await q(o,d,e`DELETE FROM ${e.identifier(E)}`);const u=[];for(const[p,w]of h)u.push(e`INSERT INTO ${e.identifier(E)} (${e.identifier("__key__")}, ${e.identifier("__value__")}, ${e.identifier("__count__")}) VALUES (${p}, ${w.value}, ${w.count})`);return await gt(o,d,u),de.set(i,!0),!0},Gt=async(t,n,i,a)=>{const r=new Map;let l,_=!0;for(;_;){const h=l===void 0?a:[...a,e`${e.identifier("id")} > ${l}`],E=h.length>0?e` WHERE ${e.join(h,e` AND `)}`:e``,u=await A(o,d,e`SELECT ${e.identifier("id")}, ${x(i.field??"")} FROM ${e.identifier(n)}${E} ORDER BY ${e.identifier("id")} ASC LIMIT ${e.raw(String(Ke))}`);for(const p of Rt(t,u))Et(r,"",i,p);l=u.at(-1)?.id,_=u.length===Ke}return r.get("")?.value??null},Vt=async(t,n,i)=>{const a=n.field??"",r=[],l=f.tables[t],_=(p,w)=>mt(d,p,w,y=>l?ne(l,p,y):He(y));for(const p of n.by??[]){const w=_(p,i[p]??null);r.push(w===null?e`${x(p)} IS NULL`:e`${x(p)} = ${w}`)}for(const[p,w]of Object.entries(n.where??{})){const y=w!==null&&typeof w=="object"&&!Array.isArray(w)?w.eq:w,S=_(p,y),v=Me(d,p);r.push(S===null?e`${v} IS NULL`:e`${v} = ${S}`)}const h=r.length>0?e` WHERE ${e.join(r,e` AND `)}`:e``;if(l&&Pt(l.shape[a]))return Gt(l,t,n,r);const E=_e(n.op),u=await A(o,d,e`SELECT ${e.raw(E)}(${x(a)}) AS ${e.identifier("value")} FROM ${e.identifier(t)}${h}`);return re(u[0]?.value)},Yt=async(t,n)=>{await q(o,d,e`DELETE FROM ${e.identifier(t)} WHERE ${e.identifier("__key__")} = ${n} AND ${e.identifier("__count__")} <= 0`)},Xt=async(t,n,i,a)=>{const r=te(t,n.name),{op:l}=n,_=n.field??"",h=i&&(!n.where||xe(i,n.where))?i:void 0,E=a&&(!n.where||xe(a,n.where))?a:void 0;if(!(!h&&!E)){if(l==="count"||l==="sum"||l==="avg"){const u=new Set;for(const[p,w]of[[h,-1],[E,1]]){if(!p)continue;const y=l==="count"?1:Pe(p[_]);if(y===void 0)continue;const S=Q(n.by??[],p);u.add(S),await q(o,d,L({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(v,I)=>({__count__:e`${I("__count__")} + ${v("__count__")}`,__value__:l==="count"?e`${I("__value__")} + ${v("__value__")}`:e`COALESCE(${I("__value__")}, 0) + ${v("__value__")}`}),table:r,values:[S,w*y,w]}))}for(const p of u)await Yt(r,p);return}if(h){const u=Q(n.by??[],h),p=Pe(h[_]),y=(await A(o,d,e`SELECT ${e.identifier("__value__")} AS ${e.identifier("value")}, ${e.identifier("__count__")} AS ${e.identifier("count")} FROM ${e.identifier(r)} WHERE ${e.identifier("__key__")} = ${u}`))[0],S=re(y?.value),v=(y?.count??0)-1;if(v<=0)await q(o,d,e`DELETE FROM ${e.identifier(r)} WHERE ${e.identifier("__key__")} = ${u}`);else if(y&&p!==void 0&&S!==null&&p===S){const I=await Vt(t,n,h);await q(o,d,e`UPDATE ${e.identifier(r)} SET ${e.identifier("__value__")} = ${I}, ${e.identifier("__count__")} = ${v} WHERE ${e.identifier("__key__")} = ${u}`)}else await q(o,d,e`UPDATE ${e.identifier(r)} SET ${e.identifier("__count__")} = ${e.identifier("__count__")} - 1 WHERE ${e.identifier("__key__")} = ${u}`)}if(E){const u=Q(n.by??[],E),p=Pe(E[_]);if(p===void 0)await q(o,d,L({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(w,y)=>({__count__:e`${y("__count__")} + 1`}),table:r,values:[u,null,1]}));else{const w=l==="min"?"MIN":"MAX";await q(o,d,L({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(y,S)=>({__count__:e`${S("__count__")} + 1`,__value__:e`${e.raw(w)}(COALESCE(${S("__value__")}, ${y("__value__")}), ${y("__value__")})`}),table:r,values:[u,p,1]}))}}}},Te=async t=>{const n=f.tables[t]?.aggregateIndexes;if(!(!n||n.length===0))for(const i of n)await Se(t,i)},le=async(t,n,i)=>{const a=f.tables[t]?.aggregateIndexes;if(!(!a||a.length===0))for(const r of a){const l=`${t}::${r.name}`;(de.get(l)??await ze(t,r.name))&&await Xt(t,r,n,i)}},ue=new Map,Je=async(t,n)=>{const i=he(t,n);return(await A(o,d,d.tableExists(i))).length>0},De=async(t,n)=>{const i=`${t}::rank::${n.name}`,a=ue.get(i);if(a!==void 0)return a;if(!await Je(t,n.name))return ue.set(i,!1),!1;const l=f.tables[t];if(!l)return ue.set(i,!1),!1;const _=he(t,n.name);await q(o,d,e`DELETE FROM ${e.identifier(_)}`);const h=n.sortBy.map((w,y)=>pe(y)),E=ie(["__id__","__partition__",...h]);let u=[];const p=async()=>{if(u.length===0)return;const w=u;u=[],await gt(o,d,w)};return await Tt(o,d,l,t,async w=>{if(n.where&&!$t(w,n.where))return;const y=Ce(n.partitionBy??[],w),S=n.sortBy.map(v=>He(w[v.field]??null));u.push(e`INSERT INTO ${e.identifier(_)} (${E}) VALUES (${se([w._id,y,...S])})`),u.length>=Ke&&await p()}),await p(),ue.set(i,!0),!0},ge=async t=>{const n=f.tables[t]?.rankIndexes;if(!(!n||n.length===0))for(const i of n)await De(t,i)},Z=async(t,n,i,a)=>{const r=f.tables[t],l=r?.rankIndexes;if(!l||l.length===0)return;const _=r?.softDeleteMode?.field,h=_===void 0||a===void 0?void 0:a[_],E=h!=null;for(const u of l){if(i!==void 0&&a!==void 0&&li(u,i,a))continue;const p=`${t}::rank::${u.name}`;if(!(ue.get(p)??await Je(t,u.name)))continue;const S=he(t,u.name);if(i&&await q(o,d,e`DELETE FROM ${e.identifier(S)} WHERE ${e.identifier("__id__")} = ${n}`),a&&!E){if(u.where&&!$t(a,u.where))continue;const v=u.sortBy.map((D,U)=>pe(U)),I=ie(["__id__","__partition__",...v]),M=Ce(u.partitionBy??[],a),k=u.sortBy.map(D=>He(a[D.field]??null));await q(o,d,e`INSERT INTO ${e.identifier(S)} (${I}) VALUES (${se([n,M,...k])})`)}}},fe=on({dialect:d,exec:o,schema:f}),Ze=new Set;for(const[t,n]of Object.entries(f.tables))for(const i of Object.values(n.triggerMap??{}))Ze.add(`${t} ${i.timing} ${i.op}`);const j=(t,n,i)=>Ze.has(`${t} ${n} ${i}`);let et;const G=async(t,n,i)=>{if(Re+=1,Re>It)throw Re-=1,new oe(`trigger recursion exceeded ${String(It)} levels on "${i.table}" — check for a self-triggering write`,"trigger");try{await Mn({ctx:et,event:i,op:n,schema:f,tableName:i.table,timing:t})}finally{Re-=1}},Qt=async(t,n)=>{try{await q(o,d,n)}catch(i){Nt(d,i,t)}},ve=async(t,n)=>(await A(o,d,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} = ${n}`))[0],tt=async(t,n,i,a,r)=>{const l=e`${e.identifier(Ee)}`,_=e.join([C(e`${e.identifier("id")}`,a.id),C(l,a[Ee]??null),...r===void 0?[]:[e`(${r})`]],e` AND `),h=n==="UPDATE"?e`UPDATE ${e.identifier(t)} SET ${i}, ${l} = ${St.sql(l)} WHERE ${_}`:e`DELETE FROM ${e.identifier(t)} WHERE ${_}`;try{if(d.supportsReturning)return(await A(o,d,e`${h} RETURNING ${e.identifier("id")}`)).length>0;const E=await q(o,d,h);return(d.affectedRows?d.affectedRows(E??{rowsAffected:0}):0)>0}catch(E){return Nt(d,E,t)}},Oe=async(t,n,i,a)=>{if(a!==void 0&&!await tt(t,n,i,a))throw new oe(`optimistic concurrency conflict on "${t}" — the row changed during this mutation; refetch and retry`,"occ")},Be=(t,n=t?._creationTime)=>({_creationTime:n,[Ee]:St.value(t?.[Ee])}),nt=async(t,n,i,a,r,l,_)=>{const h=z(n,r);if(!h||r===void 0)throw new T("INTERNAL",`document not found: ${i}`);const E=qn(n,a,h),u={...h,...kn(E),_id:i};je(n,E,u,J),Dn(_,h,u),We(n,u,!0),j(t,"before","update")&&await G("before","update",{doc:{...u},id:i,op:"update",previous:h,table:t}),await Te(t),await ge(t);const p=Object.keys(n.shape),w=e.join(p.map(y=>e`${e.identifier(y)} = ${ne(n,y,u[y]??null)}`),e`, `);if(await tt(t,"UPDATE",w,r,l))return await le(t,h,u),await Z(t,i,h,u),await fe(t,i,{document:u,previous:h,written:Be(r)}),await ae(t,i,"update",u),j(t,"after","update")&&await G("after","update",{doc:u,id:i,op:"update",previous:h,table:t}),u},zt=(t,n,i,a)=>{const r=Object.keys(t.shape);return{columns:["id","_creationTime",...r],values:[n,i,...r.map(l=>ne(t,l,a[l]??null))]}},Jt=async(t,n,i,a)=>{const r=Bn(n,i.op,i.field,a.by,a.where);if(!r||!await Se(t,r.index))return;const _=te(t,r.index.name),h=Object.keys(r.partial);if(h.length===(r.index.by??[]).length&&h.length>0){const u=Q(r.index.by??[],r.partial),p=await A(o,d,e`SELECT ${e.identifier("__value__")} AS ${e.identifier("value")}, ${e.identifier("__count__")} AS ${e.identifier("count")} FROM ${e.identifier(_)} WHERE ${e.identifier("__key__")} = ${u}`);if(p.length===0)return[];const w=p[0];return[{key:{...r.partial},value:Ue(i.op,{count:w.count,value:re(w.value)})}]}return h.length>0?void 0:(await A(o,d,e`SELECT ${e.identifier("__key__")} AS ${e.identifier("key")}, ${e.identifier("__value__")} AS ${e.identifier("value")}, ${e.identifier("__count__")} AS ${e.identifier("count")} FROM ${e.identifier(_)}`)).map(u=>{const p=u;return{key:Dt(JSON.parse(p.key)),value:Ue(i.op,{count:p.count,value:re(p.value)})}})},it=t=>{const n=f.tables[t]?.shardMode?.kind;return n==="shardBy"||n==="root"},ot=t=>{throw new T("INTERNAL",`cross-backend relation: a global table cannot load the shard-local relation '${t}' (it spans every shard) — wire a cross-shard reader to support it`)},Zt=(t,n)=>{if(n?.relationMask!==void 0&&n.with!==void 0&&Object.keys(n.with).length>0)throw new T("MASK_UNSUPPORTED",`masking cannot follow a nested \`with\` across the cross-shard relation hop to "${t}" — the nested rows are hydrated on the serving shard, where the mask policy does not exist. Read the nested relation at its own (masked) call site instead.`);const i={};if(n?.relationBaseWhere)for(const a of Object.keys(f.tables)){const r=n.relationBaseWhere(a);r!==void 0&&(i[a]=r)}return{orderBy:n?.orderBy,relationPolicies:i,where:F(n?.baseWhere,n?.where),with:n?.with}},me=(t,n)=>it(t)?$?$(t,Zt(t,n)):ot(t):P.findMany(t,n),Ae=(t,n,i)=>On(t,{fetcher:me,maxRelationKeys:R,relationBaseWhere:i,schema:f,tableName:n}),en=ei(async(t,n)=>{const i=await A(o,d,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} IN (${se(n)})`),a=new Map;for(const r of i){const{id:l}=r;typeof l=="string"&&a.set(l,r)}return a}),rt=async(t,n,i)=>{const{fetchLimit:a,limit:r,orderKeys:l,predicate:_}=await Fn(n,i,{fetcher:me,maxRelationKeys:R,schema:f,tableName:t}),h=X(_,m(n)),E=ii(l,d);let u=e`SELECT * FROM ${e.identifier(t)}`;return h&&(u=e`${u} WHERE ${h}`),u=e`${u} ORDER BY ${E}`,a!==void 0&&(u=e`${u} LIMIT ${e.raw(String(a))}`),{limit:r,orderKeys:l,query:u}},P={relationWrites:hn(f),async cdcChangedTables(t,n){if(V)try{return await W(),await Ci(o,t,d,{...n,now:b(),retained:Y!==void 0})}catch{return}},async aggregate(t,n){const i=f.tables[t];if(!i)throw new T("INTERNAL",`unknown table: ${t}`);if(await W(),_e(n.op),n.op==="count")return P.count(t,{baseWhere:n.baseWhere,relationBaseWhere:n.relationBaseWhere,restrictsCounts:n.restrictsCounts,where:n.where});if(!n.field)throw new T("INTERNAL",`aggregate(${t}, { op: "${n.op}" }): "field" is required for non-count reducers`);const a=Le(i.softDeleteMode,void 0),r=F(F(n.baseWhere,n.where),a),l=await Ae(r,t,n.relationBaseWhere),_=l!==r;if(i.aggregateIndexes&&!n.baseWhere&&!_&&!a){const y=bn(i.aggregateIndexes,n.op,n.field,n.where);if(y&&await Se(t,y.index)){const v=Q(y.index.by??[],y.key),I=te(t,y.index.name),k=(await A(o,d,e`SELECT ${e.identifier("__value__")} AS ${e.identifier("value")}, ${e.identifier("__count__")} AS ${e.identifier("count")} FROM ${e.identifier(I)} WHERE ${e.identifier("__key__")} = ${v}`))[0];return Ue(n.op,k===void 0?void 0:{count:k.count,value:re(k.value)})}}Ye(i,n.field,`aggregate(${t}, { op: "${n.op}", field: "${n.field}" })`);const h=X(l,m(i)),E=e.raw(_e(n.op)),u=e`SELECT ${E}(${x(n.field)}) AS ${e.identifier("value")} FROM ${e.identifier(t)}`,w=(await A(o,d,h?e`${u} WHERE ${h}`:u))[0]?.value;return w==null?null:Number(w)},async count(t,n){const i=f.tables[t];if(!i)throw new T("INTERNAL",`unknown table: ${t}`);await W();const a=Cn(n);if(a.restrictsCounts)throw new dt(t);const r=Le(i.softDeleteMode,void 0),l=F(F(a.baseWhere,a.where),r),_=await Ae(l,t,a.relationBaseWhere),h=_!==l;if(i.aggregateIndexes&&!a.baseWhere&&!h&&!r){const w=Ln(i.aggregateIndexes,a.where);if(w&&await Se(t,w.index)){const S=Q(w.index.by??[],w.key),v=te(t,w.index.name),I=await A(o,d,e`SELECT ${e.identifier("__value__")} AS ${e.identifier("value")} FROM ${e.identifier(v)} WHERE ${e.identifier("__key__")} = ${S}`);return Number(I[0]?.value??0)}}const E=X(_,m(i)),u=e`SELECT COUNT(*) AS ${e.identifier("count")} FROM ${e.identifier(t)}`,p=await A(o,d,E?e`${u} WHERE ${E}`:u);return Number(p[0]?.count??0)},async delete(t,n,i){const a=await ce(t,n);if(!a)return;const r=f.tables[a];if(!r)return;const l=await ve(a,t),_=z(r,l),h=i?.hard===!0,E=!h&&r.softDeleteMode?r.softDeleteMode.field:void 0;if(!(E&&(!_||_[E]!==null&&_[E]!==void 0))){if(j(a,"before","delete")&&await G("before","delete",{id:t,op:"delete",previous:_??void 0,table:a}),await In({deletedId:t,deletedReference:u=>_?.[u],findHolders:async(u,p,w)=>{if(f.tables[u]?.shardMode?.kind==="shardBy")throw new T("INTERNAL",`cross-backend cascade from global '${a}' into shardBy '${u}' is not supported — would require Query Coordinator fan-out across shards`);return(await P.findMany(u,{includeDeleted:h,where:{[p]:w}})).page},onCascade:(u,p)=>P.delete(p,void 0,i),onRestrict:u=>{throw new oe(u,"restrict")},onSetNull:(u,p,w)=>P.patch(p,{[w]:null}),schema:f,tableName:a}),await Te(a),await ge(a),E&&_){const u={[E]:b()},p={..._,...u};je(r,u,p,J);const w=e.join(Object.keys(r.shape).map(y=>e`${e.identifier(y)} = ${ne(r,y,p[y]??null)}`),e`, `);await Oe(a,"UPDATE",w,l),await le(a,_,p),await Z(a,t,_,void 0),await fe(a,t,{document:p,previous:_,written:Be(l)}),await ae(a,t,"update",p),j(a,"after","delete")&&await G("after","delete",{id:t,op:"delete",previous:_,table:a});return}await Oe(a,"DELETE",void 0,l),qe.delete(t),await le(a,_??void 0,void 0),await Z(a,t,_??void 0,void 0),await fe(a,t,void 0),await ae(a,t,"delete"),j(a,"after","delete")&&await G("after","delete",{id:t,op:"delete",previous:_??void 0,table:a})}},async findFirst(t,n={}){return(await P.findMany(t,{...n,limit:1})).page[0]??null},async findFirstOrThrow(t,n={}){const i=await P.findFirst(t,n);if(i===null)throw new An(`findFirstOrThrow: no "${t}" document matched`);return i},async findMany(t,n={}){const i=f.tables[t];if(!i)throw new T("INTERNAL",`unknown table: ${t}`);await W();const a=async(y,S,v,I)=>{if(it(y))return c?Wn(c,y,S,v,I):ot(y);const M=f.tables[y];if(!M)throw new T("INTERNAL",`unknown table: ${y}`);const k=Le(M.softDeleteMode,void 0),D={[S]:{in:v}},U=F(F(D,I),k),we=await Ae(U,y,void 0),Ie=X(we,m(M)),$e=x(S);let H=e`SELECT ${$e} AS __fk__, COUNT(*) AS ${e.identifier("count")} FROM ${e.identifier(y)}`;Ie&&(H=e`${H} WHERE ${Ie}`),H=e`${H} GROUP BY ${$e}`;const O=await A(o,d,H),ee=new Map;for(const st of O)ee.set(st.__fk__,Number(st.count??0));return ee},{limit:r,orderKeys:l,query:_}=await rt(t,i,n),h=await A(o,d,_),E=Rt(i,h);if(r===void 0)return n.with&&await ut({fetcher:me,groupedCounter:a,parents:E,...ft(n),schema:f,tableName:t,with:n.with}),{continueCursor:null,isDone:!0,page:wt(E,n.select,n.with)};const u=E.length>r,p=u?E.slice(0,r):E,w=p.at(-1);return n.with&&await ut({fetcher:me,groupedCounter:a,parents:p,...ft(n),schema:f,tableName:t,with:n.with}),{continueCursor:u&&w?mn(w,l):null,isDone:!u,page:wt(p,n.select,n.with)}},async explain(t,n={}){const i=f.tables[t];if(!i)throw new T("INTERNAL",`unknown table: ${t}`);await W();const{query:a}=await rt(t,i,n),r=d.name==="sqlite"?"EXPLAIN QUERY PLAN":"EXPLAIN",l=await A(o,d,e`${e.raw(r)} ${a}`),{params:_,sql:h}=lt(d.name,a);return{params:_,plan:l.map(E=>ri(E)),sql:h}},async get(t,n){const i=await ce(t,n);if(!i)return null;const a=f.tables[i];return a?z(a,await en.load(i,t)):null},async groupBy(t,n){const i=f.tables[t];if(!i)throw new T("INTERNAL",`unknown table: ${t}`);await W();const a=n.agg??{op:"count"};if(_e(a.op),a.op!=="count"&&!a.field)throw new T("INTERNAL",`groupBy(${t}, { agg: { op: "${a.op}" } }): "field" is required for non-count reducers`);const r=Le(i.softDeleteMode,void 0),l=F(F(n.baseWhere,n.where),r),_=await Ae(l,t,n.relationBaseWhere),h=_!==l;if(i.aggregateIndexes&&!n.baseWhere&&!h&&!r){const S=await Jt(t,i.aggregateIndexes,a,n);if(S!==void 0)return S}_i(i,t,n.by,a);const E=X(_,m(i)),u=n.by.map(S=>e`${x(S)} AS ${e.identifier(S)}`);if(a.op==="count")u.push(e`COUNT(*) AS ${e.identifier("value")}`);else{if(!a.field)throw new T("INTERNAL",`groupBy(${t}, { agg: { op: "${a.op}" } }): "field" is required for non-count reducers`);u.push(e`${e.raw(_e(a.op))}(${x(a.field)}) AS ${e.identifier("value")}`)}const p=e.join(n.by.map(S=>x(S)),e`, `);let w=e`SELECT ${e.join(u,e`, `)} FROM ${e.identifier(t)}`;E&&(w=e`${w} WHERE ${E}`),w=e`${w} GROUP BY ${p}`;const y=await A(o,d,w);return di(i,n.by,y)},async insert(t,n,i){const a=f.tables[t];if(!a)throw new T("INTERNAL",`unknown table: ${t}`);await W(),be(d.name,n);const r=oi(a,n,J);We(a,r);let l,_=!0;i?.clientId!==void 0?(vn(i.clientId),l=i.clientId):i?.allowExplicitId&&typeof r._id=="string"?l=r._id:(l=B(),_=!1);const h=i?.allowExplicitId&&typeof r._creationTime=="number"?r._creationTime:b(),E={...r,_creationTime:h,_id:l};j(t,"before","insert")&&await G("before","insert",{doc:{...E},id:l,op:"insert",table:t}),await Te(t),await ge(t);const{columns:u,values:p}=zt(a,l,h,r);return await Qt(t,e`INSERT INTO ${e.identifier(t)} (${ie(u)}) VALUES (${se(p)})`),_&&qe.set(l,t),await le(t,void 0,E),await Z(t,l,void 0,E),await fe(t,l,{document:E,written:{_creationTime:h,[Ee]:null}}),await ae(t,l,"insert",E),j(t,"after","insert")&&await G("after","insert",{doc:E,id:l,op:"insert",table:t}),l},normalizeId(t,n){return gn(f,t,n)},async patch(t,n,i,a){Fe("patch",n),be(d.name,n);const r=await ce(t,i);if(!r)throw new T("INTERNAL",`document not found: ${t}`);const l=f.tables[r];if(!l)throw new T("INTERNAL",`document not found: ${t}`);const _=Tn(l,n)?Ge:1;for(let h=0;h<_;h+=1){const E=await ve(r,t);if(await nt(r,l,t,n,E,void 0,a))return}throw new oe(`optimistic concurrency conflict on "${r}" — the row changed during this mutation; refetch and retry`,"occ")},async patchIf(t,n,i){Fe("patchIf",i.patch),be(d.name,i.patch);const a=f.tables[t];if(!a)throw new T("INTERNAL",`unknown table: ${t}`);const r=X(i.where,m(a))??e`1 = 1`;for(let l=0;l<Ge;l+=1){const[_]=await A(o,d,e`SELECT *, CASE WHEN (${r}) THEN 1 ELSE 0 END AS ${e.identifier(Mt)} FROM ${e.identifier(t)} WHERE ${e.identifier("id")} = ${n}`);if(_===void 0)return{applied:!1,doc:null};const{[Mt]:h,...E}=_;if(Number(h)!==1)return{applied:!1,doc:z(a,E)??null};const u=await nt(t,a,n,i.patch,E,r,{verify:i.verify});if(u)return{applied:!0,doc:u}}throw new oe(`patchIf on "${t}" lost the row to concurrent writes ${String(Ge)} times in a row; retry the operation`,"occ")},async restore(t,n){const i=await ce(t,n);if(!i)throw new T("INTERNAL",`document not found: ${t}`);const a=f.tables[i],r=a?.softDeleteMode?.field;if(!a||!r)throw new T("INTERNAL",`ctx.db.restore: table "${i}" is not a .softDelete() table`);const l=await ve(i,t),_=l?.[r]!==null&&l?.[r]!==void 0;if(await P.patch(t,{[r]:null},n),_){const h=z(a,l);h!==null&&await Z(i,t,void 0,{...h,[r]:null})}},query(t){const n=f.tables[t];if(!n)throw new T("INTERNAL",`unknown table: ${t}`);const i="the legacy query()/withIndex() reader is not available on the D1 (global) backend; use findMany",a=[];let r=0,l;const _=d.name!=="mysql",h={...m(n),fieldRef:w=>e`m.${x(w)}`,rangeTypeGuard:()=>{throw new T("INTERNAL","a path range is never pushed into a search")}},E=w=>a.every(y=>y(w)),u=async(w,y)=>{await W();const S=2*dn+w.filters.length,v=l===void 0?void 0:X(l,h,void 0,S),I=v!==void 0&&d.name==="sqlite"&<(d.name,v).params.length+S>jn.boundParams,M=I?void 0:v,k=r>0||I,D=await ln(o,d,n,t,M===void 0?w:{...w,scope:M},un(k?void 0:y));!k&&y===void 0&&fn(D);const U=D.filter(we=>E(we));return y===void 0?U:U.slice(0,y)},p=w=>{const y={async*[Symbol.asyncIterator](){if(!w)throw new T("INTERNAL",i);yield*await u(w,void 0)},async collect(){if(!w)throw new T("INTERNAL",i);return u(w,void 0)},async collectWithScores(){throw new T("GLOBAL_SEARCH_SCORES_UNSUPPORTED",`collectWithScores() is not supported on \`.global()\` tables (table "${t}") — relevance scores are not yet surfaced on this backend; use .collect() instead`)},filter(S){a.push(S);const v=Un(S);return v!==void 0&&xn(v,n.shape,_)?l=F(l,v):r+=1,y},async first(){if(!w)throw new T("INTERNAL",i);return(await u(w,1))[0]??null},order(){return y},async paginate(S){if(!w)throw new T("INTERNAL",i);const v=an(S);return cn(await u(w,wn(v)),v)},async take(S){if(!w)throw new T("INTERNAL",i);return u(w,S)},async unique(){if(!w)throw new T("INTERNAL",i);const S=await u(w,2);if(S.length>1)throw new Kn(`unique() on table "${t}" matched ${String(S.length)} documents; expected at most one`);return S[0]??null},withGeoIndex(){throw new T("INTERNAL",`geo indexes are not supported on \`.global()\` tables (table "${t}") — geospatial queries run only on sharded tables`)},withIndex(){throw new T("INTERNAL",i)},withSearchIndex(S,v){const I=(n.searchIndexes??[]).find(k=>k.name===S);if(!I)throw new T("INTERNAL",`unknown search index "${S}" on table "${t}"`);const M={definition:I,field:I.field,filters:[],hasQuery:!1,indexName:S,query:""};if(v(sn(M,t,nn(I.language))),!M.hasQuery)throw new T("INTERNAL",`search index "${S}" on table "${t}" requires a .search(field, query) call`);return p(M)}};return y};return p(void 0)},async rank(t,n,i){const a=f.tables[t];if(!a)throw new T("INTERNAL",`unknown table: ${t}`);const r=a.rankIndexes?.find(D=>D.name===n);if(!r)throw new T("INTERNAL",`unknown rankIndex "${n}" on table "${t}"`);if(i.restrictsCounts)throw new dt(t);if(await W(),!await De(t,r))return null;const _=typeof i.row=="string"?i.row:i.row._id;if(!_)return null;const h=he(t,r.name),E=r.sortBy.map((D,U)=>pe(U)),u=ie(["__partition__",...E]),w=(await A(o,d,e`SELECT ${u} FROM ${e.identifier(h)} WHERE ${e.identifier("__id__")} = ${_}`))[0];if(!w)return null;const y=w.__partition__,S=F(i.baseWhere,i.where);at(S,f,t,"rank");const v=ct(r,S);if(v&&Ce(r.partitionBy??[],v)!==y)return null;const I=ui(d.name,r,E,w,_),M=await A(o,d,e`SELECT COUNT(*) AS c FROM ${e.identifier(h)} WHERE ${e.identifier("__partition__")} = ${y} AND (${I})`),k=await A(o,d,e`SELECT COUNT(*) AS c FROM ${e.identifier(h)} WHERE ${e.identifier("__partition__")} = ${y}`);return{position:Number(M[0]?.c??0)+1,total:Number(k[0]?.c??0)}},async rankPage(t,n,i={}){at(F(i.baseWhere,i.where),f,t,"rankPage");const a=f.tables[t];if(!a)throw new T("INTERNAL",`unknown table: ${t}`);const r=a.rankIndexes?.find(O=>O.name===n);if(!r)throw new T("INTERNAL",`unknown rankIndex "${n}" on table "${t}"`);if(await W(),!await De(t,r))return{continueCursor:null,isDone:!0,page:[]};const _=he(t,r.name),h=r.sortBy.map((O,ee)=>pe(ee)),E=Math.max(1,Math.min(1e3,Math.floor(i.take??100))),u=F(i.baseWhere,i.where),p=ct(r,u),w=wi(r,h),y=e.join(w.flatMap(O=>Ut(d,{direction:O.direction,field:O.column,nullable:O.nullable})),e`, `),S=[];typeof i.partitionKey=="string"?S.push(e`${e.identifier("__partition__")} = ${i.partitionKey}`):p&&S.push(e`${e.identifier("__partition__")} = ${Ce(r.partitionBy??[],p)}`);const v=Sn(i);if(v!==void 0){const O=fi(d.name,w,v);O!==void 0&&S.push(O)}const I=ie([ye,"__partition__",...h]);let M=e`SELECT ${I} FROM ${e.identifier(_)}`;S.length>0&&(M=e`${M} WHERE ${e.join(S,e` AND `)}`),M=e`${M} ORDER BY ${y} LIMIT ${e.raw(String(E+1))}`;const k=await A(o,d,M),D=k.length>E,U=D?k.slice(0,E):k,we=U.map(O=>O[ye]),Ie=await $i(o,d,a,t,we);let $e=null;const H=U.at(-1);if(D&&H!==void 0){const O=[H.__partition__,...h.map(ee=>H[ee]),H[ye]];$e=hi(O)}return{continueCursor:$e,isDone:!D,page:Ie}},async replace(t,n,i,a){Fe("replace",n),be(d.name,n);const r=await ce(t,i);if(!r)throw new T("INTERNAL",`document not found: ${t}`);const l=f.tables[r];if(!l)throw new T("INTERNAL",`document not found: ${t}`);const _=await ve(r,t);if(_===void 0)throw new T("INTERNAL",`document not found: ${t}`);const E=Rn(f,r,"update")||(l.aggregateIndexes??[]).length>0||(l.rankIndexes??[]).length>0?z(l,_)??void 0:void 0,u=a?.allowExplicitId&&typeof n._creationTime=="number"?n._creationTime:void 0,p=typeof _._creationTime=="number"?_._creationTime:void 0,w=u??p??b(),y={...n,_creationTime:w,_id:t};je(l,n,y,J),We(l,y),j(r,"before","update")&&await G("before","update",{doc:{...y},id:t,op:"update",previous:E,table:r}),await Te(r),await ge(r);const S=Object.keys(l.shape),v=e.join([e`${e.identifier("_creationTime")} = ${w}`,...S.map(I=>e`${e.identifier(I)} = ${ne(l,I,y[I]??null)}`)],e`, `);await Oe(r,"UPDATE",v,_),await le(r,E,y),await Z(r,t,E,y),await fe(r,t,{document:y,previous:E,written:Be(_,w)}),await ae(r,t,"update",y),j(r,"after","update")&&await G("after","update",{doc:y,id:t,op:"update",previous:E,table:r})}};return et={db:P,scheduler:jt},P};export{ji as createSqlCtxDb,Yi as decodeGlobalRow,Ci as readSqlCdcChangedTables,Ki as readSqlCdcChanges,Kt as readSqlCdcFloor,Ri as runSqlCdcMigration,Ti as sweepSqlCdcRetention};
|
|
7
|
+
`)},Kt=async(s,c)=>{const $=await A(s,c,e`SELECT MIN(${e.identifier("seq")}) AS ${e.identifier("seq")} FROM ${e.identifier(K)}`),o=Number($[0]?.seq??Number.NaN);return Number.isFinite(o)?o:void 0},gi=async(s,c)=>{if(c.name!=="sqlite")return;const $=await A(s,c,e`SELECT ${e.identifier("seq")} AS ${e.identifier("seq")} FROM ${e.identifier("sqlite_sequence")} WHERE ${e.identifier("name")} = ${K}`),o=Number($[0]?.seq??Number.NaN);return Number.isFinite(o)?o:0},vi=s=>JSON.stringify(Bt(s)?Ft(s):s),mi=async(s,c,$,o,R,f,d)=>{await q(s,d,e`INSERT INTO ${e.identifier(K)} (${e.identifier("ts")}, ${e.identifier("table")}, ${e.identifier("id")}, ${e.identifier("op")}, ${e.identifier("doc")}) VALUES (${c}, ${$}, ${o}, ${R}, ${f===void 0?null:vi(f)})`)},ji=async(s,c,$)=>{const o=c.sinceSeq??0,R=Math.max(1,Math.min(c.limit??1e3,1e4)),f=await Kt(s,$),d=await gi(s,$);if(d!==void 0&&o>d)throw _n(d,o,"global");if(f!==void 0&&En(f,o))throw pn(f,o,"global");const g=(await A(s,$,e`SELECT seq, ts, ${e.identifier("table")}, id, op, doc FROM ${e.identifier(K)} WHERE seq > ${o} ORDER BY seq ASC LIMIT ${e.raw(String(R))}`)).map(m=>{const{doc:C}=m,L={id:String(m.id),op:String(m.op),seq:Number(m.seq),table:String(m.table),ts:Number(m.ts)};return typeof C=="string"?{...L,doc:Dt(JSON.parse(C))}:L});return{changes:g,cursor:g.at(-1)?.seq??o}},Ai=1e4,Ii=1e3,Lt=(s,c)=>{const $=e.identifier(K),o=e`(SELECT MIN(v.seq) FROM ${$} v WHERE v.seq > ${s} AND v.seq - 1 > ${s} AND v.ts > ${c} AND NOT EXISTS (SELECT 1 FROM ${$} p WHERE p.seq = v.seq - 1))`;return e`${o} AS ${e.identifier("gap")}, (SELECT MAX(q.seq) FROM ${$} q WHERE q.seq > ${s} AND q.seq < ${o}) AS ${e.identifier("below")}`},bt=(s,c,$)=>{const o=Number(c?.gap??Number.NaN);if(!Number.isFinite(o))return s;const R=Number(c?.below??Number.NaN);return Math.min(s,Number.isFinite(R)?R:$)},Ci=async(s,c,$,o={})=>{const R=e.identifier(K),f=$.name!=="sqlite",d=(o.now??Date.now())-Ai;if(o.cursorOnly){const L=e`GREATEST((SELECT MAX(seq) FROM ${R}) - ${e.raw(String(Ii))}, ${c})`,b=await A(s,$,e`SELECT MAX(seq) AS seq${f?e`, ${Lt(L,d)}`:e``} FROM ${R}`),B=Number(b[0]?.seq??c);return{cursor:bt(Number.isFinite(B)?B:c,b[0],c),tables:[]}}const N=await A(s,$,e`SELECT ${e.identifier("table")} AS ${e.identifier("table")}, MAX(seq) AS seq${f?e`, ${Lt(e`${c}`,d)}`:e``} FROM ${R} WHERE seq > ${c} GROUP BY ${e.identifier("table")}`);let g=c;const m=[];for(const L of N){const b=Number(L.seq);Number.isFinite(b)&&b>g&&(g=b),m.push(String(L.table))}g=bt(g,N[0],c);const C=o.retained===!0?await Kt(s,$):void 0;return{cursor:g,tables:m,...C===void 0?{}:{floor:C}}},Li=/string or blob too big/iu,bi=/row is too big/iu,Mi=(s,c)=>{const{code:$,errno:o}=c,R=c instanceof Error?c.message:"";switch(s.name){case"mysql":return o===1118||$==="ER_TOO_BIG_ROWSIZE"?"InnoDB's per-row ceiling — roughly 8 KB, half a 16 KB page, for the part of the row stored inline":void 0;case"postgres":return bi.test(R)?"the 8 KB heap page a tuple must fit once its wide columns have been TOASTed out":void 0;default:return Li.test(R)?"the storage engine's per-row ceiling (2 MB on D1)":void 0}},Ni=(s,c,$)=>{const o=Mi(s,c);if(o!==void 0)throw new T("PAYLOAD_TOO_LARGE",`document is too large to store in "${$}": a single row cannot exceed ${o}. The limit is on the STORED bytes, which are UTF-8. Keep the payload in R2 (ctx.storage) and store a reference on the row.`)},Ge=16,Mt="__lunora_patch_if_match__",Nt=(s,c,$)=>{throw s.isUniqueViolation(c)?new oe(`unique constraint violation on "${$}"`,"unique"):(Ni(s,c,$),c)},Ve=new WeakMap,qi=s=>{const c=yn(s);return($,o,R,f)=>o.some(d=>d instanceof Gn)?Yn(s,$,o,R):c($,o,R,f)},Gi=s=>{const{crossShardCounter:c,crossShardReader:$,exec:o,maxRelationKeys:R,schema:f}=s,{dialect:d}=s,N={fieldRef:t=>Me(d,t),rangeTypeGuard:(t,n)=>Xn(d,t,n),...d.name==="mysql"?{containsExpr:(t,n)=>{const i=pt(t);return i===void 0?e`LOCATE(${n}, ${t}) > 0`:e`LOCATE(${yt("mysql",n)}, ${i}) > 0`}}:{},...d.name==="postgres"?{containsExpr:(t,n)=>{const i=pt(t);return i===void 0?e`strpos(${t}, ${n}) > 0`:e`strpos(${i}, ${yt("postgres",n)}) > 0`}}:{},...d.name==="sqlite"?{}:{inList:qi(d.name)}},g=new WeakMap,m=t=>{const n=g.get(t);if(n!==void 0)return n;const i={...N,serialize:(a,r)=>mt(d,r,a,l=>ne(t,r,l))};return g.set(t,i),i},C=(t,n)=>Qe(d.name,t,n),L=t=>{const n=ie(t.columns),i=se(t.values),a=h=>d.name==="mysql"?e`VALUES(${e.identifier(h)})`:e`excluded.${e.identifier(h)}`,r=h=>d.name==="postgres"?e`${e.identifier(t.table)}.${e.identifier(h)}`:e`${e.identifier(h)}`,l=e.join(Object.entries(t.set(a,r)).map(([h,E])=>e`${e.identifier(h)} = ${E}`),e`, `),_=d.name==="mysql"?e`ON DUPLICATE KEY UPDATE ${l}`:e`ON CONFLICT(${e.identifier(t.conflictKey)}) DO UPDATE SET ${l}`;return e`INSERT INTO ${e.identifier(t.table)} (${n}) VALUES (${i}) ${_}`},b=s.clock??(()=>Date.now()),B=s.idGenerator??(()=>crypto.randomUUID()),V=s.cdc??!1,Y=typeof s.cdcRetentionMs=="number"&&Number.isFinite(s.cdcRetentionMs)&&s.cdcRetentionMs>0?s.cdcRetentionMs:void 0,J=s.auth??{identity:null,userId:null},ae=async(t,n,i,a)=>{if(!V||(await mi(o,b(),t,n,i,a,d),Y===void 0))return;const r=b();if(!(r-Ct<yi)){Ct=r;try{await Ti(o,d,Y,r)}catch{}}},jt=s.scheduler??$n,qe=ai();let Re=0;const ke=s.provisionScope??{},W=async()=>{const t=Ve.get(ke);if(t)return t;const n=(async()=>{await Qn(o,f,d),await zn(o,f,d),await Jn(o,f,d),await tn(o,d),await rn(o,f,d),V&&await Ri(o,d)})().catch(i=>{throw Ve.delete(ke),i});return Ve.set(ke,n),n},ce=async(t,n)=>{await W();const i=await ci(o,d,f,t,qe);if(!(n!==void 0&&i!==n))return i},de=new Map,ze=async(t,n)=>{const i=te(t,n);return(await A(o,d,d.tableExists(i))).length>0},Se=async(t,n)=>{const i=`${t}::${n.name}`,a=de.get(i);if(a!==void 0)return a;if(!await ze(t,n.name))return de.set(i,!1),!1;const l=f.tables[t];if(!l)return de.set(i,!1),!1;const _=n.by??[],h=new Map;await Tt(o,d,l,t,p=>{if(n.where&&!xe(p,n.where))return;const w=Q(_,p);Et(h,w,n,p)});const E=te(t,n.name);await q(o,d,e`DELETE FROM ${e.identifier(E)}`);const u=[];for(const[p,w]of h)u.push(e`INSERT INTO ${e.identifier(E)} (${e.identifier("__key__")}, ${e.identifier("__value__")}, ${e.identifier("__count__")}) VALUES (${p}, ${w.value}, ${w.count})`);return await gt(o,d,u),de.set(i,!0),!0},Gt=async(t,n,i,a)=>{const r=new Map;let l,_=!0;for(;_;){const h=l===void 0?a:[...a,e`${e.identifier("id")} > ${l}`],E=h.length>0?e` WHERE ${e.join(h,e` AND `)}`:e``,u=await A(o,d,e`SELECT ${e.identifier("id")}, ${x(i.field??"")} FROM ${e.identifier(n)}${E} ORDER BY ${e.identifier("id")} ASC LIMIT ${e.raw(String(Ke))}`);for(const p of Rt(t,u))Et(r,"",i,p);l=u.at(-1)?.id,_=u.length===Ke}return r.get("")?.value??null},Vt=async(t,n,i)=>{const a=n.field??"",r=[],l=f.tables[t],_=(p,w)=>mt(d,p,w,y=>l?ne(l,p,y):He(y));for(const p of n.by??[]){const w=_(p,i[p]??null);r.push(w===null?e`${x(p)} IS NULL`:e`${x(p)} = ${w}`)}for(const[p,w]of Object.entries(n.where??{})){const y=w!==null&&typeof w=="object"&&!Array.isArray(w)?w.eq:w,S=_(p,y),v=Me(d,p);r.push(S===null?e`${v} IS NULL`:e`${v} = ${S}`)}const h=r.length>0?e` WHERE ${e.join(r,e` AND `)}`:e``;if(l&&Pt(l.shape[a]))return Gt(l,t,n,r);const E=_e(n.op),u=await A(o,d,e`SELECT ${e.raw(E)}(${x(a)}) AS ${e.identifier("value")} FROM ${e.identifier(t)}${h}`);return re(u[0]?.value)},Yt=async(t,n)=>{await q(o,d,e`DELETE FROM ${e.identifier(t)} WHERE ${e.identifier("__key__")} = ${n} AND ${e.identifier("__count__")} <= 0`)},Xt=async(t,n,i,a)=>{const r=te(t,n.name),{op:l}=n,_=n.field??"",h=i&&(!n.where||xe(i,n.where))?i:void 0,E=a&&(!n.where||xe(a,n.where))?a:void 0;if(!(!h&&!E)){if(l==="count"||l==="sum"||l==="avg"){const u=new Set;for(const[p,w]of[[h,-1],[E,1]]){if(!p)continue;const y=l==="count"?1:Pe(p[_]);if(y===void 0)continue;const S=Q(n.by??[],p);u.add(S),await q(o,d,L({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(v,I)=>({__count__:e`${I("__count__")} + ${v("__count__")}`,__value__:l==="count"?e`${I("__value__")} + ${v("__value__")}`:e`COALESCE(${I("__value__")}, 0) + ${v("__value__")}`}),table:r,values:[S,w*y,w]}))}for(const p of u)await Yt(r,p);return}if(h){const u=Q(n.by??[],h),p=Pe(h[_]),y=(await A(o,d,e`SELECT ${e.identifier("__value__")} AS ${e.identifier("value")}, ${e.identifier("__count__")} AS ${e.identifier("count")} FROM ${e.identifier(r)} WHERE ${e.identifier("__key__")} = ${u}`))[0],S=re(y?.value),v=(y?.count??0)-1;if(v<=0)await q(o,d,e`DELETE FROM ${e.identifier(r)} WHERE ${e.identifier("__key__")} = ${u}`);else if(y&&p!==void 0&&S!==null&&p===S){const I=await Vt(t,n,h);await q(o,d,e`UPDATE ${e.identifier(r)} SET ${e.identifier("__value__")} = ${I}, ${e.identifier("__count__")} = ${v} WHERE ${e.identifier("__key__")} = ${u}`)}else await q(o,d,e`UPDATE ${e.identifier(r)} SET ${e.identifier("__count__")} = ${e.identifier("__count__")} - 1 WHERE ${e.identifier("__key__")} = ${u}`)}if(E){const u=Q(n.by??[],E),p=Pe(E[_]);if(p===void 0)await q(o,d,L({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(w,y)=>({__count__:e`${y("__count__")} + 1`}),table:r,values:[u,null,1]}));else{const w=l==="min"?"MIN":"MAX";await q(o,d,L({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(y,S)=>({__count__:e`${S("__count__")} + 1`,__value__:e`${e.raw(w)}(COALESCE(${S("__value__")}, ${y("__value__")}), ${y("__value__")})`}),table:r,values:[u,p,1]}))}}}},Te=async t=>{const n=f.tables[t]?.aggregateIndexes;if(!(!n||n.length===0))for(const i of n)await Se(t,i)},le=async(t,n,i)=>{const a=f.tables[t]?.aggregateIndexes;if(!(!a||a.length===0))for(const r of a){const l=`${t}::${r.name}`;(de.get(l)??await ze(t,r.name))&&await Xt(t,r,n,i)}},ue=new Map,Je=async(t,n)=>{const i=he(t,n);return(await A(o,d,d.tableExists(i))).length>0},De=async(t,n)=>{const i=`${t}::rank::${n.name}`,a=ue.get(i);if(a!==void 0)return a;if(!await Je(t,n.name))return ue.set(i,!1),!1;const l=f.tables[t];if(!l)return ue.set(i,!1),!1;const _=he(t,n.name);await q(o,d,e`DELETE FROM ${e.identifier(_)}`);const h=n.sortBy.map((w,y)=>pe(y)),E=ie(["__id__","__partition__",...h]);let u=[];const p=async()=>{if(u.length===0)return;const w=u;u=[],await gt(o,d,w)};return await Tt(o,d,l,t,async w=>{if(n.where&&!$t(w,n.where))return;const y=Ce(n.partitionBy??[],w),S=n.sortBy.map(v=>He(w[v.field]??null));u.push(e`INSERT INTO ${e.identifier(_)} (${E}) VALUES (${se([w._id,y,...S])})`),u.length>=Ke&&await p()}),await p(),ue.set(i,!0),!0},ge=async t=>{const n=f.tables[t]?.rankIndexes;if(!(!n||n.length===0))for(const i of n)await De(t,i)},Z=async(t,n,i,a)=>{const r=f.tables[t],l=r?.rankIndexes;if(!l||l.length===0)return;const _=r?.softDeleteMode?.field,h=_===void 0||a===void 0?void 0:a[_],E=h!=null;for(const u of l){if(i!==void 0&&a!==void 0&&li(u,i,a))continue;const p=`${t}::rank::${u.name}`;if(!(ue.get(p)??await Je(t,u.name)))continue;const S=he(t,u.name);if(i&&await q(o,d,e`DELETE FROM ${e.identifier(S)} WHERE ${e.identifier("__id__")} = ${n}`),a&&!E){if(u.where&&!$t(a,u.where))continue;const v=u.sortBy.map((D,U)=>pe(U)),I=ie(["__id__","__partition__",...v]),M=Ce(u.partitionBy??[],a),k=u.sortBy.map(D=>He(a[D.field]??null));await q(o,d,e`INSERT INTO ${e.identifier(S)} (${I}) VALUES (${se([n,M,...k])})`)}}},fe=on({dialect:d,exec:o,schema:f}),Ze=new Set;for(const[t,n]of Object.entries(f.tables))for(const i of Object.values(n.triggerMap??{}))Ze.add(`${t} ${i.timing} ${i.op}`);const j=(t,n,i)=>Ze.has(`${t} ${n} ${i}`);let et;const G=async(t,n,i)=>{if(Re+=1,Re>It)throw Re-=1,new oe(`trigger recursion exceeded ${String(It)} levels on "${i.table}" — check for a self-triggering write`,"trigger");try{await Mn({ctx:et,event:i,op:n,schema:f,tableName:i.table,timing:t})}finally{Re-=1}},Qt=async(t,n)=>{try{await q(o,d,n)}catch(i){Nt(d,i,t)}},ve=async(t,n)=>(await A(o,d,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} = ${n}`))[0],tt=async(t,n,i,a,r)=>{const l=e`${e.identifier(Ee)}`,_=e.join([C(e`${e.identifier("id")}`,a.id),C(l,a[Ee]??null),...r===void 0?[]:[e`(${r})`]],e` AND `),h=n==="UPDATE"?e`UPDATE ${e.identifier(t)} SET ${i}, ${l} = ${St.sql(l)} WHERE ${_}`:e`DELETE FROM ${e.identifier(t)} WHERE ${_}`;try{if(d.supportsReturning)return(await A(o,d,e`${h} RETURNING ${e.identifier("id")}`)).length>0;const E=await q(o,d,h);return(d.affectedRows?d.affectedRows(E??{rowsAffected:0}):0)>0}catch(E){return Nt(d,E,t)}},Oe=async(t,n,i,a)=>{if(a!==void 0&&!await tt(t,n,i,a))throw new oe(`optimistic concurrency conflict on "${t}" — the row changed during this mutation; refetch and retry`,"occ")},Be=(t,n=t?._creationTime)=>({_creationTime:n,[Ee]:St.value(t?.[Ee])}),nt=async(t,n,i,a,r,l,_)=>{const h=z(n,r);if(!h||r===void 0)throw new T("INTERNAL",`document not found: ${i}`);const E=qn(n,a,h),u={...h,...kn(E),_id:i};je(n,E,u,J),Dn(_,h,u),We(n,u,!0),j(t,"before","update")&&await G("before","update",{doc:{...u},id:i,op:"update",previous:h,table:t}),await Te(t),await ge(t);const p=Object.keys(n.shape),w=e.join(p.map(y=>e`${e.identifier(y)} = ${ne(n,y,u[y]??null)}`),e`, `);if(await tt(t,"UPDATE",w,r,l))return await le(t,h,u),await Z(t,i,h,u),await fe(t,i,{document:u,previous:h,written:Be(r)}),await ae(t,i,"update",u),j(t,"after","update")&&await G("after","update",{doc:u,id:i,op:"update",previous:h,table:t}),u},zt=(t,n,i,a)=>{const r=Object.keys(t.shape);return{columns:["id","_creationTime",...r],values:[n,i,...r.map(l=>ne(t,l,a[l]??null))]}},Jt=async(t,n,i,a)=>{const r=Bn(n,i.op,i.field,a.by,a.where);if(!r||!await Se(t,r.index))return;const _=te(t,r.index.name),h=Object.keys(r.partial);if(h.length===(r.index.by??[]).length&&h.length>0){const u=Q(r.index.by??[],r.partial),p=await A(o,d,e`SELECT ${e.identifier("__value__")} AS ${e.identifier("value")}, ${e.identifier("__count__")} AS ${e.identifier("count")} FROM ${e.identifier(_)} WHERE ${e.identifier("__key__")} = ${u}`);if(p.length===0)return[];const w=p[0];return[{key:{...r.partial},value:Ue(i.op,{count:w.count,value:re(w.value)})}]}return h.length>0?void 0:(await A(o,d,e`SELECT ${e.identifier("__key__")} AS ${e.identifier("key")}, ${e.identifier("__value__")} AS ${e.identifier("value")}, ${e.identifier("__count__")} AS ${e.identifier("count")} FROM ${e.identifier(_)}`)).map(u=>{const p=u;return{key:Dt(JSON.parse(p.key)),value:Ue(i.op,{count:p.count,value:re(p.value)})}})},it=t=>{const n=f.tables[t]?.shardMode?.kind;return n==="shardBy"||n==="root"},ot=t=>{throw new T("INTERNAL",`cross-backend relation: a global table cannot load the shard-local relation '${t}' (it spans every shard) — wire a cross-shard reader to support it`)},Zt=(t,n)=>{if(n?.relationMask!==void 0&&n.with!==void 0&&Object.keys(n.with).length>0)throw new T("MASK_UNSUPPORTED",`masking cannot follow a nested \`with\` across the cross-shard relation hop to "${t}" — the nested rows are hydrated on the serving shard, where the mask policy does not exist. Read the nested relation at its own (masked) call site instead.`);const i={};if(n?.relationBaseWhere)for(const a of Object.keys(f.tables)){const r=n.relationBaseWhere(a);r!==void 0&&(i[a]=r)}return{orderBy:n?.orderBy,relationPolicies:i,where:F(n?.baseWhere,n?.where),with:n?.with}},me=(t,n)=>it(t)?$?$(t,Zt(t,n)):ot(t):P.findMany(t,n),Ae=(t,n,i)=>On(t,{fetcher:me,maxRelationKeys:R,relationBaseWhere:i,schema:f,tableName:n}),en=ei(async(t,n)=>{const i=await A(o,d,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} IN (${se(n)})`),a=new Map;for(const r of i){const{id:l}=r;typeof l=="string"&&a.set(l,r)}return a}),rt=async(t,n,i)=>{const{fetchLimit:a,limit:r,orderKeys:l,predicate:_}=await Fn(n,i,{fetcher:me,maxRelationKeys:R,schema:f,tableName:t}),h=X(_,m(n)),E=ii(l,d);let u=e`SELECT * FROM ${e.identifier(t)}`;return h&&(u=e`${u} WHERE ${h}`),u=e`${u} ORDER BY ${E}`,a!==void 0&&(u=e`${u} LIMIT ${e.raw(String(a))}`),{limit:r,orderKeys:l,query:u}},P={relationWrites:hn(f),async cdcChangedTables(t,n){if(V)try{return await W(),await Ci(o,t,d,{...n,now:b(),retained:Y!==void 0})}catch{return}},async aggregate(t,n){const i=f.tables[t];if(!i)throw new T("INTERNAL",`unknown table: ${t}`);if(await W(),_e(n.op),n.op==="count")return P.count(t,{baseWhere:n.baseWhere,relationBaseWhere:n.relationBaseWhere,restrictsCounts:n.restrictsCounts,where:n.where});if(!n.field)throw new T("INTERNAL",`aggregate(${t}, { op: "${n.op}" }): "field" is required for non-count reducers`);const a=Le(i.softDeleteMode,void 0),r=F(F(n.baseWhere,n.where),a),l=await Ae(r,t,n.relationBaseWhere),_=l!==r;if(i.aggregateIndexes&&!n.baseWhere&&!_&&!a){const y=bn(i.aggregateIndexes,n.op,n.field,n.where);if(y&&await Se(t,y.index)){const v=Q(y.index.by??[],y.key),I=te(t,y.index.name),k=(await A(o,d,e`SELECT ${e.identifier("__value__")} AS ${e.identifier("value")}, ${e.identifier("__count__")} AS ${e.identifier("count")} FROM ${e.identifier(I)} WHERE ${e.identifier("__key__")} = ${v}`))[0];return Ue(n.op,k===void 0?void 0:{count:k.count,value:re(k.value)})}}Ye(i,n.field,`aggregate(${t}, { op: "${n.op}", field: "${n.field}" })`);const h=X(l,m(i)),E=e.raw(_e(n.op)),u=e`SELECT ${E}(${x(n.field)}) AS ${e.identifier("value")} FROM ${e.identifier(t)}`,w=(await A(o,d,h?e`${u} WHERE ${h}`:u))[0]?.value;return w==null?null:Number(w)},async count(t,n){const i=f.tables[t];if(!i)throw new T("INTERNAL",`unknown table: ${t}`);await W();const a=Cn(n);if(a.restrictsCounts)throw new dt(t);const r=Le(i.softDeleteMode,void 0),l=F(F(a.baseWhere,a.where),r),_=await Ae(l,t,a.relationBaseWhere),h=_!==l;if(i.aggregateIndexes&&!a.baseWhere&&!h&&!r){const w=Ln(i.aggregateIndexes,a.where);if(w&&await Se(t,w.index)){const S=Q(w.index.by??[],w.key),v=te(t,w.index.name),I=await A(o,d,e`SELECT ${e.identifier("__value__")} AS ${e.identifier("value")} FROM ${e.identifier(v)} WHERE ${e.identifier("__key__")} = ${S}`);return Number(I[0]?.value??0)}}const E=X(_,m(i)),u=e`SELECT COUNT(*) AS ${e.identifier("count")} FROM ${e.identifier(t)}`,p=await A(o,d,E?e`${u} WHERE ${E}`:u);return Number(p[0]?.count??0)},async delete(t,n,i){const a=await ce(t,n);if(!a)return;const r=f.tables[a];if(!r)return;const l=await ve(a,t),_=z(r,l),h=i?.hard===!0,E=!h&&r.softDeleteMode?r.softDeleteMode.field:void 0;if(!(E&&(!_||_[E]!==null&&_[E]!==void 0))){if(j(a,"before","delete")&&await G("before","delete",{id:t,op:"delete",previous:_??void 0,table:a}),await In({deletedId:t,deletedReference:u=>_?.[u],findHolders:async(u,p,w)=>{if(f.tables[u]?.shardMode?.kind==="shardBy")throw new T("INTERNAL",`cross-backend cascade from global '${a}' into shardBy '${u}' is not supported — would require Query Coordinator fan-out across shards`);return(await P.findMany(u,{includeDeleted:h,where:{[p]:w}})).page},onCascade:(u,p)=>P.delete(p,void 0,i),onRestrict:u=>{throw new oe(u,"restrict")},onSetNull:(u,p,w)=>P.patch(p,{[w]:null}),schema:f,tableName:a}),await Te(a),await ge(a),E&&_){const u={[E]:b()},p={..._,...u};je(r,u,p,J);const w=e.join(Object.keys(r.shape).map(y=>e`${e.identifier(y)} = ${ne(r,y,p[y]??null)}`),e`, `);await Oe(a,"UPDATE",w,l),await le(a,_,p),await Z(a,t,_,void 0),await fe(a,t,{document:p,previous:_,written:Be(l)}),await ae(a,t,"update",p),j(a,"after","delete")&&await G("after","delete",{id:t,op:"delete",previous:_,table:a});return}await Oe(a,"DELETE",void 0,l),qe.delete(t),await le(a,_??void 0,void 0),await Z(a,t,_??void 0,void 0),await fe(a,t,void 0),await ae(a,t,"delete"),j(a,"after","delete")&&await G("after","delete",{id:t,op:"delete",previous:_??void 0,table:a})}},async findFirst(t,n={}){return(await P.findMany(t,{...n,limit:1})).page[0]??null},async findFirstOrThrow(t,n={}){const i=await P.findFirst(t,n);if(i===null)throw new An(`findFirstOrThrow: no "${t}" document matched`);return i},async findMany(t,n={}){const i=f.tables[t];if(!i)throw new T("INTERNAL",`unknown table: ${t}`);await W();const a=async(y,S,v,I)=>{if(it(y))return c?Wn(c,y,S,v,I):ot(y);const M=f.tables[y];if(!M)throw new T("INTERNAL",`unknown table: ${y}`);const k=Le(M.softDeleteMode,void 0),D={[S]:{in:v}},U=F(F(D,I),k),we=await Ae(U,y,void 0),Ie=X(we,m(M)),$e=x(S);let H=e`SELECT ${$e} AS __fk__, COUNT(*) AS ${e.identifier("count")} FROM ${e.identifier(y)}`;Ie&&(H=e`${H} WHERE ${Ie}`),H=e`${H} GROUP BY ${$e}`;const O=await A(o,d,H),ee=new Map;for(const st of O)ee.set(st.__fk__,Number(st.count??0));return ee},{limit:r,orderKeys:l,query:_}=await rt(t,i,n),h=await A(o,d,_),E=Rt(i,h);if(r===void 0)return n.with&&await ut({fetcher:me,groupedCounter:a,parents:E,...ft(n),schema:f,tableName:t,with:n.with}),{continueCursor:null,isDone:!0,page:wt(E,n.select,n.with)};const u=E.length>r,p=u?E.slice(0,r):E,w=p.at(-1);return n.with&&await ut({fetcher:me,groupedCounter:a,parents:p,...ft(n),schema:f,tableName:t,with:n.with}),{continueCursor:u&&w?mn(w,l):null,isDone:!u,page:wt(p,n.select,n.with)}},async explain(t,n={}){const i=f.tables[t];if(!i)throw new T("INTERNAL",`unknown table: ${t}`);await W();const{query:a}=await rt(t,i,n),r=d.name==="sqlite"?"EXPLAIN QUERY PLAN":"EXPLAIN",l=await A(o,d,e`${e.raw(r)} ${a}`),{params:_,sql:h}=lt(d.name,a);return{params:_,plan:l.map(E=>ri(E)),sql:h}},async get(t,n){const i=await ce(t,n);if(!i)return null;const a=f.tables[i];return a?z(a,await en.load(i,t)):null},async groupBy(t,n){const i=f.tables[t];if(!i)throw new T("INTERNAL",`unknown table: ${t}`);await W();const a=n.agg??{op:"count"};if(_e(a.op),a.op!=="count"&&!a.field)throw new T("INTERNAL",`groupBy(${t}, { agg: { op: "${a.op}" } }): "field" is required for non-count reducers`);const r=Le(i.softDeleteMode,void 0),l=F(F(n.baseWhere,n.where),r),_=await Ae(l,t,n.relationBaseWhere),h=_!==l;if(i.aggregateIndexes&&!n.baseWhere&&!h&&!r){const S=await Jt(t,i.aggregateIndexes,a,n);if(S!==void 0)return S}_i(i,t,n.by,a);const E=X(_,m(i)),u=n.by.map(S=>e`${x(S)} AS ${e.identifier(S)}`);if(a.op==="count")u.push(e`COUNT(*) AS ${e.identifier("value")}`);else{if(!a.field)throw new T("INTERNAL",`groupBy(${t}, { agg: { op: "${a.op}" } }): "field" is required for non-count reducers`);u.push(e`${e.raw(_e(a.op))}(${x(a.field)}) AS ${e.identifier("value")}`)}const p=e.join(n.by.map(S=>x(S)),e`, `);let w=e`SELECT ${e.join(u,e`, `)} FROM ${e.identifier(t)}`;E&&(w=e`${w} WHERE ${E}`),w=e`${w} GROUP BY ${p}`;const y=await A(o,d,w);return di(i,n.by,y)},async insert(t,n,i){const a=f.tables[t];if(!a)throw new T("INTERNAL",`unknown table: ${t}`);await W(),be(d.name,n);const r=oi(a,n,J);We(a,r);let l,_=!0;i?.clientId!==void 0?(vn(i.clientId),l=i.clientId):i?.allowExplicitId&&typeof r._id=="string"?l=r._id:(l=B(),_=!1);const h=i?.allowExplicitId&&typeof r._creationTime=="number"?r._creationTime:b(),E={...r,_creationTime:h,_id:l};j(t,"before","insert")&&await G("before","insert",{doc:{...E},id:l,op:"insert",table:t}),await Te(t),await ge(t);const{columns:u,values:p}=zt(a,l,h,r);return await Qt(t,e`INSERT INTO ${e.identifier(t)} (${ie(u)}) VALUES (${se(p)})`),_&&qe.set(l,t),await le(t,void 0,E),await Z(t,l,void 0,E),await fe(t,l,{document:E,written:{_creationTime:h,[Ee]:null}}),await ae(t,l,"insert",E),j(t,"after","insert")&&await G("after","insert",{doc:E,id:l,op:"insert",table:t}),l},normalizeId(t,n){return gn(f,t,n)},async patch(t,n,i,a){Fe("patch",n),be(d.name,n);const r=await ce(t,i);if(!r)throw new T("INTERNAL",`document not found: ${t}`);const l=f.tables[r];if(!l)throw new T("INTERNAL",`document not found: ${t}`);const _=Tn(l,n)?Ge:1;for(let h=0;h<_;h+=1){const E=await ve(r,t);if(await nt(r,l,t,n,E,void 0,a))return}throw new oe(`optimistic concurrency conflict on "${r}" — the row changed during this mutation; refetch and retry`,"occ")},async patchIf(t,n,i){Fe("patchIf",i.patch),be(d.name,i.patch);const a=f.tables[t];if(!a)throw new T("INTERNAL",`unknown table: ${t}`);const r=X(i.where,m(a))??e`1 = 1`;for(let l=0;l<Ge;l+=1){const[_]=await A(o,d,e`SELECT *, CASE WHEN (${r}) THEN 1 ELSE 0 END AS ${e.identifier(Mt)} FROM ${e.identifier(t)} WHERE ${e.identifier("id")} = ${n}`);if(_===void 0)return{applied:!1,doc:null};const{[Mt]:h,...E}=_;if(Number(h)!==1)return{applied:!1,doc:z(a,E)??null};const u=await nt(t,a,n,i.patch,E,r,{verify:i.verify});if(u)return{applied:!0,doc:u}}throw new oe(`patchIf on "${t}" lost the row to concurrent writes ${String(Ge)} times in a row; retry the operation`,"occ")},async restore(t,n){const i=await ce(t,n);if(!i)throw new T("INTERNAL",`document not found: ${t}`);const a=f.tables[i],r=a?.softDeleteMode?.field;if(!a||!r)throw new T("INTERNAL",`ctx.db.restore: table "${i}" is not a .softDelete() table`);const l=await ve(i,t),_=l?.[r]!==null&&l?.[r]!==void 0;if(await P.patch(t,{[r]:null},n),_){const h=z(a,l);h!==null&&await Z(i,t,void 0,{...h,[r]:null})}},query(t){const n=f.tables[t];if(!n)throw new T("INTERNAL",`unknown table: ${t}`);const i="the legacy query()/withIndex() reader is not available on the D1 (global) backend; use findMany",a=[];let r=0,l;const _=d.name!=="mysql",h={...m(n),fieldRef:w=>e`m.${x(w)}`,rangeTypeGuard:()=>{throw new T("INTERNAL","a path range is never pushed into a search")}},E=w=>a.every(y=>y(w)),u=async(w,y)=>{await W();const S=2*dn+w.filters.length,v=l===void 0?void 0:X(l,h,void 0,S),I=v!==void 0&&d.name==="sqlite"&<(d.name,v).params.length+S>jn.boundParams,M=I?void 0:v,k=r>0||I,D=await ln(o,d,n,t,M===void 0?w:{...w,scope:M},un(k?void 0:y));!k&&y===void 0&&fn(D);const U=D.filter(we=>E(we));return y===void 0?U:U.slice(0,y)},p=w=>{const y={async*[Symbol.asyncIterator](){if(!w)throw new T("INTERNAL",i);yield*await u(w,void 0)},async collect(){if(!w)throw new T("INTERNAL",i);return u(w,void 0)},async collectWithScores(){throw new T("GLOBAL_SEARCH_SCORES_UNSUPPORTED",`collectWithScores() is not supported on \`.global()\` tables (table "${t}") — relevance scores are not yet surfaced on this backend; use .collect() instead`)},filter(S){a.push(S);const v=Un(S);return v!==void 0&&xn(v,n.shape,_)?l=F(l,v):r+=1,y},async first(){if(!w)throw new T("INTERNAL",i);return(await u(w,1))[0]??null},order(){return y},async paginate(S){if(!w)throw new T("INTERNAL",i);const v=an(S);return cn(await u(w,wn(v)),v)},async take(S){if(!w)throw new T("INTERNAL",i);return u(w,S)},async unique(){if(!w)throw new T("INTERNAL",i);const S=await u(w,2);if(S.length>1)throw new Kn(`unique() on table "${t}" matched ${String(S.length)} documents; expected at most one`);return S[0]??null},withGeoIndex(){throw new T("INTERNAL",`geo indexes are not supported on \`.global()\` tables (table "${t}") — geospatial queries run only on sharded tables`)},withIndex(){throw new T("INTERNAL",i)},withSearchIndex(S,v){const I=(n.searchIndexes??[]).find(k=>k.name===S);if(!I)throw new T("INTERNAL",`unknown search index "${S}" on table "${t}"`);const M={definition:I,field:I.field,filters:[],hasQuery:!1,indexName:S,query:""};if(v(sn(M,t,nn(I.language))),!M.hasQuery)throw new T("INTERNAL",`search index "${S}" on table "${t}" requires a .search(field, query) call`);return p(M)}};return y};return p(void 0)},async rank(t,n,i){const a=f.tables[t];if(!a)throw new T("INTERNAL",`unknown table: ${t}`);const r=a.rankIndexes?.find(D=>D.name===n);if(!r)throw new T("INTERNAL",`unknown rankIndex "${n}" on table "${t}"`);if(i.restrictsCounts)throw new dt(t);if(await W(),!await De(t,r))return null;const _=typeof i.row=="string"?i.row:i.row._id;if(!_)return null;const h=he(t,r.name),E=r.sortBy.map((D,U)=>pe(U)),u=ie(["__partition__",...E]),w=(await A(o,d,e`SELECT ${u} FROM ${e.identifier(h)} WHERE ${e.identifier("__id__")} = ${_}`))[0];if(!w)return null;const y=w.__partition__,S=F(i.baseWhere,i.where);at(S,f,t,"rank");const v=ct(r,S);if(v&&Ce(r.partitionBy??[],v)!==y)return null;const I=ui(d.name,r,E,w,_),M=await A(o,d,e`SELECT COUNT(*) AS c FROM ${e.identifier(h)} WHERE ${e.identifier("__partition__")} = ${y} AND (${I})`),k=await A(o,d,e`SELECT COUNT(*) AS c FROM ${e.identifier(h)} WHERE ${e.identifier("__partition__")} = ${y}`);return{position:Number(M[0]?.c??0)+1,total:Number(k[0]?.c??0)}},async rankPage(t,n,i={}){at(F(i.baseWhere,i.where),f,t,"rankPage");const a=f.tables[t];if(!a)throw new T("INTERNAL",`unknown table: ${t}`);const r=a.rankIndexes?.find(O=>O.name===n);if(!r)throw new T("INTERNAL",`unknown rankIndex "${n}" on table "${t}"`);if(await W(),!await De(t,r))return{continueCursor:null,isDone:!0,page:[]};const _=he(t,r.name),h=r.sortBy.map((O,ee)=>pe(ee)),E=Math.max(1,Math.min(1e3,Math.floor(i.take??100))),u=F(i.baseWhere,i.where),p=ct(r,u),w=wi(r,h),y=e.join(w.flatMap(O=>Ut(d,{direction:O.direction,field:O.column,nullable:O.nullable})),e`, `),S=[];typeof i.partitionKey=="string"?S.push(e`${e.identifier("__partition__")} = ${i.partitionKey}`):p&&S.push(e`${e.identifier("__partition__")} = ${Ce(r.partitionBy??[],p)}`);const v=Sn(i);if(v!==void 0){const O=fi(d.name,w,v);O!==void 0&&S.push(O)}const I=ie([ye,"__partition__",...h]);let M=e`SELECT ${I} FROM ${e.identifier(_)}`;S.length>0&&(M=e`${M} WHERE ${e.join(S,e` AND `)}`),M=e`${M} ORDER BY ${y} LIMIT ${e.raw(String(E+1))}`;const k=await A(o,d,M),D=k.length>E,U=D?k.slice(0,E):k,we=U.map(O=>O[ye]),Ie=await $i(o,d,a,t,we);let $e=null;const H=U.at(-1);if(D&&H!==void 0){const O=[H.__partition__,...h.map(ee=>H[ee]),H[ye]];$e=hi(O)}return{continueCursor:$e,isDone:!D,page:Ie}},async replace(t,n,i,a){Fe("replace",n),be(d.name,n);const r=await ce(t,i);if(!r)throw new T("INTERNAL",`document not found: ${t}`);const l=f.tables[r];if(!l)throw new T("INTERNAL",`document not found: ${t}`);const _=await ve(r,t);if(_===void 0)throw new T("INTERNAL",`document not found: ${t}`);const E=Rn(f,r,"update")||(l.aggregateIndexes??[]).length>0||(l.rankIndexes??[]).length>0?z(l,_)??void 0:void 0,u=a?.allowExplicitId&&typeof n._creationTime=="number"?n._creationTime:void 0,p=typeof _._creationTime=="number"?_._creationTime:void 0,w=u??p??b(),y={...n,_creationTime:w,_id:t};je(l,n,y,J),We(l,y),j(r,"before","update")&&await G("before","update",{doc:{...y},id:t,op:"update",previous:E,table:r}),await Te(r),await ge(r);const S=Object.keys(l.shape),v=e.join([e`${e.identifier("_creationTime")} = ${w}`,...S.map(I=>e`${e.identifier(I)} = ${ne(l,I,y[I]??null)}`)],e`, `);await Oe(r,"UPDATE",v,_),await le(r,E,y),await Z(r,t,E,y),await fe(r,t,{document:y,previous:E,written:Be(_,w)}),await ae(r,t,"update",y),j(r,"after","update")&&await G("after","update",{doc:y,id:t,op:"update",previous:E,table:r})}};return et={db:P,scheduler:jt},P};export{Gi as createSqlCtxDb,Xi as decodeGlobalRow,Ci as readSqlCdcChangedTables,ji as readSqlCdcChanges,Kt as readSqlCdcFloor,Ri as runSqlCdcMigration,Ti as sweepSqlCdcRetention};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as h}from"@lunora/errors";import{D as I,c as vt,m as Dt,r as U,a as qt,l as lt,w as F,b as Ft}from"./ctx-db-search-state-BhAPGj25.mjs";import{ftsUnmappedPage as Ut,groupUnmappedRows as bt,ftsWriteDocument as mt,ftsPurgeDocument as pt,ftsCompanionDdl as kt,unionAll as Ht,ftsRowidMapName as Pt}from"@lunora/shard-engine";import{sql as i}from"drizzle-orm";import{q as p,n as Bt,f as V,r as O,i as L,c as X,g as M,a as T,h as ht,b as rt,j as jt,k as Wt,l as xt}from"./sql-exec-BfJ_rWEB.mjs";import{OCC_VERSION_COLUMN as Kt}from"./OCC_VERSION_COLUMN-ByC64Jgx.mjs";const Gt=n=>{const t=atob(n),e=Uint8Array.from(t,r=>r.codePointAt(0)??0);return new TextDecoder().decode(e)},Yt=()=>new h("BAD_REQUEST","invalid cursor"),ot=16,st=8,y=1024,b=(n,t)=>t.query(n),Qt=(n,t)=>{if(!t)return{exact:!0,lower:n,upper:n};const e=[...n].at(-1)??"",r=(e.codePointAt(0)??0)+1;if(r>=55296&&r<=57343||r>1114111)return{exact:!0,lower:n,upper:n};const o=n.slice(0,n.length-e.length);return{exact:!1,lower:n,upper:o+String.fromCodePoint(r)}},Ln=(n,t,e)=>{const r={eq:(o,s)=>{if(!n.definition.filterFields?.includes(o))throw new h("INTERNAL",`field "${o}" is not a filter field of search index "${n.indexName}" on table "${t}"`);if(n.filters.length>=st)throw new h("BAD_REQUEST",`search index "${n.indexName}" on table "${t}": at most ${String(st)} .eq() filters are supported per search query`);return n.filters.push({field:o,value:s}),r},search:(o,s)=>{const a=n;if(o!==a.definition.field)throw new h("INTERNAL",`search index "${a.indexName}" on table "${t}" indexes "${a.definition.field}", not "${o}"`);const f=b(s,e).length;if(f>ot)throw new h("BAD_REQUEST",`search index "${a.indexName}" on table "${t}": at most ${String(ot)} search terms are supported (got ${String(f)})`);return a.field=o,a.query=s,a.hasQuery=!0,r}};return r},Mn=n=>{if(n.length>y)throw new h("BAD_REQUEST",`more than ${String(y)} documents match this search — narrow it with filters or read it a page at a time with .paginate()`)},vn=n=>Math.min(n.offset+n.numItems+1,y),Vt=n=>btoa(`search:${String(n)}`),Xt=n=>{let t;try{t=Gt(n)}catch{return}if(!t.startsWith("search:"))return;const e=Number(t.slice(7));return Number.isInteger(e)&&e>=0?e:void 0},Dn=n=>{if(typeof n.endCursor=="string")throw new h("BAD_REQUEST","bounded (endCursor) pagination is not supported on search queries — relevance order has no stable range boundary");if(!Number.isFinite(n.numItems))throw new h("BAD_REQUEST",`search pagination needs a finite numItems, got ${String(n.numItems)}`);const t=Math.max(0,Math.floor(n.numItems)),e=n.cursor?Xt(n.cursor):0;if(e===void 0)throw Yt();if(e+t>=y)throw new h("BAD_REQUEST",`search pagination reaches the ${String(y)}-document limit (offset ${String(e)} + ${String(t)} requested) — a page must end below the cap so the probe row that answers \`hasMore\` still fits: retry with numItems ${String(Math.max(1,y-e-1))} or fewer, or narrow the query or the filters instead`);return{numItems:t,offset:e}},qn=(n,t)=>{const e=t.offset+t.numItems,r=t.numItems>0&&n.length>e;return{continueCursor:r?Vt(e):null,isDone:!r,page:n.slice(t.offset,e)}},Fn=n=>{if(n===void 0)return y+1;if(!Number.isFinite(n))return y;const t=Math.max(0,Math.floor(n));if(t>y)throw new h("BAD_REQUEST",`search returns at most ${String(y)} documents (asked for ${String(t)}) — narrow the query or paginate instead`);return t},Jt=(n,t)=>{if(!t.includes("."))return n[t];let e=n;for(const r of t.split(".")){if(e===null||typeof e!="object"||Array.isArray(e))return;e=e[r]}return e},k=(n,t)=>`${n}__fts_${t}`,S="__id__",g="__token__",A="__n__",zt=1e3,gt=(n,t)=>t.document(n),x=(n,t)=>Jt(n,t),Zt=n=>typeof n=="string"?n:n==null?"":typeof n=="number"||typeof n=="bigint"||typeof n=="boolean"?String(n):JSON.stringify(n)??"",tn=(n,t,e)=>n!==void 0&&t!==void 0&&x(n,e.field)===x(t,e.field),nn=(n,t)=>gt(Zt(x(n,t.field)),I(t.language)).slice(0,zt),q=(n,t)=>nn(n,t).join(" "),Tt=(n,t)=>{const e=new Map;for(const r of gt(n,t))e.set(r,(e.get(r)??0)+1);return e},yt=[Kt,"_creationTime"],at=50,$=(n,t)=>i`${i.identifier(n)}.${i.identifier(t)}`,v=(n,t,e)=>i`DELETE FROM ${i.identifier(n)} WHERE ${$(n,S)} = ${t}${e===void 0?i``:i` AND ${e}`}`,Rt=(n,{row:t,table:e})=>{const r=yt.map(o=>i` AND ${Bt(n.name,$(e,o),t[o]??null)}`);return i`SELECT 1 FROM ${i.identifier(e)} WHERE ${$(e,"id")} = ${t.id}${i.join(r)}${n.name==="postgres"?i` FOR SHARE`:i``}`},D=(n,t)=>i`EXISTS (${Rt(n,t)})`,H=(n,t)=>i`NOT EXISTS (SELECT 1 FROM ${i.identifier(n)} WHERE ${$(n,"id")} = ${t})`,_t=(n,t,e,r)=>r===void 0?H(t,e):D(n,{row:r,table:t}),J=async(n,t,e,r)=>{const o=new Map;for(let s=0;s<r.length;s+=at){const a=r.slice(s,s+at),f=await p(n,t,i`SELECT * FROM ${i.identifier(e)} WHERE ${$(e,"id")} IN (${i.join(a.map(u=>i`${u}`),i`, `)})`);for(const u of f)o.set(String(u.id),u)}return o},K=(n,t,e)=>n.name==="mysql"?i`${i.identifier(t)}(${i.raw(String(e))})`:n.textPatternOperatorClass===void 0?i`${i.identifier(t)}`:i`${i.identifier(t)} ${i.raw(n.textPatternOperatorClass)}`,z=512,Z=(n,t)=>({columns:i`${K(n,g,256)}, ${K(n,S,z)}`,concurrently:!0,name:`${t}__unique`,table:t,unique:!0}),j=n=>i`${n} COLLATE utf8mb4_0900_bin`,W=(n,t)=>{const e=JSON.stringify(t.map(([r,o])=>({o,t:r})));switch(n.name){case"mysql":return i`JSON_TABLE(${e}, '$[*]' COLUMNS (${i.identifier("t")} VARCHAR(256) PATH '$.t', ${i.identifier("o")} INT PATH '$.o')) AS ${i.identifier("j")}`;case"postgres":return i`json_to_recordset(${e}::json) AS ${i.identifier("j")}(${i.identifier("t")} text, ${i.identifier("o")} integer)`;default:return i`(SELECT json_extract(${$("e","value")}, '$.t') AS ${i.identifier("t")}, json_extract(${$("e","value")}, '$.o') AS ${i.identifier("o")} FROM json_each(${e}) AS ${i.identifier("e")}) AS ${i.identifier("j")}`}},Nt=(n,t,e,r,o)=>{const s=i.join([g,S,A].map(f=>i.identifier(f)),i`, `),a=f=>i`INSERT INTO ${i.identifier(t)} (${s}) SELECT ${$("j","t")}, ${e}, ${$("j","o")} FROM ${W(n,r)} WHERE ${f}`;switch(n.name){case"mysql":{const f=D(n,o),u=$(t,g),c=i.identifier("held");return[i`${a(i`${f} AND NOT EXISTS (SELECT 1 FROM ${i.identifier(t)} AS ${c} WHERE ${$("held",S)} = ${e} AND ${$("held",g)} = ${j($("j","t"))})`)} ON DUPLICATE KEY UPDATE ${$(t,A)} = ${$(t,A)}`,i`UPDATE ${i.identifier(t)} JOIN ${W(n,r)} ON ${u} = ${j($("j","t"))} SET ${$(t,A)} = ${$("j","o")} WHERE ${$(t,S)} = ${e} AND ${f}`,i`DELETE FROM ${i.identifier(t)} WHERE ${$(t,S)} = ${e} AND ${f} AND ${u} NOT IN (SELECT ${j($("j","t"))} FROM ${W(n,r)})`]}case"postgres":{const f=i.identifier("__source__"),u=i.identifier("__purged__"),c=i`EXISTS (SELECT 1 FROM ${f})`;return[i`WITH ${f} AS (${Rt(n,o)}), ${u} AS (${v(t,e,c)} RETURNING 1) ${a(i`${c} AND (SELECT COUNT(*) FROM ${u}) >= 0`)} ON CONFLICT DO NOTHING`]}default:{const f=D(n,o);return[v(t,e,f),i`${a(f)} ON CONFLICT DO NOTHING`]}}},At={uniqueKeyMissing:!1,unmappedSkipped:0},ft=new Set,ut=(n,t)=>{ft.has(n)||(ft.add(n),console.warn(`[@lunora/sql-store] ${t}`))},ct=100,dt=3,G=async(n,t,e,r=0)=>{const{companion:o,definition:s,index:a,tableName:f}=e,u={done:!0,last:r,left:0};if((await p(n,t,t.tableExists(f))).length===0)return u;const d=await p(n,t,Ut(o,ct,r));if(d.length===0)return u;const w=Math.max(...d.map(_=>Number(_.rowid))),E=bt(d),l=await J(n,t,f,[...E.keys()]),m=[];for(const[_,nt]of E){const B=l.get(_),et=B===void 0?void 0:V(s,B),it=_t(t,f,_,B);m.push(...et?mt(o,_,q(et,a),{guard:it,unmappedRowids:nt}):pt(o,_,{guard:it,unmappedRowids:nt}))}await O(n,t,m);const R=await p(n,t,i`SELECT COUNT(*) AS ${i.identifier("n")} FROM ${i.identifier(o)} WHERE ${$(o,"rowid")} > ${Math.max(0,r)} AND ${$(o,"rowid")} <= ${w}`);return{done:d.length<ct,last:w,left:Number(R[0]?.n??0)}},en=async(n,t,e)=>{let r=0,o=0;for(;;){let s=await G(n,t,e,r);for(let a=1;s.left>0&&a<dt;a+=1)s=await G(n,t,e,r);if(s.left>0&&(o+=s.left,console.warn(`[@lunora/sql-store] search migration of "${e.companion}": ${String(s.left)} row(s) lost every one of ${String(dt)} attempts to a concurrent write and were left for a later pass.`)),s.done)return o;r=s.last}},rn=async(n,t,e,r)=>r==="step"?(await G(n,t,e),At):{uniqueKeyMissing:!1,unmappedSkipped:await en(n,t,e)},Y=n=>`${n}__btree`,on=async(n,t,e)=>{const r=Z(t,e),o=await L(n,t,e,r.name);if(o!=="valid"){if(o==="absent"&&(await p(n,t,i`SELECT 1 AS ${i.identifier("present")} FROM ${i.identifier(e)} LIMIT 1`)).length===0)try{await X(n,t,{...r,concurrently:!1}),await M(n,t,e,Y(e));return}catch(a){if(await L(n,t,e,r.name).catch(()=>{})==="valid")return;ut(`${e}:empty`,`search companion "${e}": adding its unique key failed (${String(a)}); run backfillSqlSearchIndexes.`);return}ut(`${e}:missing`,`search companion "${e}" has no usable unique key, so two backfills racing over one row can index it twice. Run backfillSqlSearchIndexes, which adds it.`)}},sn=async(n,t,e)=>{const r=$(e,S),o=$(e,g);return(await p(n,t,i`SELECT ${r} AS ${i.identifier("id")}, ${o} AS ${i.identifier("token")}, COUNT(*) AS ${i.identifier("n")} FROM ${i.identifier(e)} GROUP BY ${r}, ${o} HAVING COUNT(*) > 1`)).map(a=>({count:Number(a.n),id:String(a.id),token:String(a.token)}))},an=(n,t,{count:e,id:r,token:o})=>{const s=i`${$(t,S)} = ${r} AND ${$(t,g)} = ${o}`;switch(n.name){case"mysql":return i`DELETE FROM ${i.identifier(t)} WHERE ${s} LIMIT ${i.raw(String(e-1))}`;case"postgres":return i`DELETE FROM ${i.identifier(t)} WHERE ctid = ANY (ARRAY(SELECT ctid FROM ${i.identifier(t)} WHERE ${s} OFFSET 1))`;default:return i`DELETE FROM ${i.identifier(t)} WHERE rowid IN (SELECT rowid FROM ${i.identifier(t)} WHERE ${s} LIMIT -1 OFFSET 1)`}},fn=async(n,t,e,r)=>{const{companion:o,definition:s,index:a,tableName:f}=e;for(const d of r)await T(n,t,an(t,o,d));const u=[...new Set(r.map(d=>d.id))],c=await J(n,t,f,u);for(const d of u){const w=c.get(d),E=w===void 0?void 0:V(s,w);if(w!==void 0&&E){const l=[...Tt(q(E,a),I(a.language))];await O(n,t,Nt(t,o,d,l,{row:w,table:f}));continue}await T(n,t,v(o,d,_t(t,f,d,w)))}},un=async(n,t,e)=>t.name!=="mysql"?"":(await p(n,t,i`SELECT COLUMN_NAME AS ${i.identifier("name")}, COLLATION_NAME AS ${i.identifier("collation")} FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = ${e} AND COLUMN_NAME IN (${g}, ${S})`)).filter(o=>!String(o.collation).endsWith("_bin")).map(o=>` Its ${String(o.name)} column uses ${String(o.collation)}, which treats values differing only in case or accents as one; convert it with ALTER TABLE \`${e}\` MODIFY \`${String(o.name)}\` VARCHAR(768) COLLATE utf8mb4_0900_bin NOT NULL.`).join(""),cn=async(n,t,e)=>{if(t.name!=="mysql")return 0;const r=$(e,S),o=await p(n,t,i`SELECT COUNT(*) AS ${i.identifier("n")} FROM (SELECT 1 AS ${i.identifier("x")} FROM ${i.identifier(e)} GROUP BY LEFT(${r}, ${i.raw(String(z))}), ${$(e,g)} HAVING COUNT(DISTINCT ${r}) > 1) AS ${i.identifier("shared")}`);return Number(o[0]?.n??0)},dn=async(n,t,e)=>{const r=Z(t,e),o=await L(n,t,e,r.name);if(o==="valid")return"valid";o==="invalid"&&await M(n,t,e,r.name);try{return await X(n,t,r),"built"}catch(s){const a=await L(n,t,e,r.name);if(a==="valid")return"valid";if(a==="invalid"&&await M(n,t,e,r.name),!t.isUniqueViolation(s))throw s;return"refused"}},$t=3,$n=async(n,t,e)=>{const{companion:r}=e,o=await un(n,t,r);let s="";o!==""&&console.warn(`[@lunora/sql-store] search companion "${r}" folds case and accents in its unique key.${o}`);for(let a=0;a<$t;a+=1){const f=await dn(n,t,r);if(f==="valid")return await M(n,t,r,Y(r)),!0;if(f==="refused"){const u=await sn(n,t,r);if(u.length>0)await fn(n,t,e,u);else{const c=await cn(n,t,r);s=c>0?` ${String(c)} token(s) are held by document ids that agree on their first ${String(z)} characters, which the key cannot tell apart; shorten those ids.`:o}}}return await L(n,t,r,Z(t,r).name)==="valid"?(await M(n,t,r,Y(r)),!0):(console.warn(`[@lunora/sql-store] search companion "${r}" still has no unique key after ${String($t)} attempts: writes keep working, but two backfills racing over one row can index it twice.${s}`),!1)},wn=async(n,t,e,r)=>r==="step"?At:{uniqueKeyMissing:!await $n(n,t,e),unmappedSkipped:0},Sn=(n,t)=>t?i`${i.identifier(g)} LIKE ${`${n}%`}`:i`${i.identifier(g)} = ${n}`,Ot=(n,t)=>{const e=t.filters.map(r=>i`m.${rt(r.field)} = ${jt(r.value)}`);return n.softDeleteMode&&e.push(i`m.${rt(n.softDeleteMode.field)} IS NULL`),t.scope!==void 0&&e.push(i`(${t.scope})`),e},It=async(n,t,e,r,o,s,a)=>{const f=Ot(e,o);let u=i`SELECT m.* FROM (${a}) s JOIN ${i.identifier(r)} m ON m.${i.identifier("id")} = s.${i.identifier(S)}`;return f.length>0&&(u=i`${u} WHERE ${i.join(f,i` AND `)}`),u=i`${u} ORDER BY s.${i.identifier("__score__")} DESC, m.${i.identifier("_creationTime")} DESC, m.${i.identifier("id")} ASC LIMIT ${i.raw(String(s))}`,ht(e,await p(n,t,u))},En=async(n,t,e,r,o,s)=>{const a=b(o.query,I(o.definition.language));if(a.length===0)return[];const f=k(r,o.indexName),u=a.length-1,c=a.map((m,R)=>Sn(m,R===u)),d=i.join(c,i` OR `),w=c.map(m=>i`SUM(CASE WHEN ${m} THEN ${i.identifier(A)} ELSE 0 END)`),E=i.join(w.map(m=>i`${m} > 0`),i` AND `),l=i`SELECT ${i.identifier(S)}, ${i.join(w,i` + `)} AS ${i.identifier("__score__")} FROM ${i.identifier(f)} WHERE ${d} GROUP BY ${i.identifier(S)} HAVING ${E}`;return It(n,t,e,r,o,s,l)},ln=async(n,t,e,r,o,s)=>{const a=b(o.query,I(o.definition.language));if(a.length===0)return[];const f=k(r,o.indexName),u=`${f}__vocab`,c=a.length-1,d=a.map((l,m)=>{const R=Qt(l,m===c),_=R.exact?i`${i.identifier("term")} = ${R.lower}`:i`${i.identifier("term")} >= ${R.lower} AND ${i.identifier("term")} < ${R.upper}`;return i`SELECT ${i.identifier("doc")}, ${i.raw(String(m))} AS ${i.identifier("__term__")}, COUNT(*) AS ${i.identifier("__n__")} FROM ${i.identifier(u)} WHERE ${_} GROUP BY ${i.identifier("doc")}`}),w=a.map((l,m)=>i`SUM(CASE WHEN u.${i.identifier("__term__")} = ${i.raw(String(m))} THEN u.${i.identifier("__n__")} ELSE 0 END)`),E=i`SELECT f.${i.identifier(S)} AS ${i.identifier(S)}, ${i.join(w,i` + `)} AS ${i.identifier("__score__")} FROM (${Ht(d)}) u JOIN ${i.identifier(f)} f ON f.rowid = u.${i.identifier("doc")} GROUP BY f.${i.identifier(S)} HAVING ${i.join(w.map(l=>i`${l} > 0`),i` AND `)}`;return It(n,t,e,r,o,s,E)},mn=async(n,t,e,r,o,s)=>{const a=t.nativeTextSearch,f=b(o.query,I(o.definition.language));if(!a||f.length===0)return[];const u=k(r,o.indexName),c=[a.matches(u,f),...Ot(e,o)],d=i`SELECT m.* FROM ${i.identifier(u)} JOIN ${i.identifier(r)} m ON m.${i.identifier("id")} = ${i.identifier(u)}.${i.identifier(S)} WHERE ${i.join(c,i` AND `)} ORDER BY ${a.rank(u,f)} DESC, m.${i.identifier("_creationTime")} DESC, m.${i.identifier("id")} ASC LIMIT ${i.raw(String(s))}`;return ht(e,await p(n,t,d))},pn={ensureCompanion:async(n,t,e)=>{const{integer:r,key:o}=t.companionTypes;await T(n,t,i`CREATE TABLE IF NOT EXISTS ${i.identifier(e)} (${i.identifier(g)} ${i.raw(o)} NOT NULL, ${i.identifier(S)} ${i.raw(o)} NOT NULL, ${i.identifier(A)} ${i.raw(r)} NOT NULL)`),await X(n,t,{columns:K(t,S,191),name:`${e}__by_id`,table:e,unique:!1}),await on(n,t,e)},indexDocument:async(n,t,e,r,o,s)=>{const a=[...Tt(q(r,o),I(o.language))];await O(n,t,Nt(t,e,String(s.row.id),a,s))},migrate:wn,name:"inverted",purgeDocument:async(n,t,e,r,o)=>{await T(n,t,v(e,r,H(o,r)))},runSearch:En},hn={ensureCompanion:async(n,t,e)=>{await O(n,t,kt(e))},indexDocument:async(n,t,e,r,o,s)=>{await O(n,t,mt(e,String(s.row.id),q(r,o),{guard:D(t,s)}))},migrate:rn,name:"fts5",purgeDocument:async(n,t,e,r,o)=>{await O(n,t,pt(e,r,{guard:H(o,r)}))},runSearch:ln},gn={ensureCompanion:async(n,t,e)=>{const r=t.nativeTextSearch;if(r){await T(n,t,r.createCompanion(e,t.companionTypes.key));for(const o of r.createIndexes(e))await T(n,t,o)}},indexDocument:async(n,t,e,r,o,s)=>{const a=t.nativeTextSearch;a&&await T(n,t,a.indexDocument(e,String(s.row.id),q(r,o),D(t,s)))},name:"native",purgeDocument:async(n,t,e,r,o)=>{await T(n,t,v(e,r,H(o,r)))},runSearch:mn},C=(n,t)=>n.strategy==="native"&&t.nativeTextSearch!==void 0?gn:t.supportsFts5?hn:pn,P=(n,t)=>`${vt(n)}/${C(n,t).name}`,tt=function*(n){for(const[t,e]of Object.entries(n.tables)){const r=e.searchIndexes;if(!(e.shardMode!==void 0&&e.shardMode.kind!=="global"||!r))for(const o of r)yield[t,e,o]}},N=(n,t)=>k(n,t.name),Tn=async(n,t,e,r)=>{const o=N(e,r);return lt(await U(n,t,o),P(r,t)).finished?!0:Ft(n,t,o)},Un=async(n,t,e,r,o,s)=>{if(!await Tn(n,t,r,o.definition))throw new h("SEARCH_INDEX_BUILDING",`search index "${o.indexName}" on table "${r}" is still backfilling and currently covers only part of the table — retry once it finishes${t.searchBackfillHint===void 0?"":`, or complete it now: ${t.searchBackfillHint}`}`);return C(o.definition,t).runSearch(n,t,e,r,o,s)},wt=n=>n.slice(n.lastIndexOf("/")+1),St=200,Et=5,yn=async(n,t,e,r)=>{const o=[...r.keys()],s=await p(n,t,i`SELECT * FROM ${i.identifier(e)} WHERE ${i.identifier("id")} >= ${o[0]} AND ${i.identifier("id")} <= ${o.at(-1)} ORDER BY ${i.identifier("id")} ASC`),a=new Map;for(const f of s){const u=f.id,c=r.get(u)?.row;c&&yt.some(d=>String(c[d])!==String(f[d]))&&a.set(u,{row:f})}return a},Q=async(n,t,e,r,o,s,a)=>{const f=C(s,t);let u=a;for(let c=0;u.size>0&&c<Et;c+=1){for(const{document:d,row:w}of u.values()){const E=d??V(e,w);E&&await f.indexDocument(n,t,o,E,s,{row:w,table:r})}u=await yn(n,t,r,u)}u.size>0&&console.warn(`[@lunora/sql-store] search index "${o}": ${String(u.size)} row(s) were rewritten on every one of ${String(Et)} re-check rounds and were left to their writers — each stays stale only if none of those writes changed its indexed text.`)},Ct=async(n,t,e,r,o)=>{const s=N(r,o),a=P(o,t),f=lt(await U(n,t,s),a);if(f.finished)return!0;if(f.wipe&&await F(n,t,s,void 0,!1,a),(await p(n,t,t.tableExists(r))).length===0)return await F(n,t,s,void 0,!0,a),!0;const c=await Wt(n,t,r,f.cursor,St),d=c.findLast(l=>typeof l.id=="string")?.id,w=new Map;for(const l of c)typeof l.id=="string"&&w.set(l.id,{row:l});await Q(n,t,e,r,s,o,w);const E=c.length<St;return await F(n,t,s,d??f.cursor,E,a),E},Lt=async(n,t,e)=>{await Dt(n,e);for(const[r,,o]of tt(t)){const s=N(r,o),a=P(o,e),f=await U(n,e,s);f.profile!==void 0&&wt(f.profile)!==wt(a)&&(await T(n,e,i`DROP TABLE IF EXISTS ${i.identifier(s)}`),await T(n,e,i`DROP TABLE IF EXISTS ${i.identifier(Pt(s))}`),await qt(n,e,s)),await C(o,e).ensureCompanion(n,e,s)}},Rn=async(n,t,e,r,o)=>{const s=N(r,o);if((await U(n,t,s)).profile!==void 0)return;let f=0;(await p(n,t,t.tableExists(r))).length>0&&await xt(n,t,e,r,()=>{f+=1},{limit:1}),await F(n,t,s,void 0,f===0,P(o,t))},Mt=async(n,t,e,r,o,s)=>await C(o,t).migrate?.(n,t,{companion:N(r,o),definition:e,index:o,tableName:r},s)??{uniqueKeyMissing:!1,unmappedSkipped:0},bn=async(n,t,e)=>{await Lt(n,t,e);for(const[r,o,s]of tt(t)){if(await Mt(n,e,o,r,s,"step"),s.staged){await Rn(n,e,o,r,s);continue}await Ct(n,e,o,r,s)}},kn=async(n,t,e)=>{const r={uniqueKeyMissing:[],unmappedSkipped:0};await Lt(n,t,e);for(const[o,s,a]of tt(t)){const f=await Mt(n,e,s,o,a,"drain");r.unmappedSkipped+=f.unmappedSkipped,f.uniqueKeyMissing&&r.uniqueKeyMissing.push(N(o,a));let u=!1;for(;!u;)u=await Ct(n,e,s,o,a)}return r},Hn=n=>{const{dialect:t,exec:e,schema:r}=n;return async(o,s,a)=>{const f=r.tables[o],u=f?.searchIndexes;if(!(!f||!u||u.length===0))for(const c of u){if(tn(a?.previous,a?.document,c))continue;const d=N(o,c);if(a){await Q(e,t,f,o,d,c,new Map([[s,{document:a.document,row:{...a.written,id:s}}]]));continue}await C(c,t).purgeDocument(e,t,d,s,o);const E=(await J(e,t,o,[s])).get(s);E!==void 0&&await Q(e,t,f,o,d,c,new Map([[s,{row:E}]]))}}};export{Ln as A,Dn as C,qn as R,Fn as T,Un as a,vn as b,Hn as c,kn as d,bn as r,ot as u,Mn as x};
|
package/dist/packem_shared/{ctx-db-search-state-C3IGyBzm.mjs → ctx-db-search-state-BhAPGj25.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{sql as e}from"drizzle-orm";import{a as p,q as m}from"./sql-exec-
|
|
1
|
+
import{sql as e}from"drizzle-orm";import{a as p,q as m}from"./sql-exec-BfJ_rWEB.mjs";const y=["de","en","es","fr","it","nl","none","pt"],L=i=>y.includes(i),A="a an and are as at be but by for if in into is it no not of on or such that the their then there these they this to was will with",R="aber als am an auch auf aus bei bin bis bist da dass der den des dem die das denn dir du ein eine für hat ich im in ist mit nicht noch nur oder sich sie sind über und von vor war wie wir zu zum zur",F="a al como con de del el en es la las lo los mas no o para pero por que se su sus un una uno y ya",q="au aux avec ce ces dans de des du elle en et eux il je la le les leur lui ma mais me même mes moi mon ne nos notre nous on ou par pas pour qu que qui sa se ses son sur ta te tes toi ton tu un une vos votre vous y",N="a ai al alla anche che chi ci coi col come con da dal degli dei del della di do e ed gli ha hai hanno i il in la le lo ma mi ne nei nel non o per più quale quanto se si sono su sul tra un una uno vi",_="aan al als bij dan dat de der deze die dit door een en er het hij ij in is je kan me men met mij na naar niet nog nu of om ons ook op over te tot uit van voor was wat we wij zij zijn zo",x="a ao aos as até com como da das de do dos e em entre era essa esse esta este eu foi há isso já mais mas me mesmo meu na nas no nos num numa o os ou para pela pelo por qual que quem se sem seu só sua também te tem um uma você",C=new RegExp("(?<=\\p{Script=Cyrillic})[\\u0300-\\u0305\\u0307\\u0309-\\u036F]|(?<!\\p{Script=Cyrillic})[\\u0300-\\u036F]","gu"),O=/[\u0080-\u{10FFFF}]/u,b=/[\p{L}\p{N}]+/gu,H=/[\p{Script_Extensions=Han}\p{Script_Extensions=Hiragana}\p{Script_Extensions=Katakana}\p{Script_Extensions=Hangul}]+/gu,g=/[\p{Script_Extensions=Han}\p{Script_Extensions=Hiragana}\p{Script_Extensions=Katakana}\p{Script_Extensions=Hangul}]/u,D=i=>{if(!g.test(i))return[i];const n=[];let t=0;for(const r of i.matchAll(H)){const o=r.index,s=[...r[0]];if(o>t&&n.push(i.slice(t,o)),t=o+r[0].length,s.length===1){n.push(r[0]);continue}for(let a=0;a+1<s.length;a+=1)n.push(`${String(s[a])}${String(s[a+1])}`)}return t<i.length&&n.push(i.slice(t)),n},v=i=>O.test(i)?i.normalize("NFD").replaceAll(C,"").normalize("NFC").toLowerCase():i.toLowerCase(),f=i=>new Set(v(i).split(" ")),j={de:f(R),en:f(A),es:f(F),fr:f(q),it:f(N),nl:f(_),none:new Set,pt:f(x)},z=3,U=256,w=new Map,k=i=>{const n=i!==void 0&&L(i)?i:"none",t=w.get(n);if(t)return t;const r=j[n],o=a=>{const d=v(a),$=d.match(b)??[],u=(g.test(d)?$.flatMap(l=>D(l)):$).filter(l=>l.length<=U);return r.size===0?u:u.filter(l=>!r.has(l))},s={document:o,profile:`${n}-v${String(z)}`,query:a=>{const d=o(a);return d.filter(($,u)=>d.lastIndexOf($)===u)}};return w.set(n,s),s},W=i=>`${k(i.language).profile}:${i.field}`,S=i=>{const n=i.slice(i.indexOf(":")+1),t=n.lastIndexOf("/");return t===-1?n:n.slice(0,t)},V=(i,n)=>i.profile!==n?{cursor:void 0,finished:!1,wipe:i.cursor!==void 0||i.done}:{cursor:i.cursor,finished:i.done,wipe:!1},I=(i,n)=>typeof i=="string"&&S(i)===S(n),c="__lunora_search_state",K=async(i,n)=>{const{integer:t,key:r}=n.companionTypes,o=async(s,a)=>{try{await p(i,n,e`ALTER TABLE ${e.identifier(c)} ADD COLUMN ${e.identifier(s)} ${e.raw(a)}`)}catch{}};await p(i,n,e`CREATE TABLE IF NOT EXISTS ${e.identifier(c)} (${e.identifier("companion")} ${e.raw(r)} PRIMARY KEY, ${e.identifier("cursor")} ${e.raw(r)}, ${e.identifier("done")} ${e.raw(t)} NOT NULL DEFAULT 0, ${e.identifier("profile")} ${e.raw(r)}, ${e.identifier("covered")} ${e.raw(t)} NOT NULL DEFAULT 0)`),await o("profile",r),await o("covered",`${t} NOT NULL DEFAULT 0`),await p(i,n,e`UPDATE ${e.identifier(c)} SET ${e.identifier("covered")} = 1 WHERE ${e.identifier("done")} = 1 AND ${e.identifier("covered")} = 0`)},T=i=>i===1||i===!0||i==="1",P=async(i,n,t)=>{const r=await m(i,n,e`SELECT ${e.identifier("covered")} FROM ${e.identifier(c)} WHERE ${e.identifier("companion")} = ${t}`);return T(r[0]?.covered)},Y=async(i,n,t)=>{await p(i,n,e`DELETE FROM ${e.identifier(c)} WHERE ${e.identifier("companion")} = ${t}`)},X=async(i,n,t)=>{const o=(await m(i,n,e`SELECT ${e.identifier("cursor")}, ${e.identifier("done")}, ${e.identifier("profile")} FROM ${e.identifier(c)} WHERE ${e.identifier("companion")} = ${t}`))[0];if(!o)return{cursor:void 0,done:!1,profile:void 0};const{cursor:s,profile:a}=o;return{cursor:typeof s=="string"?s:void 0,done:T(o.done),profile:typeof a=="string"?a:void 0}},G=async(i,n,t,r,o,s)=>{const a=r??null,d=await m(i,n,e`SELECT ${e.identifier("profile")} FROM ${e.identifier(c)} WHERE ${e.identifier("companion")} = ${t}`),$=I(d[0]?.profile,s),u=o?1:0,l=o||!$?e`${e.identifier("covered")} = ${u}`:e`${e.identifier("covered")} = ${e.identifier("covered")}`,h=e`UPDATE ${e.identifier(c)} SET ${e.identifier("cursor")} = ${a}, ${e.identifier("done")} = ${u}, ${e.identifier("profile")} = ${s}, ${l} WHERE ${e.identifier("companion")} = ${t}`;if(d.length>0){await p(i,n,h);return}try{await p(i,n,e`INSERT INTO ${e.identifier(c)} (${e.identifier("companion")}, ${e.identifier("cursor")}, ${e.identifier("done")}, ${e.identifier("profile")}, ${e.identifier("covered")}) VALUES (${t}, ${a}, ${o?1:0}, ${s}, ${o?1:0})`)}catch(E){if(!n.isUniqueViolation(E))throw E;await p(i,n,h)}};export{k as D,c as S,Y as a,P as b,W as c,V as l,K as m,X as r,G as w};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{B as l,b as o,c as r,z as t,f as n,h as d,g as i,v as u,l as f,i as R,u as q,n as c,m,o as p,p as x,y as C,d as I,q as S,e as h,a as w,k as E,r as y,j as z,s as B,x as L,t as N}from"./sql-exec-BfJ_rWEB.mjs";import"./value-codec-DPoUomF-.mjs";import{OCC_VERSION_COLUMN as V}from"./OCC_VERSION_COLUMN-ByC64Jgx.mjs";export{l as BACKFILL_BATCH_SIZE,V as OCC_VERSION_COLUMN,o as columnRefSql,r as createIndexIfNotExists,t as decodeGlobalRow,n as decodeRow,d as decodeRows,i as dropIndexIfExists,u as fieldRefSql,f as forEachRowPaged,R as indexState,q as nextRowVersion,c as nullSafeEqualsSql,m as pathContainsNeedle,p as pathInList,x as pathTextReference,C as pathTypeGuardSql,I as qualifiedColumnRefSql,S as queryAll,h as queryBatch,w as queryRun,E as readRowsPage,y as runInOrder,z as serializeColumnValue,B as serializeDocumentColumn,L as serializeFieldValue,N as tableColumns};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{LunoraError as O}from"@lunora/errors";import{renderSql as F,aggregateTableName as j,rankTableName as K,bigintSqlKey as G,sortColumnName as N}from"@lunora/shard-engine";import{sql as t}from"drizzle-orm";import{e as Y,a as g,B as R,r as H,i as V,U as W,b as X}from"./value-codec-DPoUomF-.mjs";import{O as _,t as Q,a as m,q as h,c as w,b as d,d as z,s as J,e as Z}from"./sql-exec-BmMqDIi8.mjs";const nn=new Set(["any","null"]),C=(e,n)=>{const i=n.kindOf(e);return i!==void 0&&nn.has(i)||n.nullableOf(e)?!0:i==="union"&&(n.membersOf(e)??[]).some(o=>C(o,n))},T=e=>{const n=e._meta?.inner;return e.kind==="optional"&&n?T(n):e},L=e=>C(e,{kindOf:Y,membersOf:n=>T(n)._meta?.members,nullableOf:n=>T(n)._meta?.column?.notNull===!1}),q=(e,n,i=!1)=>n.columnType(g(e),{unique:i||e._meta?.column?.unique===!0}),v=e=>{const n=new Set;for(const i of e.indexes)i.unique===!0&&i.fields.length===1&&n.add(i.fields[0]);return n},en=(e,n,i)=>{if(i.indexKeyPrefix!==void 0)for(const o of n.indexes){if(o.unique!==!0||o.fields.length<=1)continue;const r=o.fields.filter(s=>{const a=n.shape[s];return a!==void 0&&i.indexKeyPrefix?.(g(a))!==void 0});if(r.length>0)throw new Error(`${e}.${o.name}: a composite unique index cannot cover ${r.join(", ")} in full on this engine (its key limit forces a prefix, which would constrain the prefix rather than the value). Split it into single-column unique indexes, or store those fields as a bounded type.`)}},tn=e=>e._meta?.column?.notNull===!0&&e.kind!=="optional"&&!L(e),on=(e,n,i)=>{const o=[],r=v(n);for(const[l,c]of Object.entries(n.shape)){if(!c._meta?.column)continue;const f=tn(c)?" NOT NULL":"";o.push(t`${t.identifier(l)} ${t.raw(`${q(c,i,r.has(l))}${f}`)}`)}const s=[...i.frameworkColumns().map(l=>t`${t.identifier(l.name)} ${t.raw(l.type)}`),t`${t.identifier(_)} ${t.raw(i.companionTypes.integer)}`],a=s.length+o.length,u=i.maxTableColumns;if(u!==void 0&&a>u){const l=a-1===u,c="Move one or more fields into a single object field, or split the table — either way the existing rows need a data migration (`defineMigration` + `lunora migrate up`); there is no in-place path.";throw new O("VALIDATION_ERROR",`@lunora/sql-store: global table "${e}" needs ${String(a)} columns, over this engine's ${String(u)}-column limit. ${l?`One of them is "${_}", the row version every guarded write reads, which caps declared fields at ${String(u-s.length)}. A table provisioned at ${String(u)} columns before that column existed cannot be widened to hold it. `:""}${c}`)}return t.join([...s,...o],t`, `)},rn=e=>{if(e.indexKeyPrefix?.("string")===void 0)return t`${d("_creationTime")}, ${d("id")}`},x=async(e,n,i,o)=>{const r=t.join(i.refs.map(a=>t`${a} IS NOT NULL`),t` AND `);if((await h(e,n,t`SELECT ${i.columns} FROM ${t.identifier(i.table)} WHERE ${r} GROUP BY ${i.columns} HAVING COUNT(*) > 1 LIMIT 1`)).length>0)throw new O("INTERNAL",`unique index "${i.name}" on "${i.table}" ${o}: existing rows are duplicates under it. De-duplicate the table with a data migration first.`)},sn=async(e,n,i)=>{if(!i.unique){await w(e,n,i);return}try{await w(e,n,i)}catch(o){throw n.isUniqueViolation(o)&&await x(e,n,i,"cannot be created"),o}},U=e=>{const n=e.indexOf("(");return n===-1?void 0:e.slice(n,e.lastIndexOf(")")+1)},an=(e,n)=>{const i=n.unique?t`UNIQUE `:t``;return U(F(e.name,t`CREATE ${i}INDEX ${t.identifier(n.name)} ON ${t.identifier(n.table)} (${n.columns})`).sql)},un=(e,n,i)=>{const o=an(e,i);return o!==void 0&&o!==U(n)},ln=async(e,n,i)=>{if(n.name!=="sqlite")return;const r=(await h(e,n,t`SELECT sql FROM sqlite_master WHERE type = 'index' AND name = ${i.name} AND tbl_name = ${i.table}`))[0]?.sql;typeof r=="string"&&un(n,r,i)&&(i.unique&&await x(e,n,i,"cannot be re-created with its new column list; the previous index is left in place"),await m(e,n,t`DROP INDEX IF EXISTS ${t.identifier(i.name)}`))},cn=(e,n,i)=>{en(e,n,i);const o=v(n),r=u=>{const l=d(u),c=n.shape[u],f=c&&i.indexKeyPrefix&&c._meta?.column?.unique!==!0&&!o.has(u)?i.indexKeyPrefix(g(c)):void 0;return f===void 0?l:t`${l}(${t.raw(String(f))})`},s=rn(i),a=[];for(const u of n.indexes){const l=u.fields.map($=>r($)),c=t.join(l,t`, `),f=u.unique??!1;a.push({columns:f||s===void 0?c:t`${c}, ${s}`,kind:"declared",name:`${e}_${u.name}`,refs:l,table:e,unique:f})}s!==void 0&&a.push({columns:s,kind:"default-order",name:`${e}__by_creation`,refs:[],table:e,unique:!1});for(const[u,l]of Q(n)){if(!l.unique)continue;const c=r(u);a.push({columns:c,kind:"unique-column",name:`${e}_unique_${u}`,refs:[c],table:e,unique:!0})}return a},fn=async(e,n,i,o)=>{for(const r of cn(n,i,o)){if(r.kind==="default-order"){await w(e,o,r);continue}r.kind==="declared"&&await ln(e,o,r),await sn(e,o,r)}},A="__lunora_migration_state",dn=async(e,n)=>{await m(e,n,t`CREATE TABLE IF NOT EXISTS ${t.identifier(A)} (${t.identifier("name")} ${t.raw(n.companionTypes.key)} PRIMARY KEY)`)},mn=async(e,n,i)=>(await h(e,n,t`SELECT ${t.identifier("name")} FROM ${t.identifier(A)} WHERE ${t.identifier("name")} = ${i}`)).length>0,$n=async(e,n,i,o,r,s)=>{r>0&&s!==void 0&&console.warn(`[@lunora/sql-store] storage migration "${i}" on "${o}": ${String(r)} row(s) ${s} and were left as stored — range filters and ORDER BY over them stay wrong until they are corrected by hand.`);try{await m(e,n,t`INSERT INTO ${t.identifier(A)} (${t.identifier("name")}) VALUES (${i})`)}catch(a){if(!n.isUniqueViolation(a))throw a}},gn=100,hn=(e,n)=>{const i=[],o=[];for(const r of n.fields){const s=e[r],a=n.convert(s);a!==void 0&&(i.push(t`${d(r)} = ${a}`),o.push(t`${d(r)} = ${s}`))}return{assignments:i,guards:o}},pn=e=>t.join(e.fields.map(n=>e.probe(n)),t` OR `),k=async(e,n,i,o)=>{if(o.fields.length===0||(await dn(e,i),await mn(e,i,o.marker)))return;const r=pn(o),s=t.join([d("id"),...o.fields.map(l=>d(l))],t`, `);let a="",u=0;for(;;){const l=await h(e,i,t`SELECT ${s} FROM ${t.identifier(n)} WHERE (${r}) AND ${d("id")} > ${a} ORDER BY ${d("id")} LIMIT ${t.raw(String(gn))}`);if(l.length===0){await $n(e,i,o.marker,n,u,o.describeUnconvertible);return}const c=[];for(const $ of l){const{id:p}=$,{assignments:S,guards:P}=typeof p=="string"?hn($,o):{assignments:[],guards:[]};if(S.length===0){u+=1;continue}c.push(t`UPDATE ${t.identifier(n)} SET ${t.join(S,t`, `)} WHERE ${d("id")} = ${p} AND ${t.join(P,t` AND `)}`)}await Z(e,i,c);const f=l.at(-1)?.id;if(typeof f!="string")return;a=f}},b=e=>`'${e}%'`,wn=e=>Object.entries(e.shape).filter(([,n])=>n._meta?.column!==void 0&&g(n)==="bigint").map(([n])=>n),En=e=>Object.entries(e.shape).filter(([,n])=>n._meta?.column!==void 0&&V(g(n))).map(([n])=>n),D=(e,n)=>({convert:i=>{if(!(typeof i!="string"||i.length===R))try{return G(BigInt(i))}catch{return}},describeUnconvertible:"hold a value the order-preserving key cannot represent (non-numeric text, or a magnitude past 39 digits)",fields:wn(n),marker:`bigint-key:${e}`,probe:i=>t`(${d(i)} IS NOT NULL AND LENGTH(${d(i)}) <> ${R})`}),yn=async(e,n,i,o)=>k(e,n,o,D(n,i)),M=(e,n)=>({convert:H,fields:En(n),marker:`untyped-number-key:${e}`,probe:i=>t`(${d(i)} LIKE ${t.raw(b(W))} AND ${d(i)} NOT LIKE ${t.raw(b(X))})`}),_n=async(e,n,i,o)=>k(e,n,o,M(n,i)),I=new Set,E=(e,n)=>{I.has(e)||(I.add(e),console.warn(`[@lunora/sql-store] ${n}`))},Tn=e=>{const n=e._meta?.column;return n?.defaultFn?n.defaultFn():n&&"defaultValue"in n?n.defaultValue:void 0},Ln=(e,n,i)=>i._meta?.column?.unique===!0||e.indexes.some(o=>o.unique===!0&&o.fields.includes(n)),An=async(e,n,i,o,r,s)=>{if(s.kind==="optional"||L(s))return;const a=Ln(i,r,s),u=a?void 0:Tn(s),l=`UPDATE "${n}" SET "${r}" = … WHERE "${r}" IS NULL`;if(u===void 0){const c=a?"is unique, so one default cannot be written to every row":"has no default";E(`backfill:${n}.${r}`,`"${n}.${r}" was added as a required field that ${c}, so rows written before it read NULL. Backfill it with a migration (${l}).`);return}try{await m(e,o,t`UPDATE ${t.identifier(n)} SET ${t.identifier(r)} = ${J(i,r,u)} WHERE ${t.identifier(r)} IS NULL`)}catch(c){E(`backfill:${n}.${r}`,`could not backfill "${n}.${r}" from its default (${c instanceof Error?c.message:String(c)}); rows written before it read NULL. Run ${l}.`)}},Sn=(e,n)=>[[_,n.companionTypes.integer],...Object.entries(e.shape).filter(([,i])=>i._meta?.column!==void 0).map(([i,o])=>[i,q(o,n),o])],Rn=async(e,n,i,o)=>{const r=Sn(i,o),s="t",a=async u=>{try{return await h(e,o,t`SELECT ${t.join(u.map(l=>z(s,l)),t`, `)} FROM ${t.identifier(n)} AS ${t.identifier(s)} LIMIT 0`),!0}catch{return!1}};if(!await a(r.map(([u])=>u)))for(const[u,l,c]of r)await a([u])||(await m(e,o,t`ALTER TABLE ${t.identifier(n)} ADD COLUMN ${t.identifier(u)} ${t.raw(l)}`),c!==void 0&&await An(e,n,i,o,u,c))},bn=(e,n,i)=>{const o=typeof i.charset=="string"?` CHARACTER SET ${i.charset} COLLATE ${String(i.collation)}`:"";return`ALTER TABLE \`${e}\` MODIFY COLUMN \`${n}\` ${String(i.type)}${o} NULL`},In=async(e,n,i,o)=>{if(o.name==="sqlite")return;const r=Object.keys(i.shape).filter(s=>{const a=i.shape[s];return a._meta?.column?.notNull===!0&&a.kind!=="optional"&&L(a)});if(r.length!==0)try{const s=o.name==="postgres"?t`column_name AS ${t.identifier("name")}`:t`column_name AS ${t.identifier("name")}, column_type AS ${t.identifier("type")}, character_set_name AS ${t.identifier("charset")}, collation_name AS ${t.identifier("collation")}`,a=o.name==="postgres"?t`table_schema = ANY (current_schemas(false))`:t`table_schema = DATABASE()`,u=await h(e,o,t`SELECT ${s} FROM information_schema.columns WHERE ${a} AND table_name = ${n} AND is_nullable = 'NO' AND column_name IN (${t.join(r.map(l=>t`${l}`),t`, `)})`);for(const l of u){const c=String(l.name);if(o.name==="postgres"){await m(e,o,t`ALTER TABLE ${t.identifier(n)} ALTER COLUMN ${t.identifier(c)} DROP NOT NULL`);continue}E(`${n}.${c}`,`"${n}"."${c}" accepts null in the schema but its column is NOT NULL, so writing null there fails. Relaxing it on MySQL can rebuild the table, so it is not done at startup; run this once, in a maintenance window: ${bn(n,c,l)};`)}}catch(s){E(`${n}:relax-failed`,`could not relax NOT NULL on the null-accepting columns of "${n}" (${r.join(", ")}): ${s instanceof Error?s.message:String(s)}. Writing null to them fails until the constraint is dropped by hand.`)}},On=async(e,n,i,o)=>{const r=on(n,i,o);await m(e,o,t`CREATE TABLE IF NOT EXISTS ${t.identifier(n)} (${r})`),await Rn(e,n,i,o),await In(e,n,i,o),await fn(e,n,i,o),await yn(e,n,i,o),await _n(e,n,i,o)},Dn=(e,n)=>[D(e,n),M(e,n)].filter(i=>i.fields.length>0),Mn=async(e,n,i,o)=>{for(const[r,s]of Object.entries(n.tables))s.shardMode?.kind!=="global"||o!==void 0&&!o.has(r)||await On(e,r,s,i)},B=e=>e.shardMode===void 0||e.shardMode.kind==="global",Bn=async(e,n,i)=>{const{integer:o,key:r,real:s}=i.companionTypes;for(const[a,u]of Object.entries(n.tables)){const l=u.aggregateIndexes;if(!(!l||l.length===0||!B(u)))for(const c of l){const f=j(a,c.name);await m(e,i,t`CREATE TABLE IF NOT EXISTS ${t.identifier(f)} (${t.identifier("__key__")} ${t.raw(r)} PRIMARY KEY, ${t.identifier("__value__")} ${t.raw(s)}, ${t.identifier("__count__")} ${t.raw(o)} NOT NULL DEFAULT 0)`),i.name==="sqlite"&&((await h(e,i,t`PRAGMA table_info(${t.identifier(f)})`)).some(p=>p.name==="__count__")||await m(e,i,t`ALTER TABLE ${t.identifier(f)} ADD COLUMN ${t.identifier("__count__")} ${t.raw(o)} NOT NULL DEFAULT 0`))}}},y=(e,n,i,o)=>{const r=e.name==="mysql"&&o?t`${t.identifier(n)}(191)`:t`${t.identifier(n)}`;return t`${r} ${t.raw(i)}`},Nn=(e,n,i)=>{const o=[y(e,"__partition__","ASC",!0)];for(const[r,s]of n.sortBy.entries()){const a=i.shape[s.field],u=a!==void 0&&e.indexKeyPrefix?.(g(a))!==void 0;o.push(y(e,N(r),s.direction==="desc"?"DESC":"ASC",u))}return o.push(y(e,"__id__","ASC",!0)),o},Cn=(e,n,i)=>n.sortBy.map((o,r)=>{const s=i.shape[o.field],a=e.columnType(s?g(s):void 0);return t`${t.identifier(N(r))} ${t.raw(a)}`}),Pn=async(e,n,i)=>{const{key:o}=i.companionTypes;for(const[r,s]of Object.entries(n.tables)){const a=s.rankIndexes;if(!(!a||a.length===0||!B(s)))for(const u of a){const l=K(r,u.name),c=Cn(i,u,s),f=c.length>0?t`, ${t.join(c,t`, `)}`:t``;await m(e,i,t`CREATE TABLE IF NOT EXISTS ${t.identifier(l)} (${t.identifier("__id__")} ${t.raw(o)} PRIMARY KEY, ${t.identifier("__partition__")} ${t.raw(o)} NOT NULL${f})`);const $=Nn(i,u,s),p=`${r}__rank_${u.name}__btree`;await w(e,i,{columns:t.join($,t`, `),name:p,table:l,unique:!1})}}};export{A as MIGRATION_STATE_TABLE,an as declaredIndexColumnList,on as globalTableColumnsDdl,cn as globalTableIndexSpecs,U as indexColumnList,un as indexShapeChanged,Dn as legacyRewrites,pn as legacyRowPredicate,On as provisionGlobalTable,Mn as provisionGlobalTablesSequentially,Bn as runSqlAggregateMigrations,Pn as runSqlRankMigrations,Sn as wantedGlobalColumns};
|
|
1
|
+
import{LunoraError as O}from"@lunora/errors";import{renderSql as F,aggregateTableName as j,rankTableName as K,bigintSqlKey as G,sortColumnName as N}from"@lunora/shard-engine";import{sql as t}from"drizzle-orm";import{e as Y,a as p,B as R,r as H,i as V,U as W,b as X}from"./value-codec-DPoUomF-.mjs";import{t as Q,a as m,q as g,c as w,b as d,d as z,s as J,e as Z}from"./sql-exec-BfJ_rWEB.mjs";import{OCC_VERSION_COLUMN as _}from"./OCC_VERSION_COLUMN-ByC64Jgx.mjs";const nn=new Set(["any","null"]),C=(e,n)=>{const i=n.kindOf(e);return i!==void 0&&nn.has(i)||n.nullableOf(e)?!0:i==="union"&&(n.membersOf(e)??[]).some(o=>C(o,n))},T=e=>{const n=e._meta?.inner;return e.kind==="optional"&&n?T(n):e},L=e=>C(e,{kindOf:Y,membersOf:n=>T(n)._meta?.members,nullableOf:n=>T(n)._meta?.column?.notNull===!1}),q=(e,n,i=!1)=>n.columnType(p(e),{unique:i||e._meta?.column?.unique===!0}),v=e=>{const n=new Set;for(const i of e.indexes)i.unique===!0&&i.fields.length===1&&n.add(i.fields[0]);return n},en=(e,n,i)=>{if(i.indexKeyPrefix!==void 0)for(const o of n.indexes){if(o.unique!==!0||o.fields.length<=1)continue;const r=o.fields.filter(s=>{const a=n.shape[s];return a!==void 0&&i.indexKeyPrefix?.(p(a))!==void 0});if(r.length>0)throw new Error(`${e}.${o.name}: a composite unique index cannot cover ${r.join(", ")} in full on this engine (its key limit forces a prefix, which would constrain the prefix rather than the value). Split it into single-column unique indexes, or store those fields as a bounded type.`)}},tn=e=>e._meta?.column?.notNull===!0&&e.kind!=="optional"&&!L(e),on=(e,n,i)=>{const o=[],r=v(n);for(const[l,c]of Object.entries(n.shape)){if(!c._meta?.column)continue;const f=tn(c)?" NOT NULL":"";o.push(t`${t.identifier(l)} ${t.raw(`${q(c,i,r.has(l))}${f}`)}`)}const s=[...i.frameworkColumns().map(l=>t`${t.identifier(l.name)} ${t.raw(l.type)}`),t`${t.identifier(_)} ${t.raw(i.companionTypes.integer)}`],a=s.length+o.length,u=i.maxTableColumns;if(u!==void 0&&a>u){const l=a-1===u,c="Move one or more fields into a single object field, or split the table — either way the existing rows need a data migration (`defineMigration` + `lunora migrate up`); there is no in-place path.";throw new O("VALIDATION_ERROR",`@lunora/sql-store: global table "${e}" needs ${String(a)} columns, over this engine's ${String(u)}-column limit. ${l?`One of them is "${_}", the row version every guarded write reads, which caps declared fields at ${String(u-s.length)}. A table provisioned at ${String(u)} columns before that column existed cannot be widened to hold it. `:""}${c}`)}return t.join([...s,...o],t`, `)},rn=e=>{if(e.indexKeyPrefix?.("string")===void 0)return t`${d("_creationTime")}, ${d("id")}`},x=async(e,n,i,o)=>{const r=t.join(i.refs.map(a=>t`${a} IS NOT NULL`),t` AND `);if((await g(e,n,t`SELECT ${i.columns} FROM ${t.identifier(i.table)} WHERE ${r} GROUP BY ${i.columns} HAVING COUNT(*) > 1 LIMIT 1`)).length>0)throw new O("INTERNAL",`unique index "${i.name}" on "${i.table}" ${o}: existing rows are duplicates under it. De-duplicate the table with a data migration first.`)},sn=async(e,n,i)=>{if(!i.unique){await w(e,n,i);return}try{await w(e,n,i)}catch(o){throw n.isUniqueViolation(o)&&await x(e,n,i,"cannot be created"),o}},U=e=>{const n=e.indexOf("(");return n===-1?void 0:e.slice(n,e.lastIndexOf(")")+1)},an=(e,n)=>{const i=n.unique?t`UNIQUE `:t``;return U(F(e.name,t`CREATE ${i}INDEX ${t.identifier(n.name)} ON ${t.identifier(n.table)} (${n.columns})`).sql)},un=(e,n,i)=>{const o=an(e,i);return o!==void 0&&o!==U(n)},ln=async(e,n,i)=>{if(n.name!=="sqlite")return;const r=(await g(e,n,t`SELECT sql FROM sqlite_master WHERE type = 'index' AND name = ${i.name} AND tbl_name = ${i.table}`))[0]?.sql;typeof r=="string"&&un(n,r,i)&&(i.unique&&await x(e,n,i,"cannot be re-created with its new column list; the previous index is left in place"),await m(e,n,t`DROP INDEX IF EXISTS ${t.identifier(i.name)}`))},cn=(e,n,i)=>{en(e,n,i);const o=v(n),r=u=>{const l=d(u),c=n.shape[u],f=c&&i.indexKeyPrefix&&c._meta?.column?.unique!==!0&&!o.has(u)?i.indexKeyPrefix(p(c)):void 0;return f===void 0?l:t`${l}(${t.raw(String(f))})`},s=rn(i),a=[];for(const u of n.indexes){const l=u.fields.map($=>r($)),c=t.join(l,t`, `),f=u.unique??!1;a.push({columns:f||s===void 0?c:t`${c}, ${s}`,kind:"declared",name:`${e}_${u.name}`,refs:l,table:e,unique:f})}s!==void 0&&a.push({columns:s,kind:"default-order",name:`${e}__by_creation`,refs:[],table:e,unique:!1});for(const[u,l]of Q(n)){if(!l.unique)continue;const c=r(u);a.push({columns:c,kind:"unique-column",name:`${e}_unique_${u}`,refs:[c],table:e,unique:!0})}return a},fn=async(e,n,i,o)=>{for(const r of cn(n,i,o)){if(r.kind==="default-order"){await w(e,o,r);continue}r.kind==="declared"&&await ln(e,o,r),await sn(e,o,r)}},A="__lunora_migration_state",dn=async(e,n)=>{await m(e,n,t`CREATE TABLE IF NOT EXISTS ${t.identifier(A)} (${t.identifier("name")} ${t.raw(n.companionTypes.key)} PRIMARY KEY)`)},mn=async(e,n,i)=>(await g(e,n,t`SELECT ${t.identifier("name")} FROM ${t.identifier(A)} WHERE ${t.identifier("name")} = ${i}`)).length>0,$n=async(e,n,i,o,r,s)=>{r>0&&s!==void 0&&console.warn(`[@lunora/sql-store] storage migration "${i}" on "${o}": ${String(r)} row(s) ${s} and were left as stored — range filters and ORDER BY over them stay wrong until they are corrected by hand.`);try{await m(e,n,t`INSERT INTO ${t.identifier(A)} (${t.identifier("name")}) VALUES (${i})`)}catch(a){if(!n.isUniqueViolation(a))throw a}},pn=100,gn=(e,n)=>{const i=[],o=[];for(const r of n.fields){const s=e[r],a=n.convert(s);a!==void 0&&(i.push(t`${d(r)} = ${a}`),o.push(t`${d(r)} = ${s}`))}return{assignments:i,guards:o}},hn=e=>t.join(e.fields.map(n=>e.probe(n)),t` OR `),k=async(e,n,i,o)=>{if(o.fields.length===0||(await dn(e,i),await mn(e,i,o.marker)))return;const r=hn(o),s=t.join([d("id"),...o.fields.map(l=>d(l))],t`, `);let a="",u=0;for(;;){const l=await g(e,i,t`SELECT ${s} FROM ${t.identifier(n)} WHERE (${r}) AND ${d("id")} > ${a} ORDER BY ${d("id")} LIMIT ${t.raw(String(pn))}`);if(l.length===0){await $n(e,i,o.marker,n,u,o.describeUnconvertible);return}const c=[];for(const $ of l){const{id:h}=$,{assignments:S,guards:P}=typeof h=="string"?gn($,o):{assignments:[],guards:[]};if(S.length===0){u+=1;continue}c.push(t`UPDATE ${t.identifier(n)} SET ${t.join(S,t`, `)} WHERE ${d("id")} = ${h} AND ${t.join(P,t` AND `)}`)}await Z(e,i,c);const f=l.at(-1)?.id;if(typeof f!="string")return;a=f}},b=e=>`'${e}%'`,wn=e=>Object.entries(e.shape).filter(([,n])=>n._meta?.column!==void 0&&p(n)==="bigint").map(([n])=>n),En=e=>Object.entries(e.shape).filter(([,n])=>n._meta?.column!==void 0&&V(p(n))).map(([n])=>n),D=(e,n)=>({convert:i=>{if(!(typeof i!="string"||i.length===R))try{return G(BigInt(i))}catch{return}},describeUnconvertible:"hold a value the order-preserving key cannot represent (non-numeric text, or a magnitude past 39 digits)",fields:wn(n),marker:`bigint-key:${e}`,probe:i=>t`(${d(i)} IS NOT NULL AND LENGTH(${d(i)}) <> ${R})`}),yn=async(e,n,i,o)=>k(e,n,o,D(n,i)),M=(e,n)=>({convert:H,fields:En(n),marker:`untyped-number-key:${e}`,probe:i=>t`(${d(i)} LIKE ${t.raw(b(W))} AND ${d(i)} NOT LIKE ${t.raw(b(X))})`}),_n=async(e,n,i,o)=>k(e,n,o,M(n,i)),I=new Set,E=(e,n)=>{I.has(e)||(I.add(e),console.warn(`[@lunora/sql-store] ${n}`))},Tn=e=>{const n=e._meta?.column;return n?.defaultFn?n.defaultFn():n&&"defaultValue"in n?n.defaultValue:void 0},Ln=(e,n,i)=>i._meta?.column?.unique===!0||e.indexes.some(o=>o.unique===!0&&o.fields.includes(n)),An=async(e,n,i,o,r,s)=>{if(s.kind==="optional"||L(s))return;const a=Ln(i,r,s),u=a?void 0:Tn(s),l=`UPDATE "${n}" SET "${r}" = … WHERE "${r}" IS NULL`;if(u===void 0){const c=a?"is unique, so one default cannot be written to every row":"has no default";E(`backfill:${n}.${r}`,`"${n}.${r}" was added as a required field that ${c}, so rows written before it read NULL. Backfill it with a migration (${l}).`);return}try{await m(e,o,t`UPDATE ${t.identifier(n)} SET ${t.identifier(r)} = ${J(i,r,u)} WHERE ${t.identifier(r)} IS NULL`)}catch(c){E(`backfill:${n}.${r}`,`could not backfill "${n}.${r}" from its default (${c instanceof Error?c.message:String(c)}); rows written before it read NULL. Run ${l}.`)}},Sn=(e,n)=>[[_,n.companionTypes.integer],...Object.entries(e.shape).filter(([,i])=>i._meta?.column!==void 0).map(([i,o])=>[i,q(o,n),o])],Rn=async(e,n,i,o)=>{const r=Sn(i,o),s="t",a=async u=>{try{return await g(e,o,t`SELECT ${t.join(u.map(l=>z(s,l)),t`, `)} FROM ${t.identifier(n)} AS ${t.identifier(s)} LIMIT 0`),!0}catch{return!1}};if(!await a(r.map(([u])=>u)))for(const[u,l,c]of r)await a([u])||(await m(e,o,t`ALTER TABLE ${t.identifier(n)} ADD COLUMN ${t.identifier(u)} ${t.raw(l)}`),c!==void 0&&await An(e,n,i,o,u,c))},bn=(e,n,i)=>{const o=typeof i.charset=="string"?` CHARACTER SET ${i.charset} COLLATE ${String(i.collation)}`:"";return`ALTER TABLE \`${e}\` MODIFY COLUMN \`${n}\` ${String(i.type)}${o} NULL`},In=async(e,n,i,o)=>{if(o.name==="sqlite")return;const r=Object.keys(i.shape).filter(s=>{const a=i.shape[s];return a._meta?.column?.notNull===!0&&a.kind!=="optional"&&L(a)});if(r.length!==0)try{const s=o.name==="postgres"?t`column_name AS ${t.identifier("name")}`:t`column_name AS ${t.identifier("name")}, column_type AS ${t.identifier("type")}, character_set_name AS ${t.identifier("charset")}, collation_name AS ${t.identifier("collation")}`,a=o.name==="postgres"?t`table_schema = ANY (current_schemas(false))`:t`table_schema = DATABASE()`,u=await g(e,o,t`SELECT ${s} FROM information_schema.columns WHERE ${a} AND table_name = ${n} AND is_nullable = 'NO' AND column_name IN (${t.join(r.map(l=>t`${l}`),t`, `)})`);for(const l of u){const c=String(l.name);if(o.name==="postgres"){await m(e,o,t`ALTER TABLE ${t.identifier(n)} ALTER COLUMN ${t.identifier(c)} DROP NOT NULL`);continue}E(`${n}.${c}`,`"${n}"."${c}" accepts null in the schema but its column is NOT NULL, so writing null there fails. Relaxing it on MySQL can rebuild the table, so it is not done at startup; run this once, in a maintenance window: ${bn(n,c,l)};`)}}catch(s){E(`${n}:relax-failed`,`could not relax NOT NULL on the null-accepting columns of "${n}" (${r.join(", ")}): ${s instanceof Error?s.message:String(s)}. Writing null to them fails until the constraint is dropped by hand.`)}},On=async(e,n,i,o)=>{const r=on(n,i,o);await m(e,o,t`CREATE TABLE IF NOT EXISTS ${t.identifier(n)} (${r})`),await Rn(e,n,i,o),await In(e,n,i,o),await fn(e,n,i,o),await yn(e,n,i,o),await _n(e,n,i,o)},Mn=(e,n)=>[D(e,n),M(e,n)].filter(i=>i.fields.length>0),Bn=async(e,n,i,o)=>{for(const[r,s]of Object.entries(n.tables))s.shardMode?.kind!=="global"||o!==void 0&&!o.has(r)||await On(e,r,s,i)},B=e=>e.shardMode===void 0||e.shardMode.kind==="global",Pn=async(e,n,i)=>{const{integer:o,key:r,real:s}=i.companionTypes;for(const[a,u]of Object.entries(n.tables)){const l=u.aggregateIndexes;if(!(!l||l.length===0||!B(u)))for(const c of l){const f=j(a,c.name);await m(e,i,t`CREATE TABLE IF NOT EXISTS ${t.identifier(f)} (${t.identifier("__key__")} ${t.raw(r)} PRIMARY KEY, ${t.identifier("__value__")} ${t.raw(s)}, ${t.identifier("__count__")} ${t.raw(o)} NOT NULL DEFAULT 0)`),i.name==="sqlite"&&((await g(e,i,t`PRAGMA table_info(${t.identifier(f)})`)).some(h=>h.name==="__count__")||await m(e,i,t`ALTER TABLE ${t.identifier(f)} ADD COLUMN ${t.identifier("__count__")} ${t.raw(o)} NOT NULL DEFAULT 0`))}}},y=(e,n,i,o)=>{const r=e.name==="mysql"&&o?t`${t.identifier(n)}(191)`:t`${t.identifier(n)}`;return t`${r} ${t.raw(i)}`},Nn=(e,n,i)=>{const o=[y(e,"__partition__","ASC",!0)];for(const[r,s]of n.sortBy.entries()){const a=i.shape[s.field],u=a!==void 0&&e.indexKeyPrefix?.(p(a))!==void 0;o.push(y(e,N(r),s.direction==="desc"?"DESC":"ASC",u))}return o.push(y(e,"__id__","ASC",!0)),o},Cn=(e,n,i)=>n.sortBy.map((o,r)=>{const s=i.shape[o.field],a=e.columnType(s?p(s):void 0);return t`${t.identifier(N(r))} ${t.raw(a)}`}),Fn=async(e,n,i)=>{const{key:o}=i.companionTypes;for(const[r,s]of Object.entries(n.tables)){const a=s.rankIndexes;if(!(!a||a.length===0||!B(s)))for(const u of a){const l=K(r,u.name),c=Cn(i,u,s),f=c.length>0?t`, ${t.join(c,t`, `)}`:t``;await m(e,i,t`CREATE TABLE IF NOT EXISTS ${t.identifier(l)} (${t.identifier("__id__")} ${t.raw(o)} PRIMARY KEY, ${t.identifier("__partition__")} ${t.raw(o)} NOT NULL${f})`);const $=Nn(i,u,s),h=`${r}__rank_${u.name}__btree`;await w(e,i,{columns:t.join($,t`, `),name:h,table:l,unique:!1})}}};export{A as MIGRATION_STATE_TABLE,an as declaredIndexColumnList,on as globalTableColumnsDdl,cn as globalTableIndexSpecs,U as indexColumnList,un as indexShapeChanged,Mn as legacyRewrites,hn as legacyRowPredicate,On as provisionGlobalTable,Bn as provisionGlobalTablesSequentially,Pn as runSqlAggregateMigrations,Fn as runSqlRankMigrations,Sn as wantedGlobalColumns};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{sql as l}from"drizzle-orm";import{provisionGlobalTablesSequentially as m,MIGRATION_STATE_TABLE as E,globalTableColumnsDdl as w,globalTableIndexSpecs as g,legacyRewrites as I,wantedGlobalColumns as b,indexShapeChanged as R,legacyRowPredicate as O}from"./runSqlAggregateMigrations-
|
|
1
|
+
import{sql as l}from"drizzle-orm";import{provisionGlobalTablesSequentially as m,MIGRATION_STATE_TABLE as E,globalTableColumnsDdl as w,globalTableIndexSpecs as g,legacyRewrites as I,wantedGlobalColumns as b,indexShapeChanged as R,legacyRowPredicate as O}from"./runSqlAggregateMigrations-vjt5RZB2.mjs";import{r as y,q as p}from"./sql-exec-BfJ_rWEB.mjs";const $=50,u=e=>e.replaceAll(/[A-Z]/gu,s=>s.toLowerCase()),T=new Map([["'","'"],["[","]"],["`","`"],['"','"']]),A=/^[\w$]+/u,h=(e,s)=>{const n=T.get(e[s]);let t=s+1;for(;t<e.length;)if(e[t]!==n)t+=1;else if(n!=="]"&&e[t+1]===n)t+=2;else return t+1;return t},C=e=>{const s=e.trim(),n=T.get(s[0]??"");if(n===void 0)return A.exec(s)?.[0];const t=h(s,0),o=s.slice(1,s[t-1]===n?t-1:t);return n==="]"?o:o.replaceAll(`${n}${n}`,n)},q=e=>{const s=new Set,n=i=>{const a=C(i);a!==void 0&&s.add(a)};let t=0,o=0,r=0;for(;r<e.length;){const i=e[r];if(T.has(i)){r=h(e,r);continue}if(i==="(")t+=1,o=t===1?r+1:o;else if(i===")"){if(t-=1,t===0)return n(e.slice(o,r)),s}else i===","&&t===1&&(n(e.slice(o,r)),o=r+1);r+=1}return s},M=async(e,s)=>{try{const n=await p(e,s,l`SELECT type, name, sql FROM sqlite_master WHERE type IN ('table', 'index')`),t=new Set,o=new Map,r=new Map;for(const a of n){const f=String(a.name);if(f.startsWith("sqlite_"))continue;const c=typeof a.sql=="string"?a.sql:void 0;a.type==="table"?(t.add(u(f)),o.set(u(f),new Set([...c===void 0?[]:q(c)].map(d=>u(d))))):r.set(u(f),c)}const i=new Set;if(t.has(u(E)))for(const a of await p(e,s,l`SELECT name FROM ${l.identifier(E)}`))i.add(String(a.name));return{columns:o,indexes:r,markers:i,tables:t}}catch{return}},S=e=>{const s=e.unique?l`UNIQUE `:l``;return l`CREATE ${s}INDEX IF NOT EXISTS ${l.identifier(e.name)} ON ${l.identifier(e.table)} (${e.columns})`},v=(e,s,n)=>n.length===0?[]:[l`CREATE TABLE IF NOT EXISTS ${l.identifier(E)} (${l.identifier("name")} ${l.raw(e.companionTypes.key)} PRIMARY KEY)`,...n.map(t=>l`INSERT OR IGNORE INTO ${l.identifier(E)} (${l.identifier("name")}) SELECT ${t.marker} WHERE NOT EXISTS (SELECT 1 FROM ${l.identifier(s)} WHERE ${O(t)})`)],k=(e,s,n,t)=>{const o=w(e,s,n),r=g(e,s,n),i=I(e,s);if(!t.tables.has(u(e)))return[l`CREATE TABLE IF NOT EXISTS ${l.identifier(e)} (${o})`,...r.map(c=>S(c)),...v(n,e,i)];const a=t.columns.get(u(e))??new Set;if(b(s,n).some(([c])=>!a.has(u(c)))||i.some(c=>!t.markers.has(c.marker)))return;const f=[];for(const c of r){if(!t.indexes.has(u(c.name))){f.push(S(c));continue}const d=t.indexes.get(u(c.name));if(c.kind==="declared"&&typeof d=="string"&&R(n,d,c))return}return f},L=e=>{const s=[];let n=[],t=0;for(const o of e)n.length>0&&t+o.statements.length>$&&(s.push(n),n=[],t=0),n.push(o),t+=o.statements.length;return n.length>0&&s.push(n),s},F=async(e,s,n)=>{if(!e.batch||n.name!=="sqlite"){await m(e,s,n);return}const t=await M(e,n);if(t===void 0){await m(e,s,n);return}const o=[],r=new Set;for(const[i,a]of Object.entries(s.tables)){if(a.shardMode?.kind!=="global")continue;const f=k(i,a,n,t);f===void 0?r.add(i):f.length>0&&o.push({statements:f,table:i})}for(const i of L(o))try{await y(e,n,i.flatMap(a=>a.statements))}catch{for(const a of i)r.add(a.table)}await m(e,s,n,r)};export{q as columnNamesOfCreateTable,F as runSqlGlobalTableMigrations};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as g}from"@lunora/errors";import{renderSql as $}from"@lunora/shard-engine";import{sql as s,SQL as H}from"drizzle-orm";import{c as x,s as w,d as J,a as U,n as W}from"./value-codec-DPoUomF-.mjs";import"./OCC_VERSION_COLUMN-ByC64Jgx.mjs";const h=4;class O extends Error{}const N=t=>t.includes("."),R=t=>{const n=t.split(".");if(n.length>h||n.includes(""))throw new O(`field path "${t}" must have 1 to ${String(h)} non-empty segments`);return n},it=(t,n)=>{if(!N(n))return t[n];let e=t;for(const r of R(n)){if(!x(e)||!Object.hasOwn(e,r))return;e=e[r]}return e},B={boolean:"'true', 'false'",number:"'integer', 'real'",string:"'text'"},k=/^[A-Za-z_$][\w$]*$/u,I=t=>k.test(t)?t:`"${t.replaceAll("\\",String.raw`\\`).replaceAll('"',String.raw`\"`)}"`,C=t=>t==="_id"||t==="id"?"id":t,d=t=>s`${s.identifier(C(t))}`,b=t=>{try{return R(t)}catch(n){throw n instanceof O?new g("VALIDATION_ERROR",n.message):n}},q=new WeakMap,ct=t=>q.get(t),L=(t,n)=>{let e=s`${t}::jsonb`;for(const r of n)e=s`${e} -> ${r}::text`;return s`NULLIF(${e}, 'null'::jsonb)`},K=(t,n)=>s`CASE WHEN pg_input_is_valid(${t}, 'jsonb') THEN ${L(t,n)} END`,X=(t,n)=>s`CASE WHEN pg_input_is_valid(${t}, 'jsonb') THEN ${L(t,n)} #>> '{}' END`,y=(t,n)=>{const e=`$${n.map(r=>`.${I(r)}`).join("")}`;return s`NULLIF(JSON_EXTRACT(${t}, ${e}), CAST('null' AS JSON))`},V=(t,n)=>s`CASE WHEN JSON_VALID(${t}) THEN ${y(t,n)} END`,z=(t,n)=>s`CASE WHEN JSON_VALID(${t}) THEN JSON_UNQUOTE(${y(t,n)}) END`,lt=(t,n)=>t==="postgres"?s`(${n})::jsonb #>> '{}'`:s`JSON_UNQUOTE(${n})`,D=(t,n)=>{const[e="",...r]=b(n),o=d(e);return s`CASE WHEN json_valid(${o}) THEN ${s.raw(t)}(${o}, ${`$.${r.map(a=>I(a)).join(".")}`}) END`},G=(t,n)=>{if(!N(n))return d(n);if(t.name==="sqlite")return D("json_extract",n);const[e="",...r]=b(n),o=d(e),a=t.name==="postgres",i=a?K(o,r):V(o,r);return q.set(i,a?X(o,r):z(o,r)),i},M=new WeakMap,j=t=>s`CAST(CAST(${t} AS text) AS jsonb)`,ut=(t,n,e)=>{if(t.name==="sqlite")return s`NULLIF(${D("json_type",n)}, 'null') IN (${s.raw(B[e])})`;const r=G(t,n);if(t.name==="postgres")return s`jsonb_typeof(${r}) = ${s.raw(`'${e}'`)}`;const o={boolean:"'BOOLEAN'",number:"'INTEGER', 'UNSIGNED INTEGER', 'DOUBLE', 'DECIMAL'",string:"'STRING'"}[e];return s`JSON_TYPE(${r}) IN (${s.raw(o)})`},Q=(t,n)=>{if(n===void 0)return n;if(typeof n=="bigint"||W(n))return t==="postgres"?s`CAST(NULL AS jsonb)`:s`CAST(NULL AS JSON)`;const e=JSON.stringify(n),r=t==="postgres"?s`${j(e)}`:s`CAST(${e} AS JSON)`;return M.set(r,e),r},mt=(t,n,e,r)=>{const o=[];let a=!1;for(const l of e){if(l===void 0)throw new g("BAD_REQUEST","an `in` list holds an undefined value");const m=l instanceof H?M.get(l):void 0;m===void 0?a=!0:o.push(m)}if(o.length===0||r&&a)return s`1 = 0`;const i=`[${o.join(",")}]`,c=t==="postgres"?s`SELECT e.v FROM jsonb_array_elements(${j(i)}) AS e(v)`:s`SELECT jt.v FROM JSON_TABLE(${i}, '$[*]' COLUMNS (v JSON PATH '$')) AS jt`;return r?s`${n} NOT IN (${c})`:s`${n} IN (${c})`},Et=(t,n,e,r)=>t.name==="sqlite"||!N(n)||e===null?r(e):Q(t.name,e),ft=(t,n)=>s`${s.identifier(t)}.${s.identifier(C(n))}`,$t=t=>{const n=[];for(const[e,r]of Object.entries(t.shape)){const o=r._meta?.column;o&&n.push([e,o])}return n},f=(t,n,e)=>{const{params:r,sql:o}=$(n.name,e);return t.all(o,r)},u=(t,n,e)=>{const{params:r,sql:o}=$(n.name,e);return t.run(o,r)},dt=(t,n,e)=>t==="postgres"?s`${n} IS NOT DISTINCT FROM ${e}`:t==="mysql"?s`${n} <=> ${e}`:s`${n} IS ${e}`,St={sql:t=>s`COALESCE(${t}, 0) + 1`,value:t=>(t==null?0:Number(t))+1},Nt=async(t,n,e)=>{if(e.length!==0){if(!t.batch){for(const r of e)await u(t,n,r);return}await t.batch(e.map(r=>$(n.name,r)))}},pt=async(t,n,e)=>{if(t.batch&&n.name==="sqlite"){await t.batch(e.map(r=>$(n.name,r)));return}for(const r of e)await u(t,n,r)},ht=async(t,n,e)=>{const r=e.unique?s`UNIQUE `:s``,o=e.concurrently===!0&&n.name==="postgres"?s`CONCURRENTLY `:s``;if(n.name==="mysql"){try{await u(t,n,s`CREATE ${r}INDEX ${s.identifier(e.name)} ON ${s.identifier(e.table)} (${e.columns})`)}catch(a){const i=a;if(i.errno!==1061&&i.code!=="ER_DUP_KEYNAME"&&i.code!==1061)throw a}return}await u(t,n,s`CREATE ${r}INDEX ${o}IF NOT EXISTS ${s.identifier(e.name)} ON ${s.identifier(e.table)} (${e.columns})`)},Tt=async(t,n,e,r)=>{if(n.name!=="mysql"){await u(t,n,s`DROP INDEX IF EXISTS ${s.identifier(r)}`);return}try{await u(t,n,s`DROP INDEX ${s.identifier(r)} ON ${s.identifier(e)}`)}catch(o){const a=o;if(a.errno!==1091&&a.code!=="ER_CANT_DROP_FIELD_OR_KEY"&&a.code!==1091)throw o}},_t=async(t,n,e,r)=>{switch(n.name){case"mysql":return(await f(t,n,s`SELECT 1 AS ${s.identifier("present")} FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = ${e} AND index_name = ${r} LIMIT 1`)).length>0?"valid":"absent";case"postgres":{const o=await f(t,n,s`SELECT indisvalid FROM pg_index WHERE indexrelid = to_regclass(quote_ident(${r}))`);return o.length===0?"absent":o[0]?.indisvalid===!0?"valid":"invalid"}default:return(await f(t,n,s`SELECT 1 AS ${s.identifier("present")} FROM sqlite_master WHERE type = 'index' AND name = ${r}`)).length>0?"valid":"absent"}},At=w,S=t=>{if(t===void 0)return!1;if(t._meta?.column?.notNull===!1)return!0;switch(t.kind){case"any":case"null":return!0;case"literal":return t._meta?.value===null;case"optional":return S(t._meta?.inner);case"union":return t._meta?.members?.some(n=>S(n))===!0;default:return!1}},Y=t=>t.kind==="optional"&&!S(t),T=new WeakMap,P=t=>{let n=T.get(t);return n===void 0&&(n=Object.entries(t.shape).map(([e,r])=>[e,U(r),Y(r)]),T.set(t,n)),n},_=new WeakMap,Z=(t,n)=>{let e=_.get(t);return e===void 0&&(e=new Map(P(t).map(([r,o])=>[r,o])),_.set(t,e)),e.get(n)},gt=(t,n,e)=>w(e,Z(t,n)),tt=(t,n)=>{const e={};for(const[r,o,a]of P(t)){const i=n[r];i===void 0||a&&i===null||(e[r]=J(i,o))}return e._id=n.id,e._creationTime=n._creationTime,e},F=(t,n)=>n?tt(t,n):null,wt=(t,n)=>{const e=[];for(const r of n){const o=F(t,r);o&&e.push(o)}return e},A=500,nt=(t,n,e,r,o)=>{const a=s`${s.identifier(e)}.${s.identifier("id")}`,i=r===void 0?s``:s` WHERE ${a} > ${r}`;return f(t,n,s`SELECT * FROM ${s.identifier(e)}${i} ORDER BY ${a} ASC LIMIT ${s.raw(String(o))}`)},Ot=async(t,n,e,r,o,a={})=>{let i=a.after,c=a.limit,l=!0;for(;l&&(c===void 0||c>0);){const m=c===void 0?A:Math.min(A,c),E=await nt(t,n,r,i,m);for(const v of E){const p=F(e,v);p&&await o(p)}i=E.at(-1)?.id,l=E.length===m,c=c===void 0?void 0:c-E.length}};export{A as B,u as a,d as b,ht as c,ft as d,Nt as e,F as f,Tt as g,wt as h,_t as i,At as j,nt as k,Ot as l,lt as m,dt as n,mt as o,ct as p,f as q,pt as r,gt as s,$t as t,St as u,G as v,it as w,Et as x,ut as y,tt as z};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/sql-store",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.179",
|
|
4
4
|
"description": "Internal dialect-parameterized SQL store core for Lunora .global() backends (D1, PlanetScale)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@lunora/errors": ">=1.0.0-alpha.51 <2.0.0-0",
|
|
54
|
-
"@lunora/shard-engine": "1.0.0-alpha.
|
|
54
|
+
"@lunora/shard-engine": "1.0.0-alpha.127",
|
|
55
55
|
"drizzle-orm": "^0.45.3"
|
|
56
56
|
},
|
|
57
57
|
"engines": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./ctx-db-search-state-C3IGyBzm.mjs";import{d as S,c as s,a as i,r as l}from"./ctx-db-search-Cc4WXyGR.mjs";import"./sql-exec-BmMqDIi8.mjs";export{S as backfillSqlSearchIndexes,s as createSearchSync,i as runSqlSearch,l as runSqlSearchMigrations};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as p}from"@lunora/errors";import{D as I,c as vt,m as Dt,r as U,a as qt,l as lt,w as F,b as Ft}from"./ctx-db-search-state-C3IGyBzm.mjs";import{ftsUnmappedPage as Ut,groupUnmappedRows as bt,ftsWriteDocument as mt,ftsPurgeDocument as ht,ftsCompanionDdl as kt,unionAll as Ht,ftsRowidMapName as Pt}from"@lunora/shard-engine";import{sql as i}from"drizzle-orm";import{q as h,O as Bt,n as jt,f as V,r as A,i as L,c as X,g as M,a as T,h as pt,b as rt,j as Wt,k as xt,l as Kt}from"./sql-exec-BmMqDIi8.mjs";const Gt=n=>{const t=atob(n),e=Uint8Array.from(t,r=>r.codePointAt(0)??0);return new TextDecoder().decode(e)},Yt=()=>new p("BAD_REQUEST","invalid cursor"),st=16,ot=8,y=1024,b=(n,t)=>t.query(n),Qt=(n,t)=>{if(!t)return{exact:!0,lower:n,upper:n};const e=[...n].at(-1)??"",r=(e.codePointAt(0)??0)+1;if(r>=55296&&r<=57343||r>1114111)return{exact:!0,lower:n,upper:n};const s=n.slice(0,n.length-e.length);return{exact:!1,lower:n,upper:s+String.fromCodePoint(r)}},Cn=(n,t,e)=>{const r={eq:(s,o)=>{if(!n.definition.filterFields?.includes(s))throw new p("INTERNAL",`field "${s}" is not a filter field of search index "${n.indexName}" on table "${t}"`);if(n.filters.length>=ot)throw new p("BAD_REQUEST",`search index "${n.indexName}" on table "${t}": at most ${String(ot)} .eq() filters are supported per search query`);return n.filters.push({field:s,value:o}),r},search:(s,o)=>{const a=n;if(s!==a.definition.field)throw new p("INTERNAL",`search index "${a.indexName}" on table "${t}" indexes "${a.definition.field}", not "${s}"`);const f=b(o,e).length;if(f>st)throw new p("BAD_REQUEST",`search index "${a.indexName}" on table "${t}": at most ${String(st)} search terms are supported (got ${String(f)})`);return a.field=s,a.query=o,a.hasQuery=!0,r}};return r},Ln=n=>{if(n.length>y)throw new p("BAD_REQUEST",`more than ${String(y)} documents match this search — narrow it with filters or read it a page at a time with .paginate()`)},Mn=n=>Math.min(n.offset+n.numItems+1,y),Vt=n=>btoa(`search:${String(n)}`),Xt=n=>{let t;try{t=Gt(n)}catch{return}if(!t.startsWith("search:"))return;const e=Number(t.slice(7));return Number.isInteger(e)&&e>=0?e:void 0},vn=n=>{if(typeof n.endCursor=="string")throw new p("BAD_REQUEST","bounded (endCursor) pagination is not supported on search queries — relevance order has no stable range boundary");if(!Number.isFinite(n.numItems))throw new p("BAD_REQUEST",`search pagination needs a finite numItems, got ${String(n.numItems)}`);const t=Math.max(0,Math.floor(n.numItems)),e=n.cursor?Xt(n.cursor):0;if(e===void 0)throw Yt();if(e+t>=y)throw new p("BAD_REQUEST",`search pagination reaches the ${String(y)}-document limit (offset ${String(e)} + ${String(t)} requested) — a page must end below the cap so the probe row that answers \`hasMore\` still fits: retry with numItems ${String(Math.max(1,y-e-1))} or fewer, or narrow the query or the filters instead`);return{numItems:t,offset:e}},Dn=(n,t)=>{const e=t.offset+t.numItems,r=t.numItems>0&&n.length>e;return{continueCursor:r?Vt(e):null,isDone:!r,page:n.slice(t.offset,e)}},qn=n=>{if(n===void 0)return y+1;if(!Number.isFinite(n))return y;const t=Math.max(0,Math.floor(n));if(t>y)throw new p("BAD_REQUEST",`search returns at most ${String(y)} documents (asked for ${String(t)}) — narrow the query or paginate instead`);return t},Jt=(n,t)=>{if(!t.includes("."))return n[t];let e=n;for(const r of t.split(".")){if(e===null||typeof e!="object"||Array.isArray(e))return;e=e[r]}return e},k=(n,t)=>`${n}__fts_${t}`,S="__id__",g="__token__",O="__n__",zt=1e3,gt=(n,t)=>t.document(n),x=(n,t)=>Jt(n,t),Zt=n=>typeof n=="string"?n:n==null?"":typeof n=="number"||typeof n=="bigint"||typeof n=="boolean"?String(n):JSON.stringify(n)??"",tn=(n,t,e)=>n!==void 0&&t!==void 0&&x(n,e.field)===x(t,e.field),nn=(n,t)=>gt(Zt(x(n,t.field)),I(t.language)).slice(0,zt),q=(n,t)=>nn(n,t).join(" "),Tt=(n,t)=>{const e=new Map;for(const r of gt(n,t))e.set(r,(e.get(r)??0)+1);return e},yt=[Bt,"_creationTime"],at=50,$=(n,t)=>i`${i.identifier(n)}.${i.identifier(t)}`,v=(n,t,e)=>i`DELETE FROM ${i.identifier(n)} WHERE ${$(n,S)} = ${t}${e===void 0?i``:i` AND ${e}`}`,Rt=(n,{row:t,table:e})=>{const r=yt.map(s=>i` AND ${jt(n.name,$(e,s),t[s]??null)}`);return i`SELECT 1 FROM ${i.identifier(e)} WHERE ${$(e,"id")} = ${t.id}${i.join(r)}${n.name==="postgres"?i` FOR SHARE`:i``}`},D=(n,t)=>i`EXISTS (${Rt(n,t)})`,H=(n,t)=>i`NOT EXISTS (SELECT 1 FROM ${i.identifier(n)} WHERE ${$(n,"id")} = ${t})`,_t=(n,t,e,r)=>r===void 0?H(t,e):D(n,{row:r,table:t}),J=async(n,t,e,r)=>{const s=new Map;for(let o=0;o<r.length;o+=at){const a=r.slice(o,o+at),f=await h(n,t,i`SELECT * FROM ${i.identifier(e)} WHERE ${$(e,"id")} IN (${i.join(a.map(u=>i`${u}`),i`, `)})`);for(const u of f)s.set(String(u.id),u)}return s},K=(n,t,e)=>n.name==="mysql"?i`${i.identifier(t)}(${i.raw(String(e))})`:n.textPatternOperatorClass===void 0?i`${i.identifier(t)}`:i`${i.identifier(t)} ${i.raw(n.textPatternOperatorClass)}`,z=512,Z=(n,t)=>({columns:i`${K(n,g,256)}, ${K(n,S,z)}`,concurrently:!0,name:`${t}__unique`,table:t,unique:!0}),j=n=>i`${n} COLLATE utf8mb4_0900_bin`,W=(n,t)=>{const e=JSON.stringify(t.map(([r,s])=>({o:s,t:r})));switch(n.name){case"mysql":return i`JSON_TABLE(${e}, '$[*]' COLUMNS (${i.identifier("t")} VARCHAR(256) PATH '$.t', ${i.identifier("o")} INT PATH '$.o')) AS ${i.identifier("j")}`;case"postgres":return i`json_to_recordset(${e}::json) AS ${i.identifier("j")}(${i.identifier("t")} text, ${i.identifier("o")} integer)`;default:return i`(SELECT json_extract(${$("e","value")}, '$.t') AS ${i.identifier("t")}, json_extract(${$("e","value")}, '$.o') AS ${i.identifier("o")} FROM json_each(${e}) AS ${i.identifier("e")}) AS ${i.identifier("j")}`}},Nt=(n,t,e,r,s)=>{const o=i.join([g,S,O].map(f=>i.identifier(f)),i`, `),a=f=>i`INSERT INTO ${i.identifier(t)} (${o}) SELECT ${$("j","t")}, ${e}, ${$("j","o")} FROM ${W(n,r)} WHERE ${f}`;switch(n.name){case"mysql":{const f=D(n,s),u=$(t,g),c=i.identifier("held");return[i`${a(i`${f} AND NOT EXISTS (SELECT 1 FROM ${i.identifier(t)} AS ${c} WHERE ${$("held",S)} = ${e} AND ${$("held",g)} = ${j($("j","t"))})`)} ON DUPLICATE KEY UPDATE ${$(t,O)} = ${$(t,O)}`,i`UPDATE ${i.identifier(t)} JOIN ${W(n,r)} ON ${u} = ${j($("j","t"))} SET ${$(t,O)} = ${$("j","o")} WHERE ${$(t,S)} = ${e} AND ${f}`,i`DELETE FROM ${i.identifier(t)} WHERE ${$(t,S)} = ${e} AND ${f} AND ${u} NOT IN (SELECT ${j($("j","t"))} FROM ${W(n,r)})`]}case"postgres":{const f=i.identifier("__source__"),u=i.identifier("__purged__"),c=i`EXISTS (SELECT 1 FROM ${f})`;return[i`WITH ${f} AS (${Rt(n,s)}), ${u} AS (${v(t,e,c)} RETURNING 1) ${a(i`${c} AND (SELECT COUNT(*) FROM ${u}) >= 0`)} ON CONFLICT DO NOTHING`]}default:{const f=D(n,s);return[v(t,e,f),i`${a(f)} ON CONFLICT DO NOTHING`]}}},Ot={uniqueKeyMissing:!1,unmappedSkipped:0},ft=new Set,ut=(n,t)=>{ft.has(n)||(ft.add(n),console.warn(`[@lunora/sql-store] ${t}`))},ct=100,dt=3,G=async(n,t,e,r=0)=>{const{companion:s,definition:o,index:a,tableName:f}=e,u={done:!0,last:r,left:0};if((await h(n,t,t.tableExists(f))).length===0)return u;const d=await h(n,t,Ut(s,ct,r));if(d.length===0)return u;const w=Math.max(...d.map(_=>Number(_.rowid))),E=bt(d),l=await J(n,t,f,[...E.keys()]),m=[];for(const[_,nt]of E){const B=l.get(_),et=B===void 0?void 0:V(o,B),it=_t(t,f,_,B);m.push(...et?mt(s,_,q(et,a),{guard:it,unmappedRowids:nt}):ht(s,_,{guard:it,unmappedRowids:nt}))}await A(n,t,m);const R=await h(n,t,i`SELECT COUNT(*) AS ${i.identifier("n")} FROM ${i.identifier(s)} WHERE ${$(s,"rowid")} > ${Math.max(0,r)} AND ${$(s,"rowid")} <= ${w}`);return{done:d.length<ct,last:w,left:Number(R[0]?.n??0)}},en=async(n,t,e)=>{let r=0,s=0;for(;;){let o=await G(n,t,e,r);for(let a=1;o.left>0&&a<dt;a+=1)o=await G(n,t,e,r);if(o.left>0&&(s+=o.left,console.warn(`[@lunora/sql-store] search migration of "${e.companion}": ${String(o.left)} row(s) lost every one of ${String(dt)} attempts to a concurrent write and were left for a later pass.`)),o.done)return s;r=o.last}},rn=async(n,t,e,r)=>r==="step"?(await G(n,t,e),Ot):{uniqueKeyMissing:!1,unmappedSkipped:await en(n,t,e)},Y=n=>`${n}__btree`,sn=async(n,t,e)=>{const r=Z(t,e),s=await L(n,t,e,r.name);if(s!=="valid"){if(s==="absent"&&(await h(n,t,i`SELECT 1 AS ${i.identifier("present")} FROM ${i.identifier(e)} LIMIT 1`)).length===0)try{await X(n,t,{...r,concurrently:!1}),await M(n,t,e,Y(e));return}catch(a){if(await L(n,t,e,r.name).catch(()=>{})==="valid")return;ut(`${e}:empty`,`search companion "${e}": adding its unique key failed (${String(a)}); run backfillSqlSearchIndexes.`);return}ut(`${e}:missing`,`search companion "${e}" has no usable unique key, so two backfills racing over one row can index it twice. Run backfillSqlSearchIndexes, which adds it.`)}},on=async(n,t,e)=>{const r=$(e,S),s=$(e,g);return(await h(n,t,i`SELECT ${r} AS ${i.identifier("id")}, ${s} AS ${i.identifier("token")}, COUNT(*) AS ${i.identifier("n")} FROM ${i.identifier(e)} GROUP BY ${r}, ${s} HAVING COUNT(*) > 1`)).map(a=>({count:Number(a.n),id:String(a.id),token:String(a.token)}))},an=(n,t,{count:e,id:r,token:s})=>{const o=i`${$(t,S)} = ${r} AND ${$(t,g)} = ${s}`;switch(n.name){case"mysql":return i`DELETE FROM ${i.identifier(t)} WHERE ${o} LIMIT ${i.raw(String(e-1))}`;case"postgres":return i`DELETE FROM ${i.identifier(t)} WHERE ctid = ANY (ARRAY(SELECT ctid FROM ${i.identifier(t)} WHERE ${o} OFFSET 1))`;default:return i`DELETE FROM ${i.identifier(t)} WHERE rowid IN (SELECT rowid FROM ${i.identifier(t)} WHERE ${o} LIMIT -1 OFFSET 1)`}},fn=async(n,t,e,r)=>{const{companion:s,definition:o,index:a,tableName:f}=e;for(const d of r)await T(n,t,an(t,s,d));const u=[...new Set(r.map(d=>d.id))],c=await J(n,t,f,u);for(const d of u){const w=c.get(d),E=w===void 0?void 0:V(o,w);if(w!==void 0&&E){const l=[...Tt(q(E,a),I(a.language))];await A(n,t,Nt(t,s,d,l,{row:w,table:f}));continue}await T(n,t,v(s,d,_t(t,f,d,w)))}},un=async(n,t,e)=>t.name!=="mysql"?"":(await h(n,t,i`SELECT COLUMN_NAME AS ${i.identifier("name")}, COLLATION_NAME AS ${i.identifier("collation")} FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = ${e} AND COLUMN_NAME IN (${g}, ${S})`)).filter(s=>!String(s.collation).endsWith("_bin")).map(s=>` Its ${String(s.name)} column uses ${String(s.collation)}, which treats values differing only in case or accents as one; convert it with ALTER TABLE \`${e}\` MODIFY \`${String(s.name)}\` VARCHAR(768) COLLATE utf8mb4_0900_bin NOT NULL.`).join(""),cn=async(n,t,e)=>{if(t.name!=="mysql")return 0;const r=$(e,S),s=await h(n,t,i`SELECT COUNT(*) AS ${i.identifier("n")} FROM (SELECT 1 AS ${i.identifier("x")} FROM ${i.identifier(e)} GROUP BY LEFT(${r}, ${i.raw(String(z))}), ${$(e,g)} HAVING COUNT(DISTINCT ${r}) > 1) AS ${i.identifier("shared")}`);return Number(s[0]?.n??0)},dn=async(n,t,e)=>{const r=Z(t,e),s=await L(n,t,e,r.name);if(s==="valid")return"valid";s==="invalid"&&await M(n,t,e,r.name);try{return await X(n,t,r),"built"}catch(o){const a=await L(n,t,e,r.name);if(a==="valid")return"valid";if(a==="invalid"&&await M(n,t,e,r.name),!t.isUniqueViolation(o))throw o;return"refused"}},$t=3,$n=async(n,t,e)=>{const{companion:r}=e,s=await un(n,t,r);let o="";s!==""&&console.warn(`[@lunora/sql-store] search companion "${r}" folds case and accents in its unique key.${s}`);for(let a=0;a<$t;a+=1){const f=await dn(n,t,r);if(f==="valid")return await M(n,t,r,Y(r)),!0;if(f==="refused"){const u=await on(n,t,r);if(u.length>0)await fn(n,t,e,u);else{const c=await cn(n,t,r);o=c>0?` ${String(c)} token(s) are held by document ids that agree on their first ${String(z)} characters, which the key cannot tell apart; shorten those ids.`:s}}}return await L(n,t,r,Z(t,r).name)==="valid"?(await M(n,t,r,Y(r)),!0):(console.warn(`[@lunora/sql-store] search companion "${r}" still has no unique key after ${String($t)} attempts: writes keep working, but two backfills racing over one row can index it twice.${o}`),!1)},wn=async(n,t,e,r)=>r==="step"?Ot:{uniqueKeyMissing:!await $n(n,t,e),unmappedSkipped:0},Sn=(n,t)=>t?i`${i.identifier(g)} LIKE ${`${n}%`}`:i`${i.identifier(g)} = ${n}`,At=(n,t)=>{const e=t.filters.map(r=>i`m.${rt(r.field)} = ${Wt(r.value)}`);return n.softDeleteMode&&e.push(i`m.${rt(n.softDeleteMode.field)} IS NULL`),t.scope!==void 0&&e.push(i`(${t.scope})`),e},It=async(n,t,e,r,s,o,a)=>{const f=At(e,s);let u=i`SELECT m.* FROM (${a}) s JOIN ${i.identifier(r)} m ON m.${i.identifier("id")} = s.${i.identifier(S)}`;return f.length>0&&(u=i`${u} WHERE ${i.join(f,i` AND `)}`),u=i`${u} ORDER BY s.${i.identifier("__score__")} DESC, m.${i.identifier("_creationTime")} DESC, m.${i.identifier("id")} ASC LIMIT ${i.raw(String(o))}`,pt(e,await h(n,t,u))},En=async(n,t,e,r,s,o)=>{const a=b(s.query,I(s.definition.language));if(a.length===0)return[];const f=k(r,s.indexName),u=a.length-1,c=a.map((m,R)=>Sn(m,R===u)),d=i.join(c,i` OR `),w=c.map(m=>i`SUM(CASE WHEN ${m} THEN ${i.identifier(O)} ELSE 0 END)`),E=i.join(w.map(m=>i`${m} > 0`),i` AND `),l=i`SELECT ${i.identifier(S)}, ${i.join(w,i` + `)} AS ${i.identifier("__score__")} FROM ${i.identifier(f)} WHERE ${d} GROUP BY ${i.identifier(S)} HAVING ${E}`;return It(n,t,e,r,s,o,l)},ln=async(n,t,e,r,s,o)=>{const a=b(s.query,I(s.definition.language));if(a.length===0)return[];const f=k(r,s.indexName),u=`${f}__vocab`,c=a.length-1,d=a.map((l,m)=>{const R=Qt(l,m===c),_=R.exact?i`${i.identifier("term")} = ${R.lower}`:i`${i.identifier("term")} >= ${R.lower} AND ${i.identifier("term")} < ${R.upper}`;return i`SELECT ${i.identifier("doc")}, ${i.raw(String(m))} AS ${i.identifier("__term__")}, COUNT(*) AS ${i.identifier("__n__")} FROM ${i.identifier(u)} WHERE ${_} GROUP BY ${i.identifier("doc")}`}),w=a.map((l,m)=>i`SUM(CASE WHEN u.${i.identifier("__term__")} = ${i.raw(String(m))} THEN u.${i.identifier("__n__")} ELSE 0 END)`),E=i`SELECT f.${i.identifier(S)} AS ${i.identifier(S)}, ${i.join(w,i` + `)} AS ${i.identifier("__score__")} FROM (${Ht(d)}) u JOIN ${i.identifier(f)} f ON f.rowid = u.${i.identifier("doc")} GROUP BY f.${i.identifier(S)} HAVING ${i.join(w.map(l=>i`${l} > 0`),i` AND `)}`;return It(n,t,e,r,s,o,E)},mn=async(n,t,e,r,s,o)=>{const a=t.nativeTextSearch,f=b(s.query,I(s.definition.language));if(!a||f.length===0)return[];const u=k(r,s.indexName),c=[a.matches(u,f),...At(e,s)],d=i`SELECT m.* FROM ${i.identifier(u)} JOIN ${i.identifier(r)} m ON m.${i.identifier("id")} = ${i.identifier(u)}.${i.identifier(S)} WHERE ${i.join(c,i` AND `)} ORDER BY ${a.rank(u,f)} DESC, m.${i.identifier("_creationTime")} DESC, m.${i.identifier("id")} ASC LIMIT ${i.raw(String(o))}`;return pt(e,await h(n,t,d))},hn={ensureCompanion:async(n,t,e)=>{const{integer:r,key:s}=t.companionTypes;await T(n,t,i`CREATE TABLE IF NOT EXISTS ${i.identifier(e)} (${i.identifier(g)} ${i.raw(s)} NOT NULL, ${i.identifier(S)} ${i.raw(s)} NOT NULL, ${i.identifier(O)} ${i.raw(r)} NOT NULL)`),await X(n,t,{columns:K(t,S,191),name:`${e}__by_id`,table:e,unique:!1}),await sn(n,t,e)},indexDocument:async(n,t,e,r,s,o)=>{const a=[...Tt(q(r,s),I(s.language))];await A(n,t,Nt(t,e,String(o.row.id),a,o))},migrate:wn,name:"inverted",purgeDocument:async(n,t,e,r,s)=>{await T(n,t,v(e,r,H(s,r)))},runSearch:En},pn={ensureCompanion:async(n,t,e)=>{await A(n,t,kt(e))},indexDocument:async(n,t,e,r,s,o)=>{await A(n,t,mt(e,String(o.row.id),q(r,s),{guard:D(t,o)}))},migrate:rn,name:"fts5",purgeDocument:async(n,t,e,r,s)=>{await A(n,t,ht(e,r,{guard:H(s,r)}))},runSearch:ln},gn={ensureCompanion:async(n,t,e)=>{const r=t.nativeTextSearch;if(r){await T(n,t,r.createCompanion(e,t.companionTypes.key));for(const s of r.createIndexes(e))await T(n,t,s)}},indexDocument:async(n,t,e,r,s,o)=>{const a=t.nativeTextSearch;a&&await T(n,t,a.indexDocument(e,String(o.row.id),q(r,s),D(t,o)))},name:"native",purgeDocument:async(n,t,e,r,s)=>{await T(n,t,v(e,r,H(s,r)))},runSearch:mn},C=(n,t)=>n.strategy==="native"&&t.nativeTextSearch!==void 0?gn:t.supportsFts5?pn:hn,P=(n,t)=>`${vt(n)}/${C(n,t).name}`,tt=function*(n){for(const[t,e]of Object.entries(n.tables)){const r=e.searchIndexes;if(!(e.shardMode!==void 0&&e.shardMode.kind!=="global"||!r))for(const s of r)yield[t,e,s]}},N=(n,t)=>k(n,t.name),Tn=async(n,t,e,r)=>{const s=N(e,r);return lt(await U(n,t,s),P(r,t)).finished?!0:Ft(n,t,s)},Fn=async(n,t,e,r,s,o)=>{if(!await Tn(n,t,r,s.definition))throw new p("SEARCH_INDEX_BUILDING",`search index "${s.indexName}" on table "${r}" is still backfilling and currently covers only part of the table — retry once it finishes${t.searchBackfillHint===void 0?"":`, or complete it now: ${t.searchBackfillHint}`}`);return C(s.definition,t).runSearch(n,t,e,r,s,o)},wt=n=>n.slice(n.lastIndexOf("/")+1),St=200,Et=5,yn=async(n,t,e,r)=>{const s=[...r.keys()],o=await h(n,t,i`SELECT * FROM ${i.identifier(e)} WHERE ${i.identifier("id")} >= ${s[0]} AND ${i.identifier("id")} <= ${s.at(-1)} ORDER BY ${i.identifier("id")} ASC`),a=new Map;for(const f of o){const u=f.id,c=r.get(u)?.row;c&&yt.some(d=>String(c[d])!==String(f[d]))&&a.set(u,{row:f})}return a},Q=async(n,t,e,r,s,o,a)=>{const f=C(o,t);let u=a;for(let c=0;u.size>0&&c<Et;c+=1){for(const{document:d,row:w}of u.values()){const E=d??V(e,w);E&&await f.indexDocument(n,t,s,E,o,{row:w,table:r})}u=await yn(n,t,r,u)}u.size>0&&console.warn(`[@lunora/sql-store] search index "${s}": ${String(u.size)} row(s) were rewritten on every one of ${String(Et)} re-check rounds and were left to their writers — each stays stale only if none of those writes changed its indexed text.`)},Ct=async(n,t,e,r,s)=>{const o=N(r,s),a=P(s,t),f=lt(await U(n,t,o),a);if(f.finished)return!0;if(f.wipe&&await F(n,t,o,void 0,!1,a),(await h(n,t,t.tableExists(r))).length===0)return await F(n,t,o,void 0,!0,a),!0;const c=await xt(n,t,r,f.cursor,St),d=c.findLast(l=>typeof l.id=="string")?.id,w=new Map;for(const l of c)typeof l.id=="string"&&w.set(l.id,{row:l});await Q(n,t,e,r,o,s,w);const E=c.length<St;return await F(n,t,o,d??f.cursor,E,a),E},Lt=async(n,t,e)=>{await Dt(n,e);for(const[r,,s]of tt(t)){const o=N(r,s),a=P(s,e),f=await U(n,e,o);f.profile!==void 0&&wt(f.profile)!==wt(a)&&(await T(n,e,i`DROP TABLE IF EXISTS ${i.identifier(o)}`),await T(n,e,i`DROP TABLE IF EXISTS ${i.identifier(Pt(o))}`),await qt(n,e,o)),await C(s,e).ensureCompanion(n,e,o)}},Rn=async(n,t,e,r,s)=>{const o=N(r,s);if((await U(n,t,o)).profile!==void 0)return;let f=0;(await h(n,t,t.tableExists(r))).length>0&&await Kt(n,t,e,r,()=>{f+=1},{limit:1}),await F(n,t,o,void 0,f===0,P(s,t))},Mt=async(n,t,e,r,s,o)=>await C(s,t).migrate?.(n,t,{companion:N(r,s),definition:e,index:s,tableName:r},o)??{uniqueKeyMissing:!1,unmappedSkipped:0},Un=async(n,t,e)=>{await Lt(n,t,e);for(const[r,s,o]of tt(t)){if(await Mt(n,e,s,r,o,"step"),o.staged){await Rn(n,e,s,r,o);continue}await Ct(n,e,s,r,o)}},bn=async(n,t,e)=>{const r={uniqueKeyMissing:[],unmappedSkipped:0};await Lt(n,t,e);for(const[s,o,a]of tt(t)){const f=await Mt(n,e,o,s,a,"drain");r.unmappedSkipped+=f.unmappedSkipped,f.uniqueKeyMissing&&r.uniqueKeyMissing.push(N(s,a));let u=!1;for(;!u;)u=await Ct(n,e,o,s,a)}return r},kn=n=>{const{dialect:t,exec:e,schema:r}=n;return async(s,o,a)=>{const f=r.tables[s],u=f?.searchIndexes;if(!(!f||!u||u.length===0))for(const c of u){if(tn(a?.previous,a?.document,c))continue;const d=N(s,c);if(a){await Q(e,t,f,s,d,c,new Map([[o,{document:a.document,row:{...a.written,id:o}}]]));continue}await C(c,t).purgeDocument(e,t,d,o,s);const E=(await J(e,t,s,[o])).get(o);E!==void 0&&await Q(e,t,f,s,d,c,new Map([[o,{row:E}]]))}}};export{Cn as A,vn as C,Dn as R,qn as T,Fn as a,Mn as b,kn as c,bn as d,Un as r,st as u,Ln as x};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{B as l,O as o,b as n,c as r,z as t,f as d,h as i,g as u,v as f,l as R,i as q,u as c,n as C,m,o as p,p as x,y as I,d as S,q as h,e as w,a as E,k as y,r as O,j as z,s as B,x as L,t as N}from"./sql-exec-BmMqDIi8.mjs";import"./value-codec-DPoUomF-.mjs";export{l as BACKFILL_BATCH_SIZE,o as OCC_VERSION_COLUMN,n as columnRefSql,r as createIndexIfNotExists,t as decodeGlobalRow,d as decodeRow,i as decodeRows,u as dropIndexIfExists,f as fieldRefSql,R as forEachRowPaged,q as indexState,c as nextRowVersion,C as nullSafeEqualsSql,m as pathContainsNeedle,p as pathInList,x as pathTextReference,I as pathTypeGuardSql,S as qualifiedColumnRefSql,h as queryAll,w as queryBatch,E as queryRun,y as readRowsPage,O as runInOrder,z as serializeColumnValue,B as serializeDocumentColumn,L as serializeFieldValue,N as tableColumns};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as O}from"@lunora/errors";import{renderSql as $}from"@lunora/shard-engine";import{sql as s,SQL as H}from"drizzle-orm";import{c as x,s as g,d as J,a as U,n as W}from"./value-codec-DPoUomF-.mjs";const h=4;class w extends Error{}const N=t=>t.includes("."),R=t=>{const n=t.split(".");if(n.length>h||n.includes(""))throw new w(`field path "${t}" must have 1 to ${String(h)} non-empty segments`);return n},at=(t,n)=>{if(!N(n))return t[n];let e=t;for(const r of R(n)){if(!x(e)||!Object.hasOwn(e,r))return;e=e[r]}return e},B={boolean:"'true', 'false'",number:"'integer', 'real'",string:"'text'"},k=/^[A-Za-z_$][\w$]*$/u,I=t=>k.test(t)?t:`"${t.replaceAll("\\",String.raw`\\`).replaceAll('"',String.raw`\"`)}"`,it="_version",C=t=>t==="_id"||t==="id"?"id":t,d=t=>s`${s.identifier(C(t))}`,b=t=>{try{return R(t)}catch(n){throw n instanceof w?new O("VALIDATION_ERROR",n.message):n}},q=new WeakMap,ct=t=>q.get(t),L=(t,n)=>{let e=s`${t}::jsonb`;for(const r of n)e=s`${e} -> ${r}::text`;return s`NULLIF(${e}, 'null'::jsonb)`},K=(t,n)=>s`CASE WHEN pg_input_is_valid(${t}, 'jsonb') THEN ${L(t,n)} END`,V=(t,n)=>s`CASE WHEN pg_input_is_valid(${t}, 'jsonb') THEN ${L(t,n)} #>> '{}' END`,y=(t,n)=>{const e=`$${n.map(r=>`.${I(r)}`).join("")}`;return s`NULLIF(JSON_EXTRACT(${t}, ${e}), CAST('null' AS JSON))`},X=(t,n)=>s`CASE WHEN JSON_VALID(${t}) THEN ${y(t,n)} END`,z=(t,n)=>s`CASE WHEN JSON_VALID(${t}) THEN JSON_UNQUOTE(${y(t,n)}) END`,lt=(t,n)=>t==="postgres"?s`(${n})::jsonb #>> '{}'`:s`JSON_UNQUOTE(${n})`,D=(t,n)=>{const[e="",...r]=b(n),o=d(e);return s`CASE WHEN json_valid(${o}) THEN ${s.raw(t)}(${o}, ${`$.${r.map(a=>I(a)).join(".")}`}) END`},G=(t,n)=>{if(!N(n))return d(n);if(t.name==="sqlite")return D("json_extract",n);const[e="",...r]=b(n),o=d(e),a=t.name==="postgres",i=a?K(o,r):X(o,r);return q.set(i,a?V(o,r):z(o,r)),i},M=new WeakMap,j=t=>s`CAST(CAST(${t} AS text) AS jsonb)`,ut=(t,n,e)=>{if(t.name==="sqlite")return s`NULLIF(${D("json_type",n)}, 'null') IN (${s.raw(B[e])})`;const r=G(t,n);if(t.name==="postgres")return s`jsonb_typeof(${r}) = ${s.raw(`'${e}'`)}`;const o={boolean:"'BOOLEAN'",number:"'INTEGER', 'UNSIGNED INTEGER', 'DOUBLE', 'DECIMAL'",string:"'STRING'"}[e];return s`JSON_TYPE(${r}) IN (${s.raw(o)})`},Q=(t,n)=>{if(n===void 0)return n;if(typeof n=="bigint"||W(n))return t==="postgres"?s`CAST(NULL AS jsonb)`:s`CAST(NULL AS JSON)`;const e=JSON.stringify(n),r=t==="postgres"?s`${j(e)}`:s`CAST(${e} AS JSON)`;return M.set(r,e),r},Et=(t,n,e,r)=>{const o=[];let a=!1;for(const l of e){if(l===void 0)throw new O("BAD_REQUEST","an `in` list holds an undefined value");const E=l instanceof H?M.get(l):void 0;E===void 0?a=!0:o.push(E)}if(o.length===0||r&&a)return s`1 = 0`;const i=`[${o.join(",")}]`,c=t==="postgres"?s`SELECT e.v FROM jsonb_array_elements(${j(i)}) AS e(v)`:s`SELECT jt.v FROM JSON_TABLE(${i}, '$[*]' COLUMNS (v JSON PATH '$')) AS jt`;return r?s`${n} NOT IN (${c})`:s`${n} IN (${c})`},mt=(t,n,e,r)=>t.name==="sqlite"||!N(n)||e===null?r(e):Q(t.name,e),ft=(t,n)=>s`${s.identifier(t)}.${s.identifier(C(n))}`,$t=t=>{const n=[];for(const[e,r]of Object.entries(t.shape)){const o=r._meta?.column;o&&n.push([e,o])}return n},f=(t,n,e)=>{const{params:r,sql:o}=$(n.name,e);return t.all(o,r)},u=(t,n,e)=>{const{params:r,sql:o}=$(n.name,e);return t.run(o,r)},dt=(t,n,e)=>t==="postgres"?s`${n} IS NOT DISTINCT FROM ${e}`:t==="mysql"?s`${n} <=> ${e}`:s`${n} IS ${e}`,St={sql:t=>s`COALESCE(${t}, 0) + 1`,value:t=>(t==null?0:Number(t))+1},Nt=async(t,n,e)=>{if(e.length!==0){if(!t.batch){for(const r of e)await u(t,n,r);return}await t.batch(e.map(r=>$(n.name,r)))}},pt=async(t,n,e)=>{if(t.batch&&n.name==="sqlite"){await t.batch(e.map(r=>$(n.name,r)));return}for(const r of e)await u(t,n,r)},ht=async(t,n,e)=>{const r=e.unique?s`UNIQUE `:s``,o=e.concurrently===!0&&n.name==="postgres"?s`CONCURRENTLY `:s``;if(n.name==="mysql"){try{await u(t,n,s`CREATE ${r}INDEX ${s.identifier(e.name)} ON ${s.identifier(e.table)} (${e.columns})`)}catch(a){const i=a;if(i.errno!==1061&&i.code!=="ER_DUP_KEYNAME"&&i.code!==1061)throw a}return}await u(t,n,s`CREATE ${r}INDEX ${o}IF NOT EXISTS ${s.identifier(e.name)} ON ${s.identifier(e.table)} (${e.columns})`)},_t=async(t,n,e,r)=>{if(n.name!=="mysql"){await u(t,n,s`DROP INDEX IF EXISTS ${s.identifier(r)}`);return}try{await u(t,n,s`DROP INDEX ${s.identifier(r)} ON ${s.identifier(e)}`)}catch(o){const a=o;if(a.errno!==1091&&a.code!=="ER_CANT_DROP_FIELD_OR_KEY"&&a.code!==1091)throw o}},Tt=async(t,n,e,r)=>{switch(n.name){case"mysql":return(await f(t,n,s`SELECT 1 AS ${s.identifier("present")} FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = ${e} AND index_name = ${r} LIMIT 1`)).length>0?"valid":"absent";case"postgres":{const o=await f(t,n,s`SELECT indisvalid FROM pg_index WHERE indexrelid = to_regclass(quote_ident(${r}))`);return o.length===0?"absent":o[0]?.indisvalid===!0?"valid":"invalid"}default:return(await f(t,n,s`SELECT 1 AS ${s.identifier("present")} FROM sqlite_master WHERE type = 'index' AND name = ${r}`)).length>0?"valid":"absent"}},At=g,S=t=>{if(t===void 0)return!1;if(t._meta?.column?.notNull===!1)return!0;switch(t.kind){case"any":case"null":return!0;case"literal":return t._meta?.value===null;case"optional":return S(t._meta?.inner);case"union":return t._meta?.members?.some(n=>S(n))===!0;default:return!1}},Y=t=>t.kind==="optional"&&!S(t),_=new WeakMap,P=t=>{let n=_.get(t);return n===void 0&&(n=Object.entries(t.shape).map(([e,r])=>[e,U(r),Y(r)]),_.set(t,n)),n},T=new WeakMap,Z=(t,n)=>{let e=T.get(t);return e===void 0&&(e=new Map(P(t).map(([r,o])=>[r,o])),T.set(t,e)),e.get(n)},Ot=(t,n,e)=>g(e,Z(t,n)),tt=(t,n)=>{const e={};for(const[r,o,a]of P(t)){const i=n[r];i===void 0||a&&i===null||(e[r]=J(i,o))}return e._id=n.id,e._creationTime=n._creationTime,e},v=(t,n)=>n?tt(t,n):null,gt=(t,n)=>{const e=[];for(const r of n){const o=v(t,r);o&&e.push(o)}return e},A=500,nt=(t,n,e,r,o)=>{const a=s`${s.identifier(e)}.${s.identifier("id")}`,i=r===void 0?s``:s` WHERE ${a} > ${r}`;return f(t,n,s`SELECT * FROM ${s.identifier(e)}${i} ORDER BY ${a} ASC LIMIT ${s.raw(String(o))}`)},wt=async(t,n,e,r,o,a={})=>{let i=a.after,c=a.limit,l=!0;for(;l&&(c===void 0||c>0);){const E=c===void 0?A:Math.min(A,c),m=await nt(t,n,r,i,E);for(const F of m){const p=v(e,F);p&&await o(p)}i=m.at(-1)?.id,l=m.length===E,c=c===void 0?void 0:c-m.length}};export{A as B,it as O,u as a,d as b,ht as c,ft as d,Nt as e,v as f,_t as g,gt as h,Tt as i,At as j,nt as k,wt as l,lt as m,dt as n,Et as o,ct as p,f as q,pt as r,Ot as s,$t as t,St as u,G as v,at as w,mt as x,ut as y,tt as z};
|