public object VisitSearchParameter(SearchParameterExpression expression, Context context)
        {
            switch (expression.Parameter.Code)
            {
            case SearchParameterNames.ResourceType:
                // We do not currently support specifying the system for the _type parameter value.
                // We would need to add it to the document, but for now it seems pretty unlikely that it will
                // be specified when searching.
                expression.Expression.AcceptVisitor(this, context.WithFieldNameOverride((n, i) => SearchValueConstants.RootResourceTypeName));
                break;

            case SearchParameterNames.LastUpdated:
                // For LastUpdate queries, the LastModified property on the root is
                // more performant than the searchIndices _lastUpdated.st and _lastUpdate.et
                // we will override the mapping for that
                expression.Expression.AcceptVisitor(this, context.WithFieldNameOverride((n, i) => SearchValueConstants.LastModified));
                break;

            case SearchValueConstants.TypeIdCompositeSearchParameterName:
                // This is an internal composite search parameter with components _type and _id, used when performing a query for includes.
                // We use the SearchValueConstants.RootResourceTypeName and SearchValueConstants.ResourceId fields respectively.
                expression.Expression.AcceptVisitor(
                    this,
                    context.WithFieldNameOverride(
                        (fieldName, componentIndex) =>
                        componentIndex switch
                {
                    0 => SearchValueConstants.RootResourceTypeName,
                    1 => KnownResourceWrapperProperties.ResourceId,
                    _ => throw new InvalidOperationException("unexpected component index"),
                }));
                break;
        internal static void ValidateSearchParameterExpression(Expression expression, string paramName, Action <Expression> valueValidator)
        {
            SearchParameterExpression parameterExpression = Assert.IsType <SearchParameterExpression>(expression);

            Assert.Equal(paramName, parameterExpression.Parameter.Name);
            valueValidator(parameterExpression.Expression);
        }
        public object VisitSearchParameter(SearchParameterExpression expression, Context context)
        {
            if (expression.Parameter.Name == SearchParameterNames.ResourceType)
            {
                // We do not currently support specifying the system for the _type parameter value.
                // We would need to add it to the document, but for now it seems pretty unlikely that it will
                // be specified when searching.
                expression.Expression.AcceptVisitor(this, context.WithFieldNameOverride(SearchValueConstants.RootResourceTypeName));
            }
            else if (expression.Parameter.Name == SearchParameterNames.LastUpdated)
            {
                // For LastUpdate queries, the LastModified property on the root is
                // more performant than the searchIndices _lastUpdated.st and _lastUpdate.et
                // we will override the mapping for that
                expression.Expression.AcceptVisitor(this, context.WithFieldNameOverride(SearchValueConstants.LastModified));
            }
            else
            {
                AppendSubquery(expression.Parameter.Name, expression.Expression, context);
            }

            _queryBuilder.AppendLine();

            return(null);
        }
Exemple #4
0
        public override Expression VisitSearchParameter(SearchParameterExpression expression, object context)
        {
            if (expression.Parameter.Code == SearchParameterNames.LastUpdated)
            {
                return(Expression.SearchParameter(SqlSearchParameters.ResourceSurrogateIdParameter, expression.Expression.AcceptVisitor(this, context)));
            }

            return(expression);
        }
            public override bool VisitSearchParameter(SearchParameterExpression expression, object context)
            {
                if (expression.Parameter.Type == SearchParamType.String ||
                    expression.Parameter.Type == SearchParamType.Composite)
                {
                    return(expression.Expression.AcceptVisitor(this, expression.Parameter));
                }

                return(false);
            }
        public void GivenAnUntypedReferenceExpressionWithOneTargetType_WhenRewritten_ExpressionIncludesType()
        {
            SearchParameterExpression inputExpression = Expression.SearchParameter(
                ReferenceSearchParameterWithOneTargetType,
                Expression.StringEquals(FieldName.ReferenceResourceId, null, "myId", false));

            Expression outputExpression = inputExpression.AcceptVisitor(UntypedReferenceRewriter.Instance);

            Assert.Equal("(Param p (And (StringEquals ReferenceResourceId 'myId') (StringEquals ReferenceResourceType 'Organization')))", outputExpression.ToString());
        }
        public void GivenAnUntypedReferenceExpressionWithMultipleTargetTypes_WhenRewritten_DoesNotChange()
        {
            SearchParameterExpression inputExpression = Expression.SearchParameter(
                ReferenceSearchParameterWithTwoTargetTypes,
                Expression.StringEquals(FieldName.ReferenceResourceId, null, "patientId", false));

            Expression outputExpression = inputExpression.AcceptVisitor(UntypedReferenceRewriter.Instance);

            Assert.Same(inputExpression, outputExpression);
        }
        public override Expression VisitSearchParameter(SearchParameterExpression expression, object context)
        {
            if (expression.Parameter.Type == SearchParamType.String ||
                expression.Parameter.Type == SearchParamType.Composite)
            {
                return(base.VisitSearchParameter(expression, expression.Parameter));
            }

            return(expression);
        }
Exemple #9
0
        public override Expression VisitSearchParameter(SearchParameterExpression expression, object context)
        {
            // include composites because they may contain dates.

            if (expression.Parameter.Type == SearchParamType.Date ||
                expression.Parameter.Type == SearchParamType.Composite)
            {
                return(base.VisitSearchParameter(expression, context));
            }

            return(expression);
        }
Exemple #10
0
            public override Expression VisitSearchParameter(SearchParameterExpression expression, object context)
            {
                // for now, we don't apply this optimization to composite parameters

                if (expression.Parameter.Type == SearchParamType.Date &&
                    expression.Expression is MultiaryExpression)
                {
                    return(base.VisitSearchParameter(expression, context));
                }

                return(expression);
            }
        public void GivenATypedReferenceExpressionWithOneTargetType_WhenRewritten_DoesNotChange()
        {
            SearchParameterExpression inputExpression = Expression.SearchParameter(
                ReferenceSearchParameterWithOneTargetType,
                Expression.And(
                    Expression.StringEquals(FieldName.ReferenceResourceType, null, "Organization", false),
                    Expression.StringEquals(FieldName.ReferenceResourceId, null, "myId", false)));

            Expression outputExpression = inputExpression.AcceptVisitor(UntypedReferenceRewriter.Instance);

            Assert.Same(inputExpression, outputExpression);
        }
Exemple #12
0
        public override SearchParameterQueryGeneratorContext VisitSearchParameter(SearchParameterExpression expression, SearchParameterQueryGeneratorContext context)
        {
            short          searchParamId       = context.Model.GetSearchParamId(expression.Parameter.Url);
            SmallIntColumn searchParamIdColumn = VLatest.SearchParam.SearchParamId;

            context.StringBuilder
            .Append(searchParamIdColumn, context.TableAlias)
            .Append(" = ")
            .AppendLine(context.Parameters.AddParameter(searchParamIdColumn, searchParamId).ParameterName)
            .Append("AND ");

            return(expression.Expression.AcceptVisitor(this, context));
        }
        public void GivenAnUntypedReferenceExpressionWithOneTargetTypeInACompositeSearchParameter_WhenRewritten_ExpressionIncludesType()
        {
            SearchParameterExpression inputExpression = Expression.SearchParameter(
                CompositeParameter,
                Expression.And(
                    Expression.StringEquals(FieldName.ReferenceResourceId, 0, "patientId", false),
                    Expression.StringEquals(FieldName.ReferenceResourceId, 1, "orgId", false),
                    Expression.Equals(FieldName.Number, 2, 8)));

            Expression outputExpression = inputExpression.AcceptVisitor(UntypedReferenceRewriter.Instance);

            Assert.Equal("(Param c (And (StringEquals [0].ReferenceResourceId 'patientId') (StringEquals [1].ReferenceResourceId 'orgId') (FieldEqual [2].Number 8) (StringEquals [1].ReferenceResourceType 'Organization')))", outputExpression.ToString());
        }
        public override Expression VisitSearchParameter(SearchParameterExpression expression, SqlSearchOptions context)
        {
            if (context.Sort.Count > 0)
            {
                if (expression.Parameter.Equals(context.Sort[0].searchParameterInfo))
                {
                    // We are returning null here to notify that we have found a SearchParameterExpression
                    // for the same search parameter used for sort.
                    return(null);
                }
            }

            return(expression);
        }
        public void GivenATypedReferenceExpressionWithOneTargetTypeInACompositeSearchParameter_WhenRewritten_DoesNotChange()
        {
            SearchParameterExpression inputExpression = Expression.SearchParameter(
                CompositeParameter,
                Expression.And(
                    Expression.StringEquals(FieldName.ReferenceResourceId, 0, "patientId", false),
                    Expression.StringEquals(FieldName.ReferenceResourceType, 1, "Organization", false),
                    Expression.StringEquals(FieldName.ReferenceResourceId, 1, "orgId", false),
                    Expression.Equals(FieldName.Number, 2, 8)));

            Expression outputExpression = inputExpression.AcceptVisitor(UntypedReferenceRewriter.Instance);

            Assert.Same(inputExpression, outputExpression);
        }
Exemple #16
0
        public object VisitSearchParameter(SearchParameterExpression expression, Context context)
        {
            switch (expression.Parameter.Code)
            {
            case SearchParameterNames.ResourceType:
                // We do not currently support specifying the system for the _type parameter value.
                // We would need to add it to the document, but for now it seems pretty unlikely that it will
                // be specified when searching.
                expression.Expression.AcceptVisitor(this, context.WithFieldNameOverride((n, i) => SearchValueConstants.RootResourceTypeName));
                break;

            case SearchParameterNames.Id:
                expression.Expression.AcceptVisitor(this, context.WithFieldNameOverride((n, i) => KnownResourceWrapperProperties.ResourceId));
                break;

            case SearchParameterNames.LastUpdated:
                // For LastUpdate queries, the LastModified property on the root is
                // more performant than the searchIndices _lastUpdated.st and _lastUpdate.et
                // we will override the mapping for that
                expression.Expression.AcceptVisitor(this, context.WithFieldNameOverride((n, i) => SearchValueConstants.LastModified));
                break;

            case SearchValueConstants.WildcardReferenceSearchParameterName:
                // This is an internal search parameter that that matches any reference search parameter.
                // It is used for wildcard revinclude queries
                AppendSubquery(parameterName: null, expression.Expression, context);
                break;

            default:
                if (expression.Expression is NotExpression notExpression)
                {
                    AppendSubquery(expression.Parameter.Code, notExpression.Expression, context, true);
                }
                else
                {
                    AppendSubquery(expression.Parameter.Code, expression.Expression, context);
                }

                break;
            }

            _queryBuilder.AppendLine();

            return(null);
        }
        public override SearchParameterQueryGeneratorContext VisitSearchParameter(SearchParameterExpression expression, SearchParameterQueryGeneratorContext context)
        {
            SearchParameterQueryGenerator delegatedGenerator = GetSearchParameterQueryGeneratorIfResourceColumnSearchParameter(expression);

            if (delegatedGenerator != null)
            {
                // This is a search parameter over a column that exists on the Resource table or both the Resource table and search parameter tables.
                // Delegate to the visitor specific to it.
                return(expression.Expression.AcceptVisitor(delegatedGenerator, context));
            }

            short          searchParamId       = context.Model.GetSearchParamId(expression.Parameter.Url);
            SmallIntColumn searchParamIdColumn = VLatest.SearchParam.SearchParamId;

            context.StringBuilder
            .Append(searchParamIdColumn, context.TableAlias)
            .Append(" = ")
            .AppendLine(context.Parameters.AddParameter(searchParamIdColumn, searchParamId, true).ParameterName)
            .Append("AND ");

            return(expression.Expression.AcceptVisitor(this, context));
        }
        public void Visit(SearchParameterExpression expression)
        {
            if (expression.Parameter.Name == SearchParameterNames.ResourceType)
            {
                try
                {
                    // We do not currently support specifying the system for the _type parameter value.
                    // We would need to add it to the document, but for now it seems pretty unlikely that it will
                    // be specified when searching.
                    _fieldNameOverride = SearchValueConstants.RootResourceTypeName;
                    expression.Expression.AcceptVisitor(this);
                }
                finally
                {
                    _fieldNameOverride = null;
                }
            }
            else
            {
                AppendSubquery(expression.Parameter.Name, expression.Expression);
            }

            _queryBuilder.AppendLine();
        }
 public override SearchParameterQueryGeneratorContext VisitSearchParameter(SearchParameterExpression expression, SearchParameterQueryGeneratorContext context)
 {
     return(expression.Expression.AcceptVisitor(GetSearchParameterQueryGenerator(expression), context));
 }
 public override bool VisitSearchParameter(SearchParameterExpression expression, object context) => expression.Parameter.Name == SearchParameterNames.Id;
 public SearchParamTableExpressionQueryGenerator VisitSearchParameter(SearchParameterExpression expression, object context)
 {
     return(VisitSearchParameterExpressionBase(expression.Parameter, expression.Expression, context));
 }
        public override Expression VisitSearchParameter(SearchParameterExpression expression, object context)
        {
            // Handle reference search parameters as well as composite search parameters with one or more reference components.
            // We first create a bitmask with bits set representing the component indexes that are candidates for this rule.
            // Bit 0 is for reference, non-composite parameters where the reference is of a single possible type
            // Bits 1 and up represent the component indexes (plus one) where the component is a reference search parameter with one type

            int componentCandidates = expression.Parameter.Type switch
            {
                SearchParamType.Reference when expression.Parameter.TargetResourceTypes?.Count == 1 => 1,
                SearchParamType.Composite =>
                expression.Parameter.Component.Aggregate(
                    (index: 1, flags: 0),
                    (acc, c) => (index: acc.index + 1, flags: acc.flags | (c.ResolvedSearchParameter.Type == SearchParamType.Reference && c.ResolvedSearchParameter.TargetResourceTypes?.Count == 1 ? 1 << acc.index : 0)))
                .flags,
                _ => 0,
            };

            if (componentCandidates == 0)
            {
                // nothing to do for this expression
                return(expression);
            }

            if (expression.Expression is MultiaryExpression multiaryExpression && multiaryExpression.MultiaryOperation == MultiaryOperator.Or)
            {
                Expression[] rewrittenExpressions = null;
                for (var i = 0; i < multiaryExpression.Expressions.Count; i++)
                {
                    Expression subexpression          = multiaryExpression.Expressions[i];
                    Expression rewrittenSubexpression = RewriteSubexpression(expression.Parameter, subexpression, componentCandidates);

                    if (!ReferenceEquals(rewrittenSubexpression, subexpression))
                    {
                        EnsureAllocatedAndPopulated(ref rewrittenExpressions, multiaryExpression.Expressions, i);
                    }

                    if (rewrittenExpressions != null)
                    {
                        rewrittenExpressions[i] = rewrittenSubexpression;
                    }
                }

                if (rewrittenExpressions == null)
                {
                    return(expression);
                }

                return(Expression.SearchParameter(expression.Parameter, Expression.Or(rewrittenExpressions)));
            }

            // a single expression (possibly ANDs), not multiple expressions ORed together

            Expression rewrittenExpression = RewriteSubexpression(expression.Parameter, expression.Expression, componentCandidates);

            if (ReferenceEquals(rewrittenExpression, expression.Expression))
            {
                return(expression);
            }

            return(Expression.SearchParameter(expression.Parameter, rewrittenExpression));
        }
 public NormalizedSearchParameterQueryGenerator VisitSearchParameter(SearchParameterExpression expression, object context)
 {
     return(VisitSearchParameterExpressionBase(expression.Parameter, expression.Expression, context));
 }