@@ -25,7 +25,6 @@ type Conn struct {
2525 * sqlite
2626
2727 interrupt context.Context
28- pending * Stmt
2928 stmts []* Stmt
3029 busy func (context.Context , int ) bool
3130 log func (xErrorCode , string )
@@ -41,7 +40,9 @@ type Conn struct {
4140 busylst time.Time
4241 arena arena
4342 handle ptr_t
44- nprogr uint8
43+ pending ptr_t
44+ stepped bool
45+ gosched uint8
4546}
4647
4748// Open calls [OpenFlags] with [OPEN_READWRITE], [OPEN_CREATE] and [OPEN_URI].
@@ -133,7 +134,6 @@ func (c *Conn) openDB(filename string, flags OpenFlag) (ptr_t, error) {
133134 }
134135 }
135136 if pragmas .Len () != 0 {
136- c .checkInterrupt (handle )
137137 pragmaPtr := c .arena .string (pragmas .String ())
138138 rc := res_t (c .call ("sqlite3_exec" , stk_t (handle ), stk_t (pragmaPtr ), 0 , 0 , 0 ))
139139 if err := c .sqlite .error (rc , handle , pragmas .String ()); err != nil {
@@ -167,8 +167,8 @@ func (c *Conn) Close() error {
167167 return nil
168168 }
169169
170- c .pending . Close ( )
171- c .pending = nil
170+ c .call ( "sqlite3_finalize" , stk_t ( c . pending ) )
171+ c .pending = 0
172172
173173 rc := res_t (c .call ("sqlite3_close" , stk_t (c .handle )))
174174 if err := c .error (rc ); err != nil {
@@ -187,7 +187,7 @@ func (c *Conn) Exec(sql string) error {
187187 defer c .arena .mark ()()
188188 sqlPtr := c .arena .string (sql )
189189
190- c .checkInterrupt (c . handle )
190+ c .checkInterrupt ()
191191 rc := res_t (c .call ("sqlite3_exec" , stk_t (c .handle ), stk_t (sqlPtr ), 0 , 0 , 0 ))
192192 return c .error (rc , sql )
193193}
@@ -211,16 +211,16 @@ func (c *Conn) PrepareFlags(sql string, flags PrepareFlag) (stmt *Stmt, tail str
211211 defer c .arena .mark ()()
212212 stmtPtr := c .arena .new (ptrlen )
213213 tailPtr := c .arena .new (ptrlen )
214- sqlPtr := c .arena .string (sql )
214+ textPtr := c .arena .string (sql )
215215
216- c .checkInterrupt (c . handle )
216+ c .checkInterrupt ()
217217 rc := res_t (c .call ("sqlite3_prepare_v3" , stk_t (c .handle ),
218- stk_t (sqlPtr ), stk_t (len (sql )+ 1 ), stk_t (flags ),
218+ stk_t (textPtr ), stk_t (len (sql )+ 1 ), stk_t (flags ),
219219 stk_t (stmtPtr ), stk_t (tailPtr )))
220220
221- stmt = & Stmt {c : c }
221+ stmt = & Stmt {c : c , sql : sql }
222222 stmt .handle = util .Read32 [ptr_t ](c .mod , stmtPtr )
223- if sql := sql [util .Read32 [ptr_t ](c .mod , tailPtr )- sqlPtr :]; sql != "" {
223+ if sql := sql [util .Read32 [ptr_t ](c .mod , tailPtr )- textPtr :]; sql != "" {
224224 tail = sql
225225 }
226226
@@ -344,40 +344,44 @@ func (c *Conn) SetInterrupt(ctx context.Context) (old context.Context) {
344344 old = c .interrupt
345345 c .interrupt = ctx
346346
347- if ctx == old || ctx . Done () == old . Done () {
347+ if ctx == old {
348348 return old
349349 }
350350
351- // A busy SQL statement prevents SQLite from ignoring an interrupt
351+ // An active SQL statement prevents SQLite from ignoring an interrupt
352352 // that comes before any other statements are started.
353- if c .pending == nil {
353+ if c .pending == 0 {
354354 defer c .arena .mark ()()
355355 stmtPtr := c .arena .new (ptrlen )
356- loopPtr := c .arena .string (`WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x FROM c) SELECT x FROM c ` )
357- c .call ("sqlite3_prepare_v3" , stk_t (c .handle ), stk_t (loopPtr ), math .MaxUint64 ,
356+ textPtr := c .arena .string (`SELECT 0 UNION ALL SELECT 0 ` )
357+ c .call ("sqlite3_prepare_v3" , stk_t (c .handle ), stk_t (textPtr ), math .MaxUint64 ,
358358 stk_t (PREPARE_PERSISTENT ), stk_t (stmtPtr ), 0 )
359- c .pending = & Stmt {c : c }
360- c .pending .handle = util .Read32 [ptr_t ](c .mod , stmtPtr )
359+ c .pending = util .Read32 [ptr_t ](c .mod , stmtPtr )
361360 }
362361
363- if old . Done () != nil && ctx .Err () == nil {
364- c .pending . Reset ( )
365- }
366- if ctx . Done () != nil {
367- c .pending . Step ()
362+ if c . stepped && ctx .Err () == nil {
363+ c .call ( "sqlite3_reset" , stk_t ( c . pending ) )
364+ c . stepped = false
365+ } else {
366+ c .checkInterrupt ()
368367 }
369368 return old
370369}
371370
372- func (c * Conn ) checkInterrupt (handle ptr_t ) {
373- if c .interrupt .Err () != nil {
374- c .call ("sqlite3_interrupt" , stk_t (handle ))
371+ func (c * Conn ) checkInterrupt () {
372+ if c .interrupt .Err () == nil {
373+ return
374+ }
375+ if ! c .stepped {
376+ c .call ("sqlite3_step" , stk_t (c .pending ))
377+ c .stepped = true
375378 }
379+ c .call ("sqlite3_interrupt" , stk_t (c .handle ))
376380}
377381
378382func progressCallback (ctx context.Context , mod api.Module , _ ptr_t ) (interrupt int32 ) {
379383 if c , ok := ctx .Value (connKey {}).(* Conn ); ok {
380- if c .nprogr ++ ; c .nprogr % 16 == 0 {
384+ if c .gosched ++ ; c .gosched % 16 == 0 {
381385 runtime .Gosched ()
382386 }
383387 if c .interrupt .Err () != nil {
0 commit comments