@@ -57,6 +57,8 @@ import (
5757 "github.com/tailscale/sqlite/sqliteh"
5858)
5959
60+ var emptyStrPtr = (* C .char )(unsafe .Pointer (unsafe .StringData ("" )))
61+
6062func init () {
6163 C .sqlite3_initialize ()
6264}
@@ -68,31 +70,10 @@ type DB struct {
6870 declTypes map [string ]string
6971}
7072
71- // cStmt is a wrapper around an sqlite3 *sqlite3_stmt. Except rather than
72- // storing it as a pointer, it's stored as uintptr to avoid allocations due to
73- // poor interactions between cgo's pointer checker and Go's escape analysis.
74- //
75- // The ptr method returns the value as a pointer, for call sites that haven't
76- // yet been optimized or don't need the optimization. This lets us migrate
77- // incrementally.
78- //
79- // See http://go/corp/9919.
80- type cStmt struct {
81- v C.handle_sqlite3_stmt
82- }
83-
84- // cStmtFromPtr returns a cStmt from a C pointer.
85- func cStmtFromPtr (p * C.sqlite3_stmt ) cStmt {
86- return cStmt {v : C .handle_sqlite3_stmt (uintptr (unsafe .Pointer (p )))}
87- }
88-
89- func (h cStmt ) int () C.handle_sqlite3_stmt { return h .v }
90- func (h cStmt ) ptr () * C.sqlite3_stmt { return (* C .sqlite3_stmt )(unsafe .Pointer (uintptr (h .v ))) }
91-
9273// Stmt implements sqliteh.Stmt.
9374type Stmt struct {
9475 db * DB
95- stmt cStmt
76+ stmt * C. sqlite3_stmt
9677 start C.struct_timespec
9778
9879 // used as scratch space when calling into cgo
@@ -202,7 +183,7 @@ func (db *DB) Prepare(query string, prepFlags sqliteh.PrepareFlags) (stmt sqlite
202183 return nil , "" , err
203184 }
204185 remainingQuery = query [len (query )- int (C .strlen (csqlTail )):]
205- return & Stmt {db : db , stmt : cStmtFromPtr ( cstmt ) }, remainingQuery , nil
186+ return & Stmt {db : db , stmt : cstmt }, remainingQuery , nil
206187}
207188
208189func (db * DB ) DisableFunction (name string , numArgs int ) error {
@@ -212,45 +193,45 @@ func (db *DB) DisableFunction(name string, numArgs int) error {
212193}
213194
214195func (stmt * Stmt ) DBHandle () sqliteh.DB {
215- cdb := C .sqlite3_db_handle (stmt .stmt . ptr () )
196+ cdb := C .sqlite3_db_handle (stmt .stmt )
216197 if cdb != nil {
217198 return & DB {db : cdb }
218199 }
219200 return nil
220201}
221202
222203func (stmt * Stmt ) SQL () string {
223- return C .GoString (C .sqlite3_sql (stmt .stmt . ptr () ))
204+ return C .GoString (C .sqlite3_sql (stmt .stmt ))
224205}
225206
226207func (stmt * Stmt ) ExpandedSQL () string {
227208 // sqlite3_expanded_sql returns a string obtained by sqlite3_malloc, which
228209 // must be freed after use.
229- cstr := C .sqlite3_expanded_sql (stmt .stmt . ptr () )
210+ cstr := C .sqlite3_expanded_sql (stmt .stmt )
230211 defer C .sqlite3_free (unsafe .Pointer (cstr ))
231212 return C .GoString (cstr )
232213}
233214
234215func (stmt * Stmt ) Reset () error {
235- return errCode (C .sqlite3_reset (stmt .stmt . ptr () ))
216+ return errCode (C .sqlite3_reset (stmt .stmt ))
236217}
237218
238219func (stmt * Stmt ) Finalize () error {
239- return errCode (C .sqlite3_finalize (stmt .stmt . ptr () ))
220+ return errCode (C .sqlite3_finalize (stmt .stmt ))
240221}
241222
242223func (stmt * Stmt ) ClearBindings () error {
243- return errCode (C .sqlite3_clear_bindings (stmt .stmt . ptr () ))
224+ return errCode (C .sqlite3_clear_bindings (stmt .stmt ))
244225}
245226
246227func (stmt * Stmt ) ResetAndClear () (time.Duration , error ) {
247228 if stmt .start != (C.struct_timespec {}) {
248229 stmt .duration = 0
249- err := errCode (C .reset_and_clear (stmt .stmt . int () , & stmt .start , & stmt .duration ))
230+ err := errCode (C .reset_and_clear (stmt .stmt , & stmt .start , & stmt .duration ))
250231 return time .Duration (stmt .duration ), err
251232 }
252- if sp := stmt .stmt . int (); sp != 0 {
253- return 0 , errCode (C .reset_and_clear (stmt .stmt . int () , nil , nil ))
233+ if stmt .stmt != nil {
234+ return 0 , errCode (C .reset_and_clear (stmt .stmt , nil , nil ))
254235 }
255236 // The statement was never initialized. This can happen if, for example, the
256237 // parser found only comments (so the statement was not empty, but did not
@@ -263,19 +244,19 @@ func (stmt *Stmt) StartTimer() {
263244}
264245
265246func (stmt * Stmt ) ColumnDatabaseName (col int ) string {
266- return C .GoString ((* C .char )(unsafe .Pointer (C .sqlite3_column_database_name (stmt .stmt . ptr () , C .int (col )))))
247+ return C .GoString ((* C .char )(unsafe .Pointer (C .sqlite3_column_database_name (stmt .stmt , C .int (col )))))
267248}
268249
269250func (stmt * Stmt ) ColumnTableName (col int ) string {
270- return C .GoString ((* C .char )(unsafe .Pointer (C .sqlite3_column_table_name (stmt .stmt . ptr () , C .int (col )))))
251+ return C .GoString ((* C .char )(unsafe .Pointer (C .sqlite3_column_table_name (stmt .stmt , C .int (col )))))
271252}
272253
273254func (stmt * Stmt ) Step (colType []sqliteh.ColumnType ) (row bool , err error ) {
274255 var ptr * C.char
275256 if len (colType ) > 0 {
276257 ptr = (* C .char )(unsafe .Pointer (& colType [0 ]))
277258 }
278- res := C .ts_sqlite3_step (stmt .stmt . int () , ptr , C .int (len (colType )))
259+ res := C .ts_sqlite3_step (stmt .stmt , ptr , C .int (len (colType )))
279260 switch res {
280261 case C .SQLITE_ROW :
281262 return true , nil
@@ -288,7 +269,7 @@ func (stmt *Stmt) Step(colType []sqliteh.ColumnType) (row bool, err error) {
288269
289270func (stmt * Stmt ) StepResult () (row bool , lastInsertRowID , changes int64 , d time.Duration , err error ) {
290271 stmt .rowid , stmt .changes , stmt .duration = 0 , 0 , 0
291- res := C .step_result (stmt .stmt . int () , & stmt .rowid , & stmt .changes , & stmt .duration )
272+ res := C .step_result (stmt .stmt , & stmt .rowid , & stmt .changes , & stmt .duration )
292273 lastInsertRowID = int64 (stmt .rowid )
293274 changes = int64 (stmt .changes )
294275 d = time .Duration (stmt .duration )
@@ -304,51 +285,51 @@ func (stmt *Stmt) StepResult() (row bool, lastInsertRowID, changes int64, d time
304285}
305286
306287func (stmt * Stmt ) BindDouble (col int , val float64 ) error {
307- return errCode (C .ts_sqlite3_bind_double (stmt .stmt . int () , C .int (col ), C .double (val )))
288+ return errCode (C .sqlite3_bind_double (stmt .stmt , C .int (col ), C .double (val )))
308289}
309290
310291func (stmt * Stmt ) BindInt64 (col int , val int64 ) error {
311- return errCode (C .ts_sqlite3_bind_int64 (stmt .stmt . int () , C .int (col ), C .sqlite3_int64 (val )))
292+ return errCode (C .sqlite3_bind_int64 (stmt .stmt , C .int (col ), C .sqlite3_int64 (val )))
312293}
313294
314295func (stmt * Stmt ) BindNull (col int ) error {
315- return errCode (C .ts_sqlite3_bind_null (stmt .stmt . int () , C .int (col )))
296+ return errCode (C .sqlite3_bind_null (stmt .stmt , C .int (col )))
316297}
317298
318299func (stmt * Stmt ) BindText64 (col int , val string ) error {
319300 if len (val ) == 0 {
320- return errCode (C .bind_text64_empty (stmt .stmt . int () , C .int (col )))
301+ return errCode (C .sqlite3_bind_text64 (stmt .stmt , C .int (col ), emptyStrPtr , 0 , C . SQLITE_STATIC , C . SQLITE_UTF8 ))
321302 }
322303 v := C .CString (val ) // freed by sqlite
323- return errCode (C .bind_text64 (stmt .stmt . int () , C .int (col ), v , C .sqlite3_uint64 (len (val ))))
304+ return errCode (C .sqlite3_bind_text64 (stmt .stmt , C .int (col ), v , C .sqlite3_uint64 (len (val )), ( * [ 0 ] byte )( C . free ), C . SQLITE_UTF8 ))
324305}
325306
326307func (stmt * Stmt ) BindZeroBlob64 (col int , n uint64 ) error {
327- return errCode (C .sqlite3_bind_zeroblob64 (stmt .stmt . ptr () , C .int (col ), C .sqlite3_uint64 (n )))
308+ return errCode (C .sqlite3_bind_zeroblob64 (stmt .stmt , C .int (col ), C .sqlite3_uint64 (n )))
328309}
329310
330311func (stmt * Stmt ) BindBlob64 (col int , val []byte ) error {
331312 var str * C.char
332313 if len (val ) > 0 {
333314 str = (* C .char )(unsafe .Pointer (& val [0 ]))
334315 }
335- return errCode (C .bind_blob64 (stmt .stmt . int () , C .int (col ), str , C .sqlite3_uint64 (len (val ))))
316+ return errCode (C .sqlite3_bind_blob64 (stmt .stmt , C .int (col ), unsafe . Pointer ( str ) , C .sqlite3_uint64 (len (val )), C . SQLITE_TRANSIENT ))
336317}
337318
338319func (stmt * Stmt ) BindParameterCount () int {
339- return int (C .sqlite3_bind_parameter_count (stmt .stmt . ptr () ))
320+ return int (C .sqlite3_bind_parameter_count (stmt .stmt ))
340321}
341322
342323func (stmt * Stmt ) BindParameterName (col int ) string {
343- cstr := C .sqlite3_bind_parameter_name (stmt .stmt . ptr () , C .int (col ))
324+ cstr := C .sqlite3_bind_parameter_name (stmt .stmt , C .int (col ))
344325 if cstr == nil {
345326 return ""
346327 }
347328 return C .GoString (cstr )
348329}
349330
350331func (stmt * Stmt ) BindParameterIndex (name string ) int {
351- return int (C .bind_parameter_index (stmt .stmt . int () , name ))
332+ return int (C .bind_parameter_index (stmt .stmt , name ))
352333}
353334
354335func (stmt * Stmt ) BindParameterIndexSearch (name string ) int {
@@ -363,45 +344,45 @@ func (stmt *Stmt) BindParameterIndexSearch(name string) int {
363344}
364345
365346func (stmt * Stmt ) ColumnCount () int {
366- return int (C .sqlite3_column_count (stmt .stmt . ptr () ))
347+ return int (C .sqlite3_column_count (stmt .stmt ))
367348}
368349
369350func (stmt * Stmt ) ColumnName (col int ) string {
370- return C .GoString (C .sqlite3_column_name (stmt .stmt . ptr () , C .int (col )))
351+ return C .GoString (C .sqlite3_column_name (stmt .stmt , C .int (col )))
371352}
372353
373354func (stmt * Stmt ) ColumnText (col int ) string {
374- str := (* C .char )(unsafe .Pointer (C .ts_sqlite3_column_text (stmt .stmt . int () , C .int (col ))))
375- n := C .ts_sqlite3_column_bytes (stmt .stmt . int () , C .int (col ))
355+ str := (* C .char )(unsafe .Pointer (C .sqlite3_column_text (stmt .stmt , C .int (col ))))
356+ n := C .sqlite3_column_bytes (stmt .stmt , C .int (col ))
376357 if str == nil || n == 0 {
377358 return ""
378359 }
379360 return C .GoStringN (str , n )
380361}
381362
382363func (stmt * Stmt ) ColumnBlob (col int ) []byte {
383- res := C .ts_sqlite3_column_blob (stmt .stmt . int () , C .int (col ))
364+ res := C .sqlite3_column_blob (stmt .stmt , C .int (col ))
384365 if res == nil {
385366 return nil
386367 }
387- n := int (C .ts_sqlite3_column_bytes (stmt .stmt . int () , C .int (col )))
368+ n := int (C .sqlite3_column_bytes (stmt .stmt , C .int (col )))
388369 return unsafe .Slice ((* byte )(unsafe .Pointer (res )), n )
389370}
390371
391372func (stmt * Stmt ) ColumnDouble (col int ) float64 {
392- return float64 (C .ts_sqlite3_column_double (stmt .stmt . int () , C .int (col )))
373+ return float64 (C .sqlite3_column_double (stmt .stmt , C .int (col )))
393374}
394375
395376func (stmt * Stmt ) ColumnInt64 (col int ) int64 {
396- return int64 (C .ts_sqlite3_column_int64 (stmt .stmt . int () , C .int (col )))
377+ return int64 (C .sqlite3_column_int64 (stmt .stmt , C .int (col )))
397378}
398379
399380func (stmt * Stmt ) ColumnType (col int ) sqliteh.ColumnType {
400- return sqliteh .ColumnType (C .ts_sqlite3_column_type (stmt .stmt . int () , C .int (col )))
381+ return sqliteh .ColumnType (C .sqlite3_column_type (stmt .stmt , C .int (col )))
401382}
402383
403384func (stmt * Stmt ) ColumnDeclType (col int ) string {
404- cstr := C .sqlite3_column_decltype (stmt .stmt . ptr () , C .int (col ))
385+ cstr := C .sqlite3_column_decltype (stmt .stmt , C .int (col ))
405386 if cstr == nil {
406387 return ""
407388 }
@@ -418,8 +399,6 @@ func (stmt *Stmt) ColumnDeclType(col int) string {
418399 return res
419400}
420401
421- var emptyCStr = C .CString ("" )
422-
423402func errCode (code C.int ) error { return sqliteh .CodeAsError (sqliteh .Code (code )) }
424403
425404// internCache contains interned strings.
0 commit comments