chore: sql builder instead of row sql
feat: extensive search queries
This commit is contained in:
1 parent
9434b02422
commit
80a90b65bb
4 files changed
+79
-35
No files matched your search
@@ -3,6 +3,7 @@ package sqlite
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/abelith/spellbook/internal/errors"
|
||||
"github.com/abelith/spellbook/internal/models"
|
||||
"strings"
|
||||
@@ -44,15 +45,14 @@ func (r *Repo) Init(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (r *Repo) Add(ctx context.Context, spell models.Spell) error {
|
||||
const query = `INSERT INTO spells (name, spell, short_desc, description, tags) VALUES (?, ?, ?, ?, ?)`
|
||||
tags := strings.Join(spell.Tags, ",")
|
||||
|
||||
_, err := r.db.ExecContext(
|
||||
ctx, query,
|
||||
spell.Name, spell.Spell,
|
||||
spell.ShortDesc, spell.Description,
|
||||
tags,
|
||||
)
|
||||
_, err := sq.Insert("spells").
|
||||
Columns("name", "spell", "short_desc", "description", "tags").
|
||||
Values(spell.Name, spell.Spell, spell.ShortDesc, spell.Description, tags).
|
||||
PlaceholderFormat(sq.Question).
|
||||
RunWith(r.db).
|
||||
ExecContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -60,53 +60,79 @@ func (r *Repo) Add(ctx context.Context, spell models.Spell) error {
|
||||
}
|
||||
|
||||
func (r *Repo) Delete(ctx context.Context, spellName string) error {
|
||||
const query = `DELETE FROM spells WHERE name = ?`
|
||||
|
||||
if _, err := r.db.ExecContext(ctx, query, spellName); err != nil {
|
||||
_, err := sq.Delete("spells").
|
||||
Where(sq.Eq{"name": spellName}).
|
||||
PlaceholderFormat(sq.Question).
|
||||
RunWith(r.db).
|
||||
ExecContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Repo) Get(ctx context.Context, spellName string) (models.Spell, error) {
|
||||
const query = `SELECT id, name, spell, short_desc, description, tags FROM spells WHERE name = ?`
|
||||
|
||||
row := r.db.QueryRowContext(ctx, query, spellName)
|
||||
if err := row.Err(); err != nil {
|
||||
return models.Spell{}, err
|
||||
}
|
||||
row := sq.Select("id", "name", "spell", "short_desc", "description", "tags").
|
||||
From("spells").
|
||||
Where(sq.Eq{"name": spellName}).
|
||||
PlaceholderFormat(sq.Question).
|
||||
RunWith(r.db).
|
||||
QueryRowContext(ctx)
|
||||
|
||||
return scanSpell(row)
|
||||
}
|
||||
|
||||
func (r *Repo) GetMany(ctx context.Context, query models.SearchQuery) ([]models.Spell, error) {
|
||||
sqlQuery := `
|
||||
SELECT id, name, spell, short_desc, description, tags
|
||||
FROM spells
|
||||
WHERE id > ?`
|
||||
builder := sq.Select("id", "name", "spell", "short_desc", "description", "tags").
|
||||
From("spells")
|
||||
|
||||
args := []any{query.Cursor}
|
||||
if query.Cursor > 0 {
|
||||
builder = builder.Where(sq.Gt{"id": query.Cursor})
|
||||
}
|
||||
|
||||
for _, tag := range query.Tags {
|
||||
if trimmed := strings.TrimSpace(tag); trimmed != "" {
|
||||
sqlQuery += " AND tags LIKE ?"
|
||||
args = append(args, "%"+trimmed+"%")
|
||||
if query.Text != "" {
|
||||
pattern := "%" + query.Text + "%"
|
||||
builder = builder.Where(sq.Or{
|
||||
sq.Like{"name": pattern},
|
||||
sq.Like{"spell": pattern},
|
||||
sq.Like{"description": pattern},
|
||||
})
|
||||
}
|
||||
|
||||
if query.Name != "" {
|
||||
builder = builder.Where(sq.Like{"name": "%" + query.Name + "%"})
|
||||
}
|
||||
if query.Command != "" {
|
||||
builder = builder.Where(sq.Like{"spell": "%" + query.Command + "%"})
|
||||
}
|
||||
if query.Description != "" {
|
||||
builder = builder.Where(sq.Like{"description": "%" + query.Description + "%"})
|
||||
}
|
||||
|
||||
if len(query.Tags) > 0 {
|
||||
var tagConditions sq.Or
|
||||
for _, tag := range query.Tags {
|
||||
tagConditions = append(tagConditions, sq.Like{"tags": "%" + tag + "%"})
|
||||
}
|
||||
builder = builder.Where(tagConditions)
|
||||
}
|
||||
|
||||
sqlQuery += " ORDER BY id ASC LIMIT ?"
|
||||
limit := query.Limit
|
||||
if limit <= 0 {
|
||||
limit = 20
|
||||
if query.Limit > 0 {
|
||||
builder = builder.Limit(uint64(query.Limit))
|
||||
}
|
||||
args = append(args, limit)
|
||||
|
||||
rows, err := r.db.QueryContext(ctx, sqlQuery, args...)
|
||||
builder = builder.
|
||||
OrderBy("id ASC").
|
||||
PlaceholderFormat(sq.Question)
|
||||
|
||||
rows, err := builder.RunWith(r.db).QueryContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
spells := make([]models.Spell, 0)
|
||||
var spells []models.Spell
|
||||
for rows.Next() {
|
||||
spell, err := scanSpell(rows)
|
||||
if err != nil {
|
||||
@@ -114,9 +140,11 @@ func (r *Repo) GetMany(ctx context.Context, query models.SearchQuery) ([]models.
|
||||
}
|
||||
spells = append(spells, spell)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return spells, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,11 @@ type CastResult struct {
|
||||
}
|
||||
|
||||
type SearchQuery struct {
|
||||
Cursor int
|
||||
Limit int
|
||||
Tags []string
|
||||
Text string
|
||||
Name string
|
||||
Description string
|
||||
Command string
|
||||
Tags []string
|
||||
Cursor int
|
||||
Limit int
|
||||
}
|
||||
Reference in new issue
Block a user