Пример #1
0
 internal FunctionDefinition(string name, DbLambda lambda, int startPosition, int endPosition)
 {
     this._name          = name;
     this._lambda        = lambda;
     this._startPosition = startPosition;
     this._endPosition   = endPosition;
 }
Пример #2
0
 /// <summary>
 /// Dumps the specified DbLambda instance
 /// </summary>
 /// <param name="lambda">The DbLambda to dump.</param>
 internal void Dump(DbLambda lambda)
 {
     Begin("DbLambda");
     Dump(System.Linq.Enumerable.Cast <DbExpression>(lambda.Variables), "Variables", "Variable");
     Dump(lambda.Body, "Body");
     End("DbLambda");
 }
Пример #3
0
        protected virtual DbLambda VisitLambda(DbLambda lambda)
        {
            Check.NotNull(lambda, "lambda");

            var result     = lambda;
            var newFormals = VisitList(
                lambda.Variables, varRef =>
            {
                var newVarType = VisitTypeUsage(varRef.ResultType);
                if (!ReferenceEquals(varRef.ResultType, newVarType))
                {
                    return(CqtBuilder.Variable(newVarType, varRef.VariableName));
                }
                else
                {
                    return(varRef);
                }
            }
                );

            EnterScope(newFormals.ToArray()); // ToArray: Don't pass the List instance directly to OnEnterScope
            var newBody = VisitExpression(lambda.Body);

            ExitScope();

            if (!ReferenceEquals(lambda.Variables, newFormals)
                ||
                !ReferenceEquals(lambda.Body, newBody))
            {
                result = CqtBuilder.Lambda(newBody, newFormals);
            }
            return(result);
        }
Пример #4
0
 /// <summary>
 ///     Dumps the specified DbLambda instance
 /// </summary>
 /// <param name="lambda"> The DbLambda to dump. </param>
 internal void Dump(DbLambda lambda)
 {
     Begin("DbLambda");
     Dump(lambda.Variables.Cast <DbExpression>(), "Variables", "Variable");
     Dump(lambda.Body, "Body");
     End("DbLambda");
 }
        protected virtual DbLambda VisitLambda(DbLambda lambda)
        {
            EntityUtil.CheckArgumentNull(lambda, "lambda");

            DbLambda result = lambda;
            IList <DbVariableReferenceExpression> newFormals = this.VisitList(lambda.Variables, varRef =>
            {
                TypeUsage newVarType = this.VisitTypeUsage(varRef.ResultType);
                if (!object.ReferenceEquals(varRef.ResultType, newVarType))
                {
                    return(CqtBuilder.Variable(newVarType, varRef.VariableName));
                }
                else
                {
                    return(varRef);
                }
            }
                                                                              );

            this.EnterScope(newFormals.ToArray()); // ToArray: Don't pass the List instance directly to OnEnterScope
            DbExpression newBody = this.VisitExpression(lambda.Body);

            this.ExitScope();

            if (!object.ReferenceEquals(lambda.Variables, newFormals) ||
                !object.ReferenceEquals(lambda.Body, newBody))
            {
                result = CqtBuilder.Lambda(newBody, newFormals);
            }
            return(result);
        }
