private SearchParameterQueryGenerator GetSearchParameterQueryGenerator(SearchParameterExpressionBase searchParameter)
        {
            switch (searchParameter.Parameter.Name)
            {
            case SearchParameterNames.Id:
                return(ResourceIdParameterQueryGenerator.Instance);

            case SearchParameterNames.ResourceType:
                return(ResourceTypeIdParameterQueryGenerator.Instance);

            case SqlSearchParameters.ResourceSurrogateIdParameterName:
                return(ResourceSurrogateIdParameterQueryGenerator.Instance);

            default:
                throw new NotSupportedException(searchParameter.Parameter.Name);
            }
        }
 private static SearchParameterQueryGenerator GetSearchParameterQueryGenerator(SearchParameterExpressionBase searchParameter)
 {
     return(GetSearchParameterQueryGeneratorIfResourceColumnSearchParameter(searchParameter) ?? throw new InvalidOperationException($"Unexpected search parameter {searchParameter.Parameter.Code}"));
 }
Exemple #3
0
        public override Expression VisitSqlRoot(SqlRootExpression expression, object context)
        {
            if (expression.SearchParamTableExpressions.Count == 0 || expression.ResourceTableExpressions.Count == 0 ||
                expression.SearchParamTableExpressions.All(e => e.Kind == SearchParamTableExpressionKind.Include))
            {
                // if only Include expressions, the case is handled in IncludeMatchSeedRewriter
                return(expression);
            }

            Expression extractedCommonResourceExpressions = null;
            bool       containsResourceExpressionFoundOnlyOnResourceTable = false;

            for (int i = 0; i < expression.ResourceTableExpressions.Count; i++)
            {
                SearchParameterExpressionBase currentExpression = expression.ResourceTableExpressions[i];

                if (currentExpression is SearchParameterExpression searchParameterExpression)
                {
                    if (searchParameterExpression.Parameter.ColumnLocation().HasFlag(SearchParameterColumnLocation.SearchParamTable))
                    {
                        extractedCommonResourceExpressions = extractedCommonResourceExpressions == null ? (Expression)currentExpression : Expression.And(extractedCommonResourceExpressions, currentExpression);
                    }
                    else
                    {
                        containsResourceExpressionFoundOnlyOnResourceTable = true;
                    }
                }
            }

            var newTableExpressions = new List <SearchParamTableExpression>(expression.SearchParamTableExpressions.Count);

            if (containsResourceExpressionFoundOnlyOnResourceTable)
            {
                // There is a predicate over _id, which is on the Resource table but not on the search parameter tables.
                // So the first table expression should be an "All" expression, where we restrict the resultset to resources with that ID.
                newTableExpressions.Add(new SearchParamTableExpression(null, Expression.And(expression.ResourceTableExpressions), SearchParamTableExpressionKind.All));
            }

            foreach (var tableExpression in expression.SearchParamTableExpressions)
            {
                if (tableExpression.Kind == SearchParamTableExpressionKind.Include ||
                    (tableExpression.Kind == SearchParamTableExpressionKind.Normal && tableExpression.ChainLevel > 0) ||
                    (tableExpression.Kind == SearchParamTableExpressionKind.Chain && tableExpression.ChainLevel > 1))
                {
                    // these predicates do not apply to referenced resources

                    newTableExpressions.Add(tableExpression);
                }
                else if (tableExpression.Kind == SearchParamTableExpressionKind.Chain)
                {
                    var sqlChainLinkExpression = (SqlChainLinkExpression)tableExpression.Predicate;

                    Debug.Assert(sqlChainLinkExpression.ExpressionOnSource == null);

                    var newChainLinkExpression = new SqlChainLinkExpression(
                        sqlChainLinkExpression.ResourceTypes,
                        sqlChainLinkExpression.ReferenceSearchParameter,
                        sqlChainLinkExpression.TargetResourceTypes,
                        sqlChainLinkExpression.Reversed,
                        extractedCommonResourceExpressions,
                        sqlChainLinkExpression.ExpressionOnTarget);

                    newTableExpressions.Add(new SearchParamTableExpression(tableExpression.QueryGenerator, newChainLinkExpression, tableExpression.Kind, chainLevel: tableExpression.ChainLevel));
                }
                else
                {
                    Expression predicate = tableExpression.Predicate == null
                        ? extractedCommonResourceExpressions
                        : Expression.And(tableExpression.Predicate, extractedCommonResourceExpressions);

                    newTableExpressions.Add(new SearchParamTableExpression(tableExpression.QueryGenerator, predicate, tableExpression.Kind, tableExpression.ChainLevel));
                }
            }

            return(new SqlRootExpression(newTableExpressions, Array.Empty <SearchParameterExpressionBase>()));
        }
        protected static SearchParameterQueryGenerator GetSearchParameterQueryGeneratorIfResourceColumnSearchParameter(SearchParameterExpressionBase searchParameter)
        {
            switch (searchParameter.Parameter.Code)
            {
            case SearchParameterNames.Id:
                return(ResourceIdParameterQueryGenerator.Instance);

            case SearchParameterNames.ResourceType:
                return(ResourceTypeIdParameterQueryGenerator.Instance);

            case SqlSearchParameters.ResourceSurrogateIdParameterName:
                return(ResourceSurrogateIdParameterQueryGenerator.Instance);

            case SqlSearchParameters.PrimaryKeyParameterName:
                return(PrimaryKeyRangeParameterQueryGenerator.Instance);

#if DEBUG
            case SearchParameterNames.LastUpdated:
                throw new InvalidOperationException($"Expression with {SearchParameterNames.LastUpdated} parameter should have been rewritten to use {SqlSearchParameters.ResourceSurrogateIdParameterName}.");
#endif
            default:
                return(null);
            }
        }