base on Go bindings to SQLite using wazero # Go bindings to SQLite using wazero [![Go Reference](https://pkg.go.dev/badge/image)](https://pkg.go.dev/github.com/ncruces/go-sqlite3) [![Go Report](https://goreportcard.com/badge/github.com/ncruces/go-sqlite3)](https://goreportcard.com/report/github.com/ncruces/go-sqlite3) [![Go Coverage](https://github.com/ncruces/go-sqlite3/wiki/coverage.svg)](https://github.com/ncruces/go-sqlite3/wiki/Test-coverage-report) Go module `github.com/ncruces/go-sqlite3` is a `cgo`-free [SQLite](https://sqlite.org/) wrapper.\ It provides a [`database/sql`](https://pkg.go.dev/database/sql) compatible driver, as well as direct access to most of the [C SQLite API](https://sqlite.org/cintro.html). It wraps a [Wasm](https://webassembly.org/) [build](embed/) of SQLite, and uses [wazero](https://wazero.io/) as the runtime.\ Go, wazero and [`x/sys`](https://pkg.go.dev/golang.org/x/sys) are the _only_ direct dependencies. ### Getting started Using the [`database/sql`](https://pkg.go.dev/database/sql) driver: ```go import "database/sql" import _ "github.com/ncruces/go-sqlite3/driver" import _ "github.com/ncruces/go-sqlite3/embed" var version string db, _ := sql.Open("sqlite3", "file:demo.db") db.QueryRow(`SELECT sqlite_version()`).Scan(&version) ``` ### Packages - [`github.com/ncruces/go-sqlite3`](https://pkg.go.dev/github.com/ncruces/go-sqlite3) wraps the [C SQLite API](https://sqlite.org/cintro.html) ([example](https://pkg.go.dev/github.com/ncruces/go-sqlite3#example-package)). - [`github.com/ncruces/go-sqlite3/driver`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/driver) provides a [`database/sql`](https://pkg.go.dev/database/sql) driver ([example](https://pkg.go.dev/github.com/ncruces/go-sqlite3/driver#example-package)). - [`github.com/ncruces/go-sqlite3/embed`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/embed) embeds a build of SQLite into your application. - [`github.com/ncruces/go-sqlite3/vfs`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs) wraps the [C SQLite VFS API](https://sqlite.org/vfs.html) and provides a pure Go implementation. - [`github.com/ncruces/go-sqlite3/gormlite`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/gormlite) provides a [GORM](https://gorm.io) driver. ### Advanced features - [incremental BLOB I/O](https://sqlite.org/c3ref/blob_open.html) ([example](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/blobio#example-package)) - [nested transactions](https://sqlite.org/lang_savepoint.html) ([example](https://pkg.go.dev/github.com/ncruces/go-sqlite3/driver#example-Savepoint)) - [custom functions](https://sqlite.org/c3ref/create_function.html) ([example](https://pkg.go.dev/github.com/ncruces/go-sqlite3#example-Conn.CreateFunction)) - [virtual tables](https://sqlite.org/vtab.html) ([example](https://pkg.go.dev/github.com/ncruces/go-sqlite3#example-CreateModule)) - [custom VFSes](https://sqlite.org/vfs.html) ([examples](vfs/README.md#custom-vfses)) - [online backup](https://sqlite.org/backup.html) ([example](https://pkg.go.dev/github.com/ncruces/go-sqlite3/driver#Conn)) - [JSON support](https://sqlite.org/json1.html) ([example](https://pkg.go.dev/github.com/ncruces/go-sqlite3/driver#example-package-Json)) - [math functions](https://sqlite.org/lang_mathfunc.html) - [full-text search](https://sqlite.org/fts5.html) - [geospatial search](https://sqlite.org/geopoly.html) - [Unicode support](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/unicode) - [statistics functions](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/stats) - [encryption at rest](vfs/adiantum/README.md) - [many extensions](ext/README.md) - [and more…](embed/README.md) ### Caveats This module replaces the SQLite [OS Interface](https://sqlite.org/vfs.html) (aka VFS) with a [pure Go](vfs/) implementation, which has advantages and disadvantages. Read more about the Go VFS design [here](vfs/README.md). Because each database connection executes within a Wasm sandboxed environment, memory usage will be higher than alternatives. ### Testing This project aims for [high test coverage](https://github.com/ncruces/go-sqlite3/wiki/Test-coverage-report). It also benefits greatly from [SQLite's](https://sqlite.org/testing.html) and [wazero's](https://tetrate.io/blog/introducing-wazero-from-tetrate/#:~:text=Rock%2Dsolid%20test%20approach) thorough testing. Every commit is tested on: * Linux: amd64, arm64, 386, arm, riscv64, ppc64le, loong64, s390x * macOS: amd64, arm64 * Windows: amd64, arm64 * BSD: * FreeBSD: amd64, arm64 * NetBSD: amd64, arm64 * DragonFly BSD: amd64 * OpenBSD: amd64 * illumos: amd64 * Solaris: amd64 Certain operating system and CPU combinations have some limitations. See the [support matrix](https://github.com/ncruces/go-sqlite3/wiki/Support-matrix) for a complete overview. The Go VFS is tested by running SQLite's [mptest](https://github.com/sqlite/sqlite/blob/master/mptest/mptest.c). ### Performance Performance of the [`database/sql`](https://pkg.go.dev/database/sql) driver is [competitive](https://github.com/cvilsmeier/go-sqlite-bench) with alternatives. The Wasm and VFS layers are also benchmarked by running SQLite's [speedtest1](https://github.com/sqlite/sqlite/blob/master/test/speedtest1.c). ### Concurrency This module behaves similarly to SQLite in [multi-thread](https://sqlite.org/threadsafe.html) mode: it is goroutine-safe, provided that no single database connection, or object derived from it, is used concurrently by multiple goroutines. The [`database/sql`](https://pkg.go.dev/database/sql) API is safe to use concurrently, according to its documentation. ### FAQ, issues, new features For questions, please see [Discussions](https://github.com/ncruces/go-sqlite3/discussions/categories/q-a). Also, post there if you used this driver for something interesting ([_"Show and tell"_](https://github.com/ncruces/go-sqlite3/discussions/categories/show-and-tell)), have an [idea](https://github.com/ncruces/go-sqlite3/discussions/categories/ideas)… The [Issue](https://github.com/ncruces/go-sqlite3/issues) tracker is for bugs, and features we're working on, planning to work on, or asking for help with. ### Alternatives - [`modernc.org/sqlite`](https://pkg.go.dev/modernc.org/sqlite) - [`crawshaw.io/sqlite`](https://pkg.go.dev/crawshaw.io/sqlite) - [`github.com/mattn/go-sqlite3`](https://pkg.go.dev/github.com/mattn/go-sqlite3) - [`github.com/zombiezen/go-sqlite`](https://pkg.go.dev/github.com/zombiezen/go-sqlite) ", Assign "at most 3 tags" to the expected json: {"id":"13529","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"