Пример #6
0
        /// <summary>
        /// Compiles eSQL <paramref name="functionDefinition"/> and returns <see cref="DbLambda"/>.
        /// Guarantees type match of lambda variables and <paramref name="functionParameters"/>.
        /// Passes thru all excepions coming from <see cref="CqlQuery"/>.
        /// </summary>
        static internal DbLambda CompileFunctionDefinition(
            string functionFullName,
            string functionDefinition,
            IList <FunctionParameter> functionParameters,
            EdmItemCollection edmItemCollection)
        {
            Debug.Assert(!String.IsNullOrEmpty(functionFullName), "!String.IsNullOrEmpty(functionFullName)");
            Debug.Assert(!String.IsNullOrEmpty(functionDefinition), "!String.IsNullOrEmpty(functionDefinition)");
            Debug.Assert(functionParameters != null, "functionParameters != null");
            Debug.Assert(edmItemCollection != null, "edmItemCollection != null");

            MetadataWorkspace workspace = new MetadataWorkspace();

            workspace.RegisterItemCollection(edmItemCollection);
            Perspective perspective = new ModelPerspective(workspace);

            // Since we compile lambda expression and generate variables from the function parameter definitions,
            // the returned DbLambda will contain variable types that match function parameter types.
            DbLambda functionBody = CqlQuery.CompileQueryCommandLambda(
                functionDefinition,
                perspective,
                null /* use default parser options */,
                null /* parameters */,
                functionParameters.Select(pInfo => pInfo.TypeUsage.Variable(pInfo.Name)));

            Debug.Assert(functionBody != null, "functionBody != null");

            return(functionBody);
        }
Пример #7
0
        static internal DbExpression CompileFunctionView(
            string viewDef,
            StorageMappingItemCollection mappingItemCollection,
            ParserOptions.CompilationMode compilationMode,
            IEnumerable <DbParameterReferenceExpression> parameters)
        {
            Debug.Assert(!String.IsNullOrEmpty(viewDef), "!String.IsNullOrEmpty(viewDef)");
            Debug.Assert(mappingItemCollection != null, "mappingItemCollection != null");

            Perspective   perspective   = new TargetPerspective(mappingItemCollection.Workspace);
            ParserOptions parserOptions = new ParserOptions();

            parserOptions.ParserCompilationMode = compilationMode;

            // Parameters have to be accessible in the body as regular scope variables, not as command parameters.
            // Hence compile view as lambda with parameters as lambda vars, then invoke the lambda specifying
            // command parameters as values of the lambda vars.
            DbLambda functionBody = CqlQuery.CompileQueryCommandLambda(
                viewDef,
                perspective,
                parserOptions,
                null /* parameters */,
                parameters.Select(pInfo => pInfo.ResultType.Variable(pInfo.ParameterName)));

            Debug.Assert(functionBody != null, "functionBody != null");
            DbExpression expr = functionBody.Invoke(parameters);

            return(expr);
        }
        internal FunctionDefinition(string name, DbLambda lambda, int startPosition, int endPosition)
        {
            Debug.Assert(name != null, "name can not be null");
            Debug.Assert(lambda != null, "lambda cannot be null");

            this._name          = name;
            this._lambda        = lambda;
            this._startPosition = startPosition;
            this._endPosition   = endPosition;
        }
Пример #9
0
        internal FunctionDefinition(string name, DbLambda lambda, int startPosition, int endPosition)
        {
            DebugCheck.NotNull(name);
            DebugCheck.NotNull(lambda);

            _name          = name;
            _lambda        = lambda;
            _startPosition = startPosition;
            _endPosition   = endPosition;
        }
Пример #10
0
        internal DbLambdaExpression(TypeUsage resultType, DbLambda lambda, DbExpressionList args)
            : base(DbExpressionKind.Lambda, resultType)
        {
            Debug.Assert(lambda != null, "DbLambdaExpression lambda cannot be null");
            Debug.Assert(args != null, "DbLambdaExpression arguments cannot be null");
            Debug.Assert(object.ReferenceEquals(resultType, lambda.Body.ResultType), "DbLambdaExpression result type must be Lambda body result type");
            Debug.Assert(lambda.Variables.Count == args.Count, "DbLambdaExpression argument count does not match Lambda parameter count");

            this._lambda    = lambda;
            this._arguments = args;
        }
Пример #11
0
                protected DbFilterExpression ComposeFilter(DbExpression input, DbProjectExpression first, DbFilterExpression second)
                {
                    // source.Project(first).Filter(second) -> source.Filter(e => second(first(e)))

                    // create lambda expression representing the filter (e => second(e))
                    DbLambda secondLambda = DbExpressionBuilder.Lambda(second.Predicate, second.Input.Variable);

                    // invoke lambda with variable from the project
                    DbFilterExpression composed = first.Input.Filter(secondLambda.Invoke(first.Projection));

                    return(RebindFilter(input, composed));
                }
