-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsqlite_jq.go
110 lines (89 loc) · 1.86 KB
/
sqlite_jq.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package main
import (
"encoding/json"
"fmt"
"github.com/itchyny/gojq"
"go.riyazali.net/sqlite"
)
type Jq struct{}
func (m *Jq) Args() int { return 2 }
func (m *Jq) Deterministic() bool { return true }
func (m *Jq) Apply(ctx *sqlite.Context, values ...sqlite.Value) {
var val interface{}
err := json.Unmarshal(values[0].Blob(), &val)
if err != nil {
err = fmt.Errorf("error parsing JSON data: %v", err)
ctx.ResultError(err)
return
}
query, err := gojq.Parse(values[1].Text())
if err != nil {
err = fmt.Errorf("error parsing JQ query: %v", err)
ctx.ResultError(err)
return
}
var rows []interface{}
iter := query.Run(val)
for {
v, ok := iter.Next()
if !ok {
break
}
if err, ok := v.(error); ok {
err = fmt.Errorf("error creating result: %v", err)
ctx.ResultError(err)
return
}
rows = append(rows, v)
}
switch len(rows) {
case 0:
ctx.ResultNull()
case 1:
formatResult(ctx, rows[0])
default:
formatResult(ctx, rows)
}
}
func formatResult(ctx *sqlite.Context, v interface{}) {
if v == nil {
ctx.ResultNull()
return
}
switch v := v.(type) {
case bool:
if v {
ctx.ResultInt(1)
} else {
ctx.ResultInt(0)
}
case int:
ctx.ResultInt(v)
case int64:
ctx.ResultInt64(v)
case float64:
ctx.ResultFloat(v)
case string:
ctx.ResultText(v)
default:
tmp, err := json.Marshal(v)
if err != nil {
err = fmt.Errorf("error marshalling result data: %v", err)
ctx.ResultError(err)
return
}
ctx.ResultBlob(tmp)
}
}
func init() {
sqlite.Register(func(api *sqlite.ExtensionApi) (sqlite.ErrorCode, error) {
if err := api.CreateFunction("jq", &Jq{}); err != nil {
return sqlite.SQLITE_ERROR, err
}
if err := api.CreateModule("jq_each", &JqEachModule{}, sqlite.EponymousOnly(true)); err != nil {
return sqlite.SQLITE_ERROR, err
}
return sqlite.SQLITE_OK, nil
})
}
func main() {}