Bug #32976 was filed because SqlServerJsonPostprocessor visited only the QueryExpression part of ShapedQueryExpression; however, when split query is enabled, the split query is actually stored on the shaper side, and ShapedQueryExpression.QueryExpression represents only the main/first query.
Review other post-processing visitors to see where we have similar issues. For example, the recently-introduced SqlTreePruner and the visitors inside SqlAliasManager also visit only ShapedQueryExpression.QueryExpression (these affect only 9.0).
Another more subtle problem that affects previous versions: SqlExpressionSimplifyingExpressionVisitor does the following for ShapedQueryExpression:
var newQueryExpression = Visit(shapedQueryExpression.QueryExpression);
var newShaperExpression = Visit(shapedQueryExpression.ShaperExpression);
return shapedQueryExpression.Update(newQueryExpression, newShaperExpression);
This indeed visits both the query and the shaper, but note that the shaper contains references to the query (in ProjectionBindingExpression); this means that replacing the query as above causes us to lose referential integrity, since the shaper still points to the old query. Note that ShapedQueryExpression.UpdateQueryExpression() does a recursive replace instead the shaper to update it for the new query, but ShapedQueryExpression.Update(query, shaper) does not do this.
For thoughts on changing the query architecture to improve this, see #32980.
Bug #32976 was filed because SqlServerJsonPostprocessor visited only the QueryExpression part of ShapedQueryExpression; however, when split query is enabled, the split query is actually stored on the shaper side, and ShapedQueryExpression.QueryExpression represents only the main/first query.
Review other post-processing visitors to see where we have similar issues. For example, the recently-introduced SqlTreePruner and the visitors inside SqlAliasManager also visit only ShapedQueryExpression.QueryExpression (these affect only 9.0).
Another more subtle problem that affects previous versions: SqlExpressionSimplifyingExpressionVisitor does the following for ShapedQueryExpression:
This indeed visits both the query and the shaper, but note that the shaper contains references to the query (in ProjectionBindingExpression); this means that replacing the query as above causes us to lose referential integrity, since the shaper still points to the old query. Note that ShapedQueryExpression.UpdateQueryExpression() does a recursive replace instead the shaper to update it for the new query, but ShapedQueryExpression.Update(query, shaper) does not do this.
For thoughts on changing the query architecture to improve this, see #32980.