Repository navigation
Text graphs end to end (M10 step 4) - #60
Merged
Merged
Conversation
…the pool pg_warren's generic parameter is now the id map's key storage (FixedKeys<E> or TextKeys): IdDatum converts datums and keys, StoredIds writes and reads an id map's segments (a text id map's id_bytes, id_offsets and id_order), and CachedIds places and views them in a region. The build maps each batch of edge rows on the compute pool (warren-core's EdgeBatch), its text index charged to the build budget; per-call bulk lookups index a text id map past 65,536 ids, charged to the call's compute memory. The compute pool moves to interrupts::pool so the build can use it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
…er a text graph test/sql/text_ids.sql runs every id-mapping function on a text graph and on the same graph with bigint ids, whose ids sort alike, and compares the results; pg_tests cover create_graph's text checks, a text build's segments and stable ids, and the datum's encoding check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
…shared cache Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
… 54000 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
…pts::pool Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
The map runs on the rayon pool, whose work stealing runs through crossbeam-epoch, which Miri's Stacked Borrows model rejects (as for the compute pool's other tests); under Miri the batch tests take the unmapped path only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
Case a with IRIs and with bigint ids at 5M nodes and 50M edges, private and shared: the full scale needs about 16 GB of free disk, which the machine did not have. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
The collector compared the batch's capacity, which the rows' fixed columns already filled, with its whole share of the budget, so a text build below about 124 MiB, or an int8 build at a budget its rows filled exactly, mapped every row once one text id had grown the batch. Half the share is now the rows', the rest their text ids', compared by the bytes the ids hold; an emptied batch frees text room past that share. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
Past 65,536 lookups a call was refused with 53400 when its compute memory had no room for the hash index, though the binary search it used until then needs none; it now keeps the search for the rest of the call. An index that fails to build is raised with its GraphError's SQLSTATE. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
…ed ids within a batch id_in_place and text_in_place were safe functions whose results could outlive the rows' memory context, which holds what detoasting them allocated. for_each_tuple now lends each row as a source::Row whose in-place reads borrow it for one call, and resets the context within a batch once it holds 64 MB, so long toasted ids no longer pile up uncharged until the batch's 10,000 rows end. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
Errors that name an id (a node with two rows in vector_from_query, a negative weight in a community detection) embedded the whole id, and naming a text id built a datum, which checks its encoding and length: an invalid id would have hidden the error it was named in. IdDatum::named clips a text id on a character boundary and checks nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
A bigint graph's char(5) endpoint was refused with a hint to cast it to text; it is now refused as of the wrong type, as any other. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
…oss encodings shared_cache_parallel_text.sql runs a text graph's PARALLEL SAFE reads in a worker and compares them with the leader's; text_ids_sql_ascii.sql maps ids that are not UTF-8 in a SQL_ASCII database; dump.py restores a text graph from a UTF8 database into a LATIN1 one and checks that reading it is refused with 55000. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
wfaithfull
pushed a commit
that referenced
this pull request
Oct 23, 2026
Conflicts: the loader's fill takes main's per-id-type sinks and still reports the bytes copied; the build's imports and intake keep main's batched mapping, with the row counts and CSR reporting around it; interrupts keeps main's pool module and the Progress adapter; imports of CachedIds beside activity's; DESIGN.md's "built so far" lists step 4 and step 9. sql/pg_warren--0.6.0.sql regenerated with sql/schema-drift.sh --update. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
M10 step 4 (DESIGN.md §5.7, §14 item 41):
textnode ids work everywhere an external id is mapped, built on theTextKeysid map that merged in #58. Design decisions and deviations are recorded in §5.7, "Built (step 4)".What changes
FixedKeys<i32>,FixedKeys<i64>,FixedKeys<[u8; 16]>andTextKeys. The oldIdDatumtrait is split by concern into four:source::IdDatumsource::InPlaceIdsegment::StoredIdscache::CachedIdsid_bytes,id_offsetsandid_ordersegments. In a shared-cache region these are arrays 7–9; the region format is still 1.EdgeBatch, 65,536 rows or 1/32 of the build budget). Each batch's endpoints are mapped on the compute pool, through aTextIndexcharged to the build budget. A property test checks that this gives exactly the row-by-row edge list.compute_sqltointerrupts::pool, sobuildcan use it. CLAUDE.md's dependency list gainsinterrupts→build.warren.max_compute_memory(80 MB at 10M nodes). This applies to:vector_from_querygather's messagessimilarity's pairstextvalue is built: 22021 if it is invalid, 54000 if it is longer than atextcan hold. A load checks only theid_bytesheader's encoding (55000), so a version restored into a database with another encoding is refused.Tests
test/sql/text_ids.sql: runs every function that maps ids on a text graph and on the same graph withbigintids, and compares the results.a4_typed_retrieval_iris.sql: the Appendix A.4 use case written with IRIs, checked against recursive CTEs.shared_cache_text.sql: shares a text version across backends.dump.pyandupgrade.pynow cover a text graph.soak.py --ids textis new.Run locally:
run.py: 55/55 plain, 55/55--trusted, 55/55--shared-cache preload.dump.pyandupgrade.pypass.Soak: 5M nodes, 50M edges (half scale for disk, §12)
refreshbfsdepth 6similarity, 100k pairspagerankpagerankgap is probably noise: the machine had a load average of 2–4.Generated by Claude Code