Skip to content
quarry Artifact [78e85278d3]
Login

Artifact [78e85278d3]

Artifact 78e85278d32dcf9e4816b4497ce23b02a987d77d8a8b3f7b4dffc60c7cc96ba8:


package index

import (
	"context"
	"database/sql"
	sqldriver "database/sql/driver"

	"github.com/ncruces/go-sqlite3"
	"github.com/ncruces/go-sqlite3/driver"
	"github.com/ncruces/go-sqlite3/ext/fts5"
)

// connMaxMemory is how much memory one index connection may use. The
// driver's own ceiling is 256MB per connection (go-sqlite3 wrap.go),
// and a store of millions of artifacts went past it: netbsd-src (2.5M
// artifacts) ran SQLite out of memory folding and opening its index
// (#357). Memory grows only as a connection uses it, so this is a
// ceiling, not a reservation; wasm32 cannot address more than 4GB.
var connMaxMemory int64 = 1 << 30

// openDB opens an index handle whose every connection carries
// connMaxMemory and the fts5 module. The limit travels on the context
// the connection is opened with, which database/sql supplies, so the
// driver's connector is wrapped rather than configured.
func openDB(dsn string) (*sql.DB, error) {
	c, err := (&driver.SQLite{}).OpenConnector(dsn)
	if err != nil {
		return nil, err
	}
	return sql.OpenDB(memConnector{c}), nil
}

type memConnector struct{ inner sqldriver.Connector }

func (m memConnector) Connect(ctx context.Context) (sqldriver.Conn, error) {
	c, err := m.inner.Connect(sqlite3.WithMaxMemory(ctx, connMaxMemory))
	if err != nil {
		return nil, err
	}
	if err := fts5.Register(c.(interface{ Raw() *sqlite3.Conn }).Raw()); err != nil {
		c.Close()
		return nil, err
	}
	return c, nil
}

func (m memConnector) Driver() sqldriver.Driver { return m.inner.Driver() }