So judging from the bytecode examples, the VColumn opcodes in 21-22 should be generated with a P5 of 1 instead of 0, just like the corresponding calls in the direct update. The update from is using a full table scan and checking the primary key against the motable, instead of scanning the motable and doing a lookup in the virtual table. What are the constraints the xBestIndex function is being called with? And what are you returning as cost and estimated number of rows? IMHO you should be returning an estimatedCost of 1, an estimatedRows of 1 and setting the SQLITE_INDEX_SCAN_UNIQUE in idxFlags whenever there is a usable constraint on the primary key, and the number of rows in the table if not.