Пример #12
0
        internal DbLambdaExpression(TypeUsage resultType, DbLambda lambda, DbExpressionList args)
            : base(DbExpressionKind.Lambda, resultType)
        {
            DebugCheck.NotNull(lambda);
            DebugCheck.NotNull(args);
            Debug.Assert(
                ReferenceEquals(resultType, lambda.Body.ResultType), "DbLambdaExpression result type must be Lambda body result type");
            Debug.Assert(lambda.Variables.Count == args.Count, "DbLambdaExpression argument count does not match Lambda parameter count");

            _lambda    = lambda;
            _arguments = args;
        }
Пример #13
0
        /// <summary>
        /// Parse a specific query with a specific set variables and produce a <see cref="DbLambda"/>.
        /// </summary>
        public DbLambda ParseLambda(string query, params DbVariableReferenceExpression[] variables)
        {
            EntityUtil.CheckArgumentNull(query, "query");
            if (variables != null)
            {
                IEnumerable <DbVariableReferenceExpression> varsEnum = variables;
                EntityUtil.CheckArgumentContainsNull(ref varsEnum, "variables");
            }

            DbLambda result = CqlQuery.CompileQueryCommandLambda(query, _perspective, null /* parser options - use default */, null /* parameters */, variables);

            return(result);
        }
Пример #14
0
        internal DbLambda GenerateFunctionDefinition(EdmFunction function)
        {
            if (!function.HasUserDefinedBody)
            {
                throw new InvalidOperationException(Strings.Cqt_UDF_FunctionHasNoDefinition((object)function.Identity));
            }
            DbLambda dbLambda = ExternalCalls.CompileFunctionDefinition(function.CommandTextAttribute, (IList <FunctionParameter>)function.Parameters, this);

            if (!TypeSemantics.IsStructurallyEqual(function.ReturnParameter.TypeUsage, dbLambda.Body.ResultType))
            {
                throw new InvalidOperationException(Strings.Cqt_UDF_FunctionDefinitionResultTypeMismatch((object)function.ReturnParameter.TypeUsage.ToString(), (object)function.FullName, (object)dbLambda.Body.ResultType.ToString()));
            }
            return(dbLambda);
        }
Пример #15
0
        internal static TypeUsage ValidateInvoke(
            DbLambda lambda,
            IEnumerable <DbExpression> arguments,
            out DbExpressionList validArguments)
        {
            validArguments = (DbExpressionList)null;
            EnumerableValidator <DbExpression, DbExpression, DbExpressionList> validator = ArgumentValidation.CreateValidator <DbExpression, DbExpression, DbExpressionList>(arguments, nameof(arguments), (Func <DbExpression, int, DbExpression>)((exp, idx) =>
            {
                ArgumentValidation.RequireCompatibleType(exp, lambda.Variables[idx].ResultType, nameof(arguments), idx);
                return(exp);
            }), (Func <List <DbExpression>, DbExpressionList>)(expList => new DbExpressionList((IList <DbExpression>)expList)));

            validator.ExpectedElementCount = lambda.Variables.Count;
            validArguments = validator.Validate();
            return(lambda.Body.ResultType);
        }
        public override DbExpression Visit(DbLambdaExpression expression)
        {
            EntityUtil.CheckArgumentNull(expression, "expression");

            DbExpression         result       = expression;
            IList <DbExpression> newArguments = this.VisitExpressionList(expression.Arguments);
            DbLambda             newLambda    = this.VisitLambda(expression.Lambda);

            if (!object.ReferenceEquals(expression.Arguments, newArguments) ||
                !object.ReferenceEquals(expression.Lambda, newLambda))
            {
                result = CqtBuilder.Invoke(newLambda, newArguments);
            }
            NotifyIfChanged(expression, result);
            return(result);
        }
