@@ -182,6 +182,19 @@ static int cXRowid(sqlite3_vtab_cursor *pCursor, sqlite3_int64 *pRowid) {
182
182
return SQLITE_OK;
183
183
}
184
184
185
+ char* goVUpdate(void *pVTab, int argc, sqlite3_value **argv, sqlite3_int64 *pRowid);
186
+
187
+ static int cXUpdate(sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, sqlite3_int64 *pRowid) {
188
+ char *pzErr = goVUpdate(((goVTab*)pVTab)->vTab, argc, argv, pRowid);
189
+ if (pzErr) {
190
+ if (pVTab->zErrMsg)
191
+ sqlite3_free(pVTab->zErrMsg);
192
+ pVTab->zErrMsg = pzErr;
193
+ return SQLITE_ERROR;
194
+ }
195
+ return SQLITE_OK;
196
+ }
197
+
185
198
static sqlite3_module goModule = {
186
199
0, // iVersion
187
200
cXCreate, // xCreate - create a table
@@ -196,8 +209,8 @@ static sqlite3_module goModule = {
196
209
cXEof, // xEof
197
210
cXColumn, // xColumn - read data
198
211
cXRowid, // xRowid - read data
212
+ cXUpdate, // xUpdate - write data
199
213
// Not implemented
200
- 0, // xUpdate - write data
201
214
0, // xBegin - begin transaction
202
215
0, // xSync - sync transaction
203
216
0, // xCommit - commit transaction
@@ -218,6 +231,7 @@ static int _sqlite3_create_module(sqlite3 *db, const char *zName, uintptr_t pCli
218
231
import "C"
219
232
220
233
import (
234
+ "fmt"
221
235
"math"
222
236
"reflect"
223
237
"unsafe"
@@ -306,7 +320,7 @@ func orderBys(info *C.sqlite3_index_info) []InfoOrderBy {
306
320
return ob
307
321
}
308
322
309
- // IndexResult is a Go struct represetnation of what eventually ends up in the
323
+ // IndexResult is a Go struct representation of what eventually ends up in the
310
324
// output fields for `sqlite3_index_info`
311
325
// See: https://www.sqlite.org/c3ref/index_info.html
312
326
type IndexResult struct {
@@ -502,6 +516,53 @@ func goVRowid(pCursor unsafe.Pointer, pRowid *C.sqlite3_int64) *C.char {
502
516
return nil
503
517
}
504
518
519
+ //export goVUpdate
520
+ func goVUpdate (pVTab unsafe.Pointer , argc C.int , argv * * C.sqlite3_value , pRowid * C.sqlite3_int64 ) * C.char {
521
+ vt := lookupHandle (uintptr (pVTab )).(* sqliteVTab )
522
+
523
+ var tname string
524
+ if n , ok := vt .vTab .(interface {
525
+ TableName () string
526
+ }); ok {
527
+ tname = n .TableName () + " "
528
+ }
529
+
530
+ err := fmt .Errorf ("virtual %s table %sis read-only" , vt .module .name , tname )
531
+ if v , ok := vt .vTab .(VTabUpdater ); ok {
532
+ // convert argv
533
+ args := (* [(math .MaxInt32 - 1 ) / unsafe .Sizeof ((* C .sqlite3_value )(nil ))]* C.sqlite3_value )(unsafe .Pointer (argv ))[:argc :argc ]
534
+ vals := make ([]interface {}, 0 , argc )
535
+ for _ , v := range args {
536
+ conv , err := callbackArgGeneric (v )
537
+ if err != nil {
538
+ return mPrintf ("%s" , err .Error ())
539
+ }
540
+ vals = append (vals , conv .Interface ())
541
+ }
542
+
543
+ switch {
544
+ case argc == 1 :
545
+ err = v .Delete (vals [0 ])
546
+
547
+ case argc > 1 && vals [0 ] == nil :
548
+ var id int64
549
+ id , err = v .Insert (vals [1 ], vals [2 :])
550
+ if err == nil {
551
+ * pRowid = C .sqlite3_int64 (id )
552
+ }
553
+
554
+ case argc > 1 :
555
+ err = v .Update (vals [1 ], vals [2 :])
556
+ }
557
+ }
558
+
559
+ if err != nil {
560
+ return mPrintf ("%s" , err .Error ())
561
+ }
562
+
563
+ return nil
564
+ }
565
+
505
566
// Module is a "virtual table module", it defines the implementation of a
506
567
// virtual tables. See: http://sqlite.org/c3ref/module.html
507
568
type Module interface {
@@ -526,6 +587,15 @@ type VTab interface {
526
587
Open () (VTabCursor , error )
527
588
}
528
589
590
+ // VTabUpdater is a type that allows a VTab to be inserted, updated, or
591
+ // deleted.
592
+ // See: https://sqlite.org/vtab.html#xupdate
593
+ type VTabUpdater interface {
594
+ Delete (interface {}) error
595
+ Insert (interface {}, []interface {}) (int64 , error )
596
+ Update (interface {}, []interface {}) error
597
+ }
598
+
529
599
// VTabCursor describes cursors that point into the virtual table and are used
530
600
// to loop through the virtual table. See: http://sqlite.org/c3ref/vtab_cursor.html
531
601
type VTabCursor interface {
0 commit comments