protected static SearchParameterQueryGeneratorContext VisitSimpleString()

in src/Microsoft.Health.Fhir.SqlServer/Features/Search/Expressions/Visitors/QueryGenerators/SearchParameterQueryGenerator.cs [177:252]


        protected static SearchParameterQueryGeneratorContext VisitSimpleString(StringExpression expression, SearchParameterQueryGeneratorContext context, StringColumn column, string value)
        {
            if (expression.StringOperator != StringOperator.LeftSideStartsWith)
            {
                AppendColumnName(context, column, expression);
            }

            bool needsEscaping = false;
            switch (expression.StringOperator)
            {
                case StringOperator.Contains:
                    needsEscaping = TryEscapeValueForLike(ref value);
                    SqlParameter containsParameter = context.Parameters.AddParameter(column, $"%{value}%", true);
                    context.StringBuilder.Append(" LIKE ").Append(containsParameter.ParameterName);
                    break;
                case StringOperator.EndsWith:
                    needsEscaping = TryEscapeValueForLike(ref value);
                    SqlParameter endWithParameter = context.Parameters.AddParameter(column, $"%{value}", true);
                    context.StringBuilder.Append(" LIKE ").Append(endWithParameter.ParameterName);
                    break;
                case StringOperator.Equals:
                    SqlParameter equalsParameter = context.Parameters.AddParameter(column, value, true);
                    context.StringBuilder.Append(" = ").Append(equalsParameter.ParameterName);
                    break;
                case StringOperator.NotContains:
                    context.StringBuilder.Append(" NOT ");
                    goto case StringOperator.Contains;
                case StringOperator.NotEndsWith:
                    context.StringBuilder.Append(" NOT ");
                    goto case StringOperator.EndsWith;
                case StringOperator.NotStartsWith:
                    context.StringBuilder.Append(" NOT ");
                    goto case StringOperator.StartsWith;
                case StringOperator.StartsWith:
                    needsEscaping = TryEscapeValueForLike(ref value);
                    SqlParameter startsWithParameter = context.Parameters.AddParameter(column, $"{value}%", true);
                    context.StringBuilder.Append(" LIKE ").Append(startsWithParameter.ParameterName);
                    break;
                case StringOperator.LeftSideStartsWith:
                    needsEscaping = TryEscapeValueForLike(ref value);
                    SqlParameter leftParameter = context.Parameters.AddParameter(column, $"{value}", true);
                    context.StringBuilder.Append(leftParameter.ParameterName).Append(" LIKE ");
                    AppendColumnName(context, column, expression);
                    context.StringBuilder.Append("+'%'");
                    break;

                default:
                    throw new ArgumentOutOfRangeException(expression.StringOperator.ToString());
            }

            if (needsEscaping)
            {
                context.StringBuilder.Append(" ESCAPE '!'");
            }

            if (column.IsAcentSensitive == null || column.IsCaseSensitive == null ||
                column.IsAcentSensitive == expression.IgnoreCase ||
                column.IsCaseSensitive == expression.IgnoreCase)
            {
                if (!expression.IgnoreCase && expression.StringOperator == StringOperator.Equals && column.IsAcentSensitive != null && column.IsCaseSensitive != null)
                {
                    // We are doing a case/accent sensitive query over a column that is case/accent insensitive.
                    // We can improve efficiency of the query by including an accent/case insensitive predicate
                    // in addition to the sensitive one. This allows the optimizer choose an index seek.

                    context.StringBuilder.Append(" AND ");
                    AppendColumnName(context, column, expression);
                    SqlParameter equalsParameter = context.Parameters.AddParameter(column, value, true);
                    context.StringBuilder.Append(" = ").Append(equalsParameter.ParameterName);
                }

                context.StringBuilder.Append(" COLLATE ").Append(expression.IgnoreCase ? DefaultCaseInsensitiveCollation : DefaultCaseSensitiveCollation);
            }

            return context;
        }