@@ -25,7 +25,6 @@ type Conn struct {
25
25
* sqlite
26
26
27
27
interrupt context.Context
28
- pending * Stmt
29
28
stmts []* Stmt
30
29
busy func (context.Context , int ) bool
31
30
log func (xErrorCode , string )
@@ -41,7 +40,9 @@ type Conn struct {
41
40
busylst time.Time
42
41
arena arena
43
42
handle ptr_t
44
- nprogr uint8
43
+ pending ptr_t
44
+ stepped bool
45
+ gosched uint8
45
46
}
46
47
47
48
// 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) {
133
134
}
134
135
}
135
136
if pragmas .Len () != 0 {
136
- c .checkInterrupt (handle )
137
137
pragmaPtr := c .arena .string (pragmas .String ())
138
138
rc := res_t (c .call ("sqlite3_exec" , stk_t (handle ), stk_t (pragmaPtr ), 0 , 0 , 0 ))
139
139
if err := c .sqlite .error (rc , handle , pragmas .String ()); err != nil {
@@ -167,8 +167,8 @@ func (c *Conn) Close() error {
167
167
return nil
168
168
}
169
169
170
- c .pending . Close ( )
171
- c .pending = nil
170
+ c .call ( "sqlite3_finalize" , stk_t ( c . pending ) )
171
+ c .pending = 0
172
172
173
173
rc := res_t (c .call ("sqlite3_close" , stk_t (c .handle )))
174
174
if err := c .error (rc ); err != nil {
@@ -187,7 +187,7 @@ func (c *Conn) Exec(sql string) error {
187
187
defer c .arena .mark ()()
188
188
sqlPtr := c .arena .string (sql )
189
189
190
- c .checkInterrupt (c . handle )
190
+ c .checkInterrupt ()
191
191
rc := res_t (c .call ("sqlite3_exec" , stk_t (c .handle ), stk_t (sqlPtr ), 0 , 0 , 0 ))
192
192
return c .error (rc , sql )
193
193
}
@@ -211,16 +211,16 @@ func (c *Conn) PrepareFlags(sql string, flags PrepareFlag) (stmt *Stmt, tail str
211
211
defer c .arena .mark ()()
212
212
stmtPtr := c .arena .new (ptrlen )
213
213
tailPtr := c .arena .new (ptrlen )
214
- sqlPtr := c .arena .string (sql )
214
+ textPtr := c .arena .string (sql )
215
215
216
- c .checkInterrupt (c . handle )
216
+ c .checkInterrupt ()
217
217
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 ),
219
219
stk_t (stmtPtr ), stk_t (tailPtr )))
220
220
221
- stmt = & Stmt {c : c }
221
+ stmt = & Stmt {c : c , sql : sql }
222
222
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 != "" {
224
224
tail = sql
225
225
}
226
226
@@ -344,40 +344,44 @@ func (c *Conn) SetInterrupt(ctx context.Context) (old context.Context) {
344
344
old = c .interrupt
345
345
c .interrupt = ctx
346
346
347
- if ctx == old || ctx . Done () == old . Done () {
347
+ if ctx == old {
348
348
return old
349
349
}
350
350
351
- // A busy SQL statement prevents SQLite from ignoring an interrupt
351
+ // An active SQL statement prevents SQLite from ignoring an interrupt
352
352
// that comes before any other statements are started.
353
- if c .pending == nil {
353
+ if c .pending == 0 {
354
354
defer c .arena .mark ()()
355
355
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 ,
358
358
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 )
361
360
}
362
361
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 ()
368
367
}
369
368
return old
370
369
}
371
370
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
375
378
}
379
+ c .call ("sqlite3_interrupt" , stk_t (c .handle ))
376
380
}
377
381
378
382
func progressCallback (ctx context.Context , mod api.Module , _ ptr_t ) (interrupt int32 ) {
379
383
if c , ok := ctx .Value (connKey {}).(* Conn ); ok {
380
- if c .nprogr ++ ; c .nprogr % 16 == 0 {
384
+ if c .gosched ++ ; c .gosched % 16 == 0 {
381
385
runtime .Gosched ()
382
386
}
383
387
if c .interrupt .Err () != nil {
0 commit comments