I was able to solve this in the end by writing a virtual table extension. I've published that extension [here](https://github.com/abetlen/sqlite3-bfsvtab-ext). It uses the AVL tree implementation from [ext/misc/closure.c](https://www.sqlite.org/src/file?name=ext/misc/closure.c) to keep an in-memory set of visited nodes. Currently, only integer node IDs are supported, there's also no filtering / ordering on the node neighbour query in the breadth-first search, but I'm planning to include both soon. If anyone has any thoughts / suggestions, please let me know.