Repository navigation
feat: user functions, minigraf_register_predicate/_aggregate (minigraf#180 PR 8) - #13
Merged
Merged
Conversation
…f#180) C user functions per minigraf's UDF spec §6.2, SQLite style: a function pointer, user_data and an optional destroy; results and errors go through a MiniGrafUdfContext. A failing call stops the query with QRY-014. - minigraf_register_predicate, minigraf_register_aggregate (init/step/finish + acc_free), minigraf_udf_error, minigraf_udf_result over the core's try_register_*. Values cross as the fact records' typed JSON. - destroy runs when the last reference drops (after close and every cursor), and on a failed registration. acc_free runs when the query drops the accumulator, including an early minigraf_cursor_free. - Handle locks: every minigraf_* call clones the Minigraf under the handle mutex and releases it before calling the core, so a callback can call back into its own database (it deadlocked before). - Pin minigraf v3 at 02243f16 (#757); the old pin had #181/#316 already. - Consumer contract: one predicate, one aggregate and a QRY-014 failure. - README: User functions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Urda7FD9CYYoxdeGGJa11x
10 tasks done
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.
Plan step 23 of minigraf's
docs/superpowers/plans/2026-10-24-180-udf-uniffi.md(spec §6.1, §6.2). Part of project-minigraf/minigraf#180, which is closed by hand after the Node PR.What
7c8c5540→02243f16(#757), the pin the other bindings use. The old pin already had #181 and #316. #306 (:limit/:order-by) needs no binding change.minigraf_*call clones theMinigrafunderhandle.db.lock()and releases the lock before calling the core (MiniGrafDb::core()). Before this, a callback that called back into its own database deadlocked: the re-entry test hangs with the old lock inminigraf_execute.minigraf_register_predicate(db, name, f, user_data, destroy),minigraf_register_aggregate(db, name, init, step, finish, acc_free, user_data, destroy), overtry_register_predicate/try_register_aggregate.minigraf_udf_error(ctx, msg),minigraf_udf_result(ctx, value_json).MiniGrafUdfContextis a stack value with result/error slots, valid for one call.{"type": "integer", "value": 30}.UserData(user_data+destroy) isunsafe impl Send + Sync, and itsDropcallsdestroy.Accumulator'sDropcallsacc_free. The header states the threading contract.adult?), one aggregate (product,acc_free=free), a failing call →QRY-014, and bothdestroys run at close.Deviations from the spec text
minigraf_udf_errorfails, whatever it returns. The spec only says -1 means failed "afterminigraf_udf_error". This way an error a callback sets is never dropped.user function returned N). The spec does not say what such a code means. Reading it as true would be a silent guess.destroybefore it returns (NULL argument → API-017, a name already taken → INT-040, NULLdb), as in SQLite'ssqlite3_create_function_v2. The spec does not cover this case.minigraf_udf_error(ctx, NULL)setsuser function failed.minigraf_udf_result(ctx, NULL)clears the result, sofinishthen fails withfinish set no result.minigraf_closeon the database it runs on (stated in the header and README).Tests
9 new Rust tests drive the C ABI through
extern "C"callbacks (28 total)::findand:over, with the count passed throughdestroy/acc_freecounts, including a cursor freed before its first batch anddestroywaiting for the last cursor afterminigraf_closedestroyon a failed registrationminigraf_query+minigraf_execute, writes, and registers a predicate on its own databaseChecked locally and on the bench machine:
cargo test,cargo clippy --all-targetsetl_smoke.cbuilt withgcc -std=c99 -Wall -Wextra -WerrorCountsthat the tests leak on purpose withBox::leak.🤖 Generated with Claude Code
https://claude.ai/code/session_01Urda7FD9CYYoxdeGGJa11x