diff --git a/cmd/lure-api-server/api.go b/cmd/lure-api-server/api.go index f45ac4e..5e18e86 100644 --- a/cmd/lure-api-server/api.go +++ b/cmd/lure-api-server/api.go @@ -19,7 +19,7 @@ type lureWebAPI struct { } func (l lureWebAPI) Search(ctx context.Context, req *api.SearchRequest) (*api.SearchResponse, error) { - query := "(name LIKE ? OR description LIKE ? OR provides.value = ?)" + query := "(name LIKE ? OR description LIKE ? OR json_array_contains(provides, ?))" args := []any{"%" + req.Query + "%", "%" + req.Query + "%", req.Query} if req.FilterValue != nil && req.FilterType != api.FILTER_TYPE_NO_FILTER { diff --git a/cmd/lure-api-server/db.go b/cmd/lure-api-server/db.go index 68ad5c7..265a829 100644 --- a/cmd/lure-api-server/db.go +++ b/cmd/lure-api-server/db.go @@ -1,17 +1,30 @@ package main import ( + "os" + "github.com/jmoiron/sqlx" "go.arsenm.dev/logger/log" "go.arsenm.dev/lure/internal/config" "go.arsenm.dev/lure/internal/db" - _ "modernc.org/sqlite" + "modernc.org/sqlite" ) var gdb *sqlx.DB func init() { - var err error + fi, err := os.Stat(config.DBPath) + if err != nil { + log.Fatal("Cannot stat database path").Err(err).Send() + } + + // TODO: This should be removed by the first stable release. + if fi.IsDir() { + log.Fatal("Your package cache database is using the old database engine. Please remove ~/.cache/lure and then run `lure ref`.").Send() + } + + sqlite.MustRegisterScalarFunction("json_array_contains", 2, db.JsonArrayContains) + gdb, err = sqlx.Open("sqlite", config.DBPath) if err != nil { log.Fatal("Error opening database").Err(err).Send() diff --git a/db.go b/db.go index 5ad661a..265a829 100644 --- a/db.go +++ b/db.go @@ -7,7 +7,7 @@ import ( "go.arsenm.dev/logger/log" "go.arsenm.dev/lure/internal/config" "go.arsenm.dev/lure/internal/db" - _ "modernc.org/sqlite" + "modernc.org/sqlite" ) var gdb *sqlx.DB @@ -23,6 +23,8 @@ func init() { log.Fatal("Your package cache database is using the old database engine. Please remove ~/.cache/lure and then run `lure ref`.").Send() } + sqlite.MustRegisterScalarFunction("json_array_contains", 2, db.JsonArrayContains) + gdb, err = sqlx.Open("sqlite", config.DBPath) if err != nil { log.Fatal("Error opening database").Err(err).Send() diff --git a/internal/db/db.go b/internal/db/db.go index 339c6c4..ace2a17 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -8,7 +8,8 @@ import ( "fmt" "github.com/jmoiron/sqlx" - _ "modernc.org/sqlite" + "golang.org/x/exp/slices" + "modernc.org/sqlite" ) // Package is a LURE package's database representation @@ -98,7 +99,7 @@ func InsertPackage(db *sqlx.DB, pkg Package) error { // GetPkgs returns a result containing packages that match the where conditions func GetPkgs(db *sqlx.DB, where string, args ...any) (*sqlx.Rows, error) { - stream, err := db.Queryx("SELECT DISTINCT * FROM pkgs, json_each(pkgs.provides) AS provides WHERE "+where, args...) + stream, err := db.Queryx("SELECT * FROM pkgs WHERE "+where, args...) if err != nil { return nil, err } @@ -108,7 +109,7 @@ func GetPkgs(db *sqlx.DB, where string, args ...any) (*sqlx.Rows, error) { // GetPkg returns a single package that match the where conditions func GetPkg(db *sqlx.DB, where string, args ...any) (*Package, error) { out := &Package{} - err := db.Get(out, "SELECT DISTINCT * FROM pkgs, json_each(pkgs.provides) AS provides WHERE "+where+"LIMIT 1", args...) + err := db.Get(out, "SELECT * FROM pkgs WHERE "+where+"LIMIT 1", args...) return out, err } @@ -118,6 +119,26 @@ func DeletePkgs(db *sqlx.DB, where string, args ...any) error { return err } +func JsonArrayContains(ctx *sqlite.FunctionContext, args []driver.Value) (driver.Value, error) { + value, ok := args[0].(string) + if !ok { + return nil, errors.New("both arguments to json_array_contains must be strings") + } + + item, ok := args[1].(string) + if !ok { + return nil, errors.New("both arguments to json_array_contains must be strings") + } + + var array []string + err := json.Unmarshal([]byte(value), &array) + if err != nil { + return nil, err + } + + return slices.Contains(array, item), nil +} + type JSON[T any] struct { Val T } diff --git a/internal/repos/find.go b/internal/repos/find.go index fa62f07..e080270 100644 --- a/internal/repos/find.go +++ b/internal/repos/find.go @@ -32,7 +32,7 @@ func FindPkgs(gdb *sqlx.DB, pkgs []string) (map[string][]db.Package, []string, e result.Close() if added == 0 { - result, err := db.GetPkgs(gdb, "provides.value = ?", pkgName) + result, err := db.GetPkgs(gdb, "json_array_contains(provides, ?)", pkgName) if err != nil { return nil, nil, err } diff --git a/list.go b/list.go index ef53c32..03a4326 100644 --- a/list.go +++ b/list.go @@ -37,7 +37,7 @@ func listCmd(c *cli.Context) error { where := "true" args := []any(nil) if c.NArg() > 0 { - where = "name LIKE ? OR ? IN provides" + where = "name LIKE ? OR json_array_contains(provides, ?)" args = []any{c.Args().First(), c.Args().First()} }