From a4d86693394ba9b181b5928c1c6e8c31c9bb2b64 Mon Sep 17 00:00:00 2001 From: JP Appel Date: Mon, 30 Jun 2025 17:18:45 -0400 Subject: Implement compiled query execution --- pkg/data/db.go | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pkg/data/get.go | 23 +++++++++++---------- 2 files changed, 75 insertions(+), 10 deletions(-) (limited to 'pkg/data') diff --git a/pkg/data/db.go b/pkg/data/db.go index b4b7f90..24a8793 100644 --- a/pkg/data/db.go +++ b/pkg/data/db.go @@ -3,9 +3,11 @@ package data import ( "context" "database/sql" + "fmt" "strings" "github.com/jpappel/atlas/pkg/index" + "github.com/jpappel/atlas/pkg/query" _ "github.com/mattn/go-sqlite3" ) @@ -202,6 +204,29 @@ func createSchema(db *sql.DB) error { return err } + _, err = tx.Exec(` + CREATE VIEW IF NOT EXISTS Search AS + SELECT + d.id AS docId, + d.path, + d.title, + d.date, + d.fileTime, + d.meta, + COALESCE(a.name, al.alias) AS author, + t.name AS tag + FROM Documents d + LEFT JOIN DocumentAuthors da ON d.id = da.docId + LEFT JOIN Authors a ON da.authorId = a.id + LEFT JOIN Aliases al ON a.id = al.authorId + LEFT JOIN DocumentTags dt ON d.id = dt.docId + LEFT JOIN Tags t ON dt.tagId = t.id + `) + if err != nil { + tx.Rollback() + return err + } + return nil } @@ -254,3 +279,40 @@ func (q Query) GetDocument(path string) (*index.Document, error) { f := Fill{Path: path, Db: q.db} return f.Get(ctx) } + +func (q Query) Execute(artifact query.CompilationArtifact) (map[string]*index.Document, error) { + ctx := context.TODO() + f := FillMany{ + Db: q.db, + docs: make(map[string]*index.Document), + ids: make(map[string]int), + } + + compiledQuery := fmt.Sprintf(` + SELECT DISTINCT docId, path, title, date, fileTime, meta + FROM Search + WHERE %s`, artifact.Query) + + rows, err := q.db.QueryContext(ctx, compiledQuery, artifact.Args...) + if err != nil { + return nil, err + } + + if err := f.documents(ctx, rows); err != nil { + rows.Close() + return nil, err + } + rows.Close() + + if err := f.tags(ctx); err != nil { + return nil, err + } + if err := f.links(ctx); err != nil { + return nil, err + } + if err := f.authors(ctx); err != nil { + return nil, err + } + + return f.docs, nil +} diff --git a/pkg/data/get.go b/pkg/data/get.go index 7cae03a..968789b 100644 --- a/pkg/data/get.go +++ b/pkg/data/get.go @@ -22,9 +22,9 @@ type Fill struct { // // Use to build documents and aliases from a database connection type FillMany struct { - docs map[string]*index.Document - ids map[string]int - Db *sql.DB + docs map[string]*index.Document + ids map[string]int + Db *sql.DB } func (f Fill) Get(ctx context.Context) (*index.Document, error) { @@ -49,7 +49,7 @@ func (f FillMany) Get(ctx context.Context) (map[string]*index.Document, error) { f.docs = make(map[string]*index.Document) f.ids = make(map[string]int) - if err := f.documents(ctx); err != nil { + if err := f.documents(ctx, nil); err != nil { return nil, err } if err := f.tags(ctx); err != nil { @@ -95,15 +95,19 @@ func (f *Fill) document(ctx context.Context) error { return nil } -func (f *FillMany) documents(ctx context.Context) error { - rows, err := f.Db.QueryContext(ctx, ` +// Fill document info for documents provided by rows (id, path, title, date, fileTime, meta) +// pass nil rows to get all documents in the database. +func (f *FillMany) documents(ctx context.Context, rows *sql.Rows) error { + if rows == nil { + rows, err := f.Db.QueryContext(ctx, ` SELECT id, path, title, date, fileTime, meta FROM Documents `) - if err != nil { - return err + if err != nil { + return err + } + defer rows.Close() } - defer rows.Close() var id int var docPath string @@ -138,7 +142,6 @@ func (f *FillMany) documents(ctx context.Context) error { return nil } - func (f Fill) authors(ctx context.Context) error { rows, err := f.Db.QueryContext(ctx, ` SELECT name -- cgit v1.2.3