From 040a71883850cba9dc909bd060f93dcdd47231d6 Mon Sep 17 00:00:00 2001 From: Abraham Egnor Date: Mon, 12 Jul 2021 14:15:11 -0400 Subject: [PATCH 1/4] sync spec tests --- .../spec/json/crud/unified/aggregate-let.json | 478 ++++++++++++++++++ .../spec/json/crud/unified/aggregate-let.yml | 173 +++++++ 2 files changed, 651 insertions(+) create mode 100644 src/test/spec/json/crud/unified/aggregate-let.json create mode 100644 src/test/spec/json/crud/unified/aggregate-let.yml diff --git a/src/test/spec/json/crud/unified/aggregate-let.json b/src/test/spec/json/crud/unified/aggregate-let.json new file mode 100644 index 000000000..4ce8256cb --- /dev/null +++ b/src/test/spec/json/crud/unified/aggregate-let.json @@ -0,0 +1,478 @@ +{ + "description": "aggregate-let", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + }, + { + "collection": { + "id": "collection1", + "database": "database0", + "collectionName": "coll1" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1 + } + ] + }, + { + "collectionName": "coll1", + "databaseName": "crud-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "Aggregate with let option", + "runOnRequirements": [ + { + "minServerVersion": "5.0" + } + ], + "operations": [ + { + "name": "aggregate", + "object": "collection0", + "arguments": { + "pipeline": [ + { + "$match": { + "$expr": { + "$eq": [ + "$_id", + "$$id" + ] + } + } + }, + { + "$project": { + "_id": 0, + "x": "$$x", + "y": "$$y", + "rand": "$$rand" + } + } + ], + "let": { + "id": 1, + "x": "foo", + "y": { + "$literal": "bar" + }, + "rand": { + "$rand": {} + } + } + }, + "expectResult": [ + { + "x": "foo", + "y": "bar", + "rand": { + "$$type": "double" + } + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll0", + "pipeline": [ + { + "$match": { + "$expr": { + "$eq": [ + "$_id", + "$$id" + ] + } + } + }, + { + "$project": { + "_id": 0, + "x": "$$x", + "y": "$$y", + "rand": "$$rand" + } + } + ], + "let": { + "id": 1, + "x": "foo", + "y": { + "$literal": "bar" + }, + "rand": { + "$rand": {} + } + } + } + } + } + ] + } + ] + }, + { + "description": "Aggregate with let option and dollar-prefixed $literal value", + "runOnRequirements": [ + { + "minServerVersion": "5.0", + "topologies": [ + "single", + "replicaset" + ] + } + ], + "operations": [ + { + "name": "aggregate", + "object": "collection0", + "arguments": { + "pipeline": [ + { + "$match": { + "$expr": { + "$eq": [ + "$_id", + "$$id" + ] + } + } + }, + { + "$project": { + "_id": 0, + "x": "$$x", + "y": "$$y", + "rand": "$$rand" + } + } + ], + "let": { + "id": 1, + "x": "foo", + "y": { + "$literal": "$bar" + }, + "rand": { + "$rand": {} + } + } + }, + "expectResult": [ + { + "x": "foo", + "y": "$bar", + "rand": { + "$$type": "double" + } + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll0", + "pipeline": [ + { + "$match": { + "$expr": { + "$eq": [ + "$_id", + "$$id" + ] + } + } + }, + { + "$project": { + "_id": 0, + "x": "$$x", + "y": "$$y", + "rand": "$$rand" + } + } + ], + "let": { + "id": 1, + "x": "foo", + "y": { + "$literal": "$bar" + }, + "rand": { + "$rand": {} + } + } + } + } + } + ] + } + ] + }, + { + "description": "Aggregate with let option unsupported (server-side error)", + "runOnRequirements": [ + { + "minServerVersion": "2.6.0", + "maxServerVersion": "4.4.99" + } + ], + "operations": [ + { + "name": "aggregate", + "object": "collection0", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": 1 + } + } + ], + "let": { + "x": "foo" + } + }, + "expectError": { + "errorContains": "unrecognized field 'let'", + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll0", + "pipeline": [ + { + "$match": { + "_id": 1 + } + } + ], + "let": { + "x": "foo" + } + } + } + } + ] + } + ] + }, + { + "description": "Aggregate to collection with let option", + "runOnRequirements": [ + { + "minServerVersion": "5.0" + } + ], + "operations": [ + { + "name": "aggregate", + "object": "collection0", + "arguments": { + "pipeline": [ + { + "$match": { + "$expr": { + "$eq": [ + "$_id", + "$$id" + ] + } + } + }, + { + "$project": { + "_id": 1 + } + }, + { + "$out": "coll1" + } + ], + "let": { + "id": 1 + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll0", + "pipeline": [ + { + "$match": { + "$expr": { + "$eq": [ + "$_id", + "$$id" + ] + } + } + }, + { + "$project": { + "_id": 1 + } + }, + { + "$out": "coll1" + } + ], + "let": { + "id": 1 + } + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll1", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1 + } + ] + } + ] + }, + { + "description": "Aggregate to collection with let option unsupported (server-side error)", + "runOnRequirements": [ + { + "minServerVersion": "2.6.0", + "maxServerVersion": "4.4.99" + } + ], + "operations": [ + { + "name": "aggregate", + "object": "collection0", + "arguments": { + "pipeline": [ + { + "$match": { + "$expr": { + "$eq": [ + "$_id", + "$$id" + ] + } + } + }, + { + "$project": { + "_id": 1 + } + }, + { + "$out": "coll1" + } + ], + "let": { + "id": 1 + } + }, + "expectError": { + "errorContains": "unrecognized field 'let'", + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll0", + "pipeline": [ + { + "$match": { + "$expr": { + "$eq": [ + "$_id", + "$$id" + ] + } + } + }, + { + "$project": { + "_id": 1 + } + }, + { + "$out": "coll1" + } + ], + "let": { + "id": 1 + } + } + } + } + ] + } + ] + } + ] +} diff --git a/src/test/spec/json/crud/unified/aggregate-let.yml b/src/test/spec/json/crud/unified/aggregate-let.yml new file mode 100644 index 000000000..ed34c37c4 --- /dev/null +++ b/src/test/spec/json/crud/unified/aggregate-let.yml @@ -0,0 +1,173 @@ +description: "aggregate-let" + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name crud-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + - collection: + id: &collection1 collection1 + database: *database0 + collectionName: &collection1Name coll1 + +initialData: &initialData + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1 } + - collectionName: *collection1Name + databaseName: *database0Name + documents: [ ] + +tests: + # TODO: Once SERVER-57403 is resolved, this test can be removed in favor of + # the "dollar-prefixed $literal value" test below. + - description: "Aggregate with let option" + runOnRequirements: + - minServerVersion: "5.0" + operations: + - name: aggregate + object: *collection0 + arguments: + pipeline: &pipeline0 + # $match takes a query expression, so $expr is necessary to utilize + # an aggregate expression context and access "let" variables. + - $match: { $expr: { $eq: ["$_id", "$$id"] } } + - $project: { _id: 0, x: "$$x", y: "$$y", rand: "$$rand" } + # Values in "let" must be constant or closed expressions that do not + # depend on document values. This test demonstrates a basic constant + # value, a value wrapped with $literal (to avoid expression parsing), + # and a closed expression (e.g. $rand). + let: &let0 + id: 1 + x: foo + y: { $literal: "bar" } + rand: { $rand: {} } + expectResult: + - { x: "foo", y: "bar", rand: { $$type: "double" } } + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + pipeline: *pipeline0 + let: *let0 + + - description: "Aggregate with let option and dollar-prefixed $literal value" + runOnRequirements: + - minServerVersion: "5.0" + # TODO: Remove topology restrictions once SERVER-57403 is resolved + topologies: ["single", "replicaset"] + operations: + - name: aggregate + object: *collection0 + arguments: + pipeline: &pipeline0 + # $match takes a query expression, so $expr is necessary to utilize + # an aggregate expression context and access "let" variables. + - $match: { $expr: { $eq: ["$_id", "$$id"] } } + - $project: { _id: 0, x: "$$x", y: "$$y", rand: "$$rand" } + # Values in "let" must be constant or closed expressions that do not + # depend on document values. This test demonstrates a basic constant + # value, a value wrapped with $literal (to avoid expression parsing), + # and a closed expression (e.g. $rand). + let: &let0 + id: 1 + x: foo + y: { $literal: "$bar" } + rand: { $rand: {} } + expectResult: + - { x: "foo", y: "$bar", rand: { $$type: "double" } } + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + pipeline: *pipeline0 + let: *let0 + + - description: "Aggregate with let option unsupported (server-side error)" + runOnRequirements: + - minServerVersion: "2.6.0" + maxServerVersion: "4.4.99" + operations: + - name: aggregate + object: *collection0 + arguments: + pipeline: &pipeline1 + - $match: { _id: 1 } + let: &let1 + x: foo + expectError: + # Older server versions may not report an error code, but the error + # message is consistent between 2.6.x and 4.4.x server versions. + errorContains: "unrecognized field 'let'" + isClientError: false + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + pipeline: *pipeline1 + let: *let1 + + - description: "Aggregate to collection with let option" + runOnRequirements: + - minServerVersion: "5.0" + operations: + - name: aggregate + object: *collection0 + arguments: + pipeline: &pipeline2 + - $match: { $expr: { $eq: ["$_id", "$$id"] } } + - $project: { _id: 1 } + - $out: *collection1Name + let: &let2 + id: 1 + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + pipeline: *pipeline2 + let: *let2 + outcome: + - collectionName: *collection1Name + databaseName: *database0Name + documents: + - { _id: 1 } + + - description: "Aggregate to collection with let option unsupported (server-side error)" + runOnRequirements: + - minServerVersion: "2.6.0" + maxServerVersion: "4.4.99" + operations: + - name: aggregate + object: *collection0 + arguments: + pipeline: *pipeline2 + let: *let2 + expectError: + errorContains: "unrecognized field 'let'" + isClientError: false + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + pipeline: *pipeline2 + let: *let2 From 048f650cf12b3b3a817f7852014e67728e0399ab Mon Sep 17 00:00:00 2001 From: Abraham Egnor Date: Mon, 12 Jul 2021 14:35:14 -0400 Subject: [PATCH 2/4] add field to AggregateOptions --- src/coll/options.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/coll/options.rs b/src/coll/options.rs index 8987eac0f..7f4759077 100644 --- a/src/coll/options.rs +++ b/src/coll/options.rs @@ -490,6 +490,14 @@ pub struct AggregateOptions { /// If none is specified, the write concern defined on the object executing this operation will /// be used. pub write_concern: Option, + + /// Any amount of parameter names, each followed by definitions of constants in the MQL + /// Aggregate Expression language. + /// + /// Each parameter name is then usable to access the value of the corresponding MQL Expression + /// with the "$$" syntax within Aggregate Expression contexts. + #[serde(rename = "let")] + pub bindings: Option, } /// Specifies the options to a From 69e93ad8ebb7a42201723a6401eda97e9efdd88e Mon Sep 17 00:00:00 2001 From: Abraham Egnor Date: Mon, 12 Jul 2021 14:41:17 -0400 Subject: [PATCH 3/4] update doc to call out 5.0 requirement --- src/coll/options.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coll/options.rs b/src/coll/options.rs index 7f4759077..8df68c88a 100644 --- a/src/coll/options.rs +++ b/src/coll/options.rs @@ -492,10 +492,10 @@ pub struct AggregateOptions { pub write_concern: Option, /// Any amount of parameter names, each followed by definitions of constants in the MQL - /// Aggregate Expression language. + /// Aggregate Expression language. Each parameter name is then usable to access the value of + /// the corresponding MQL Expression with the "$$" syntax within Aggregate Expression contexts. /// - /// Each parameter name is then usable to access the value of the corresponding MQL Expression - /// with the "$$" syntax within Aggregate Expression contexts. + /// This feature is only available on server versions 5.0 and above. #[serde(rename = "let")] pub bindings: Option, } From eb7347eda01a92870e94fecf0d32f909a3761a7e Mon Sep 17 00:00:00 2001 From: Abraham Egnor Date: Mon, 12 Jul 2021 16:04:18 -0400 Subject: [PATCH 4/4] rename option and tweak comment --- src/coll/options.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/coll/options.rs b/src/coll/options.rs index 8df68c88a..983d1ca4e 100644 --- a/src/coll/options.rs +++ b/src/coll/options.rs @@ -491,13 +491,14 @@ pub struct AggregateOptions { /// be used. pub write_concern: Option, - /// Any amount of parameter names, each followed by definitions of constants in the MQL - /// Aggregate Expression language. Each parameter name is then usable to access the value of - /// the corresponding MQL Expression with the "$$" syntax within Aggregate Expression contexts. + /// A document with any amount of parameter names, each followed by definitions of constants in + /// the MQL Aggregate Expression language. Each parameter name is then usable to access the + /// value of the corresponding MQL Expression with the "$$" syntax within Aggregate Expression + /// contexts. /// /// This feature is only available on server versions 5.0 and above. #[serde(rename = "let")] - pub bindings: Option, + pub let_vars: Option, } /// Specifies the options to a