gemini-search

A simple search engine for Geminispace
git clone git://git.laack.co/gemini-search.git
Log | Files | Refs | README

sqlite3_opt_serialize.go (1810B)


      1 //go:build !libsqlite3 || sqlite_serialize
      2 // +build !libsqlite3 sqlite_serialize
      3 
      4 package sqlite3
      5 
      6 /*
      7 #ifndef USE_LIBSQLITE3
      8 #include "sqlite3-binding.h"
      9 #else
     10 #include <sqlite3.h>
     11 #endif
     12 #include <stdlib.h>
     13 #include <stdint.h>
     14 */
     15 import "C"
     16 
     17 import (
     18 	"fmt"
     19 	"math"
     20 	"unsafe"
     21 )
     22 
     23 // Serialize returns a byte slice that is a serialization of the database.
     24 //
     25 // See https://www.sqlite.org/c3ref/serialize.html
     26 func (c *SQLiteConn) Serialize(schema string) ([]byte, error) {
     27 	if schema == "" {
     28 		schema = "main"
     29 	}
     30 	var zSchema *C.char
     31 	zSchema = C.CString(schema)
     32 	defer C.free(unsafe.Pointer(zSchema))
     33 
     34 	var sz C.sqlite3_int64
     35 	ptr := C.sqlite3_serialize(c.db, zSchema, &sz, 0)
     36 	if ptr == nil {
     37 		return nil, fmt.Errorf("serialize failed")
     38 	}
     39 	defer C.sqlite3_free(unsafe.Pointer(ptr))
     40 
     41 	if sz > C.sqlite3_int64(math.MaxInt) {
     42 		return nil, fmt.Errorf("serialized database is too large (%d bytes)", sz)
     43 	}
     44 
     45 	res := make([]byte, int(sz))
     46 	copy(res, unsafe.Slice((*byte)(unsafe.Pointer(ptr)), int(sz)))
     47 	return res, nil
     48 }
     49 
     50 // Deserialize causes the connection to disconnect from the current database and
     51 // then re-open as an in-memory database based on the contents of the byte slice.
     52 //
     53 // See https://www.sqlite.org/c3ref/deserialize.html
     54 func (c *SQLiteConn) Deserialize(b []byte, schema string) error {
     55 	if schema == "" {
     56 		schema = "main"
     57 	}
     58 	var zSchema *C.char
     59 	zSchema = C.CString(schema)
     60 	defer C.free(unsafe.Pointer(zSchema))
     61 
     62 	tmpBuf := (*C.uchar)(C.sqlite3_malloc64(C.sqlite3_uint64(len(b))))
     63 	copy(unsafe.Slice((*byte)(unsafe.Pointer(tmpBuf)), len(b)), b)
     64 
     65 	rc := C.sqlite3_deserialize(c.db, zSchema, tmpBuf, C.sqlite3_int64(len(b)),
     66 		C.sqlite3_int64(len(b)), C.SQLITE_DESERIALIZE_FREEONCLOSE)
     67 	if rc != C.SQLITE_OK {
     68 		return fmt.Errorf("deserialize failed with return %v", rc)
     69 	}
     70 	return nil
     71 }