diff --git a/integration/test/ParseQueryTest.js b/integration/test/ParseQueryTest.js index 18891517b..3d476c6ea 100644 --- a/integration/test/ParseQueryTest.js +++ b/integration/test/ParseQueryTest.js @@ -2401,4 +2401,19 @@ describe('Parse Query', () => { expect(results[1].get('arrayField')).toEqual([{ subfield: 1 }]); expect(results[2].get('arrayField')).toEqual(null); }); + + it('can query and send a comment', async () => { + const obj1 = new TestObject({ number: 1 }); + const obj2 = new TestObject({ number: 2 }); + const obj3 = new TestObject({ number: 3 }); + await Parse.Object.saveAll([obj1, obj2, obj3]); + + const query = new Parse.Query(TestObject); + const comment = 'Hello Parse'; + query.comment(comment); + query.explain(); + const explain = await query.find(); + assert.equal(explain.command.comment, comment); + }); + }); diff --git a/src/ParseQuery.js b/src/ParseQuery.js index 9be6b37a9..07aa71fe5 100644 --- a/src/ParseQuery.js +++ b/src/ParseQuery.js @@ -36,6 +36,7 @@ export type QueryJSON = { readPreference?: string, includeReadPreference?: string, subqueryReadPreference?: string, + comment?: string, }; /** @@ -242,6 +243,7 @@ class ParseQuery { _hint: mixed; _explain: boolean; _xhrRequest: any; + _comment: string; /** * @param {(string | Parse.Object)} objectClass An instance of a subclass of Parse.Object, or a Parse className string. @@ -283,6 +285,7 @@ class ParseQuery { task: null, onchange: () => {}, }; + this._comment = null; } /** @@ -468,6 +471,9 @@ class ParseQuery { if (this._explain) { params.explain = true; } + if(this._comment) { + params.comment = this._comment; + } for (const key in this._extraOptions) { params[key] = this._extraOptions[key]; } @@ -553,6 +559,10 @@ class ParseQuery { this._explain = !!json.explain; } + if(json.comment) { + this._comment = json.comment; + } + for (const key in json) { if (json.hasOwnProperty(key)) { if ( @@ -569,6 +579,7 @@ class ParseQuery { 'subqueryReadPreference', 'hint', 'explain', + 'comment', ].indexOf(key) === -1 ) { this._extraOptions[key] = json[key]; @@ -2111,6 +2122,25 @@ class ParseQuery { this._xhrRequest.onchange(); }; } + + /** + * Sets a comment to the query so that the query + *can be identified when using a the profiler for MongoDB. + * + * @param {string} value a comment can make your profile data easier to interpret and trace. + * @returns {Parse.Query} Returns the query, so you can chain this call. + */ + comment(value: string): ParseQuery { + if (value == null) { + delete this._comment; + return this; + } + if (typeof value !== 'string') { + throw new Error('The value of a comment to be sent with this query must be a string.'); + } + this._comment = value; + return this; + } } const DefaultController = { diff --git a/src/__tests__/ParseQuery-test.js b/src/__tests__/ParseQuery-test.js index 7aef3d28d..41541ba6b 100644 --- a/src/__tests__/ParseQuery-test.js +++ b/src/__tests__/ParseQuery-test.js @@ -3824,4 +3824,52 @@ describe('ParseQuery LocalDatastore', () => { expect(subscription.sessionToken).toBe('r:test'); expect(subscription.query).toEqual(query); }); + + it('can add comment to query', () => { + const query = new ParseQuery('TestObject'); + const comment = 'Hello Parse'; + query.comment(comment); + expect(query.toJSON()).toEqual({ + where: {}, + comment: comment, + }); + }); + + it('can add comment to query from json', () => { + const query = new ParseQuery('Item'); + const comment = 'Hello Parse'; + query.comment(comment); + const json = query.toJSON(); + expect(json).toEqual({ + where: {}, + comment: comment, + }); + const query2 = new ParseQuery('Item'); + query2.withJSON(json); + expect(query2._comment).toEqual(comment); + }); + + it('comment can only be string', () => { + const obj1 = { + className: 'Item', + objectId: 'objectId1', + password: 123, + number: 3, + string: 'a', + }; + const query = new ParseQuery('TestObject'); + expect(query.comment.bind(query, obj1)).toThrow( + 'The value of a comment to be sent with this query must be a string.' + ); + }); + + it('clear comment when no value passed', () => { + const query = new ParseQuery('Item'); + const comment = 'Hello Parse'; + query.comment(comment); + expect(query._comment).toBe(comment); + query.comment(); + expect(query._comment).toBeUndefined(); + }); + }); diff --git a/types/ParseQuery.d.ts b/types/ParseQuery.d.ts index 5c8f9de0e..60b0bbb5e 100644 --- a/types/ParseQuery.d.ts +++ b/types/ParseQuery.d.ts @@ -18,6 +18,7 @@ type QueryJSON = { readPreference?: string; includeReadPreference?: string; subqueryReadPreference?: string; + comment?: string, }; export default ParseQuery; /** @@ -140,6 +141,7 @@ declare class ParseQuery { _hint: mixed; _explain: boolean; _xhrRequest: any; + _comment: string; /** * Adds constraint that at least one of the passed in queries matches. * @@ -915,6 +917,14 @@ declare class ParseQuery { */ cancel(): ParseQuery; _setRequestTask(options: any): void; + /** + * Sets a comment to the query so that the query + * can be identified when using a the profiler for MongoDB. + * + * @param {string} value a comment can make your profile data easier to interpret and trace. + * @returns {Parse.Query} Returns the query, so you can chain this call. + */ + comment(value: string): ParseQuery; } import { FullOptions } from './RESTController'; import ParseObject from './ParseObject';