@nicia-ai/typegraph 0.37.0 → 0.38.0
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/README.md +12 -10
- package/dist/backend/drizzle/indexes.cjs +32 -0
- package/dist/backend/drizzle/indexes.cjs.map +1 -0
- package/dist/backend/drizzle/indexes.d.cts +43 -0
- package/dist/backend/drizzle/indexes.d.ts +43 -0
- package/dist/backend/drizzle/indexes.js +11 -0
- package/dist/backend/drizzle/indexes.js.map +1 -0
- package/dist/backend/index.cjs +161 -0
- package/dist/backend/index.cjs.map +1 -0
- package/dist/backend/index.d.cts +3 -0
- package/dist/backend/index.d.ts +3 -0
- package/dist/backend/index.js +8 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/postgres/index.cjs +32 -28
- package/dist/backend/postgres/index.d.cts +13 -12
- package/dist/backend/postgres/index.d.ts +13 -12
- package/dist/backend/postgres/index.js +19 -15
- package/dist/backend/postgres/pglite-store.cjs +67 -0
- package/dist/backend/postgres/pglite-store.cjs.map +1 -0
- package/dist/backend/postgres/pglite-store.d.cts +38 -0
- package/dist/backend/postgres/pglite-store.d.ts +38 -0
- package/dist/backend/postgres/pglite-store.js +65 -0
- package/dist/backend/postgres/pglite-store.js.map +1 -0
- package/dist/backend/postgres/pglite.cjs +25 -50
- package/dist/backend/postgres/pglite.cjs.map +1 -1
- package/dist/backend/postgres/pglite.d.cts +10 -9
- package/dist/backend/postgres/pglite.d.ts +10 -9
- package/dist/backend/postgres/pglite.js +20 -52
- package/dist/backend/postgres/pglite.js.map +1 -1
- package/dist/backend/sqlite/index.cjs +29 -25
- package/dist/backend/sqlite/index.d.cts +11 -11
- package/dist/backend/sqlite/index.d.ts +11 -11
- package/dist/backend/sqlite/index.js +17 -13
- package/dist/backend/sqlite/libsql.cjs +23 -19
- package/dist/backend/sqlite/libsql.cjs.map +1 -1
- package/dist/backend/sqlite/libsql.d.cts +9 -10
- package/dist/backend/sqlite/libsql.d.ts +9 -10
- package/dist/backend/sqlite/libsql.js +19 -15
- package/dist/backend/sqlite/libsql.js.map +1 -1
- package/dist/backend/sqlite/local-store.cjs +72 -0
- package/dist/backend/sqlite/local-store.cjs.map +1 -0
- package/dist/backend/sqlite/local-store.d.cts +42 -0
- package/dist/backend/sqlite/local-store.d.ts +42 -0
- package/dist/backend/sqlite/local-store.js +67 -0
- package/dist/backend/sqlite/local-store.js.map +1 -0
- package/dist/backend/sqlite/local.cjs +28 -183
- package/dist/backend/sqlite/local.cjs.map +1 -1
- package/dist/backend/sqlite/local.d.cts +8 -81
- package/dist/backend/sqlite/local.d.ts +8 -81
- package/dist/backend/sqlite/local.js +20 -180
- package/dist/backend/sqlite/local.js.map +1 -1
- package/dist/chunk-2EBMPJBO.js +16 -0
- package/dist/chunk-2EBMPJBO.js.map +1 -0
- package/dist/{chunk-NBP2WTJW.cjs → chunk-2SL7OGPR.cjs} +2900 -1597
- package/dist/chunk-2SL7OGPR.cjs.map +1 -0
- package/dist/chunk-35S6P5ZU.js +27 -0
- package/dist/chunk-35S6P5ZU.js.map +1 -0
- package/dist/chunk-3LKL3S6X.js +50 -0
- package/dist/chunk-3LKL3S6X.js.map +1 -0
- package/dist/chunk-6G5CQ6JX.js +47 -0
- package/dist/chunk-6G5CQ6JX.js.map +1 -0
- package/dist/chunk-6XDBRDZE.js +312 -0
- package/dist/chunk-6XDBRDZE.js.map +1 -0
- package/dist/chunk-764JHTLT.cjs +15 -0
- package/dist/chunk-764JHTLT.cjs.map +1 -0
- package/dist/chunk-76HE7DJP.js +68 -0
- package/dist/chunk-76HE7DJP.js.map +1 -0
- package/dist/{chunk-VGDDG3XJ.cjs → chunk-7M3NACL3.cjs} +12 -12
- package/dist/{chunk-VGDDG3XJ.cjs.map → chunk-7M3NACL3.cjs.map} +1 -1
- package/dist/{chunk-NXQFATMF.cjs → chunk-7VLCN3JB.cjs} +153 -123
- package/dist/chunk-7VLCN3JB.cjs.map +1 -0
- package/dist/{chunk-552KNYQJ.js → chunk-A2FGSWMQ.js} +1907 -607
- package/dist/chunk-A2FGSWMQ.js.map +1 -0
- package/dist/chunk-AOL64O4Z.js +165 -0
- package/dist/chunk-AOL64O4Z.js.map +1 -0
- package/dist/{chunk-27SSDCEP.cjs → chunk-B63IFHXR.cjs} +53 -74
- package/dist/chunk-B63IFHXR.cjs.map +1 -0
- package/dist/{chunk-3XXGYU62.cjs → chunk-BKAKAVRW.cjs} +56 -53
- package/dist/chunk-BKAKAVRW.cjs.map +1 -0
- package/dist/{chunk-YTSN73ND.js → chunk-BQITNFQJ.js} +3 -3
- package/dist/{chunk-YTSN73ND.js.map → chunk-BQITNFQJ.js.map} +1 -1
- package/dist/{chunk-NUIG3BCV.cjs → chunk-CQC6VBAF.cjs} +93 -155
- package/dist/chunk-CQC6VBAF.cjs.map +1 -0
- package/dist/{chunk-6EEO3OVU.cjs → chunk-CWX77JB4.cjs} +22 -59
- package/dist/chunk-CWX77JB4.cjs.map +1 -0
- package/dist/{chunk-UGZUAYAR.js → chunk-D7PG5D5K.js} +4 -3
- package/dist/chunk-D7PG5D5K.js.map +1 -0
- package/dist/chunk-DDCIXXOO.js +9 -0
- package/dist/chunk-DDCIXXOO.js.map +1 -0
- package/dist/chunk-DDCYVIVV.cjs +44 -0
- package/dist/chunk-DDCYVIVV.cjs.map +1 -0
- package/dist/{chunk-XPCZADMT.cjs → chunk-DOVMTPKE.cjs} +89 -27
- package/dist/chunk-DOVMTPKE.cjs.map +1 -0
- package/dist/{chunk-5PNMDJ7J.js → chunk-DPNA466P.js} +14 -9
- package/dist/chunk-DPNA466P.js.map +1 -0
- package/dist/{chunk-BYPOGQWK.js → chunk-DRACN6XG.js} +6 -4
- package/dist/chunk-DRACN6XG.js.map +1 -0
- package/dist/chunk-E6TXEISH.cjs +175 -0
- package/dist/chunk-E6TXEISH.cjs.map +1 -0
- package/dist/{chunk-TKT2XHED.js → chunk-E6YZRKMM.js} +13 -12
- package/dist/chunk-E6YZRKMM.js.map +1 -0
- package/dist/{chunk-3C2RYI6L.cjs → chunk-EOJFGECD.cjs} +11 -11
- package/dist/chunk-EOJFGECD.cjs.map +1 -0
- package/dist/{chunk-XWV4JT34.js → chunk-ERZ4QPQX.js} +27 -22
- package/dist/chunk-ERZ4QPQX.js.map +1 -0
- package/dist/{chunk-DFVLCOP6.js → chunk-EZH7FNUS.js} +3 -3
- package/dist/{chunk-DFVLCOP6.js.map → chunk-EZH7FNUS.js.map} +1 -1
- package/dist/{chunk-WWFHO375.cjs → chunk-FJMPR3OH.cjs} +4 -3
- package/dist/chunk-FJMPR3OH.cjs.map +1 -0
- package/dist/chunk-FMNUSGZ4.cjs +12 -0
- package/dist/chunk-FMNUSGZ4.cjs.map +1 -0
- package/dist/{chunk-K3Q3LJY3.js → chunk-G32AO634.js} +201 -100
- package/dist/chunk-G32AO634.js.map +1 -0
- package/dist/{chunk-EXU3RASM.js → chunk-G3CSQLLT.js} +20 -474
- package/dist/chunk-G3CSQLLT.js.map +1 -0
- package/dist/chunk-GNPGGLAE.cjs +212 -0
- package/dist/chunk-GNPGGLAE.cjs.map +1 -0
- package/dist/{chunk-QARBLBXT.cjs → chunk-GUUWKPTK.cjs} +7 -7
- package/dist/{chunk-QARBLBXT.cjs.map → chunk-GUUWKPTK.cjs.map} +1 -1
- package/dist/chunk-GYA4JRP5.js +31 -0
- package/dist/chunk-GYA4JRP5.js.map +1 -0
- package/dist/chunk-I6FX7AAG.js +39 -0
- package/dist/chunk-I6FX7AAG.js.map +1 -0
- package/dist/chunk-IMQKXL4E.cjs +12 -0
- package/dist/{chunk-QSXTWU4U.cjs.map → chunk-IMQKXL4E.cjs.map} +1 -1
- package/dist/chunk-J6IJARLG.js +94 -0
- package/dist/chunk-J6IJARLG.js.map +1 -0
- package/dist/{chunk-W63OVYY4.js → chunk-K34OPSJK.js} +3 -3
- package/dist/{chunk-W63OVYY4.js.map → chunk-K34OPSJK.js.map} +1 -1
- package/dist/{chunk-TGOMW4MB.cjs → chunk-KCLZHYPU.cjs} +110 -109
- package/dist/chunk-KCLZHYPU.cjs.map +1 -0
- package/dist/{chunk-XGPUQ56G.js → chunk-KFLXWVUJ.js} +4 -38
- package/dist/chunk-KFLXWVUJ.js.map +1 -0
- package/dist/{chunk-3DS7Z4T4.cjs → chunk-LZ3TVJY4.cjs} +44 -43
- package/dist/chunk-LZ3TVJY4.cjs.map +1 -0
- package/dist/{chunk-UXLSNRYL.js → chunk-MTNEGGM2.js} +4 -4
- package/dist/chunk-MTNEGGM2.js.map +1 -0
- package/dist/{chunk-IP3CGGPA.cjs → chunk-N2V3HJFV.cjs} +92 -185
- package/dist/chunk-N2V3HJFV.cjs.map +1 -0
- package/dist/chunk-NAUA4PW5.cjs +28 -0
- package/dist/chunk-NAUA4PW5.cjs.map +1 -0
- package/dist/chunk-NMQ6C6TS.cjs +61 -0
- package/dist/chunk-NMQ6C6TS.cjs.map +1 -0
- package/dist/{chunk-2N6EOBTH.cjs → chunk-NPWACFQJ.cjs} +58 -53
- package/dist/chunk-NPWACFQJ.cjs.map +1 -0
- package/dist/{chunk-5KEQ74YU.cjs → chunk-NT6ILURI.cjs} +9 -86
- package/dist/chunk-NT6ILURI.cjs.map +1 -0
- package/dist/chunk-NU23DUSJ.cjs +192 -0
- package/dist/chunk-NU23DUSJ.cjs.map +1 -0
- package/dist/{chunk-WOJMKB3N.cjs → chunk-NWYCOFEZ.cjs} +1677 -308
- package/dist/chunk-NWYCOFEZ.cjs.map +1 -0
- package/dist/{chunk-3GH67G4Z.cjs → chunk-O5H62ZWJ.cjs} +4 -42
- package/dist/chunk-O5H62ZWJ.cjs.map +1 -0
- package/dist/{chunk-3SLPDKHQ.js → chunk-PH4IJ3V5.js} +5 -77
- package/dist/chunk-PH4IJ3V5.js.map +1 -0
- package/dist/chunk-PWXGB77L.cjs +56 -0
- package/dist/chunk-PWXGB77L.cjs.map +1 -0
- package/dist/chunk-PZHC5GCD.js +193 -0
- package/dist/chunk-PZHC5GCD.js.map +1 -0
- package/dist/chunk-QMQLUA66.js +12 -0
- package/dist/chunk-QMQLUA66.js.map +1 -0
- package/dist/{chunk-5WWVZMVX.js → chunk-QZ7A6HBM.js} +2 -2
- package/dist/{chunk-5WWVZMVX.js.map → chunk-QZ7A6HBM.js.map} +1 -1
- package/dist/{chunk-VKGKDOKR.js → chunk-RQPRCEIO.js} +1539 -206
- package/dist/chunk-RQPRCEIO.js.map +1 -0
- package/dist/chunk-RW24SAHI.cjs +74 -0
- package/dist/chunk-RW24SAHI.cjs.map +1 -0
- package/dist/{chunk-BVRDGYXQ.cjs → chunk-SAFZ6JTI.cjs} +14 -9
- package/dist/chunk-SAFZ6JTI.cjs.map +1 -0
- package/dist/{chunk-L7HQ2OSI.js → chunk-SCTZRFW5.js} +87 -166
- package/dist/chunk-SCTZRFW5.js.map +1 -0
- package/dist/{chunk-5KPNWT6X.js → chunk-SDHV2MWU.js} +24 -45
- package/dist/chunk-SDHV2MWU.js.map +1 -0
- package/dist/chunk-SVJ5GEXW.cjs +45 -0
- package/dist/chunk-SVJ5GEXW.cjs.map +1 -0
- package/dist/chunk-SVUKGWSN.cjs +102 -0
- package/dist/chunk-SVUKGWSN.cjs.map +1 -0
- package/dist/chunk-TAUGGLNQ.js +59 -0
- package/dist/chunk-TAUGGLNQ.js.map +1 -0
- package/dist/{chunk-J4IUSYFF.js → chunk-TE5ZA4VX.js} +69 -27
- package/dist/chunk-TE5ZA4VX.js.map +1 -0
- package/dist/{chunk-A42GCBGX.cjs → chunk-TRF4EBJT.cjs} +6 -4
- package/dist/chunk-TRF4EBJT.cjs.map +1 -0
- package/dist/{chunk-KQJ54OG5.js → chunk-U4JDJKPD.js} +19 -56
- package/dist/chunk-U4JDJKPD.js.map +1 -0
- package/dist/chunk-UH2USOMG.cjs +627 -0
- package/dist/chunk-UH2USOMG.cjs.map +1 -0
- package/dist/{chunk-RCVLFTCT.js → chunk-UPXDVI3T.js} +13 -12
- package/dist/chunk-UPXDVI3T.js.map +1 -0
- package/dist/{chunk-5VQM6VWP.cjs → chunk-UWG5GX6E.cjs} +2 -2
- package/dist/{chunk-5VQM6VWP.cjs.map → chunk-UWG5GX6E.cjs.map} +1 -1
- package/dist/{chunk-3RWZPJKV.js → chunk-VBH7ZXSZ.js} +21 -78
- package/dist/chunk-VBH7ZXSZ.js.map +1 -0
- package/dist/{chunk-K5UBVGJN.js → chunk-VDYA2HMS.js} +6 -6
- package/dist/{chunk-K5UBVGJN.js.map → chunk-VDYA2HMS.js.map} +1 -1
- package/dist/chunk-X4PVHAZ6.cjs +83 -0
- package/dist/chunk-X4PVHAZ6.cjs.map +1 -0
- package/dist/{chunk-UYQMBBWJ.js → chunk-X6CNEA32.js} +23 -20
- package/dist/chunk-X6CNEA32.js.map +1 -0
- package/dist/chunk-X6RDQ5NB.cjs +335 -0
- package/dist/chunk-X6RDQ5NB.cjs.map +1 -0
- package/dist/chunk-XD6X7O5R.js +184 -0
- package/dist/chunk-XD6X7O5R.js.map +1 -0
- package/dist/{chunk-DIQ3AV5W.cjs → chunk-XFY73JWD.cjs} +324 -224
- package/dist/chunk-XFY73JWD.cjs.map +1 -0
- package/dist/{chunk-DEFQM7JU.cjs → chunk-XRU7V7FF.cjs} +7 -7
- package/dist/{chunk-DEFQM7JU.cjs.map → chunk-XRU7V7FF.cjs.map} +1 -1
- package/dist/{chunk-TPF25IG6.js → chunk-XZA3Y4YH.js} +3 -3
- package/dist/{chunk-TPF25IG6.js.map → chunk-XZA3Y4YH.js.map} +1 -1
- package/dist/chunk-Y7M44XEK.js +462 -0
- package/dist/chunk-Y7M44XEK.js.map +1 -0
- package/dist/{chunk-RRSNR3TP.js → chunk-YIRLBUNN.js} +3 -3
- package/dist/{chunk-RRSNR3TP.js.map → chunk-YIRLBUNN.js.map} +1 -1
- package/dist/{chunk-IXGYRP2P.js → chunk-YJDSPA5E.js} +79 -49
- package/dist/chunk-YJDSPA5E.js.map +1 -0
- package/dist/{chunk-JBNOGRKW.cjs → chunk-YLINFV7Z.cjs} +157 -115
- package/dist/chunk-YLINFV7Z.cjs.map +1 -0
- package/dist/{chunk-QERAIDRJ.js → chunk-Z2PPIVOO.js} +82 -22
- package/dist/chunk-Z2PPIVOO.js.map +1 -0
- package/dist/chunk-Z5QHVL5U.cjs +12 -0
- package/dist/chunk-Z5QHVL5U.cjs.map +1 -0
- package/dist/chunk-ZDH3DX3C.cjs +30 -0
- package/dist/chunk-ZDH3DX3C.cjs.map +1 -0
- package/dist/chunk-ZE6NVENI.js +77 -0
- package/dist/chunk-ZE6NVENI.js.map +1 -0
- package/dist/chunk-ZHX4KEM7.cjs +49 -0
- package/dist/chunk-ZHX4KEM7.cjs.map +1 -0
- package/dist/chunk-ZKZAIX42.cjs +479 -0
- package/dist/chunk-ZKZAIX42.cjs.map +1 -0
- package/dist/{chunk-TEDRJXOG.cjs → chunk-ZY4GXIVN.cjs} +5 -5
- package/dist/{chunk-TEDRJXOG.cjs.map → chunk-ZY4GXIVN.cjs.map} +1 -1
- package/dist/core/index.cjs +117 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +225 -0
- package/dist/core/index.d.ts +225 -0
- package/dist/core/index.js +12 -0
- package/dist/core/index.js.map +1 -0
- package/dist/{ddl-CS0KUVwB.d.ts → ddl-Dx3Z0_WC.d.ts} +3 -3
- package/dist/{ddl-BD-ZfKeX.d.cts → ddl-J6sDyABg.d.cts} +3 -3
- package/dist/define-graph-CzEvA_8F.d.cts +174 -0
- package/dist/define-graph-DRo9xpYN.d.ts +174 -0
- package/dist/{extension-types-BM2ACfYO.d.cts → extension-types-BLEVH4SG.d.cts} +1 -1
- package/dist/{extension-types-BM2ACfYO.d.ts → extension-types-BLEVH4SG.d.ts} +1 -1
- package/dist/graph-extension/index.cjs +21 -19
- package/dist/graph-extension/index.d.cts +4 -4
- package/dist/graph-extension/index.d.ts +4 -4
- package/dist/graph-extension/index.js +6 -4
- package/dist/graph-merge/index.cjs +265 -214
- package/dist/graph-merge/index.cjs.map +1 -1
- package/dist/graph-merge/index.d.cts +8 -89
- package/dist/graph-merge/index.d.ts +8 -89
- package/dist/graph-merge/index.js +141 -90
- package/dist/graph-merge/index.js.map +1 -1
- package/dist/{index-BeacbPoe.d.ts → index-BD_3TCgh.d.ts} +6 -4
- package/dist/{index-BPM59vsg.d.cts → index-BihFPsPu.d.cts} +6 -4
- package/dist/{fulltext-strategy-C27vXaeB.d.cts → index-Bq7vSPHy.d.ts} +3195 -2646
- package/dist/{fulltext-strategy-DebsMrqg.d.ts → index-CrFL_ENI.d.cts} +3195 -2646
- package/dist/index.cjs +326 -315
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +59 -240
- package/dist/index.d.ts +59 -240
- package/dist/index.js +46 -79
- package/dist/index.js.map +1 -1
- package/dist/indexes/index.cjs +26 -38
- package/dist/indexes/index.d.cts +6 -41
- package/dist/indexes/index.d.ts +6 -41
- package/dist/indexes/index.js +14 -10
- package/dist/interchange/index.cjs +48 -39
- package/dist/interchange/index.cjs.map +1 -1
- package/dist/interchange/index.d.cts +7 -8
- package/dist/interchange/index.d.ts +7 -8
- package/dist/interchange/index.js +23 -14
- package/dist/interchange/index.js.map +1 -1
- package/dist/local-options-CZ1BnIoF.d.cts +29 -0
- package/dist/local-options-CZ1BnIoF.d.ts +29 -0
- package/dist/{manager-D00_NXvT.d.ts → manager-CASfhmzV.d.ts} +4 -173
- package/dist/{manager-nU1vTJLy.d.cts → manager-nCEJiYBb.d.cts} +4 -173
- package/dist/{materialize-indexes-zK2J_flP.d.ts → materialize-indexes-D4iei4Kp.d.ts} +1 -1
- package/dist/{materialize-indexes-CuR3gAZb.d.cts → materialize-indexes-ExQ6OrAh.d.cts} +1 -1
- package/dist/{postgres-IaBA4RgE.d.ts → postgres-Cl1ZAN1G.d.ts} +1 -1
- package/dist/{postgres-YrYmPlaU.d.cts → postgres-DMgIKQU-.d.cts} +1 -1
- package/dist/postgres-execution-fKW0qRiN.d.cts +14 -0
- package/dist/postgres-execution-fKW0qRiN.d.ts +14 -0
- package/dist/profiler/index.cjs +9 -8
- package/dist/profiler/index.cjs.map +1 -1
- package/dist/profiler/index.d.cts +9 -17
- package/dist/profiler/index.d.ts +9 -17
- package/dist/profiler/index.js +8 -7
- package/dist/profiler/index.js.map +1 -1
- package/dist/provenance/index.cjs +61 -55
- package/dist/provenance/index.cjs.map +1 -1
- package/dist/provenance/index.d.cts +7 -8
- package/dist/provenance/index.d.ts +7 -8
- package/dist/provenance/index.js +34 -28
- package/dist/provenance/index.js.map +1 -1
- package/dist/schema/index.cjs +46 -37
- package/dist/schema/index.cjs.map +1 -1
- package/dist/schema/index.d.cts +8 -10
- package/dist/schema/index.d.ts +8 -10
- package/dist/schema/index.js +22 -13
- package/dist/schema/index.js.map +1 -1
- package/dist/{sqlite-BUOHPx7p.d.ts → sqlite-BDkW39aa.d.cts} +1 -1
- package/dist/{sqlite-Pp8O19WE.d.cts → sqlite-CYfhvESj.d.ts} +1 -1
- package/dist/sqlite-execution-DwbE2a9y.d.cts +32 -0
- package/dist/sqlite-execution-DwbE2a9y.d.ts +32 -0
- package/dist/{store-view-X96Rd00T.d.cts → store-view-BoHqdHjB.d.cts} +394 -1393
- package/dist/{store-view-ANL6mTph.d.ts → store-view-Ctq-3OHy.d.ts} +394 -1393
- package/dist/temporal-BC_NQV5Y.d.cts +281 -0
- package/dist/temporal-DqtOEo_B.d.ts +281 -0
- package/dist/{types-r-Zyq2Hz.d.cts → types-COq3-vMC.d.cts} +2 -2
- package/dist/{types-wsvuBgPK.d.ts → types-CUevi_D1.d.ts} +2 -2
- package/dist/{where-CJOpJj3a.d.ts → where-BdE_cYtx.d.ts} +5 -5
- package/dist/{where-K3uBP33l.d.cts → where-C92TXCzT.d.cts} +5 -5
- package/package.json +37 -6
- package/dist/chunk-27SSDCEP.cjs.map +0 -1
- package/dist/chunk-2N6EOBTH.cjs.map +0 -1
- package/dist/chunk-3C2RYI6L.cjs.map +0 -1
- package/dist/chunk-3DS7Z4T4.cjs.map +0 -1
- package/dist/chunk-3GH67G4Z.cjs.map +0 -1
- package/dist/chunk-3RWZPJKV.js.map +0 -1
- package/dist/chunk-3SLPDKHQ.js.map +0 -1
- package/dist/chunk-3XXGYU62.cjs.map +0 -1
- package/dist/chunk-44TA22QT.js +0 -1478
- package/dist/chunk-44TA22QT.js.map +0 -1
- package/dist/chunk-552KNYQJ.js.map +0 -1
- package/dist/chunk-5KEQ74YU.cjs.map +0 -1
- package/dist/chunk-5KPNWT6X.js.map +0 -1
- package/dist/chunk-5PNMDJ7J.js.map +0 -1
- package/dist/chunk-6EEO3OVU.cjs.map +0 -1
- package/dist/chunk-7YSP4V4R.cjs +0 -69
- package/dist/chunk-7YSP4V4R.cjs.map +0 -1
- package/dist/chunk-A42GCBGX.cjs.map +0 -1
- package/dist/chunk-BVRDGYXQ.cjs.map +0 -1
- package/dist/chunk-BYPOGQWK.js.map +0 -1
- package/dist/chunk-CUHM5CWJ.cjs +0 -12
- package/dist/chunk-CUHM5CWJ.cjs.map +0 -1
- package/dist/chunk-DIQ3AV5W.cjs.map +0 -1
- package/dist/chunk-EXU3RASM.js.map +0 -1
- package/dist/chunk-IP3CGGPA.cjs.map +0 -1
- package/dist/chunk-IPSVVTWT.cjs +0 -1540
- package/dist/chunk-IPSVVTWT.cjs.map +0 -1
- package/dist/chunk-IXGYRP2P.js.map +0 -1
- package/dist/chunk-J4IUSYFF.js.map +0 -1
- package/dist/chunk-JBNOGRKW.cjs.map +0 -1
- package/dist/chunk-K3Q3LJY3.js.map +0 -1
- package/dist/chunk-KQJ54OG5.js.map +0 -1
- package/dist/chunk-L7HQ2OSI.js.map +0 -1
- package/dist/chunk-M6VES7V6.js +0 -239
- package/dist/chunk-M6VES7V6.js.map +0 -1
- package/dist/chunk-NBP2WTJW.cjs.map +0 -1
- package/dist/chunk-NUIG3BCV.cjs.map +0 -1
- package/dist/chunk-NXQFATMF.cjs.map +0 -1
- package/dist/chunk-OHMP6N2J.js +0 -47
- package/dist/chunk-OHMP6N2J.js.map +0 -1
- package/dist/chunk-QERAIDRJ.js.map +0 -1
- package/dist/chunk-QSXTWU4U.cjs +0 -12
- package/dist/chunk-RCVLFTCT.js.map +0 -1
- package/dist/chunk-TGOMW4MB.cjs.map +0 -1
- package/dist/chunk-TKT2XHED.js.map +0 -1
- package/dist/chunk-UGZUAYAR.js.map +0 -1
- package/dist/chunk-UXLSNRYL.js.map +0 -1
- package/dist/chunk-UYQMBBWJ.js.map +0 -1
- package/dist/chunk-VKGKDOKR.js.map +0 -1
- package/dist/chunk-VL2V6PEN.cjs +0 -261
- package/dist/chunk-VL2V6PEN.cjs.map +0 -1
- package/dist/chunk-WOJMKB3N.cjs.map +0 -1
- package/dist/chunk-WWFHO375.cjs.map +0 -1
- package/dist/chunk-XGPUQ56G.js.map +0 -1
- package/dist/chunk-XGU7DZDA.cjs +0 -1095
- package/dist/chunk-XGU7DZDA.cjs.map +0 -1
- package/dist/chunk-XPCZADMT.cjs.map +0 -1
- package/dist/chunk-XWV4JT34.js.map +0 -1
|
@@ -1,25 +1,32 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { compareStrings, compareCodePoints } from './chunk-DRACN6XG.js';
|
|
2
|
+
import { createEdgeRowMapper, createNodeRowMapper, SQLITE_ROW_MAPPER_CONFIG, POSTGRES_ROW_MAPPER_CONFIG } from './chunk-AOL64O4Z.js';
|
|
3
|
+
import { rowToNode, executeNodeBulkFindByIndex, executeNodeBulkFindByConstraint, executeNodeFindByConstraint, executeNodeBulkGetOrCreateByConstraint, executeNodeGetOrCreateByConstraint, executeNodeHardDelete, executeNodeDelete, nodeUpsertDirtyCheck, executeNodeUpsertUpdate, executeNodeUpdate, executeNodeCreateNoReturnBatch, executeNodeCreateBatch, executeNodeCreate, rowToEdge, runInWriteTransaction, checkCardinalityConstraint, runHookedWriteOperation, rowToNodeMeta, rowToEdgeMeta } from './chunk-UPXDVI3T.js';
|
|
4
|
+
import { isParameterRef, fieldRef, buildFieldBuilderForTypeInfo, stringField, createFulltextAccessor, storeRuntime, CURRENT_READ_INSTANT_PLACEHOLDER, DEFAULT_SQL_SCHEMA, requireSqlSchema, recordedReadSchemaFor, withPinnedReadInstant, STORE_RUNTIME, assertRevisionTrackableBackend, createSqlSchema, requireExternalRecordedReadSource, createRecordedReadBinding, createRecordedBackend, readRecordedClock, ensureRevisionOrigin, TRANSACTION_RUNTIME, withRecordedFlushObserver, recordedCaptureRequiresCallbackTransactionError, assertRecordedCaptureTransactionIsolation, createRecordedTransactionScope, lockRecordedGraphWrite, generateId, createGraphBackendProjection, vectorSlotKey, baseField, objectField, arrayField, dateField, numberField, computeFulltextContent, AUTO_REFRESH_STATISTICS_ROW_THRESHOLD, throwHistoryUnsafeSqlAccess, throwRevisionTrackingUnsafeSqlAccess, advanceRevisionClock, recordedReadSqlSchema, requireRecordedReadBinding, runInsertBatch, edgeInsertDispatch, runInsertBatchReturning, projectBackendMembers, sqlValueList, getEmbeddingFields, getNodeRowsByIds, getEdgeRowsByIds, compileKindFilter, currentReadInstant, compileTemporalFilter, validateEdgeEndpoints, buildPredicateIndex, compileFieldValue, recordedBindParamBudget, extractVectorSimilarityPredicates, extractFulltextMatchPredicates, currentReadInstantFor, extractTemporalOptions, compilePredicateExpression, getPredicatesForAlias, getFieldPointer, getNodeKindsForAlias, getHybridTargetAlias, closeRecordedHardDeletedKind, compilePredicateClauses, ALIAS_CTE_PREFIX, EMBEDDINGS_CTE_ALIAS, FULLTEXT_CTE_ALIAS, HYBRID_CANDIDATES_CTE_ALIAS } from './chunk-RQPRCEIO.js';
|
|
5
|
+
import { chunk } from './chunk-35S6P5ZU.js';
|
|
6
|
+
import { runOptionallyInTransaction, createTransactionReadBackend, rowPropsToObject, createBackendOverlay, INTERNAL_TEMPORARY_WRITES } from './chunk-PZHC5GCD.js';
|
|
7
|
+
import { resolveReadCoordinate, withRecordedCoordinate, describeCoordinate, coordinateContext, asRecordedInstant, assertValidRecordedInstant } from './chunk-J6IJARLG.js';
|
|
8
|
+
import { loadAndMergeGraphExtensionDocument, ensureSchema, loadAndVerifyGraph, buildKindRegistry, mergeGraphExtension, commitNewSchemaVersion, applyDeprecatedKinds, loadActiveSchemaWithBootstrap, parseSerializedSchema, extensionKindNames, serializeSchemaProperties, buildGraphExtensionOntologyKeySet, compileTimeOntologyKey, serializeIndexDeclaration } from './chunk-VBH7ZXSZ.js';
|
|
9
|
+
import { getTypeName } from './chunk-76HE7DJP.js';
|
|
10
|
+
import { validateEdgeProps } from './chunk-ZE6NVENI.js';
|
|
5
11
|
import { canonicalEqual, sortedReplacer } from './chunk-UR7W5YQK.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
12
|
+
import { withRecordedRelationsPrecondition, isMissingTableError } from './chunk-KFLXWVUJ.js';
|
|
13
|
+
import { isKnownKind } from './chunk-PH4IJ3V5.js';
|
|
14
|
+
import { nowIso, validateOptionalCanonicalIsoDate } from './chunk-I6FX7AAG.js';
|
|
15
|
+
import { generateIndexDDL } from './chunk-U4JDJKPD.js';
|
|
16
|
+
import { SYSTEM_INDEX_DECLARATIONS, resolveSystemIndexTableName, systemIndexName, resolveSystemIndexNames, generateSystemIndexDDL } from './chunk-BQITNFQJ.js';
|
|
17
|
+
import { NODE_META_KEYS, EDGE_META_KEYS } from './chunk-VDYA2HMS.js';
|
|
18
|
+
import { sha256Hex, fnv1aBase36 } from './chunk-K34OPSJK.js';
|
|
19
|
+
import { DEFAULT_PAGINATION_LIMIT, DEFAULT_STREAM_BATCH_SIZE, SQLITE_PATH_DELIMITER, PG_ARRAY_START, PG_ARRAY_END, PG_PATH_ELEMENT_SEPARATOR, MAX_PG_IDENTIFIER_LENGTH } from './chunk-2EBMPJBO.js';
|
|
20
|
+
import { getDialect } from './chunk-G3CSQLLT.js';
|
|
21
|
+
import { assertVectorMinScore, vectorScoreExpression, vectorMinScoreCondition } from './chunk-Y7M44XEK.js';
|
|
22
|
+
import { isSqlPlaceholder, bindSqlValue, markAnnIndexScan, asCompiledSelectSql, isRawExecutable, annIndexScanTypes, sql, asCompiledRowsSql, markForceCustomPlan, asCompiledTemporaryStatementSql, asCompiledStatementSql } from './chunk-6XDBRDZE.js';
|
|
23
|
+
import { createSchemaIntrospector } from './chunk-D7PG5D5K.js';
|
|
24
|
+
import { requireDefined, isPresent } from './chunk-QMQLUA66.js';
|
|
19
25
|
import { getSearchableFields, resolveEmbeddingFields, resolveGraphVectorSlots, resolveDeclaredFulltextLanguage } from './chunk-PC2UBAUB.js';
|
|
20
|
-
import {
|
|
26
|
+
import { IncompatibleChangeError, RemoveCompileTimeKindError, KindHasReferentsError } from './chunk-SCTZRFW5.js';
|
|
27
|
+
import { validateProjectionField } from './chunk-XZA3Y4YH.js';
|
|
28
|
+
import { ConfigurationError, UnsupportedPredicateError, ValidationError, KindNotFoundError, EndpointError, EagerMaterializationError, CompilerInvariantError, CardinalityError, EdgeNotFoundError, DatabaseOperationError, UnsupportedBackendCapabilityError, GraphAlgorithmConvergenceError, EndpointNotFoundError, InvalidEdgeWeightError } from './chunk-DPNA466P.js';
|
|
21
29
|
import { jsonPointer, parseJsonPointer, resolveJsonPointer } from './chunk-G6Q5UM7U.js';
|
|
22
|
-
import { Placeholder, sql } from 'drizzle-orm';
|
|
23
30
|
|
|
24
31
|
// src/store/collection-surface.ts
|
|
25
32
|
var CURRENT_ONLY_READ_NAMES = [
|
|
@@ -279,7 +286,7 @@ function pinnedCollections(live, coordinate, isKind, wrap) {
|
|
|
279
286
|
if (cached !== void 0) return cached;
|
|
280
287
|
const wrapped = wrap(
|
|
281
288
|
kind,
|
|
282
|
-
live[kind],
|
|
289
|
+
requireDefined(live[kind]),
|
|
283
290
|
coordinate
|
|
284
291
|
);
|
|
285
292
|
cache.set(kind, wrapped);
|
|
@@ -306,15 +313,15 @@ function pinnedEdgeCollectionsFor(store, coordinate, wrap) {
|
|
|
306
313
|
}
|
|
307
314
|
function recordedNodeCollection(store, kind, live, coordinate) {
|
|
308
315
|
const reads = {
|
|
309
|
-
getById: (id) => store.recordedNodeGetById(kind, id, coordinate),
|
|
310
|
-
getByIds: (ids) => store.recordedNodeGetByIds(kind, ids, coordinate)
|
|
316
|
+
getById: (id) => storeRuntime(store).recordedNodeGetById(kind, id, coordinate),
|
|
317
|
+
getByIds: (ids) => storeRuntime(store).recordedNodeGetByIds(kind, ids, coordinate)
|
|
311
318
|
};
|
|
312
319
|
return recordedCollectionProxy(reads, live, coordinate, "node");
|
|
313
320
|
}
|
|
314
321
|
function recordedEdgeCollection(store, kind, live, coordinate) {
|
|
315
322
|
const reads = {
|
|
316
|
-
getById: (id) => store.recordedEdgeGetById(kind, id, coordinate),
|
|
317
|
-
getByIds: (ids) => store.recordedEdgeGetByIds(kind, ids, coordinate)
|
|
323
|
+
getById: (id) => storeRuntime(store).recordedEdgeGetById(kind, id, coordinate),
|
|
324
|
+
getByIds: (ids) => storeRuntime(store).recordedEdgeGetByIds(kind, ids, coordinate)
|
|
318
325
|
};
|
|
319
326
|
return recordedCollectionProxy(reads, live, coordinate, "edge");
|
|
320
327
|
}
|
|
@@ -414,12 +421,12 @@ var CoordinatePinnedView = class {
|
|
|
414
421
|
* view's coordinate cannot be overridden on a per-query basis.
|
|
415
422
|
*/
|
|
416
423
|
query() {
|
|
417
|
-
return this.store.sealedQuery(this.coordinate);
|
|
424
|
+
return storeRuntime(this.store).sealedQuery(this.coordinate);
|
|
418
425
|
}
|
|
419
426
|
internalAlgorithms() {
|
|
420
|
-
this.#internalAlgorithms ??=
|
|
421
|
-
this.
|
|
422
|
-
);
|
|
427
|
+
this.#internalAlgorithms ??= storeRuntime(
|
|
428
|
+
this.store
|
|
429
|
+
).algorithmsAtCoordinate(this.coordinate);
|
|
423
430
|
return this.#internalAlgorithms;
|
|
424
431
|
}
|
|
425
432
|
/** Graph algorithms pinned to this view's immutable temporal coordinate. */
|
|
@@ -431,7 +438,10 @@ var CoordinatePinnedView = class {
|
|
|
431
438
|
canReach: (from, to, options) => this.canReach(from, to, options),
|
|
432
439
|
neighbors: (node, options) => this.neighbors(node, options),
|
|
433
440
|
degree: (node, options) => this.degree(node, options),
|
|
434
|
-
|
|
441
|
+
labelPropagation: (options) => this.labelPropagation(options),
|
|
442
|
+
weaklyConnectedComponents: (options) => this.weaklyConnectedComponents(options),
|
|
443
|
+
pageRank: (options) => this.pageRank(options),
|
|
444
|
+
personalizedPageRank: (options) => this.personalizedPageRank(options)
|
|
435
445
|
});
|
|
436
446
|
return this.#algorithmFacade;
|
|
437
447
|
}
|
|
@@ -441,7 +451,10 @@ var CoordinatePinnedView = class {
|
|
|
441
451
|
...options,
|
|
442
452
|
...withCoordinate(this.coordinate)
|
|
443
453
|
};
|
|
444
|
-
return this.store.subgraphAtCoordinate(
|
|
454
|
+
return storeRuntime(this.store).subgraphAtCoordinate(
|
|
455
|
+
rootId,
|
|
456
|
+
internalOptions
|
|
457
|
+
);
|
|
445
458
|
}
|
|
446
459
|
/** Shortest path between two nodes at this view's pinned coordinate. */
|
|
447
460
|
shortestPath(from, to, options) {
|
|
@@ -485,6 +498,13 @@ var CoordinatePinnedView = class {
|
|
|
485
498
|
...withCoordinate(this.coordinate)
|
|
486
499
|
});
|
|
487
500
|
}
|
|
501
|
+
/** Deterministic label-propagation memberships at this view's coordinate. */
|
|
502
|
+
labelPropagation(options) {
|
|
503
|
+
return this.internalAlgorithms().labelPropagation({
|
|
504
|
+
...options,
|
|
505
|
+
...withCoordinate(this.coordinate)
|
|
506
|
+
});
|
|
507
|
+
}
|
|
488
508
|
/** Exact WCC memberships at this view's pinned coordinate. */
|
|
489
509
|
weaklyConnectedComponents(options) {
|
|
490
510
|
return this.internalAlgorithms().weaklyConnectedComponents({
|
|
@@ -492,6 +512,20 @@ var CoordinatePinnedView = class {
|
|
|
492
512
|
...withCoordinate(this.coordinate)
|
|
493
513
|
});
|
|
494
514
|
}
|
|
515
|
+
/** Global PageRank scores at this view's pinned coordinate. */
|
|
516
|
+
pageRank(options) {
|
|
517
|
+
return this.internalAlgorithms().pageRank({
|
|
518
|
+
...options,
|
|
519
|
+
...withCoordinate(this.coordinate)
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
/** Personalized PageRank scores at this view's pinned coordinate. */
|
|
523
|
+
personalizedPageRank(options) {
|
|
524
|
+
return this.internalAlgorithms().personalizedPageRank({
|
|
525
|
+
...options,
|
|
526
|
+
...withCoordinate(this.coordinate)
|
|
527
|
+
});
|
|
528
|
+
}
|
|
495
529
|
};
|
|
496
530
|
var StoreView = class extends CoordinatePinnedView {
|
|
497
531
|
#nodes;
|
|
@@ -788,6 +822,8 @@ function inspectSetOperationPlan(logicalPlan) {
|
|
|
788
822
|
sortNode
|
|
789
823
|
};
|
|
790
824
|
}
|
|
825
|
+
|
|
826
|
+
// src/query/compiler/emitter/recursive.ts
|
|
791
827
|
function assertRecursiveEmitterClauseAlignment(logicalPlan, input) {
|
|
792
828
|
const planShape = inspectRecursiveProjectPlan(logicalPlan);
|
|
793
829
|
if (planShape.hasSort && input.orderBy === void 0) {
|
|
@@ -832,6 +868,8 @@ function emitRecursiveQuerySql(input) {
|
|
|
832
868
|
}
|
|
833
869
|
return sql.join(parts, sql` `);
|
|
834
870
|
}
|
|
871
|
+
|
|
872
|
+
// src/query/compiler/emitter/set-operations.ts
|
|
835
873
|
function assertSetOperationEmitterClauseAlignment(logicalPlan, suffixClauses) {
|
|
836
874
|
const shape = inspectSetOperationPlan(logicalPlan);
|
|
837
875
|
const hasSuffixClauses = suffixClauses !== void 0 && suffixClauses.length > 0;
|
|
@@ -874,6 +912,8 @@ function emitSetOperationQuerySql(input) {
|
|
|
874
912
|
}
|
|
875
913
|
return sql.join(parts, sql` `);
|
|
876
914
|
}
|
|
915
|
+
|
|
916
|
+
// src/query/compiler/emitter/standard.ts
|
|
877
917
|
function assertStandardEmitterClauseAlignment(logicalPlan, input) {
|
|
878
918
|
const planShape = inspectStandardProjectPlan(logicalPlan);
|
|
879
919
|
if (input.groupBy !== void 0 && !planShape.hasAggregate) {
|
|
@@ -942,7 +982,7 @@ function truncateToBytes(value, maxBytes) {
|
|
|
942
982
|
const encoded = TEXT_ENCODER.encode(value);
|
|
943
983
|
if (encoded.byteLength <= maxBytes) return value;
|
|
944
984
|
let end = maxBytes;
|
|
945
|
-
while (end > 0 && encoded[end] >= 128 && encoded[end] < 192) {
|
|
985
|
+
while (end > 0 && requireDefined(encoded[end]) >= 128 && requireDefined(encoded[end]) < 192) {
|
|
946
986
|
end--;
|
|
947
987
|
}
|
|
948
988
|
return new TextDecoder().decode(encoded.slice(0, end));
|
|
@@ -1009,6 +1049,94 @@ function compileSelectivePropsExtraction(field2, column, dialect) {
|
|
|
1009
1049
|
});
|
|
1010
1050
|
}
|
|
1011
1051
|
|
|
1052
|
+
// src/query/compiler/utils.ts
|
|
1053
|
+
var NODE_COLUMNS = [
|
|
1054
|
+
"id",
|
|
1055
|
+
"kind",
|
|
1056
|
+
"props",
|
|
1057
|
+
"version",
|
|
1058
|
+
"valid_from",
|
|
1059
|
+
"valid_to",
|
|
1060
|
+
"created_at",
|
|
1061
|
+
"updated_at",
|
|
1062
|
+
"deleted_at"
|
|
1063
|
+
];
|
|
1064
|
+
var EDGE_COLUMNS = [
|
|
1065
|
+
"id",
|
|
1066
|
+
"kind",
|
|
1067
|
+
"from_id",
|
|
1068
|
+
"to_id",
|
|
1069
|
+
"props",
|
|
1070
|
+
"valid_from",
|
|
1071
|
+
"valid_to",
|
|
1072
|
+
"created_at",
|
|
1073
|
+
"updated_at",
|
|
1074
|
+
"deleted_at"
|
|
1075
|
+
];
|
|
1076
|
+
var EMPTY_REQUIRED_COLUMNS = /* @__PURE__ */ new Set();
|
|
1077
|
+
function quoteIdentifier(identifier) {
|
|
1078
|
+
return sql.identifier(identifier);
|
|
1079
|
+
}
|
|
1080
|
+
function shouldProjectColumn(requiredColumns, column, alwaysRequiredColumns) {
|
|
1081
|
+
if (alwaysRequiredColumns?.has(column)) return true;
|
|
1082
|
+
if (requiredColumns === void 0) return true;
|
|
1083
|
+
return requiredColumns.has(column);
|
|
1084
|
+
}
|
|
1085
|
+
function addRequiredColumn(requiredColumnsByAlias, alias, column) {
|
|
1086
|
+
const existing = requiredColumnsByAlias.get(alias);
|
|
1087
|
+
if (existing) {
|
|
1088
|
+
existing.add(column);
|
|
1089
|
+
return;
|
|
1090
|
+
}
|
|
1091
|
+
requiredColumnsByAlias.set(alias, /* @__PURE__ */ new Set([column]));
|
|
1092
|
+
}
|
|
1093
|
+
function markFieldRefAsRequired(requiredColumnsByAlias, field2) {
|
|
1094
|
+
const column = field2.path[0];
|
|
1095
|
+
if (column === void 0) return;
|
|
1096
|
+
addRequiredColumn(requiredColumnsByAlias, field2.alias, column);
|
|
1097
|
+
}
|
|
1098
|
+
function mapSelectiveSystemFieldToColumn(field2) {
|
|
1099
|
+
if (field2 === "fromId") return "from_id";
|
|
1100
|
+
if (field2 === "toId") return "to_id";
|
|
1101
|
+
if (field2.startsWith("meta.")) {
|
|
1102
|
+
return field2.slice(5).replaceAll(/([A-Z])/g, "_$1").toLowerCase();
|
|
1103
|
+
}
|
|
1104
|
+
return field2;
|
|
1105
|
+
}
|
|
1106
|
+
function markSelectiveFieldAsRequired(requiredColumnsByAlias, field2) {
|
|
1107
|
+
if (field2.isSystemField) {
|
|
1108
|
+
addRequiredColumn(
|
|
1109
|
+
requiredColumnsByAlias,
|
|
1110
|
+
field2.alias,
|
|
1111
|
+
mapSelectiveSystemFieldToColumn(field2.field)
|
|
1112
|
+
);
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
addRequiredColumn(requiredColumnsByAlias, field2.alias, "props");
|
|
1116
|
+
}
|
|
1117
|
+
function getTopLevelPropsFieldName(field2) {
|
|
1118
|
+
const pointer = getFieldPointer(field2);
|
|
1119
|
+
if (pointer === void 0) return void 0;
|
|
1120
|
+
const segments = parseJsonPointer(pointer);
|
|
1121
|
+
return segments.length === 1 ? segments[0] : void 0;
|
|
1122
|
+
}
|
|
1123
|
+
function findSelectivePropsFieldForFieldRef(selectiveFields, field2) {
|
|
1124
|
+
if (selectiveFields === void 0 || selectiveFields.length === 0) {
|
|
1125
|
+
return void 0;
|
|
1126
|
+
}
|
|
1127
|
+
const propsFieldName = getTopLevelPropsFieldName(field2);
|
|
1128
|
+
if (propsFieldName === void 0) return void 0;
|
|
1129
|
+
return selectiveFields.find(
|
|
1130
|
+
(selectiveField) => !selectiveField.isSystemField && selectiveField.alias === field2.alias && selectiveField.field === propsFieldName
|
|
1131
|
+
);
|
|
1132
|
+
}
|
|
1133
|
+
function isIdFieldRef(field2) {
|
|
1134
|
+
return field2.path.length === 1 && field2.path[0] === "id" && field2.jsonPointer === void 0;
|
|
1135
|
+
}
|
|
1136
|
+
function isAggregateExpr(source) {
|
|
1137
|
+
return "__type" in source && source.__type === "aggregate";
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1012
1140
|
// src/query/compiler/emitter/standard-builders.ts
|
|
1013
1141
|
function compileColumnReference(tableAlias, column) {
|
|
1014
1142
|
if (tableAlias === void 0) {
|
|
@@ -1137,7 +1265,7 @@ function buildStandardTraversalCte(input) {
|
|
|
1137
1265
|
traversalIndex,
|
|
1138
1266
|
traversalLimit
|
|
1139
1267
|
} = input;
|
|
1140
|
-
const traversal = ast.traversals[traversalIndex];
|
|
1268
|
+
const traversal = requireDefined(ast.traversals[traversalIndex]);
|
|
1141
1269
|
const traversalLimitValue = traversalIndex === ast.traversals.length - 1 ? traversalLimit : void 0;
|
|
1142
1270
|
const previousNodeKinds = getNodeKindsForAlias(ast, traversal.joinFromAlias);
|
|
1143
1271
|
const directEdgeKinds = [...new Set(traversal.edgeKinds)];
|
|
@@ -1540,7 +1668,10 @@ function buildLateMaterializedTopKCte(input) {
|
|
|
1540
1668
|
limit: input.limit,
|
|
1541
1669
|
offset: input.offset
|
|
1542
1670
|
});
|
|
1543
|
-
const parts = [
|
|
1671
|
+
const parts = [
|
|
1672
|
+
sql`SELECT ${sql.join(columns, sql`, `)}`,
|
|
1673
|
+
fromClause
|
|
1674
|
+
];
|
|
1544
1675
|
if (innerOrderBy !== void 0) parts.push(innerOrderBy);
|
|
1545
1676
|
if (limitOffset !== void 0) parts.push(limitOffset);
|
|
1546
1677
|
return sql`${sql.raw(LATE_MAT_TOPK_CTE_ALIAS)} AS (${sql.join(parts, sql` `)})`;
|
|
@@ -2369,7 +2500,7 @@ function lowerSetOperationToLogicalPlanNode(op, graphId, dialect, nextPlanNodeId
|
|
|
2369
2500
|
if (op.limit !== void 0 && op.offset !== void 0) {
|
|
2370
2501
|
currentNode = { ...limitOffsetBase, limit: op.limit, offset: op.offset };
|
|
2371
2502
|
} else if (op.limit === void 0) {
|
|
2372
|
-
currentNode = { ...limitOffsetBase, offset: op.offset };
|
|
2503
|
+
currentNode = { ...limitOffsetBase, offset: requireDefined(op.offset) };
|
|
2373
2504
|
} else {
|
|
2374
2505
|
currentNode = { ...limitOffsetBase, limit: op.limit };
|
|
2375
2506
|
}
|
|
@@ -2995,6 +3126,8 @@ function decodeByValueType(value, valueType) {
|
|
|
2995
3126
|
}
|
|
2996
3127
|
}
|
|
2997
3128
|
}
|
|
3129
|
+
|
|
3130
|
+
// src/store/recursive-cte.ts
|
|
2998
3131
|
function buildReachableCte(options) {
|
|
2999
3132
|
const trackPath = options.cyclePolicy === "prevent" || options.includePath;
|
|
3000
3133
|
const edgeKindFilter = compileKindFilter(
|
|
@@ -3196,26 +3329,35 @@ async function executeSubgraph(params) {
|
|
|
3196
3329
|
});
|
|
3197
3330
|
const includedIdsCte = buildIncludedIdsCte(ctx);
|
|
3198
3331
|
let membership;
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3332
|
+
const dialect = ctx.dialect.name;
|
|
3333
|
+
switch (dialect) {
|
|
3334
|
+
case "postgres": {
|
|
3335
|
+
const includedIds = await fetchIncludedIds(
|
|
3336
|
+
ctx,
|
|
3337
|
+
reachableCte,
|
|
3338
|
+
includedIdsCte
|
|
3339
|
+
);
|
|
3340
|
+
const idsArray = textArrayParam(includedIds);
|
|
3341
|
+
membership = {
|
|
3342
|
+
prefix: sql``,
|
|
3343
|
+
idFilter: (column) => sql`EXISTS (SELECT 1 FROM unnest(${idsArray}) AS tg_included(id) WHERE tg_included.id = ${column})`,
|
|
3344
|
+
parameterDependentPlan: true
|
|
3345
|
+
};
|
|
3346
|
+
break;
|
|
3347
|
+
}
|
|
3348
|
+
case "sqlite": {
|
|
3349
|
+
membership = {
|
|
3350
|
+
prefix: sql`${reachableCte}${includedIdsCte} `,
|
|
3351
|
+
// SQLite: `column IN (subquery)` evaluates via a transient index —
|
|
3352
|
+
// optimal as-is. (Postgres takes the parameterized text[] form above.)
|
|
3353
|
+
idFilter: (column) => sql`${column} IN (SELECT id FROM included_ids)`,
|
|
3354
|
+
parameterDependentPlan: false
|
|
3355
|
+
};
|
|
3356
|
+
break;
|
|
3357
|
+
}
|
|
3358
|
+
default: {
|
|
3359
|
+
throw new Error(`Unsupported SQL dialect: ${String(dialect)}`);
|
|
3360
|
+
}
|
|
3219
3361
|
}
|
|
3220
3362
|
const [nodeRows, edgeRows] = await Promise.all([
|
|
3221
3363
|
fetchSubgraphNodes(ctx, membership, nodeProjectionPlan),
|
|
@@ -3473,7 +3615,7 @@ function mapSubgraphNodeRow(row, projectionPlan) {
|
|
|
3473
3615
|
id: row.id
|
|
3474
3616
|
};
|
|
3475
3617
|
if (kindPlan.includeMeta) {
|
|
3476
|
-
projectedNode
|
|
3618
|
+
projectedNode["meta"] = rowToNodeMeta(row);
|
|
3477
3619
|
}
|
|
3478
3620
|
applyProjectedFields(projectedNode, row, kindPlan);
|
|
3479
3621
|
return projectedNode;
|
|
@@ -3495,11 +3637,13 @@ function mapSubgraphEdgeRow(row, projectionPlan) {
|
|
|
3495
3637
|
toId: row.to_id
|
|
3496
3638
|
};
|
|
3497
3639
|
if (kindPlan.includeMeta) {
|
|
3498
|
-
projectedEdge
|
|
3640
|
+
projectedEdge["meta"] = rowToEdgeMeta(row);
|
|
3499
3641
|
}
|
|
3500
3642
|
applyProjectedFields(projectedEdge, row, kindPlan);
|
|
3501
3643
|
return projectedEdge;
|
|
3502
3644
|
}
|
|
3645
|
+
|
|
3646
|
+
// src/query/compiler/set-operations.ts
|
|
3503
3647
|
var OPERATOR_MAP = {
|
|
3504
3648
|
union: "UNION",
|
|
3505
3649
|
unionAll: "UNION ALL",
|
|
@@ -4114,7 +4258,7 @@ function tryLowerSingleHopRecursiveTraversal(ast) {
|
|
|
4114
4258
|
if (ast.traversals.length !== 1) {
|
|
4115
4259
|
return void 0;
|
|
4116
4260
|
}
|
|
4117
|
-
const traversal = ast.traversals[0];
|
|
4261
|
+
const traversal = requireDefined(ast.traversals[0]);
|
|
4118
4262
|
const variableLength = traversal.variableLength;
|
|
4119
4263
|
if (!variableLength) {
|
|
4120
4264
|
return void 0;
|
|
@@ -4210,11 +4354,11 @@ function resolveCountAggregateFastPath(ast) {
|
|
|
4210
4354
|
if (ast.orderBy?.some((orderSpec) => orderSpec.field.alias !== ast.start.alias)) {
|
|
4211
4355
|
return void 0;
|
|
4212
4356
|
}
|
|
4213
|
-
const traversal = ast.traversals[0];
|
|
4357
|
+
const traversal = requireDefined(ast.traversals[0]);
|
|
4214
4358
|
if ((traversal.inverseEdgeKinds?.length ?? 0) > 0) {
|
|
4215
4359
|
return void 0;
|
|
4216
4360
|
}
|
|
4217
|
-
const groupField = ast.groupBy.fields[0];
|
|
4361
|
+
const groupField = requireDefined(ast.groupBy.fields[0]);
|
|
4218
4362
|
if (groupField.alias !== ast.start.alias || !isIdFieldRef(groupField)) {
|
|
4219
4363
|
return void 0;
|
|
4220
4364
|
}
|
|
@@ -4981,14 +5125,14 @@ function decodeCursor(cursor) {
|
|
|
4981
5125
|
}
|
|
4982
5126
|
const json = atob(base64);
|
|
4983
5127
|
const raw = JSON.parse(json);
|
|
4984
|
-
if (typeof raw
|
|
5128
|
+
if (typeof raw["v"] !== "number" || raw["v"] > CURSOR_VERSION) {
|
|
4985
5129
|
throw new ValidationError(
|
|
4986
|
-
`Unsupported cursor version: ${String(raw
|
|
5130
|
+
`Unsupported cursor version: ${String(raw["v"])}. Maximum supported: ${CURSOR_VERSION}`,
|
|
4987
5131
|
{
|
|
4988
5132
|
issues: [
|
|
4989
5133
|
{
|
|
4990
5134
|
path: "cursor",
|
|
4991
|
-
message: `Cursor version ${String(raw
|
|
5135
|
+
message: `Cursor version ${String(raw["v"])} is not supported`
|
|
4992
5136
|
}
|
|
4993
5137
|
]
|
|
4994
5138
|
},
|
|
@@ -4997,17 +5141,20 @@ function decodeCursor(cursor) {
|
|
|
4997
5141
|
}
|
|
4998
5142
|
);
|
|
4999
5143
|
}
|
|
5000
|
-
if (raw
|
|
5001
|
-
throw new ValidationError(
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5144
|
+
if (raw["d"] !== "f" && raw["d"] !== "b") {
|
|
5145
|
+
throw new ValidationError(
|
|
5146
|
+
`Invalid cursor direction: ${String(raw["d"])}`,
|
|
5147
|
+
{
|
|
5148
|
+
issues: [
|
|
5149
|
+
{
|
|
5150
|
+
path: "cursor",
|
|
5151
|
+
message: `Direction must be "f" (forward) or "b" (backward)`
|
|
5152
|
+
}
|
|
5153
|
+
]
|
|
5154
|
+
}
|
|
5155
|
+
);
|
|
5009
5156
|
}
|
|
5010
|
-
if (!Array.isArray(raw
|
|
5157
|
+
if (!Array.isArray(raw["vals"]) || !Array.isArray(raw["cols"])) {
|
|
5011
5158
|
throw new ValidationError("Invalid cursor structure", {
|
|
5012
5159
|
issues: [
|
|
5013
5160
|
{
|
|
@@ -5017,21 +5164,21 @@ function decodeCursor(cursor) {
|
|
|
5017
5164
|
]
|
|
5018
5165
|
});
|
|
5019
5166
|
}
|
|
5020
|
-
if (raw
|
|
5167
|
+
if (raw["vals"].length !== raw["cols"].length) {
|
|
5021
5168
|
throw new ValidationError("Cursor column count mismatch", {
|
|
5022
5169
|
issues: [
|
|
5023
5170
|
{
|
|
5024
5171
|
path: "cursor",
|
|
5025
|
-
message: `vals (${raw
|
|
5172
|
+
message: `vals (${raw["vals"].length}) and cols (${raw["cols"].length}) must have same length`
|
|
5026
5173
|
}
|
|
5027
5174
|
]
|
|
5028
5175
|
});
|
|
5029
5176
|
}
|
|
5030
5177
|
return {
|
|
5031
|
-
v: raw
|
|
5032
|
-
d: raw
|
|
5033
|
-
vals: raw
|
|
5034
|
-
cols: raw
|
|
5178
|
+
v: raw["v"],
|
|
5179
|
+
d: raw["d"],
|
|
5180
|
+
vals: raw["vals"],
|
|
5181
|
+
cols: raw["cols"]
|
|
5035
5182
|
};
|
|
5036
5183
|
} catch (error) {
|
|
5037
5184
|
if (error instanceof ValidationError) {
|
|
@@ -5138,11 +5285,11 @@ function buildCursorPredicate(cursorData, orderBy, direction, targetAlias) {
|
|
|
5138
5285
|
for (let index = 0; index < orderBy.length; index++) {
|
|
5139
5286
|
const andConditions = [];
|
|
5140
5287
|
for (let index_ = 0; index_ < index; index_++) {
|
|
5141
|
-
const spec = orderBy[index_];
|
|
5288
|
+
const spec = requireDefined(orderBy[index_]);
|
|
5142
5289
|
const value = values[index_];
|
|
5143
5290
|
andConditions.push(buildEqualityPredicate(spec.field, value));
|
|
5144
5291
|
}
|
|
5145
|
-
const currentSpec = orderBy[index];
|
|
5292
|
+
const currentSpec = requireDefined(orderBy[index]);
|
|
5146
5293
|
const currentValue = values[index];
|
|
5147
5294
|
const isAsc = currentSpec.direction === "asc";
|
|
5148
5295
|
const isForward = direction === "forward";
|
|
@@ -5151,12 +5298,12 @@ function buildCursorPredicate(cursorData, orderBy, direction, targetAlias) {
|
|
|
5151
5298
|
buildComparisonPredicate(currentSpec.field, op, currentValue)
|
|
5152
5299
|
);
|
|
5153
5300
|
if (andConditions.length === 1) {
|
|
5154
|
-
orConditions.push(andConditions[0]);
|
|
5301
|
+
orConditions.push(requireDefined(andConditions[0]));
|
|
5155
5302
|
} else {
|
|
5156
5303
|
orConditions.push({ __type: "and", predicates: andConditions });
|
|
5157
5304
|
}
|
|
5158
5305
|
}
|
|
5159
|
-
const expression = orConditions.length === 1 ? orConditions[0] : { __type: "or", predicates: orConditions };
|
|
5306
|
+
const expression = orConditions.length === 1 ? requireDefined(orConditions[0]) : { __type: "or", predicates: orConditions };
|
|
5160
5307
|
return {
|
|
5161
5308
|
targetAlias,
|
|
5162
5309
|
expression
|
|
@@ -5191,8 +5338,8 @@ function buildPaginatedResult(data, orderedRows, orderBy, limit, hasMore, isBack
|
|
|
5191
5338
|
let nextCursor;
|
|
5192
5339
|
let previousCursor;
|
|
5193
5340
|
if (orderedRows.length > 0) {
|
|
5194
|
-
const firstRow = orderedRows[0];
|
|
5195
|
-
const lastRow = orderedRows.at(-1);
|
|
5341
|
+
const firstRow = requireDefined(orderedRows[0]);
|
|
5342
|
+
const lastRow = requireDefined(orderedRows.at(-1));
|
|
5196
5343
|
const firstContext = buildContext(firstRow);
|
|
5197
5344
|
const lastContext = buildContext(lastRow);
|
|
5198
5345
|
previousCursor = buildCursorFromContext(firstContext, orderBy, "b");
|
|
@@ -5646,7 +5793,7 @@ function buildRequiredAliasValue(row, plan) {
|
|
|
5646
5793
|
for (const field2 of plan.metaFields) {
|
|
5647
5794
|
meta[field2.metaKey] = nullToUndefined(row[field2.outputName]);
|
|
5648
5795
|
}
|
|
5649
|
-
base
|
|
5796
|
+
base["meta"] = createGuardedProxy(meta, `${plan.alias}.meta`);
|
|
5650
5797
|
}
|
|
5651
5798
|
for (const field2 of plan.propsFields) {
|
|
5652
5799
|
const decoded = decodeSelectedValue(row[field2.outputName], field2.typeInfo);
|
|
@@ -5673,9 +5820,11 @@ function createGuardedProxy(target, debugPath) {
|
|
|
5673
5820
|
}
|
|
5674
5821
|
});
|
|
5675
5822
|
}
|
|
5823
|
+
|
|
5824
|
+
// src/query/builder/read-instant-template.ts
|
|
5676
5825
|
function templateHasReadInstant(template) {
|
|
5677
5826
|
return template.params.some(
|
|
5678
|
-
(parameter) => parameter
|
|
5827
|
+
(parameter) => isSqlPlaceholder(parameter) && parameter.name === CURRENT_READ_INSTANT_PLACEHOLDER
|
|
5679
5828
|
);
|
|
5680
5829
|
}
|
|
5681
5830
|
function queryAstNeedsCurrentReadInstant(ast) {
|
|
@@ -5709,10 +5858,9 @@ function buildQueryTemplate(ast, graphId, compileOptions, backend) {
|
|
|
5709
5858
|
});
|
|
5710
5859
|
}
|
|
5711
5860
|
function fillTemplateParams(params, bindings, dialect) {
|
|
5712
|
-
const adapter = getDialect(dialect);
|
|
5713
5861
|
let readInstant;
|
|
5714
5862
|
return params.map((parameter) => {
|
|
5715
|
-
if (!(parameter
|
|
5863
|
+
if (!isSqlPlaceholder(parameter)) return parameter;
|
|
5716
5864
|
const name = parameter.name;
|
|
5717
5865
|
if (name === CURRENT_READ_INSTANT_PLACEHOLDER) {
|
|
5718
5866
|
readInstant ??= nowIso();
|
|
@@ -5724,8 +5872,7 @@ function fillTemplateParams(params, bindings, dialect) {
|
|
|
5724
5872
|
parameterName: name
|
|
5725
5873
|
});
|
|
5726
5874
|
}
|
|
5727
|
-
|
|
5728
|
-
return adapter.bindValue(value);
|
|
5875
|
+
return bindSqlValue(value, dialect);
|
|
5729
5876
|
});
|
|
5730
5877
|
}
|
|
5731
5878
|
|
|
@@ -5981,7 +6128,7 @@ var PreparedQuery = class {
|
|
|
5981
6128
|
bindings,
|
|
5982
6129
|
this.#dialect
|
|
5983
6130
|
);
|
|
5984
|
-
const rawRows2 = await
|
|
6131
|
+
const rawRows2 = await executeRaw(
|
|
5985
6132
|
template.sql,
|
|
5986
6133
|
params
|
|
5987
6134
|
);
|
|
@@ -6703,10 +6850,10 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
6703
6850
|
return this.#config.backend.compileSql(this.compile());
|
|
6704
6851
|
}
|
|
6705
6852
|
/**
|
|
6706
|
-
* Compiles the query to
|
|
6853
|
+
* Compiles the query to TypeGraph's database-independent SQL fragment.
|
|
6707
6854
|
*
|
|
6708
|
-
*
|
|
6709
|
-
*
|
|
6855
|
+
* Pass the result to a GraphBackend, or use toSQL() to render SQL text and
|
|
6856
|
+
* parameters for the configured dialect.
|
|
6710
6857
|
*/
|
|
6711
6858
|
compile() {
|
|
6712
6859
|
const ast = this.toAst();
|
|
@@ -6827,13 +6974,9 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
6827
6974
|
const template = executeRaw === void 0 ? void 0 : this.#templateFor(ast, slot);
|
|
6828
6975
|
const rawRows = await this.#executeOnBackend(
|
|
6829
6976
|
backend,
|
|
6830
|
-
template !== void 0 && executeRaw !== void 0 ? (
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
backend.executeRaw(
|
|
6834
|
-
template.sql,
|
|
6835
|
-
fillTemplateParams(template.params, {}, this.#dialect())
|
|
6836
|
-
)
|
|
6977
|
+
template !== void 0 && executeRaw !== void 0 ? executeRaw(
|
|
6978
|
+
template.sql,
|
|
6979
|
+
fillTemplateParams(template.params, {}, this.#dialect())
|
|
6837
6980
|
) : backend.execute(
|
|
6838
6981
|
compileQuery(ast, this.#config.graphId, this.#compileOptions())
|
|
6839
6982
|
),
|
|
@@ -7147,12 +7290,12 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
7147
7290
|
if (orderedRows.length > 0) {
|
|
7148
7291
|
try {
|
|
7149
7292
|
previousCursor = this.#buildCursorFromSelectiveRow(
|
|
7150
|
-
orderedRows[0],
|
|
7293
|
+
requireDefined(orderedRows[0]),
|
|
7151
7294
|
selectiveFields,
|
|
7152
7295
|
"b"
|
|
7153
7296
|
);
|
|
7154
7297
|
nextCursor = this.#buildCursorFromSelectiveRow(
|
|
7155
|
-
orderedRows.at(-1),
|
|
7298
|
+
requireDefined(orderedRows.at(-1)),
|
|
7156
7299
|
selectiveFields,
|
|
7157
7300
|
"f"
|
|
7158
7301
|
);
|
|
@@ -7180,7 +7323,7 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
7180
7323
|
for (const spec of this.#paginationOrderBy()) {
|
|
7181
7324
|
const field2 = spec.field;
|
|
7182
7325
|
if (field2.path.length === 1 && field2.path[0] !== "props" && field2.jsonPointer === void 0) {
|
|
7183
|
-
tracker.record(field2.alias, field2.path[0], true);
|
|
7326
|
+
tracker.record(field2.alias, requireDefined(field2.path[0]), true);
|
|
7184
7327
|
continue;
|
|
7185
7328
|
}
|
|
7186
7329
|
if (field2.path.length !== 1 || field2.path[0] !== "props") {
|
|
@@ -7193,7 +7336,7 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
7193
7336
|
if (segments.length !== 1) {
|
|
7194
7337
|
return false;
|
|
7195
7338
|
}
|
|
7196
|
-
tracker.record(field2.alias, segments[0], false);
|
|
7339
|
+
tracker.record(field2.alias, requireDefined(segments[0]), false);
|
|
7197
7340
|
}
|
|
7198
7341
|
return true;
|
|
7199
7342
|
}
|
|
@@ -7226,7 +7369,7 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
7226
7369
|
if (spec.field.path.length !== 1) {
|
|
7227
7370
|
throw new MissingSelectiveFieldError(alias, "orderBy");
|
|
7228
7371
|
}
|
|
7229
|
-
const fieldName = spec.field.path[0];
|
|
7372
|
+
const fieldName = requireDefined(spec.field.path[0]);
|
|
7230
7373
|
const outputName2 = outputNameByAliasField.get(
|
|
7231
7374
|
`${alias}\0${fieldName}`
|
|
7232
7375
|
);
|
|
@@ -7241,7 +7384,7 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
7241
7384
|
if (segments.length === 0) {
|
|
7242
7385
|
throw new MissingSelectiveFieldError(alias, "orderBy");
|
|
7243
7386
|
}
|
|
7244
|
-
const topField = segments[0];
|
|
7387
|
+
const topField = requireDefined(segments[0]);
|
|
7245
7388
|
const outputName = outputNameByAliasField.get(
|
|
7246
7389
|
`${alias}\0${topField}`
|
|
7247
7390
|
);
|
|
@@ -7271,7 +7414,7 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
7271
7414
|
}
|
|
7272
7415
|
let current = aliasObject;
|
|
7273
7416
|
for (let index = 0; index < segments.length - 1; index++) {
|
|
7274
|
-
const segment = segments[index];
|
|
7417
|
+
const segment = requireDefined(segments[index]);
|
|
7275
7418
|
const existing_ = current[segment];
|
|
7276
7419
|
if (typeof existing_ === "object" && existing_ !== null) {
|
|
7277
7420
|
current = existing_;
|
|
@@ -7281,7 +7424,7 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
7281
7424
|
current = created;
|
|
7282
7425
|
}
|
|
7283
7426
|
}
|
|
7284
|
-
current[segments.at(-1)] = decoded;
|
|
7427
|
+
current[requireDefined(segments.at(-1))] = decoded;
|
|
7285
7428
|
}
|
|
7286
7429
|
return cursorContext;
|
|
7287
7430
|
}
|
|
@@ -7573,7 +7716,7 @@ var ExecutableAggregateQuery = class _ExecutableAggregateQuery {
|
|
|
7573
7716
|
return this.#config.backend.compileSql(this.compile());
|
|
7574
7717
|
}
|
|
7575
7718
|
/**
|
|
7576
|
-
* Compiles the query to
|
|
7719
|
+
* Compiles the query to TypeGraph's database-independent SQL fragment.
|
|
7577
7720
|
*/
|
|
7578
7721
|
compile() {
|
|
7579
7722
|
const ast = this.toAst();
|
|
@@ -7617,16 +7760,12 @@ var ExecutableAggregateQuery = class _ExecutableAggregateQuery {
|
|
|
7617
7760
|
}
|
|
7618
7761
|
const executeRaw = backend.executeRaw;
|
|
7619
7762
|
const template = executeRaw === void 0 ? void 0 : this.#resolveTemplate(ast);
|
|
7620
|
-
const rows = template !== void 0 && executeRaw !== void 0 ? (
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
template.params,
|
|
7627
|
-
{},
|
|
7628
|
-
this.#config.dialect ?? "sqlite"
|
|
7629
|
-
)
|
|
7763
|
+
const rows = template !== void 0 && executeRaw !== void 0 ? await executeRaw(
|
|
7764
|
+
template.sql,
|
|
7765
|
+
fillTemplateParams(
|
|
7766
|
+
template.params,
|
|
7767
|
+
{},
|
|
7768
|
+
this.#config.dialect ?? "sqlite"
|
|
7630
7769
|
)
|
|
7631
7770
|
) : await backend.execute(
|
|
7632
7771
|
compileQuery(ast, this.#config.graphId, this.#compileOptions())
|
|
@@ -8969,16 +9108,12 @@ var UnionableQuery = class _UnionableQuery {
|
|
|
8969
9108
|
return executeOnBackend(
|
|
8970
9109
|
backend,
|
|
8971
9110
|
recordedAsOfForComposableQuery(ast),
|
|
8972
|
-
template !== void 0 && executeRaw !== void 0 ? (
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
8977
|
-
|
|
8978
|
-
template.params,
|
|
8979
|
-
{},
|
|
8980
|
-
this.#config.dialect ?? "sqlite"
|
|
8981
|
-
)
|
|
9111
|
+
template !== void 0 && executeRaw !== void 0 ? executeRaw(
|
|
9112
|
+
template.sql,
|
|
9113
|
+
fillTemplateParams(
|
|
9114
|
+
template.params,
|
|
9115
|
+
{},
|
|
9116
|
+
this.#config.dialect ?? "sqlite"
|
|
8982
9117
|
)
|
|
8983
9118
|
) : backend.execute(
|
|
8984
9119
|
compileSetOperation2(
|
|
@@ -9441,6 +9576,8 @@ function processPage(schema, rows) {
|
|
|
9441
9576
|
}
|
|
9442
9577
|
return { toUpsert, toDelete, skipped, skippedIds };
|
|
9443
9578
|
}
|
|
9579
|
+
|
|
9580
|
+
// src/store/search.ts
|
|
9444
9581
|
var SEARCH_CANDIDATE_ALIAS = "_sc";
|
|
9445
9582
|
function buildKindCandidates(ctx, nodeKind, where) {
|
|
9446
9583
|
if (where === void 0) return void 0;
|
|
@@ -9550,7 +9687,7 @@ async function executeFulltextSearch(ctx, nodeKind, options) {
|
|
|
9550
9687
|
kinds.map(async (kind) => {
|
|
9551
9688
|
const candidates = buildKindCandidates(ctx, kind, options.where);
|
|
9552
9689
|
const language = effectiveFulltextLanguage(ctx, kind, options.language);
|
|
9553
|
-
const rows = await backend.fulltextSearch({
|
|
9690
|
+
const rows = await requireDefined(backend.fulltextSearch)({
|
|
9554
9691
|
graphId,
|
|
9555
9692
|
nodeKind: kind,
|
|
9556
9693
|
query: options.query,
|
|
@@ -9572,7 +9709,7 @@ async function executeFulltextSearch(ctx, nodeKind, options) {
|
|
|
9572
9709
|
}));
|
|
9573
9710
|
})
|
|
9574
9711
|
);
|
|
9575
|
-
const merged = singleKind ? perKindRows[0] : perKindRows.flat().toSorted(
|
|
9712
|
+
const merged = singleKind ? requireDefined(perKindRows[0]) : perKindRows.flat().toSorted(
|
|
9576
9713
|
(a, b) => b.score - a.score || compareCodePoints(a.kind, b.kind) || compareCodePoints(a.nodeId, b.nodeId)
|
|
9577
9714
|
).slice(offset, offset + options.limit);
|
|
9578
9715
|
if (merged.length === 0) return [];
|
|
@@ -9629,12 +9766,12 @@ async function executeVectorSearch(ctx, nodeKind, options) {
|
|
|
9629
9766
|
}
|
|
9630
9767
|
const offset = options.offset ?? 0;
|
|
9631
9768
|
const singleKind = searchKinds.length === 1;
|
|
9632
|
-
const metric = options.metric ?? searchKinds[0].slot.metric;
|
|
9769
|
+
const metric = options.metric ?? requireDefined(searchKinds[0]).slot.metric;
|
|
9633
9770
|
const perKindRows = await Promise.all(
|
|
9634
9771
|
searchKinds.map(
|
|
9635
9772
|
async ({ kind, slot }) => {
|
|
9636
9773
|
const candidates = buildKindCandidates(ctx, kind, options.where);
|
|
9637
|
-
const rows = await backend.vectorSearch({
|
|
9774
|
+
const rows = await requireDefined(backend.vectorSearch)({
|
|
9638
9775
|
graphId,
|
|
9639
9776
|
nodeKind: kind,
|
|
9640
9777
|
fieldPath: options.fieldPath,
|
|
@@ -9662,7 +9799,7 @@ async function executeVectorSearch(ctx, nodeKind, options) {
|
|
|
9662
9799
|
}
|
|
9663
9800
|
)
|
|
9664
9801
|
);
|
|
9665
|
-
const merged = singleKind ? perKindRows[0] : mergeVectorRows(perKindRows, metric).slice(
|
|
9802
|
+
const merged = singleKind ? requireDefined(perKindRows[0]) : mergeVectorRows(perKindRows, metric).slice(
|
|
9666
9803
|
offset,
|
|
9667
9804
|
offset + options.limit
|
|
9668
9805
|
);
|
|
@@ -9771,7 +9908,7 @@ async function executeHybridSearch(ctx, nodeKind, options) {
|
|
|
9771
9908
|
"hybridSearch.vector.minScore"
|
|
9772
9909
|
);
|
|
9773
9910
|
}
|
|
9774
|
-
const vectorMetric = options.vector.metric ?? vectorKinds[0].slot.metric;
|
|
9911
|
+
const vectorMetric = options.vector.metric ?? requireDefined(vectorKinds[0]).slot.metric;
|
|
9775
9912
|
const candidatesByKind = /* @__PURE__ */ new Map();
|
|
9776
9913
|
for (const kind of fulltextKinds) {
|
|
9777
9914
|
candidatesByKind.set(kind, buildKindCandidates(ctx, kind, options.where));
|
|
@@ -9781,9 +9918,9 @@ async function executeHybridSearch(ctx, nodeKind, options) {
|
|
|
9781
9918
|
candidatesByKind.set(kind, buildKindCandidates(ctx, kind, options.where));
|
|
9782
9919
|
}
|
|
9783
9920
|
}
|
|
9784
|
-
if (backend.hybridSearch !== void 0 && fulltextKinds.length === 1 && vectorKinds.length === 1 && fulltextKinds[0] === vectorKinds[0].kind) {
|
|
9921
|
+
if (backend.hybridSearch !== void 0 && fulltextKinds.length === 1 && vectorKinds.length === 1 && fulltextKinds[0] === requireDefined(vectorKinds[0]).kind) {
|
|
9785
9922
|
const kind = fulltextKinds[0];
|
|
9786
|
-
const { slot } = vectorKinds[0];
|
|
9923
|
+
const { slot } = requireDefined(vectorKinds[0]);
|
|
9787
9924
|
const candidates = candidatesByKind.get(kind);
|
|
9788
9925
|
const hybridFulltextLanguage = effectiveFulltextLanguage(
|
|
9789
9926
|
ctx,
|
|
@@ -9844,7 +9981,7 @@ async function executeHybridSearch(ctx, nodeKind, options) {
|
|
|
9844
9981
|
vectorKinds.map(
|
|
9845
9982
|
async ({ kind, slot }) => {
|
|
9846
9983
|
const candidates = candidatesByKind.get(kind);
|
|
9847
|
-
const rows = await backend.vectorSearch({
|
|
9984
|
+
const rows = await requireDefined(backend.vectorSearch)({
|
|
9848
9985
|
graphId,
|
|
9849
9986
|
nodeKind: kind,
|
|
9850
9987
|
fieldPath: options.vector.fieldPath,
|
|
@@ -9874,7 +10011,7 @@ async function executeHybridSearch(ctx, nodeKind, options) {
|
|
|
9874
10011
|
kind,
|
|
9875
10012
|
options.fulltext.language
|
|
9876
10013
|
);
|
|
9877
|
-
const rows = await backend.fulltextSearch({
|
|
10014
|
+
const rows = await requireDefined(backend.fulltextSearch)({
|
|
9878
10015
|
graphId,
|
|
9879
10016
|
nodeKind: kind,
|
|
9880
10017
|
query: options.fulltext.query,
|
|
@@ -10314,7 +10451,7 @@ function classifyProperties(kind, existing, next, recorders) {
|
|
|
10314
10451
|
}
|
|
10315
10452
|
for (const name of nextNames) {
|
|
10316
10453
|
if (!existingNames.has(name)) {
|
|
10317
|
-
const property = next[name];
|
|
10454
|
+
const property = requireDefined(next[name]);
|
|
10318
10455
|
if (property.optional === true) continue;
|
|
10319
10456
|
recorders.recordRequireEmpty({
|
|
10320
10457
|
kind,
|
|
@@ -10325,7 +10462,13 @@ function classifyProperties(kind, existing, next, recorders) {
|
|
|
10325
10462
|
}
|
|
10326
10463
|
for (const name of existingNames) {
|
|
10327
10464
|
if (!nextNames.has(name)) continue;
|
|
10328
|
-
classifyProperty(
|
|
10465
|
+
classifyProperty(
|
|
10466
|
+
kind,
|
|
10467
|
+
name,
|
|
10468
|
+
requireDefined(existing[name]),
|
|
10469
|
+
requireDefined(next[name]),
|
|
10470
|
+
recorders
|
|
10471
|
+
);
|
|
10329
10472
|
}
|
|
10330
10473
|
}
|
|
10331
10474
|
function classifyProperty(kind, field2, existing, next, recorders) {
|
|
@@ -10736,6 +10879,13 @@ function buildCompileTimeReferentIndex(graph, runtimeEdgeNames) {
|
|
|
10736
10879
|
// src/store/algorithms/context.ts
|
|
10737
10880
|
var DEFAULT_ALGORITHM_MAX_HOPS = 10;
|
|
10738
10881
|
var DEFAULT_NEIGHBOR_DEPTH = 1;
|
|
10882
|
+
function pickTemporalOptions(options) {
|
|
10883
|
+
return {
|
|
10884
|
+
...options.temporalMode === void 0 ? {} : { temporalMode: options.temporalMode },
|
|
10885
|
+
...options.asOf === void 0 ? {} : { asOf: options.asOf },
|
|
10886
|
+
...options.recordedAsOf === void 0 ? {} : { recordedAsOf: options.recordedAsOf }
|
|
10887
|
+
};
|
|
10888
|
+
}
|
|
10739
10889
|
function resolveTemporalOptions(ctx, options) {
|
|
10740
10890
|
const { valid } = resolveReadCoordinate(
|
|
10741
10891
|
options.temporalMode ?? ctx.defaultTemporalMode,
|
|
@@ -10809,6 +10959,33 @@ function assertEdgeKinds(edges) {
|
|
|
10809
10959
|
);
|
|
10810
10960
|
}
|
|
10811
10961
|
}
|
|
10962
|
+
function compileNodeKindSeedFilter(nodeKinds) {
|
|
10963
|
+
if (nodeKinds === void 0) return sql`TRUE`;
|
|
10964
|
+
return compileKindFilter(sql.raw("n.kind"), nodeKinds);
|
|
10965
|
+
}
|
|
10966
|
+
function normalizeNodeKinds(nodeKinds) {
|
|
10967
|
+
if (nodeKinds === void 0) return void 0;
|
|
10968
|
+
return [...new Set(nodeKinds)].toSorted(
|
|
10969
|
+
(left, right) => compareCodePoints(left, right)
|
|
10970
|
+
);
|
|
10971
|
+
}
|
|
10972
|
+
function assertGraphAnalyticsSupported(ctx, algorithm, options = {}) {
|
|
10973
|
+
const graphAnalytics = ctx.backend.capabilities.graphAnalytics?.supported === true;
|
|
10974
|
+
const windowFunctions = ctx.backend.capabilities.windowFunctions;
|
|
10975
|
+
if (graphAnalytics && (options.requiresWindowFunctions !== true || windowFunctions)) {
|
|
10976
|
+
return;
|
|
10977
|
+
}
|
|
10978
|
+
throw new UnsupportedBackendCapabilityError(
|
|
10979
|
+
algorithm,
|
|
10980
|
+
"graphAnalytics",
|
|
10981
|
+
{
|
|
10982
|
+
dialect: ctx.backend.dialect,
|
|
10983
|
+
supported: graphAnalytics,
|
|
10984
|
+
...options.requiresWindowFunctions === true ? { windowFunctions } : {}
|
|
10985
|
+
},
|
|
10986
|
+
"Use a built-in transactional SQLite/PostgreSQL backend, or declare graphAnalytics support on a compatible custom backend."
|
|
10987
|
+
);
|
|
10988
|
+
}
|
|
10812
10989
|
|
|
10813
10990
|
// src/store/algorithms/degree.ts
|
|
10814
10991
|
async function executeDegree(ctx, nodeId, options = {}) {
|
|
@@ -10850,6 +11027,23 @@ function compileDirectionFilter(ctx, direction, nodeId, nodesTable) {
|
|
|
10850
11027
|
}
|
|
10851
11028
|
}
|
|
10852
11029
|
}
|
|
11030
|
+
|
|
11031
|
+
// src/store/algorithms/iterative-graph-operation.ts
|
|
11032
|
+
function frontierIndexIdentifier(context) {
|
|
11033
|
+
return sql.identifier(
|
|
11034
|
+
`typegraph_iterative_${context.runId.replaceAll("-", "_")}_frontier`
|
|
11035
|
+
);
|
|
11036
|
+
}
|
|
11037
|
+
async function countWorkingTableRows(context) {
|
|
11038
|
+
const rows = await context.backend.execute(
|
|
11039
|
+
asCompiledRowsSql(sql`
|
|
11040
|
+
SELECT COUNT(*) AS count
|
|
11041
|
+
FROM ${context.workingTable}
|
|
11042
|
+
WHERE graph_id = ${context.graphId} AND run_id = ${context.runId}
|
|
11043
|
+
`)
|
|
11044
|
+
);
|
|
11045
|
+
return Number(rows[0]?.count ?? 0);
|
|
11046
|
+
}
|
|
10853
11047
|
var DEFAULT_MAX_BIND_PARAMETERS = 999;
|
|
10854
11048
|
var RESERVED_TEMPORAL_BIND_PARAMETERS_PER_BRANCH = 12;
|
|
10855
11049
|
var RESERVED_WEIGHT_BIND_PARAMETERS_PER_BRANCH = 4;
|
|
@@ -10900,71 +11094,69 @@ async function runIterativeGraphOperation(ctx, options, plan) {
|
|
|
10900
11094
|
{ dialect: ctx.backend.dialect }
|
|
10901
11095
|
);
|
|
10902
11096
|
}
|
|
10903
|
-
|
|
10904
|
-
|
|
10905
|
-
|
|
10906
|
-
|
|
10907
|
-
|
|
10908
|
-
|
|
11097
|
+
const transactionOptions = {
|
|
11098
|
+
isolationLevel: "repeatable_read",
|
|
11099
|
+
accessMode: "read_only",
|
|
11100
|
+
temporaryWrites: INTERNAL_TEMPORARY_WRITES
|
|
11101
|
+
};
|
|
11102
|
+
return ctx.backend.transaction(async (backend) => {
|
|
11103
|
+
const temporaryBackend = requireTemporaryStatements(backend);
|
|
11104
|
+
const runId = generateId();
|
|
11105
|
+
const workingTable = sql.identifier(
|
|
11106
|
+
`typegraph_iterative_${runId.replaceAll("-", "_")}`
|
|
11107
|
+
);
|
|
11108
|
+
const context = {
|
|
11109
|
+
operation: createOperation(ctx, options, temporaryBackend),
|
|
11110
|
+
backend: temporaryBackend,
|
|
11111
|
+
workingTable,
|
|
11112
|
+
graphId: ctx.graphId,
|
|
11113
|
+
runId,
|
|
11114
|
+
executeTemporary: async (query) => {
|
|
11115
|
+
await temporaryBackend.executeTemporaryStatement(
|
|
11116
|
+
asCompiledTemporaryStatementSql(query)
|
|
11117
|
+
);
|
|
11118
|
+
}
|
|
11119
|
+
};
|
|
11120
|
+
if (context.operation.workingMemory !== void 0) {
|
|
11121
|
+
const workingMemoryStatement = ctx.dialect.setTransactionWorkingMemory(
|
|
11122
|
+
context.operation.workingMemory
|
|
10909
11123
|
);
|
|
10910
|
-
|
|
10911
|
-
|
|
10912
|
-
|
|
10913
|
-
|
|
10914
|
-
|
|
10915
|
-
|
|
10916
|
-
|
|
10917
|
-
|
|
10918
|
-
|
|
11124
|
+
if (workingMemoryStatement !== void 0) {
|
|
11125
|
+
await context.executeTemporary(workingMemoryStatement);
|
|
11126
|
+
}
|
|
11127
|
+
}
|
|
11128
|
+
await context.executeTemporary(plan.createWorkingTable(context));
|
|
11129
|
+
let operationFailure;
|
|
11130
|
+
try {
|
|
11131
|
+
let state = await plan.initialize(context);
|
|
11132
|
+
let analyzedRowCount = await refreshWorkingTableStatistics(
|
|
11133
|
+
context,
|
|
11134
|
+
state.workingTableSize
|
|
11135
|
+
);
|
|
11136
|
+
for (let iteration = 1; iteration <= plan.maxIterations && !plan.hasConverged(state); iteration++) {
|
|
11137
|
+
state = await plan.runRound(context, state, iteration);
|
|
11138
|
+
if (iteration < plan.maxIterations && !plan.hasConverged(state)) {
|
|
11139
|
+
analyzedRowCount = await refreshWorkingTableStatistics(
|
|
11140
|
+
context,
|
|
11141
|
+
state.workingTableSize,
|
|
11142
|
+
analyzedRowCount
|
|
10919
11143
|
);
|
|
10920
11144
|
}
|
|
10921
|
-
};
|
|
10922
|
-
if (context.operation.workingMemory !== void 0) {
|
|
10923
|
-
const workingMemoryStatement = ctx.dialect.setTransactionWorkingMemory(
|
|
10924
|
-
context.operation.workingMemory
|
|
10925
|
-
);
|
|
10926
|
-
if (workingMemoryStatement !== void 0) {
|
|
10927
|
-
await context.executeTemporary(workingMemoryStatement);
|
|
10928
|
-
}
|
|
10929
11145
|
}
|
|
10930
|
-
|
|
10931
|
-
|
|
10932
|
-
|
|
10933
|
-
|
|
10934
|
-
let analyzedRowCount = await refreshWorkingTableStatistics(
|
|
10935
|
-
context,
|
|
10936
|
-
state.workingTableSize
|
|
11146
|
+
if (!plan.hasConverged(state)) {
|
|
11147
|
+
throw new GraphAlgorithmConvergenceError(
|
|
11148
|
+
plan.algorithm,
|
|
11149
|
+
plan.maxIterations
|
|
10937
11150
|
);
|
|
10938
|
-
for (let iteration = 1; iteration <= plan.maxIterations && !plan.hasConverged(state); iteration++) {
|
|
10939
|
-
state = await plan.runRound(context, state, iteration);
|
|
10940
|
-
if (iteration < plan.maxIterations && !plan.hasConverged(state)) {
|
|
10941
|
-
analyzedRowCount = await refreshWorkingTableStatistics(
|
|
10942
|
-
context,
|
|
10943
|
-
state.workingTableSize,
|
|
10944
|
-
analyzedRowCount
|
|
10945
|
-
);
|
|
10946
|
-
}
|
|
10947
|
-
}
|
|
10948
|
-
if (!plan.hasConverged(state)) {
|
|
10949
|
-
throw new GraphAlgorithmConvergenceError(
|
|
10950
|
-
plan.algorithm,
|
|
10951
|
-
plan.maxIterations
|
|
10952
|
-
);
|
|
10953
|
-
}
|
|
10954
|
-
return await plan.extractResult(context, state);
|
|
10955
|
-
} catch (error) {
|
|
10956
|
-
operationError = error;
|
|
10957
|
-
throw error;
|
|
10958
|
-
} finally {
|
|
10959
|
-
await dropWorkingTable(context, operationError);
|
|
10960
11151
|
}
|
|
10961
|
-
|
|
10962
|
-
{
|
|
10963
|
-
|
|
10964
|
-
|
|
10965
|
-
|
|
11152
|
+
return await plan.extractResult(context, state);
|
|
11153
|
+
} catch (error) {
|
|
11154
|
+
operationFailure = { error };
|
|
11155
|
+
throw error;
|
|
11156
|
+
} finally {
|
|
11157
|
+
await cleanupWorkingTables(context, plan.cleanup, operationFailure);
|
|
10966
11158
|
}
|
|
10967
|
-
);
|
|
11159
|
+
}, transactionOptions);
|
|
10968
11160
|
}
|
|
10969
11161
|
function shouldRefreshWorkingTableStatistics(workingTableSize, analyzedRowCount) {
|
|
10970
11162
|
if (workingTableSize < WORKING_TABLE_ANALYZE_MINIMUM_ROWS) return false;
|
|
@@ -10982,14 +11174,27 @@ async function refreshWorkingTableStatistics(context, workingTableSize, analyzed
|
|
|
10982
11174
|
await context.executeTemporary(statement);
|
|
10983
11175
|
return workingTableSize;
|
|
10984
11176
|
}
|
|
10985
|
-
async function dropWorkingTable(context,
|
|
11177
|
+
async function dropWorkingTable(context, hasPrimaryFailure) {
|
|
10986
11178
|
try {
|
|
10987
11179
|
await context.executeTemporary(
|
|
10988
11180
|
sql`DROP TABLE IF EXISTS ${context.workingTable}`
|
|
10989
11181
|
);
|
|
10990
11182
|
} catch (cleanupError) {
|
|
10991
|
-
if (
|
|
11183
|
+
if (!hasPrimaryFailure) throw cleanupError;
|
|
11184
|
+
}
|
|
11185
|
+
}
|
|
11186
|
+
async function cleanupWorkingTables(context, cleanup, operationFailure) {
|
|
11187
|
+
let cleanupFailure;
|
|
11188
|
+
try {
|
|
11189
|
+
await cleanup?.(context);
|
|
11190
|
+
} catch (error) {
|
|
11191
|
+
if (operationFailure === void 0) cleanupFailure = { error };
|
|
10992
11192
|
}
|
|
11193
|
+
await dropWorkingTable(
|
|
11194
|
+
context,
|
|
11195
|
+
operationFailure !== void 0 || cleanupFailure !== void 0
|
|
11196
|
+
);
|
|
11197
|
+
if (cleanupFailure !== void 0) throw cleanupFailure.error;
|
|
10993
11198
|
}
|
|
10994
11199
|
async function fetchVisibleWorkingNodes(operation, nodeIds) {
|
|
10995
11200
|
const nodes = /* @__PURE__ */ new Map();
|
|
@@ -11041,147 +11246,90 @@ function nodeIdentityKeyFromRow(id, kind) {
|
|
|
11041
11246
|
return nodeIdentityKey({ id, kind });
|
|
11042
11247
|
}
|
|
11043
11248
|
function compareNodeIdentity(left, right) {
|
|
11044
|
-
return
|
|
11249
|
+
return compareCodePoints(left.id, right.id) || compareCodePoints(left.kind, right.kind);
|
|
11045
11250
|
}
|
|
11046
|
-
|
|
11047
|
-
|
|
11048
|
-
|
|
11049
|
-
|
|
11050
|
-
|
|
11051
|
-
|
|
11251
|
+
var OUTGOING_DIRECTION_FIELDS = {
|
|
11252
|
+
joinField: "from_id",
|
|
11253
|
+
joinKindField: "from_kind",
|
|
11254
|
+
targetField: "to_id",
|
|
11255
|
+
targetKindField: "to_kind"
|
|
11256
|
+
};
|
|
11257
|
+
var INCOMING_DIRECTION_FIELDS = {
|
|
11258
|
+
joinField: "to_id",
|
|
11259
|
+
joinKindField: "to_kind",
|
|
11260
|
+
targetField: "from_id",
|
|
11261
|
+
targetKindField: "from_kind"
|
|
11262
|
+
};
|
|
11263
|
+
function fieldsForDirection(direction) {
|
|
11052
11264
|
switch (direction) {
|
|
11053
11265
|
case "out": {
|
|
11054
|
-
return
|
|
11266
|
+
return [OUTGOING_DIRECTION_FIELDS];
|
|
11055
11267
|
}
|
|
11056
11268
|
case "in": {
|
|
11057
|
-
return
|
|
11269
|
+
return [INCOMING_DIRECTION_FIELDS];
|
|
11058
11270
|
}
|
|
11059
11271
|
case "both": {
|
|
11060
|
-
|
|
11061
|
-
operation,
|
|
11062
|
-
sql`working_set`,
|
|
11063
|
-
sql`TRUE`,
|
|
11064
|
-
edgeKinds,
|
|
11065
|
-
"from_id",
|
|
11066
|
-
"from_kind",
|
|
11067
|
-
"to_id",
|
|
11068
|
-
"to_kind"
|
|
11069
|
-
);
|
|
11070
|
-
const incoming = compileDirectionalExpansion(
|
|
11071
|
-
operation,
|
|
11072
|
-
sql`working_set`,
|
|
11073
|
-
sql`TRUE`,
|
|
11074
|
-
edgeKinds,
|
|
11075
|
-
"to_id",
|
|
11076
|
-
"to_kind",
|
|
11077
|
-
"from_id",
|
|
11078
|
-
"from_kind"
|
|
11079
|
-
);
|
|
11080
|
-
return sql`${workingCte} ${outgoing} UNION ALL ${incoming}`;
|
|
11272
|
+
return [OUTGOING_DIRECTION_FIELDS, INCOMING_DIRECTION_FIELDS];
|
|
11081
11273
|
}
|
|
11082
11274
|
}
|
|
11083
11275
|
}
|
|
11276
|
+
function compileDirectionUnion(direction, compileDirection) {
|
|
11277
|
+
return sql.join(
|
|
11278
|
+
fieldsForDirection(direction).map((fields) => compileDirection(fields)),
|
|
11279
|
+
sql` UNION ALL `
|
|
11280
|
+
);
|
|
11281
|
+
}
|
|
11282
|
+
function compileExpansionQuery(operation, workingSet, direction, edgeKinds) {
|
|
11283
|
+
const workingValues = sql.join(
|
|
11284
|
+
workingSet.map((node) => sql`(${node.id}, ${node.kind})`),
|
|
11285
|
+
sql`, `
|
|
11286
|
+
);
|
|
11287
|
+
const workingCte = sql`WITH working_set(node_id, node_kind) AS (VALUES ${workingValues})`;
|
|
11288
|
+
const expansion = compileDirectionUnion(
|
|
11289
|
+
direction,
|
|
11290
|
+
(fields) => compileDirectionalExpansion(
|
|
11291
|
+
operation,
|
|
11292
|
+
sql`working_set`,
|
|
11293
|
+
sql`TRUE`,
|
|
11294
|
+
edgeKinds,
|
|
11295
|
+
fields.joinField,
|
|
11296
|
+
fields.joinKindField,
|
|
11297
|
+
fields.targetField,
|
|
11298
|
+
fields.targetKindField
|
|
11299
|
+
)
|
|
11300
|
+
);
|
|
11301
|
+
return sql`${workingCte} ${expansion}`;
|
|
11302
|
+
}
|
|
11084
11303
|
function compileWorkingTableExpansion(operation, workingTable, sourceFilter, direction, edgeKinds) {
|
|
11085
|
-
|
|
11086
|
-
|
|
11087
|
-
|
|
11088
|
-
|
|
11089
|
-
|
|
11090
|
-
|
|
11091
|
-
|
|
11092
|
-
|
|
11093
|
-
|
|
11094
|
-
|
|
11095
|
-
|
|
11096
|
-
|
|
11097
|
-
|
|
11098
|
-
case "in": {
|
|
11099
|
-
return compileDirectionalExpansion(
|
|
11100
|
-
operation,
|
|
11101
|
-
workingTable,
|
|
11102
|
-
sourceFilter,
|
|
11103
|
-
edgeKinds,
|
|
11104
|
-
"to_id",
|
|
11105
|
-
"to_kind",
|
|
11106
|
-
"from_id",
|
|
11107
|
-
"from_kind"
|
|
11108
|
-
);
|
|
11109
|
-
}
|
|
11110
|
-
case "both": {
|
|
11111
|
-
const outgoing = compileDirectionalExpansion(
|
|
11112
|
-
operation,
|
|
11113
|
-
workingTable,
|
|
11114
|
-
sourceFilter,
|
|
11115
|
-
edgeKinds,
|
|
11116
|
-
"from_id",
|
|
11117
|
-
"from_kind",
|
|
11118
|
-
"to_id",
|
|
11119
|
-
"to_kind"
|
|
11120
|
-
);
|
|
11121
|
-
const incoming = compileDirectionalExpansion(
|
|
11122
|
-
operation,
|
|
11123
|
-
workingTable,
|
|
11124
|
-
sourceFilter,
|
|
11125
|
-
edgeKinds,
|
|
11126
|
-
"to_id",
|
|
11127
|
-
"to_kind",
|
|
11128
|
-
"from_id",
|
|
11129
|
-
"from_kind"
|
|
11130
|
-
);
|
|
11131
|
-
return sql`${outgoing} UNION ALL ${incoming}`;
|
|
11132
|
-
}
|
|
11133
|
-
}
|
|
11304
|
+
return compileDirectionUnion(
|
|
11305
|
+
direction,
|
|
11306
|
+
(fields) => compileDirectionalExpansion(
|
|
11307
|
+
operation,
|
|
11308
|
+
workingTable,
|
|
11309
|
+
sourceFilter,
|
|
11310
|
+
edgeKinds,
|
|
11311
|
+
fields.joinField,
|
|
11312
|
+
fields.joinKindField,
|
|
11313
|
+
fields.targetField,
|
|
11314
|
+
fields.targetKindField
|
|
11315
|
+
)
|
|
11316
|
+
);
|
|
11134
11317
|
}
|
|
11135
|
-
function compileWorkingTableEdgeExpansion(operation, workingTable, sourceFilter, direction, edgeKinds) {
|
|
11136
|
-
|
|
11137
|
-
|
|
11138
|
-
|
|
11139
|
-
|
|
11140
|
-
|
|
11141
|
-
|
|
11142
|
-
|
|
11143
|
-
|
|
11144
|
-
|
|
11145
|
-
|
|
11146
|
-
|
|
11147
|
-
|
|
11148
|
-
|
|
11149
|
-
|
|
11150
|
-
return compileDirectionalEdgeExpansion(
|
|
11151
|
-
operation,
|
|
11152
|
-
workingTable,
|
|
11153
|
-
sourceFilter,
|
|
11154
|
-
edgeKinds,
|
|
11155
|
-
"to_id",
|
|
11156
|
-
"to_kind",
|
|
11157
|
-
"from_id",
|
|
11158
|
-
"from_kind"
|
|
11159
|
-
);
|
|
11160
|
-
}
|
|
11161
|
-
case "both": {
|
|
11162
|
-
const outgoing = compileDirectionalEdgeExpansion(
|
|
11163
|
-
operation,
|
|
11164
|
-
workingTable,
|
|
11165
|
-
sourceFilter,
|
|
11166
|
-
edgeKinds,
|
|
11167
|
-
"from_id",
|
|
11168
|
-
"from_kind",
|
|
11169
|
-
"to_id",
|
|
11170
|
-
"to_kind"
|
|
11171
|
-
);
|
|
11172
|
-
const incoming = compileDirectionalEdgeExpansion(
|
|
11173
|
-
operation,
|
|
11174
|
-
workingTable,
|
|
11175
|
-
sourceFilter,
|
|
11176
|
-
edgeKinds,
|
|
11177
|
-
"to_id",
|
|
11178
|
-
"to_kind",
|
|
11179
|
-
"from_id",
|
|
11180
|
-
"from_kind"
|
|
11181
|
-
);
|
|
11182
|
-
return sql`${outgoing} UNION ALL ${incoming}`;
|
|
11183
|
-
}
|
|
11184
|
-
}
|
|
11318
|
+
function compileWorkingTableEdgeExpansion(operation, workingTable, sourceFilter, direction, edgeKinds, sourceProjection) {
|
|
11319
|
+
return compileDirectionUnion(
|
|
11320
|
+
direction,
|
|
11321
|
+
(fields) => compileDirectionalEdgeExpansion(
|
|
11322
|
+
operation,
|
|
11323
|
+
workingTable,
|
|
11324
|
+
sourceFilter,
|
|
11325
|
+
edgeKinds,
|
|
11326
|
+
fields.joinField,
|
|
11327
|
+
fields.joinKindField,
|
|
11328
|
+
fields.targetField,
|
|
11329
|
+
fields.targetKindField,
|
|
11330
|
+
sourceProjection
|
|
11331
|
+
)
|
|
11332
|
+
);
|
|
11185
11333
|
}
|
|
11186
11334
|
function compileDirectionalExpansion(operation, workingRelation, sourceFilter, edgeKinds, joinField, joinKindField, targetField, targetKindField) {
|
|
11187
11335
|
const edgeExpansion = compileDirectionalEdgeExpansion(
|
|
@@ -11197,10 +11345,11 @@ function compileDirectionalExpansion(operation, workingRelation, sourceFilter, e
|
|
|
11197
11345
|
const weightColumn = operation.weightExpression === void 0 ? sql`` : sql`, expanded.weight`;
|
|
11198
11346
|
return sql`SELECT expanded.source_id, expanded.source_kind, n.id AS target_id, n.kind AS target_kind${weightColumn} FROM (${edgeExpansion}) expanded JOIN ${operation.schema.nodesTable} n ON n.graph_id = ${operation.ctx.graphId} AND n.id = expanded.target_id AND n.kind = expanded.target_kind WHERE ${operation.nodeTemporalFilter}`;
|
|
11199
11347
|
}
|
|
11200
|
-
function compileDirectionalEdgeExpansion(operation, workingRelation, sourceFilter, edgeKinds, joinField, joinKindField, targetField, targetKindField) {
|
|
11348
|
+
function compileDirectionalEdgeExpansion(operation, workingRelation, sourceFilter, edgeKinds, joinField, joinKindField, targetField, targetKindField, sourceProjection) {
|
|
11201
11349
|
const edgeKindFilter = compileKindFilter(sql.raw("e.kind"), edgeKinds);
|
|
11202
11350
|
const weightColumn = operation.weightExpression === void 0 ? sql`` : sql`, ${operation.weightExpression} AS weight`;
|
|
11203
|
-
|
|
11351
|
+
const sourceColumns = sourceProjection === void 0 ? sql`` : sql`, ${sourceProjection}`;
|
|
11352
|
+
return sql`SELECT w.node_id AS source_id, w.node_kind AS source_kind${sourceColumns}, e.${sql.raw(targetField)} AS target_id, e.${sql.raw(targetKindField)} AS target_kind${weightColumn} FROM ${workingRelation} w JOIN ${operation.schema.edgesTable} e ON e.${sql.raw(joinField)} = w.node_id AND e.${sql.raw(joinKindField)} = w.node_kind AND e.graph_id = ${operation.ctx.graphId} WHERE ${sourceFilter} AND ${edgeKindFilter} AND ${operation.edgeTemporalFilter}`;
|
|
11204
11353
|
}
|
|
11205
11354
|
function chunkValues(values, chunkSize) {
|
|
11206
11355
|
const chunks = [];
|
|
@@ -11283,7 +11432,7 @@ function compileWeightExpression(dialect, weightProperty, defaultWeight) {
|
|
|
11283
11432
|
return defaultWeight === void 0 ? extracted : sql`COALESCE(${extracted}, ${defaultWeight})`;
|
|
11284
11433
|
}
|
|
11285
11434
|
function supportsTemporaryIteration(ctx) {
|
|
11286
|
-
return ctx.backend.capabilities.transactions && ctx.backend.capabilities.returning !== false && ctx.backend.executeTemporaryStatement !== void 0;
|
|
11435
|
+
return ctx.backend.capabilities.transactions && ctx.backend.capabilities.graphAnalytics?.supported !== false && ctx.backend.capabilities.returning !== false && ctx.backend.executeTemporaryStatement !== void 0;
|
|
11287
11436
|
}
|
|
11288
11437
|
function requireTemporaryStatements(backend) {
|
|
11289
11438
|
if (backend.executeTemporaryStatement === void 0) {
|
|
@@ -11298,30 +11447,763 @@ function requireTemporaryStatements(backend) {
|
|
|
11298
11447
|
return backend;
|
|
11299
11448
|
}
|
|
11300
11449
|
|
|
11301
|
-
// src/store/algorithms/
|
|
11302
|
-
|
|
11303
|
-
|
|
11304
|
-
|
|
11305
|
-
|
|
11306
|
-
|
|
11307
|
-
}
|
|
11308
|
-
|
|
11309
|
-
|
|
11310
|
-
|
|
11311
|
-
|
|
11312
|
-
|
|
11313
|
-
|
|
11314
|
-
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
|
|
11319
|
-
|
|
11320
|
-
|
|
11450
|
+
// src/store/algorithms/label-propagation.ts
|
|
11451
|
+
var DEFAULT_LABEL_PROPAGATION_MAX_ITERATIONS = 1e3;
|
|
11452
|
+
async function executeLabelPropagation(ctx, options) {
|
|
11453
|
+
assertEdgeKinds(options.edges);
|
|
11454
|
+
assertGraphAnalyticsSupported(ctx, "labelPropagation", {
|
|
11455
|
+
requiresWindowFunctions: true
|
|
11456
|
+
});
|
|
11457
|
+
const maxIterations = resolveMaxIterations(
|
|
11458
|
+
options.maxIterations,
|
|
11459
|
+
DEFAULT_LABEL_PROPAGATION_MAX_ITERATIONS,
|
|
11460
|
+
"labelPropagation"
|
|
11461
|
+
);
|
|
11462
|
+
const nodeKinds = normalizeNodeKinds(options.nodeKinds);
|
|
11463
|
+
const policy = {
|
|
11464
|
+
detector: createOscillationDetector(),
|
|
11465
|
+
maxIterations,
|
|
11466
|
+
onMaxIterations: options.onMaxIterations ?? "throw"
|
|
11467
|
+
};
|
|
11468
|
+
const traversalOptions = {
|
|
11469
|
+
edges: options.edges,
|
|
11470
|
+
direction: "both",
|
|
11471
|
+
...pickTemporalOptions(options),
|
|
11472
|
+
...options.workingMemory === void 0 ? {} : { workingMemory: options.workingMemory }
|
|
11473
|
+
};
|
|
11474
|
+
return runIterativeGraphOperation(ctx, traversalOptions, {
|
|
11475
|
+
algorithm: "labelPropagation",
|
|
11476
|
+
maxIterations,
|
|
11477
|
+
createWorkingTable,
|
|
11478
|
+
initialize: (context) => initializeWorkingTables(context, nodeKinds),
|
|
11479
|
+
runRound: (context, state, iteration) => runLabelPropagationRound(context, state, iteration, policy),
|
|
11480
|
+
hasConverged(state) {
|
|
11481
|
+
return state.changedCount === 0 || state.completed;
|
|
11482
|
+
},
|
|
11483
|
+
extractResult: extractMemberships,
|
|
11484
|
+
cleanup: dropNeighborTable
|
|
11485
|
+
});
|
|
11486
|
+
}
|
|
11487
|
+
function createOscillationDetector() {
|
|
11488
|
+
const shadowLabels = /* @__PURE__ */ new Map();
|
|
11489
|
+
let previousRound;
|
|
11490
|
+
return {
|
|
11491
|
+
/** Records one applied round; true when the round inverts the previous. */
|
|
11492
|
+
observeRound(changedRows) {
|
|
11493
|
+
const round = /* @__PURE__ */ new Map();
|
|
11494
|
+
for (const row of changedRows) {
|
|
11495
|
+
const node = nodeIdentityKey({ id: row.node_id, kind: row.node_kind });
|
|
11496
|
+
const after = nodeIdentityKey({
|
|
11497
|
+
id: row.label_id,
|
|
11498
|
+
kind: row.label_kind
|
|
11499
|
+
});
|
|
11500
|
+
const before = shadowLabels.get(node) ?? node;
|
|
11501
|
+
round.set(node, { before, after });
|
|
11502
|
+
shadowLabels.set(node, after);
|
|
11503
|
+
}
|
|
11504
|
+
const priorRound = previousRound;
|
|
11505
|
+
previousRound = round;
|
|
11506
|
+
if (priorRound?.size !== round.size) return false;
|
|
11507
|
+
if (round.size === 0) return false;
|
|
11508
|
+
for (const [node, change] of round) {
|
|
11509
|
+
if (priorRound.get(node)?.before !== change.after) return false;
|
|
11510
|
+
}
|
|
11511
|
+
return true;
|
|
11512
|
+
}
|
|
11513
|
+
};
|
|
11514
|
+
}
|
|
11515
|
+
function createWorkingTable(context) {
|
|
11516
|
+
return sql`
|
|
11517
|
+
CREATE TEMP TABLE ${context.workingTable} (
|
|
11518
|
+
graph_id TEXT NOT NULL,
|
|
11519
|
+
run_id TEXT NOT NULL,
|
|
11520
|
+
node_id TEXT NOT NULL,
|
|
11521
|
+
node_kind TEXT NOT NULL,
|
|
11522
|
+
label_id TEXT NOT NULL,
|
|
11523
|
+
label_kind TEXT NOT NULL,
|
|
11524
|
+
next_label_id TEXT NOT NULL,
|
|
11525
|
+
next_label_kind TEXT NOT NULL,
|
|
11526
|
+
changed_round INTEGER NOT NULL,
|
|
11527
|
+
active_round INTEGER NOT NULL,
|
|
11528
|
+
PRIMARY KEY (graph_id, run_id, node_kind, node_id)
|
|
11529
|
+
)
|
|
11530
|
+
`;
|
|
11531
|
+
}
|
|
11532
|
+
function neighborTableIdentifier(context) {
|
|
11533
|
+
return sql.identifier(
|
|
11534
|
+
`typegraph_iterative_n_${context.runId.replaceAll("-", "_")}`
|
|
11535
|
+
);
|
|
11536
|
+
}
|
|
11537
|
+
function activeIndexIdentifier(context) {
|
|
11538
|
+
return sql.identifier(
|
|
11539
|
+
`typegraph_iterative_a_${context.runId.replaceAll("-", "_")}`
|
|
11540
|
+
);
|
|
11541
|
+
}
|
|
11542
|
+
async function initializeWorkingTables(context, nodeKinds) {
|
|
11543
|
+
const { operation, workingTable, graphId, runId } = context;
|
|
11544
|
+
const nodeKindFilter = compileNodeKindSeedFilter(nodeKinds);
|
|
11545
|
+
await context.executeTemporary(sql`
|
|
11546
|
+
INSERT INTO ${workingTable}
|
|
11547
|
+
(graph_id, run_id, node_id, node_kind, label_id, label_kind,
|
|
11548
|
+
next_label_id, next_label_kind, changed_round, active_round)
|
|
11549
|
+
SELECT
|
|
11550
|
+
${graphId}, ${runId}, n.id, n.kind, n.id, n.kind, n.id, n.kind, 0, 1
|
|
11551
|
+
FROM ${operation.schema.nodesTable} n
|
|
11552
|
+
WHERE n.graph_id = ${graphId}
|
|
11553
|
+
AND ${nodeKindFilter}
|
|
11554
|
+
AND ${operation.nodeTemporalFilter}
|
|
11555
|
+
`);
|
|
11556
|
+
await context.executeTemporary(sql`
|
|
11557
|
+
CREATE INDEX ${frontierIndexIdentifier(context)}
|
|
11558
|
+
ON ${workingTable} (graph_id, run_id, changed_round)
|
|
11559
|
+
`);
|
|
11560
|
+
await context.executeTemporary(sql`
|
|
11561
|
+
CREATE INDEX ${activeIndexIdentifier(context)}
|
|
11562
|
+
ON ${workingTable} (graph_id, run_id, active_round)
|
|
11563
|
+
`);
|
|
11564
|
+
const neighborTable = neighborTableIdentifier(context);
|
|
11565
|
+
await context.executeTemporary(sql`
|
|
11566
|
+
CREATE TEMP TABLE ${neighborTable} (
|
|
11567
|
+
target_id TEXT NOT NULL,
|
|
11568
|
+
target_kind TEXT NOT NULL,
|
|
11569
|
+
neighbor_id TEXT NOT NULL,
|
|
11570
|
+
neighbor_kind TEXT NOT NULL,
|
|
11571
|
+
PRIMARY KEY (target_kind, target_id, neighbor_kind, neighbor_id)
|
|
11572
|
+
)
|
|
11573
|
+
`);
|
|
11574
|
+
for (const edgeKinds of operation.edgeKindChunks) {
|
|
11575
|
+
await materializeChunkNeighbors(context, edgeKinds);
|
|
11576
|
+
}
|
|
11577
|
+
const analyzeNeighbors = operation.ctx.dialect.analyzeTemporaryTable(neighborTable);
|
|
11578
|
+
if (analyzeNeighbors !== void 0) {
|
|
11579
|
+
await context.executeTemporary(analyzeNeighbors);
|
|
11580
|
+
}
|
|
11581
|
+
const workingTableSize = await countWorkingTableRows(context);
|
|
11582
|
+
return {
|
|
11583
|
+
changedCount: workingTableSize,
|
|
11584
|
+
workingTableSize,
|
|
11585
|
+
completed: false,
|
|
11586
|
+
finishNextRound: false
|
|
11587
|
+
};
|
|
11588
|
+
}
|
|
11589
|
+
async function runLabelPropagationRound(context, state, iteration, policy) {
|
|
11590
|
+
if (iteration > 1) {
|
|
11591
|
+
await markActiveNeighbors(context, iteration);
|
|
11592
|
+
}
|
|
11593
|
+
await selectWinningLabels(context, iteration);
|
|
11594
|
+
const changedRows = await applyNextLabels(context, iteration);
|
|
11595
|
+
const next = {
|
|
11596
|
+
changedCount: changedRows.length,
|
|
11597
|
+
workingTableSize: state.workingTableSize,
|
|
11598
|
+
completed: false,
|
|
11599
|
+
finishNextRound: false
|
|
11600
|
+
};
|
|
11601
|
+
if (next.changedCount === 0) return next;
|
|
11602
|
+
if (state.finishNextRound) return { ...next, completed: true };
|
|
11603
|
+
if (policy.detector.observeRound(changedRows)) {
|
|
11604
|
+
return resolveOscillation(next, iteration, policy);
|
|
11605
|
+
}
|
|
11606
|
+
if (policy.onMaxIterations === "return" && iteration === policy.maxIterations) {
|
|
11607
|
+
return { ...next, completed: true };
|
|
11608
|
+
}
|
|
11609
|
+
return next;
|
|
11610
|
+
}
|
|
11611
|
+
function resolveOscillation(state, iteration, policy) {
|
|
11612
|
+
if (policy.onMaxIterations === "throw") {
|
|
11613
|
+
throw new GraphAlgorithmConvergenceError(
|
|
11614
|
+
"labelPropagation",
|
|
11615
|
+
policy.maxIterations,
|
|
11616
|
+
{ oscillating: true }
|
|
11617
|
+
);
|
|
11618
|
+
}
|
|
11619
|
+
const remaining = policy.maxIterations - iteration;
|
|
11620
|
+
if (remaining % 2 === 0) return { ...state, completed: true };
|
|
11621
|
+
return { ...state, finishNextRound: true };
|
|
11622
|
+
}
|
|
11623
|
+
async function markActiveNeighbors(context, iteration) {
|
|
11624
|
+
const { workingTable, graphId, runId } = context;
|
|
11625
|
+
const neighborTable = neighborTableIdentifier(context);
|
|
11626
|
+
await context.executeTemporary(sql`
|
|
11627
|
+
WITH candidates AS (
|
|
11628
|
+
SELECT DISTINCT neighbors.neighbor_id, neighbors.neighbor_kind
|
|
11629
|
+
FROM ${workingTable} changed
|
|
11630
|
+
JOIN ${neighborTable} neighbors
|
|
11631
|
+
ON neighbors.target_id = changed.node_id
|
|
11632
|
+
AND neighbors.target_kind = changed.node_kind
|
|
11633
|
+
WHERE changed.graph_id = ${graphId}
|
|
11634
|
+
AND changed.run_id = ${runId}
|
|
11635
|
+
AND changed.changed_round = ${iteration - 1}
|
|
11636
|
+
)
|
|
11637
|
+
UPDATE ${workingTable} AS target
|
|
11638
|
+
SET active_round = ${iteration}
|
|
11639
|
+
FROM candidates
|
|
11640
|
+
WHERE target.graph_id = ${graphId}
|
|
11641
|
+
AND target.run_id = ${runId}
|
|
11642
|
+
AND target.node_id = candidates.neighbor_id
|
|
11643
|
+
AND target.node_kind = candidates.neighbor_kind
|
|
11644
|
+
`);
|
|
11645
|
+
}
|
|
11646
|
+
async function materializeChunkNeighbors(context, edgeKinds) {
|
|
11647
|
+
const { operation, workingTable, graphId, runId } = context;
|
|
11648
|
+
const expansion = compileWorkingTableEdgeExpansion(
|
|
11649
|
+
operation,
|
|
11650
|
+
workingTable,
|
|
11651
|
+
sql`
|
|
11652
|
+
w.graph_id = ${graphId}
|
|
11653
|
+
AND w.run_id = ${runId}
|
|
11654
|
+
`,
|
|
11655
|
+
"both",
|
|
11656
|
+
edgeKinds
|
|
11657
|
+
);
|
|
11658
|
+
const neighborTable = neighborTableIdentifier(context);
|
|
11659
|
+
await context.executeTemporary(sql`
|
|
11660
|
+
INSERT INTO ${neighborTable}
|
|
11661
|
+
(target_id, target_kind, neighbor_id, neighbor_kind)
|
|
11662
|
+
SELECT DISTINCT
|
|
11663
|
+
expanded.source_id,
|
|
11664
|
+
expanded.source_kind,
|
|
11665
|
+
expanded.target_id,
|
|
11666
|
+
expanded.target_kind
|
|
11667
|
+
FROM (${expansion}) expanded
|
|
11668
|
+
JOIN ${workingTable} scoped_neighbor
|
|
11669
|
+
ON scoped_neighbor.graph_id = ${graphId}
|
|
11670
|
+
AND scoped_neighbor.run_id = ${runId}
|
|
11671
|
+
AND scoped_neighbor.node_id = expanded.target_id
|
|
11672
|
+
AND scoped_neighbor.node_kind = expanded.target_kind
|
|
11673
|
+
WHERE expanded.source_id <> expanded.target_id
|
|
11674
|
+
OR expanded.source_kind <> expanded.target_kind
|
|
11675
|
+
ON CONFLICT (target_kind, target_id, neighbor_kind, neighbor_id)
|
|
11676
|
+
DO NOTHING
|
|
11677
|
+
`);
|
|
11678
|
+
}
|
|
11679
|
+
async function selectWinningLabels(context, iteration) {
|
|
11680
|
+
const { operation, workingTable, graphId, runId } = context;
|
|
11681
|
+
const neighborTable = neighborTableIdentifier(context);
|
|
11682
|
+
const targetId = operation.ctx.dialect.binaryText(sql`totals.target_id`);
|
|
11683
|
+
const targetKind = operation.ctx.dialect.binaryText(sql`totals.target_kind`);
|
|
11684
|
+
const labelId = operation.ctx.dialect.binaryText(sql`totals.label_id`);
|
|
11685
|
+
const labelKind = operation.ctx.dialect.binaryText(sql`totals.label_kind`);
|
|
11686
|
+
await context.executeTemporary(sql`
|
|
11687
|
+
WITH totals AS (
|
|
11688
|
+
SELECT
|
|
11689
|
+
neighbors.target_id,
|
|
11690
|
+
neighbors.target_kind,
|
|
11691
|
+
neighbor.label_id,
|
|
11692
|
+
neighbor.label_kind,
|
|
11693
|
+
COUNT(*) AS total_votes
|
|
11694
|
+
FROM ${neighborTable} neighbors
|
|
11695
|
+
JOIN ${workingTable} active
|
|
11696
|
+
ON active.graph_id = ${graphId}
|
|
11697
|
+
AND active.run_id = ${runId}
|
|
11698
|
+
AND active.active_round = ${iteration}
|
|
11699
|
+
AND active.node_id = neighbors.target_id
|
|
11700
|
+
AND active.node_kind = neighbors.target_kind
|
|
11701
|
+
JOIN ${workingTable} neighbor
|
|
11702
|
+
ON neighbor.graph_id = ${graphId}
|
|
11703
|
+
AND neighbor.run_id = ${runId}
|
|
11704
|
+
AND neighbor.node_id = neighbors.neighbor_id
|
|
11705
|
+
AND neighbor.node_kind = neighbors.neighbor_kind
|
|
11706
|
+
GROUP BY
|
|
11707
|
+
target_id,
|
|
11708
|
+
target_kind,
|
|
11709
|
+
neighbor.label_id,
|
|
11710
|
+
neighbor.label_kind
|
|
11711
|
+
), ranked AS (
|
|
11712
|
+
SELECT
|
|
11713
|
+
target_id,
|
|
11714
|
+
target_kind,
|
|
11715
|
+
label_id,
|
|
11716
|
+
label_kind,
|
|
11717
|
+
ROW_NUMBER() OVER (
|
|
11718
|
+
PARTITION BY ${targetKind}, ${targetId}
|
|
11719
|
+
ORDER BY total_votes DESC, ${labelId}, ${labelKind}
|
|
11720
|
+
) AS label_rank
|
|
11721
|
+
FROM totals
|
|
11722
|
+
)
|
|
11723
|
+
UPDATE ${workingTable} AS target
|
|
11724
|
+
SET next_label_id = ranked.label_id,
|
|
11725
|
+
next_label_kind = ranked.label_kind
|
|
11726
|
+
FROM ranked
|
|
11727
|
+
WHERE target.graph_id = ${graphId}
|
|
11728
|
+
AND target.run_id = ${runId}
|
|
11729
|
+
AND target.active_round = ${iteration}
|
|
11730
|
+
AND target.node_id = ranked.target_id
|
|
11731
|
+
AND target.node_kind = ranked.target_kind
|
|
11732
|
+
AND ranked.label_rank = 1
|
|
11733
|
+
AND (
|
|
11734
|
+
target.next_label_id <> ranked.label_id
|
|
11735
|
+
OR target.next_label_kind <> ranked.label_kind
|
|
11736
|
+
)
|
|
11737
|
+
`);
|
|
11738
|
+
}
|
|
11739
|
+
function applyNextLabels(context, iteration) {
|
|
11740
|
+
return context.backend.execute(
|
|
11741
|
+
asCompiledRowsSql(sql`
|
|
11742
|
+
UPDATE ${context.workingTable}
|
|
11743
|
+
SET label_id = next_label_id,
|
|
11744
|
+
label_kind = next_label_kind,
|
|
11745
|
+
changed_round = ${iteration}
|
|
11746
|
+
WHERE graph_id = ${context.graphId}
|
|
11747
|
+
AND run_id = ${context.runId}
|
|
11748
|
+
AND active_round = ${iteration}
|
|
11749
|
+
AND (
|
|
11750
|
+
label_id <> next_label_id OR label_kind <> next_label_kind
|
|
11751
|
+
)
|
|
11752
|
+
RETURNING node_id, node_kind, label_id, label_kind
|
|
11753
|
+
`)
|
|
11754
|
+
);
|
|
11755
|
+
}
|
|
11756
|
+
async function extractMemberships(context) {
|
|
11757
|
+
const { operation } = context;
|
|
11758
|
+
const labelId = operation.ctx.dialect.binaryText(sql`label_id`);
|
|
11759
|
+
const labelKind = operation.ctx.dialect.binaryText(sql`label_kind`);
|
|
11760
|
+
const nodeId = operation.ctx.dialect.binaryText(sql`node_id`);
|
|
11761
|
+
const nodeKind = operation.ctx.dialect.binaryText(sql`node_kind`);
|
|
11762
|
+
const rows = await context.backend.execute(
|
|
11763
|
+
asCompiledRowsSql(sql`
|
|
11764
|
+
SELECT
|
|
11765
|
+
node_id,
|
|
11766
|
+
node_kind,
|
|
11767
|
+
label_id,
|
|
11768
|
+
label_kind
|
|
11769
|
+
FROM ${context.workingTable}
|
|
11770
|
+
WHERE graph_id = ${context.graphId} AND run_id = ${context.runId}
|
|
11771
|
+
ORDER BY ${labelId}, ${labelKind}, ${nodeId}, ${nodeKind}
|
|
11772
|
+
`)
|
|
11773
|
+
);
|
|
11774
|
+
return rows.map((row) => ({
|
|
11775
|
+
id: row.node_id,
|
|
11776
|
+
kind: row.node_kind,
|
|
11777
|
+
labelId: row.label_id,
|
|
11778
|
+
labelKind: row.label_kind
|
|
11779
|
+
}));
|
|
11780
|
+
}
|
|
11781
|
+
async function dropNeighborTable(context) {
|
|
11782
|
+
await context.executeTemporary(
|
|
11783
|
+
sql`DROP TABLE IF EXISTS ${neighborTableIdentifier(context)}`
|
|
11784
|
+
);
|
|
11785
|
+
}
|
|
11786
|
+
|
|
11787
|
+
// src/store/algorithms/page-rank.ts
|
|
11788
|
+
var DEFAULT_DAMPING_FACTOR = 0.85;
|
|
11789
|
+
var DEFAULT_TOLERANCE = 1e-8;
|
|
11790
|
+
var DEFAULT_MAX_ITERATIONS = 1e3;
|
|
11791
|
+
var BIND_PARAMETERS_PER_SEED = 3;
|
|
11792
|
+
var RESERVED_SEED_STATEMENT_BIND_PARAMETERS = 2;
|
|
11793
|
+
async function executePageRank(ctx, options) {
|
|
11794
|
+
return executePageRankOperation(ctx, options, void 0);
|
|
11795
|
+
}
|
|
11796
|
+
async function executePersonalizedPageRank(ctx, options) {
|
|
11797
|
+
return executePageRankOperation(ctx, options, normalizeSeeds(options.seeds));
|
|
11798
|
+
}
|
|
11799
|
+
function executePageRankOperation(ctx, options, seeds) {
|
|
11800
|
+
const algorithm = seeds === void 0 ? "pageRank" : "personalizedPageRank";
|
|
11801
|
+
assertEdgeKinds(options.edges);
|
|
11802
|
+
assertGraphAnalyticsSupported(ctx, algorithm);
|
|
11803
|
+
const resolved = resolvePageRankOptions(options, algorithm);
|
|
11804
|
+
const traversalOptions = {
|
|
11805
|
+
edges: options.edges,
|
|
11806
|
+
direction: options.direction ?? "out",
|
|
11807
|
+
...pickTemporalOptions(options),
|
|
11808
|
+
...options.workingMemory === void 0 ? {} : { workingMemory: options.workingMemory }
|
|
11809
|
+
};
|
|
11810
|
+
return runIterativeGraphOperation(ctx, traversalOptions, {
|
|
11811
|
+
algorithm,
|
|
11812
|
+
maxIterations: resolved.maxIterations,
|
|
11813
|
+
createWorkingTable: createWorkingTable2,
|
|
11814
|
+
initialize: (context) => initializeWorkingTable(context, resolved.nodeKinds, seeds),
|
|
11815
|
+
runRound: (context, state) => runPowerIterationRound(context, state, resolved.dampingFactor),
|
|
11816
|
+
hasConverged(state) {
|
|
11817
|
+
return state.maximumChange <= resolved.tolerance;
|
|
11818
|
+
},
|
|
11819
|
+
extractResult: extractScores
|
|
11820
|
+
});
|
|
11821
|
+
}
|
|
11822
|
+
function resolvePageRankOptions(options, algorithm) {
|
|
11823
|
+
const dampingFactor = options.dampingFactor ?? DEFAULT_DAMPING_FACTOR;
|
|
11824
|
+
if (!Number.isFinite(dampingFactor) || dampingFactor < 0 || dampingFactor >= 1) {
|
|
11825
|
+
throw new ConfigurationError(
|
|
11826
|
+
`PageRank dampingFactor must be finite and in [0, 1), got ${String(dampingFactor)}.`,
|
|
11827
|
+
{ dampingFactor }
|
|
11828
|
+
);
|
|
11829
|
+
}
|
|
11830
|
+
const tolerance = options.tolerance ?? DEFAULT_TOLERANCE;
|
|
11831
|
+
if (!Number.isFinite(tolerance) || tolerance <= 0) {
|
|
11832
|
+
throw new ConfigurationError(
|
|
11833
|
+
`PageRank tolerance must be finite and greater than 0, got ${String(tolerance)}.`,
|
|
11834
|
+
{ tolerance }
|
|
11835
|
+
);
|
|
11836
|
+
}
|
|
11837
|
+
return {
|
|
11838
|
+
dampingFactor,
|
|
11839
|
+
tolerance,
|
|
11840
|
+
maxIterations: resolveMaxIterations(
|
|
11841
|
+
options.maxIterations,
|
|
11842
|
+
DEFAULT_MAX_ITERATIONS,
|
|
11843
|
+
algorithm
|
|
11844
|
+
),
|
|
11845
|
+
nodeKinds: normalizeNodeKinds(options.nodeKinds)
|
|
11846
|
+
};
|
|
11847
|
+
}
|
|
11848
|
+
function normalizeSeeds(seeds) {
|
|
11849
|
+
if (seeds.length === 0) {
|
|
11850
|
+
throw new ConfigurationError(
|
|
11851
|
+
"Personalized PageRank requires at least one seed.",
|
|
11852
|
+
{ seeds }
|
|
11853
|
+
);
|
|
11854
|
+
}
|
|
11855
|
+
const combined = /* @__PURE__ */ new Map();
|
|
11856
|
+
for (const seed of seeds) {
|
|
11857
|
+
if (typeof seed.id !== "string" || seed.id.length === 0 || seed.id.includes("\0") || typeof seed.kind !== "string" || seed.kind.length === 0 || seed.kind.includes("\0")) {
|
|
11858
|
+
throw new ConfigurationError(
|
|
11859
|
+
"Personalized PageRank seed id and kind must be non-empty strings without NUL characters.",
|
|
11860
|
+
{ seed }
|
|
11861
|
+
);
|
|
11862
|
+
}
|
|
11863
|
+
const weight = seed.weight ?? 1;
|
|
11864
|
+
if (!Number.isFinite(weight) || weight <= 0) {
|
|
11865
|
+
throw new ConfigurationError(
|
|
11866
|
+
`Personalized PageRank seed weight must be finite and greater than 0, got ${String(weight)}.`,
|
|
11867
|
+
{ seed }
|
|
11868
|
+
);
|
|
11869
|
+
}
|
|
11870
|
+
const key = nodeIdentityKey(seed);
|
|
11871
|
+
const previous = combined.get(key);
|
|
11872
|
+
const combinedWeight = (previous?.weight ?? 0) + weight;
|
|
11873
|
+
if (!Number.isFinite(combinedWeight)) {
|
|
11874
|
+
throw new ConfigurationError(
|
|
11875
|
+
"Personalized PageRank seed weights overflowed while combining duplicate seeds.",
|
|
11876
|
+
{ seed }
|
|
11877
|
+
);
|
|
11878
|
+
}
|
|
11879
|
+
combined.set(key, { id: seed.id, kind: seed.kind, weight: combinedWeight });
|
|
11880
|
+
}
|
|
11881
|
+
const combinedSeeds = [...combined.values()];
|
|
11882
|
+
let maximumWeight = 0;
|
|
11883
|
+
for (const seed of combinedSeeds) {
|
|
11884
|
+
maximumWeight = Math.max(maximumWeight, seed.weight);
|
|
11885
|
+
}
|
|
11886
|
+
const scaledTotal = combinedSeeds.reduce(
|
|
11887
|
+
(total, seed) => total + seed.weight / maximumWeight,
|
|
11888
|
+
0
|
|
11889
|
+
);
|
|
11890
|
+
return combinedSeeds.map((seed) => {
|
|
11891
|
+
const weight = seed.weight / maximumWeight / scaledTotal;
|
|
11892
|
+
if (weight === 0) {
|
|
11893
|
+
throw new ConfigurationError(
|
|
11894
|
+
"Personalized PageRank seed weights differ too much to normalize without underflow.",
|
|
11895
|
+
{ seed }
|
|
11896
|
+
);
|
|
11897
|
+
}
|
|
11898
|
+
return { id: seed.id, kind: seed.kind, weight };
|
|
11899
|
+
}).toSorted((left, right) => compareNodeIdentity(left, right));
|
|
11900
|
+
}
|
|
11901
|
+
function createWorkingTable2(context) {
|
|
11902
|
+
return sql`
|
|
11903
|
+
CREATE TEMP TABLE ${context.workingTable} (
|
|
11904
|
+
graph_id TEXT NOT NULL,
|
|
11905
|
+
run_id TEXT NOT NULL,
|
|
11906
|
+
node_id TEXT NOT NULL,
|
|
11907
|
+
node_kind TEXT NOT NULL,
|
|
11908
|
+
score DOUBLE PRECISION NOT NULL,
|
|
11909
|
+
next_score DOUBLE PRECISION NOT NULL,
|
|
11910
|
+
personalization DOUBLE PRECISION NOT NULL,
|
|
11911
|
+
out_weight DOUBLE PRECISION NOT NULL,
|
|
11912
|
+
PRIMARY KEY (graph_id, run_id, node_kind, node_id)
|
|
11913
|
+
)
|
|
11914
|
+
`;
|
|
11915
|
+
}
|
|
11916
|
+
async function initializeWorkingTable(context, nodeKinds, seeds) {
|
|
11917
|
+
const { operation, workingTable, graphId, runId } = context;
|
|
11918
|
+
const nodeKindFilter = compileNodeKindSeedFilter(nodeKinds);
|
|
11919
|
+
await context.executeTemporary(sql`
|
|
11920
|
+
INSERT INTO ${workingTable}
|
|
11921
|
+
(graph_id, run_id, node_id, node_kind, score, next_score,
|
|
11922
|
+
personalization, out_weight)
|
|
11923
|
+
SELECT ${graphId}, ${runId}, n.id, n.kind, 0.0, 0.0, 0.0, 0.0
|
|
11924
|
+
FROM ${operation.schema.nodesTable} n
|
|
11925
|
+
WHERE n.graph_id = ${graphId}
|
|
11926
|
+
AND ${nodeKindFilter}
|
|
11927
|
+
AND ${operation.nodeTemporalFilter}
|
|
11928
|
+
`);
|
|
11929
|
+
const workingTableSize = await countWorkingTableRows(context);
|
|
11930
|
+
if (workingTableSize === 0) {
|
|
11931
|
+
if (seeds !== void 0) {
|
|
11932
|
+
throw missingSeedError(seeds);
|
|
11933
|
+
}
|
|
11934
|
+
return {
|
|
11935
|
+
activeScoreColumn: "score",
|
|
11936
|
+
maximumChange: 0,
|
|
11937
|
+
workingTableSize
|
|
11938
|
+
};
|
|
11939
|
+
}
|
|
11940
|
+
if (seeds === void 0) {
|
|
11941
|
+
const uniformWeight = 1 / workingTableSize;
|
|
11942
|
+
await context.executeTemporary(sql`
|
|
11943
|
+
UPDATE ${workingTable}
|
|
11944
|
+
SET score = ${uniformWeight},
|
|
11945
|
+
personalization = ${uniformWeight}
|
|
11946
|
+
WHERE graph_id = ${graphId} AND run_id = ${runId}
|
|
11947
|
+
`);
|
|
11948
|
+
} else {
|
|
11949
|
+
await initializePersonalization(context, seeds);
|
|
11950
|
+
}
|
|
11951
|
+
for (const edgeKinds of operation.edgeKindChunks) {
|
|
11952
|
+
await accumulateOutWeights(context, edgeKinds);
|
|
11953
|
+
}
|
|
11954
|
+
return {
|
|
11955
|
+
activeScoreColumn: "score",
|
|
11956
|
+
maximumChange: Number.POSITIVE_INFINITY,
|
|
11957
|
+
workingTableSize
|
|
11958
|
+
};
|
|
11959
|
+
}
|
|
11960
|
+
async function initializePersonalization(context, seeds) {
|
|
11961
|
+
const parameterLimit = context.operation.backend.capabilities.maxBindParameters ?? DEFAULT_MAX_BIND_PARAMETERS;
|
|
11962
|
+
const seedChunkSize = Math.floor(
|
|
11963
|
+
(parameterLimit - RESERVED_SEED_STATEMENT_BIND_PARAMETERS) / BIND_PARAMETERS_PER_SEED
|
|
11964
|
+
);
|
|
11965
|
+
if (seedChunkSize < 1) {
|
|
11966
|
+
throw new ConfigurationError(
|
|
11967
|
+
"Personalized PageRank cannot fit one seed within the backend bind-parameter limit.",
|
|
11968
|
+
{ parameterLimit }
|
|
11969
|
+
);
|
|
11970
|
+
}
|
|
11971
|
+
for (let offset = 0; offset < seeds.length; offset += seedChunkSize) {
|
|
11972
|
+
const chunk2 = seeds.slice(offset, offset + seedChunkSize);
|
|
11973
|
+
const values = sql.join(
|
|
11974
|
+
chunk2.map(
|
|
11975
|
+
(seed) => sql`(${seed.id}, ${seed.kind}, CAST(${seed.weight} AS DOUBLE PRECISION))`
|
|
11976
|
+
),
|
|
11977
|
+
sql`, `
|
|
11978
|
+
);
|
|
11979
|
+
await context.executeTemporary(sql`
|
|
11980
|
+
WITH seed_values(node_id, node_kind, weight) AS (VALUES ${values})
|
|
11981
|
+
UPDATE ${context.workingTable} AS target
|
|
11982
|
+
SET score = seed_values.weight,
|
|
11983
|
+
personalization = seed_values.weight
|
|
11984
|
+
FROM seed_values
|
|
11985
|
+
WHERE target.graph_id = ${context.graphId}
|
|
11986
|
+
AND target.run_id = ${context.runId}
|
|
11987
|
+
AND target.node_id = seed_values.node_id
|
|
11988
|
+
AND target.node_kind = seed_values.node_kind
|
|
11989
|
+
`);
|
|
11990
|
+
}
|
|
11991
|
+
const matchedRows = await context.backend.execute(
|
|
11992
|
+
asCompiledRowsSql(sql`
|
|
11993
|
+
SELECT node_id, node_kind
|
|
11994
|
+
FROM ${context.workingTable}
|
|
11995
|
+
WHERE graph_id = ${context.graphId}
|
|
11996
|
+
AND run_id = ${context.runId}
|
|
11997
|
+
AND personalization > 0
|
|
11998
|
+
`)
|
|
11999
|
+
);
|
|
12000
|
+
const matched = new Set(
|
|
12001
|
+
matchedRows.map(
|
|
12002
|
+
(row) => nodeIdentityKey({ id: row.node_id, kind: row.node_kind })
|
|
12003
|
+
)
|
|
12004
|
+
);
|
|
12005
|
+
const missing = seeds.filter((seed) => !matched.has(nodeIdentityKey(seed)));
|
|
12006
|
+
if (missing.length > 0) throw missingSeedError(missing);
|
|
12007
|
+
}
|
|
12008
|
+
function missingSeedError(seeds) {
|
|
12009
|
+
return new ConfigurationError(
|
|
12010
|
+
"Personalized PageRank seeds must identify visible nodes inside the selected induced subgraph.",
|
|
12011
|
+
{ missingSeeds: seeds.map((seed) => ({ id: seed.id, kind: seed.kind })) }
|
|
12012
|
+
);
|
|
12013
|
+
}
|
|
12014
|
+
async function accumulateOutWeights(context, edgeKinds) {
|
|
12015
|
+
const { operation, workingTable, graphId, runId } = context;
|
|
12016
|
+
const expansion = compileWorkingTableEdgeExpansion(
|
|
12017
|
+
operation,
|
|
12018
|
+
workingTable,
|
|
12019
|
+
sql`w.graph_id = ${graphId} AND w.run_id = ${runId}`,
|
|
12020
|
+
operation.direction,
|
|
12021
|
+
edgeKinds
|
|
12022
|
+
);
|
|
12023
|
+
const transitionWeight = compileTransitionWeight(operation.direction);
|
|
12024
|
+
await context.executeTemporary(sql`
|
|
12025
|
+
WITH scoped_edges AS (
|
|
12026
|
+
SELECT
|
|
12027
|
+
expanded.source_id,
|
|
12028
|
+
expanded.source_kind,
|
|
12029
|
+
${transitionWeight} AS transition_weight
|
|
12030
|
+
FROM (${expansion}) expanded
|
|
12031
|
+
JOIN ${workingTable} scoped_target
|
|
12032
|
+
ON scoped_target.graph_id = ${graphId}
|
|
12033
|
+
AND scoped_target.run_id = ${runId}
|
|
12034
|
+
AND scoped_target.node_id = expanded.target_id
|
|
12035
|
+
AND scoped_target.node_kind = expanded.target_kind
|
|
12036
|
+
), degrees AS (
|
|
12037
|
+
SELECT source_id, source_kind, SUM(transition_weight) AS out_weight
|
|
12038
|
+
FROM scoped_edges
|
|
12039
|
+
GROUP BY source_id, source_kind
|
|
12040
|
+
)
|
|
12041
|
+
UPDATE ${workingTable} AS target
|
|
12042
|
+
SET out_weight = target.out_weight + degrees.out_weight
|
|
12043
|
+
FROM degrees
|
|
12044
|
+
WHERE target.graph_id = ${graphId}
|
|
12045
|
+
AND target.run_id = ${runId}
|
|
12046
|
+
AND target.node_id = degrees.source_id
|
|
12047
|
+
AND target.node_kind = degrees.source_kind
|
|
12048
|
+
`);
|
|
12049
|
+
}
|
|
12050
|
+
function compileTransitionWeight(direction) {
|
|
12051
|
+
if (direction !== "both") return sql`1.0`;
|
|
12052
|
+
return sql`
|
|
12053
|
+
CASE
|
|
12054
|
+
WHEN expanded.source_id = expanded.target_id
|
|
12055
|
+
AND expanded.source_kind = expanded.target_kind
|
|
12056
|
+
THEN 0.5
|
|
12057
|
+
ELSE 1.0
|
|
12058
|
+
END
|
|
12059
|
+
`;
|
|
12060
|
+
}
|
|
12061
|
+
async function runPowerIterationRound(context, state, dampingFactor) {
|
|
12062
|
+
const sourceScoreColumn = state.activeScoreColumn;
|
|
12063
|
+
const targetScoreColumn = sourceScoreColumn === "score" ? "next_score" : "score";
|
|
12064
|
+
await resetTargetScores(
|
|
12065
|
+
context,
|
|
12066
|
+
sourceScoreColumn,
|
|
12067
|
+
targetScoreColumn,
|
|
12068
|
+
dampingFactor
|
|
12069
|
+
);
|
|
12070
|
+
for (const edgeKinds of context.operation.edgeKindChunks) {
|
|
12071
|
+
await accumulateContributions(
|
|
12072
|
+
context,
|
|
12073
|
+
edgeKinds,
|
|
12074
|
+
dampingFactor,
|
|
12075
|
+
sourceScoreColumn,
|
|
12076
|
+
targetScoreColumn
|
|
12077
|
+
);
|
|
12078
|
+
}
|
|
12079
|
+
const maximumChange = await readMaximumChange(
|
|
12080
|
+
context,
|
|
12081
|
+
sourceScoreColumn,
|
|
12082
|
+
targetScoreColumn
|
|
12083
|
+
);
|
|
12084
|
+
return {
|
|
12085
|
+
activeScoreColumn: targetScoreColumn,
|
|
12086
|
+
maximumChange,
|
|
12087
|
+
workingTableSize: state.workingTableSize
|
|
12088
|
+
};
|
|
12089
|
+
}
|
|
12090
|
+
async function resetTargetScores(context, sourceScoreColumn, targetScoreColumn, dampingFactor) {
|
|
12091
|
+
const sourceScore = sql.identifier(sourceScoreColumn);
|
|
12092
|
+
const targetScore = sql.identifier(targetScoreColumn);
|
|
12093
|
+
await context.executeTemporary(sql`
|
|
12094
|
+
UPDATE ${context.workingTable}
|
|
12095
|
+
SET ${targetScore} = personalization * (
|
|
12096
|
+
${1 - dampingFactor} + ${dampingFactor} * (
|
|
12097
|
+
SELECT COALESCE(SUM(dangling.${sourceScore}), 0.0)
|
|
12098
|
+
FROM ${context.workingTable} dangling
|
|
12099
|
+
WHERE dangling.graph_id = ${context.graphId}
|
|
12100
|
+
AND dangling.run_id = ${context.runId}
|
|
12101
|
+
AND dangling.out_weight = 0.0
|
|
12102
|
+
)
|
|
12103
|
+
)
|
|
12104
|
+
WHERE graph_id = ${context.graphId} AND run_id = ${context.runId}
|
|
12105
|
+
`);
|
|
12106
|
+
}
|
|
12107
|
+
async function accumulateContributions(context, edgeKinds, dampingFactor, sourceScoreColumn, targetScoreColumn) {
|
|
12108
|
+
const { operation, workingTable, graphId, runId } = context;
|
|
12109
|
+
const sourceScore = sql.identifier(sourceScoreColumn);
|
|
12110
|
+
const targetScore = sql.identifier(targetScoreColumn);
|
|
12111
|
+
const expansion = compileWorkingTableEdgeExpansion(
|
|
12112
|
+
operation,
|
|
12113
|
+
workingTable,
|
|
12114
|
+
sql`w.graph_id = ${graphId} AND w.run_id = ${runId}`,
|
|
12115
|
+
operation.direction,
|
|
12116
|
+
edgeKinds,
|
|
12117
|
+
sql`w.${sourceScore} AS source_score, w.out_weight AS source_out_weight`
|
|
12118
|
+
);
|
|
12119
|
+
const transitionWeight = compileTransitionWeight(operation.direction);
|
|
12120
|
+
await context.executeTemporary(sql`
|
|
12121
|
+
WITH scoped_edges AS (
|
|
12122
|
+
SELECT
|
|
12123
|
+
expanded.target_id,
|
|
12124
|
+
expanded.target_kind,
|
|
12125
|
+
expanded.source_score,
|
|
12126
|
+
expanded.source_out_weight,
|
|
12127
|
+
${transitionWeight} AS transition_weight
|
|
12128
|
+
FROM (${expansion}) expanded
|
|
12129
|
+
JOIN ${workingTable} scoped_target
|
|
12130
|
+
ON scoped_target.graph_id = ${graphId}
|
|
12131
|
+
AND scoped_target.run_id = ${runId}
|
|
12132
|
+
AND scoped_target.node_id = expanded.target_id
|
|
12133
|
+
AND scoped_target.node_kind = expanded.target_kind
|
|
12134
|
+
WHERE expanded.source_out_weight > 0.0
|
|
12135
|
+
), contributions AS (
|
|
12136
|
+
SELECT
|
|
12137
|
+
target_id,
|
|
12138
|
+
target_kind,
|
|
12139
|
+
SUM(source_score * transition_weight / source_out_weight) AS score
|
|
12140
|
+
FROM scoped_edges
|
|
12141
|
+
GROUP BY target_id, target_kind
|
|
12142
|
+
)
|
|
12143
|
+
UPDATE ${workingTable} AS target
|
|
12144
|
+
SET ${targetScore} = target.${targetScore} + ${dampingFactor} * contributions.score
|
|
12145
|
+
FROM contributions
|
|
12146
|
+
WHERE target.graph_id = ${graphId}
|
|
12147
|
+
AND target.run_id = ${runId}
|
|
12148
|
+
AND target.node_id = contributions.target_id
|
|
12149
|
+
AND target.node_kind = contributions.target_kind
|
|
12150
|
+
`);
|
|
12151
|
+
}
|
|
12152
|
+
async function readMaximumChange(context, sourceScoreColumn, targetScoreColumn) {
|
|
12153
|
+
const sourceScore = sql.identifier(sourceScoreColumn);
|
|
12154
|
+
const targetScore = sql.identifier(targetScoreColumn);
|
|
12155
|
+
const rows = await context.backend.execute(
|
|
12156
|
+
asCompiledRowsSql(sql`
|
|
12157
|
+
SELECT COALESCE(MAX(ABS(${targetScore} - ${sourceScore})), 0.0) AS value
|
|
12158
|
+
FROM ${context.workingTable}
|
|
12159
|
+
WHERE graph_id = ${context.graphId} AND run_id = ${context.runId}
|
|
12160
|
+
`)
|
|
12161
|
+
);
|
|
12162
|
+
return Number(rows[0]?.value ?? 0);
|
|
12163
|
+
}
|
|
12164
|
+
async function extractScores(context, state) {
|
|
12165
|
+
const score = sql.identifier(state.activeScoreColumn);
|
|
12166
|
+
const nodeId = context.operation.ctx.dialect.binaryText(sql`node_id`);
|
|
12167
|
+
const nodeKind = context.operation.ctx.dialect.binaryText(sql`node_kind`);
|
|
12168
|
+
const rows = await context.backend.execute(
|
|
12169
|
+
asCompiledRowsSql(sql`
|
|
12170
|
+
SELECT node_id, node_kind, ${score} AS score
|
|
12171
|
+
FROM ${context.workingTable}
|
|
12172
|
+
WHERE graph_id = ${context.graphId} AND run_id = ${context.runId}
|
|
12173
|
+
ORDER BY ${score} DESC, ${nodeId}, ${nodeKind}
|
|
12174
|
+
`)
|
|
12175
|
+
);
|
|
12176
|
+
return rows.map((row) => ({
|
|
12177
|
+
id: row.node_id,
|
|
12178
|
+
kind: row.node_kind,
|
|
12179
|
+
score: Number(row.score)
|
|
12180
|
+
}));
|
|
12181
|
+
}
|
|
12182
|
+
|
|
12183
|
+
// src/store/algorithms/breadth-first.ts
|
|
12184
|
+
async function findReachableNodes(ctx, sourceId, maxHops, options) {
|
|
12185
|
+
if (supportsTemporaryIteration(ctx)) {
|
|
12186
|
+
return findReachableNodesInWorkingTable(ctx, sourceId, maxHops, options);
|
|
12187
|
+
}
|
|
12188
|
+
return findReachableNodesInline(ctx, sourceId, maxHops, options);
|
|
12189
|
+
}
|
|
12190
|
+
async function findShortestPath(ctx, sourceId, targetId, maxHops, options) {
|
|
12191
|
+
if (supportsTemporaryIteration(ctx)) {
|
|
12192
|
+
return findShortestPathInWorkingTable(
|
|
12193
|
+
ctx,
|
|
12194
|
+
sourceId,
|
|
12195
|
+
targetId,
|
|
12196
|
+
maxHops,
|
|
12197
|
+
options
|
|
12198
|
+
);
|
|
12199
|
+
}
|
|
12200
|
+
return findShortestPathInline(ctx, sourceId, targetId, maxHops, options);
|
|
12201
|
+
}
|
|
12202
|
+
async function findReachableNodesInWorkingTable(ctx, sourceId, maxHops, options) {
|
|
11321
12203
|
return runIterativeGraphOperation(ctx, options, {
|
|
11322
12204
|
algorithm: "reachable",
|
|
11323
12205
|
maxIterations: maxHops,
|
|
11324
|
-
createWorkingTable,
|
|
12206
|
+
createWorkingTable: createWorkingTable3,
|
|
11325
12207
|
async initialize(context) {
|
|
11326
12208
|
const seeded = await seedWorkingSide(context, sourceId, "forward");
|
|
11327
12209
|
return {
|
|
@@ -11364,7 +12246,7 @@ async function findShortestPathInWorkingTable(ctx, sourceId, targetId, maxHops,
|
|
|
11364
12246
|
return runIterativeGraphOperation(ctx, options, {
|
|
11365
12247
|
algorithm: "shortestPath",
|
|
11366
12248
|
maxIterations: maxHops,
|
|
11367
|
-
createWorkingTable,
|
|
12249
|
+
createWorkingTable: createWorkingTable3,
|
|
11368
12250
|
async initialize(context) {
|
|
11369
12251
|
const forwardSeeds = await seedWorkingSide(context, sourceId, "forward");
|
|
11370
12252
|
const reverseSeeds = await seedWorkingSide(context, targetId, "reverse");
|
|
@@ -11414,7 +12296,7 @@ async function findShortestPathInWorkingTable(ctx, sourceId, targetId, maxHops,
|
|
|
11414
12296
|
}
|
|
11415
12297
|
});
|
|
11416
12298
|
}
|
|
11417
|
-
function
|
|
12299
|
+
function createWorkingTable3(context) {
|
|
11418
12300
|
return sql`
|
|
11419
12301
|
CREATE TEMP TABLE ${context.workingTable} (
|
|
11420
12302
|
graph_id TEXT NOT NULL,
|
|
@@ -11467,6 +12349,11 @@ async function expandWorkingTableRound(context, side, currentDepth, nextDepth, d
|
|
|
11467
12349
|
const oppositeSide = side === "forward" ? "reverse" : "forward";
|
|
11468
12350
|
let insertedCount = 0;
|
|
11469
12351
|
let meeting;
|
|
12352
|
+
const { dialect } = context.operation.ctx;
|
|
12353
|
+
const targetKind = dialect.binaryText(sql`expanded.target_kind`);
|
|
12354
|
+
const targetId = dialect.binaryText(sql`expanded.target_id`);
|
|
12355
|
+
const sourceId = dialect.binaryText(sql`expanded.source_id`);
|
|
12356
|
+
const sourceKind = dialect.binaryText(sql`expanded.source_kind`);
|
|
11470
12357
|
for (const edgeKinds of context.operation.edgeKindChunks) {
|
|
11471
12358
|
const sourceFilter = sql`
|
|
11472
12359
|
w.graph_id = ${context.graphId}
|
|
@@ -11502,8 +12389,8 @@ async function expandWorkingTableRound(context, side, currentDepth, nextDepth, d
|
|
|
11502
12389
|
FROM (
|
|
11503
12390
|
SELECT expanded.*,
|
|
11504
12391
|
ROW_NUMBER() OVER (
|
|
11505
|
-
PARTITION BY
|
|
11506
|
-
ORDER BY
|
|
12392
|
+
PARTITION BY ${targetKind}, ${targetId}
|
|
12393
|
+
ORDER BY ${sourceId}, ${sourceKind}
|
|
11507
12394
|
) AS candidate_rank
|
|
11508
12395
|
FROM (${expansion}) expanded
|
|
11509
12396
|
) ranked
|
|
@@ -11606,7 +12493,6 @@ async function readWorkingRows(context, side) {
|
|
|
11606
12493
|
WHERE graph_id = ${context.graphId}
|
|
11607
12494
|
AND run_id = ${context.runId}
|
|
11608
12495
|
AND ${sideFilter}
|
|
11609
|
-
ORDER BY side, depth, node_id, node_kind
|
|
11610
12496
|
`)
|
|
11611
12497
|
);
|
|
11612
12498
|
}
|
|
@@ -11652,7 +12538,8 @@ async function findShortestPathInline(ctx, sourceId, targetId, maxHops, options)
|
|
|
11652
12538
|
const sources = visibleNodes.filter((node) => node.id === sourceId);
|
|
11653
12539
|
const targets = visibleNodes.filter((node) => node.id === targetId);
|
|
11654
12540
|
if (sources.length === 0 || targets.length === 0) return;
|
|
11655
|
-
if (sourceId === targetId)
|
|
12541
|
+
if (sourceId === targetId)
|
|
12542
|
+
return { nodes: [requireDefined(sources[0])], depth: 0 };
|
|
11656
12543
|
const forwardVisited = createVisitedMap(sources);
|
|
11657
12544
|
const reverseVisited = createVisitedMap(targets);
|
|
11658
12545
|
let forwardWorkingSet = sources;
|
|
@@ -11738,8 +12625,12 @@ function findMeetingNodeKey(candidates, activeVisited, oppositeVisited) {
|
|
|
11738
12625
|
const active = activeVisited.get(key);
|
|
11739
12626
|
const opposite = oppositeVisited.get(key);
|
|
11740
12627
|
if (active === void 0 || opposite === void 0) continue;
|
|
11741
|
-
const meeting = {
|
|
11742
|
-
|
|
12628
|
+
const meeting = {
|
|
12629
|
+
key,
|
|
12630
|
+
node: { id: candidate.id, kind: candidate.kind },
|
|
12631
|
+
depth: active.depth + opposite.depth
|
|
12632
|
+
};
|
|
12633
|
+
if (best === void 0 || meeting.depth < best.depth || meeting.depth === best.depth && compareNodeIdentity(meeting.node, best.node) < 0) {
|
|
11743
12634
|
best = meeting;
|
|
11744
12635
|
}
|
|
11745
12636
|
}
|
|
@@ -11831,13 +12722,7 @@ async function executeNeighbors(ctx, sourceId, options) {
|
|
|
11831
12722
|
maxHops: depth,
|
|
11832
12723
|
direction: options.direction ?? "out",
|
|
11833
12724
|
cyclePolicy: options.cyclePolicy ?? "prevent",
|
|
11834
|
-
...options
|
|
11835
|
-
temporalMode: options.temporalMode
|
|
11836
|
-
},
|
|
11837
|
-
...options.asOf !== void 0 && { asOf: options.asOf },
|
|
11838
|
-
...options.recordedAsOf !== void 0 && {
|
|
11839
|
-
recordedAsOf: options.recordedAsOf
|
|
11840
|
-
},
|
|
12725
|
+
...pickTemporalOptions(options),
|
|
11841
12726
|
...options.workingMemory !== void 0 && {
|
|
11842
12727
|
workingMemory: options.workingMemory
|
|
11843
12728
|
},
|
|
@@ -11855,54 +12740,39 @@ async function executeShortestPath(ctx, sourceId, targetId, options) {
|
|
|
11855
12740
|
);
|
|
11856
12741
|
return findShortestPath(ctx, sourceId, targetId, maxHops, options);
|
|
11857
12742
|
}
|
|
12743
|
+
|
|
12744
|
+
// src/store/algorithms/weakly-connected-components.ts
|
|
11858
12745
|
var DEFAULT_WCC_MAX_ITERATIONS = 1e3;
|
|
11859
12746
|
async function executeWeaklyConnectedComponents(ctx, options) {
|
|
11860
12747
|
assertEdgeKinds(options.edges);
|
|
11861
|
-
|
|
12748
|
+
assertGraphAnalyticsSupported(ctx, "weaklyConnectedComponents", {
|
|
12749
|
+
requiresWindowFunctions: true
|
|
12750
|
+
});
|
|
11862
12751
|
const maxIterations = resolveMaxIterations(
|
|
11863
12752
|
options.maxIterations,
|
|
11864
12753
|
DEFAULT_WCC_MAX_ITERATIONS,
|
|
11865
12754
|
"weaklyConnectedComponents"
|
|
11866
12755
|
);
|
|
11867
|
-
const nodeKinds =
|
|
11868
|
-
(left, right) => compareCodePoints(left, right)
|
|
11869
|
-
);
|
|
12756
|
+
const nodeKinds = normalizeNodeKinds(options.nodeKinds);
|
|
11870
12757
|
const traversalOptions = {
|
|
11871
12758
|
edges: options.edges,
|
|
11872
12759
|
direction: "both",
|
|
11873
|
-
...options
|
|
11874
|
-
...options.asOf === void 0 ? {} : { asOf: options.asOf },
|
|
11875
|
-
...options.recordedAsOf === void 0 ? {} : { recordedAsOf: options.recordedAsOf },
|
|
12760
|
+
...pickTemporalOptions(options),
|
|
11876
12761
|
...options.workingMemory === void 0 ? {} : { workingMemory: options.workingMemory }
|
|
11877
12762
|
};
|
|
11878
12763
|
return runIterativeGraphOperation(ctx, traversalOptions, {
|
|
11879
12764
|
algorithm: "weaklyConnectedComponents",
|
|
11880
12765
|
maxIterations,
|
|
11881
|
-
createWorkingTable:
|
|
11882
|
-
initialize: (context) =>
|
|
11883
|
-
runRound:
|
|
12766
|
+
createWorkingTable: createWorkingTable4,
|
|
12767
|
+
initialize: (context) => initializeWorkingTable2(context, nodeKinds),
|
|
12768
|
+
runRound: runLabelPropagationRound2,
|
|
11884
12769
|
hasConverged(state) {
|
|
11885
12770
|
return state.changedCount === 0;
|
|
11886
12771
|
},
|
|
11887
|
-
extractResult:
|
|
12772
|
+
extractResult: extractMemberships2
|
|
11888
12773
|
});
|
|
11889
12774
|
}
|
|
11890
|
-
function
|
|
11891
|
-
if (ctx.backend.capabilities.graphAnalytics?.supported === true && ctx.backend.capabilities.windowFunctions) {
|
|
11892
|
-
return;
|
|
11893
|
-
}
|
|
11894
|
-
throw new UnsupportedBackendCapabilityError(
|
|
11895
|
-
"weaklyConnectedComponents",
|
|
11896
|
-
"graphAnalytics",
|
|
11897
|
-
{
|
|
11898
|
-
dialect: ctx.backend.dialect,
|
|
11899
|
-
supported: ctx.backend.capabilities.graphAnalytics?.supported === true,
|
|
11900
|
-
windowFunctions: ctx.backend.capabilities.windowFunctions
|
|
11901
|
-
},
|
|
11902
|
-
"Use a built-in transactional SQLite/PostgreSQL backend, or declare graphAnalytics support on a compatible custom backend."
|
|
11903
|
-
);
|
|
11904
|
-
}
|
|
11905
|
-
function createWorkingTable2(context) {
|
|
12775
|
+
function createWorkingTable4(context) {
|
|
11906
12776
|
return sql`
|
|
11907
12777
|
CREATE TEMP TABLE ${context.workingTable} (
|
|
11908
12778
|
graph_id TEXT NOT NULL,
|
|
@@ -11913,60 +12783,55 @@ function createWorkingTable2(context) {
|
|
|
11913
12783
|
label_kind TEXT NOT NULL,
|
|
11914
12784
|
next_label_id TEXT NOT NULL,
|
|
11915
12785
|
next_label_kind TEXT NOT NULL,
|
|
12786
|
+
improved_round INTEGER NOT NULL,
|
|
11916
12787
|
PRIMARY KEY (graph_id, run_id, node_kind, node_id)
|
|
11917
12788
|
)
|
|
11918
12789
|
`;
|
|
11919
12790
|
}
|
|
11920
|
-
async function
|
|
12791
|
+
async function initializeWorkingTable2(context, nodeKinds) {
|
|
11921
12792
|
const { operation, workingTable, graphId, runId } = context;
|
|
11922
|
-
const nodeKindFilter =
|
|
12793
|
+
const nodeKindFilter = compileNodeKindSeedFilter(nodeKinds);
|
|
11923
12794
|
await context.executeTemporary(sql`
|
|
11924
12795
|
INSERT INTO ${workingTable}
|
|
11925
12796
|
(graph_id, run_id, node_id, node_kind, label_id, label_kind,
|
|
11926
|
-
next_label_id, next_label_kind)
|
|
12797
|
+
next_label_id, next_label_kind, improved_round)
|
|
11927
12798
|
SELECT
|
|
11928
|
-
${graphId}, ${runId}, n.id, n.kind, n.id, n.kind, n.id, n.kind
|
|
12799
|
+
${graphId}, ${runId}, n.id, n.kind, n.id, n.kind, n.id, n.kind, 0
|
|
11929
12800
|
FROM ${operation.schema.nodesTable} n
|
|
11930
12801
|
WHERE n.graph_id = ${graphId}
|
|
11931
12802
|
AND ${nodeKindFilter}
|
|
11932
12803
|
AND ${operation.nodeTemporalFilter}
|
|
11933
12804
|
`);
|
|
11934
|
-
|
|
11935
|
-
|
|
11936
|
-
|
|
11937
|
-
|
|
11938
|
-
|
|
11939
|
-
`)
|
|
11940
|
-
);
|
|
11941
|
-
const workingTableSize = Number(rows[0]?.count ?? 0);
|
|
12805
|
+
await context.executeTemporary(sql`
|
|
12806
|
+
CREATE INDEX ${frontierIndexIdentifier(context)}
|
|
12807
|
+
ON ${workingTable} (graph_id, run_id, improved_round)
|
|
12808
|
+
`);
|
|
12809
|
+
const workingTableSize = await countWorkingTableRows(context);
|
|
11942
12810
|
return { changedCount: workingTableSize, workingTableSize };
|
|
11943
12811
|
}
|
|
11944
|
-
async function
|
|
11945
|
-
await resetNextLabels(context);
|
|
12812
|
+
async function runLabelPropagationRound2(context, state, iteration) {
|
|
11946
12813
|
for (const edgeKinds of context.operation.edgeKindChunks) {
|
|
11947
|
-
await propagateChunkLabels(context, edgeKinds);
|
|
12814
|
+
await propagateChunkLabels(context, edgeKinds, iteration);
|
|
11948
12815
|
}
|
|
11949
|
-
const changedRows = await
|
|
12816
|
+
const changedRows = await applyNextLabels2(context, iteration);
|
|
11950
12817
|
return {
|
|
11951
12818
|
changedCount: changedRows.length,
|
|
11952
12819
|
workingTableSize: state.workingTableSize
|
|
11953
12820
|
};
|
|
11954
12821
|
}
|
|
11955
|
-
async function
|
|
11956
|
-
await context.executeTemporary(sql`
|
|
11957
|
-
UPDATE ${context.workingTable}
|
|
11958
|
-
SET next_label_id = label_id, next_label_kind = label_kind
|
|
11959
|
-
WHERE graph_id = ${context.graphId} AND run_id = ${context.runId}
|
|
11960
|
-
`);
|
|
11961
|
-
}
|
|
11962
|
-
async function propagateChunkLabels(context, edgeKinds) {
|
|
12822
|
+
async function propagateChunkLabels(context, edgeKinds, iteration) {
|
|
11963
12823
|
const { operation, workingTable, graphId, runId } = context;
|
|
11964
12824
|
const expansion = compileWorkingTableEdgeExpansion(
|
|
11965
12825
|
operation,
|
|
11966
12826
|
workingTable,
|
|
11967
|
-
sql`
|
|
12827
|
+
sql`
|
|
12828
|
+
w.graph_id = ${graphId}
|
|
12829
|
+
AND w.run_id = ${runId}
|
|
12830
|
+
AND w.improved_round = ${iteration - 1}
|
|
12831
|
+
`,
|
|
11968
12832
|
"both",
|
|
11969
|
-
edgeKinds
|
|
12833
|
+
edgeKinds,
|
|
12834
|
+
sql`w.label_id AS source_label_id, w.label_kind AS source_label_kind`
|
|
11970
12835
|
);
|
|
11971
12836
|
const candidateId = operation.ctx.dialect.binaryText(sql`ranked.label_id`);
|
|
11972
12837
|
const candidateKind = operation.ctx.dialect.binaryText(
|
|
@@ -11985,14 +12850,9 @@ async function propagateChunkLabels(context, edgeKinds) {
|
|
|
11985
12850
|
SELECT
|
|
11986
12851
|
expanded.target_id,
|
|
11987
12852
|
expanded.target_kind,
|
|
11988
|
-
|
|
11989
|
-
|
|
12853
|
+
expanded.source_label_id AS label_id,
|
|
12854
|
+
expanded.source_label_kind AS label_kind
|
|
11990
12855
|
FROM (${expansion}) expanded
|
|
11991
|
-
JOIN ${workingTable} source
|
|
11992
|
-
ON source.graph_id = ${graphId}
|
|
11993
|
-
AND source.run_id = ${runId}
|
|
11994
|
-
AND source.node_id = expanded.source_id
|
|
11995
|
-
AND source.node_kind = expanded.source_kind
|
|
11996
12856
|
JOIN ${workingTable} scoped_target
|
|
11997
12857
|
ON scoped_target.graph_id = ${graphId}
|
|
11998
12858
|
AND scoped_target.run_id = ${runId}
|
|
@@ -12028,11 +12888,13 @@ async function propagateChunkLabels(context, edgeKinds) {
|
|
|
12028
12888
|
)
|
|
12029
12889
|
`);
|
|
12030
12890
|
}
|
|
12031
|
-
function
|
|
12891
|
+
function applyNextLabels2(context, iteration) {
|
|
12032
12892
|
return context.backend.execute(
|
|
12033
12893
|
asCompiledRowsSql(sql`
|
|
12034
12894
|
UPDATE ${context.workingTable}
|
|
12035
|
-
SET label_id = next_label_id,
|
|
12895
|
+
SET label_id = next_label_id,
|
|
12896
|
+
label_kind = next_label_kind,
|
|
12897
|
+
improved_round = ${iteration}
|
|
12036
12898
|
WHERE graph_id = ${context.graphId}
|
|
12037
12899
|
AND run_id = ${context.runId}
|
|
12038
12900
|
AND (
|
|
@@ -12042,7 +12904,7 @@ function applyNextLabels(context) {
|
|
|
12042
12904
|
`)
|
|
12043
12905
|
);
|
|
12044
12906
|
}
|
|
12045
|
-
async function
|
|
12907
|
+
async function extractMemberships2(context) {
|
|
12046
12908
|
const { operation } = context;
|
|
12047
12909
|
const componentId = operation.ctx.dialect.binaryText(sql`label_id`);
|
|
12048
12910
|
const componentKind = operation.ctx.dialect.binaryText(sql`label_kind`);
|
|
@@ -12069,11 +12931,10 @@ async function extractMemberships(context) {
|
|
|
12069
12931
|
componentId: row.component_id,
|
|
12070
12932
|
componentKind: row.component_kind,
|
|
12071
12933
|
size: Number(row.component_size)
|
|
12072
|
-
}))
|
|
12073
|
-
}
|
|
12074
|
-
function compareMemberships(left, right) {
|
|
12075
|
-
return compareCodePoints(left.componentId, right.componentId) || compareCodePoints(left.componentKind, right.componentKind) || compareCodePoints(left.id, right.id) || compareCodePoints(left.kind, right.kind);
|
|
12934
|
+
}));
|
|
12076
12935
|
}
|
|
12936
|
+
|
|
12937
|
+
// src/store/algorithms/weighted-shortest-path.ts
|
|
12077
12938
|
var DEFAULT_WEIGHTED_SHORTEST_PATH_MAX_ITERATIONS = 1e3;
|
|
12078
12939
|
var WEIGHTED_ALGORITHM_NAME = "weightedShortestPath";
|
|
12079
12940
|
var MAX_EDGE_WEIGHT = Number.MAX_VALUE / 2 ** 64;
|
|
@@ -12189,14 +13050,11 @@ function formatWeightValue(value) {
|
|
|
12189
13050
|
}
|
|
12190
13051
|
return JSON.stringify(value);
|
|
12191
13052
|
}
|
|
12192
|
-
function compareNodeIdentityCodePoints(left, right) {
|
|
12193
|
-
return compareCodePoints(left.id, right.id) || compareCodePoints(left.kind, right.kind);
|
|
12194
|
-
}
|
|
12195
13053
|
async function findWeightedShortestPathInWorkingTable(ctx, sourceId, targetId, maxIterations, options) {
|
|
12196
13054
|
return runIterativeGraphOperation(ctx, options, {
|
|
12197
13055
|
algorithm: WEIGHTED_ALGORITHM_NAME,
|
|
12198
13056
|
maxIterations,
|
|
12199
|
-
createWorkingTable:
|
|
13057
|
+
createWorkingTable: createWorkingTable5,
|
|
12200
13058
|
async initialize(context) {
|
|
12201
13059
|
await assertValidEdgeWeights(
|
|
12202
13060
|
context.operation,
|
|
@@ -12247,11 +13105,6 @@ async function findWeightedShortestPathInWorkingTable(ctx, sourceId, targetId, m
|
|
|
12247
13105
|
}
|
|
12248
13106
|
});
|
|
12249
13107
|
}
|
|
12250
|
-
function frontierIndexIdentifier(context) {
|
|
12251
|
-
return sql.identifier(
|
|
12252
|
-
`typegraph_iterative_${context.runId.replaceAll("-", "_")}_frontier`
|
|
12253
|
-
);
|
|
12254
|
-
}
|
|
12255
13108
|
async function hasVisibleNode(operation, nodeId) {
|
|
12256
13109
|
const rows = await operation.backend.execute(
|
|
12257
13110
|
asCompiledRowsSql(sql`
|
|
@@ -12264,7 +13117,7 @@ async function hasVisibleNode(operation, nodeId) {
|
|
|
12264
13117
|
);
|
|
12265
13118
|
return rows.length > 0;
|
|
12266
13119
|
}
|
|
12267
|
-
function
|
|
13120
|
+
function createWorkingTable5(context) {
|
|
12268
13121
|
return sql`
|
|
12269
13122
|
CREATE TEMP TABLE ${context.workingTable} (
|
|
12270
13123
|
graph_id TEXT NOT NULL,
|
|
@@ -12420,7 +13273,7 @@ async function findWeightedSelfPath(ctx, nodeId, options) {
|
|
|
12420
13273
|
);
|
|
12421
13274
|
const nodes = await fetchVisibleWorkingNodes(operation, [nodeId]);
|
|
12422
13275
|
const node = nodes.toSorted(
|
|
12423
|
-
(left, right) =>
|
|
13276
|
+
(left, right) => compareNodeIdentity(left, right)
|
|
12424
13277
|
)[0];
|
|
12425
13278
|
if (node === void 0) return;
|
|
12426
13279
|
return { nodes: [node], depth: 0, totalWeight: 0 };
|
|
@@ -12496,7 +13349,7 @@ async function findWeightedShortestPathInline(ctx, sourceId, targetId, maxIterat
|
|
|
12496
13349
|
}
|
|
12497
13350
|
}
|
|
12498
13351
|
frontier = improved.toSorted(
|
|
12499
|
-
(left, right) =>
|
|
13352
|
+
(left, right) => compareNodeIdentity(left, right)
|
|
12500
13353
|
);
|
|
12501
13354
|
}
|
|
12502
13355
|
return buildWeightedPathResult(settled, targetId);
|
|
@@ -12508,7 +13361,7 @@ function reduceWeightedCandidate(existing, expansion, settled) {
|
|
|
12508
13361
|
const sourceEntry = settled.get(nodeIdentityKey(expansion.source));
|
|
12509
13362
|
if (sourceEntry === void 0) return existing;
|
|
12510
13363
|
const candidateDistance = sourceEntry.distance + weight;
|
|
12511
|
-
if (existing !== void 0 && (existing.distance < candidateDistance || existing.distance === candidateDistance &&
|
|
13364
|
+
if (existing !== void 0 && (existing.distance < candidateDistance || existing.distance === candidateDistance && compareNodeIdentity(
|
|
12512
13365
|
{ id: existing.parentId, kind: existing.parentKind },
|
|
12513
13366
|
expansion.source
|
|
12514
13367
|
) <= 0)) {
|
|
@@ -12527,7 +13380,7 @@ function buildWeightedPathResult(visited, targetId) {
|
|
|
12527
13380
|
let target;
|
|
12528
13381
|
for (const node of visited.values()) {
|
|
12529
13382
|
if (node.id !== targetId) continue;
|
|
12530
|
-
if (target === void 0 || node.distance < target.distance || node.distance === target.distance &&
|
|
13383
|
+
if (target === void 0 || node.distance < target.distance || node.distance === target.distance && compareNodeIdentity(node, target) < 0) {
|
|
12531
13384
|
target = node;
|
|
12532
13385
|
}
|
|
12533
13386
|
}
|
|
@@ -12618,6 +13471,14 @@ function createGraphAlgorithms(params) {
|
|
|
12618
13471
|
assertRecordedAsOfInternalOnly(options, "degree", allowRecordedAsOf);
|
|
12619
13472
|
return executeDegree(ctx, resolveNodeId(node), options ?? {});
|
|
12620
13473
|
},
|
|
13474
|
+
labelPropagation(options) {
|
|
13475
|
+
assertRecordedAsOfInternalOnly(
|
|
13476
|
+
options,
|
|
13477
|
+
"labelPropagation",
|
|
13478
|
+
allowRecordedAsOf
|
|
13479
|
+
);
|
|
13480
|
+
return executeLabelPropagation(ctx, options);
|
|
13481
|
+
},
|
|
12621
13482
|
weaklyConnectedComponents(options) {
|
|
12622
13483
|
assertRecordedAsOfInternalOnly(
|
|
12623
13484
|
options,
|
|
@@ -12625,6 +13486,18 @@ function createGraphAlgorithms(params) {
|
|
|
12625
13486
|
allowRecordedAsOf
|
|
12626
13487
|
);
|
|
12627
13488
|
return executeWeaklyConnectedComponents(ctx, options);
|
|
13489
|
+
},
|
|
13490
|
+
pageRank(options) {
|
|
13491
|
+
assertRecordedAsOfInternalOnly(options, "pageRank", allowRecordedAsOf);
|
|
13492
|
+
return executePageRank(ctx, options);
|
|
13493
|
+
},
|
|
13494
|
+
personalizedPageRank(options) {
|
|
13495
|
+
assertRecordedAsOfInternalOnly(
|
|
13496
|
+
options,
|
|
13497
|
+
"personalizedPageRank",
|
|
13498
|
+
allowRecordedAsOf
|
|
13499
|
+
);
|
|
13500
|
+
return executePersonalizedPageRank(ctx, options);
|
|
12628
13501
|
}
|
|
12629
13502
|
};
|
|
12630
13503
|
}
|
|
@@ -12851,10 +13724,10 @@ function createEdgeCollection(config) {
|
|
|
12851
13724
|
itemIndex++;
|
|
12852
13725
|
continue;
|
|
12853
13726
|
}
|
|
12854
|
-
const deletedAt = pendingEntry === void 0 ? original.deleted_at : void 0;
|
|
13727
|
+
const deletedAt = pendingEntry === void 0 ? requireDefined(original).deleted_at : void 0;
|
|
12855
13728
|
let dirty;
|
|
12856
13729
|
if (config.upsertDirtyCheck !== void 0) {
|
|
12857
|
-
const currentProps = pendingEntry?.props ?? rowPropsToObject(original.props);
|
|
13730
|
+
const currentProps = pendingEntry?.props ?? rowPropsToObject(requireDefined(original).props);
|
|
12858
13731
|
try {
|
|
12859
13732
|
dirty = config.upsertDirtyCheck(
|
|
12860
13733
|
original?.kind ?? kind,
|
|
@@ -12869,7 +13742,9 @@ function createEdgeCollection(config) {
|
|
|
12869
13742
|
const coalesce = dirty?.unchanged === true && deletedAt === void 0 && item.validFrom === void 0 && item.validTo === void 0;
|
|
12870
13743
|
if (coalesce) {
|
|
12871
13744
|
if (pendingEntry === void 0) {
|
|
12872
|
-
results2[itemIndex] = narrowEdge(
|
|
13745
|
+
results2[itemIndex] = narrowEdge(
|
|
13746
|
+
rowToEdge2(requireDefined(original))
|
|
13747
|
+
);
|
|
12873
13748
|
} else {
|
|
12874
13749
|
deferred.push({
|
|
12875
13750
|
index: itemIndex,
|
|
@@ -12895,7 +13770,9 @@ function createEdgeCollection(config) {
|
|
|
12895
13770
|
const createInputs = toCreate.map((entry2) => entry2.input);
|
|
12896
13771
|
const created = await executeEdgeCreateBatch2(createInputs, target);
|
|
12897
13772
|
for (const [index, entry2] of toCreate.entries()) {
|
|
12898
|
-
results2[entry2.index] = narrowEdge(
|
|
13773
|
+
results2[entry2.index] = narrowEdge(
|
|
13774
|
+
requireDefined(created[index])
|
|
13775
|
+
);
|
|
12899
13776
|
}
|
|
12900
13777
|
}
|
|
12901
13778
|
for (const entry2 of toUpdate) {
|
|
@@ -12905,7 +13782,7 @@ function createEdgeCollection(config) {
|
|
|
12905
13782
|
results2[entry2.index] = narrowEdge(result);
|
|
12906
13783
|
}
|
|
12907
13784
|
for (const { index, sourceIndex } of deferred) {
|
|
12908
|
-
results2[index] = results2[sourceIndex];
|
|
13785
|
+
results2[index] = requireDefined(results2[sourceIndex]);
|
|
12909
13786
|
}
|
|
12910
13787
|
return { results: results2, mutations: toCreate.length + toUpdate.length };
|
|
12911
13788
|
};
|
|
@@ -13113,7 +13990,7 @@ function createNodeCollection(config) {
|
|
|
13113
13990
|
temporal,
|
|
13114
13991
|
defaultTemporalMode
|
|
13115
13992
|
);
|
|
13116
|
-
let query = createQuery().from(kind, "_n").temporal(asOf === void 0 ? temporalMode : "asOf", asOf).whereNode("_n", filter.where).select((ctx) => ctx
|
|
13993
|
+
let query = createQuery().from(kind, "_n").temporal(asOf === void 0 ? temporalMode : "asOf", asOf).whereNode("_n", filter.where).select((ctx) => ctx["_n"]);
|
|
13117
13994
|
if (filter.limit !== void 0) query = query.limit(filter.limit);
|
|
13118
13995
|
if (filter.offset !== void 0) query = query.offset(filter.offset);
|
|
13119
13996
|
const results = await query.execute();
|
|
@@ -13143,7 +14020,7 @@ function createNodeCollection(config) {
|
|
|
13143
14020
|
async upsertByIdFromRecord(id, data, options) {
|
|
13144
14021
|
const existing = await backend.getNode(graphId, kind, id);
|
|
13145
14022
|
if (existing) {
|
|
13146
|
-
const runDirtyCheck = config.upsertDirtyCheck && (() => config.upsertDirtyCheck(
|
|
14023
|
+
const runDirtyCheck = config.upsertDirtyCheck && (() => requireDefined(config.upsertDirtyCheck)(
|
|
13147
14024
|
kind,
|
|
13148
14025
|
id,
|
|
13149
14026
|
rowPropsToObject(existing.props),
|
|
@@ -13213,10 +14090,10 @@ function createNodeCollection(config) {
|
|
|
13213
14090
|
itemIndex++;
|
|
13214
14091
|
continue;
|
|
13215
14092
|
}
|
|
13216
|
-
const deletedAt = pendingEntry === void 0 ? original.deleted_at : void 0;
|
|
14093
|
+
const deletedAt = pendingEntry === void 0 ? requireDefined(original).deleted_at : void 0;
|
|
13217
14094
|
let dirty;
|
|
13218
14095
|
if (config.upsertDirtyCheck !== void 0) {
|
|
13219
|
-
const currentProps = pendingEntry?.props ?? rowPropsToObject(original.props);
|
|
14096
|
+
const currentProps = pendingEntry?.props ?? rowPropsToObject(requireDefined(original).props);
|
|
13220
14097
|
try {
|
|
13221
14098
|
dirty = config.upsertDirtyCheck(
|
|
13222
14099
|
kind,
|
|
@@ -13231,7 +14108,9 @@ function createNodeCollection(config) {
|
|
|
13231
14108
|
const coalesce = dirty?.unchanged === true && deletedAt === void 0 && item.validFrom === void 0 && item.validTo === void 0;
|
|
13232
14109
|
if (coalesce) {
|
|
13233
14110
|
if (pendingEntry === void 0) {
|
|
13234
|
-
results2[itemIndex] = narrowNode(
|
|
14111
|
+
results2[itemIndex] = narrowNode(
|
|
14112
|
+
rowToNode2(requireDefined(original))
|
|
14113
|
+
);
|
|
13235
14114
|
} else {
|
|
13236
14115
|
deferred.push({
|
|
13237
14116
|
index: itemIndex,
|
|
@@ -13257,7 +14136,9 @@ function createNodeCollection(config) {
|
|
|
13257
14136
|
const createInputs = toCreate.map((entry2) => entry2.input);
|
|
13258
14137
|
const created = await executeNodeCreateBatch2(createInputs, target);
|
|
13259
14138
|
for (const [index, entry2] of toCreate.entries()) {
|
|
13260
|
-
results2[entry2.index] = narrowNode(
|
|
14139
|
+
results2[entry2.index] = narrowNode(
|
|
14140
|
+
requireDefined(created[index])
|
|
14141
|
+
);
|
|
13261
14142
|
}
|
|
13262
14143
|
}
|
|
13263
14144
|
for (const entry2 of toUpdate) {
|
|
@@ -13267,7 +14148,7 @@ function createNodeCollection(config) {
|
|
|
13267
14148
|
results2[entry2.index] = narrowNode(result);
|
|
13268
14149
|
}
|
|
13269
14150
|
for (const { index, sourceIndex } of deferred) {
|
|
13270
|
-
results2[index] = results2[sourceIndex];
|
|
14151
|
+
results2[index] = requireDefined(results2[sourceIndex]);
|
|
13271
14152
|
}
|
|
13272
14153
|
return { results: results2, mutations: toCreate.length + toUpdate.length };
|
|
13273
14154
|
};
|
|
@@ -13419,6 +14300,99 @@ function createEdgeCollectionsProxy(graph, graphId, registry, backend, operation
|
|
|
13419
14300
|
});
|
|
13420
14301
|
}
|
|
13421
14302
|
|
|
14303
|
+
// src/store/history-store-backend.ts
|
|
14304
|
+
var HISTORY_STORE_BACKEND_KEYS = [
|
|
14305
|
+
"assertRuntimeContributionsInitialized",
|
|
14306
|
+
"assertVectorSlotInitialized",
|
|
14307
|
+
"assertVectorSlotsInitialized",
|
|
14308
|
+
"bootstrapTables",
|
|
14309
|
+
"capabilities",
|
|
14310
|
+
"checkUnique",
|
|
14311
|
+
"checkUniqueBatch",
|
|
14312
|
+
"claimIndexMaterialization",
|
|
14313
|
+
"close",
|
|
14314
|
+
"commitSchemaVersion",
|
|
14315
|
+
"compileSql",
|
|
14316
|
+
"countEdgesByKind",
|
|
14317
|
+
"countEdgesFrom",
|
|
14318
|
+
"countNodesByKind",
|
|
14319
|
+
"createVectorIndex",
|
|
14320
|
+
"deleteEdge",
|
|
14321
|
+
"deleteEdgesBatch",
|
|
14322
|
+
"deleteEmbedding",
|
|
14323
|
+
"deleteFulltext",
|
|
14324
|
+
"deleteFulltextBatch",
|
|
14325
|
+
"deleteNode",
|
|
14326
|
+
"deleteUnique",
|
|
14327
|
+
"deleteVectorSlotContribution",
|
|
14328
|
+
"dialect",
|
|
14329
|
+
"dropVectorIndex",
|
|
14330
|
+
"edgeExistsBetween",
|
|
14331
|
+
"ensureContributionMaterializationsTable",
|
|
14332
|
+
"ensureFulltextTable",
|
|
14333
|
+
"ensureIndexMaterializationsTable",
|
|
14334
|
+
"ensureKindRemovalsTable",
|
|
14335
|
+
"ensureReconciliationMarkersTable",
|
|
14336
|
+
"ensureRevisionOriginsTable",
|
|
14337
|
+
"ensureRuntimeContributions",
|
|
14338
|
+
"ensureVectorSlotContribution",
|
|
14339
|
+
"ensureVectorSlotContributions",
|
|
14340
|
+
"execute",
|
|
14341
|
+
"executeTemporaryStatement",
|
|
14342
|
+
"findEdgesByKind",
|
|
14343
|
+
"findEdgesConnectedTo",
|
|
14344
|
+
"findNodesByKind",
|
|
14345
|
+
"fulltextSearch",
|
|
14346
|
+
"fulltextStrategy",
|
|
14347
|
+
"getActiveSchema",
|
|
14348
|
+
"getAllKindRemovals",
|
|
14349
|
+
"getContributionMaterialization",
|
|
14350
|
+
"getEdge",
|
|
14351
|
+
"getEdges",
|
|
14352
|
+
"getIndexMaterialization",
|
|
14353
|
+
"getIndexMaterializations",
|
|
14354
|
+
"getNode",
|
|
14355
|
+
"getNodes",
|
|
14356
|
+
"getPendingKindRemovals",
|
|
14357
|
+
"getReconciliationMarker",
|
|
14358
|
+
"getSchemaVersion",
|
|
14359
|
+
"hardDeleteEdge",
|
|
14360
|
+
"hardDeleteEdgesBatch",
|
|
14361
|
+
"hardDeleteNode",
|
|
14362
|
+
"hybridSearch",
|
|
14363
|
+
"insertEdge",
|
|
14364
|
+
"insertEdgeNoReturn",
|
|
14365
|
+
"insertEdgesBatch",
|
|
14366
|
+
"insertEdgesBatchReturning",
|
|
14367
|
+
"insertNode",
|
|
14368
|
+
"insertNodeNoReturn",
|
|
14369
|
+
"insertNodesBatch",
|
|
14370
|
+
"insertNodesBatchReturning",
|
|
14371
|
+
"insertUnique",
|
|
14372
|
+
"insertUniqueBatch",
|
|
14373
|
+
"recordContributionMaterialization",
|
|
14374
|
+
"recordIndexMaterialization",
|
|
14375
|
+
"recordKindRemoval",
|
|
14376
|
+
"refreshStatistics",
|
|
14377
|
+
"releaseIndexMaterializationClaim",
|
|
14378
|
+
"setActiveVersion",
|
|
14379
|
+
"setReconciliationMarker",
|
|
14380
|
+
"tableNames",
|
|
14381
|
+
"updateEdge",
|
|
14382
|
+
"updateNode",
|
|
14383
|
+
"upsertEmbedding",
|
|
14384
|
+
"upsertEmbeddingBatch",
|
|
14385
|
+
"upsertFulltext",
|
|
14386
|
+
"upsertFulltextBatch",
|
|
14387
|
+
"vectorSearch",
|
|
14388
|
+
"vectorStrategy"
|
|
14389
|
+
];
|
|
14390
|
+
function createHistoryStoreBackendProjection(backend) {
|
|
14391
|
+
return Object.freeze(
|
|
14392
|
+
projectBackendMembers(backend, HISTORY_STORE_BACKEND_KEYS)
|
|
14393
|
+
);
|
|
14394
|
+
}
|
|
14395
|
+
|
|
13422
14396
|
// src/store/introspect.ts
|
|
13423
14397
|
function introspectSchema(graph, context) {
|
|
13424
14398
|
const extension = graph.extension;
|
|
@@ -13530,6 +14504,18 @@ async function runMaterialization(items, options, runOne) {
|
|
|
13530
14504
|
var CLAIM_LEASE_MS = 15 * 6e4;
|
|
13531
14505
|
var CLAIM_RETRY_DELAY_MS = 200;
|
|
13532
14506
|
var CLAIM_WAIT_TIMEOUT_MS = CLAIM_LEASE_MS + 6e4;
|
|
14507
|
+
var INDEX_DIALECT_BEHAVIOR = {
|
|
14508
|
+
postgres: {
|
|
14509
|
+
concurrentBuilds: true,
|
|
14510
|
+
hasInvalidIndexState: true,
|
|
14511
|
+
supportsGinFamily: true
|
|
14512
|
+
},
|
|
14513
|
+
sqlite: {
|
|
14514
|
+
concurrentBuilds: false,
|
|
14515
|
+
hasInvalidIndexState: false,
|
|
14516
|
+
supportsGinFamily: false
|
|
14517
|
+
}
|
|
14518
|
+
};
|
|
13533
14519
|
function hasIndexBuildClaimProtocol(backend) {
|
|
13534
14520
|
return backend.claimIndexMaterialization !== void 0 && backend.releaseIndexMaterializationClaim !== void 0;
|
|
13535
14521
|
}
|
|
@@ -13574,7 +14560,7 @@ async function materializeIndexes(context, options = {}) {
|
|
|
13574
14560
|
const tableNames = backend.tableNames;
|
|
13575
14561
|
const ddlOptions = {
|
|
13576
14562
|
ifNotExists: true,
|
|
13577
|
-
concurrent: dialect
|
|
14563
|
+
concurrent: INDEX_DIALECT_BEHAVIOR[dialect].concurrentBuilds,
|
|
13578
14564
|
...tableNames?.nodes === void 0 ? {} : { nodesTableName: tableNames.nodes },
|
|
13579
14565
|
...tableNames?.edges === void 0 ? {} : { edgesTableName: tableNames.edges }
|
|
13580
14566
|
};
|
|
@@ -13655,7 +14641,7 @@ function parallelBucketKey(declaration) {
|
|
|
13655
14641
|
return declaration.entity;
|
|
13656
14642
|
}
|
|
13657
14643
|
async function materializeRelationalIndex(declaration, backend, dialect, ddlOptions, graphId, schemaVersion, existingByStatusKey, invalidLeftovers) {
|
|
13658
|
-
if (declaration.method !== void 0 && dialect
|
|
14644
|
+
if (declaration.method !== void 0 && !INDEX_DIALECT_BEHAVIOR[dialect].supportsGinFamily) {
|
|
13659
14645
|
return {
|
|
13660
14646
|
indexName: declaration.name,
|
|
13661
14647
|
entity: declaration.entity,
|
|
@@ -13677,9 +14663,11 @@ async function materializeRelationalIndex(declaration, backend, dialect, ddlOpti
|
|
|
13677
14663
|
driftLabel: "Index",
|
|
13678
14664
|
run: async () => {
|
|
13679
14665
|
if (declaration.method === "trigram") {
|
|
13680
|
-
await backend.executeDdl(
|
|
14666
|
+
await requireDefined(backend.executeDdl)(
|
|
14667
|
+
"CREATE EXTENSION IF NOT EXISTS pg_trgm;"
|
|
14668
|
+
);
|
|
13681
14669
|
}
|
|
13682
|
-
await backend.executeDdl(ddl);
|
|
14670
|
+
await requireDefined(backend.executeDdl)(ddl);
|
|
13683
14671
|
},
|
|
13684
14672
|
existingByStatusKey,
|
|
13685
14673
|
physicalRebuildPreload: invalidLeftovers
|
|
@@ -13727,7 +14715,7 @@ async function materializeVectorIndex(declaration, backend, graphId, schemaVersi
|
|
|
13727
14715
|
efConstruction: declaration.indexParams.efConstruction,
|
|
13728
14716
|
...declaration.indexParams.lists === void 0 ? {} : { lists: declaration.indexParams.lists }
|
|
13729
14717
|
},
|
|
13730
|
-
concurrent: backend.dialect
|
|
14718
|
+
concurrent: INDEX_DIALECT_BEHAVIOR[backend.dialect].concurrentBuilds
|
|
13731
14719
|
};
|
|
13732
14720
|
return materializeOne(declaration, backend, graphId, schemaVersion, {
|
|
13733
14721
|
// Compound status-table key for vector entries. Pgvector creates
|
|
@@ -13738,13 +14726,15 @@ async function materializeVectorIndex(declaration, backend, graphId, schemaVersi
|
|
|
13738
14726
|
statusKey: vectorStatusKey(graphId, declaration.name),
|
|
13739
14727
|
signature,
|
|
13740
14728
|
driftLabel: "Vector index",
|
|
13741
|
-
run: () => backend.createVectorIndex(params),
|
|
14729
|
+
run: () => requireDefined(backend.createVectorIndex)(params),
|
|
13742
14730
|
existingByStatusKey,
|
|
13743
14731
|
physicalRebuildPreload: invalidLeftovers
|
|
13744
14732
|
});
|
|
13745
14733
|
}
|
|
13746
14734
|
async function materializeOne(declaration, backend, graphId, schemaVersion, action) {
|
|
13747
|
-
const recordIndexMaterialization =
|
|
14735
|
+
const recordIndexMaterialization = requireDefined(
|
|
14736
|
+
backend.recordIndexMaterialization
|
|
14737
|
+
);
|
|
13748
14738
|
const { statusKey, signature, driftLabel, run, existingByStatusKey } = action;
|
|
13749
14739
|
const statusOverride = statusKey === declaration.name ? void 0 : { statusName: statusKey };
|
|
13750
14740
|
const settled = await settleAgainstExisting(
|
|
@@ -13816,7 +14806,7 @@ async function settleAgainstExisting(existing, declaration, backend, graphId, sc
|
|
|
13816
14806
|
const error = new Error(
|
|
13817
14807
|
`${driftLabel} "${declaration.name}" already materialized with a different signature (recorded by graph "${existing.graphId}" at version ${existing.schemaVersion}). Drop the index manually and retry, or rename the new declaration.`
|
|
13818
14808
|
);
|
|
13819
|
-
await backend.recordIndexMaterialization(
|
|
14809
|
+
await requireDefined(backend.recordIndexMaterialization)(
|
|
13820
14810
|
buildAttempt({
|
|
13821
14811
|
declaration,
|
|
13822
14812
|
graphId,
|
|
@@ -13832,11 +14822,13 @@ async function settleAgainstExisting(existing, declaration, backend, graphId, sc
|
|
|
13832
14822
|
async function materializeWithClaim(declaration, backend, graphId, schemaVersion, action) {
|
|
13833
14823
|
const { statusKey, signature, driftLabel, run } = action;
|
|
13834
14824
|
const statusOverride = statusKey === declaration.name ? void 0 : { statusName: statusKey };
|
|
13835
|
-
const recordIndexMaterialization =
|
|
14825
|
+
const recordIndexMaterialization = requireDefined(
|
|
14826
|
+
backend.recordIndexMaterialization
|
|
14827
|
+
);
|
|
13836
14828
|
const token = `${statusKey}:${nowIso()}:${Math.floor(performance.now() * 1e3)}`;
|
|
13837
14829
|
const deadline = Date.now() + CLAIM_WAIT_TIMEOUT_MS;
|
|
13838
14830
|
for (; ; ) {
|
|
13839
|
-
const claimed = await backend.claimIndexMaterialization({
|
|
14831
|
+
const claimed = await requireDefined(backend.claimIndexMaterialization)({
|
|
13840
14832
|
indexName: statusKey,
|
|
13841
14833
|
graphId,
|
|
13842
14834
|
entity: declaration.entity,
|
|
@@ -13860,7 +14852,9 @@ async function materializeWithClaim(declaration, backend, graphId, schemaVersion
|
|
|
13860
14852
|
continue;
|
|
13861
14853
|
}
|
|
13862
14854
|
try {
|
|
13863
|
-
const fresh = await backend.getIndexMaterialization(
|
|
14855
|
+
const fresh = await requireDefined(backend.getIndexMaterialization)(
|
|
14856
|
+
statusKey
|
|
14857
|
+
);
|
|
13864
14858
|
const settled = await settleAgainstExisting(
|
|
13865
14859
|
fresh,
|
|
13866
14860
|
declaration,
|
|
@@ -13914,7 +14908,7 @@ async function materializeWithClaim(declaration, backend, graphId, schemaVersion
|
|
|
13914
14908
|
}
|
|
13915
14909
|
} finally {
|
|
13916
14910
|
try {
|
|
13917
|
-
await backend.releaseIndexMaterializationClaim({
|
|
14911
|
+
await requireDefined(backend.releaseIndexMaterializationClaim)({
|
|
13918
14912
|
indexName: statusKey,
|
|
13919
14913
|
token
|
|
13920
14914
|
});
|
|
@@ -13928,7 +14922,9 @@ async function materializeWithClaim(declaration, backend, graphId, schemaVersion
|
|
|
13928
14922
|
}
|
|
13929
14923
|
}
|
|
13930
14924
|
async function hasInvalidIndexLeftover(backend, physicalIndexName) {
|
|
13931
|
-
if (backend.dialect
|
|
14925
|
+
if (!INDEX_DIALECT_BEHAVIOR[backend.dialect].hasInvalidIndexState) {
|
|
14926
|
+
return false;
|
|
14927
|
+
}
|
|
13932
14928
|
const rows = await backend.execute(
|
|
13933
14929
|
asCompiledRowsSql(sql`
|
|
13934
14930
|
SELECT NOT i.indisvalid AS invalid
|
|
@@ -13941,7 +14937,7 @@ async function hasInvalidIndexLeftover(backend, physicalIndexName) {
|
|
|
13941
14937
|
return rows[0]?.invalid === true;
|
|
13942
14938
|
}
|
|
13943
14939
|
async function preloadInvalidIndexLeftovers(backend, physicalIndexNames) {
|
|
13944
|
-
if (backend.dialect
|
|
14940
|
+
if (!INDEX_DIALECT_BEHAVIOR[backend.dialect].hasInvalidIndexState || physicalIndexNames.length === 0) {
|
|
13945
14941
|
return /* @__PURE__ */ new Set();
|
|
13946
14942
|
}
|
|
13947
14943
|
const { invalid } = await preloadPhysicalIndexStates(
|
|
@@ -13952,55 +14948,69 @@ async function preloadInvalidIndexLeftovers(backend, physicalIndexNames) {
|
|
|
13952
14948
|
}
|
|
13953
14949
|
async function preloadExistingTables(backend, tableNames) {
|
|
13954
14950
|
if (tableNames.length === 0) return /* @__PURE__ */ new Set();
|
|
13955
|
-
|
|
13956
|
-
|
|
13957
|
-
|
|
13958
|
-
|
|
13959
|
-
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
14951
|
+
switch (backend.dialect) {
|
|
14952
|
+
case "postgres": {
|
|
14953
|
+
const rows = await backend.execute(
|
|
14954
|
+
asCompiledRowsSql(sql`
|
|
14955
|
+
SELECT c.relname AS name
|
|
14956
|
+
FROM pg_class c
|
|
14957
|
+
WHERE c.relname IN (${sqlValueList(tableNames)})
|
|
14958
|
+
AND c.relkind IN ('r', 'p')
|
|
14959
|
+
AND pg_catalog.pg_table_is_visible(c.oid)
|
|
14960
|
+
`)
|
|
14961
|
+
);
|
|
14962
|
+
return new Set(rows.map((row) => row.name));
|
|
14963
|
+
}
|
|
14964
|
+
case "sqlite": {
|
|
14965
|
+
const rows = await backend.execute(
|
|
14966
|
+
asCompiledRowsSql(sql`
|
|
14967
|
+
SELECT name
|
|
14968
|
+
FROM sqlite_master
|
|
14969
|
+
WHERE type = 'table'
|
|
14970
|
+
AND name IN (${sqlValueList(tableNames)})
|
|
14971
|
+
`)
|
|
14972
|
+
);
|
|
14973
|
+
return new Set(rows.map((row) => row.name));
|
|
14974
|
+
}
|
|
14975
|
+
default: {
|
|
14976
|
+
return backend.dialect;
|
|
14977
|
+
}
|
|
13966
14978
|
}
|
|
13967
|
-
const rows = await backend.execute(
|
|
13968
|
-
asCompiledRowsSql(sql`
|
|
13969
|
-
SELECT name
|
|
13970
|
-
FROM sqlite_master
|
|
13971
|
-
WHERE type = 'table'
|
|
13972
|
-
AND name IN (${sqlValueList(tableNames)})
|
|
13973
|
-
`)
|
|
13974
|
-
);
|
|
13975
|
-
return new Set(rows.map((row) => row.name));
|
|
13976
14979
|
}
|
|
13977
14980
|
async function preloadPhysicalIndexStates(backend, physicalIndexNames) {
|
|
13978
14981
|
const valid = /* @__PURE__ */ new Set();
|
|
13979
14982
|
const invalid = /* @__PURE__ */ new Set();
|
|
13980
14983
|
if (physicalIndexNames.length === 0) return { valid, invalid };
|
|
13981
|
-
|
|
13982
|
-
|
|
13983
|
-
|
|
13984
|
-
|
|
13985
|
-
|
|
13986
|
-
|
|
13987
|
-
|
|
13988
|
-
|
|
13989
|
-
|
|
13990
|
-
|
|
13991
|
-
|
|
13992
|
-
|
|
14984
|
+
switch (backend.dialect) {
|
|
14985
|
+
case "postgres": {
|
|
14986
|
+
const rows = await backend.execute(
|
|
14987
|
+
asCompiledRowsSql(sql`
|
|
14988
|
+
SELECT c.relname AS name, i.indisvalid AS valid
|
|
14989
|
+
FROM pg_class c
|
|
14990
|
+
JOIN pg_index i ON i.indexrelid = c.oid
|
|
14991
|
+
WHERE c.relname IN (${sqlValueList(physicalIndexNames)})
|
|
14992
|
+
AND pg_catalog.pg_table_is_visible(c.oid)
|
|
14993
|
+
`)
|
|
14994
|
+
);
|
|
14995
|
+
for (const row of rows) (row.valid ? valid : invalid).add(row.name);
|
|
14996
|
+
return { valid, invalid };
|
|
14997
|
+
}
|
|
14998
|
+
case "sqlite": {
|
|
14999
|
+
const rows = await backend.execute(
|
|
15000
|
+
asCompiledRowsSql(sql`
|
|
15001
|
+
SELECT name
|
|
15002
|
+
FROM sqlite_master
|
|
15003
|
+
WHERE type = 'index'
|
|
15004
|
+
AND name IN (${sqlValueList(physicalIndexNames)})
|
|
15005
|
+
`)
|
|
15006
|
+
);
|
|
15007
|
+
for (const row of rows) valid.add(row.name);
|
|
15008
|
+
return { valid, invalid };
|
|
15009
|
+
}
|
|
15010
|
+
default: {
|
|
15011
|
+
return backend.dialect;
|
|
15012
|
+
}
|
|
13993
15013
|
}
|
|
13994
|
-
const rows = await backend.execute(
|
|
13995
|
-
asCompiledRowsSql(sql`
|
|
13996
|
-
SELECT name
|
|
13997
|
-
FROM sqlite_master
|
|
13998
|
-
WHERE type = 'index'
|
|
13999
|
-
AND name IN (${sqlValueList(physicalIndexNames)})
|
|
14000
|
-
`)
|
|
14001
|
-
);
|
|
14002
|
-
for (const row of rows) valid.add(row.name);
|
|
14003
|
-
return { valid, invalid };
|
|
14004
15014
|
}
|
|
14005
15015
|
async function dropInvalidIndexLeftover(backend, physicalIndexName) {
|
|
14006
15016
|
if (backend.executeDdl === void 0) return;
|
|
@@ -14040,10 +15050,10 @@ async function preloadMaterializations(backend, statusKeys) {
|
|
|
14040
15050
|
for (const row of rows2) map.set(row.indexName, row);
|
|
14041
15051
|
return map;
|
|
14042
15052
|
}
|
|
14043
|
-
const getOne = backend.getIndexMaterialization;
|
|
15053
|
+
const getOne = requireDefined(backend.getIndexMaterialization);
|
|
14044
15054
|
const rows = await Promise.all(statusKeys.map((key) => getOne(key)));
|
|
14045
15055
|
for (const [index, row] of rows.entries()) {
|
|
14046
|
-
if (row !== void 0) map.set(statusKeys[index], row);
|
|
15056
|
+
if (row !== void 0) map.set(requireDefined(statusKeys[index]), row);
|
|
14047
15057
|
}
|
|
14048
15058
|
return map;
|
|
14049
15059
|
}
|
|
@@ -14080,7 +15090,7 @@ async function materializeSystemIndexes(context, options = {}) {
|
|
|
14080
15090
|
backend,
|
|
14081
15091
|
backend.ensureIndexMaterializationsTable
|
|
14082
15092
|
);
|
|
14083
|
-
const concurrent = backend.dialect
|
|
15093
|
+
const concurrent = INDEX_DIALECT_BEHAVIOR[backend.dialect].concurrentBuilds;
|
|
14084
15094
|
const candidates = SYSTEM_INDEX_DECLARATIONS.map((declaration) => {
|
|
14085
15095
|
const physicalTable = resolveSystemIndexTableName(
|
|
14086
15096
|
declaration.table,
|
|
@@ -14147,7 +15157,7 @@ async function materializeSystemIndexes(context, options = {}) {
|
|
|
14147
15157
|
statusKey: candidate.name,
|
|
14148
15158
|
signature,
|
|
14149
15159
|
driftLabel: "System index",
|
|
14150
|
-
run: () => backend.executeDdl(ddl),
|
|
15160
|
+
run: () => requireDefined(backend.executeDdl)(ddl),
|
|
14151
15161
|
existingByStatusKey,
|
|
14152
15162
|
physicalRebuildPreload,
|
|
14153
15163
|
freshNeedsPhysicalRebuild: async (physicalIndexName) => {
|
|
@@ -14184,6 +15194,8 @@ async function computeIndexSignature(dialect, targetTableName, declaration) {
|
|
|
14184
15194
|
const json = JSON.stringify(hashable, sortedReplacer);
|
|
14185
15195
|
return sha256Hex(json, 16);
|
|
14186
15196
|
}
|
|
15197
|
+
|
|
15198
|
+
// src/store/materialize-removals.ts
|
|
14187
15199
|
var ENTITY_KINDS = ["node", "edge"];
|
|
14188
15200
|
function buildPendingKindRemoval(args) {
|
|
14189
15201
|
return { ...args, removedAt: void 0, error: void 0 };
|
|
@@ -14241,7 +15253,7 @@ async function reconcilePendingRemovals(context) {
|
|
|
14241
15253
|
}
|
|
14242
15254
|
const marker = backend.getReconciliationMarker === void 0 ? void 0 : await backend.getReconciliationMarker(graphId);
|
|
14243
15255
|
if (marker !== void 0 && marker >= activeRow.version) return;
|
|
14244
|
-
const allRemovals = await (backend.getAllKindRemovals === void 0 ? backend.getPendingKindRemovals(graphId) : backend.getAllKindRemovals(graphId));
|
|
15256
|
+
const allRemovals = await (backend.getAllKindRemovals === void 0 ? requireDefined(backend.getPendingKindRemovals)(graphId) : backend.getAllKindRemovals(graphId));
|
|
14245
15257
|
const recorded = new Set(
|
|
14246
15258
|
allRemovals.map(
|
|
14247
15259
|
(row) => kindRemovalKey(row.entity, row.kindName, row.schemaVersion)
|
|
@@ -14300,7 +15312,7 @@ function kindRemovalKey(entity, kindName, version) {
|
|
|
14300
15312
|
return `${entity}|${kindName}|${version}`;
|
|
14301
15313
|
}
|
|
14302
15314
|
async function materializeOne2(row, ctx) {
|
|
14303
|
-
const recordKindRemoval = ctx.backend.recordKindRemoval;
|
|
15315
|
+
const recordKindRemoval = requireDefined(ctx.backend.recordKindRemoval);
|
|
14304
15316
|
try {
|
|
14305
15317
|
await closeRecordedAndDeleteLiveRows(ctx, row);
|
|
14306
15318
|
await Promise.all(buildEmbeddingTableCleanup(ctx, row));
|
|
@@ -14380,7 +15392,9 @@ async function executeDeleteStatements(target, statements) {
|
|
|
14380
15392
|
if (target.executeStatement !== void 0) {
|
|
14381
15393
|
await Promise.all(
|
|
14382
15394
|
statements.map(
|
|
14383
|
-
(statement) => target.executeStatement(
|
|
15395
|
+
(statement) => requireDefined(target.executeStatement)(
|
|
15396
|
+
asCompiledStatementSql(sql.raw(statement))
|
|
15397
|
+
)
|
|
14384
15398
|
)
|
|
14385
15399
|
);
|
|
14386
15400
|
return;
|
|
@@ -14392,13 +15406,13 @@ async function executeDeleteStatements(target, statements) {
|
|
|
14392
15406
|
);
|
|
14393
15407
|
}
|
|
14394
15408
|
await Promise.all(
|
|
14395
|
-
statements.map((statement) => target.executeDdl(statement))
|
|
15409
|
+
statements.map((statement) => requireDefined(target.executeDdl)(statement))
|
|
14396
15410
|
);
|
|
14397
15411
|
}
|
|
14398
15412
|
function buildEmbeddingTableCleanup(ctx, row) {
|
|
14399
15413
|
const vectorStrategy = ctx.backend.vectorStrategy;
|
|
14400
15414
|
if (vectorStrategy === void 0) return [];
|
|
14401
|
-
const executeDdl = ctx.backend.executeDdl;
|
|
15415
|
+
const executeDdl = requireDefined(ctx.backend.executeDdl);
|
|
14402
15416
|
const cleanup = (async () => {
|
|
14403
15417
|
const slots = await resolveRemovedKindEmbeddingSlots(ctx.backend, row);
|
|
14404
15418
|
await Promise.all(
|
|
@@ -15032,7 +16046,7 @@ async function executeEdgeFindByEndpoints(ctx, kind, fromKind, fromId, toKind, t
|
|
|
15032
16046
|
...options?.asOf !== void 0 && { asOf: options.asOf }
|
|
15033
16047
|
});
|
|
15034
16048
|
if (candidateRows.length === 0) return void 0;
|
|
15035
|
-
if (matchOn.length === 0) return rowToEdge(candidateRows[0]);
|
|
16049
|
+
if (matchOn.length === 0) return rowToEdge(requireDefined(candidateRows[0]));
|
|
15036
16050
|
const { liveRow } = findMatchingEdge(candidateRows, matchOn, props);
|
|
15037
16051
|
return liveRow === void 0 ? void 0 : rowToEdge(liveRow);
|
|
15038
16052
|
}
|
|
@@ -15265,7 +16279,10 @@ async function executeEdgeBulkGetOrCreateByEndpoints(ctx, kind, items, backend,
|
|
|
15265
16279
|
found[entry2.index] = { edge: rowToEdge(entry2.row), action: "found" };
|
|
15266
16280
|
}
|
|
15267
16281
|
for (const { index, sourceIndex } of probe.duplicateOf) {
|
|
15268
|
-
found[index] = {
|
|
16282
|
+
found[index] = {
|
|
16283
|
+
edge: requireDefined(found[sourceIndex]).edge,
|
|
16284
|
+
action: "found"
|
|
16285
|
+
};
|
|
15269
16286
|
}
|
|
15270
16287
|
return found;
|
|
15271
16288
|
}
|
|
@@ -15284,7 +16301,7 @@ async function executeEdgeBulkGetOrCreateByEndpoints(ctx, kind, items, backend,
|
|
|
15284
16301
|
);
|
|
15285
16302
|
for (const [batchIndex, entry2] of toCreate.entries()) {
|
|
15286
16303
|
results[entry2.index] = {
|
|
15287
|
-
edge: createdEdges[batchIndex],
|
|
16304
|
+
edge: requireDefined(createdEdges[batchIndex]),
|
|
15288
16305
|
action: "created"
|
|
15289
16306
|
};
|
|
15290
16307
|
}
|
|
@@ -15326,12 +16343,14 @@ async function executeEdgeBulkGetOrCreateByEndpoints(ctx, kind, items, backend,
|
|
|
15326
16343
|
}
|
|
15327
16344
|
}
|
|
15328
16345
|
for (const { index, sourceIndex } of duplicateOf) {
|
|
15329
|
-
const sourceResult = results[sourceIndex];
|
|
16346
|
+
const sourceResult = requireDefined(results[sourceIndex]);
|
|
15330
16347
|
results[index] = { edge: sourceResult.edge, action: "found" };
|
|
15331
16348
|
}
|
|
15332
16349
|
return results;
|
|
15333
16350
|
});
|
|
15334
16351
|
}
|
|
16352
|
+
|
|
16353
|
+
// src/store/recorded-read-service.ts
|
|
15335
16354
|
var RECORDED_POINT_READ_FIXED_BIND_PARAMS = 8;
|
|
15336
16355
|
function recordedPointReadIdChunk(backend) {
|
|
15337
16356
|
const budget = recordedBindParamBudget(backend);
|
|
@@ -15347,12 +16366,13 @@ function withRelationsPrecondition(backend, promise, surface) {
|
|
|
15347
16366
|
);
|
|
15348
16367
|
}
|
|
15349
16368
|
function createRecordedReadBackend(backend, surface) {
|
|
15350
|
-
|
|
16369
|
+
const projectedBackend = createGraphBackendProjection(backend);
|
|
16370
|
+
return createBackendOverlay(projectedBackend, {
|
|
15351
16371
|
execute: (query) => withRelationsPrecondition(backend, backend.execute(query), surface),
|
|
15352
16372
|
...backend.executeRaw === void 0 ? {} : {
|
|
15353
16373
|
executeRaw: (sqlText, params) => withRelationsPrecondition(
|
|
15354
16374
|
backend,
|
|
15355
|
-
backend.executeRaw(sqlText, params),
|
|
16375
|
+
requireDefined(backend.executeRaw)(sqlText, params),
|
|
15356
16376
|
surface
|
|
15357
16377
|
)
|
|
15358
16378
|
}
|
|
@@ -15660,9 +16680,6 @@ function wrapTransactionCollections(nodes, edges, recorder) {
|
|
|
15660
16680
|
};
|
|
15661
16681
|
}
|
|
15662
16682
|
|
|
15663
|
-
// src/store/types.ts
|
|
15664
|
-
var AUTO_REFRESH_STATISTICS_ROW_THRESHOLD = 1e3;
|
|
15665
|
-
|
|
15666
16683
|
// src/store/store.ts
|
|
15667
16684
|
var UNKNOWN_SCHEMA_METADATA = Object.freeze({
|
|
15668
16685
|
schemaVersion: void 0,
|
|
@@ -15689,8 +16706,12 @@ var CAUGHT_UP_VERB_DETAILS = {
|
|
|
15689
16706
|
code: "REEMBED_BEFORE_INITIALIZE"
|
|
15690
16707
|
}
|
|
15691
16708
|
};
|
|
16709
|
+
var ROW_MAPPER_CONFIGS = {
|
|
16710
|
+
postgres: POSTGRES_ROW_MAPPER_CONFIG,
|
|
16711
|
+
sqlite: SQLITE_ROW_MAPPER_CONFIG
|
|
16712
|
+
};
|
|
15692
16713
|
function rowMapperConfigFor(backend) {
|
|
15693
|
-
return backend.dialect
|
|
16714
|
+
return ROW_MAPPER_CONFIGS[backend.dialect];
|
|
15694
16715
|
}
|
|
15695
16716
|
function asError(error) {
|
|
15696
16717
|
return error instanceof Error ? error : new Error(String(error));
|
|
@@ -15705,7 +16726,18 @@ function transactionOutcome(result, recorder, recordedByGraph, graphId) {
|
|
|
15705
16726
|
)
|
|
15706
16727
|
};
|
|
15707
16728
|
}
|
|
15708
|
-
|
|
16729
|
+
function overlayPropertyDescriptors(base, overlay) {
|
|
16730
|
+
return Object.defineProperties(Object.create(Reflect.getPrototypeOf(base)), {
|
|
16731
|
+
...Object.getOwnPropertyDescriptors(base),
|
|
16732
|
+
...Object.getOwnPropertyDescriptors(overlay)
|
|
16733
|
+
});
|
|
16734
|
+
}
|
|
16735
|
+
function syncStoreReplacementRef(ref, replacement) {
|
|
16736
|
+
if (ref === void 0) return;
|
|
16737
|
+
ref.current = replacement;
|
|
16738
|
+
}
|
|
16739
|
+
var StoreImplementation = class _StoreImplementation {
|
|
16740
|
+
[STORE_RUNTIME];
|
|
15709
16741
|
#graph;
|
|
15710
16742
|
/**
|
|
15711
16743
|
* Bare backend for DDL, vector-storage, and bulk-materialization work that must
|
|
@@ -15713,6 +16745,7 @@ var Store = class _Store {
|
|
|
15713
16745
|
*/
|
|
15714
16746
|
#baseBackend;
|
|
15715
16747
|
#backend;
|
|
16748
|
+
#adapterBackend;
|
|
15716
16749
|
#captureEnabled;
|
|
15717
16750
|
#revisionTrackingEnabled;
|
|
15718
16751
|
#revisionOrigin;
|
|
@@ -15732,9 +16765,10 @@ var Store = class _Store {
|
|
|
15732
16765
|
#edgeCollections;
|
|
15733
16766
|
#algorithms;
|
|
15734
16767
|
#search;
|
|
15735
|
-
constructor(graph, backend, options, schemaMetadata) {
|
|
16768
|
+
constructor(graph, backend, options, schemaMetadata, adapterBackend) {
|
|
15736
16769
|
this.#graph = graph;
|
|
15737
16770
|
this.#baseBackend = asRawBackend(backend);
|
|
16771
|
+
this.#adapterBackend = adapterBackend;
|
|
15738
16772
|
this.#captureEnabled = options?.history === true;
|
|
15739
16773
|
this.#revisionTrackingEnabled = this.#captureEnabled || options?.revisionTracking === true;
|
|
15740
16774
|
if (this.#revisionTrackingEnabled) {
|
|
@@ -15771,6 +16805,21 @@ var Store = class _Store {
|
|
|
15771
16805
|
this.#defaultTraversalExpansion = options?.queryDefaults?.traversalExpansion ?? "inverse";
|
|
15772
16806
|
this.#options = options;
|
|
15773
16807
|
this.#schemaMetadata = schemaMetadata ?? UNKNOWN_SCHEMA_METADATA;
|
|
16808
|
+
this[STORE_RUNTIME] = {
|
|
16809
|
+
backend: this.#backend,
|
|
16810
|
+
sealedQuery: (coordinate) => this.sealedQuery(coordinate),
|
|
16811
|
+
recordedNodeGetById: (kind, id, coordinate) => this.recordedNodeGetById(kind, id, coordinate),
|
|
16812
|
+
recordedNodeGetByIds: (kind, ids, coordinate) => this.recordedNodeGetByIds(kind, ids, coordinate),
|
|
16813
|
+
recordedEdgeGetById: (kind, id, coordinate) => this.recordedEdgeGetById(kind, id, coordinate),
|
|
16814
|
+
recordedEdgeGetByIds: (kind, ids, coordinate) => this.recordedEdgeGetByIds(kind, ids, coordinate),
|
|
16815
|
+
subgraphAtCoordinate: (rootId, subgraphOptions) => this.subgraphAtCoordinate(rootId, subgraphOptions),
|
|
16816
|
+
algorithmsAtCoordinate: (coordinate) => this.algorithmsAtCoordinate(coordinate)
|
|
16817
|
+
};
|
|
16818
|
+
Object.defineProperty(this, STORE_RUNTIME, {
|
|
16819
|
+
configurable: false,
|
|
16820
|
+
enumerable: false,
|
|
16821
|
+
writable: false
|
|
16822
|
+
});
|
|
15774
16823
|
}
|
|
15775
16824
|
// === Accessors ===
|
|
15776
16825
|
/** The graph definition */
|
|
@@ -15781,14 +16830,14 @@ var Store = class _Store {
|
|
|
15781
16830
|
get graphId() {
|
|
15782
16831
|
return this.#graph.id;
|
|
15783
16832
|
}
|
|
16833
|
+
/** Runtime features available through this store's configured backend. */
|
|
16834
|
+
get capabilities() {
|
|
16835
|
+
return this.#baseBackend.capabilities;
|
|
16836
|
+
}
|
|
15784
16837
|
/** The kind registry for ontology lookups */
|
|
15785
16838
|
get registry() {
|
|
15786
16839
|
return this.#registry;
|
|
15787
16840
|
}
|
|
15788
|
-
/** The database backend */
|
|
15789
|
-
get backend() {
|
|
15790
|
-
return this.#backend;
|
|
15791
|
-
}
|
|
15792
16841
|
/**
|
|
15793
16842
|
* Whether recorded-time capture is enabled for this store.
|
|
15794
16843
|
*
|
|
@@ -15993,7 +17042,7 @@ var Store = class _Store {
|
|
|
15993
17042
|
*/
|
|
15994
17043
|
getNodePropsSchema(kind) {
|
|
15995
17044
|
if (!Object.hasOwn(this.#graph.nodes, kind)) return void 0;
|
|
15996
|
-
return this.#graph.nodes[kind].type.schema;
|
|
17045
|
+
return requireDefined(this.#graph.nodes[kind]).type.schema;
|
|
15997
17046
|
}
|
|
15998
17047
|
/**
|
|
15999
17048
|
* Returns the Zod props schema for the given node kind. Throws
|
|
@@ -16014,7 +17063,7 @@ var Store = class _Store {
|
|
|
16014
17063
|
*/
|
|
16015
17064
|
getEdgePropsSchema(kind) {
|
|
16016
17065
|
if (!Object.hasOwn(this.#graph.edges, kind)) return void 0;
|
|
16017
|
-
return this.#graph.edges[kind].type.schema;
|
|
17066
|
+
return requireDefined(this.#graph.edges[kind]).type.schema;
|
|
16018
17067
|
}
|
|
16019
17068
|
/**
|
|
16020
17069
|
* Returns the Zod props schema for the given edge kind. Throws
|
|
@@ -16628,15 +17677,21 @@ var Store = class _Store {
|
|
|
16628
17677
|
edges,
|
|
16629
17678
|
// No real transaction: `tx.sql` is absent and there is no atomicity.
|
|
16630
17679
|
sqlAvailability: "unavailable",
|
|
16631
|
-
backend: this.#backend,
|
|
16632
|
-
|
|
16633
|
-
|
|
16634
|
-
|
|
16635
|
-
|
|
16636
|
-
|
|
16637
|
-
|
|
16638
|
-
|
|
17680
|
+
backend: createTransactionReadBackend(this.#backend),
|
|
17681
|
+
[TRANSACTION_RUNTIME]: {
|
|
17682
|
+
backend: this.#backend,
|
|
17683
|
+
runNodeOperationHooks: (operation, kind, id, hookedFunction) => this.#withOperationHooks(
|
|
17684
|
+
this.#createOperationContext(operation, "node", kind, id),
|
|
17685
|
+
hookedFunction
|
|
17686
|
+
)
|
|
17687
|
+
},
|
|
17688
|
+
getNodeCollection: (kind) => this.#resolveDynamicNodeCollection(nodes, kind)
|
|
16639
17689
|
};
|
|
17690
|
+
Object.defineProperty(fallbackContext, TRANSACTION_RUNTIME, {
|
|
17691
|
+
configurable: false,
|
|
17692
|
+
enumerable: false,
|
|
17693
|
+
writable: false
|
|
17694
|
+
});
|
|
16640
17695
|
const result = await invoke(
|
|
16641
17696
|
receiptRecorder === void 0 ? fallbackContext : this.#attachMeasure(fallbackContext)
|
|
16642
17697
|
);
|
|
@@ -16649,15 +17704,19 @@ var Store = class _Store {
|
|
|
16649
17704
|
recordedByGraph = instants;
|
|
16650
17705
|
}) : backendOptions;
|
|
16651
17706
|
try {
|
|
16652
|
-
const
|
|
16653
|
-
|
|
16654
|
-
|
|
16655
|
-
|
|
16656
|
-
|
|
16657
|
-
|
|
16658
|
-
|
|
16659
|
-
|
|
16660
|
-
|
|
17707
|
+
const run = async (txBackend, nativeTransaction) => invoke(
|
|
17708
|
+
this.#buildTransactionContext(
|
|
17709
|
+
txBackend,
|
|
17710
|
+
nativeTransaction,
|
|
17711
|
+
runHooks,
|
|
17712
|
+
receiptRecorder
|
|
17713
|
+
)
|
|
17714
|
+
);
|
|
17715
|
+
const result = this.#captureEnabled || this.#adapterBackend === void 0 ? await this.#backend.transaction(
|
|
17716
|
+
(txBackend) => run(txBackend, void 0),
|
|
17717
|
+
transactionOptions
|
|
17718
|
+
) : await this.#adapterBackend.transactionWithNative(
|
|
17719
|
+
(txBackend, nativeTransaction) => run(txBackend, nativeTransaction),
|
|
16661
17720
|
transactionOptions
|
|
16662
17721
|
);
|
|
16663
17722
|
for (const outcome of pending) {
|
|
@@ -16674,12 +17733,86 @@ var Store = class _Store {
|
|
|
16674
17733
|
throw error;
|
|
16675
17734
|
}
|
|
16676
17735
|
}
|
|
17736
|
+
/**
|
|
17737
|
+
* Adopts a caller-owned, already-open Drizzle transaction so the graph
|
|
17738
|
+
* store and the caller's relational writes commit or roll back as one
|
|
17739
|
+
* Postgres/SQLite transaction (#134).
|
|
17740
|
+
*
|
|
17741
|
+
* Use this when the **relational layer owns the transaction**: the
|
|
17742
|
+
* caller has opened a transaction and needs TypeGraph writes enlisted
|
|
17743
|
+
* on the *same* connection. Unlike {@link transaction}, this opens no
|
|
17744
|
+
* transaction — the caller's transaction is the single commit/rollback
|
|
17745
|
+
* boundary.
|
|
17746
|
+
*
|
|
17747
|
+
* `withTransaction` is driver-agnostic; how the caller opens the
|
|
17748
|
+
* transaction is not. **Async drivers** (node-postgres,
|
|
17749
|
+
* `neon-serverless` Pool, libsql) use `db.transaction(async …)`.
|
|
17750
|
+
* **Synchronous `better-sqlite3`** cannot — its driver rejects an
|
|
17751
|
+
* `async` transaction callback (`Transaction function cannot return a
|
|
17752
|
+
* promise`) and the async continuation would run outside the
|
|
17753
|
+
* rolled-back transaction — so the caller opens the transaction with
|
|
17754
|
+
* explicit `BEGIN`/`COMMIT`/`ROLLBACK` on the single connection
|
|
17755
|
+
* instead. See the "Cross-Store Transactions" recipe for both shapes.
|
|
17756
|
+
*
|
|
17757
|
+
* The returned context reuses this store's already-resolved
|
|
17758
|
+
* schema/registry: it runs **no** schema bootstrap, `evolve`, or
|
|
17759
|
+
* migration, and emits **no DDL** inside the caller's transaction.
|
|
17760
|
+
* Fulltext operations assert the durable materialization marker (a
|
|
17761
|
+
* cached SELECT) and throw {@link StoreNotInitializedError} on a
|
|
17762
|
+
* missing/stale/failed marker rather than migrating mid-transaction —
|
|
17763
|
+
* so boot the parent store via `createAdapterStoreWithSchema` once at
|
|
17764
|
+
* startup.
|
|
17765
|
+
*
|
|
17766
|
+
* @example
|
|
17767
|
+
* ```typescript
|
|
17768
|
+
* // Async driver (Postgres / libsql):
|
|
17769
|
+
* await db.transaction(async (sqlTx) => {
|
|
17770
|
+
* const connector = await createConnectorRow(sqlTx, input); // Drizzle
|
|
17771
|
+
* const txStore = store.withTransaction(sqlTx);
|
|
17772
|
+
* await txStore.nodes.ArtifactSource.create({ // TypeGraph
|
|
17773
|
+
* connectorId: connector.id,
|
|
17774
|
+
* });
|
|
17775
|
+
* }); // one COMMIT / ROLLBACK across both layers
|
|
17776
|
+
* ```
|
|
17777
|
+
*
|
|
17778
|
+
* **The caller owns the connection — don't overlap writes on it.** The graph
|
|
17779
|
+
* store and your Drizzle writes share the one connection the caller's
|
|
17780
|
+
* transaction pinned. TypeGraph serializes the statements *its* collections
|
|
17781
|
+
* issue, but your raw Drizzle statements (and any graph write run alongside
|
|
17782
|
+
* them) are yours to sequence: a `Promise.all` mixing the two races two
|
|
17783
|
+
* queries on that connection — the overlap Postgres removes in `pg@9`. Await
|
|
17784
|
+
* each write before starting the next.
|
|
17785
|
+
*
|
|
17786
|
+
* Not available when the store was created with `{ history: true }`: a
|
|
17787
|
+
* caller-owned transaction context would let writes happen after capture has
|
|
17788
|
+
* lost its flush point. {@link AdapterHistoryStore} omits this method, while
|
|
17789
|
+
* the runtime guard still throws `ConfigurationError` if the public contract
|
|
17790
|
+
* is bypassed
|
|
17791
|
+
* (`RECORDED_CAPTURE_REQUIRES_CALLBACK_TRANSACTION`) if the check is
|
|
17792
|
+
* suppressed. Use {@link AdapterStore.withRecordedTransaction} on a history-enabled
|
|
17793
|
+
* store, which adopts the same external transaction but flushes recorded-time
|
|
17794
|
+
* capture before the caller commits.
|
|
17795
|
+
*
|
|
17796
|
+
* @throws {ConfigurationError} when the store has history capture enabled
|
|
17797
|
+
* (use {@link AdapterStore.withRecordedTransaction} instead), or when the backend
|
|
17798
|
+
* cannot adopt an external transaction — either it is not a Drizzle
|
|
17799
|
+
* Postgres/SQLite backend, or `backend.capabilities.transactions` is `false`
|
|
17800
|
+
* (`drizzle-orm/neon-http`, Cloudflare D1, SQLite
|
|
17801
|
+
* `transactionMode: "none"`). A non-atomic fallback is deliberately
|
|
17802
|
+
* not offered here: the caller's relational write *would* still
|
|
17803
|
+
* commit, defeating the purpose of cross-store atomicity.
|
|
17804
|
+
* @throws {StoreNotInitializedError} at point of use, when a fulltext
|
|
17805
|
+
* operation on the returned context observes a missing/stale/failed
|
|
17806
|
+
* durable materialization marker (parent store not booted via
|
|
17807
|
+
* `createAdapterStoreWithSchema`). Rolls back the caller's transaction
|
|
17808
|
+
* without emitting any DDL.
|
|
17809
|
+
*/
|
|
16677
17810
|
withTransaction(externalTx) {
|
|
16678
17811
|
if (this.#captureEnabled) {
|
|
16679
17812
|
throw recordedCaptureRequiresCallbackTransactionError();
|
|
16680
17813
|
}
|
|
16681
|
-
const adopt = this.#
|
|
16682
|
-
if (
|
|
17814
|
+
const adopt = this.#adapterBackend?.adoptTransaction;
|
|
17815
|
+
if (adopt === void 0) {
|
|
16683
17816
|
throw new ConfigurationError(
|
|
16684
17817
|
"This backend cannot adopt an external transaction for cross-store atomicity. adoptTransaction is provided only by the Drizzle Postgres/SQLite backends with transaction support. Check backend.capabilities.transactions, or run the relational and graph writes as separate transactions with manual compensation.",
|
|
16685
17818
|
{ capability: "adoptTransaction" }
|
|
@@ -16688,8 +17821,8 @@ var Store = class _Store {
|
|
|
16688
17821
|
return this.#buildTransactionContext(adopt(externalTx), externalTx);
|
|
16689
17822
|
}
|
|
16690
17823
|
async withRecordedTransaction(externalTx, fn) {
|
|
16691
|
-
const adopt = this.#
|
|
16692
|
-
if (
|
|
17824
|
+
const adopt = this.#adapterBackend?.adoptTransaction;
|
|
17825
|
+
if (adopt === void 0) {
|
|
16693
17826
|
throw new ConfigurationError(
|
|
16694
17827
|
"This backend cannot adopt an external transaction for recorded-time capture.",
|
|
16695
17828
|
{ capability: "adoptTransaction" },
|
|
@@ -16750,16 +17883,17 @@ var Store = class _Store {
|
|
|
16750
17883
|
context.edges,
|
|
16751
17884
|
scopeRecorder
|
|
16752
17885
|
);
|
|
16753
|
-
const scoped = this.#attachMeasure(
|
|
16754
|
-
|
|
16755
|
-
|
|
16756
|
-
|
|
16757
|
-
|
|
16758
|
-
|
|
17886
|
+
const scoped = this.#attachMeasure(
|
|
17887
|
+
overlayPropertyDescriptors(context, {
|
|
17888
|
+
nodes,
|
|
17889
|
+
edges,
|
|
17890
|
+
getNodeCollection: (kind) => this.#resolveDynamicNodeCollection(nodes, kind)
|
|
17891
|
+
})
|
|
17892
|
+
);
|
|
16759
17893
|
const result = await fn(scoped);
|
|
16760
17894
|
return { result, receipt: scopeRecorder.snapshot() };
|
|
16761
17895
|
};
|
|
16762
|
-
return
|
|
17896
|
+
return overlayPropertyDescriptors(context, { measure });
|
|
16763
17897
|
}
|
|
16764
17898
|
/**
|
|
16765
17899
|
* Builds the `{ nodes, edges, sql }` projection bound to a
|
|
@@ -16771,7 +17905,7 @@ var Store = class _Store {
|
|
|
16771
17905
|
* (#140); when history capture is enabled it is replaced with a fail-loud
|
|
16772
17906
|
* guard because raw graph writes would bypass recorded-time capture.
|
|
16773
17907
|
*/
|
|
16774
|
-
#buildTransactionContext(txBackend,
|
|
17908
|
+
#buildTransactionContext(txBackend, sql2, runHooks = this.#immediateHookRunner(), receiptRecorder) {
|
|
16775
17909
|
const txNodeOperations = {
|
|
16776
17910
|
...this.#buildNodeOperations(this.#createNodeOperationContext(runHooks)),
|
|
16777
17911
|
createQuery: () => this.#createQueryForBackend(txBackend),
|
|
@@ -16805,19 +17939,40 @@ var Store = class _Store {
|
|
|
16805
17939
|
));
|
|
16806
17940
|
}
|
|
16807
17941
|
const getNodeCollection = (kind) => this.#resolveDynamicNodeCollection(nodes, kind);
|
|
16808
|
-
const sqlAvailability = this.#captureEnabled ? "history" : this.#revisionTrackingEnabled ? "revisionTracking" : sql19 === void 0 ? "unavailable" : "available";
|
|
16809
17942
|
const base = {
|
|
16810
17943
|
nodes,
|
|
16811
17944
|
edges,
|
|
16812
|
-
|
|
16813
|
-
backend: txBackend,
|
|
16814
|
-
getNodeCollection
|
|
16815
|
-
runNodeOperationHooks
|
|
16816
|
-
};
|
|
16817
|
-
const withSql = sql19 === void 0 ? base : {
|
|
16818
|
-
...base,
|
|
16819
|
-
sql: this.#captureEnabled ? createHistoryUnsafeSqlRef() : this.#revisionTrackingEnabled ? createRevisionTrackingUnsafeSqlRef() : sql19
|
|
17945
|
+
backend: createTransactionReadBackend(txBackend),
|
|
17946
|
+
[TRANSACTION_RUNTIME]: { backend: txBackend, runNodeOperationHooks },
|
|
17947
|
+
getNodeCollection
|
|
16820
17948
|
};
|
|
17949
|
+
let withSql;
|
|
17950
|
+
if (this.#captureEnabled) {
|
|
17951
|
+
withSql = {
|
|
17952
|
+
...base,
|
|
17953
|
+
sqlAvailability: "history",
|
|
17954
|
+
get sql() {
|
|
17955
|
+
return throwHistoryUnsafeSqlAccess();
|
|
17956
|
+
}
|
|
17957
|
+
};
|
|
17958
|
+
} else if (this.#revisionTrackingEnabled) {
|
|
17959
|
+
withSql = {
|
|
17960
|
+
...base,
|
|
17961
|
+
sqlAvailability: "revisionTracking",
|
|
17962
|
+
get sql() {
|
|
17963
|
+
return throwRevisionTrackingUnsafeSqlAccess();
|
|
17964
|
+
}
|
|
17965
|
+
};
|
|
17966
|
+
} else if (sql2 === void 0) {
|
|
17967
|
+
withSql = { ...base, sqlAvailability: "unavailable" };
|
|
17968
|
+
} else {
|
|
17969
|
+
withSql = { ...base, sql: sql2, sqlAvailability: "available" };
|
|
17970
|
+
}
|
|
17971
|
+
Object.defineProperty(withSql, TRANSACTION_RUNTIME, {
|
|
17972
|
+
configurable: false,
|
|
17973
|
+
enumerable: false,
|
|
17974
|
+
writable: false
|
|
17975
|
+
});
|
|
16821
17976
|
return receiptRecorder === void 0 ? withSql : this.#attachMeasure(withSql);
|
|
16822
17977
|
}
|
|
16823
17978
|
// === Graph Lifecycle ===
|
|
@@ -16969,7 +18124,7 @@ var Store = class _Store {
|
|
|
16969
18124
|
const merged = mergeGraphExtension(baseline, extension);
|
|
16970
18125
|
if (merged === baseline) {
|
|
16971
18126
|
if (baseline === this.#graph) {
|
|
16972
|
-
|
|
18127
|
+
syncStoreReplacementRef(options?.ref, this);
|
|
16973
18128
|
if (options?.eager !== void 0) {
|
|
16974
18129
|
await this.#runEagerOrThrow(this, options.eager);
|
|
16975
18130
|
}
|
|
@@ -17316,7 +18471,7 @@ var Store = class _Store {
|
|
|
17316
18471
|
const plan = planRemovals(baseline, names);
|
|
17317
18472
|
if (plan.removedNodeKinds.length === 0 && plan.removedEdgeKinds.length === 0) {
|
|
17318
18473
|
if (baseline === this.#graph) {
|
|
17319
|
-
|
|
18474
|
+
syncStoreReplacementRef(options?.ref, this);
|
|
17320
18475
|
return this;
|
|
17321
18476
|
}
|
|
17322
18477
|
return this.#cloneWithGraph(
|
|
@@ -17407,7 +18562,7 @@ var Store = class _Store {
|
|
|
17407
18562
|
}
|
|
17408
18563
|
if (setsEqual(nextSet, baseline.deprecatedKinds)) {
|
|
17409
18564
|
if (baseline === this.#graph) {
|
|
17410
|
-
|
|
18565
|
+
syncStoreReplacementRef(options?.ref, this);
|
|
17411
18566
|
return this;
|
|
17412
18567
|
}
|
|
17413
18568
|
return this.#cloneWithGraph(
|
|
@@ -17499,13 +18654,18 @@ var Store = class _Store {
|
|
|
17499
18654
|
return nonEmpty;
|
|
17500
18655
|
}
|
|
17501
18656
|
#cloneWithGraph(graph, ref, schemaMetadata = this.#schemaMetadata) {
|
|
17502
|
-
const next = new
|
|
18657
|
+
const next = this.#adapterBackend === void 0 ? new _StoreImplementation(
|
|
17503
18658
|
graph,
|
|
17504
18659
|
this.#baseBackend,
|
|
17505
18660
|
this.#options,
|
|
17506
18661
|
schemaMetadata
|
|
18662
|
+
) : new AdapterStoreImplementation(
|
|
18663
|
+
graph,
|
|
18664
|
+
this.#adapterBackend,
|
|
18665
|
+
this.#options,
|
|
18666
|
+
schemaMetadata
|
|
17507
18667
|
);
|
|
17508
|
-
|
|
18668
|
+
syncStoreReplacementRef(ref, next);
|
|
17509
18669
|
return next;
|
|
17510
18670
|
}
|
|
17511
18671
|
/**
|
|
@@ -17647,8 +18807,100 @@ var Store = class _Store {
|
|
|
17647
18807
|
);
|
|
17648
18808
|
}
|
|
17649
18809
|
};
|
|
18810
|
+
var AdapterStoreImplementation = class extends StoreImplementation {
|
|
18811
|
+
backend;
|
|
18812
|
+
constructor(graph, backend, options, schemaMetadata) {
|
|
18813
|
+
super(graph, backend, options, schemaMetadata, backend);
|
|
18814
|
+
this.backend = options?.history === true ? createHistoryStoreBackendProjection(this[STORE_RUNTIME].backend) : Object.freeze(
|
|
18815
|
+
createGraphBackendProjection(this[STORE_RUNTIME].backend)
|
|
18816
|
+
);
|
|
18817
|
+
}
|
|
18818
|
+
async evolve(extension, options) {
|
|
18819
|
+
return this.#withAdapterReplacement(
|
|
18820
|
+
options?.ref,
|
|
18821
|
+
(replacementRef) => super.evolve(
|
|
18822
|
+
extension,
|
|
18823
|
+
options?.eager === void 0 ? { ref: replacementRef } : { eager: options.eager, ref: replacementRef }
|
|
18824
|
+
)
|
|
18825
|
+
);
|
|
18826
|
+
}
|
|
18827
|
+
async deprecateKinds(names, options) {
|
|
18828
|
+
return this.#withAdapterReplacement(
|
|
18829
|
+
options?.ref,
|
|
18830
|
+
(replacementRef) => super.deprecateKinds(names, { ref: replacementRef })
|
|
18831
|
+
);
|
|
18832
|
+
}
|
|
18833
|
+
async undeprecateKinds(names, options) {
|
|
18834
|
+
return this.#withAdapterReplacement(
|
|
18835
|
+
options?.ref,
|
|
18836
|
+
(replacementRef) => super.undeprecateKinds(names, { ref: replacementRef })
|
|
18837
|
+
);
|
|
18838
|
+
}
|
|
18839
|
+
async removeKinds(names, options) {
|
|
18840
|
+
return this.#withAdapterReplacement(
|
|
18841
|
+
options?.ref,
|
|
18842
|
+
(replacementRef) => super.removeKinds(
|
|
18843
|
+
names,
|
|
18844
|
+
options?.eager === void 0 ? { ref: replacementRef } : { eager: options.eager, ref: replacementRef }
|
|
18845
|
+
)
|
|
18846
|
+
);
|
|
18847
|
+
}
|
|
18848
|
+
async #withAdapterReplacement(ref, operation) {
|
|
18849
|
+
const tracked = createTrackedReplacementRef(this);
|
|
18850
|
+
try {
|
|
18851
|
+
await operation(tracked.ref);
|
|
18852
|
+
} catch (error) {
|
|
18853
|
+
if (tracked.wasReplaced()) {
|
|
18854
|
+
const replacement2 = requireAdapterStoreImplementation(tracked.ref.current);
|
|
18855
|
+
syncAdapterReplacementRef(ref, replacement2);
|
|
18856
|
+
}
|
|
18857
|
+
throw error;
|
|
18858
|
+
}
|
|
18859
|
+
const replacement = requireAdapterStoreImplementation(tracked.ref.current);
|
|
18860
|
+
syncAdapterReplacementRef(ref, replacement);
|
|
18861
|
+
return replacement;
|
|
18862
|
+
}
|
|
18863
|
+
};
|
|
18864
|
+
function createTrackedReplacementRef(initial) {
|
|
18865
|
+
let current = initial;
|
|
18866
|
+
let replaced = false;
|
|
18867
|
+
return {
|
|
18868
|
+
ref: {
|
|
18869
|
+
get current() {
|
|
18870
|
+
return current;
|
|
18871
|
+
},
|
|
18872
|
+
set current(next) {
|
|
18873
|
+
current = next;
|
|
18874
|
+
replaced = true;
|
|
18875
|
+
}
|
|
18876
|
+
},
|
|
18877
|
+
wasReplaced: () => replaced
|
|
18878
|
+
};
|
|
18879
|
+
}
|
|
18880
|
+
function syncAdapterReplacementRef(ref, replacement) {
|
|
18881
|
+
if (ref === void 0) return;
|
|
18882
|
+
ref.current = replacement;
|
|
18883
|
+
}
|
|
18884
|
+
function requireAdapterStoreImplementation(store) {
|
|
18885
|
+
if (isAdapterStoreImplementation(store)) return store;
|
|
18886
|
+
throw new ConfigurationError(
|
|
18887
|
+
"Adapter store replacement lost its adapter capabilities.",
|
|
18888
|
+
{ code: "ADAPTER_STORE_REPLACEMENT_INVARIANT" }
|
|
18889
|
+
);
|
|
18890
|
+
}
|
|
18891
|
+
function isAdapterStoreImplementation(store) {
|
|
18892
|
+
return store instanceof AdapterStoreImplementation;
|
|
18893
|
+
}
|
|
18894
|
+
function asAdapterStoreSurface(store) {
|
|
18895
|
+
return store;
|
|
18896
|
+
}
|
|
17650
18897
|
function createStore(graph, backend, options) {
|
|
17651
|
-
return new
|
|
18898
|
+
return new StoreImplementation(graph, backend, options);
|
|
18899
|
+
}
|
|
18900
|
+
function createAdapterStore(graph, backend, options) {
|
|
18901
|
+
return asAdapterStoreSurface(
|
|
18902
|
+
new AdapterStoreImplementation(graph, backend, options)
|
|
18903
|
+
);
|
|
17652
18904
|
}
|
|
17653
18905
|
function isKnownEdgeKind(graph, name) {
|
|
17654
18906
|
return Object.hasOwn(graph.edges, name);
|
|
@@ -17693,6 +18945,18 @@ async function materializeVectorContributions(backend, graph) {
|
|
|
17693
18945
|
}
|
|
17694
18946
|
}
|
|
17695
18947
|
async function createStoreWithSchema(graph, backend, options) {
|
|
18948
|
+
const prepared = await prepareStoreWithSchema(graph, backend, options);
|
|
18949
|
+
return [
|
|
18950
|
+
new StoreImplementation(
|
|
18951
|
+
prepared.graph,
|
|
18952
|
+
backend,
|
|
18953
|
+
options,
|
|
18954
|
+
prepared.schemaMetadata
|
|
18955
|
+
),
|
|
18956
|
+
prepared.result
|
|
18957
|
+
];
|
|
18958
|
+
}
|
|
18959
|
+
async function prepareStoreWithSchema(graph, backend, options) {
|
|
17696
18960
|
const {
|
|
17697
18961
|
graph: merged,
|
|
17698
18962
|
activeRow,
|
|
@@ -17707,13 +18971,25 @@ async function createStoreWithSchema(graph, backend, options) {
|
|
|
17707
18971
|
if (options?.systemIndexes !== "skip") {
|
|
17708
18972
|
await materializeSystemIndexesOnBoot(backend, merged.id, result);
|
|
17709
18973
|
}
|
|
17710
|
-
|
|
17711
|
-
merged,
|
|
17712
|
-
|
|
17713
|
-
|
|
17714
|
-
|
|
17715
|
-
|
|
17716
|
-
|
|
18974
|
+
return {
|
|
18975
|
+
graph: merged,
|
|
18976
|
+
result,
|
|
18977
|
+
schemaMetadata: schemaMetadataForResult(activeRow, result)
|
|
18978
|
+
};
|
|
18979
|
+
}
|
|
18980
|
+
async function createAdapterStoreWithSchema(graph, backend, options) {
|
|
18981
|
+
const prepared = await prepareStoreWithSchema(graph, backend, options);
|
|
18982
|
+
return [
|
|
18983
|
+
asAdapterStoreSurface(
|
|
18984
|
+
new AdapterStoreImplementation(
|
|
18985
|
+
prepared.graph,
|
|
18986
|
+
backend,
|
|
18987
|
+
options,
|
|
18988
|
+
prepared.schemaMetadata
|
|
18989
|
+
)
|
|
18990
|
+
),
|
|
18991
|
+
prepared.result
|
|
18992
|
+
];
|
|
17717
18993
|
}
|
|
17718
18994
|
async function materializeSystemIndexesOnBoot(backend, graphId, result) {
|
|
17719
18995
|
if (result.status === "breaking") return;
|
|
@@ -17740,20 +19016,44 @@ async function materializeSystemIndexesOnBoot(backend, graphId, result) {
|
|
|
17740
19016
|
}
|
|
17741
19017
|
}
|
|
17742
19018
|
async function createVerifiedStore(graph, backend, options) {
|
|
19019
|
+
const prepared = await prepareVerifiedStore(graph, backend);
|
|
19020
|
+
return [
|
|
19021
|
+
new StoreImplementation(
|
|
19022
|
+
prepared.graph,
|
|
19023
|
+
backend,
|
|
19024
|
+
options,
|
|
19025
|
+
prepared.schemaMetadata
|
|
19026
|
+
),
|
|
19027
|
+
prepared.result
|
|
19028
|
+
];
|
|
19029
|
+
}
|
|
19030
|
+
async function prepareVerifiedStore(graph, backend) {
|
|
17743
19031
|
const {
|
|
17744
19032
|
graph: merged,
|
|
17745
19033
|
activeRow,
|
|
17746
19034
|
result
|
|
17747
19035
|
} = await loadAndVerifyGraph(backend, graph);
|
|
17748
|
-
|
|
17749
|
-
merged,
|
|
17750
|
-
|
|
17751
|
-
|
|
17752
|
-
|
|
17753
|
-
|
|
17754
|
-
|
|
19036
|
+
return {
|
|
19037
|
+
graph: merged,
|
|
19038
|
+
result,
|
|
19039
|
+
schemaMetadata: schemaMetadataFromRow(activeRow)
|
|
19040
|
+
};
|
|
19041
|
+
}
|
|
19042
|
+
async function createVerifiedAdapterStore(graph, backend, options) {
|
|
19043
|
+
const prepared = await prepareVerifiedStore(graph, backend);
|
|
19044
|
+
return [
|
|
19045
|
+
asAdapterStoreSurface(
|
|
19046
|
+
new AdapterStoreImplementation(
|
|
19047
|
+
prepared.graph,
|
|
19048
|
+
backend,
|
|
19049
|
+
options,
|
|
19050
|
+
prepared.schemaMetadata
|
|
19051
|
+
)
|
|
19052
|
+
),
|
|
19053
|
+
prepared.result
|
|
19054
|
+
];
|
|
17755
19055
|
}
|
|
17756
19056
|
|
|
17757
|
-
export { ExecutableAggregateQuery, ExecutableQuery, MAX_EXPLICIT_RECURSIVE_DEPTH, MAX_RECURSIVE_DEPTH, PreparedQuery, QueryBuilder, RecordedStoreView, StoreSearch, StoreView, UnionableQuery, avg, composeFragments, count, countDistinct, countDistinctEdges, countEdges, createFragment, createQueryBuilder, createStore, createStoreWithSchema, createVerifiedStore, defineSubgraphProject, field, having, havingEq, havingGt, havingGte, havingLt, havingLte, limitFragment, max, min, offsetFragment, orderByFragment, sum };
|
|
17758
|
-
//# sourceMappingURL=chunk-
|
|
17759
|
-
//# sourceMappingURL=chunk-
|
|
19057
|
+
export { ExecutableAggregateQuery, ExecutableQuery, MAX_EXPLICIT_RECURSIVE_DEPTH, MAX_RECURSIVE_DEPTH, PreparedQuery, QueryBuilder, RecordedStoreView, StoreSearch, StoreView, UnionableQuery, avg, composeFragments, count, countDistinct, countDistinctEdges, countEdges, createAdapterStore, createAdapterStoreWithSchema, createFragment, createQueryBuilder, createStore, createStoreWithSchema, createVerifiedAdapterStore, createVerifiedStore, defineSubgraphProject, field, having, havingEq, havingGt, havingGte, havingLt, havingLte, limitFragment, max, min, offsetFragment, orderByFragment, sum };
|
|
19058
|
+
//# sourceMappingURL=chunk-A2FGSWMQ.js.map
|
|
19059
|
+
//# sourceMappingURL=chunk-A2FGSWMQ.js.map
|