From 6b8d1502de99dc9b039b7cab04547a263610db7e Mon Sep 17 00:00:00 2001 From: Patryk Kwiatek Date: Mon, 13 Nov 2023 11:22:38 +0100 Subject: [PATCH] Add test for tailable cursor with non-capped collection (#3677) --- integration/query_test.go | 18 ++++++++++++++++ internal/handlers/common/find.go | 2 +- internal/handlers/sqlite/msg_find.go | 32 ++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/integration/query_test.go b/integration/query_test.go index 4542003b1442..948088612617 100644 --- a/integration/query_test.go +++ b/integration/query_test.go @@ -1203,3 +1203,21 @@ func TestQueryShowRecordIDErrors(t *testing.T) { }) } } + +func TestQueryTailableCursors(t *testing.T) { + t.Parallel() + + ctx, collection := setup.Setup(t) + _, err := collection.InsertOne(ctx, bson.D{{"v", int32(42)}}) + require.NoError(t, err) + + expectedErr := mongo.CommandError{ + Code: 2, + Message: "error processing query: ns=TestQueryTailableCursors.TestQueryTailableCursorsTree:" + + " $eq null\nSort: {}\nProj: {}\n tailable cursor requested on non capped collection", + Name: "BadValue", + } + + _, err = collection.Find(ctx, bson.D{{}}, options.Find().SetCursorType(options.Tailable)) + AssertEqualCommandError(t, expectedErr, err) +} diff --git a/internal/handlers/common/find.go b/internal/handlers/common/find.go index 4387c3054c55..b2567ab9b1d5 100644 --- a/internal/handlers/common/find.go +++ b/internal/handlers/common/find.go @@ -39,6 +39,7 @@ type FindParams struct { SingleBatch bool `ferretdb:"singleBatch,opt"` Comment string `ferretdb:"comment,opt"` MaxTimeMS int64 `ferretdb:"maxTimeMS,opt,wholePositiveNumber"` + Tailable bool `ferretdb:"tailable,opt"` Collation *types.Document `ferretdb:"collation,unimplemented"` Let *types.Document `ferretdb:"let,unimplemented"` @@ -52,7 +53,6 @@ type FindParams struct { ReturnKey bool `ferretdb:"returnKey,unimplemented-non-default"` ShowRecordId bool `ferretdb:"showRecordId,opt"` - Tailable bool `ferretdb:"tailable,unimplemented-non-default"` OplogReplay bool `ferretdb:"oplogReplay,unimplemented-non-default"` NoCursorTimeout bool `ferretdb:"noCursorTimeout,unimplemented-non-default"` AwaitData bool `ferretdb:"awaitData,unimplemented-non-default"` diff --git a/internal/handlers/sqlite/msg_find.go b/internal/handlers/sqlite/msg_find.go index 2f5ab567ceec..596f10a1798d 100644 --- a/internal/handlers/sqlite/msg_find.go +++ b/internal/handlers/sqlite/msg_find.go @@ -66,6 +66,38 @@ func (h *Handler) MsgFind(ctx context.Context, msg *wire.OpMsg) (*wire.OpMsg, er return nil, lazyerrors.Error(err) } + if params.Tailable { + var res *backends.ListCollectionsResult + var collInfo *backends.CollectionInfo + + res, err = db.ListCollections(ctx, nil) + if err != nil { + return nil, err + } + + // TODO https://github.com/FerretDB/FerretDB/issues/3601 + for _, coll := range res.Collections { + if coll.Name == params.Collection { + collInfo = &coll + } + } + + if collInfo != nil && !collInfo.Capped() { + return nil, commonerrors.NewCommandErrorMsgWithArgument( + commonerrors.ErrBadValue, + fmt.Sprintf( + "error processing query: ns=%s.%sTree:"+ + " $eq null\nSort: {}\nProj: {}\n tailable cursor requested on non capped collection", + params.DB, + params.Collection, + ), + "find", + ) + } + + return nil, common.Unimplemented(document, "tailable") + } + qp := &backends.QueryParams{ Comment: params.Comment, }