unify (and extend) query specification
This commit is contained in:
parent
cad0da95e1
commit
a9f8ea6b47
4 changed files with 51 additions and 32 deletions
|
@ -4,7 +4,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
lib "git.sr.ht/~cco/go-scopes"
|
|
||||||
"git.sr.ht/~cco/go-scopes/logging/log"
|
"git.sr.ht/~cco/go-scopes/logging/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,7 +21,7 @@ func Template(name, src string) *template.Template {
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildSql(t *template.Template, data lib.Map) string {
|
func BuildSql(t *template.Template, data any) string {
|
||||||
var out strings.Builder
|
var out strings.Builder
|
||||||
err := t.Execute(&out, data)
|
err := t.Execute(&out, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -41,17 +41,16 @@ insert into {{ $tablename }} (
|
||||||
returning trackid, timestamp`
|
returning trackid, timestamp`
|
||||||
|
|
||||||
sql_select = `
|
sql_select = `
|
||||||
{{- $tablename := or (and .schema (printf "%s.%s" .schema .tablename)) .tablename -}}
|
select {{ range $j, $c := .Scols -}}
|
||||||
select {{ range $j, $c := .scols -}}
|
|
||||||
{{- if ne $j 0 -}}, {{ end }}{{ toLower $c }}{{- end }}
|
{{- if ne $j 0 -}}, {{ end }}{{ toLower $c }}{{- end }}
|
||||||
from {{ $tablename }}
|
from {{ .Table }}
|
||||||
where {{ range $j, $c := .qucols -}}
|
where {{ range $j, $c := .Qucols -}}
|
||||||
{{- if ne $j 0 }} and {{ end }}{{ toLower $c }} = ${{ add1 $j }}{{- end }}
|
{{- if ne $j 0 }} and {{ end }}{{ toLower $c }} = ${{ add1 $j }}{{- end }}
|
||||||
{{ with .ordcols -}}
|
{{ with .Ordcols -}}
|
||||||
order by {{ range $j, $c := . -}}
|
order by {{ range $j, $c := . -}}
|
||||||
{{- if ne $j 0 -}}, {{ end }}{{ toLower $c }}{{- end -}}
|
{{- if ne $j 0 -}}, {{ end }}{{ toLower $c }}{{- end -}}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{ with .limit }}limit {{ . }}{{ end }}
|
{{ with .Limit }}limit {{ . }}{{ end }}
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ package tracking
|
||||||
import (
|
import (
|
||||||
sqllib "database/sql"
|
sqllib "database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
lib "git.sr.ht/~cco/go-scopes"
|
lib "git.sr.ht/~cco/go-scopes"
|
||||||
|
@ -92,6 +93,36 @@ func Tracks(db *sql.Storage) *Container {
|
||||||
return &Container{container_definition, db}
|
return &Container{container_definition, db}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cont *Container) setupQuerySpec(spec *querySpec) *querySpec {
|
||||||
|
if cont.Storage.Schema == "" {
|
||||||
|
spec.Table = cont.TableName
|
||||||
|
} else {
|
||||||
|
spec.Table = fmt.Sprintf("%s.%s", cont.Storage.Schema, cont.TableName)
|
||||||
|
}
|
||||||
|
spec.Scols = append(cont.HeadFields, "timestamp", "data", "trackid")
|
||||||
|
for i, v := range spec.Headvals {
|
||||||
|
if v != "" {
|
||||||
|
spec.Qucols = append(spec.Qucols, cont.HeadFields[i])
|
||||||
|
spec.Quvals = append(spec.Quvals, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return spec
|
||||||
|
}
|
||||||
|
|
||||||
|
type querySpec struct {
|
||||||
|
Table string
|
||||||
|
Headvals lib.StrSlice
|
||||||
|
Scols lib.StrSlice
|
||||||
|
Qucols, Ordcols lib.StrSlice
|
||||||
|
Quspecs []struct{ col, op string }
|
||||||
|
Ordspecs []struct {
|
||||||
|
Col string
|
||||||
|
Desc bool
|
||||||
|
}
|
||||||
|
Limit int
|
||||||
|
Quvals []any
|
||||||
|
}
|
||||||
|
|
||||||
func (cont *Container) Get(id lib.Ident) *Track {
|
func (cont *Container) Get(id lib.Ident) *Track {
|
||||||
db := cont.Storage
|
db := cont.Storage
|
||||||
var tr *Track
|
var tr *Track
|
||||||
|
@ -99,41 +130,31 @@ func (cont *Container) Get(id lib.Ident) *Track {
|
||||||
tr = cont.ItemFactory(cont)
|
tr = cont.ItemFactory(cont)
|
||||||
return tr.ScanP(r)
|
return tr.ScanP(r)
|
||||||
}
|
}
|
||||||
quData := lib.Map{
|
quSpec := &querySpec{
|
||||||
"schema": db.Schema,
|
Qucols: lib.StrSlice{"trackid"},
|
||||||
"tablename": cont.TableName,
|
Quvals: []any{id},
|
||||||
"scols": append(cont.HeadFields, "timestamp", "data", "trackid"),
|
|
||||||
"qucols": lib.StrSlice{"trackid"},
|
|
||||||
}
|
}
|
||||||
sql := storage.BuildSql(SqlSelect, quData)
|
cont.setupQuerySpec(quSpec)
|
||||||
|
sql := storage.BuildSql(SqlSelect, quSpec)
|
||||||
db.Query(proc, sql, id)
|
db.Query(proc, sql, id)
|
||||||
return tr
|
return tr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cont *Container) QueryLast(hv lib.StrSlice) *Track {
|
func (cont *Container) QueryLast(hv ...string) *Track {
|
||||||
db := cont.Storage
|
db := cont.Storage
|
||||||
var tr *Track
|
var tr *Track
|
||||||
proc := func(r *sql.Rows) error {
|
proc := func(r *sql.Rows) error {
|
||||||
tr = cont.ItemFactory(cont)
|
tr = cont.ItemFactory(cont)
|
||||||
return tr.ScanP(r)
|
return tr.ScanP(r)
|
||||||
}
|
}
|
||||||
var qucols lib.StrSlice
|
quSpec := &querySpec{
|
||||||
var quvals []any
|
Headvals: hv,
|
||||||
for i, k := range hv {
|
Ordcols: lib.StrSlice{"timestamp"},
|
||||||
if k != "" {
|
|
||||||
qucols = append(qucols, cont.HeadFields[i])
|
|
||||||
quvals = append(quvals, k)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
quData := lib.Map{
|
cont.setupQuerySpec(quSpec)
|
||||||
"schema": db.Schema,
|
sql := storage.BuildSql(SqlSelect, quSpec)
|
||||||
"tablename": cont.TableName,
|
println(sql)
|
||||||
"scols": append(cont.HeadFields, "timestamp", "data", "trackid"),
|
db.Query(proc, sql, quSpec.Quvals...)
|
||||||
"qucols": qucols,
|
|
||||||
"ordcols": lib.StrSlice{"timestamp"},
|
|
||||||
}
|
|
||||||
sql := storage.BuildSql(SqlSelect, quData)
|
|
||||||
db.Query(proc, sql, quvals...)
|
|
||||||
return tr
|
return tr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ func TrackingTest(t *testing.T, cfg *sql.Cfg, db *sql.Storage) {
|
||||||
tr2 := cont.Get(1)
|
tr2 := cont.Get(1)
|
||||||
//fmt.Printf("%+v\n", tr2.TimeStamp())
|
//fmt.Printf("%+v\n", tr2.TimeStamp())
|
||||||
t.AssertEqual(tr2.Head["userName"], "john")
|
t.AssertEqual(tr2.Head["userName"], "john")
|
||||||
tr3 := cont.QueryLast(lib.StrSlice{"", "john"})
|
tr3 := cont.QueryLast("", "john")
|
||||||
t.AssertEqual(tr3.Head["taskId"], "t01")
|
t.AssertEqual(tr3.Head["taskId"], "t01")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue