diff --git a/client.go b/client.go index 29005c10d..e4401a69a 100644 --- a/client.go +++ b/client.go @@ -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 } diff --git a/executor.go b/executor.go index ef510ffb9..9c156ec56 100644 --- a/executor.go +++ b/executor.go @@ -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 diff --git a/glide.lock b/glide.lock index 001257bf1..7fffeca5e 100644 --- a/glide.lock +++ b/glide.lock @@ -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: diff --git a/glide.yaml b/glide.yaml index 1c4f35dae..d4615b0ba 100644 --- a/glide.yaml +++ b/glide.yaml @@ -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 diff --git a/handler.go b/handler.go index 5b44c51d7..0e25c3f2f 100644 --- a/handler.go +++ b/handler.go @@ -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/ 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, diff --git a/handler_internal_test.go b/handler_internal_test.go index b5ce8c161..8a7bc910f 100644 --- a/handler_internal_test.go +++ b/handler_internal_test.go @@ -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{} diff --git a/handler_test.go b/handler_test.go index 200deb0b3..c19a83a93 100644 --- a/handler_test.go +++ b/handler_test.go @@ -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) diff --git a/internal/public.pb.go b/internal/public.pb.go index 904ed879e..249bbfddf 100644 --- a/internal/public.pb.go +++ b/internal/public.pb.go @@ -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, } diff --git a/internal/public.proto b/internal/public.proto index b62dcc13f..03cfdaabd 100644 --- a/internal/public.proto +++ b/internal/public.proto @@ -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 { diff --git a/server/server_test.go b/server/server_test.go index 64bfa2d42..8cd7c1d24 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -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) }