@nicia-ai/typegraph 0.37.1 → 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-5AVRFNP4.cjs → chunk-2SL7OGPR.cjs} +2866 -1507
- 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-GA4TT3DH.js → chunk-A2FGSWMQ.js} +1845 -489
- 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-UV3WP5WZ.js → chunk-TE5ZA4VX.js} +55 -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-EJYMTO3K.cjs → chunk-YLINFV7Z.cjs} +144 -116
- 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-5AVRFNP4.cjs.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-EJYMTO3K.cjs.map +0 -1
- package/dist/chunk-EXU3RASM.js.map +0 -1
- package/dist/chunk-GA4TT3DH.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-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-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-UV3WP5WZ.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) {
|
|
@@ -10816,6 +10959,33 @@ function assertEdgeKinds(edges) {
|
|
|
10816
10959
|
);
|
|
10817
10960
|
}
|
|
10818
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
|
+
}
|
|
10819
10989
|
|
|
10820
10990
|
// src/store/algorithms/degree.ts
|
|
10821
10991
|
async function executeDegree(ctx, nodeId, options = {}) {
|
|
@@ -10857,11 +11027,23 @@ function compileDirectionFilter(ctx, direction, nodeId, nodesTable) {
|
|
|
10857
11027
|
}
|
|
10858
11028
|
}
|
|
10859
11029
|
}
|
|
11030
|
+
|
|
11031
|
+
// src/store/algorithms/iterative-graph-operation.ts
|
|
10860
11032
|
function frontierIndexIdentifier(context) {
|
|
10861
11033
|
return sql.identifier(
|
|
10862
11034
|
`typegraph_iterative_${context.runId.replaceAll("-", "_")}_frontier`
|
|
10863
11035
|
);
|
|
10864
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
|
+
}
|
|
10865
11047
|
var DEFAULT_MAX_BIND_PARAMETERS = 999;
|
|
10866
11048
|
var RESERVED_TEMPORAL_BIND_PARAMETERS_PER_BRANCH = 12;
|
|
10867
11049
|
var RESERVED_WEIGHT_BIND_PARAMETERS_PER_BRANCH = 4;
|
|
@@ -10912,71 +11094,69 @@ async function runIterativeGraphOperation(ctx, options, plan) {
|
|
|
10912
11094
|
{ dialect: ctx.backend.dialect }
|
|
10913
11095
|
);
|
|
10914
11096
|
}
|
|
10915
|
-
|
|
10916
|
-
|
|
10917
|
-
|
|
10918
|
-
|
|
10919
|
-
|
|
10920
|
-
|
|
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
|
|
10921
11123
|
);
|
|
10922
|
-
|
|
10923
|
-
|
|
10924
|
-
|
|
10925
|
-
|
|
10926
|
-
|
|
10927
|
-
|
|
10928
|
-
|
|
10929
|
-
|
|
10930
|
-
|
|
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
|
|
10931
11143
|
);
|
|
10932
11144
|
}
|
|
10933
|
-
};
|
|
10934
|
-
if (context.operation.workingMemory !== void 0) {
|
|
10935
|
-
const workingMemoryStatement = ctx.dialect.setTransactionWorkingMemory(
|
|
10936
|
-
context.operation.workingMemory
|
|
10937
|
-
);
|
|
10938
|
-
if (workingMemoryStatement !== void 0) {
|
|
10939
|
-
await context.executeTemporary(workingMemoryStatement);
|
|
10940
|
-
}
|
|
10941
11145
|
}
|
|
10942
|
-
|
|
10943
|
-
|
|
10944
|
-
|
|
10945
|
-
|
|
10946
|
-
let analyzedRowCount = await refreshWorkingTableStatistics(
|
|
10947
|
-
context,
|
|
10948
|
-
state.workingTableSize
|
|
11146
|
+
if (!plan.hasConverged(state)) {
|
|
11147
|
+
throw new GraphAlgorithmConvergenceError(
|
|
11148
|
+
plan.algorithm,
|
|
11149
|
+
plan.maxIterations
|
|
10949
11150
|
);
|
|
10950
|
-
for (let iteration = 1; iteration <= plan.maxIterations && !plan.hasConverged(state); iteration++) {
|
|
10951
|
-
state = await plan.runRound(context, state, iteration);
|
|
10952
|
-
if (iteration < plan.maxIterations && !plan.hasConverged(state)) {
|
|
10953
|
-
analyzedRowCount = await refreshWorkingTableStatistics(
|
|
10954
|
-
context,
|
|
10955
|
-
state.workingTableSize,
|
|
10956
|
-
analyzedRowCount
|
|
10957
|
-
);
|
|
10958
|
-
}
|
|
10959
|
-
}
|
|
10960
|
-
if (!plan.hasConverged(state)) {
|
|
10961
|
-
throw new GraphAlgorithmConvergenceError(
|
|
10962
|
-
plan.algorithm,
|
|
10963
|
-
plan.maxIterations
|
|
10964
|
-
);
|
|
10965
|
-
}
|
|
10966
|
-
return await plan.extractResult(context, state);
|
|
10967
|
-
} catch (error) {
|
|
10968
|
-
operationError = error;
|
|
10969
|
-
throw error;
|
|
10970
|
-
} finally {
|
|
10971
|
-
await dropWorkingTable(context, operationError);
|
|
10972
11151
|
}
|
|
10973
|
-
|
|
10974
|
-
{
|
|
10975
|
-
|
|
10976
|
-
|
|
10977
|
-
|
|
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);
|
|
10978
11158
|
}
|
|
10979
|
-
);
|
|
11159
|
+
}, transactionOptions);
|
|
10980
11160
|
}
|
|
10981
11161
|
function shouldRefreshWorkingTableStatistics(workingTableSize, analyzedRowCount) {
|
|
10982
11162
|
if (workingTableSize < WORKING_TABLE_ANALYZE_MINIMUM_ROWS) return false;
|
|
@@ -10994,14 +11174,27 @@ async function refreshWorkingTableStatistics(context, workingTableSize, analyzed
|
|
|
10994
11174
|
await context.executeTemporary(statement);
|
|
10995
11175
|
return workingTableSize;
|
|
10996
11176
|
}
|
|
10997
|
-
async function dropWorkingTable(context,
|
|
11177
|
+
async function dropWorkingTable(context, hasPrimaryFailure) {
|
|
10998
11178
|
try {
|
|
10999
11179
|
await context.executeTemporary(
|
|
11000
11180
|
sql`DROP TABLE IF EXISTS ${context.workingTable}`
|
|
11001
11181
|
);
|
|
11002
11182
|
} catch (cleanupError) {
|
|
11003
|
-
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 };
|
|
11004
11192
|
}
|
|
11193
|
+
await dropWorkingTable(
|
|
11194
|
+
context,
|
|
11195
|
+
operationFailure !== void 0 || cleanupFailure !== void 0
|
|
11196
|
+
);
|
|
11197
|
+
if (cleanupFailure !== void 0) throw cleanupFailure.error;
|
|
11005
11198
|
}
|
|
11006
11199
|
async function fetchVisibleWorkingNodes(operation, nodeIds) {
|
|
11007
11200
|
const nodes = /* @__PURE__ */ new Map();
|
|
@@ -11254,100 +11447,833 @@ function requireTemporaryStatements(backend) {
|
|
|
11254
11447
|
return backend;
|
|
11255
11448
|
}
|
|
11256
11449
|
|
|
11257
|
-
// src/store/algorithms/
|
|
11258
|
-
|
|
11259
|
-
|
|
11260
|
-
|
|
11261
|
-
|
|
11262
|
-
|
|
11263
|
-
}
|
|
11264
|
-
|
|
11265
|
-
|
|
11266
|
-
|
|
11267
|
-
|
|
11268
|
-
|
|
11269
|
-
|
|
11270
|
-
|
|
11271
|
-
|
|
11272
|
-
|
|
11273
|
-
|
|
11274
|
-
|
|
11275
|
-
|
|
11276
|
-
|
|
11277
|
-
|
|
11278
|
-
|
|
11279
|
-
|
|
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,
|
|
11280
11477
|
createWorkingTable,
|
|
11281
|
-
|
|
11282
|
-
|
|
11283
|
-
return {
|
|
11284
|
-
depth: 0,
|
|
11285
|
-
frontierCount: seeded.length,
|
|
11286
|
-
workingTableSize: seeded.length
|
|
11287
|
-
};
|
|
11288
|
-
},
|
|
11289
|
-
async runRound(context, state) {
|
|
11290
|
-
const nextDepth = state.depth + 1;
|
|
11291
|
-
const frontierCount = await expandReachableWorkingTableRound(
|
|
11292
|
-
context,
|
|
11293
|
-
"forward",
|
|
11294
|
-
state.depth,
|
|
11295
|
-
nextDepth,
|
|
11296
|
-
context.operation.direction
|
|
11297
|
-
);
|
|
11298
|
-
return {
|
|
11299
|
-
depth: nextDepth,
|
|
11300
|
-
frontierCount,
|
|
11301
|
-
workingTableSize: state.workingTableSize + frontierCount
|
|
11302
|
-
};
|
|
11303
|
-
},
|
|
11478
|
+
initialize: (context) => initializeWorkingTables(context, nodeKinds),
|
|
11479
|
+
runRound: (context, state, iteration) => runLabelPropagationRound(context, state, iteration, policy),
|
|
11304
11480
|
hasConverged(state) {
|
|
11305
|
-
return state.
|
|
11481
|
+
return state.changedCount === 0 || state.completed;
|
|
11306
11482
|
},
|
|
11307
|
-
|
|
11308
|
-
|
|
11309
|
-
return rows.map((row) => ({
|
|
11310
|
-
id: row.node_id,
|
|
11311
|
-
kind: row.node_kind,
|
|
11312
|
-
depth: Number(row.depth)
|
|
11313
|
-
})).toSorted(
|
|
11314
|
-
(left, right) => left.depth - right.depth || compareNodeIdentity(left, right)
|
|
11315
|
-
);
|
|
11316
|
-
}
|
|
11483
|
+
extractResult: extractMemberships,
|
|
11484
|
+
cleanup: dropNeighborTable
|
|
11317
11485
|
});
|
|
11318
11486
|
}
|
|
11319
|
-
|
|
11320
|
-
|
|
11321
|
-
|
|
11322
|
-
|
|
11323
|
-
|
|
11324
|
-
|
|
11325
|
-
const
|
|
11326
|
-
const
|
|
11327
|
-
|
|
11328
|
-
|
|
11329
|
-
|
|
11330
|
-
|
|
11331
|
-
|
|
11332
|
-
|
|
11333
|
-
|
|
11334
|
-
|
|
11335
|
-
|
|
11336
|
-
|
|
11337
|
-
|
|
11338
|
-
|
|
11339
|
-
|
|
11340
|
-
const
|
|
11341
|
-
|
|
11342
|
-
|
|
11343
|
-
|
|
11344
|
-
|
|
11345
|
-
|
|
11346
|
-
|
|
11347
|
-
|
|
11348
|
-
|
|
11349
|
-
|
|
11350
|
-
|
|
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) {
|
|
12203
|
+
return runIterativeGraphOperation(ctx, options, {
|
|
12204
|
+
algorithm: "reachable",
|
|
12205
|
+
maxIterations: maxHops,
|
|
12206
|
+
createWorkingTable: createWorkingTable3,
|
|
12207
|
+
async initialize(context) {
|
|
12208
|
+
const seeded = await seedWorkingSide(context, sourceId, "forward");
|
|
12209
|
+
return {
|
|
12210
|
+
depth: 0,
|
|
12211
|
+
frontierCount: seeded.length,
|
|
12212
|
+
workingTableSize: seeded.length
|
|
12213
|
+
};
|
|
12214
|
+
},
|
|
12215
|
+
async runRound(context, state) {
|
|
12216
|
+
const nextDepth = state.depth + 1;
|
|
12217
|
+
const frontierCount = await expandReachableWorkingTableRound(
|
|
12218
|
+
context,
|
|
12219
|
+
"forward",
|
|
12220
|
+
state.depth,
|
|
12221
|
+
nextDepth,
|
|
12222
|
+
context.operation.direction
|
|
12223
|
+
);
|
|
12224
|
+
return {
|
|
12225
|
+
depth: nextDepth,
|
|
12226
|
+
frontierCount,
|
|
12227
|
+
workingTableSize: state.workingTableSize + frontierCount
|
|
12228
|
+
};
|
|
12229
|
+
},
|
|
12230
|
+
hasConverged(state) {
|
|
12231
|
+
return state.frontierCount === 0 || state.depth >= maxHops;
|
|
12232
|
+
},
|
|
12233
|
+
async extractResult(context) {
|
|
12234
|
+
const rows = await readWorkingRows(context, "forward");
|
|
12235
|
+
return rows.map((row) => ({
|
|
12236
|
+
id: row.node_id,
|
|
12237
|
+
kind: row.node_kind,
|
|
12238
|
+
depth: Number(row.depth)
|
|
12239
|
+
})).toSorted(
|
|
12240
|
+
(left, right) => left.depth - right.depth || compareNodeIdentity(left, right)
|
|
12241
|
+
);
|
|
12242
|
+
}
|
|
12243
|
+
});
|
|
12244
|
+
}
|
|
12245
|
+
async function findShortestPathInWorkingTable(ctx, sourceId, targetId, maxHops, options) {
|
|
12246
|
+
return runIterativeGraphOperation(ctx, options, {
|
|
12247
|
+
algorithm: "shortestPath",
|
|
12248
|
+
maxIterations: maxHops,
|
|
12249
|
+
createWorkingTable: createWorkingTable3,
|
|
12250
|
+
async initialize(context) {
|
|
12251
|
+
const forwardSeeds = await seedWorkingSide(context, sourceId, "forward");
|
|
12252
|
+
const reverseSeeds = await seedWorkingSide(context, targetId, "reverse");
|
|
12253
|
+
return {
|
|
12254
|
+
forwardDepth: 0,
|
|
12255
|
+
reverseDepth: 0,
|
|
12256
|
+
forwardFrontierCount: forwardSeeds.length,
|
|
12257
|
+
reverseFrontierCount: reverseSeeds.length,
|
|
12258
|
+
meeting: findSeedMeeting(forwardSeeds, reverseSeeds),
|
|
12259
|
+
workingTableSize: forwardSeeds.length + reverseSeeds.length
|
|
12260
|
+
};
|
|
12261
|
+
},
|
|
12262
|
+
async runRound(context, state) {
|
|
12263
|
+
const expandForward = state.forwardFrontierCount <= state.reverseFrontierCount;
|
|
12264
|
+
const side = expandForward ? "forward" : "reverse";
|
|
12265
|
+
const currentDepth = expandForward ? state.forwardDepth : state.reverseDepth;
|
|
12266
|
+
const nextDepth = currentDepth + 1;
|
|
12267
|
+
const direction = expandForward ? context.operation.direction : reverseDirection(context.operation.direction);
|
|
12268
|
+
const round = await expandWorkingTableRound(
|
|
12269
|
+
context,
|
|
12270
|
+
side,
|
|
12271
|
+
currentDepth,
|
|
12272
|
+
nextDepth,
|
|
12273
|
+
direction,
|
|
12274
|
+
maxHops
|
|
12275
|
+
);
|
|
12276
|
+
return {
|
|
11351
12277
|
forwardDepth: expandForward ? nextDepth : state.forwardDepth,
|
|
11352
12278
|
reverseDepth: expandForward ? state.reverseDepth : nextDepth,
|
|
11353
12279
|
forwardFrontierCount: expandForward ? round.insertedCount : state.forwardFrontierCount,
|
|
@@ -11370,7 +12296,7 @@ async function findShortestPathInWorkingTable(ctx, sourceId, targetId, maxHops,
|
|
|
11370
12296
|
}
|
|
11371
12297
|
});
|
|
11372
12298
|
}
|
|
11373
|
-
function
|
|
12299
|
+
function createWorkingTable3(context) {
|
|
11374
12300
|
return sql`
|
|
11375
12301
|
CREATE TEMP TABLE ${context.workingTable} (
|
|
11376
12302
|
graph_id TEXT NOT NULL,
|
|
@@ -11612,7 +12538,8 @@ async function findShortestPathInline(ctx, sourceId, targetId, maxHops, options)
|
|
|
11612
12538
|
const sources = visibleNodes.filter((node) => node.id === sourceId);
|
|
11613
12539
|
const targets = visibleNodes.filter((node) => node.id === targetId);
|
|
11614
12540
|
if (sources.length === 0 || targets.length === 0) return;
|
|
11615
|
-
if (sourceId === targetId)
|
|
12541
|
+
if (sourceId === targetId)
|
|
12542
|
+
return { nodes: [requireDefined(sources[0])], depth: 0 };
|
|
11616
12543
|
const forwardVisited = createVisitedMap(sources);
|
|
11617
12544
|
const reverseVisited = createVisitedMap(targets);
|
|
11618
12545
|
let forwardWorkingSet = sources;
|
|
@@ -11813,18 +12740,20 @@ async function executeShortestPath(ctx, sourceId, targetId, options) {
|
|
|
11813
12740
|
);
|
|
11814
12741
|
return findShortestPath(ctx, sourceId, targetId, maxHops, options);
|
|
11815
12742
|
}
|
|
12743
|
+
|
|
12744
|
+
// src/store/algorithms/weakly-connected-components.ts
|
|
11816
12745
|
var DEFAULT_WCC_MAX_ITERATIONS = 1e3;
|
|
11817
12746
|
async function executeWeaklyConnectedComponents(ctx, options) {
|
|
11818
12747
|
assertEdgeKinds(options.edges);
|
|
11819
|
-
|
|
12748
|
+
assertGraphAnalyticsSupported(ctx, "weaklyConnectedComponents", {
|
|
12749
|
+
requiresWindowFunctions: true
|
|
12750
|
+
});
|
|
11820
12751
|
const maxIterations = resolveMaxIterations(
|
|
11821
12752
|
options.maxIterations,
|
|
11822
12753
|
DEFAULT_WCC_MAX_ITERATIONS,
|
|
11823
12754
|
"weaklyConnectedComponents"
|
|
11824
12755
|
);
|
|
11825
|
-
const nodeKinds =
|
|
11826
|
-
(left, right) => compareCodePoints(left, right)
|
|
11827
|
-
);
|
|
12756
|
+
const nodeKinds = normalizeNodeKinds(options.nodeKinds);
|
|
11828
12757
|
const traversalOptions = {
|
|
11829
12758
|
edges: options.edges,
|
|
11830
12759
|
direction: "both",
|
|
@@ -11834,31 +12763,16 @@ async function executeWeaklyConnectedComponents(ctx, options) {
|
|
|
11834
12763
|
return runIterativeGraphOperation(ctx, traversalOptions, {
|
|
11835
12764
|
algorithm: "weaklyConnectedComponents",
|
|
11836
12765
|
maxIterations,
|
|
11837
|
-
createWorkingTable:
|
|
11838
|
-
initialize: (context) =>
|
|
11839
|
-
runRound:
|
|
12766
|
+
createWorkingTable: createWorkingTable4,
|
|
12767
|
+
initialize: (context) => initializeWorkingTable2(context, nodeKinds),
|
|
12768
|
+
runRound: runLabelPropagationRound2,
|
|
11840
12769
|
hasConverged(state) {
|
|
11841
12770
|
return state.changedCount === 0;
|
|
11842
12771
|
},
|
|
11843
|
-
extractResult:
|
|
12772
|
+
extractResult: extractMemberships2
|
|
11844
12773
|
});
|
|
11845
12774
|
}
|
|
11846
|
-
function
|
|
11847
|
-
if (ctx.backend.capabilities.graphAnalytics?.supported === true && ctx.backend.capabilities.windowFunctions) {
|
|
11848
|
-
return;
|
|
11849
|
-
}
|
|
11850
|
-
throw new UnsupportedBackendCapabilityError(
|
|
11851
|
-
"weaklyConnectedComponents",
|
|
11852
|
-
"graphAnalytics",
|
|
11853
|
-
{
|
|
11854
|
-
dialect: ctx.backend.dialect,
|
|
11855
|
-
supported: ctx.backend.capabilities.graphAnalytics?.supported === true,
|
|
11856
|
-
windowFunctions: ctx.backend.capabilities.windowFunctions
|
|
11857
|
-
},
|
|
11858
|
-
"Use a built-in transactional SQLite/PostgreSQL backend, or declare graphAnalytics support on a compatible custom backend."
|
|
11859
|
-
);
|
|
11860
|
-
}
|
|
11861
|
-
function createWorkingTable2(context) {
|
|
12775
|
+
function createWorkingTable4(context) {
|
|
11862
12776
|
return sql`
|
|
11863
12777
|
CREATE TEMP TABLE ${context.workingTable} (
|
|
11864
12778
|
graph_id TEXT NOT NULL,
|
|
@@ -11874,9 +12788,9 @@ function createWorkingTable2(context) {
|
|
|
11874
12788
|
)
|
|
11875
12789
|
`;
|
|
11876
12790
|
}
|
|
11877
|
-
async function
|
|
12791
|
+
async function initializeWorkingTable2(context, nodeKinds) {
|
|
11878
12792
|
const { operation, workingTable, graphId, runId } = context;
|
|
11879
|
-
const nodeKindFilter =
|
|
12793
|
+
const nodeKindFilter = compileNodeKindSeedFilter(nodeKinds);
|
|
11880
12794
|
await context.executeTemporary(sql`
|
|
11881
12795
|
INSERT INTO ${workingTable}
|
|
11882
12796
|
(graph_id, run_id, node_id, node_kind, label_id, label_kind,
|
|
@@ -11892,21 +12806,14 @@ async function initializeWorkingTable(context, nodeKinds) {
|
|
|
11892
12806
|
CREATE INDEX ${frontierIndexIdentifier(context)}
|
|
11893
12807
|
ON ${workingTable} (graph_id, run_id, improved_round)
|
|
11894
12808
|
`);
|
|
11895
|
-
const
|
|
11896
|
-
asCompiledRowsSql(sql`
|
|
11897
|
-
SELECT COUNT(*) AS count
|
|
11898
|
-
FROM ${workingTable}
|
|
11899
|
-
WHERE graph_id = ${graphId} AND run_id = ${runId}
|
|
11900
|
-
`)
|
|
11901
|
-
);
|
|
11902
|
-
const workingTableSize = Number(rows[0]?.count ?? 0);
|
|
12809
|
+
const workingTableSize = await countWorkingTableRows(context);
|
|
11903
12810
|
return { changedCount: workingTableSize, workingTableSize };
|
|
11904
12811
|
}
|
|
11905
|
-
async function
|
|
12812
|
+
async function runLabelPropagationRound2(context, state, iteration) {
|
|
11906
12813
|
for (const edgeKinds of context.operation.edgeKindChunks) {
|
|
11907
12814
|
await propagateChunkLabels(context, edgeKinds, iteration);
|
|
11908
12815
|
}
|
|
11909
|
-
const changedRows = await
|
|
12816
|
+
const changedRows = await applyNextLabels2(context, iteration);
|
|
11910
12817
|
return {
|
|
11911
12818
|
changedCount: changedRows.length,
|
|
11912
12819
|
workingTableSize: state.workingTableSize
|
|
@@ -11981,7 +12888,7 @@ async function propagateChunkLabels(context, edgeKinds, iteration) {
|
|
|
11981
12888
|
)
|
|
11982
12889
|
`);
|
|
11983
12890
|
}
|
|
11984
|
-
function
|
|
12891
|
+
function applyNextLabels2(context, iteration) {
|
|
11985
12892
|
return context.backend.execute(
|
|
11986
12893
|
asCompiledRowsSql(sql`
|
|
11987
12894
|
UPDATE ${context.workingTable}
|
|
@@ -11997,7 +12904,7 @@ function applyNextLabels(context, iteration) {
|
|
|
11997
12904
|
`)
|
|
11998
12905
|
);
|
|
11999
12906
|
}
|
|
12000
|
-
async function
|
|
12907
|
+
async function extractMemberships2(context) {
|
|
12001
12908
|
const { operation } = context;
|
|
12002
12909
|
const componentId = operation.ctx.dialect.binaryText(sql`label_id`);
|
|
12003
12910
|
const componentKind = operation.ctx.dialect.binaryText(sql`label_kind`);
|
|
@@ -12026,6 +12933,8 @@ async function extractMemberships(context) {
|
|
|
12026
12933
|
size: Number(row.component_size)
|
|
12027
12934
|
}));
|
|
12028
12935
|
}
|
|
12936
|
+
|
|
12937
|
+
// src/store/algorithms/weighted-shortest-path.ts
|
|
12029
12938
|
var DEFAULT_WEIGHTED_SHORTEST_PATH_MAX_ITERATIONS = 1e3;
|
|
12030
12939
|
var WEIGHTED_ALGORITHM_NAME = "weightedShortestPath";
|
|
12031
12940
|
var MAX_EDGE_WEIGHT = Number.MAX_VALUE / 2 ** 64;
|
|
@@ -12145,7 +13054,7 @@ async function findWeightedShortestPathInWorkingTable(ctx, sourceId, targetId, m
|
|
|
12145
13054
|
return runIterativeGraphOperation(ctx, options, {
|
|
12146
13055
|
algorithm: WEIGHTED_ALGORITHM_NAME,
|
|
12147
13056
|
maxIterations,
|
|
12148
|
-
createWorkingTable:
|
|
13057
|
+
createWorkingTable: createWorkingTable5,
|
|
12149
13058
|
async initialize(context) {
|
|
12150
13059
|
await assertValidEdgeWeights(
|
|
12151
13060
|
context.operation,
|
|
@@ -12208,7 +13117,7 @@ async function hasVisibleNode(operation, nodeId) {
|
|
|
12208
13117
|
);
|
|
12209
13118
|
return rows.length > 0;
|
|
12210
13119
|
}
|
|
12211
|
-
function
|
|
13120
|
+
function createWorkingTable5(context) {
|
|
12212
13121
|
return sql`
|
|
12213
13122
|
CREATE TEMP TABLE ${context.workingTable} (
|
|
12214
13123
|
graph_id TEXT NOT NULL,
|
|
@@ -12562,6 +13471,14 @@ function createGraphAlgorithms(params) {
|
|
|
12562
13471
|
assertRecordedAsOfInternalOnly(options, "degree", allowRecordedAsOf);
|
|
12563
13472
|
return executeDegree(ctx, resolveNodeId(node), options ?? {});
|
|
12564
13473
|
},
|
|
13474
|
+
labelPropagation(options) {
|
|
13475
|
+
assertRecordedAsOfInternalOnly(
|
|
13476
|
+
options,
|
|
13477
|
+
"labelPropagation",
|
|
13478
|
+
allowRecordedAsOf
|
|
13479
|
+
);
|
|
13480
|
+
return executeLabelPropagation(ctx, options);
|
|
13481
|
+
},
|
|
12565
13482
|
weaklyConnectedComponents(options) {
|
|
12566
13483
|
assertRecordedAsOfInternalOnly(
|
|
12567
13484
|
options,
|
|
@@ -12569,6 +13486,18 @@ function createGraphAlgorithms(params) {
|
|
|
12569
13486
|
allowRecordedAsOf
|
|
12570
13487
|
);
|
|
12571
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);
|
|
12572
13501
|
}
|
|
12573
13502
|
};
|
|
12574
13503
|
}
|
|
@@ -12795,10 +13724,10 @@ function createEdgeCollection(config) {
|
|
|
12795
13724
|
itemIndex++;
|
|
12796
13725
|
continue;
|
|
12797
13726
|
}
|
|
12798
|
-
const deletedAt = pendingEntry === void 0 ? original.deleted_at : void 0;
|
|
13727
|
+
const deletedAt = pendingEntry === void 0 ? requireDefined(original).deleted_at : void 0;
|
|
12799
13728
|
let dirty;
|
|
12800
13729
|
if (config.upsertDirtyCheck !== void 0) {
|
|
12801
|
-
const currentProps = pendingEntry?.props ?? rowPropsToObject(original.props);
|
|
13730
|
+
const currentProps = pendingEntry?.props ?? rowPropsToObject(requireDefined(original).props);
|
|
12802
13731
|
try {
|
|
12803
13732
|
dirty = config.upsertDirtyCheck(
|
|
12804
13733
|
original?.kind ?? kind,
|
|
@@ -12813,7 +13742,9 @@ function createEdgeCollection(config) {
|
|
|
12813
13742
|
const coalesce = dirty?.unchanged === true && deletedAt === void 0 && item.validFrom === void 0 && item.validTo === void 0;
|
|
12814
13743
|
if (coalesce) {
|
|
12815
13744
|
if (pendingEntry === void 0) {
|
|
12816
|
-
results2[itemIndex] = narrowEdge(
|
|
13745
|
+
results2[itemIndex] = narrowEdge(
|
|
13746
|
+
rowToEdge2(requireDefined(original))
|
|
13747
|
+
);
|
|
12817
13748
|
} else {
|
|
12818
13749
|
deferred.push({
|
|
12819
13750
|
index: itemIndex,
|
|
@@ -12839,7 +13770,9 @@ function createEdgeCollection(config) {
|
|
|
12839
13770
|
const createInputs = toCreate.map((entry2) => entry2.input);
|
|
12840
13771
|
const created = await executeEdgeCreateBatch2(createInputs, target);
|
|
12841
13772
|
for (const [index, entry2] of toCreate.entries()) {
|
|
12842
|
-
results2[entry2.index] = narrowEdge(
|
|
13773
|
+
results2[entry2.index] = narrowEdge(
|
|
13774
|
+
requireDefined(created[index])
|
|
13775
|
+
);
|
|
12843
13776
|
}
|
|
12844
13777
|
}
|
|
12845
13778
|
for (const entry2 of toUpdate) {
|
|
@@ -12849,7 +13782,7 @@ function createEdgeCollection(config) {
|
|
|
12849
13782
|
results2[entry2.index] = narrowEdge(result);
|
|
12850
13783
|
}
|
|
12851
13784
|
for (const { index, sourceIndex } of deferred) {
|
|
12852
|
-
results2[index] = results2[sourceIndex];
|
|
13785
|
+
results2[index] = requireDefined(results2[sourceIndex]);
|
|
12853
13786
|
}
|
|
12854
13787
|
return { results: results2, mutations: toCreate.length + toUpdate.length };
|
|
12855
13788
|
};
|
|
@@ -13057,7 +13990,7 @@ function createNodeCollection(config) {
|
|
|
13057
13990
|
temporal,
|
|
13058
13991
|
defaultTemporalMode
|
|
13059
13992
|
);
|
|
13060
|
-
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"]);
|
|
13061
13994
|
if (filter.limit !== void 0) query = query.limit(filter.limit);
|
|
13062
13995
|
if (filter.offset !== void 0) query = query.offset(filter.offset);
|
|
13063
13996
|
const results = await query.execute();
|
|
@@ -13087,7 +14020,7 @@ function createNodeCollection(config) {
|
|
|
13087
14020
|
async upsertByIdFromRecord(id, data, options) {
|
|
13088
14021
|
const existing = await backend.getNode(graphId, kind, id);
|
|
13089
14022
|
if (existing) {
|
|
13090
|
-
const runDirtyCheck = config.upsertDirtyCheck && (() => config.upsertDirtyCheck(
|
|
14023
|
+
const runDirtyCheck = config.upsertDirtyCheck && (() => requireDefined(config.upsertDirtyCheck)(
|
|
13091
14024
|
kind,
|
|
13092
14025
|
id,
|
|
13093
14026
|
rowPropsToObject(existing.props),
|
|
@@ -13157,10 +14090,10 @@ function createNodeCollection(config) {
|
|
|
13157
14090
|
itemIndex++;
|
|
13158
14091
|
continue;
|
|
13159
14092
|
}
|
|
13160
|
-
const deletedAt = pendingEntry === void 0 ? original.deleted_at : void 0;
|
|
14093
|
+
const deletedAt = pendingEntry === void 0 ? requireDefined(original).deleted_at : void 0;
|
|
13161
14094
|
let dirty;
|
|
13162
14095
|
if (config.upsertDirtyCheck !== void 0) {
|
|
13163
|
-
const currentProps = pendingEntry?.props ?? rowPropsToObject(original.props);
|
|
14096
|
+
const currentProps = pendingEntry?.props ?? rowPropsToObject(requireDefined(original).props);
|
|
13164
14097
|
try {
|
|
13165
14098
|
dirty = config.upsertDirtyCheck(
|
|
13166
14099
|
kind,
|
|
@@ -13175,7 +14108,9 @@ function createNodeCollection(config) {
|
|
|
13175
14108
|
const coalesce = dirty?.unchanged === true && deletedAt === void 0 && item.validFrom === void 0 && item.validTo === void 0;
|
|
13176
14109
|
if (coalesce) {
|
|
13177
14110
|
if (pendingEntry === void 0) {
|
|
13178
|
-
results2[itemIndex] = narrowNode(
|
|
14111
|
+
results2[itemIndex] = narrowNode(
|
|
14112
|
+
rowToNode2(requireDefined(original))
|
|
14113
|
+
);
|
|
13179
14114
|
} else {
|
|
13180
14115
|
deferred.push({
|
|
13181
14116
|
index: itemIndex,
|
|
@@ -13201,7 +14136,9 @@ function createNodeCollection(config) {
|
|
|
13201
14136
|
const createInputs = toCreate.map((entry2) => entry2.input);
|
|
13202
14137
|
const created = await executeNodeCreateBatch2(createInputs, target);
|
|
13203
14138
|
for (const [index, entry2] of toCreate.entries()) {
|
|
13204
|
-
results2[entry2.index] = narrowNode(
|
|
14139
|
+
results2[entry2.index] = narrowNode(
|
|
14140
|
+
requireDefined(created[index])
|
|
14141
|
+
);
|
|
13205
14142
|
}
|
|
13206
14143
|
}
|
|
13207
14144
|
for (const entry2 of toUpdate) {
|
|
@@ -13211,7 +14148,7 @@ function createNodeCollection(config) {
|
|
|
13211
14148
|
results2[entry2.index] = narrowNode(result);
|
|
13212
14149
|
}
|
|
13213
14150
|
for (const { index, sourceIndex } of deferred) {
|
|
13214
|
-
results2[index] = results2[sourceIndex];
|
|
14151
|
+
results2[index] = requireDefined(results2[sourceIndex]);
|
|
13215
14152
|
}
|
|
13216
14153
|
return { results: results2, mutations: toCreate.length + toUpdate.length };
|
|
13217
14154
|
};
|
|
@@ -13363,6 +14300,99 @@ function createEdgeCollectionsProxy(graph, graphId, registry, backend, operation
|
|
|
13363
14300
|
});
|
|
13364
14301
|
}
|
|
13365
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
|
+
|
|
13366
14396
|
// src/store/introspect.ts
|
|
13367
14397
|
function introspectSchema(graph, context) {
|
|
13368
14398
|
const extension = graph.extension;
|
|
@@ -13474,6 +14504,18 @@ async function runMaterialization(items, options, runOne) {
|
|
|
13474
14504
|
var CLAIM_LEASE_MS = 15 * 6e4;
|
|
13475
14505
|
var CLAIM_RETRY_DELAY_MS = 200;
|
|
13476
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
|
+
};
|
|
13477
14519
|
function hasIndexBuildClaimProtocol(backend) {
|
|
13478
14520
|
return backend.claimIndexMaterialization !== void 0 && backend.releaseIndexMaterializationClaim !== void 0;
|
|
13479
14521
|
}
|
|
@@ -13518,7 +14560,7 @@ async function materializeIndexes(context, options = {}) {
|
|
|
13518
14560
|
const tableNames = backend.tableNames;
|
|
13519
14561
|
const ddlOptions = {
|
|
13520
14562
|
ifNotExists: true,
|
|
13521
|
-
concurrent: dialect
|
|
14563
|
+
concurrent: INDEX_DIALECT_BEHAVIOR[dialect].concurrentBuilds,
|
|
13522
14564
|
...tableNames?.nodes === void 0 ? {} : { nodesTableName: tableNames.nodes },
|
|
13523
14565
|
...tableNames?.edges === void 0 ? {} : { edgesTableName: tableNames.edges }
|
|
13524
14566
|
};
|
|
@@ -13599,7 +14641,7 @@ function parallelBucketKey(declaration) {
|
|
|
13599
14641
|
return declaration.entity;
|
|
13600
14642
|
}
|
|
13601
14643
|
async function materializeRelationalIndex(declaration, backend, dialect, ddlOptions, graphId, schemaVersion, existingByStatusKey, invalidLeftovers) {
|
|
13602
|
-
if (declaration.method !== void 0 && dialect
|
|
14644
|
+
if (declaration.method !== void 0 && !INDEX_DIALECT_BEHAVIOR[dialect].supportsGinFamily) {
|
|
13603
14645
|
return {
|
|
13604
14646
|
indexName: declaration.name,
|
|
13605
14647
|
entity: declaration.entity,
|
|
@@ -13621,9 +14663,11 @@ async function materializeRelationalIndex(declaration, backend, dialect, ddlOpti
|
|
|
13621
14663
|
driftLabel: "Index",
|
|
13622
14664
|
run: async () => {
|
|
13623
14665
|
if (declaration.method === "trigram") {
|
|
13624
|
-
await backend.executeDdl(
|
|
14666
|
+
await requireDefined(backend.executeDdl)(
|
|
14667
|
+
"CREATE EXTENSION IF NOT EXISTS pg_trgm;"
|
|
14668
|
+
);
|
|
13625
14669
|
}
|
|
13626
|
-
await backend.executeDdl(ddl);
|
|
14670
|
+
await requireDefined(backend.executeDdl)(ddl);
|
|
13627
14671
|
},
|
|
13628
14672
|
existingByStatusKey,
|
|
13629
14673
|
physicalRebuildPreload: invalidLeftovers
|
|
@@ -13671,7 +14715,7 @@ async function materializeVectorIndex(declaration, backend, graphId, schemaVersi
|
|
|
13671
14715
|
efConstruction: declaration.indexParams.efConstruction,
|
|
13672
14716
|
...declaration.indexParams.lists === void 0 ? {} : { lists: declaration.indexParams.lists }
|
|
13673
14717
|
},
|
|
13674
|
-
concurrent: backend.dialect
|
|
14718
|
+
concurrent: INDEX_DIALECT_BEHAVIOR[backend.dialect].concurrentBuilds
|
|
13675
14719
|
};
|
|
13676
14720
|
return materializeOne(declaration, backend, graphId, schemaVersion, {
|
|
13677
14721
|
// Compound status-table key for vector entries. Pgvector creates
|
|
@@ -13682,13 +14726,15 @@ async function materializeVectorIndex(declaration, backend, graphId, schemaVersi
|
|
|
13682
14726
|
statusKey: vectorStatusKey(graphId, declaration.name),
|
|
13683
14727
|
signature,
|
|
13684
14728
|
driftLabel: "Vector index",
|
|
13685
|
-
run: () => backend.createVectorIndex(params),
|
|
14729
|
+
run: () => requireDefined(backend.createVectorIndex)(params),
|
|
13686
14730
|
existingByStatusKey,
|
|
13687
14731
|
physicalRebuildPreload: invalidLeftovers
|
|
13688
14732
|
});
|
|
13689
14733
|
}
|
|
13690
14734
|
async function materializeOne(declaration, backend, graphId, schemaVersion, action) {
|
|
13691
|
-
const recordIndexMaterialization =
|
|
14735
|
+
const recordIndexMaterialization = requireDefined(
|
|
14736
|
+
backend.recordIndexMaterialization
|
|
14737
|
+
);
|
|
13692
14738
|
const { statusKey, signature, driftLabel, run, existingByStatusKey } = action;
|
|
13693
14739
|
const statusOverride = statusKey === declaration.name ? void 0 : { statusName: statusKey };
|
|
13694
14740
|
const settled = await settleAgainstExisting(
|
|
@@ -13760,7 +14806,7 @@ async function settleAgainstExisting(existing, declaration, backend, graphId, sc
|
|
|
13760
14806
|
const error = new Error(
|
|
13761
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.`
|
|
13762
14808
|
);
|
|
13763
|
-
await backend.recordIndexMaterialization(
|
|
14809
|
+
await requireDefined(backend.recordIndexMaterialization)(
|
|
13764
14810
|
buildAttempt({
|
|
13765
14811
|
declaration,
|
|
13766
14812
|
graphId,
|
|
@@ -13776,11 +14822,13 @@ async function settleAgainstExisting(existing, declaration, backend, graphId, sc
|
|
|
13776
14822
|
async function materializeWithClaim(declaration, backend, graphId, schemaVersion, action) {
|
|
13777
14823
|
const { statusKey, signature, driftLabel, run } = action;
|
|
13778
14824
|
const statusOverride = statusKey === declaration.name ? void 0 : { statusName: statusKey };
|
|
13779
|
-
const recordIndexMaterialization =
|
|
14825
|
+
const recordIndexMaterialization = requireDefined(
|
|
14826
|
+
backend.recordIndexMaterialization
|
|
14827
|
+
);
|
|
13780
14828
|
const token = `${statusKey}:${nowIso()}:${Math.floor(performance.now() * 1e3)}`;
|
|
13781
14829
|
const deadline = Date.now() + CLAIM_WAIT_TIMEOUT_MS;
|
|
13782
14830
|
for (; ; ) {
|
|
13783
|
-
const claimed = await backend.claimIndexMaterialization({
|
|
14831
|
+
const claimed = await requireDefined(backend.claimIndexMaterialization)({
|
|
13784
14832
|
indexName: statusKey,
|
|
13785
14833
|
graphId,
|
|
13786
14834
|
entity: declaration.entity,
|
|
@@ -13804,7 +14852,9 @@ async function materializeWithClaim(declaration, backend, graphId, schemaVersion
|
|
|
13804
14852
|
continue;
|
|
13805
14853
|
}
|
|
13806
14854
|
try {
|
|
13807
|
-
const fresh = await backend.getIndexMaterialization(
|
|
14855
|
+
const fresh = await requireDefined(backend.getIndexMaterialization)(
|
|
14856
|
+
statusKey
|
|
14857
|
+
);
|
|
13808
14858
|
const settled = await settleAgainstExisting(
|
|
13809
14859
|
fresh,
|
|
13810
14860
|
declaration,
|
|
@@ -13858,7 +14908,7 @@ async function materializeWithClaim(declaration, backend, graphId, schemaVersion
|
|
|
13858
14908
|
}
|
|
13859
14909
|
} finally {
|
|
13860
14910
|
try {
|
|
13861
|
-
await backend.releaseIndexMaterializationClaim({
|
|
14911
|
+
await requireDefined(backend.releaseIndexMaterializationClaim)({
|
|
13862
14912
|
indexName: statusKey,
|
|
13863
14913
|
token
|
|
13864
14914
|
});
|
|
@@ -13872,7 +14922,9 @@ async function materializeWithClaim(declaration, backend, graphId, schemaVersion
|
|
|
13872
14922
|
}
|
|
13873
14923
|
}
|
|
13874
14924
|
async function hasInvalidIndexLeftover(backend, physicalIndexName) {
|
|
13875
|
-
if (backend.dialect
|
|
14925
|
+
if (!INDEX_DIALECT_BEHAVIOR[backend.dialect].hasInvalidIndexState) {
|
|
14926
|
+
return false;
|
|
14927
|
+
}
|
|
13876
14928
|
const rows = await backend.execute(
|
|
13877
14929
|
asCompiledRowsSql(sql`
|
|
13878
14930
|
SELECT NOT i.indisvalid AS invalid
|
|
@@ -13885,7 +14937,7 @@ async function hasInvalidIndexLeftover(backend, physicalIndexName) {
|
|
|
13885
14937
|
return rows[0]?.invalid === true;
|
|
13886
14938
|
}
|
|
13887
14939
|
async function preloadInvalidIndexLeftovers(backend, physicalIndexNames) {
|
|
13888
|
-
if (backend.dialect
|
|
14940
|
+
if (!INDEX_DIALECT_BEHAVIOR[backend.dialect].hasInvalidIndexState || physicalIndexNames.length === 0) {
|
|
13889
14941
|
return /* @__PURE__ */ new Set();
|
|
13890
14942
|
}
|
|
13891
14943
|
const { invalid } = await preloadPhysicalIndexStates(
|
|
@@ -13896,55 +14948,69 @@ async function preloadInvalidIndexLeftovers(backend, physicalIndexNames) {
|
|
|
13896
14948
|
}
|
|
13897
14949
|
async function preloadExistingTables(backend, tableNames) {
|
|
13898
14950
|
if (tableNames.length === 0) return /* @__PURE__ */ new Set();
|
|
13899
|
-
|
|
13900
|
-
|
|
13901
|
-
|
|
13902
|
-
|
|
13903
|
-
|
|
13904
|
-
|
|
13905
|
-
|
|
13906
|
-
|
|
13907
|
-
|
|
13908
|
-
|
|
13909
|
-
|
|
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
|
+
}
|
|
13910
14978
|
}
|
|
13911
|
-
const rows = await backend.execute(
|
|
13912
|
-
asCompiledRowsSql(sql`
|
|
13913
|
-
SELECT name
|
|
13914
|
-
FROM sqlite_master
|
|
13915
|
-
WHERE type = 'table'
|
|
13916
|
-
AND name IN (${sqlValueList(tableNames)})
|
|
13917
|
-
`)
|
|
13918
|
-
);
|
|
13919
|
-
return new Set(rows.map((row) => row.name));
|
|
13920
14979
|
}
|
|
13921
14980
|
async function preloadPhysicalIndexStates(backend, physicalIndexNames) {
|
|
13922
14981
|
const valid = /* @__PURE__ */ new Set();
|
|
13923
14982
|
const invalid = /* @__PURE__ */ new Set();
|
|
13924
14983
|
if (physicalIndexNames.length === 0) return { valid, invalid };
|
|
13925
|
-
|
|
13926
|
-
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
|
|
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
|
+
}
|
|
13937
15013
|
}
|
|
13938
|
-
const rows = await backend.execute(
|
|
13939
|
-
asCompiledRowsSql(sql`
|
|
13940
|
-
SELECT name
|
|
13941
|
-
FROM sqlite_master
|
|
13942
|
-
WHERE type = 'index'
|
|
13943
|
-
AND name IN (${sqlValueList(physicalIndexNames)})
|
|
13944
|
-
`)
|
|
13945
|
-
);
|
|
13946
|
-
for (const row of rows) valid.add(row.name);
|
|
13947
|
-
return { valid, invalid };
|
|
13948
15014
|
}
|
|
13949
15015
|
async function dropInvalidIndexLeftover(backend, physicalIndexName) {
|
|
13950
15016
|
if (backend.executeDdl === void 0) return;
|
|
@@ -13984,10 +15050,10 @@ async function preloadMaterializations(backend, statusKeys) {
|
|
|
13984
15050
|
for (const row of rows2) map.set(row.indexName, row);
|
|
13985
15051
|
return map;
|
|
13986
15052
|
}
|
|
13987
|
-
const getOne = backend.getIndexMaterialization;
|
|
15053
|
+
const getOne = requireDefined(backend.getIndexMaterialization);
|
|
13988
15054
|
const rows = await Promise.all(statusKeys.map((key) => getOne(key)));
|
|
13989
15055
|
for (const [index, row] of rows.entries()) {
|
|
13990
|
-
if (row !== void 0) map.set(statusKeys[index], row);
|
|
15056
|
+
if (row !== void 0) map.set(requireDefined(statusKeys[index]), row);
|
|
13991
15057
|
}
|
|
13992
15058
|
return map;
|
|
13993
15059
|
}
|
|
@@ -14024,7 +15090,7 @@ async function materializeSystemIndexes(context, options = {}) {
|
|
|
14024
15090
|
backend,
|
|
14025
15091
|
backend.ensureIndexMaterializationsTable
|
|
14026
15092
|
);
|
|
14027
|
-
const concurrent = backend.dialect
|
|
15093
|
+
const concurrent = INDEX_DIALECT_BEHAVIOR[backend.dialect].concurrentBuilds;
|
|
14028
15094
|
const candidates = SYSTEM_INDEX_DECLARATIONS.map((declaration) => {
|
|
14029
15095
|
const physicalTable = resolveSystemIndexTableName(
|
|
14030
15096
|
declaration.table,
|
|
@@ -14091,7 +15157,7 @@ async function materializeSystemIndexes(context, options = {}) {
|
|
|
14091
15157
|
statusKey: candidate.name,
|
|
14092
15158
|
signature,
|
|
14093
15159
|
driftLabel: "System index",
|
|
14094
|
-
run: () => backend.executeDdl(ddl),
|
|
15160
|
+
run: () => requireDefined(backend.executeDdl)(ddl),
|
|
14095
15161
|
existingByStatusKey,
|
|
14096
15162
|
physicalRebuildPreload,
|
|
14097
15163
|
freshNeedsPhysicalRebuild: async (physicalIndexName) => {
|
|
@@ -14128,6 +15194,8 @@ async function computeIndexSignature(dialect, targetTableName, declaration) {
|
|
|
14128
15194
|
const json = JSON.stringify(hashable, sortedReplacer);
|
|
14129
15195
|
return sha256Hex(json, 16);
|
|
14130
15196
|
}
|
|
15197
|
+
|
|
15198
|
+
// src/store/materialize-removals.ts
|
|
14131
15199
|
var ENTITY_KINDS = ["node", "edge"];
|
|
14132
15200
|
function buildPendingKindRemoval(args) {
|
|
14133
15201
|
return { ...args, removedAt: void 0, error: void 0 };
|
|
@@ -14185,7 +15253,7 @@ async function reconcilePendingRemovals(context) {
|
|
|
14185
15253
|
}
|
|
14186
15254
|
const marker = backend.getReconciliationMarker === void 0 ? void 0 : await backend.getReconciliationMarker(graphId);
|
|
14187
15255
|
if (marker !== void 0 && marker >= activeRow.version) return;
|
|
14188
|
-
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));
|
|
14189
15257
|
const recorded = new Set(
|
|
14190
15258
|
allRemovals.map(
|
|
14191
15259
|
(row) => kindRemovalKey(row.entity, row.kindName, row.schemaVersion)
|
|
@@ -14244,7 +15312,7 @@ function kindRemovalKey(entity, kindName, version) {
|
|
|
14244
15312
|
return `${entity}|${kindName}|${version}`;
|
|
14245
15313
|
}
|
|
14246
15314
|
async function materializeOne2(row, ctx) {
|
|
14247
|
-
const recordKindRemoval = ctx.backend.recordKindRemoval;
|
|
15315
|
+
const recordKindRemoval = requireDefined(ctx.backend.recordKindRemoval);
|
|
14248
15316
|
try {
|
|
14249
15317
|
await closeRecordedAndDeleteLiveRows(ctx, row);
|
|
14250
15318
|
await Promise.all(buildEmbeddingTableCleanup(ctx, row));
|
|
@@ -14324,7 +15392,9 @@ async function executeDeleteStatements(target, statements) {
|
|
|
14324
15392
|
if (target.executeStatement !== void 0) {
|
|
14325
15393
|
await Promise.all(
|
|
14326
15394
|
statements.map(
|
|
14327
|
-
(statement) => target.executeStatement(
|
|
15395
|
+
(statement) => requireDefined(target.executeStatement)(
|
|
15396
|
+
asCompiledStatementSql(sql.raw(statement))
|
|
15397
|
+
)
|
|
14328
15398
|
)
|
|
14329
15399
|
);
|
|
14330
15400
|
return;
|
|
@@ -14336,13 +15406,13 @@ async function executeDeleteStatements(target, statements) {
|
|
|
14336
15406
|
);
|
|
14337
15407
|
}
|
|
14338
15408
|
await Promise.all(
|
|
14339
|
-
statements.map((statement) => target.executeDdl(statement))
|
|
15409
|
+
statements.map((statement) => requireDefined(target.executeDdl)(statement))
|
|
14340
15410
|
);
|
|
14341
15411
|
}
|
|
14342
15412
|
function buildEmbeddingTableCleanup(ctx, row) {
|
|
14343
15413
|
const vectorStrategy = ctx.backend.vectorStrategy;
|
|
14344
15414
|
if (vectorStrategy === void 0) return [];
|
|
14345
|
-
const executeDdl = ctx.backend.executeDdl;
|
|
15415
|
+
const executeDdl = requireDefined(ctx.backend.executeDdl);
|
|
14346
15416
|
const cleanup = (async () => {
|
|
14347
15417
|
const slots = await resolveRemovedKindEmbeddingSlots(ctx.backend, row);
|
|
14348
15418
|
await Promise.all(
|
|
@@ -14976,7 +16046,7 @@ async function executeEdgeFindByEndpoints(ctx, kind, fromKind, fromId, toKind, t
|
|
|
14976
16046
|
...options?.asOf !== void 0 && { asOf: options.asOf }
|
|
14977
16047
|
});
|
|
14978
16048
|
if (candidateRows.length === 0) return void 0;
|
|
14979
|
-
if (matchOn.length === 0) return rowToEdge(candidateRows[0]);
|
|
16049
|
+
if (matchOn.length === 0) return rowToEdge(requireDefined(candidateRows[0]));
|
|
14980
16050
|
const { liveRow } = findMatchingEdge(candidateRows, matchOn, props);
|
|
14981
16051
|
return liveRow === void 0 ? void 0 : rowToEdge(liveRow);
|
|
14982
16052
|
}
|
|
@@ -15209,7 +16279,10 @@ async function executeEdgeBulkGetOrCreateByEndpoints(ctx, kind, items, backend,
|
|
|
15209
16279
|
found[entry2.index] = { edge: rowToEdge(entry2.row), action: "found" };
|
|
15210
16280
|
}
|
|
15211
16281
|
for (const { index, sourceIndex } of probe.duplicateOf) {
|
|
15212
|
-
found[index] = {
|
|
16282
|
+
found[index] = {
|
|
16283
|
+
edge: requireDefined(found[sourceIndex]).edge,
|
|
16284
|
+
action: "found"
|
|
16285
|
+
};
|
|
15213
16286
|
}
|
|
15214
16287
|
return found;
|
|
15215
16288
|
}
|
|
@@ -15228,7 +16301,7 @@ async function executeEdgeBulkGetOrCreateByEndpoints(ctx, kind, items, backend,
|
|
|
15228
16301
|
);
|
|
15229
16302
|
for (const [batchIndex, entry2] of toCreate.entries()) {
|
|
15230
16303
|
results[entry2.index] = {
|
|
15231
|
-
edge: createdEdges[batchIndex],
|
|
16304
|
+
edge: requireDefined(createdEdges[batchIndex]),
|
|
15232
16305
|
action: "created"
|
|
15233
16306
|
};
|
|
15234
16307
|
}
|
|
@@ -15270,12 +16343,14 @@ async function executeEdgeBulkGetOrCreateByEndpoints(ctx, kind, items, backend,
|
|
|
15270
16343
|
}
|
|
15271
16344
|
}
|
|
15272
16345
|
for (const { index, sourceIndex } of duplicateOf) {
|
|
15273
|
-
const sourceResult = results[sourceIndex];
|
|
16346
|
+
const sourceResult = requireDefined(results[sourceIndex]);
|
|
15274
16347
|
results[index] = { edge: sourceResult.edge, action: "found" };
|
|
15275
16348
|
}
|
|
15276
16349
|
return results;
|
|
15277
16350
|
});
|
|
15278
16351
|
}
|
|
16352
|
+
|
|
16353
|
+
// src/store/recorded-read-service.ts
|
|
15279
16354
|
var RECORDED_POINT_READ_FIXED_BIND_PARAMS = 8;
|
|
15280
16355
|
function recordedPointReadIdChunk(backend) {
|
|
15281
16356
|
const budget = recordedBindParamBudget(backend);
|
|
@@ -15291,12 +16366,13 @@ function withRelationsPrecondition(backend, promise, surface) {
|
|
|
15291
16366
|
);
|
|
15292
16367
|
}
|
|
15293
16368
|
function createRecordedReadBackend(backend, surface) {
|
|
15294
|
-
|
|
16369
|
+
const projectedBackend = createGraphBackendProjection(backend);
|
|
16370
|
+
return createBackendOverlay(projectedBackend, {
|
|
15295
16371
|
execute: (query) => withRelationsPrecondition(backend, backend.execute(query), surface),
|
|
15296
16372
|
...backend.executeRaw === void 0 ? {} : {
|
|
15297
16373
|
executeRaw: (sqlText, params) => withRelationsPrecondition(
|
|
15298
16374
|
backend,
|
|
15299
|
-
backend.executeRaw(sqlText, params),
|
|
16375
|
+
requireDefined(backend.executeRaw)(sqlText, params),
|
|
15300
16376
|
surface
|
|
15301
16377
|
)
|
|
15302
16378
|
}
|
|
@@ -15604,9 +16680,6 @@ function wrapTransactionCollections(nodes, edges, recorder) {
|
|
|
15604
16680
|
};
|
|
15605
16681
|
}
|
|
15606
16682
|
|
|
15607
|
-
// src/store/types.ts
|
|
15608
|
-
var AUTO_REFRESH_STATISTICS_ROW_THRESHOLD = 1e3;
|
|
15609
|
-
|
|
15610
16683
|
// src/store/store.ts
|
|
15611
16684
|
var UNKNOWN_SCHEMA_METADATA = Object.freeze({
|
|
15612
16685
|
schemaVersion: void 0,
|
|
@@ -15633,8 +16706,12 @@ var CAUGHT_UP_VERB_DETAILS = {
|
|
|
15633
16706
|
code: "REEMBED_BEFORE_INITIALIZE"
|
|
15634
16707
|
}
|
|
15635
16708
|
};
|
|
16709
|
+
var ROW_MAPPER_CONFIGS = {
|
|
16710
|
+
postgres: POSTGRES_ROW_MAPPER_CONFIG,
|
|
16711
|
+
sqlite: SQLITE_ROW_MAPPER_CONFIG
|
|
16712
|
+
};
|
|
15636
16713
|
function rowMapperConfigFor(backend) {
|
|
15637
|
-
return backend.dialect
|
|
16714
|
+
return ROW_MAPPER_CONFIGS[backend.dialect];
|
|
15638
16715
|
}
|
|
15639
16716
|
function asError(error) {
|
|
15640
16717
|
return error instanceof Error ? error : new Error(String(error));
|
|
@@ -15649,7 +16726,18 @@ function transactionOutcome(result, recorder, recordedByGraph, graphId) {
|
|
|
15649
16726
|
)
|
|
15650
16727
|
};
|
|
15651
16728
|
}
|
|
15652
|
-
|
|
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];
|
|
15653
16741
|
#graph;
|
|
15654
16742
|
/**
|
|
15655
16743
|
* Bare backend for DDL, vector-storage, and bulk-materialization work that must
|
|
@@ -15657,6 +16745,7 @@ var Store = class _Store {
|
|
|
15657
16745
|
*/
|
|
15658
16746
|
#baseBackend;
|
|
15659
16747
|
#backend;
|
|
16748
|
+
#adapterBackend;
|
|
15660
16749
|
#captureEnabled;
|
|
15661
16750
|
#revisionTrackingEnabled;
|
|
15662
16751
|
#revisionOrigin;
|
|
@@ -15676,9 +16765,10 @@ var Store = class _Store {
|
|
|
15676
16765
|
#edgeCollections;
|
|
15677
16766
|
#algorithms;
|
|
15678
16767
|
#search;
|
|
15679
|
-
constructor(graph, backend, options, schemaMetadata) {
|
|
16768
|
+
constructor(graph, backend, options, schemaMetadata, adapterBackend) {
|
|
15680
16769
|
this.#graph = graph;
|
|
15681
16770
|
this.#baseBackend = asRawBackend(backend);
|
|
16771
|
+
this.#adapterBackend = adapterBackend;
|
|
15682
16772
|
this.#captureEnabled = options?.history === true;
|
|
15683
16773
|
this.#revisionTrackingEnabled = this.#captureEnabled || options?.revisionTracking === true;
|
|
15684
16774
|
if (this.#revisionTrackingEnabled) {
|
|
@@ -15715,6 +16805,21 @@ var Store = class _Store {
|
|
|
15715
16805
|
this.#defaultTraversalExpansion = options?.queryDefaults?.traversalExpansion ?? "inverse";
|
|
15716
16806
|
this.#options = options;
|
|
15717
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
|
+
});
|
|
15718
16823
|
}
|
|
15719
16824
|
// === Accessors ===
|
|
15720
16825
|
/** The graph definition */
|
|
@@ -15725,14 +16830,14 @@ var Store = class _Store {
|
|
|
15725
16830
|
get graphId() {
|
|
15726
16831
|
return this.#graph.id;
|
|
15727
16832
|
}
|
|
16833
|
+
/** Runtime features available through this store's configured backend. */
|
|
16834
|
+
get capabilities() {
|
|
16835
|
+
return this.#baseBackend.capabilities;
|
|
16836
|
+
}
|
|
15728
16837
|
/** The kind registry for ontology lookups */
|
|
15729
16838
|
get registry() {
|
|
15730
16839
|
return this.#registry;
|
|
15731
16840
|
}
|
|
15732
|
-
/** The database backend */
|
|
15733
|
-
get backend() {
|
|
15734
|
-
return this.#backend;
|
|
15735
|
-
}
|
|
15736
16841
|
/**
|
|
15737
16842
|
* Whether recorded-time capture is enabled for this store.
|
|
15738
16843
|
*
|
|
@@ -15937,7 +17042,7 @@ var Store = class _Store {
|
|
|
15937
17042
|
*/
|
|
15938
17043
|
getNodePropsSchema(kind) {
|
|
15939
17044
|
if (!Object.hasOwn(this.#graph.nodes, kind)) return void 0;
|
|
15940
|
-
return this.#graph.nodes[kind].type.schema;
|
|
17045
|
+
return requireDefined(this.#graph.nodes[kind]).type.schema;
|
|
15941
17046
|
}
|
|
15942
17047
|
/**
|
|
15943
17048
|
* Returns the Zod props schema for the given node kind. Throws
|
|
@@ -15958,7 +17063,7 @@ var Store = class _Store {
|
|
|
15958
17063
|
*/
|
|
15959
17064
|
getEdgePropsSchema(kind) {
|
|
15960
17065
|
if (!Object.hasOwn(this.#graph.edges, kind)) return void 0;
|
|
15961
|
-
return this.#graph.edges[kind].type.schema;
|
|
17066
|
+
return requireDefined(this.#graph.edges[kind]).type.schema;
|
|
15962
17067
|
}
|
|
15963
17068
|
/**
|
|
15964
17069
|
* Returns the Zod props schema for the given edge kind. Throws
|
|
@@ -16572,15 +17677,21 @@ var Store = class _Store {
|
|
|
16572
17677
|
edges,
|
|
16573
17678
|
// No real transaction: `tx.sql` is absent and there is no atomicity.
|
|
16574
17679
|
sqlAvailability: "unavailable",
|
|
16575
|
-
backend: this.#backend,
|
|
16576
|
-
|
|
16577
|
-
|
|
16578
|
-
|
|
16579
|
-
|
|
16580
|
-
|
|
16581
|
-
|
|
16582
|
-
|
|
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)
|
|
16583
17689
|
};
|
|
17690
|
+
Object.defineProperty(fallbackContext, TRANSACTION_RUNTIME, {
|
|
17691
|
+
configurable: false,
|
|
17692
|
+
enumerable: false,
|
|
17693
|
+
writable: false
|
|
17694
|
+
});
|
|
16584
17695
|
const result = await invoke(
|
|
16585
17696
|
receiptRecorder === void 0 ? fallbackContext : this.#attachMeasure(fallbackContext)
|
|
16586
17697
|
);
|
|
@@ -16593,15 +17704,19 @@ var Store = class _Store {
|
|
|
16593
17704
|
recordedByGraph = instants;
|
|
16594
17705
|
}) : backendOptions;
|
|
16595
17706
|
try {
|
|
16596
|
-
const
|
|
16597
|
-
|
|
16598
|
-
|
|
16599
|
-
|
|
16600
|
-
|
|
16601
|
-
|
|
16602
|
-
|
|
16603
|
-
|
|
16604
|
-
|
|
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),
|
|
16605
17720
|
transactionOptions
|
|
16606
17721
|
);
|
|
16607
17722
|
for (const outcome of pending) {
|
|
@@ -16618,12 +17733,86 @@ var Store = class _Store {
|
|
|
16618
17733
|
throw error;
|
|
16619
17734
|
}
|
|
16620
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
|
+
*/
|
|
16621
17810
|
withTransaction(externalTx) {
|
|
16622
17811
|
if (this.#captureEnabled) {
|
|
16623
17812
|
throw recordedCaptureRequiresCallbackTransactionError();
|
|
16624
17813
|
}
|
|
16625
|
-
const adopt = this.#
|
|
16626
|
-
if (
|
|
17814
|
+
const adopt = this.#adapterBackend?.adoptTransaction;
|
|
17815
|
+
if (adopt === void 0) {
|
|
16627
17816
|
throw new ConfigurationError(
|
|
16628
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.",
|
|
16629
17818
|
{ capability: "adoptTransaction" }
|
|
@@ -16632,8 +17821,8 @@ var Store = class _Store {
|
|
|
16632
17821
|
return this.#buildTransactionContext(adopt(externalTx), externalTx);
|
|
16633
17822
|
}
|
|
16634
17823
|
async withRecordedTransaction(externalTx, fn) {
|
|
16635
|
-
const adopt = this.#
|
|
16636
|
-
if (
|
|
17824
|
+
const adopt = this.#adapterBackend?.adoptTransaction;
|
|
17825
|
+
if (adopt === void 0) {
|
|
16637
17826
|
throw new ConfigurationError(
|
|
16638
17827
|
"This backend cannot adopt an external transaction for recorded-time capture.",
|
|
16639
17828
|
{ capability: "adoptTransaction" },
|
|
@@ -16694,16 +17883,17 @@ var Store = class _Store {
|
|
|
16694
17883
|
context.edges,
|
|
16695
17884
|
scopeRecorder
|
|
16696
17885
|
);
|
|
16697
|
-
const scoped = this.#attachMeasure(
|
|
16698
|
-
|
|
16699
|
-
|
|
16700
|
-
|
|
16701
|
-
|
|
16702
|
-
|
|
17886
|
+
const scoped = this.#attachMeasure(
|
|
17887
|
+
overlayPropertyDescriptors(context, {
|
|
17888
|
+
nodes,
|
|
17889
|
+
edges,
|
|
17890
|
+
getNodeCollection: (kind) => this.#resolveDynamicNodeCollection(nodes, kind)
|
|
17891
|
+
})
|
|
17892
|
+
);
|
|
16703
17893
|
const result = await fn(scoped);
|
|
16704
17894
|
return { result, receipt: scopeRecorder.snapshot() };
|
|
16705
17895
|
};
|
|
16706
|
-
return
|
|
17896
|
+
return overlayPropertyDescriptors(context, { measure });
|
|
16707
17897
|
}
|
|
16708
17898
|
/**
|
|
16709
17899
|
* Builds the `{ nodes, edges, sql }` projection bound to a
|
|
@@ -16715,7 +17905,7 @@ var Store = class _Store {
|
|
|
16715
17905
|
* (#140); when history capture is enabled it is replaced with a fail-loud
|
|
16716
17906
|
* guard because raw graph writes would bypass recorded-time capture.
|
|
16717
17907
|
*/
|
|
16718
|
-
#buildTransactionContext(txBackend,
|
|
17908
|
+
#buildTransactionContext(txBackend, sql2, runHooks = this.#immediateHookRunner(), receiptRecorder) {
|
|
16719
17909
|
const txNodeOperations = {
|
|
16720
17910
|
...this.#buildNodeOperations(this.#createNodeOperationContext(runHooks)),
|
|
16721
17911
|
createQuery: () => this.#createQueryForBackend(txBackend),
|
|
@@ -16749,19 +17939,40 @@ var Store = class _Store {
|
|
|
16749
17939
|
));
|
|
16750
17940
|
}
|
|
16751
17941
|
const getNodeCollection = (kind) => this.#resolveDynamicNodeCollection(nodes, kind);
|
|
16752
|
-
const sqlAvailability = this.#captureEnabled ? "history" : this.#revisionTrackingEnabled ? "revisionTracking" : sql19 === void 0 ? "unavailable" : "available";
|
|
16753
17942
|
const base = {
|
|
16754
17943
|
nodes,
|
|
16755
17944
|
edges,
|
|
16756
|
-
|
|
16757
|
-
backend: txBackend,
|
|
16758
|
-
getNodeCollection
|
|
16759
|
-
runNodeOperationHooks
|
|
16760
|
-
};
|
|
16761
|
-
const withSql = sql19 === void 0 ? base : {
|
|
16762
|
-
...base,
|
|
16763
|
-
sql: this.#captureEnabled ? createHistoryUnsafeSqlRef() : this.#revisionTrackingEnabled ? createRevisionTrackingUnsafeSqlRef() : sql19
|
|
17945
|
+
backend: createTransactionReadBackend(txBackend),
|
|
17946
|
+
[TRANSACTION_RUNTIME]: { backend: txBackend, runNodeOperationHooks },
|
|
17947
|
+
getNodeCollection
|
|
16764
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
|
+
});
|
|
16765
17976
|
return receiptRecorder === void 0 ? withSql : this.#attachMeasure(withSql);
|
|
16766
17977
|
}
|
|
16767
17978
|
// === Graph Lifecycle ===
|
|
@@ -16913,7 +18124,7 @@ var Store = class _Store {
|
|
|
16913
18124
|
const merged = mergeGraphExtension(baseline, extension);
|
|
16914
18125
|
if (merged === baseline) {
|
|
16915
18126
|
if (baseline === this.#graph) {
|
|
16916
|
-
|
|
18127
|
+
syncStoreReplacementRef(options?.ref, this);
|
|
16917
18128
|
if (options?.eager !== void 0) {
|
|
16918
18129
|
await this.#runEagerOrThrow(this, options.eager);
|
|
16919
18130
|
}
|
|
@@ -17260,7 +18471,7 @@ var Store = class _Store {
|
|
|
17260
18471
|
const plan = planRemovals(baseline, names);
|
|
17261
18472
|
if (plan.removedNodeKinds.length === 0 && plan.removedEdgeKinds.length === 0) {
|
|
17262
18473
|
if (baseline === this.#graph) {
|
|
17263
|
-
|
|
18474
|
+
syncStoreReplacementRef(options?.ref, this);
|
|
17264
18475
|
return this;
|
|
17265
18476
|
}
|
|
17266
18477
|
return this.#cloneWithGraph(
|
|
@@ -17351,7 +18562,7 @@ var Store = class _Store {
|
|
|
17351
18562
|
}
|
|
17352
18563
|
if (setsEqual(nextSet, baseline.deprecatedKinds)) {
|
|
17353
18564
|
if (baseline === this.#graph) {
|
|
17354
|
-
|
|
18565
|
+
syncStoreReplacementRef(options?.ref, this);
|
|
17355
18566
|
return this;
|
|
17356
18567
|
}
|
|
17357
18568
|
return this.#cloneWithGraph(
|
|
@@ -17443,13 +18654,18 @@ var Store = class _Store {
|
|
|
17443
18654
|
return nonEmpty;
|
|
17444
18655
|
}
|
|
17445
18656
|
#cloneWithGraph(graph, ref, schemaMetadata = this.#schemaMetadata) {
|
|
17446
|
-
const next = new
|
|
18657
|
+
const next = this.#adapterBackend === void 0 ? new _StoreImplementation(
|
|
17447
18658
|
graph,
|
|
17448
18659
|
this.#baseBackend,
|
|
17449
18660
|
this.#options,
|
|
17450
18661
|
schemaMetadata
|
|
18662
|
+
) : new AdapterStoreImplementation(
|
|
18663
|
+
graph,
|
|
18664
|
+
this.#adapterBackend,
|
|
18665
|
+
this.#options,
|
|
18666
|
+
schemaMetadata
|
|
17451
18667
|
);
|
|
17452
|
-
|
|
18668
|
+
syncStoreReplacementRef(ref, next);
|
|
17453
18669
|
return next;
|
|
17454
18670
|
}
|
|
17455
18671
|
/**
|
|
@@ -17591,8 +18807,100 @@ var Store = class _Store {
|
|
|
17591
18807
|
);
|
|
17592
18808
|
}
|
|
17593
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
|
+
}
|
|
17594
18897
|
function createStore(graph, backend, options) {
|
|
17595
|
-
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
|
+
);
|
|
17596
18904
|
}
|
|
17597
18905
|
function isKnownEdgeKind(graph, name) {
|
|
17598
18906
|
return Object.hasOwn(graph.edges, name);
|
|
@@ -17637,6 +18945,18 @@ async function materializeVectorContributions(backend, graph) {
|
|
|
17637
18945
|
}
|
|
17638
18946
|
}
|
|
17639
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) {
|
|
17640
18960
|
const {
|
|
17641
18961
|
graph: merged,
|
|
17642
18962
|
activeRow,
|
|
@@ -17651,13 +18971,25 @@ async function createStoreWithSchema(graph, backend, options) {
|
|
|
17651
18971
|
if (options?.systemIndexes !== "skip") {
|
|
17652
18972
|
await materializeSystemIndexesOnBoot(backend, merged.id, result);
|
|
17653
18973
|
}
|
|
17654
|
-
|
|
17655
|
-
merged,
|
|
17656
|
-
|
|
17657
|
-
|
|
17658
|
-
|
|
17659
|
-
|
|
17660
|
-
|
|
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
|
+
];
|
|
17661
18993
|
}
|
|
17662
18994
|
async function materializeSystemIndexesOnBoot(backend, graphId, result) {
|
|
17663
18995
|
if (result.status === "breaking") return;
|
|
@@ -17684,20 +19016,44 @@ async function materializeSystemIndexesOnBoot(backend, graphId, result) {
|
|
|
17684
19016
|
}
|
|
17685
19017
|
}
|
|
17686
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) {
|
|
17687
19031
|
const {
|
|
17688
19032
|
graph: merged,
|
|
17689
19033
|
activeRow,
|
|
17690
19034
|
result
|
|
17691
19035
|
} = await loadAndVerifyGraph(backend, graph);
|
|
17692
|
-
|
|
17693
|
-
merged,
|
|
17694
|
-
|
|
17695
|
-
|
|
17696
|
-
|
|
17697
|
-
|
|
17698
|
-
|
|
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
|
+
];
|
|
17699
19055
|
}
|
|
17700
19056
|
|
|
17701
|
-
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 };
|
|
17702
|
-
//# sourceMappingURL=chunk-
|
|
17703
|
-
//# 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
|