Merge pull request #459 from travisturner/handler-mux

Handler mux
This commit is contained in:
Travis Turner 2017-04-18 16:44:19 -05:00 committed by GitHub
commit 65de0c7d8a
10 changed files with 291 additions and 470 deletions

View file

@ -125,7 +125,6 @@ func (c *Client) Schema(ctx context.Context) ([]*DBInfo, error) {
func (c *Client) CreateDB(ctx context.Context, db string, opt DBOptions) error {
// Encode query request.
buf, err := json.Marshal(&postDBRequest{
DB: db,
Options: opt,
})
if err != nil {
@ -133,7 +132,7 @@ func (c *Client) CreateDB(ctx context.Context, db string, opt DBOptions) error {
}
// Create URL & HTTP request.
u := url.URL{Scheme: "http", Host: c.host, Path: "/db"}
u := url.URL{Scheme: "http", Host: c.host, Path: fmt.Sprintf("/db/%s", db)}
req, err := http.NewRequest("POST", u.String(), bytes.NewReader(buf))
if err != nil {
return err
@ -209,7 +208,6 @@ func (c *Client) ExecuteQuery(ctx context.Context, db, query string, allowRedire
// Encode query request.
buf, err := proto.Marshal(&internal.QueryRequest{
DB: db,
Query: query,
Remote: !allowRedirect,
})
@ -218,7 +216,11 @@ func (c *Client) ExecuteQuery(ctx context.Context, db, query string, allowRedire
}
// Create URL & HTTP request.
u := url.URL{Scheme: "http", Host: c.host, Path: "/query"}
u := url.URL{
Scheme: "http",
Host: c.host,
Path: fmt.Sprintf("/db/%s/query", db),
}
req, err := http.NewRequest("POST", u.String(), bytes.NewReader(buf))
if err != nil {
return nil, err
@ -664,8 +666,6 @@ func (c *Client) CreateFrame(ctx context.Context, db, frame string, opt FrameOpt
// Encode query request.
buf, err := json.Marshal(&postFrameRequest{
DB: db,
Frame: frame,
Options: opt,
})
if err != nil {
@ -673,7 +673,7 @@ func (c *Client) CreateFrame(ctx context.Context, db, frame string, opt FrameOpt
}
// Create URL & HTTP request.
u := url.URL{Scheme: "http", Host: c.host, Path: "/frame"}
u := url.URL{Scheme: "http", Host: c.host, Path: fmt.Sprintf("/db/%s/frame/%s", db, frame)}
req, err := http.NewRequest("POST", u.String(), bytes.NewReader(buf))
if err != nil {
return err
@ -711,11 +711,9 @@ func (c *Client) RestoreFrame(ctx context.Context, host, db, frame string) error
u := url.URL{
Scheme: "http",
Host: c.Host(),
Path: "/frame/restore",
Path: fmt.Sprintf("/db/%s/frame/%s/restore", db, frame),
RawQuery: url.Values{
"host": {host},
"db": {db},
"frame": {frame},
"host": {host},
}.Encode(),
}
@ -747,11 +745,7 @@ func (c *Client) FrameViews(ctx context.Context, db, frame string) ([]string, er
u := url.URL{
Scheme: "http",
Host: c.host,
Path: "/frame/views",
RawQuery: (&url.Values{
"db": {db},
"frame": {frame},
}).Encode(),
Path: fmt.Sprintf("/db/%s/frame/%s/views", db, frame),
}
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
@ -879,14 +873,13 @@ func (c *Client) BlockData(ctx context.Context, db, frame, view string, slice ui
// ProfileAttrDiff returns data from differing blocks on a remote host.
func (c *Client) ProfileAttrDiff(ctx context.Context, db string, blks []AttrBlock) (map[uint64]map[string]interface{}, error) {
u := url.URL{
Scheme: "http",
Host: c.host,
Path: "/db/attr/diff",
RawQuery: url.Values{"db": {db}}.Encode(),
Scheme: "http",
Host: c.host,
Path: fmt.Sprintf("/db/%s/attr/diff", db),
}
// Encode request.
buf, err := json.Marshal(postDBAttrDiffRequest{DB: db, Blocks: blks})
buf, err := json.Marshal(postDBAttrDiffRequest{Blocks: blks})
if err != nil {
return nil, err
}
@ -923,14 +916,13 @@ func (c *Client) ProfileAttrDiff(ctx context.Context, db string, blks []AttrBloc
// BitmapAttrDiff returns data from differing blocks on a remote host.
func (c *Client) BitmapAttrDiff(ctx context.Context, db, frame string, blks []AttrBlock) (map[uint64]map[string]interface{}, error) {
u := url.URL{
Scheme: "http",
Host: c.host,
Path: "/frame/attr/diff",
RawQuery: url.Values{"db": {db}, "frame": {frame}}.Encode(),
Scheme: "http",
Host: c.host,
Path: fmt.Sprintf("/db/%s/frame/%s/attr/diff", db, frame),
}
// Encode request.
buf, err := json.Marshal(postFrameAttrDiffRequest{DB: db, Frame: frame, Blocks: blks})
buf, err := json.Marshal(postFrameAttrDiffRequest{Blocks: blks})
if err != nil {
return nil, err
}

View file

@ -944,7 +944,6 @@ func (e *Executor) executeSetProfileAttrs(ctx context.Context, db string, c *pql
func (e *Executor) exec(ctx context.Context, node *Node, db string, q *pql.Query, slices []uint64, opt *ExecOptions) (results []interface{}, err error) {
// Encode request object.
pbreq := &internal.QueryRequest{
DB: db,
Query: q.String(),
Slices: slices,
Remote: true,
@ -958,7 +957,7 @@ func (e *Executor) exec(ctx context.Context, node *Node, db string, q *pql.Query
req, err := http.NewRequest("POST", (&url.URL{
Scheme: "http",
Host: node.Host,
Path: "/query",
Path: fmt.Sprintf("/db/%s/query", db),
}).String(), bytes.NewReader(buf))
if err != nil {
return nil, err

8
glide.lock generated
View file

@ -1,5 +1,5 @@
hash: 7de62dbaf3cc1dc4959f4f6d8213102cb182b4dd7a87b3ac29260ad6bc1b0cef
updated: 2017-03-03T12:25:48.088390296-06:00
hash: 743e8f978eb4ad8f80a2ab71b05caebbf50b6769b71aa457bc4f144fef8c6595
updated: 2017-04-18T15:33:39.035615802-05:00
imports:
- name: github.com/boltdb/bolt
version: 4b1ebc1869ad66568b313d0dc410e2be72670dda
@ -27,6 +27,10 @@ imports:
version: 888eb0692c857ec880338addf316bd662d5e630e
subpackages:
- proto
- name: github.com/gorilla/context
version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42
- name: github.com/gorilla/mux
version: 392c28fe23e1c45ddba891b0320b3b5df220beea
- name: github.com/hashicorp/hcl
version: 630949a3c5fa3c613328e1b8256052cbc2327c9b
subpackages:

View file

@ -29,3 +29,5 @@ import:
version: ^1.1.0
- package: github.com/spf13/cobra
- package: github.com/spf13/viper
- package: github.com/gorilla/mux
version: ^1.3.0

View file

@ -11,13 +11,14 @@ import (
"io/ioutil"
"log"
"net/http"
"net/http/pprof"
_ "net/http/pprof"
"os"
"strconv"
"strings"
"time"
"github.com/gogo/protobuf/proto"
"github.com/gorilla/mux"
"github.com/pilosa/pilosa/internal"
"github.com/pilosa/pilosa/pql"
)
@ -30,6 +31,8 @@ type Handler struct {
Host string
Cluster *Cluster
Router *mux.Router
// The execution engine for running queries.
Executor interface {
Execute(context context.Context, db string, query *pql.Query, slices []uint64, opt *ExecOptions) ([]interface{}, error)
@ -44,178 +47,59 @@ type Handler struct {
// NewHandler returns a new instance of Handler with a default logger.
func NewHandler() *Handler {
return &Handler{
handler := &Handler{
LogOutput: os.Stderr,
}
handler.Router = NewRouter(handler)
return handler
}
func NewRouter(handler *Handler) *mux.Router {
router := mux.NewRouter()
router.HandleFunc("/db", handler.handleGetDBs).Methods("GET")
router.HandleFunc("/db/{db}", handler.handleGetDB).Methods("GET")
router.HandleFunc("/db/{db}", handler.handlePostDB).Methods("POST")
router.HandleFunc("/db/{db}", handler.handleDeleteDB).Methods("DELETE")
router.HandleFunc("/db/{db}/attr/diff", handler.handlePostDBAttrDiff).Methods("POST")
//router.HandleFunc("/db/{db}/frame", handler.handleGetFrames).Methods("GET") // Not implemented.
router.HandleFunc("/db/{db}/frame/{frame}", handler.handlePostFrame).Methods("POST")
router.HandleFunc("/db/{db}/frame/{frame}", handler.handleDeleteFrame).Methods("DELETE")
router.HandleFunc("/db/{db}/query", handler.handlePostQuery).Methods("POST")
router.HandleFunc("/db/{db}/frame/{frame}/attr/diff", handler.handlePostFrameAttrDiff).Methods("POST")
router.HandleFunc("/db/{db}/frame/{frame}/restore", handler.handlePostFrameRestore).Methods("POST")
router.HandleFunc("/db/{db}/frame/{frame}/time-quantum", handler.handlePatchFrameTimeQuantum).Methods("PATCH")
router.HandleFunc("/db/{db}/frame/{frame}/views", handler.handleGetFrameViews).Methods("GET")
router.HandleFunc("/db/{db}/time-quantum", handler.handlePatchDBTimeQuantum).Methods("PATCH")
router.PathPrefix("/debug/pprof/").Handler(http.DefaultServeMux).Methods("GET")
router.HandleFunc("/debug/vars", handler.handleExpvar).Methods("GET")
router.HandleFunc("/export", handler.handleGetExport).Methods("GET")
router.HandleFunc("/fragment/block/data", handler.handleGetFragmentBlockData).Methods("GET")
router.HandleFunc("/fragment/blocks", handler.handleGetFragmentBlocks).Methods("GET")
router.HandleFunc("/fragment/data", handler.handleGetFragmentData).Methods("GET")
router.HandleFunc("/fragment/data", handler.handlePostFragmentData).Methods("POST")
router.HandleFunc("/fragment/nodes", handler.handleGetFragmentNodes).Methods("GET")
router.HandleFunc("/import", handler.handlePostImport).Methods("POST")
router.HandleFunc("/nodes", handler.handleGetNodes).Methods("GET")
router.HandleFunc("/schema", handler.handleGetSchema).Methods("GET")
router.HandleFunc("/slices/max", handler.handleGetSliceMax).Methods("GET")
router.HandleFunc("/version", handler.handleGetVersion).Methods("GET")
// TODO: Apply MethodNotAllowed statuses to all endpoints.
// Ideally this would be automatic, as described in this (wontfix) ticket:
// https://github.com/gorilla/mux/issues/6
// For now we just do it for the most commonly used handler, /query
router.HandleFunc("/db/{db}/query", handler.methodNotAllowedHandler).Methods("GET")
return router
}
func (h *Handler) methodNotAllowedHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
// ServeHTTP handles an HTTP request.
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Handle pprof requests separately.
if strings.HasPrefix(r.URL.Path, "/debug/pprof") {
switch r.URL.Path {
case "/debug/pprof/cmdline":
pprof.Cmdline(w, r)
case "/debug/pprof/profile":
pprof.Profile(w, r)
case "/debug/pprof/symbol":
pprof.Symbol(w, r)
case "/debug/pprof/trace":
pprof.Trace(w, r)
default:
pprof.Index(w, r)
}
return
}
// Route API calls to appropriate handler functions.
t := time.Now()
switch r.URL.Path {
case "/schema":
switch r.Method {
case "GET":
h.handleGetSchema(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/query":
switch r.Method {
case "POST":
h.handlePostQuery(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/import":
switch r.Method {
case "POST":
h.handlePostImport(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/export":
switch r.Method {
case "GET":
h.handleGetExport(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/slices/max":
switch r.Method {
case "GET":
h.handleGetSliceMax(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/db":
switch r.Method {
case "POST":
h.handlePostDB(w, r)
case "DELETE":
h.handleDeleteDB(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/db/time_quantum":
switch r.Method {
case "PATCH":
h.handlePatchDBTimeQuantum(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/db/attr/diff":
switch r.Method {
case "POST":
h.handlePostDBAttrDiff(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/frame":
switch r.Method {
case "POST":
h.handlePostFrame(w, r)
case "DELETE":
h.handleDeleteFrame(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/frame/time_quantum":
switch r.Method {
case "PATCH":
h.handlePatchFrameTimeQuantum(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/frame/views":
switch r.Method {
case "GET":
h.handleGetFrameViews(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/frame/attr/diff":
switch r.Method {
case "POST":
h.handlePostFrameAttrDiff(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/fragment/nodes":
switch r.Method {
case "GET":
h.handleGetFragmentNodes(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/fragment/data":
switch r.Method {
case "GET":
h.handleGetFragmentData(w, r)
case "POST":
h.handlePostFragmentData(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/fragment/blocks":
switch r.Method {
case "GET":
h.handleGetFragmentBlocks(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/fragment/block/data":
switch r.Method {
case "GET":
h.handleGetFragmentBlockData(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/frame/restore":
switch r.Method {
case "POST":
h.handlePostFrameRestore(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/nodes":
switch r.Method {
case "GET":
h.handleGetNodes(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
case "/version":
h.handleVersion(w, r)
case "/debug/vars":
h.handleExpvar(w, r)
default:
http.NotFound(w, r)
}
dif := time.Since(t).Seconds()
if dif > 90 {
h.logger().Printf("%s %s %.03fs", r.Method, r.URL.String(), dif)
}
h.Router.ServeHTTP(w, r)
}
// handleGetSchema handles GET /schema requests.
@ -233,6 +117,8 @@ type getSchemaResponse struct {
// handlePostQuery handles /query requests.
func (h *Handler) handlePostQuery(w http.ResponseWriter, r *http.Request) {
dbName := mux.Vars(r)["db"]
// Parse incoming request.
req, err := h.readQueryRequest(r)
if err != nil {
@ -255,7 +141,7 @@ func (h *Handler) handlePostQuery(w http.ResponseWriter, r *http.Request) {
}
// Execute the query.
results, err := h.Executor.Execute(r.Context(), req.DB, q, req.Slices, opt)
results, err := h.Executor.Execute(r.Context(), dbName, q, req.Slices, opt)
resp := &QueryResponse{Results: results, Err: err}
// Fill profile attributes if requested.
@ -271,7 +157,7 @@ func (h *Handler) handlePostQuery(w http.ResponseWriter, r *http.Request) {
}
// Retrieve profile attributes across all calls.
profiles, err := h.readProfiles(h.Index.DB(req.DB), profileIDs)
profiles, err := h.readProfiles(h.Index.DB(dbName), profileIDs)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
h.writeQueryResponse(w, r, &QueryResponse{Err: err})
@ -291,26 +177,24 @@ func (h *Handler) handlePostQuery(w http.ResponseWriter, r *http.Request) {
}
}
func (h *Handler) handleGetSliceMax(w http.ResponseWriter, r *http.Request) error {
func (h *Handler) handleGetSliceMax(w http.ResponseWriter, r *http.Request) {
var ms map[string]uint64
if inverse, _ := strconv.ParseBool(r.URL.Query().Get("inverse")); inverse {
ms = h.Index.MaxInverseSlices()
} else {
ms = h.Index.MaxSlices()
}
if strings.Contains(r.Header.Get("Accept"), "application/x-protobuf") {
pb := &internal.MaxSlicesResponse{
MaxSlices: ms,
}
if buf, err := proto.Marshal(pb); err != nil {
return err
h.logger().Printf("protobuf marshal error: %s", err)
} else if _, err := w.Write(buf); err != nil {
return err
h.logger().Printf("stream write error: %s", err)
}
return nil
}
return json.NewEncoder(w).Encode(sliceMaxResponse{
json.NewEncoder(w).Encode(sliceMaxResponse{
MaxSlices: ms,
})
}
@ -319,29 +203,33 @@ type sliceMaxResponse struct {
MaxSlices map[string]uint64 `json:"MaxSlices"`
}
// handlePostDB handles POST /db request.
func (h *Handler) handlePostDB(w http.ResponseWriter, r *http.Request) {
// Decode request.
var req postDBRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
// handleGetDBs handles GET /db request.
func (h *Handler) handleGetDBs(w http.ResponseWriter, r *http.Request) {
h.handleGetSchema(w, r)
}
// handleGetDB handles GET /db/<dbname> requests.
func (h *Handler) handleGetDB(w http.ResponseWriter, r *http.Request) {
dbName := mux.Vars(r)["db"]
db := h.Index.DB(dbName)
if db == nil {
http.Error(w, ErrDatabaseNotFound.Error(), http.StatusNotFound)
return
}
// Create database.
_, err := h.Index.CreateDB(req.DB, req.Options)
if err == ErrDatabaseExists {
http.Error(w, err.Error(), http.StatusConflict)
return
} else if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
if err := json.NewEncoder(w).Encode(getDBResponse{
map[string]string{"name": db.Name()},
}); err != nil {
h.logger().Printf("write response error: %s", err)
}
}
// Encode response.
if err := json.NewEncoder(w).Encode(postDBResponse{}); err != nil {
h.logger().Printf("response encoding error: %s", err)
}
type getDBResponse struct {
DB map[string]string `json:"db"`
}
type postDBRequest struct {
Options DBOptions `json:"options"`
}
// Custom Unmarshal JSON to validate request body when creating a new database
@ -352,12 +240,6 @@ func (p *postDBRequest) UnmarshalJSON(b []byte) error {
}
for key, value := range data {
switch key {
case "db":
val, ok := data["db"].(string)
if !ok {
return errors.New("db required and must be a string")
}
p.DB = val
case "options":
value, err := validateOptions(data, "columnLabel")
if err != nil {
@ -401,24 +283,14 @@ func validateOptions(data map[string]interface{}, field string) (string, error)
return optionValue, nil
}
type postDBRequest struct {
DB string `json:"db"`
Options DBOptions `json:"options"`
}
type postDBResponse struct{}
// handleDeleteDB handles DELETE /db request.
func (h *Handler) handleDeleteDB(w http.ResponseWriter, r *http.Request) {
// Decode request.
var req deleteDBRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
dbName := mux.Vars(r)["db"]
// Delete database from the index.
if err := h.Index.DeleteDB(req.DB); err != nil {
if err := h.Index.DeleteDB(dbName); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
@ -429,14 +301,39 @@ func (h *Handler) handleDeleteDB(w http.ResponseWriter, r *http.Request) {
}
}
type deleteDBRequest struct {
DB string `json:"db"`
}
type deleteDBResponse struct{}
// handlePostDB handles POST /db request.
func (h *Handler) handlePostDB(w http.ResponseWriter, r *http.Request) {
dbName := mux.Vars(r)["db"]
// Decode request.
var req postDBRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// Create database.
_, err := h.Index.CreateDB(dbName, req.Options)
if err == ErrDatabaseExists {
http.Error(w, err.Error(), http.StatusConflict)
return
} else if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Encode response.
if err := json.NewEncoder(w).Encode(postDBResponse{}); err != nil {
h.logger().Printf("response encoding error: %s", err)
}
}
// handlePatchDBTimeQuantum handles PATCH /db/time_quantum request.
func (h *Handler) handlePatchDBTimeQuantum(w http.ResponseWriter, r *http.Request) {
dbName := mux.Vars(r)["db"]
// Decode request.
var req patchDBTimeQuantumRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
@ -452,14 +349,14 @@ func (h *Handler) handlePatchDBTimeQuantum(w http.ResponseWriter, r *http.Reques
}
// Retrieve database by name.
db := h.Index.DB(req.DB)
if db == nil {
database := h.Index.DB(dbName)
if database == nil {
http.Error(w, ErrDatabaseNotFound.Error(), http.StatusNotFound)
return
}
// Set default time quantum on database.
if err := db.SetTimeQuantum(tq); err != nil {
if err := database.SetTimeQuantum(tq); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
@ -471,7 +368,6 @@ func (h *Handler) handlePatchDBTimeQuantum(w http.ResponseWriter, r *http.Reques
}
type patchDBTimeQuantumRequest struct {
DB string `json:"db"`
TimeQuantum string `json:"time_quantum"`
}
@ -479,6 +375,8 @@ type patchDBTimeQuantumResponse struct{}
// handlePostDBAttrDiff handles POST /db/attr/diff requests.
func (h *Handler) handlePostDBAttrDiff(w http.ResponseWriter, r *http.Request) {
dbName := mux.Vars(r)["db"]
// Decode request.
var req postDBAttrDiffRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
@ -487,7 +385,7 @@ func (h *Handler) handlePostDBAttrDiff(w http.ResponseWriter, r *http.Request) {
}
// Retrieve database from index.
db := h.Index.DB(req.DB)
db := h.Index.DB(dbName)
if db == nil {
http.Error(w, ErrDatabaseNotFound.Error(), http.StatusNotFound)
return
@ -525,7 +423,6 @@ func (h *Handler) handlePostDBAttrDiff(w http.ResponseWriter, r *http.Request) {
}
type postDBAttrDiffRequest struct {
DB string `json:"db"`
Blocks []AttrBlock `json:"blocks"`
}
@ -535,6 +432,8 @@ type postDBAttrDiffResponse struct {
// handlePostFrame handles POST /frame request.
func (h *Handler) handlePostFrame(w http.ResponseWriter, r *http.Request) {
dbName := mux.Vars(r)["db"]
frameName := mux.Vars(r)["frame"]
// Decode request.
var req postFrameRequest
@ -544,14 +443,14 @@ func (h *Handler) handlePostFrame(w http.ResponseWriter, r *http.Request) {
}
// Find database.
db := h.Index.DB(req.DB)
db := h.Index.DB(dbName)
if db == nil {
http.Error(w, ErrDatabaseNotFound.Error(), http.StatusNotFound)
return
}
// Create frame.
_, err := db.CreateFrame(req.Frame, req.Options)
_, err := db.CreateFrame(frameName, req.Options)
if err == ErrFrameExists {
http.Error(w, err.Error(), http.StatusConflict)
return
@ -574,19 +473,6 @@ func (p *postFrameRequest) UnmarshalJSON(b []byte) error {
}
for key, value := range data {
switch key {
case "db":
val, ok := data["db"].(string)
if !ok {
return errors.New("db required and must be a string")
}
p.DB = val
case "frame":
val, ok := data["frame"].(string)
if !ok {
return errors.New("frame required and must be a string")
}
p.Frame = val
case "options":
value, err := validateOptions(data, "rowLabel")
if err != nil {
@ -597,7 +483,6 @@ func (p *postFrameRequest) UnmarshalJSON(b []byte) error {
} else {
p.Options = FrameOptions{RowLabel: value}
}
default:
return fmt.Errorf("Unknown key: {%v:%v}", key, value)
}
@ -607,8 +492,6 @@ func (p *postFrameRequest) UnmarshalJSON(b []byte) error {
}
type postFrameRequest struct {
DB string `json:"db"`
Frame string `json:"frame"`
Options FrameOptions `json:"options"`
}
@ -616,15 +499,11 @@ type postFrameResponse struct{}
// handleDeleteFrame handles DELETE /frame request.
func (h *Handler) handleDeleteFrame(w http.ResponseWriter, r *http.Request) {
// Decode request.
var req deleteFrameRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
dbName := mux.Vars(r)["db"]
frameName := mux.Vars(r)["frame"]
// Find database.
db := h.Index.DB(req.DB)
db := h.Index.DB(dbName)
if db == nil {
if err := json.NewEncoder(w).Encode(deleteDBResponse{}); err != nil {
h.logger().Printf("response encoding error: %s", err)
@ -633,7 +512,7 @@ func (h *Handler) handleDeleteFrame(w http.ResponseWriter, r *http.Request) {
}
// Delete frame from the database.
if err := db.DeleteFrame(req.Frame); err != nil {
if err := db.DeleteFrame(frameName); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
@ -644,15 +523,13 @@ func (h *Handler) handleDeleteFrame(w http.ResponseWriter, r *http.Request) {
}
}
type deleteFrameRequest struct {
DB string `json:"db"`
Frame string `json:"frame"`
}
type deleteFrameResponse struct{}
// handlePatchFrameTimeQuantum handles PATCH /frame/time_quantum request.
func (h *Handler) handlePatchFrameTimeQuantum(w http.ResponseWriter, r *http.Request) {
dbName := mux.Vars(r)["db"]
frameName := mux.Vars(r)["frame"]
// Decode request.
var req patchFrameTimeQuantumRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
@ -668,7 +545,7 @@ func (h *Handler) handlePatchFrameTimeQuantum(w http.ResponseWriter, r *http.Req
}
// Retrieve database by name.
f := h.Index.Frame(req.DB, req.Frame)
f := h.Index.Frame(dbName, frameName)
if f == nil {
http.Error(w, ErrFrameNotFound.Error(), http.StatusNotFound)
return
@ -687,8 +564,6 @@ func (h *Handler) handlePatchFrameTimeQuantum(w http.ResponseWriter, r *http.Req
}
type patchFrameTimeQuantumRequest struct {
DB string `json:"db"`
Frame string `json:"frame"`
TimeQuantum string `json:"time_quantum"`
}
@ -696,11 +571,11 @@ type patchFrameTimeQuantumResponse struct{}
// handleGetFrameViews handles GET /frame/views request.
func (h *Handler) handleGetFrameViews(w http.ResponseWriter, r *http.Request) {
q := r.URL.Query()
db, frame := q.Get("db"), q.Get("frame")
dbName := mux.Vars(r)["db"]
frameName := mux.Vars(r)["frame"]
// Retrieve views.
f := h.Index.Frame(db, frame)
f := h.Index.Frame(dbName, frameName)
if f == nil {
http.Error(w, ErrFrameNotFound.Error(), http.StatusNotFound)
return
@ -725,6 +600,9 @@ type getFrameViewsResponse struct {
// handlePostFrameAttrDiff handles POST /frame/attr/diff requests.
func (h *Handler) handlePostFrameAttrDiff(w http.ResponseWriter, r *http.Request) {
dbName := mux.Vars(r)["db"]
frameName := mux.Vars(r)["frame"]
// Decode request.
var req postFrameAttrDiffRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
@ -733,7 +611,7 @@ func (h *Handler) handlePostFrameAttrDiff(w http.ResponseWriter, r *http.Request
}
// Retrieve database from index.
f := h.Index.Frame(req.DB, req.Frame)
f := h.Index.Frame(dbName, frameName)
if f == nil {
http.Error(w, ErrFrameNotFound.Error(), http.StatusNotFound)
return
@ -771,8 +649,6 @@ func (h *Handler) handlePostFrameAttrDiff(w http.ResponseWriter, r *http.Request
}
type postFrameAttrDiffRequest struct {
DB string `json:"db"`
Frame string `json:"frame"`
Blocks []AttrBlock `json:"blocks"`
}
@ -858,7 +734,6 @@ func (h *Handler) readURLQueryRequest(r *http.Request) (*QueryRequest, error) {
}
return &QueryRequest{
DB: q.Get("db"),
Query: query,
Slices: slices,
Profiles: q.Get("profiles") == "true",
@ -1175,20 +1050,16 @@ type getFragmentBlocksResponse struct {
// handlePostFrameRestore handles POST /frame/restore requests.
func (h *Handler) handlePostFrameRestore(w http.ResponseWriter, r *http.Request) {
dbName := mux.Vars(r)["db"]
frameName := mux.Vars(r)["frame"]
q := r.URL.Query()
host := q.Get("host")
db, frame := q.Get("db"), q.Get("frame")
// Validate query parameters.
if host == "" {
http.Error(w, "host required", http.StatusBadRequest)
return
} else if db == "" {
http.Error(w, "db required", http.StatusBadRequest)
return
} else if frame == "" {
http.Error(w, "frame required", http.StatusBadRequest)
return
}
// Create a client for the remote cluster.
@ -1206,24 +1077,23 @@ func (h *Handler) handlePostFrameRestore(w http.ResponseWriter, r *http.Request)
}
// Retrieve frame.
f := h.Index.Frame(db, frame)
f := h.Index.Frame(dbName, frameName)
if f == nil {
http.Error(w, ErrFrameNotFound.Error(), http.StatusNotFound)
return
}
// Retrieve list of all views.
views, err := client.FrameViews(r.Context(), db, frame)
views, err := client.FrameViews(r.Context(), dbName, frameName)
if err != nil {
http.Error(w, "cannot retrieve frame views: "+err.Error(), http.StatusInternalServerError)
return
}
// Loop over each slice and import it if this node owns it.
//travis
for slice := uint64(0); slice <= maxSlices[db]; slice++ {
for slice := uint64(0); slice <= maxSlices[dbName]; slice++ {
// Ignore this slice if we don't own it.
if !h.Cluster.OwnsFragment(h.Host, db, slice) {
if !h.Cluster.OwnsFragment(h.Host, dbName, slice) {
continue
}
@ -1244,7 +1114,7 @@ func (h *Handler) handlePostFrameRestore(w http.ResponseWriter, r *http.Request)
}
// Stream backup from remote node.
rd, err := client.BackupSlice(r.Context(), db, frame, view, slice)
rd, err := client.BackupSlice(r.Context(), dbName, frameName, view, slice)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@ -1275,7 +1145,7 @@ func (h *Handler) handleGetNodes(w http.ResponseWriter, r *http.Request) {
}
// handleGetVersion handles /version requests.
func (h *Handler) handleVersion(w http.ResponseWriter, r *http.Request) {
func (h *Handler) handleGetVersion(w http.ResponseWriter, r *http.Request) {
if err := json.NewEncoder(w).Encode(struct {
Version string `json:"version"`
}{
@ -1331,7 +1201,6 @@ type QueryRequest struct {
func decodeQueryRequest(pb *internal.QueryRequest) *QueryRequest {
req := &QueryRequest{
DB: pb.DB,
Query: pb.Query,
Slices: pb.Slices,
Profiles: pb.Profiles,

View file

@ -13,12 +13,11 @@ func TestPostDBRequestUnmarshalJSON(t *testing.T) {
expected postDBRequest
err string
}{
{json: `{"db": "d", "options": {}}`, expected: postDBRequest{DB: "d", Options: DBOptions{}}},
{json: `{"db": 1, "options": {}}`, err: "db required and must be a string"},
{json: `{"db": "d", "options": 4}`, err: "options is not map[string]interface{}"},
{json: `{"db": "d", "option": {}}`, err: "Unknown key: option:map[]"},
{json: `{"db": "d", "options": {"columnLabel": "test"}}`, expected: postDBRequest{DB: "d", Options: DBOptions{ColumnLabel: "test"}}},
{json: `{"db": "d", "options": {"columnLabl": "test"}}`, err: "invalid key for options {columnLabl:test}"},
{json: `{"options": {}}`, expected: postDBRequest{Options: DBOptions{}}},
{json: `{"options": 4}`, err: "options is not map[string]interface{}"},
{json: `{"option": {}}`, err: "Unknown key: option:map[]"},
{json: `{"options": {"columnLabel": "test"}}`, expected: postDBRequest{Options: DBOptions{ColumnLabel: "test"}}},
{json: `{"options": {"columnLabl": "test"}}`, err: "invalid key for options {columnLabl:test}"},
}
for _, test := range tests {
actual := &postDBRequest{}
@ -50,12 +49,11 @@ func TestPostFrameRequestUnmarshalJSON(t *testing.T) {
expected postFrameRequest
err string
}{
{json: `{"db": "d", "frame":"f", "options": {}}`, expected: postFrameRequest{DB: "d", Frame: "f", Options: FrameOptions{}}},
{json: `{"db": "d", "options": {}}`, err: "frame required and must be a string"},
{json: `{"db": "d", "frame":"f", "options": 4}`, err: "options is not map[string]interface{}"},
{json: `{"db": "d", "frame":"f", "option": {}}`, err: "Unknown key: {option:map[]}"},
{json: `{"db": "d", "frame":"f", "options": {"rowLabel": "test"}}`, expected: postFrameRequest{DB: "d", Frame: "f", Options: FrameOptions{RowLabel: "test"}}},
{json: `{"db": "d", "frame":"f", "options": {"rowLabl": "test"}}`, err: "invalid key for options {rowLabl:test}"},
{json: `{"options": {}}`, expected: postFrameRequest{Options: FrameOptions{}}},
{json: `{"options": 4}`, err: "options is not map[string]interface{}"},
{json: `{"option": {}}`, err: "Unknown key: {option:map[]}"},
{json: `{"options": {"rowLabel": "test"}}`, expected: postFrameRequest{Options: FrameOptions{RowLabel: "test"}}},
{json: `{"options": {"rowLabl": "test"}}`, err: "invalid key for options {rowLabl:test}"},
}
for _, test := range tests {
actual := &postFrameRequest{}

View file

@ -143,7 +143,7 @@ func TestHandler_Query_Args_URL(t *testing.T) {
}
w := httptest.NewRecorder()
h.ServeHTTP(w, MustNewHTTPRequest("POST", "/query?db=db0&slices=0,1", strings.NewReader("Count( Bitmap( id=100))")))
h.ServeHTTP(w, MustNewHTTPRequest("POST", "/db/db0/query?slices=0,1", strings.NewReader("Count( Bitmap( id=100))")))
if w.Code != http.StatusOK {
t.Fatalf("unexpected status code: %d", w.Code, w.Body.String())
} else if body := w.Body.String(); body != `{"results":[100]}`+"\n" {
@ -167,7 +167,6 @@ func TestHandler_Query_Args_Protobuf(t *testing.T) {
// Generate request body.
reqBody, err := proto.Marshal(&internal.QueryRequest{
DB: "db0",
Query: "Count(Bitmap(id=100))",
Slices: []uint64{0, 1},
})
@ -176,7 +175,7 @@ func TestHandler_Query_Args_Protobuf(t *testing.T) {
}
// Generate protobuf request.
req := MustNewHTTPRequest("POST", "/query", bytes.NewReader(reqBody))
req := MustNewHTTPRequest("POST", "/db/db0/query", bytes.NewReader(reqBody))
req.Header.Set("Content-Type", "application/x-protobuf")
w := httptest.NewRecorder()
@ -189,7 +188,7 @@ func TestHandler_Query_Args_Protobuf(t *testing.T) {
// Ensure the handler returns an error when parsing bad arguments.
func TestHandler_Query_Args_Err(t *testing.T) {
w := httptest.NewRecorder()
NewHandler().ServeHTTP(w, MustNewHTTPRequest("POST", "/query?db=db0&slices=a,b", strings.NewReader("Bitmap(id=100)")))
NewHandler().ServeHTTP(w, MustNewHTTPRequest("POST", "/db/db0/query?slices=a,b", strings.NewReader("Bitmap(id=100)")))
if w.Code != http.StatusBadRequest {
t.Fatalf("unexpected status code: %d", w.Code)
} else if body := w.Body.String(); body != `{"error":"invalid slice argument"}`+"\n" {
@ -205,7 +204,7 @@ func TestHandler_Query_Uint64_JSON(t *testing.T) {
}
w := httptest.NewRecorder()
h.ServeHTTP(w, MustNewHTTPRequest("POST", "/query?db=db0&slices=0,1", strings.NewReader("Count( Bitmap( id=100))")))
h.ServeHTTP(w, MustNewHTTPRequest("POST", "/db/db0/query?slices=0,1", strings.NewReader("Count( Bitmap( id=100))")))
if w.Code != http.StatusOK {
t.Fatalf("unexpected status code: %d", w.Code)
} else if body := w.Body.String(); body != `{"results":[100]}`+"\n" {
@ -221,7 +220,7 @@ func TestHandler_Query_Uint64_Protobuf(t *testing.T) {
}
w := httptest.NewRecorder()
r := MustNewHTTPRequest("POST", "/query", strings.NewReader("Count(Bitmap(id=100))"))
r := MustNewHTTPRequest("POST", "/db/d/query", strings.NewReader("Count(Bitmap(id=100))"))
r.Header.Set("Accept", "application/x-protobuf")
h.ServeHTTP(w, r)
if w.Code != http.StatusOK {
@ -246,7 +245,7 @@ func TestHandler_Query_Bitmap_JSON(t *testing.T) {
}
w := httptest.NewRecorder()
h.ServeHTTP(w, MustNewHTTPRequest("POST", "/query?db=d", strings.NewReader("Bitmap(id=100)")))
h.ServeHTTP(w, MustNewHTTPRequest("POST", "/db/d/query", strings.NewReader("Bitmap(id=100)")))
if w.Code != http.StatusOK {
t.Fatalf("unexpected status code: %d", w.Code)
} else if body := w.Body.String(); body != `{"results":[{"attrs":{"a":"b","c":1,"d":true},"bits":[1,3,66,1048577]}]}`+"\n" {
@ -278,7 +277,7 @@ func TestHandler_Query_Bitmap_Profiles_JSON(t *testing.T) {
}
w := httptest.NewRecorder()
h.ServeHTTP(w, MustNewHTTPRequest("POST", "/query?db=d&profiles=true", strings.NewReader("Bitmap(id=100)")))
h.ServeHTTP(w, MustNewHTTPRequest("POST", "/db/d/query?profiles=true", strings.NewReader("Bitmap(id=100)")))
if w.Code != http.StatusOK {
t.Fatalf("unexpected status code: %d", w.Code)
} else if body := w.Body.String(); body != `{"results":[{"attrs":{"a":"b","c":1,"d":true},"bits":[1,3,66,1048577]}],"profiles":[{"id":3,"attrs":{"x":"y"}},{"id":66,"attrs":{"y":123,"z":false}}]}`+"\n" {
@ -296,7 +295,7 @@ func TestHandler_Query_Bitmap_Protobuf(t *testing.T) {
}
w := httptest.NewRecorder()
r := MustNewHTTPRequest("POST", "/query", strings.NewReader("Bitmap(id=100)"))
r := MustNewHTTPRequest("POST", "/db/d/query", strings.NewReader("Bitmap(id=100)"))
r.Header.Set("Accept", "application/x-protobuf")
h.ServeHTTP(w, r)
if w.Code != http.StatusOK {
@ -342,7 +341,6 @@ func TestHandler_Query_Bitmap_Profiles_Protobuf(t *testing.T) {
// Encode request body.
buf, err := proto.Marshal(&internal.QueryRequest{
DB: "d",
Query: "Bitmap(id=100)",
Profiles: true,
})
@ -351,7 +349,7 @@ func TestHandler_Query_Bitmap_Profiles_Protobuf(t *testing.T) {
}
w := httptest.NewRecorder()
r := MustNewHTTPRequest("POST", "/query", bytes.NewReader(buf))
r := MustNewHTTPRequest("POST", "/db/d/query", bytes.NewReader(buf))
r.Header.Set("Content-Type", "application/x-protobuf")
r.Header.Set("Accept", "application/x-protobuf")
h.ServeHTTP(w, r)
@ -397,7 +395,7 @@ func TestHandler_Query_Pairs_JSON(t *testing.T) {
}
w := httptest.NewRecorder()
h.ServeHTTP(w, MustNewHTTPRequest("POST", "/query", strings.NewReader(`TopN(frame=x, n=2)`)))
h.ServeHTTP(w, MustNewHTTPRequest("POST", "/db/d/query", strings.NewReader(`TopN(frame=x, n=2)`)))
if w.Code != http.StatusOK {
t.Fatalf("unexpected status code: %d", w.Code)
} else if body := w.Body.String(); body != `{"results":[[{"id":1,"count":2},{"id":3,"count":4}]]}`+"\n" {
@ -416,7 +414,7 @@ func TestHandler_Query_Pairs_Protobuf(t *testing.T) {
}
w := httptest.NewRecorder()
r := MustNewHTTPRequest("POST", "/query", strings.NewReader(`TopN(frame=x, n=2)`))
r := MustNewHTTPRequest("POST", "/db/d/query", strings.NewReader(`TopN(frame=x, n=2)`))
r.Header.Set("Accept", "application/x-protobuf")
h.ServeHTTP(w, r)
if w.Code != http.StatusOK {
@ -439,7 +437,7 @@ func TestHandler_Query_Err_JSON(t *testing.T) {
}
w := httptest.NewRecorder()
h.ServeHTTP(w, MustNewHTTPRequest("POST", "/query", strings.NewReader(`Bitmap(id=100)`)))
h.ServeHTTP(w, MustNewHTTPRequest("POST", "/db/d/query", strings.NewReader(`Bitmap(id=100)`)))
if w.Code != http.StatusInternalServerError {
t.Fatalf("unexpected status code: %d", w.Code)
} else if body := w.Body.String(); body != `{"error":"marker"}`+"\n" {
@ -455,7 +453,7 @@ func TestHandler_Query_Err_Protobuf(t *testing.T) {
}
w := httptest.NewRecorder()
r := MustNewHTTPRequest("POST", "/query", strings.NewReader(`TopN(frame=x, n=2)`))
r := MustNewHTTPRequest("POST", "/db/d/query", strings.NewReader(`TopN(frame=x, n=2)`))
r.Header.Set("Accept", "application/x-protobuf")
h.ServeHTTP(w, r)
if w.Code != http.StatusInternalServerError {
@ -473,7 +471,7 @@ func TestHandler_Query_Err_Protobuf(t *testing.T) {
// Ensure the handler returns "method not allowed" for non-POST queries.
func TestHandler_Query_MethodNotAllowed(t *testing.T) {
w := httptest.NewRecorder()
NewHandler().ServeHTTP(w, MustNewHTTPRequest("GET", "/query", nil))
NewHandler().ServeHTTP(w, MustNewHTTPRequest("GET", "/db/d/query", nil))
if w.Code != http.StatusMethodNotAllowed {
t.Fatalf("invalid status: %d", w.Code)
}
@ -483,7 +481,7 @@ func TestHandler_Query_MethodNotAllowed(t *testing.T) {
func TestHandler_Query_ErrParse(t *testing.T) {
h := NewHandler()
w := httptest.NewRecorder()
h.ServeHTTP(w, MustNewHTTPRequest("POST", "/query?db=db0&slices=0,1", strings.NewReader("bad_fn(")))
h.ServeHTTP(w, MustNewHTTPRequest("POST", "/db/db0/query?slices=0,1", strings.NewReader("bad_fn(")))
if w.Code != http.StatusBadRequest {
t.Fatalf("unexpected status code: %d", w.Code)
} else if body := w.Body.String(); body != `{"error":"expected comma, right paren, or identifier, found \"\" occurred at line 1, char 8"}`+"\n" {
@ -506,7 +504,7 @@ func TestHandler_DB_Delete(t *testing.T) {
}
// Send request to delete database.
resp, err := http.DefaultClient.Do(MustNewHTTPRequest("DELETE", s.URL+"/db", strings.NewReader(`{"db":"d"}`)))
resp, err := http.DefaultClient.Do(MustNewHTTPRequest("DELETE", s.URL+"/db/d", strings.NewReader("")))
if err != nil {
t.Fatal(err)
}
@ -539,7 +537,7 @@ func TestHandler_DeleteFrame(t *testing.T) {
h := NewHandler()
h.Index = idx.Index
w := httptest.NewRecorder()
h.ServeHTTP(w, MustNewHTTPRequest("DELETE", "/frame", strings.NewReader(`{"db":"d0","frame":"f1"}`)))
h.ServeHTTP(w, MustNewHTTPRequest("DELETE", "/db/d0/frame/f1", strings.NewReader("")))
if w.Code != http.StatusOK {
t.Fatalf("unexpected status code: %d", w.Code)
} else if body := w.Body.String(); body != `{}`+"\n" {
@ -558,7 +556,7 @@ func TestHandler_SetDBTimeQuantum(t *testing.T) {
h := NewHandler()
h.Index = idx.Index
w := httptest.NewRecorder()
h.ServeHTTP(w, MustNewHTTPRequest("PATCH", "/db/time_quantum", strings.NewReader(`{"db":"d0","time_quantum":"ymdh"}`)))
h.ServeHTTP(w, MustNewHTTPRequest("PATCH", "/db/d0/time-quantum", strings.NewReader(`{"time_quantum":"ymdh"}`)))
if w.Code != http.StatusOK {
t.Fatalf("unexpected status code: %d", w.Code)
} else if body := w.Body.String(); body != `{}`+"\n" {
@ -581,7 +579,7 @@ func TestHandler_SetFrameTimeQuantum(t *testing.T) {
h := NewHandler()
h.Index = idx.Index
w := httptest.NewRecorder()
h.ServeHTTP(w, MustNewHTTPRequest("PATCH", "/frame/time_quantum", strings.NewReader(`{"db":"d0","frame":"f1","time_quantum":"ymdh"}`)))
h.ServeHTTP(w, MustNewHTTPRequest("PATCH", "/db/d0/frame/f1/time-quantum", strings.NewReader(`{"time_quantum":"ymdh"}`)))
if w.Code != http.StatusOK {
t.Fatalf("unexpected status code: %d", w.Code)
} else if body := w.Body.String(); body != `{}`+"\n" {
@ -625,9 +623,9 @@ func TestHandler_DB_AttrStore_Diff(t *testing.T) {
// Send block checksums to determine diff.
resp, err := http.Post(
s.URL+"/db/attr/diff?db=d",
s.URL+"/db/d/attr/diff",
"application/json",
strings.NewReader(`{"db":"d", "blocks":`+string(MustMarshalJSON(blks))+`}`),
strings.NewReader(`{"blocks":`+string(MustMarshalJSON(blks))+`}`),
)
if err != nil {
t.Fatal(err)
@ -675,9 +673,9 @@ func TestHandler_Frame_AttrStore_Diff(t *testing.T) {
// Send block checksums to determine diff.
resp, err := http.Post(
s.URL+"/frame/attr/diff?db=d",
s.URL+"/db/d/frame/meta/attr/diff",
"application/json",
strings.NewReader(`{"db":"d", "frame":"meta", "blocks":`+string(MustMarshalJSON(blks))+`}`),
strings.NewReader(`{"blocks":`+string(MustMarshalJSON(blks))+`}`),
)
if err != nil {
t.Fatal(err)

View file

@ -125,12 +125,11 @@ func (m *AttrMap) GetAttrs() []*Attr {
}
type QueryRequest struct {
DB string `protobuf:"bytes,1,opt,name=DB,proto3" json:"DB,omitempty"`
Query string `protobuf:"bytes,2,opt,name=Query,proto3" json:"Query,omitempty"`
Slices []uint64 `protobuf:"varint,3,rep,packed,name=Slices" json:"Slices,omitempty"`
Profiles bool `protobuf:"varint,4,opt,name=Profiles,proto3" json:"Profiles,omitempty"`
Quantum string `protobuf:"bytes,5,opt,name=Quantum,proto3" json:"Quantum,omitempty"`
Remote bool `protobuf:"varint,6,opt,name=Remote,proto3" json:"Remote,omitempty"`
Query string `protobuf:"bytes,1,opt,name=Query,proto3" json:"Query,omitempty"`
Slices []uint64 `protobuf:"varint,2,rep,packed,name=Slices" json:"Slices,omitempty"`
Profiles bool `protobuf:"varint,3,opt,name=Profiles,proto3" json:"Profiles,omitempty"`
Quantum string `protobuf:"bytes,4,opt,name=Quantum,proto3" json:"Quantum,omitempty"`
Remote bool `protobuf:"varint,5,opt,name=Remote,proto3" json:"Remote,omitempty"`
}
func (m *QueryRequest) Reset() { *m = QueryRequest{} }
@ -458,14 +457,8 @@ func (m *QueryRequest) MarshalTo(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if len(m.DB) > 0 {
dAtA[i] = 0xa
i++
i = encodeVarintPublic(dAtA, i, uint64(len(m.DB)))
i += copy(dAtA[i:], m.DB)
}
if len(m.Query) > 0 {
dAtA[i] = 0x12
dAtA[i] = 0xa
i++
i = encodeVarintPublic(dAtA, i, uint64(len(m.Query)))
i += copy(dAtA[i:], m.Query)
@ -482,13 +475,13 @@ func (m *QueryRequest) MarshalTo(dAtA []byte) (int, error) {
dAtA4[j3] = uint8(num)
j3++
}
dAtA[i] = 0x1a
dAtA[i] = 0x12
i++
i = encodeVarintPublic(dAtA, i, uint64(j3))
i += copy(dAtA[i:], dAtA4[:j3])
}
if m.Profiles {
dAtA[i] = 0x20
dAtA[i] = 0x18
i++
if m.Profiles {
dAtA[i] = 1
@ -498,13 +491,13 @@ func (m *QueryRequest) MarshalTo(dAtA []byte) (int, error) {
i++
}
if len(m.Quantum) > 0 {
dAtA[i] = 0x2a
dAtA[i] = 0x22
i++
i = encodeVarintPublic(dAtA, i, uint64(len(m.Quantum)))
i += copy(dAtA[i:], m.Quantum)
}
if m.Remote {
dAtA[i] = 0x30
dAtA[i] = 0x28
i++
if m.Remote {
dAtA[i] = 1
@ -835,10 +828,6 @@ func (m *AttrMap) Size() (n int) {
func (m *QueryRequest) Size() (n int) {
var l int
_ = l
l = len(m.DB)
if l > 0 {
n += 1 + l + sovPublic(uint64(l))
}
l = len(m.Query)
if l > 0 {
n += 1 + l + sovPublic(uint64(l))
@ -1691,35 +1680,6 @@ func (m *QueryRequest) Unmarshal(dAtA []byte) error {
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field DB", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowPublic
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthPublic
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.DB = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Query", wireType)
}
@ -1748,7 +1708,7 @@ func (m *QueryRequest) Unmarshal(dAtA []byte) error {
}
m.Query = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
case 2:
if wireType == 2 {
var packedLen int
for shift := uint(0); ; shift += 7 {
@ -1810,7 +1770,7 @@ func (m *QueryRequest) Unmarshal(dAtA []byte) error {
} else {
return fmt.Errorf("proto: wrong wireType = %d for field Slices", wireType)
}
case 4:
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Profiles", wireType)
}
@ -1830,7 +1790,7 @@ func (m *QueryRequest) Unmarshal(dAtA []byte) error {
}
}
m.Profiles = bool(v != 0)
case 5:
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Quantum", wireType)
}
@ -1859,7 +1819,7 @@ func (m *QueryRequest) Unmarshal(dAtA []byte) error {
}
m.Quantum = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 6:
case 5:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Remote", wireType)
}
@ -2616,40 +2576,40 @@ func init() { proto.RegisterFile("public.proto", fileDescriptorPublic) }
var fileDescriptorPublic = []byte{
// 570 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x54, 0xcb, 0x6e, 0xd3, 0x40,
0x14, 0x65, 0x62, 0xe7, 0x75, 0x93, 0x56, 0x61, 0x04, 0xc8, 0x42, 0x28, 0xb2, 0x2c, 0x16, 0xde,
0x90, 0x4a, 0xe5, 0x03, 0x10, 0x6e, 0x5a, 0xc9, 0x42, 0x54, 0xed, 0xb4, 0x62, 0xc7, 0xc2, 0x2d,
0x43, 0xb1, 0xe4, 0x17, 0x33, 0xe3, 0x45, 0x96, 0x2c, 0xf8, 0x07, 0xc4, 0x17, 0xc0, 0x9f, 0xb0,
0xe4, 0x13, 0x50, 0xf8, 0x11, 0x74, 0xe7, 0x61, 0x7b, 0x55, 0xb1, 0x9b, 0x73, 0x4e, 0xee, 0xf8,
0x9e, 0x39, 0xf7, 0x06, 0x96, 0x4d, 0x7b, 0x53, 0xe4, 0xb7, 0x9b, 0x46, 0xd4, 0xaa, 0xa6, 0xb3,
0xbc, 0x52, 0x5c, 0x54, 0x59, 0x11, 0x25, 0x30, 0x49, 0x72, 0x55, 0x66, 0x0d, 0xa5, 0xe0, 0x27,
0xb9, 0x92, 0x01, 0x09, 0xbd, 0xd8, 0x67, 0xfa, 0x4c, 0x9f, 0xc3, 0xf8, 0xb5, 0x52, 0x42, 0x06,
0xa3, 0xd0, 0x8b, 0x17, 0xc7, 0x87, 0x1b, 0x57, 0xb7, 0x41, 0x9a, 0x19, 0x31, 0xda, 0x80, 0x7f,
0x91, 0xe5, 0x82, 0xae, 0xc0, 0x7b, 0xc3, 0x77, 0x01, 0x09, 0x49, 0xec, 0x33, 0x3c, 0xd2, 0x47,
0x30, 0x3e, 0xa9, 0xdb, 0x4a, 0x05, 0x23, 0xcd, 0x19, 0x10, 0xbd, 0x07, 0x2f, 0xc9, 0x15, 0x7d,
0x0a, 0x33, 0xf3, 0xe9, 0x74, 0x6b, 0x6b, 0x3a, 0x4c, 0x9f, 0xc1, 0xfc, 0x42, 0xd4, 0x1f, 0xf3,
0x82, 0xa7, 0x5b, 0x5b, 0xdc, 0x13, 0xa8, 0x5e, 0xe7, 0x25, 0x97, 0x2a, 0x2b, 0x9b, 0xc0, 0x0b,
0x49, 0xec, 0xb1, 0x9e, 0x88, 0x5e, 0xc1, 0xd4, 0xfe, 0x94, 0x1e, 0xc2, 0xa8, 0xbb, 0x7c, 0x94,
0x6e, 0xff, 0xd3, 0xcf, 0x0f, 0x02, 0x3e, 0x9e, 0x86, 0x86, 0xe6, 0xc6, 0x10, 0x05, 0xff, 0x7a,
0xd7, 0x70, 0xdb, 0x92, 0x3e, 0xd3, 0x10, 0x16, 0x57, 0x4a, 0xe4, 0xd5, 0xdd, 0xbb, 0xac, 0x68,
0xb9, 0xee, 0x67, 0xce, 0x86, 0x14, 0x3a, 0x4d, 0x2b, 0x65, 0x64, 0x5f, 0xb7, 0xdb, 0x61, 0xf4,
0x92, 0xd4, 0x75, 0x61, 0xc4, 0x71, 0x48, 0xe2, 0x19, 0xeb, 0x09, 0xba, 0x06, 0x38, 0x2b, 0xea,
0xcc, 0xd6, 0x4e, 0x42, 0x12, 0x13, 0x36, 0x60, 0xa2, 0x23, 0x98, 0x62, 0xa7, 0x6f, 0xb3, 0xa6,
0xf7, 0x46, 0xee, 0xf3, 0xf6, 0x9d, 0xc0, 0xf2, 0xb2, 0xe5, 0x62, 0xc7, 0xf8, 0xe7, 0x96, 0x4b,
0x85, 0x4f, 0xb4, 0x4d, 0xac, 0xc5, 0xd1, 0x36, 0xc1, 0xc8, 0xb4, 0xae, 0x2d, 0xce, 0x99, 0x01,
0xf4, 0x09, 0x4c, 0xae, 0x8a, 0xfc, 0x96, 0xcb, 0xc0, 0xd3, 0xe3, 0x61, 0x11, 0x3a, 0xb3, 0x6f,
0x2d, 0xb5, 0xb3, 0x19, 0xeb, 0x30, 0x0d, 0x60, 0x7a, 0xd9, 0x66, 0x95, 0x6a, 0x4b, 0xed, 0x6b,
0xce, 0x1c, 0xc4, 0xdb, 0x18, 0x2f, 0x6b, 0x65, 0x1c, 0xcd, 0x98, 0x45, 0xd1, 0x17, 0x02, 0x07,
0xb6, 0x39, 0xd9, 0xd4, 0x95, 0xe4, 0x98, 0xc0, 0xa9, 0x10, 0x2e, 0x81, 0x53, 0x21, 0xe8, 0x11,
0x4c, 0x19, 0x97, 0x6d, 0xa1, 0x5c, 0x88, 0x8f, 0x7b, 0xa3, 0xae, 0xb6, 0x2d, 0x14, 0x73, 0xbf,
0xa2, 0x2f, 0x06, 0x2d, 0x7a, 0xba, 0xe2, 0x61, 0x5f, 0x61, 0x95, 0xbe, 0xeb, 0xe8, 0x2b, 0x81,
0xc5, 0xe0, 0x1e, 0x1a, 0xbb, 0x05, 0xd1, 0x4d, 0x2c, 0x8e, 0x57, 0x7d, 0xb1, 0xe1, 0x99, 0x5b,
0xa0, 0x25, 0x90, 0x73, 0x3b, 0x18, 0xe4, 0x1c, 0xe3, 0xc0, 0xa5, 0x70, 0xdf, 0x1c, 0xc4, 0x81,
0x34, 0x33, 0x22, 0xbe, 0xd1, 0xc9, 0xa7, 0xac, 0xba, 0xe3, 0x1f, 0xec, 0xf3, 0x39, 0x18, 0xfd,
0x24, 0x70, 0x90, 0x96, 0x4d, 0x2d, 0xd4, 0x3d, 0x49, 0x9d, 0x89, 0xac, 0xe4, 0x2e, 0x29, 0x0d,
0x90, 0xd5, 0xd9, 0xe8, 0x39, 0xf4, 0x99, 0x01, 0x7a, 0xca, 0xec, 0x6e, 0x61, 0x50, 0x18, 0x61,
0x4f, 0xe0, 0x94, 0x75, 0xcb, 0x25, 0x83, 0xb1, 0x96, 0x07, 0x0c, 0xea, 0xdd, 0x7a, 0xc9, 0x60,
0x12, 0x7a, 0xb1, 0xc7, 0x06, 0x4c, 0xb2, 0xfa, 0xb5, 0x5f, 0x93, 0xdf, 0xfb, 0x35, 0xf9, 0xb3,
0x5f, 0x93, 0x6f, 0x7f, 0xd7, 0x0f, 0x6e, 0x26, 0xfa, 0x7f, 0xe6, 0xe5, 0xbf, 0x00, 0x00, 0x00,
0xff, 0xff, 0x36, 0x47, 0xff, 0x96, 0x77, 0x04, 0x00, 0x00,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x54, 0x4b, 0x6e, 0xd4, 0x40,
0x10, 0xa5, 0x6d, 0xcf, 0xaf, 0x26, 0x19, 0x0d, 0x2d, 0x40, 0x16, 0x42, 0x23, 0xcb, 0x62, 0xe1,
0x0d, 0x13, 0x29, 0x1c, 0x00, 0xe1, 0x4c, 0x22, 0x8d, 0x10, 0x51, 0xd2, 0x89, 0xd8, 0xb1, 0x70,
0x42, 0x13, 0x2c, 0xf9, 0x47, 0x77, 0x7b, 0x31, 0x4b, 0x16, 0x6c, 0x38, 0x01, 0x47, 0x80, 0x9b,
0xb0, 0xe4, 0x08, 0x68, 0xb8, 0x08, 0xaa, 0xfe, 0xd8, 0x66, 0x83, 0xd8, 0xf5, 0x7b, 0xe5, 0xea,
0xae, 0xf7, 0xaa, 0xca, 0x70, 0xd0, 0xb4, 0x37, 0x45, 0x7e, 0xbb, 0x6e, 0x44, 0xad, 0x6a, 0x3a,
0xcd, 0x2b, 0xc5, 0x45, 0x95, 0x15, 0x71, 0x0a, 0xe3, 0x34, 0x57, 0x65, 0xd6, 0x50, 0x0a, 0x41,
0x9a, 0x2b, 0x19, 0x92, 0xc8, 0x4f, 0x02, 0xa6, 0xcf, 0xf4, 0x29, 0x8c, 0x5e, 0x2a, 0x25, 0x64,
0xe8, 0x45, 0x7e, 0x32, 0x3f, 0x5e, 0xac, 0x5d, 0xde, 0x1a, 0x69, 0x66, 0x82, 0xf1, 0x1a, 0x82,
0x8b, 0x2c, 0x17, 0x74, 0x09, 0xfe, 0x2b, 0xbe, 0x0b, 0x49, 0x44, 0x92, 0x80, 0xe1, 0x91, 0x3e,
0x80, 0xd1, 0x49, 0xdd, 0x56, 0x2a, 0xf4, 0x34, 0x67, 0x40, 0xfc, 0x16, 0xfc, 0x34, 0x57, 0xf4,
0x31, 0x4c, 0xcd, 0xd3, 0xdb, 0x8d, 0xcd, 0xe9, 0x30, 0x7d, 0x02, 0xb3, 0x0b, 0x51, 0xbf, 0xcf,
0x0b, 0xbe, 0xdd, 0xd8, 0xe4, 0x9e, 0xc0, 0xe8, 0x75, 0x5e, 0x72, 0xa9, 0xb2, 0xb2, 0x09, 0xfd,
0x88, 0x24, 0x3e, 0xeb, 0x89, 0xf8, 0x05, 0x4c, 0xec, 0xa7, 0x74, 0x01, 0x5e, 0x77, 0xb9, 0xb7,
0xdd, 0xfc, 0xa7, 0x9e, 0x6f, 0x04, 0x02, 0x3c, 0x0d, 0x05, 0xcd, 0x8c, 0x20, 0x0a, 0xc1, 0xf5,
0xae, 0xe1, 0xb6, 0x24, 0x7d, 0xa6, 0x11, 0xcc, 0xaf, 0x94, 0xc8, 0xab, 0xbb, 0x37, 0x59, 0xd1,
0x72, 0x5d, 0xcf, 0x8c, 0x0d, 0x29, 0x54, 0xba, 0xad, 0x94, 0x09, 0x07, 0xba, 0xdc, 0x0e, 0xa3,
0x96, 0xb4, 0xae, 0x0b, 0x13, 0x1c, 0x45, 0x24, 0x99, 0xb2, 0x9e, 0xa0, 0x2b, 0x80, 0xb3, 0xa2,
0xce, 0x6c, 0xee, 0x38, 0x22, 0x09, 0x61, 0x03, 0x26, 0x3e, 0x82, 0x09, 0x56, 0xfa, 0x3a, 0x6b,
0x7a, 0x6d, 0xe4, 0x5f, 0xda, 0xbe, 0x10, 0x38, 0xb8, 0x6c, 0xb9, 0xd8, 0x31, 0xfe, 0xb1, 0xe5,
0x52, 0x61, 0x8b, 0x34, 0xb6, 0x2a, 0x0d, 0xa0, 0x8f, 0x60, 0x7c, 0x55, 0xe4, 0xb7, 0xdc, 0x38,
0x15, 0x30, 0x8b, 0x50, 0x89, 0xf5, 0x56, 0x6a, 0xa1, 0x53, 0xd6, 0x61, 0x1a, 0xc2, 0xe4, 0xb2,
0xcd, 0x2a, 0xd5, 0x96, 0x5a, 0xe4, 0x8c, 0x39, 0x88, 0xb7, 0x31, 0x5e, 0xd6, 0xca, 0x09, 0xb4,
0x28, 0xfe, 0x44, 0xe0, 0xd0, 0x16, 0x23, 0x9b, 0xba, 0x92, 0x1c, 0x1d, 0x3f, 0x15, 0xc2, 0x39,
0x7e, 0x2a, 0x04, 0x3d, 0x82, 0x09, 0xe3, 0xb2, 0x2d, 0x94, 0x6b, 0xda, 0xc3, 0x5e, 0x98, 0xcb,
0x6d, 0x0b, 0xc5, 0xdc, 0x57, 0xf4, 0xd9, 0x5f, 0x25, 0x62, 0xc6, 0xfd, 0x3e, 0xc3, 0x46, 0xfa,
0xaa, 0xe3, 0xcf, 0x04, 0xe6, 0x83, 0x7b, 0x68, 0xe2, 0x16, 0x42, 0x17, 0x31, 0x3f, 0x5e, 0xf6,
0xc9, 0x86, 0x67, 0x6e, 0x61, 0x0e, 0x80, 0x9c, 0xdb, 0x41, 0x20, 0xe7, 0x68, 0x3f, 0x2e, 0x81,
0x7b, 0x73, 0x60, 0x3f, 0xd2, 0xcc, 0x04, 0xd1, 0xa3, 0x93, 0x0f, 0x59, 0x75, 0xc7, 0xdf, 0x69,
0x8f, 0xa6, 0xcc, 0xc1, 0xf8, 0x3b, 0x81, 0xc3, 0x6d, 0xd9, 0xd4, 0x42, 0xb9, 0xce, 0x2c, 0xc0,
0xdb, 0xa4, 0xd6, 0x0a, 0x6f, 0x93, 0x62, 0xa7, 0xce, 0x44, 0x56, 0x9a, 0xe1, 0x9b, 0x31, 0x03,
0x90, 0xd5, 0xbd, 0xd1, 0xed, 0x08, 0x98, 0x01, 0x7a, 0xaa, 0xec, 0x2e, 0xc9, 0x30, 0xd0, 0x2d,
0xec, 0x09, 0x9c, 0xaa, 0x6e, 0x99, 0x64, 0x38, 0xd2, 0xe1, 0x01, 0x83, 0xf1, 0x6e, 0x9d, 0x64,
0x38, 0x8e, 0xfc, 0xc4, 0x67, 0x03, 0x26, 0x5d, 0xfe, 0xd8, 0xaf, 0xc8, 0xcf, 0xfd, 0x8a, 0xfc,
0xda, 0xaf, 0xc8, 0xd7, 0xdf, 0xab, 0x7b, 0x37, 0x63, 0xfd, 0x5f, 0x79, 0xfe, 0x27, 0x00, 0x00,
0xff, 0xff, 0x37, 0xb6, 0x15, 0x22, 0x67, 0x04, 0x00, 0x00,
}

View file

@ -37,12 +37,11 @@ message AttrMap {
}
message QueryRequest {
string DB = 1;
string Query = 2;
repeated uint64 Slices = 3;
bool Profiles = 4;
string Quantum = 5;
bool Remote = 6;
string Query = 1;
repeated uint64 Slices = 2;
bool Profiles = 3;
string Quantum = 4;
bool Remote = 5;
}
message QueryResponse {

View file

@ -45,7 +45,7 @@ func TestMain_Set_Quick(t *testing.T) {
if err := client.CreateFrame(context.Background(), "d", cmd.Frame, pilosa.FrameOptions{}); err != nil && err != pilosa.ErrFrameExists {
t.Fatal(err)
}
if _, err := m.Query("db=d", fmt.Sprintf(`SetBit(id=%d, frame=%q, profileID=%d)`, cmd.ID, cmd.Frame, cmd.ProfileID)); err != nil {
if _, err := m.Query("d", "", fmt.Sprintf(`SetBit(id=%d, frame=%q, profileID=%d)`, cmd.ID, cmd.Frame, cmd.ProfileID)); err != nil {
t.Fatal(err)
}
}
@ -61,7 +61,7 @@ func TestMain_Set_Quick(t *testing.T) {
},
},
}) + "\n"
if res, err := m.Query("db=d", fmt.Sprintf(`Bitmap(id=%d, frame=%q)`, id, frame)); err != nil {
if res, err := m.Query("d", "", fmt.Sprintf(`Bitmap(id=%d, frame=%q)`, id, frame)); err != nil {
t.Fatal(err)
} else if res != exp {
t.Fatalf("unexpected result:\n\ngot=%s\n\nexp=%s\n\n", res, exp)
@ -84,7 +84,7 @@ func TestMain_Set_Quick(t *testing.T) {
},
},
}) + "\n"
if res, err := m.Query("db=d", fmt.Sprintf(`Bitmap(id=%d, frame=%q)`, id, frame)); err != nil {
if res, err := m.Query("d", "", fmt.Sprintf(`Bitmap(id=%d, frame=%q)`, id, frame)); err != nil {
t.Fatal(err)
} else if res != exp {
t.Fatalf("unexpected result (reopen):\n\ngot=%s\n\nexp=%s\n\n", res, exp)
@ -120,36 +120,36 @@ func TestMain_SetBitmapAttrs(t *testing.T) {
}
// Set bits on different bitmaps in different frames.
if _, err := m.Query("db=d", `SetBit(id=1, frame="x.n", profileID=100)`); err != nil {
if _, err := m.Query("d", "", `SetBit(id=1, frame="x.n", profileID=100)`); err != nil {
t.Fatal(err)
} else if _, err := m.Query("db=d", `SetBit(id=2, frame="x.n", profileID=100)`); err != nil {
} else if _, err := m.Query("d", "", `SetBit(id=2, frame="x.n", profileID=100)`); err != nil {
t.Fatal(err)
} else if _, err := m.Query("db=d", `SetBit(id=2, frame="z", profileID=100)`); err != nil {
} else if _, err := m.Query("d", "", `SetBit(id=2, frame="z", profileID=100)`); err != nil {
t.Fatal(err)
} else if _, err := m.Query("db=d", `SetBit(id=3, frame="neg", profileID=100)`); err != nil {
} else if _, err := m.Query("d", "", `SetBit(id=3, frame="neg", profileID=100)`); err != nil {
t.Fatal(err)
}
// Set bitmap attributes.
if _, err := m.Query("db=d", `SetBitmapAttrs(id=1, frame="x.n", x=100)`); err != nil {
if _, err := m.Query("d", "", `SetBitmapAttrs(id=1, frame="x.n", x=100)`); err != nil {
t.Fatal(err)
} else if _, err := m.Query("db=d", `SetBitmapAttrs(id=2, frame="x.n", x=-200)`); err != nil {
} else if _, err := m.Query("d", "", `SetBitmapAttrs(id=2, frame="x.n", x=-200)`); err != nil {
t.Fatal(err)
} else if _, err := m.Query("db=d", `SetBitmapAttrs(id=2, frame="z", x=300)`); err != nil {
} else if _, err := m.Query("d", "", `SetBitmapAttrs(id=2, frame="z", x=300)`); err != nil {
t.Fatal(err)
} else if _, err := m.Query("db=d", `SetBitmapAttrs(id=3, frame="neg", x=-0.44)`); err != nil {
} else if _, err := m.Query("d", "", `SetBitmapAttrs(id=3, frame="neg", x=-0.44)`); err != nil {
t.Fatal(err)
}
// Query bitmap x.n/1.
if res, err := m.Query("db=d", `Bitmap(id=1, frame="x.n")`); err != nil {
if res, err := m.Query("d", "", `Bitmap(id=1, frame="x.n")`); err != nil {
t.Fatal(err)
} else if res != `{"results":[{"attrs":{"x":100},"bits":[100]}]}`+"\n" {
t.Fatalf("unexpected result: %s", res)
}
// Query bitmap x.n/2.
if res, err := m.Query("db=d", `Bitmap(id=2, frame="x.n")`); err != nil {
if res, err := m.Query("d", "", `Bitmap(id=2, frame="x.n")`); err != nil {
t.Fatal(err)
} else if res != `{"results":[{"attrs":{"x":-200},"bits":[100]}]}`+"\n" {
t.Fatalf("unexpected result: %s", res)
@ -160,19 +160,19 @@ func TestMain_SetBitmapAttrs(t *testing.T) {
}
// Query bitmaps after reopening.
if res, err := m.Query("db=d&profiles=true", `Bitmap(id=1, frame="x.n")`); err != nil {
if res, err := m.Query("d", "profiles=true", `Bitmap(id=1, frame="x.n")`); err != nil {
t.Fatal(err)
} else if res != `{"results":[{"attrs":{"x":100},"bits":[100]}]}`+"\n" {
t.Fatalf("unexpected result(reopen): %s", res)
}
if res, err := m.Query("db=d&profiles=true", `Bitmap(id=3, frame="neg")`); err != nil {
if res, err := m.Query("d", "profiles=true", `Bitmap(id=3, frame="neg")`); err != nil {
t.Fatal(err)
} else if res != `{"results":[{"attrs":{"x":-0.44},"bits":[100]}]}`+"\n" {
t.Fatalf("unexpected result(reopen): %s", res)
}
// Query bitmap x.n/2.
if res, err := m.Query("db=d", `Bitmap(id=2, frame="x.n")`); err != nil {
if res, err := m.Query("d", "", `Bitmap(id=2, frame="x.n")`); err != nil {
t.Fatal(err)
} else if res != `{"results":[{"attrs":{"x":-200},"bits":[100]}]}`+"\n" {
t.Fatalf("unexpected result: %s", res)
@ -193,19 +193,19 @@ func TestMain_SetProfileAttrs(t *testing.T) {
}
// Set bits on bitmap.
if _, err := m.Query("db=d", `SetBit(id=1, frame="x.n", profileID=100)`); err != nil {
if _, err := m.Query("d", "", `SetBit(id=1, frame="x.n", profileID=100)`); err != nil {
t.Fatal(err)
} else if _, err := m.Query("db=d", `SetBit(id=1, frame="x.n", profileID=101)`); err != nil {
} else if _, err := m.Query("d", "", `SetBit(id=1, frame="x.n", profileID=101)`); err != nil {
t.Fatal(err)
}
// Set profile attributes.
if _, err := m.Query("db=d", `SetProfileAttrs(id=100, foo="bar")`); err != nil {
if _, err := m.Query("d", "", `SetProfileAttrs(id=100, foo="bar")`); err != nil {
t.Fatal(err)
}
// Query bitmap.
if res, err := m.Query("db=d&profiles=true", `Bitmap(id=1, frame="x.n")`); err != nil {
if res, err := m.Query("d", "profiles=true", `Bitmap(id=1, frame="x.n")`); err != nil {
t.Fatal(err)
} else if res != `{"results":[{"attrs":{},"bits":[100,101]}],"profiles":[{"id":100,"attrs":{"foo":"bar"}}]}`+"\n" {
t.Fatalf("unexpected result: %s", res)
@ -216,7 +216,7 @@ func TestMain_SetProfileAttrs(t *testing.T) {
}
// Query bitmap after reopening.
if res, err := m.Query("db=d&profiles=true", `Bitmap(id=1, frame="x.n")`); err != nil {
if res, err := m.Query("d", "profiles=true", `Bitmap(id=1, frame="x.n")`); err != nil {
t.Fatal(err)
} else if res != `{"results":[{"attrs":{},"bits":[100,101]}],"profiles":[{"id":100,"attrs":{"foo":"bar"}}]}`+"\n" {
t.Fatalf("unexpected result(reopen): %s", res)
@ -237,19 +237,19 @@ func TestMain_SetProfileAttrsWithColumnOption(t *testing.T) {
}
// Set bits on bitmap.
if _, err := m.Query("db=d", `SetBit(id=1, frame="x.n", col=100)`); err != nil {
if _, err := m.Query("d", "", `SetBit(id=1, frame="x.n", col=100)`); err != nil {
t.Fatal(err)
} else if _, err := m.Query("db=d", `SetBit(id=1, frame="x.n", col=101)`); err != nil {
} else if _, err := m.Query("d", "", `SetBit(id=1, frame="x.n", col=101)`); err != nil {
t.Fatal(err)
}
// Set profile attributes.
if _, err := m.Query("db=d", `SetProfileAttrs(col=100, foo="bar")`); err != nil {
if _, err := m.Query("d", "", `SetProfileAttrs(col=100, foo="bar")`); err != nil {
t.Fatal(err)
}
// Query bitmap.
if res, err := m.Query("db=d&profiles=true", `Bitmap(id=1, frame="x.n")`); err != nil {
if res, err := m.Query("d", "profiles=true", `Bitmap(id=1, frame="x.n")`); err != nil {
t.Fatal(err)
} else if res != `{"results":[{"attrs":{},"bits":[100,101]}],"profiles":[{"id":100,"attrs":{"foo":"bar"}}]}`+"\n" {
t.Fatalf("unexpected result: %s", res)
@ -281,7 +281,7 @@ func TestMain_FrameRestore(t *testing.T) {
}
// Write data on first cluster.
if _, err := m0.Query("db=d", `
if _, err := m0.Query("d", "", `
SetBit(id=1, frame="f", profileID=100)
SetBit(id=1, frame="f", profileID=1000)
SetBit(id=1, frame="f", profileID=100000)
@ -294,7 +294,7 @@ func TestMain_FrameRestore(t *testing.T) {
}
// Query bitmap on first cluster.
if res, err := m0.Query("db=d", `Bitmap(id=1, frame="f")`); err != nil {
if res, err := m0.Query("d", "", `Bitmap(id=1, frame="f")`); err != nil {
t.Fatal(err)
} else if res != `{"results":[{"attrs":{},"bits":[100,1000,100000,200000,400000,600000,800000]}]}`+"\n" {
t.Fatalf("unexpected result: %s", res)
@ -317,7 +317,7 @@ func TestMain_FrameRestore(t *testing.T) {
}
// Query bitmap on second cluster.
if res, err := m2.Query("db=d", `Bitmap(id=1, frame="f")`); err != nil {
if res, err := m2.Query("d", "", `Bitmap(id=1, frame="f")`); err != nil {
t.Fatal(err)
} else if res != `{"results":[{"attrs":{},"bits":[100,1000,100000,200000,400000,600000,800000]}]}`+"\n" {
t.Fatalf("unexpected result: %s", res)
@ -431,8 +431,8 @@ func (m *Main) Client() *pilosa.Client {
}
// Query executes a query against the program through the HTTP API.
func (m *Main) Query(rawQuery, query string) (string, error) {
resp := MustDo("POST", m.URL()+"/query?"+rawQuery, query)
func (m *Main) Query(db, rawQuery, query string) (string, error) {
resp := MustDo("POST", m.URL()+fmt.Sprintf("/db/%s/query?", db)+rawQuery, query)
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("invalid status: %d, body=%s", resp.StatusCode, resp.Body)
}