-
Notifications
You must be signed in to change notification settings - Fork 37
/
cql.go
95 lines (83 loc) · 2.67 KB
/
cql.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
package handler
import "C"
import (
"github.com/goccy/go-json"
"github.com/gofiber/fiber/v2"
"pkg.world.dev/world-engine/cardinal/server/handler/cql"
servertypes "pkg.world.dev/world-engine/cardinal/server/types"
"pkg.world.dev/world-engine/cardinal/types"
)
type CQLQueryRequest struct {
CQL string
}
type cqlData struct {
ID types.EntityID `json:"id"`
Data []json.RawMessage `json:"data" swaggertype:"object"`
}
type CQLQueryResponse struct {
Results []cqlData `json:"results"`
}
// PostCQL godoc
//
// @Summary Executes a CQL (Cardinal Query Language) query
// @Description Executes a CQL (Cardinal Query Language) query
// @Accept application/json
// @Produce application/json
// @Param cql body CQLQueryRequest true "CQL query to be executed"
// @Success 200 {object} CQLQueryResponse "Results of the executed CQL query"
// @Failure 400 {string} string "Invalid request parameters"
// @Router /cql [post]
func PostCQL(provider servertypes.Provider) func(*fiber.Ctx) error { //nolint:gocognit // to refactor later
return func(ctx *fiber.Ctx) error {
req := new(CQLQueryRequest)
if err := ctx.BodyParser(req); err != nil {
return err
}
// getComponentByName is a wrapper function that casts component.ComponentMetadata from ctx.GetComponentByName
// to types.Component
getComponentByName := func(name string) (types.Component, error) {
comp, err := provider.GetComponentByName(name)
if err != nil {
return nil, err
}
return comp, nil
}
// Parse the CQL string into a filter
resultFilter, err := cql.Parse(req.CQL, getComponentByName)
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
}
result := make([]cqlData, 0)
var eachError error
searchErr := provider.Search(resultFilter).Each(provider.GetReadOnlyCtx(),
func(id types.EntityID) bool {
components, err := provider.StoreReader().GetComponentTypesForEntity(id)
if err != nil {
eachError = err
return false
}
resultElement := cqlData{
ID: id,
Data: make([]json.RawMessage, 0),
}
for _, c := range components {
data, err := provider.StoreReader().GetComponentForEntityInRawJSON(c, id)
if err != nil {
eachError = err
return false
}
resultElement.Data = append(resultElement.Data, data)
}
result = append(result, resultElement)
return true
},
)
if searchErr != nil {
return fiber.NewError(fiber.StatusInternalServerError, searchErr.Error())
}
if eachError != nil {
return fiber.NewError(fiber.StatusInternalServerError, eachError.Error())
}
return ctx.JSON(CQLQueryResponse{Results: result})
}
}