Пример #17
0
        internal DbExpression Parse()
        {
            if (_queryExpression != null)
            {
                return(_queryExpression);
            }

            List <DbParameterReferenceExpression> parameters = null;

            if (this.Parameters != null)
            {
                parameters = new List <DbParameterReferenceExpression>(this.Parameters.Count);
                foreach (ObjectParameter parameter in this.Parameters)
                {
                    TypeUsage typeUsage = parameter.TypeUsage;
                    if (null == typeUsage)
                    {
                        // Since ObjectParameters do not allow users to specify 'facets', make
                        // sure that the parameter TypeUsage is not populated with the provider
                        // default facet values.
                        this.ObjectContext.Perspective.TryGetTypeByName(
                            parameter.MappableType.FullName,
                            false /* bIgnoreCase */,
                            out typeUsage);
                    }

                    Debug.Assert(typeUsage != null, "typeUsage != null");

                    parameters.Add(typeUsage.Parameter(parameter.Name));
                }
            }

            DbLambda lambda =
                CqlQuery.CompileQueryCommandLambda(
                    _queryText,                     // Command Text
                    this.ObjectContext.Perspective, // Perspective
                    null,                           // Parser options - null indicates 'use default'
                    parameters,                     // Parameters
                    null                            // Variables
                    );

            Debug.Assert(lambda.Variables == null || lambda.Variables.Count == 0, "lambda.Variables must be empty");

            return(lambda.Body);
        }
Пример #18
0
 /// <summary>
 /// Performs semantic conversion, validation on a query command AST and creates a <see cref="DbLambda"/>
 /// </summary>
 /// <param name="astQueryCommand">Abstract Syntax Tree of the query command</param>
 /// <param name="perspective">perspective</param>
 /// <param name="parserOptions">parser options<seealso cref="ParserOptions"/></param>
 /// <param name="parameters">ordinary command parameters</param>
 /// <param name="variables">command free variables</param>
 /// <remarks>Parameters name/types must be bound before invoking this method</remarks>
 /// <exception cref="System.Data.EntityException">Thrown when Syntatic or Semantic rules are violated and the query cannot be accepted.</exception>
 /// <exception cref="System.Data.MetadataException">Thrown as inner exception of a EntityException when metadata related service requests fail.</exception>
 /// <exception cref="System.Data.MappingException">Thrown as inner exception of a EntityException when mapping related service requests fail.</exception>
 /// <remarks>
 /// This method is not thread safe.
 /// </remarks>
 /// <seealso cref="ParserOptions"/>
 /// <seealso cref="DbExpression"/>
 private static DbLambda AnalyzeQueryExpressionSemantics(AST.Node astQueryCommand,
                                                         Perspective perspective,
                                                         ParserOptions parserOptions,
                                                         IEnumerable <DbParameterReferenceExpression> parameters,
                                                         IEnumerable <DbVariableReferenceExpression> variables)
 {
     return(AnalyzeSemanticsCommon(
                astQueryCommand,
                perspective,
                parserOptions,
                parameters,
                variables,
                (analyzer, astExpr) =>
     {
         DbLambda lambda = analyzer.AnalyzeQueryCommand(astExpr);
         Debug.Assert(null != lambda, "null != lambda post-condition FAILED");
         return lambda;
     }));
 }
