From ceda4ab61bc04dfdddfc4ec55938d499ca1e6c4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Podg=C3=B3rski?= Date: Mon, 24 Aug 2020 13:24:18 +0200 Subject: [PATCH] Add support for drop table --- server/grpc_test.go | 25 +++++++++++++++++ server/sql.go | 11 +++----- sql/ddl.go | 65 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 sql/ddl.go diff --git a/server/grpc_test.go b/server/grpc_test.go index 4529c0df8..77c030e23 100644 --- a/server/grpc_test.go +++ b/server/grpc_test.go @@ -709,6 +709,7 @@ func TestQuerySQLUnary(t *testing.T) { {"Table", "string"}, }, rows: []row{ + {[]columnResponse{"delete_me"}}, {[]columnResponse{"grouper"}}, {[]columnResponse{"joiner"}}, }, @@ -731,6 +732,27 @@ func TestQuerySQLUnary(t *testing.T) { }, eq: equal, }, + { + sql: "drop table delete_me", + exp: tableResponse{ + headers: []columnInfo{}, + rows: []row{}, + }, + eq: equal, + }, + { + sql: "show tables", + exp: tableResponse{ + headers: []columnInfo{ + {"Table", "string"}, + }, + rows: []row{ + {[]columnResponse{"grouper"}}, + {[]columnResponse{"joiner"}}, + }, + }, + eq: equal, + }, } for i, test := range tests { @@ -881,6 +903,9 @@ func setUpTestQuerySQLUnary(ctx context.Context, t *testing.T) (gh *server.GRPCH } } + // delete_me + m.MustCreateIndex(t, "delete_me", pilosa.IndexOptions{TrackExistence: true}) + return gh, func() { if err := m.API.DeleteIndex(ctx, joiner.Name()); err != nil { panic(err) diff --git a/server/sql.go b/server/sql.go index 0f1de916c..7647e0377 100644 --- a/server/sql.go +++ b/server/sql.go @@ -38,17 +38,14 @@ func execSQL(ctx context.Context, api *pilosa.API, logger logger.Logger, querySt case sql.SQLTypeSelect: handler := sql.NewSelectHandler(api) results, err = handler.Handle(ctx, query) - if err != nil { - return nil, errors.Wrap(err, "failed to start SQL query") - } case sql.SQLTypeShow: handler := sql.NewShowHandler(api) results, err = handler.Handle(ctx, query) - if err != nil { - return nil, errors.Wrap(err, "failed to start SQL query") - } + case sql.SQLTypeEmpty: + handler := sql.NewDDLHandler(api) + results, err = handler.Handle(ctx, query) default: return nil, status.Errorf(codes.Unimplemented, "query type not supported") } - return results, nil + return results, errors.Wrap(err, "failed to start SQL query") } diff --git a/sql/ddl.go b/sql/ddl.go new file mode 100644 index 000000000..3b693850e --- /dev/null +++ b/sql/ddl.go @@ -0,0 +1,65 @@ +// Copyright 2020 Pilosa Corp. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sql + +import ( + "context" + "fmt" + + "github.com/pilosa/pilosa/v2" + pproto "github.com/pilosa/pilosa/v2/proto" + "github.com/pkg/errors" + "vitess.io/vitess/go/vt/sqlparser" +) + +// DDLHandler executes CREATE, ALTER, DROP, RENAME, TRUNCATE or ANALYZE statement. +type DDLHandler struct { + api *pilosa.API +} + +// NewDDLHandler constructor +func NewDDLHandler(api *pilosa.API) *DDLHandler { + return &DDLHandler{ + api: api, + } +} + +// Handle executes mapped SQL +func (h *DDLHandler) Handle(ctx context.Context, mapped *MappedSQL) (pproto.StreamClient, error) { + stmt, ok := mapped.Statement.(*sqlparser.DDL) + if !ok { + return nil, fmt.Errorf("statement is not type DDL: %T", mapped.Statement) + } + + switch stmt.Action { + case sqlparser.DropStr: + return h.execDropTable(ctx, stmt) + + default: + return nil, errors.Errorf("unsupported DDL action: %s", stmt.Action) + } +} + +func (h *DDLHandler) execDropTable(ctx context.Context, stmt *sqlparser.DDL) (pproto.StreamClient, error) { + if n := len(stmt.FromTables); n != 1 { + return nil, fmt.Errorf("statement can only contain a single drop table, but got: %d", n) + } + + indexName := stmt.FromTables[0].ToViewName().Name.String() + if err := h.api.DeleteIndex(ctx, indexName); err != nil { + return nil, errors.Wrapf(err, "deleting index %s", indexName) + } + return pproto.EmptyStream{}, nil +}