function merge(mAggregatedQueryOptions, mQueryOptions0, sMetaPath, bInsideExpand, bAdd) {
			/*
			 * Recursively merges the expand path into the aggregated query options.
			 *
			 * @param {string} sExpandPath The expand path
			 * @returns {boolean} Whether the query options can be fulfilled by this binding
			 */
			function mergeExpandPath(sExpandPath) {
				var bAddExpand = !mAggregatedQueryOptions.$expand[sExpandPath],
					sExpandMetaPath = sMetaPath + "/" + sExpandPath;

				if (bAddExpand) {
					mAggregatedQueryOptions.$expand[sExpandPath] = {};
					if (bCacheImmutable && that.oModel.getMetaModel()
							.fetchObject(sExpandMetaPath).getResult().$isCollection) {
						return false;
					}
				}
				return merge(mAggregatedQueryOptions.$expand[sExpandPath],
					mQueryOptions0.$expand[sExpandPath], sExpandMetaPath, true, bAddExpand);
			}

			/*
			 * Merges the select path into the aggregated query options.
			 *
			 * @param {string} sSelectPath The select path
			 * @returns {boolean} Whether the query options can be fulfilled by this binding
			 */
			function mergeSelectPath(sSelectPath) {
				if (!mAggregatedQueryOptions.$select.includes(sSelectPath)) {
					mAggregatedQueryOptions.$select.push(sSelectPath);
				}
				return true;
			}

			// Top-level all query options in the aggregate are OK, even if not repeated in the
			// child. In a $expand the child must also have them (and the second loop checks that
			// they're equal). Property bindings are an exception to this rule.
			return (bIsProperty || !bInsideExpand
				|| Object.keys(mAggregatedQueryOptions).every(function (sName) {
					return sName in mQueryOptions0 || sName === "$count" || sName === "$expand"
						|| sName === "$select";
				}))
				// merge $count, $expand and $select; check that all others equal the aggregate
				&& Object.keys(mQueryOptions0).every(function (sName) {
					switch (sName) {
						case "$count":
							if (mQueryOptions0.$count) {
								mAggregatedQueryOptions.$count = true;
							}
							return true;
						case "$expand":
							mAggregatedQueryOptions.$expand ??= {};
							return Object.keys(mQueryOptions0.$expand).every(mergeExpandPath);
						case "$select":
							mAggregatedQueryOptions.$select ??= [];
							return mQueryOptions0.$select.every(mergeSelectPath);
						default:
							if (bAdd) {
								mAggregatedQueryOptions[sName] = mQueryOptions0[sName];
								return true;
							}
							return mQueryOptions0[sName] === mAggregatedQueryOptions[sName];
					}
				});
		}
Decides whether the given query options can be fulfilled by this binding and merges them into
this binding's <code>mAggregatedQueryOptions</code> if necessary.

The query options cannot be fulfilled if there are conflicts. A conflict is an option other
than <code>$expand</code>, <code>$select</code> and <code>$count</code> which has different
values in the aggregate and the options to be merged. This is checked recursively.

If the cache is already immutable the query options are aggregated into
<code>mLateQueryOptions</code>. Then they also cannot be fulfilled if they contain a
<code>$expand</code> using a collection-valued navigation property.

Note: * is an item in <code>$select</code> and <code>$expand</code> just as others, that is
it must be part of the array of items and one must not ignore the other items if * is
provided. See "5.1.2 System Query Option $expand" and "5.1.3 System Query Option $select" in
specification "OData Version 4.0 Part 2: URL Conventions".

@param {object} mQueryOptions - The query options to be merged
@param {string} sBaseMetaPath - This binding's meta path
@param {boolean} bCacheImmutable - Whether the cache of this binding is immutable
@param {boolean} [bIsProperty] - Whether the child is a property binding
@returns {boolean} Whether the query options can be fulfilled by this binding

@private