Пример #19
0
        /// <summary>
        /// Compiles an eSQL query command producing a validated <see cref="DbLambda"/>.
        /// </summary>
        /// <param name="queryCommandText">eSQL query command text</param>
        /// <param name="perspective">perspective</param>
        /// <param name="parserOptions">parser options<seealso cref="ParserOptions"/></param>
        /// <param name="parameters">ordinary command parameters</param>
        /// <param name="variables">command free variables</param>
        /// <returns>The query expression tree produced by parsing the given query command.</returns>
        /// <exception cref="System.Data.EntityException">Thrown when Syntatic or Semantic rules are violated and the query expression cannot be accepted</exception>
        /// <exception cref="System.Data.MetadataException">Thrown when metadata related service requests fail</exception>
        /// <exception cref="System.Data.MappingException">Thrown when mapping related service requests fail</exception>
        /// <remarks>
        /// This method is not thread safe.
        /// </remarks>
        /// <seealso cref="ParserOptions"/>
        /// <seealso cref="DbExpression"/>
        internal static DbLambda CompileQueryCommandLambda(string queryCommandText,
                                                           Perspective perspective,
                                                           ParserOptions parserOptions,
                                                           IEnumerable <DbParameterReferenceExpression> parameters,
                                                           IEnumerable <DbVariableReferenceExpression> variables)
        {
            return(CompileCommon(queryCommandText, perspective, parserOptions, (astCommand, validatedParserOptions) =>
            {
                DbLambda lambda = AnalyzeQueryExpressionSemantics(astCommand,
                                                                  perspective,
                                                                  validatedParserOptions,
                                                                  parameters,
                                                                  variables);


                TypeHelpers.AssertEdmType(lambda.Body.ResultType);

                Debug.Assert(lambda != null, "lambda != null post-condition FAILED");

                return lambda;
            }));
        }
Пример #20
0
 /// <summary>
 ///     Convenience method for post-processing after a DbLambda has been visited.
 /// </summary>
 /// <param name="lambda"> The previously visited DbLambda. </param>
 protected virtual void VisitLambdaPost(DbLambda lambda)
 {
 }
Пример #21
0
 /// <summary>
 ///     Convenience method indicating that the body of a Lambda <see cref="DbFunctionExpression" /> is now about to be visited.
 /// </summary>
 /// <param name="lambda"> The DbLambda that is about to be visited </param>
 /// <exception cref="ArgumentNullException">
 ///     <paramref name="lambda" />
 ///     is null
 /// </exception>
 protected virtual void VisitLambdaPre(DbLambda lambda)
 {
     Check.NotNull(lambda, "lambda");
 }
Пример #22
0
 /// <summary>
 /// Convenience method indicating that the body of a Lambda <see cref="T:System.Data.Entity.Core.Common.CommandTrees.DbFunctionExpression" /> is now about to be visited.
 /// </summary>
 /// <param name="lambda"> The DbLambda that is about to be visited </param>
 /// <exception cref="T:System.ArgumentNullException">
 /// <paramref name="lambda" />
 /// is null
 /// </exception>
 protected virtual void VisitLambdaPre(DbLambda lambda)
 {
     Check.NotNull <DbLambda>(lambda, nameof(lambda));
 }
