예제 #1
0
        public virtual CommandPart CreateQueryPart(IQueryRequest request, string parameterNamePrefix, ParameterContext parameterContext)
        {
            ArgumentValidator.EnsureArgumentNotNull(request, "request");
            ArgumentValidator.EnsureArgumentNotNullOrEmpty(parameterNamePrefix, "parameterNamePrefix");

            int parameterIndex    = 0;
            var compilationResult = request.GetCompiledStatement();
            var configuration     = new SqlPostCompilerConfiguration();
            var result            = new CommandPart();

            using (parameterContext.ActivateSafely()) {
                foreach (var binding in request.ParameterBindings)
                {
                    object parameterValue = GetParameterValue(binding);
                    switch (binding.BindingType)
                    {
                    case QueryParameterBindingType.Regular:
                        break;

                    case QueryParameterBindingType.SmartNull:
                        // replacing "x = @p" with "x is null" when @p = null (or empty string in case of Oracle)
                        if (IsHandledLikeNull(parameterValue))
                        {
                            configuration.AlternativeBranches.Add(binding);
                            continue;
                        }
                        break;

                    case QueryParameterBindingType.BooleanConstant:
                        // expanding true/false parameters to constants to help query optimizer with branching
                        if ((bool)parameterValue)
                        {
                            configuration.AlternativeBranches.Add(binding);
                        }
                        continue;

                    case QueryParameterBindingType.LimitOffset:
                        // not parameter, just inlined constant
                        configuration.PlaceholderValues.Add(binding, parameterValue.ToString());
                        continue;

                    case QueryParameterBindingType.NonZeroLimitOffset:
                        // Like "LimitOffset" but we handle zero value specially
                        // We replace value with 1 and activate special branch that evaluates "where" part to "false"
                        var stringValue = parameterValue.ToString();
                        if (stringValue == "0")
                        {
                            configuration.PlaceholderValues.Add(binding, "1");
                            configuration.AlternativeBranches.Add(binding);
                        }
                        else
                        {
                            configuration.PlaceholderValues.Add(binding, stringValue);
                        }
                        continue;

                    case QueryParameterBindingType.RowFilter:
                        var filterData     = (List <Tuple>)parameterValue;
                        var rowTypeMapping = ((QueryRowFilterParameterBinding)binding).RowTypeMapping;
                        if (filterData == null)
                        {
                            configuration.AlternativeBranches.Add(binding);
                            continue;
                        }
                        var commonPrefix = GetParameterName(parameterNamePrefix, ref parameterIndex);
                        var filterValues = new List <string[]>();
                        for (int tupleIndex = 0; tupleIndex < filterData.Count; tupleIndex++)
                        {
                            var tuple = filterData[tupleIndex];
                            var parameterReferences = new string[tuple.Count];
                            for (int fieldIndex = 0; fieldIndex < tuple.Count; fieldIndex++)
                            {
                                var name  = string.Format(RowFilterParameterNameFormat, commonPrefix, tupleIndex, fieldIndex);
                                var value = tuple.GetValueOrDefault(fieldIndex);
                                parameterReferences[fieldIndex] = Driver.BuildParameterReference(name);
                                AddRegularParameter(result, rowTypeMapping[fieldIndex], name, value);
                            }
                            filterValues.Add(parameterReferences);
                        }
                        configuration.DynamicFilterValues.Add(binding, filterValues);
                        continue;

                    default:
                        throw new ArgumentOutOfRangeException("binding.BindingType");
                    }
                    // regular case -> just adding the parameter
                    string parameterName = GetParameterName(parameterNamePrefix, ref parameterIndex);
                    configuration.PlaceholderValues.Add(binding, Driver.BuildParameterReference(parameterName));
                    AddParameter(result, binding, parameterName, parameterValue);
                }
            }
            result.Statement = compilationResult.GetCommandText(configuration);
            return(result);
        }