Пример #23
0
 /// <summary>
 /// Convenience method indicating that the body of a Lambda <see cref="DbFunctionExpression"/> is now about to be visited.
 /// </summary>
 /// <param name="lambda">The DbLambda that is about to be visited</param>
 /// <exception cref="ArgumentNullException"><paramref name="lambda"/> is null</exception>
 protected virtual void VisitLambdaPre(DbLambda lambda)
 {
     EntityUtil.CheckArgumentNull(lambda, "lambda");
 }
 /// <summary>
 ///     Dumps the specified DbLambda instance
 /// </summary>
 /// <param name="lambda"> The DbLambda to dump. </param>
 internal void Dump(DbLambda lambda)
 {
     Begin("DbLambda");
     Dump(lambda.Variables.Cast<DbExpression>(), "Variables", "Variable");
     Dump(lambda.Body, "Body");
     End("DbLambda");
 }
        private DbExpression RewriteRow(DbExpression expression, RowType rowType)
        {
            DbLambdaExpression             lambdaExpression   = expression as DbLambdaExpression;
            DbNewInstanceExpression        instanceExpression = lambdaExpression == null ? expression as DbNewInstanceExpression : lambdaExpression.Lambda.Body as DbNewInstanceExpression;
            Dictionary <int, DbExpression> dictionary1        = (Dictionary <int, DbExpression>)null;
            Dictionary <int, DbExpression> dictionary2        = (Dictionary <int, DbExpression>)null;

            for (int index = 0; index < rowType.Properties.Count; ++index)
            {
                EdmProperty  property     = rowType.Properties[index];
                DbExpression expression1  = instanceExpression == null ? (DbExpression)expression.Property(property.Name) : instanceExpression.Arguments[index];
                DbExpression dbExpression = this.Rewrite(expression1);
                if (!object.ReferenceEquals((object)dbExpression, (object)expression1))
                {
                    if (dictionary2 == null)
                    {
                        dictionary2 = new Dictionary <int, DbExpression>();
                    }
                    dictionary2[index] = dbExpression;
                }
                else
                {
                    if (dictionary1 == null)
                    {
                        dictionary1 = new Dictionary <int, DbExpression>();
                    }
                    dictionary1[index] = expression1;
                }
            }
            if (dictionary2 == null)
            {
                return(expression);
            }
            List <DbExpression> dbExpressionList = new List <DbExpression>(rowType.Properties.Count);
            List <EdmProperty>  edmPropertyList  = new List <EdmProperty>(rowType.Properties.Count);

            for (int key = 0; key < rowType.Properties.Count; ++key)
            {
                EdmProperty  property     = rowType.Properties[key];
                DbExpression dbExpression = (DbExpression)null;
                if (!dictionary2.TryGetValue(key, out dbExpression))
                {
                    dbExpression = dictionary1[key];
                }
                dbExpressionList.Add(dbExpression);
                edmPropertyList.Add(new EdmProperty(property.Name, dbExpression.ResultType));
            }
            RowType      spannedType   = new RowType((IEnumerable <EdmProperty>)edmPropertyList, rowType.InitializerMetadata);
            TypeUsage    typeUsage     = TypeUsage.Create((EdmType)spannedType);
            DbExpression dbExpression1 = (DbExpression)typeUsage.New((IEnumerable <DbExpression>)dbExpressionList);

            if (instanceExpression == null)
            {
                dbExpression1 = (DbExpression)DbExpressionBuilder.Case((IEnumerable <DbExpression>) new List <DbExpression>((IEnumerable <DbExpression>) new DbExpression[1]
                {
                    (DbExpression)expression.IsNull()
                }), (IEnumerable <DbExpression>) new List <DbExpression>((IEnumerable <DbExpression>) new DbExpression[1]
                {
                    (DbExpression)typeUsage.Null()
                }), dbExpression1);
            }
            this.AddSpannedRowType(spannedType, expression.ResultType);
            if (lambdaExpression != null && instanceExpression != null)
            {
                dbExpression1 = (DbExpression)DbLambda.Create(dbExpression1, (IEnumerable <DbVariableReferenceExpression>)lambdaExpression.Lambda.Variables).Invoke((IEnumerable <DbExpression>)lambdaExpression.Arguments);
            }
            return(dbExpression1);
        }
Пример #26
0
        private DbExpression RewriteRow(DbExpression expression, RowType rowType)
        {
            DbLambdaExpression      lambdaExpression = expression as DbLambdaExpression;
            DbNewInstanceExpression newRow;

            if (lambdaExpression != null)
            {
                // NOTE: We rely on the fact that today span cannot be done over queries containing DbLambdaExpressions
                // created by users, because user-created expressions cannot be used for querying in O-space.
                // If that were to change, pushing span beyond a LambdaExpression could cause variable name
                // collisions between the variable names used in the Lambda and the names generated by the
                // RelationshipNavigationVisitor.
                newRow = lambdaExpression.Lambda.Body as DbNewInstanceExpression;
            }
            else
            {
                newRow = expression as DbNewInstanceExpression;
            }

            Dictionary <int, DbExpression> unmodifiedColumns = null;
            Dictionary <int, DbExpression> spannedColumns    = null;

            for (int idx = 0; idx < rowType.Properties.Count; idx++)
            {
                // Retrieve the property that represents the current column
                EdmProperty columnProp = rowType.Properties[idx];

                // Construct an expression that defines the current column.
                DbExpression columnExpr = null;
                if (newRow != null)
                {
                    // For a row-constructing NewInstance expression, the corresponding argument can simply be used
                    columnExpr = newRow.Arguments[idx];
                }
                else
                {
                    // For all other expressions the property corresponding to the column name must be retrieved
                    // from the row-typed expression
                    columnExpr = expression.Property(columnProp.Name);
                }

                DbExpression spannedColumn = this.Rewrite(columnExpr);
                if (!object.ReferenceEquals(spannedColumn, columnExpr))
                {
                    // If so, then update the dictionary of column index to span information
                    if (null == spannedColumns)
                    {
                        spannedColumns = new Dictionary <int, DbExpression>();
                    }

                    spannedColumns[idx] = spannedColumn;
                }
                else
                {
                    // Otherwise, update the dictionary of column index to unmodified expression
                    if (null == unmodifiedColumns)
                    {
                        unmodifiedColumns = new Dictionary <int, DbExpression>();
                    }

                    unmodifiedColumns[idx] = columnExpr;
                }
            }

            // A new expression need only be built if at least one column was spanned
            if (null == spannedColumns)
            {
                // No columns were spanned, indicate that the original expression should remain.
                return(expression);
            }
            else
            {
                // At least one column was spanned, so build a new row constructor that defines the new row, including spanned columns.
                List <DbExpression> columnArguments = new List <DbExpression>(rowType.Properties.Count);
                List <EdmProperty>  properties      = new List <EdmProperty>(rowType.Properties.Count);
                for (int idx = 0; idx < rowType.Properties.Count; idx++)
                {
                    EdmProperty  columnProp = rowType.Properties[idx];
                    DbExpression columnDef  = null;
                    if (!spannedColumns.TryGetValue(idx, out columnDef))
                    {
                        columnDef = unmodifiedColumns[idx];
                    }
                    columnArguments.Add(columnDef);
                    properties.Add(new EdmProperty(columnProp.Name, columnDef.ResultType));
                }

                // Copy over any eLinq initializer metadata (if present, or null if not).
                // Note that this initializer metadata does not strictly match the new row type
                // that includes spanned columns, but will be correct once the object materializer
                // has interpreted the query results to produce the correct value for each colum.
                RowType      rewrittenRow          = new RowType(properties, rowType.InitializerMetadata);
                TypeUsage    rewrittenRowTypeUsage = TypeUsage.Create(rewrittenRow);
                DbExpression rewritten             = rewrittenRowTypeUsage.New(columnArguments);

                // SQLBUDT #554182: If we insert a new projection we should should make sure to
                // not interfere with the nullability of the input.
                // In particular, if the input row is null and we construct a new row as a projection over its columns
                // we would get a row consisting of nulls, instead of a null row.
                // Thus, given an input X, we rewritte it as:  if (X is null) then NULL else rewritten.
                if (newRow == null)
                {
                    DbExpression condition      = DbExpressionBuilder.CreateIsNullExpressionAllowingRowTypeArgument(expression);
                    DbExpression nullExpression = DbExpressionBuilder.Null(rewrittenRowTypeUsage);
                    rewritten = DbExpressionBuilder.Case(
                        new List <DbExpression>(new DbExpression[] { condition }),
                        new List <DbExpression>(new DbExpression[] { nullExpression }),
                        rewritten);
                }

                // Add an entry to the spanned row type => original row type map for the new row type.
                AddSpannedRowType(rewrittenRow, expression.ResultType);

                if (lambdaExpression != null && newRow != null)
                {
                    rewritten = DbLambda.Create(rewritten, lambdaExpression.Lambda.Variables).Invoke(lambdaExpression.Arguments);
                }

                return(rewritten);
            }
        }
 internal DbLambdaExpression(TypeUsage resultType, DbLambda lambda, DbExpressionList args)
     : base(DbExpressionKind.Lambda, resultType, true)
 {
     this._lambda    = lambda;
     this._arguments = args;
 }