Base class for simple column maps; can be either a VarRefColumnMap or ScalarColumnMap; the former is used pretty much throughout the PlanCompiler, while the latter will only be used once we generate the final Plan.
Inheritance: System.Data.Entity.Core.Query.InternalTrees.ColumnMap
        private static EntityColumnMap CreateEntityTypeElementColumnMap(
            DbDataReader storeDataReader,
            EdmType edmType,
            EntitySet entitySet,
            ColumnMap[] propertyColumnMaps,
            Dictionary <string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping> renameList)
        {
            EntityType entityType = (EntityType)edmType;

            ColumnMap[] columnMapArray = new ColumnMap[storeDataReader.FieldCount];
            foreach (ColumnMap propertyColumnMap in propertyColumnMaps)
            {
                int columnPos = ((ScalarColumnMap)propertyColumnMap).ColumnPos;
                columnMapArray[columnPos] = propertyColumnMap;
            }
            IList <EdmMember> keyMembers = (IList <EdmMember>)entityType.KeyMembers;

            SimpleColumnMap[] keyColumns = new SimpleColumnMap[keyMembers.Count];
            int index = 0;

            foreach (EdmMember member in (IEnumerable <EdmMember>)keyMembers)
            {
                int       ordinalFromReader = ColumnMapFactory.GetMemberOrdinalFromReader(storeDataReader, member, edmType, renameList);
                ColumnMap columnMap         = columnMapArray[ordinalFromReader];
                keyColumns[index] = (SimpleColumnMap)columnMap;
                ++index;
            }
            SimpleEntityIdentity simpleEntityIdentity = new SimpleEntityIdentity(entitySet, keyColumns);

            return(new EntityColumnMap(TypeUsage.Create(edmType), edmType.Name, propertyColumnMaps, (EntityIdentity)simpleEntityIdentity));
        }
 internal DiscriminatedEntityIdentity(
     SimpleColumnMap entitySetColumn,
     EntitySet[] entitySetMap,
     SimpleColumnMap[] keyColumns)
     : base(keyColumns)
 {
     this.m_entitySetColumn = entitySetColumn;
     this.m_entitySetMap    = entitySetMap;
 }
Example #3
0
 internal ComplexTypeColumnMap(
     TypeUsage type,
     string name,
     ColumnMap[] properties,
     SimpleColumnMap nullSentinel)
     : base(type, name, properties)
 {
     this.m_nullSentinel = nullSentinel;
 }
Example #4
0
        protected override EntityIdentity VisitEntityIdentity(
            DiscriminatedEntityIdentity entityIdentity,
            VarMap replacementVarMap)
        {
            SimpleColumnMap entitySetColumn = (SimpleColumnMap)entityIdentity.EntitySetColumnMap.Accept <ColumnMap, VarMap>((ColumnMapVisitorWithResults <ColumnMap, VarMap>) this, replacementVarMap);

            SimpleColumnMap[] keyColumns = this.VisitList <SimpleColumnMap>(entityIdentity.Keys, replacementVarMap);
            return((EntityIdentity) new DiscriminatedEntityIdentity(entitySetColumn, entityIdentity.EntitySetMap, keyColumns));
        }
        private readonly EntitySet[] m_entitySetMap;        // optional dictionary that maps values to entitysets

        // <summary>
        // Simple constructor
        // </summary>
        // <param name="entitySetColumn"> column map representing the entityset </param>
        // <param name="entitySetMap"> Map from value -> the appropriate entityset </param>
        // <param name="keyColumns"> list of key columns </param>
        internal DiscriminatedEntityIdentity(
            SimpleColumnMap entitySetColumn, EntitySet[] entitySetMap,
            SimpleColumnMap[] keyColumns)
            : base(keyColumns)
        {
            DebugCheck.NotNull(entitySetColumn);
            DebugCheck.NotNull(entitySetMap);
            m_entitySetColumn = entitySetColumn;
            m_entitySetMap    = entitySetMap;
        }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="type">datatype of column</param>
        /// <param name="name">column name</param>
        /// <param name="elementMap">column map for collection element</param>
        /// <param name="keys">List of keys</param>
        /// <param name="foreignKeys">List of foreign keys</param>
        internal CollectionColumnMap(
            TypeUsage type, string name, ColumnMap elementMap, SimpleColumnMap[] keys, SimpleColumnMap[] foreignKeys)
            : base(type, name)
        {
            Debug.Assert(elementMap != null, "Must specify column map for element");

            m_element = elementMap;
            m_keys = keys ?? new SimpleColumnMap[0];
            m_foreignKeys = foreignKeys ?? new SimpleColumnMap[0];
        }
        private readonly EntitySet[] m_entitySetMap; // optional dictionary that maps values to entitysets

        // <summary>
        // Simple constructor
        // </summary>
        // <param name="entitySetColumn"> column map representing the entityset </param>
        // <param name="entitySetMap"> Map from value -> the appropriate entityset </param>
        // <param name="keyColumns"> list of key columns </param>
        internal DiscriminatedEntityIdentity(
            SimpleColumnMap entitySetColumn, EntitySet[] entitySetMap,
            SimpleColumnMap[] keyColumns)
            : base(keyColumns)
        {
            DebugCheck.NotNull(entitySetColumn);
            DebugCheck.NotNull(entitySetMap);
            m_entitySetColumn = entitySetColumn;
            m_entitySetMap = entitySetMap;
        }
        /// <summary>
        ///     Constructor
        /// </summary>
        /// <param name="type"> datatype of column </param>
        /// <param name="name"> column name </param>
        /// <param name="elementMap"> column map for collection element </param>
        /// <param name="keys"> List of keys </param>
        /// <param name="foreignKeys"> List of foreign keys </param>
        internal CollectionColumnMap(
            TypeUsage type, string name, ColumnMap elementMap, SimpleColumnMap[] keys, SimpleColumnMap[] foreignKeys)
            : base(type, name)
        {
            DebugCheck.NotNull(elementMap);

            m_element = elementMap;
            m_keys = keys ?? new SimpleColumnMap[0];
            m_foreignKeys = foreignKeys ?? new SimpleColumnMap[0];
        }
        private readonly EntitySet[] m_entitySetMap; // optional dictionary that maps values to entitysets

        /// <summary>
        /// Simple constructor
        /// </summary>
        /// <param name="entitySetColumn">column map representing the entityset</param>
        /// <param name="entitySetMap">Map from value -> the appropriate entityset</param>
        /// <param name="keyColumns">list of key columns</param>
        internal DiscriminatedEntityIdentity(
            SimpleColumnMap entitySetColumn, EntitySet[] entitySetMap,
            SimpleColumnMap[] keyColumns)
            : base(keyColumns)
        {
            Debug.Assert(entitySetColumn != null, "Must specify a column map to identify the entity set");
            Debug.Assert(entitySetMap != null, "Must specify a dictionary to look up entitysets");
            m_entitySetColumn = entitySetColumn;
            m_entitySetMap = entitySetMap;
        }
Example #10
0
        internal override ColumnMap Visit(
            DiscriminatedCollectionColumnMap columnMap,
            VarMap replacementVarMap)
        {
            ColumnMap       elementMap    = columnMap.Element.Accept <ColumnMap, VarMap>((ColumnMapVisitorWithResults <ColumnMap, VarMap>) this, replacementVarMap);
            SimpleColumnMap discriminator = (SimpleColumnMap)columnMap.Discriminator.Accept <ColumnMap, VarMap>((ColumnMapVisitorWithResults <ColumnMap, VarMap>) this, replacementVarMap);

            SimpleColumnMap[] keys        = this.VisitList <SimpleColumnMap>(columnMap.Keys, replacementVarMap);
            SimpleColumnMap[] foreignKeys = this.VisitList <SimpleColumnMap>(columnMap.ForeignKeys, replacementVarMap);
            return((ColumnMap) new DiscriminatedCollectionColumnMap(columnMap.Type, columnMap.Name, elementMap, keys, foreignKeys, discriminator, columnMap.DiscriminatorValue));
        }
Example #11
0
        internal override ColumnMap Visit(RecordColumnMap columnMap, VarMap replacementVarMap)
        {
            SimpleColumnMap nullSentinel = columnMap.NullSentinel;

            if (nullSentinel != null)
            {
                nullSentinel = (SimpleColumnMap)nullSentinel.Accept <ColumnMap, VarMap>((ColumnMapVisitorWithResults <ColumnMap, VarMap>) this, replacementVarMap);
            }
            ColumnMap[] properties = this.VisitList <ColumnMap>(columnMap.Properties, replacementVarMap);
            return((ColumnMap) new RecordColumnMap(columnMap.Type, columnMap.Name, properties, nullSentinel));
        }
Example #12
0
 internal SimplePolymorphicColumnMap(
     TypeUsage type,
     string name,
     ColumnMap[] baseTypeColumns,
     SimpleColumnMap typeDiscriminator,
     Dictionary <object, TypedColumnMap> typeChoices)
     : base(type, name, baseTypeColumns)
 {
     this.m_typedColumnMap    = typeChoices;
     this.m_typeDiscriminator = typeDiscriminator;
 }
 internal DiscriminatedCollectionColumnMap(
     TypeUsage type,
     string name,
     ColumnMap elementMap,
     SimpleColumnMap[] keys,
     SimpleColumnMap[] foreignKeys,
     SimpleColumnMap discriminator,
     object discriminatorValue)
     : base(type, name, elementMap, keys, foreignKeys)
 {
     this.m_discriminator      = discriminator;
     this.m_discriminatorValue = discriminatorValue;
 }
 /// <summary>
 ///     Internal constructor
 /// </summary>
 /// <param name="type"> datatype of the column </param>
 /// <param name="name"> column name </param>
 /// <param name="baseTypeColumns"> base list of fields common to all types </param>
 /// <param name="typeDiscriminator"> column map for type discriminator column </param>
 /// <param name="typeChoices"> map from type discriminator value->columnMap </param>
 internal SimplePolymorphicColumnMap(
     TypeUsage type,
     string name,
     ColumnMap[] baseTypeColumns,
     SimpleColumnMap typeDiscriminator,
     Dictionary <object, TypedColumnMap> typeChoices)
     : base(type, name, baseTypeColumns)
 {
     DebugCheck.NotNull(typeDiscriminator);
     DebugCheck.NotNull(typeChoices);
     m_typedColumnMap    = typeChoices;
     m_typeDiscriminator = typeDiscriminator;
 }
Example #15
0
 /// <summary>
 ///     Internal constructor
 /// </summary>
 /// <param name="type"> Column datatype </param>
 /// <param name="name"> column name </param>
 /// <param name="elementMap"> column map for collection element </param>
 /// <param name="keys"> Keys for the collection </param>
 /// <param name="foreignKeys"> Foreign keys for the collection </param>
 /// <param name="discriminator"> Discriminator column map </param>
 /// <param name="discriminatorValue"> Discriminator value </param>
 internal DiscriminatedCollectionColumnMap(
     TypeUsage type, string name,
     ColumnMap elementMap,
     SimpleColumnMap[] keys,
     SimpleColumnMap[] foreignKeys,
     SimpleColumnMap discriminator,
     object discriminatorValue)
     : base(type, name, elementMap, keys, foreignKeys)
 {
     DebugCheck.NotNull(discriminator);
     DebugCheck.NotNull(discriminatorValue);
     m_discriminator      = discriminator;
     m_discriminatorValue = discriminatorValue;
 }
Example #16
0
        internal override ColumnMap Visit(
            SimplePolymorphicColumnMap columnMap,
            VarMap replacementVarMap)
        {
            SimpleColumnMap typeDiscriminator = (SimpleColumnMap)columnMap.TypeDiscriminator.Accept <ColumnMap, VarMap>((ColumnMapVisitorWithResults <ColumnMap, VarMap>) this, replacementVarMap);
            Dictionary <object, TypedColumnMap> typeChoices = new Dictionary <object, TypedColumnMap>(columnMap.TypeChoices.Comparer);

            foreach (KeyValuePair <object, TypedColumnMap> typeChoice in columnMap.TypeChoices)
            {
                TypedColumnMap typedColumnMap = (TypedColumnMap)typeChoice.Value.Accept <ColumnMap, VarMap>((ColumnMapVisitorWithResults <ColumnMap, VarMap>) this, replacementVarMap);
                typeChoices[typeChoice.Key] = typedColumnMap;
            }
            ColumnMap[] baseTypeColumns = this.VisitList <ColumnMap>(columnMap.Properties, replacementVarMap);
            return((ColumnMap) new SimplePolymorphicColumnMap(columnMap.Type, columnMap.Name, baseTypeColumns, typeDiscriminator, typeChoices));
        }
Example #17
0
        // <summary>
        // Build the entityColumnMap from a store datareader, a type and an entitySet and
        // a list of properties.
        // </summary>
        private static EntityColumnMap CreateEntityTypeElementColumnMap(
            DbDataReader storeDataReader, EdmType edmType, EntitySet entitySet,
            ColumnMap[] propertyColumnMaps, Dictionary <string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping> renameList)
        {
            var entityType = (EntityType)edmType;

            // The tricky part here is
            // that the KeyColumns list must point at the same ColumnMap(s) that
            // the properties list points to, so we build a quick array of
            // ColumnMap(s) that are indexed by their ordinal; then we can walk
            // the list of keyMembers, and find the ordinal in the reader, and
            // pick the same ColumnMap for it.

            // Build the ordinal -> ColumnMap index
            var ordinalToColumnMap = new ColumnMap[storeDataReader.FieldCount];

            foreach (var propertyColumnMap in propertyColumnMaps)
            {
                var ordinal = ((ScalarColumnMap)propertyColumnMap).ColumnPos;
                ordinalToColumnMap[ordinal] = propertyColumnMap;
            }

            // Now build the list of KeyColumns;
            IList <EdmMember> keyMembers = entityType.KeyMembers;
            var keyColumns = new SimpleColumnMap[keyMembers.Count];

            var keyMemberIndex = 0;

            foreach (var keyMember in keyMembers)
            {
                var keyOrdinal = GetMemberOrdinalFromReader(storeDataReader, keyMember, edmType, renameList);

                Debug.Assert(keyOrdinal >= 0, "keyMember for entity is not found by name in the data reader?");

                var keyColumnMap = ordinalToColumnMap[keyOrdinal];

                Debug.Assert(null != keyColumnMap, "keyMember for entity isn't in properties collection for the entity?");
                keyColumns[keyMemberIndex] = (SimpleColumnMap)keyColumnMap;
                keyMemberIndex++;
            }

            var entityIdentity = new SimpleEntityIdentity(entitySet, keyColumns);

            var result = new EntityColumnMap(TypeUsage.Create(edmType), edmType.Name, propertyColumnMaps, entityIdentity);

            return(result);
        }
        private readonly EntitySet m_entitySet; // the entity set

        /// <summary>
        ///     Basic constructor.
        ///     Note: the entitySet may be null - in which case, we are referring to
        ///     a transient entity
        /// </summary>
        /// <param name="entitySet"> The entityset </param>
        /// <param name="keyColumns"> key columns of the entity </param>
        internal SimpleEntityIdentity(EntitySet entitySet, SimpleColumnMap[] keyColumns)
            : base(keyColumns)
        {
            // the entityset may be null
            m_entitySet = entitySet;
        }
Example #19
0
        // <summary>
        // convert MultiStreamNestOp to SingleStreamNestOp
        // </summary>
        // <remarks>
        // A MultiStreamNestOp is typically of the form M(D, N1, N2, ..., Nk)
        // where D is the driver stream, and N1, N2 etc. represent the collections.
        // In general, this can be converted into a SingleStreamNestOp over:
        // (D+ outerApply N1) AugmentedUnionAll (D+ outerApply N2) ...
        // Where:
        // D+ is D with an extra discriminator column that helps to identify
        // the specific collection.
        // AugmentedUnionAll is simply a unionAll where each branch of the
        // unionAll is augmented with nulls for the corresponding columns
        // of other tables in the branch
        // The simple case where there is only a single nested collection is easier
        // to address, and can be represented by:
        // MultiStreamNest(D, N1) => SingleStreamNest(OuterApply(D, N1))
        // The more complex case, where there is more than one nested column, requires
        // quite a bit more work:
        // MultiStreamNest(D, X, Y,...) => SingleStreamNest(UnionAll(Project{"1", D1...Dn, X1...Xn, nY1...nYn}(OuterApply(D, X)), Project{"2", D1...Dn, nX1...nXn, Y1...Yn}(OuterApply(D, Y)), ...))
        // Where:
        // D           is the driving collection
        // D1...Dn     are the columns from the driving collection
        // X           is the first nested collection
        // X1...Xn     are the columns from the first nested collection
        // nX1...nXn   are null values for all columns from the first nested collection
        // Y           is the second nested collection
        // Y1...Yn     are the columns from the second nested collection
        // nY1...nYn   are null values for all columns from the second nested collection
        // </remarks>
        private Node ConvertToSingleStreamNest(
            Node nestNode, Dictionary<Var, ColumnMap> varRefReplacementMap, VarList flattenedOutputVarList,
            out SimpleColumnMap[] parentKeyColumnMaps)
        {
#if DEBUG
            var input = Dump.ToXml(nestNode);
#endif
            //DEBUG
            var nestOp = (MultiStreamNestOp)nestNode.Op;

            // We can't convert this node to a SingleStreamNest until all it's MultiStreamNest 
            // inputs are converted, so do that first.
            for (var i = 1; i < nestNode.Children.Count; i++)
            {
                var chi = nestNode.Children[i];

                if (chi.Op.OpType
                    == OpType.MultiStreamNest)
                {
                    var chiCi = nestOp.CollectionInfo[i - 1];

                    var childFlattenedOutputVars = Command.CreateVarList();
                    SimpleColumnMap[] childKeyColumnMaps;

                    nestNode.Children[i] = ConvertToSingleStreamNest(
                        chi, varRefReplacementMap, childFlattenedOutputVars, out childKeyColumnMaps);

                    // Now this may seem odd here, and it may look like we should have done this
                    // inside the recursive ConvertToSingleStreamNest call above, but that call
                    // doesn't have access to the CollectionInfo for it's parent, which is what
                    // we need to manipulate before we enter the loop below where we try and fold
                    // THIS nestOp nodes into a singleStreamNestOp.
                    var childColumnMap = ColumnMapTranslator.Translate(chiCi.ColumnMap, varRefReplacementMap);

                    var childKeys = Command.CreateVarVec(((SingleStreamNestOp)nestNode.Children[i].Op).Keys);

                    nestOp.CollectionInfo[i - 1] = Command.CreateCollectionInfo(
                        chiCi.CollectionVar,
                        childColumnMap,
                        childFlattenedOutputVars,
                        childKeys,
                        chiCi.SortKeys,
                        null /*discriminatorValue*/
                        );
                }
            }

            // Make sure that the driving node has keys defined. Otherwise we're in
            // trouble; we must be able to infer keys from the driving node.
            var drivingNode = nestNode.Child0;
            var drivingNodeKeys = Command.PullupKeys(drivingNode);
            if (drivingNodeKeys.NoKeys)
            {
                // ALMINEEV: In this case we used to wrap drivingNode into a projection that would also project Edm.NewGuid() thus giving us a synthetic key.
                // This solution did not work however due to a bug in SQL Server that allowed pulling non-deterministic functions above joins and applies, thus 
                // producing incorrect results. SQL Server bug was filed in "sqlbuvsts01\Sql Server" database as #725272.
                // The only known path how we can get a keyless drivingNode is if 
                //    - drivingNode is over a TVF call
                //    - TVF is declared as Collection(Row) is SSDL (the only form of TVF definitions at the moment)
                //    - TVF is not mapped to entities
                //      Note that if TVF is mapped to entities via function import mapping, and the user query is actually the call of the 
                //      function import, we infer keys for the TVF from the c-space entity keys and their mappings.
                throw new NotSupportedException(Strings.ADP_KeysRequiredForNesting);
            }

            // Get a deterministic ordering of Vars from this node.
            // NOTE: we're using the drivingNode's definitions, which is a VarVec so it
            //       won't match the order of the input's columns, but the key thing is 
            //       that we use the same order for all nested children, so it's OK.
            var drivingNodeInfo = Command.GetExtendedNodeInfo(drivingNode);
            var drivingNodeVarVec = drivingNodeInfo.Definitions;
            var drivingNodeVars = Command.CreateVarList(drivingNodeVarVec);

            // Normalize all collection inputs to the nestOp. Specifically, remove any
            // SortOps (adding the sort keys to the postfix sortkey list). Additionally,
            // add a discriminatorVar to each collection child
            VarList discriminatorVarList;
            List<List<SortKey>> postfixSortKeyList;
            NormalizeNestOpInputs(nestOp, nestNode, out discriminatorVarList, out postfixSortKeyList);

            // Now build up the union-all subquery
            List<Dictionary<Var, Var>> varMapList;
            Var outputDiscriminatorVar;
            var unionAllNode = BuildUnionAllSubqueryForNestOp(
                nestOp, nestNode, drivingNodeVars, discriminatorVarList, out outputDiscriminatorVar, out varMapList);
            var drivingNodeVarMap = varMapList[0];

            // OK.  We've finally created the UnionAll over each of the project/outerApply
            // combinations.  We know that the output columns will be:
            //
            //      Discriminator, DrivingColumns, Collection1Columns, Collection2Columns, ...
            //
            // Now, rebuild the columnMaps, since all of the columns in the original column
            // maps are now referencing newer variables.  To do that, we'll walk the list of
            // outputs from the unionAll, and construct new VarRefColumnMaps for each one,
            // and adding it to a ColumnMapPatcher, which we'll use to actually fix everything
            // up.
            //
            // While we're at it, we'll build a new list of top-level output columns, which
            // should include only the Discriminator, the columns from the driving collection,
            // and and one column for each of the nested collections.

            // Start building the flattenedOutputVarList that the top level PhysicalProjectOp
            // is to output.
            flattenedOutputVarList.AddRange(RemapVars(drivingNodeVars, drivingNodeVarMap));

            var flattenedOutputVarVec = Command.CreateVarVec(flattenedOutputVarList);
            var nestOpOutputs = Command.CreateVarVec(flattenedOutputVarVec);

            // Add any adjustments to the driving nodes vars to the column map patcher
            foreach (var kv in drivingNodeVarMap)
            {
                if (kv.Key
                    != kv.Value)
                {
                    varRefReplacementMap[kv.Key] = new VarRefColumnMap(kv.Value);
                }
            }

            RemapSortKeys(nestOp.PrefixSortKeys, drivingNodeVarMap);

            var newPostfixSortKeys = new List<SortKey>();
            var newCollectionInfoList = new List<CollectionInfo>();

            // Build the discriminator column map, and ensure it's in the outputs
            var discriminatorColumnMap = new VarRefColumnMap(outputDiscriminatorVar);
            nestOpOutputs.Set(outputDiscriminatorVar);

            if (!flattenedOutputVarVec.IsSet(outputDiscriminatorVar))
            {
                flattenedOutputVarList.Add(outputDiscriminatorVar);
                flattenedOutputVarVec.Set(outputDiscriminatorVar);
            }

            // Build the key column maps, and ensure they're in the outputs as well.
            var parentKeys = RemapVarVec(drivingNodeKeys.KeyVars, drivingNodeVarMap);
            parentKeyColumnMaps = new SimpleColumnMap[parentKeys.Count];

            var index = 0;
            foreach (var keyVar in parentKeys)
            {
                parentKeyColumnMaps[index] = new VarRefColumnMap(keyVar);
                index++;

                if (!flattenedOutputVarVec.IsSet(keyVar))
                {
                    flattenedOutputVarList.Add(keyVar);
                    flattenedOutputVarVec.Set(keyVar);
                }
            }

            // Now that we've handled the driving node, deal with each of the 
            // nested inputs, in sequence.
            for (var i = 1; i < nestNode.Children.Count; i++)
            {
                var ci = nestOp.CollectionInfo[i - 1];
                var postfixSortKeys = postfixSortKeyList[i];

                RemapSortKeys(postfixSortKeys, varMapList[i]);
                newPostfixSortKeys.AddRange(postfixSortKeys);

                var newColumnMap = ColumnMapTranslator.Translate(ci.ColumnMap, varMapList[i]);
                var newFlattenedElementVars = RemapVarList(ci.FlattenedElementVars, varMapList[i]);
                var newCollectionKeys = RemapVarVec(ci.Keys, varMapList[i]);

                RemapSortKeys(ci.SortKeys, varMapList[i]);

                var newCollectionInfo = Command.CreateCollectionInfo(
                    ci.CollectionVar,
                    newColumnMap,
                    newFlattenedElementVars,
                    newCollectionKeys,
                    ci.SortKeys,
                    i);
                newCollectionInfoList.Add(newCollectionInfo);

                // For a collection Var, we add the flattened elementVars for the
                // collection in place of the collection Var itself, and we create
                // a new column map to represent all the stuff we've done.

                foreach (var v in newFlattenedElementVars)
                {
                    if (!flattenedOutputVarVec.IsSet(v))
                    {
                        flattenedOutputVarList.Add(v);
                        flattenedOutputVarVec.Set(v);
                    }
                }

                nestOpOutputs.Set(ci.CollectionVar);

                var keyColumnMapIndex = 0;
                var keyColumnMaps = new SimpleColumnMap[newCollectionInfo.Keys.Count];
                foreach (var keyVar in newCollectionInfo.Keys)
                {
                    keyColumnMaps[keyColumnMapIndex] = new VarRefColumnMap(keyVar);
                    keyColumnMapIndex++;
                }

                var collectionColumnMap = new DiscriminatedCollectionColumnMap(
                    TypeUtils.CreateCollectionType(newCollectionInfo.ColumnMap.Type),
                    newCollectionInfo.ColumnMap.Name,
                    newCollectionInfo.ColumnMap,
                    keyColumnMaps,
                    parentKeyColumnMaps,
                    discriminatorColumnMap,
                    newCollectionInfo.DiscriminatorValue
                    );
                varRefReplacementMap[ci.CollectionVar] = collectionColumnMap;
            }

            // Finally, build up the SingleStreamNest Node
            var newSsnOp = Command.CreateSingleStreamNestOp(
                parentKeys,
                nestOp.PrefixSortKeys,
                newPostfixSortKeys,
                nestOpOutputs,
                newCollectionInfoList,
                outputDiscriminatorVar);
            var newNestNode = Command.CreateNode(newSsnOp, unionAllNode);

#if DEBUG
            var size = input.Length; // GC.KeepAlive makes FxCop Grumpy.
            var output = Dump.ToXml(newNestNode);
#endif
            //DEBUG

            return newNestNode;
        }
        private readonly SimpleColumnMap[] m_keys; // list of keys

        // <summary>
        // Simple constructor - gets a list of key columns
        // </summary>
        internal EntityIdentity(SimpleColumnMap[] keyColumns)
        {
            DebugCheck.NotNull(keyColumns);
            m_keys = keyColumns;
        }
Example #21
0
        private readonly SimpleColumnMap[] m_keys; // list of keys

        /// <summary>
        ///     Simple constructor - gets a list of key columns
        /// </summary>
        /// <param name="keyColumns"> </param>
        internal EntityIdentity(SimpleColumnMap[] keyColumns)
        {
            Debug.Assert(keyColumns != null, "Must specify column maps for key columns");
            m_keys = keyColumns;
        }
        /// <summary>
        ///     Create a column map for a ref type
        /// </summary>
        /// <param name="typeInfo"> Type information for the ref type </param>
        /// <param name="name"> Name of the column </param>
        /// <returns> Column map for the ref type </returns>
        private RefColumnMap CreateRefColumnMap(TypeInfo typeInfo, string name)
        {
            SimpleColumnMap entitySetIdColumnMap = null;
            if (typeInfo.HasEntitySetIdProperty)
            {
                entitySetIdColumnMap = CreateSimpleColumnMap(
                    md.Helper.GetModelTypeUsage(typeInfo.EntitySetIdProperty), c_EntitySetIdColumnName);
            }

            // get the target entity type, 
            var entityType = (md.EntityType)(TypeHelpers.GetEdmType<md.RefType>(typeInfo.Type).ElementType);

            // Iterate through the list of "key" properties
            var keyColList = new SimpleColumnMap[entityType.KeyMembers.Count];
            for (var i = 0; i < keyColList.Length; ++i)
            {
                var property = entityType.KeyMembers[i];
                keyColList[i] = CreateSimpleColumnMap(md.Helper.GetModelTypeUsage(property), property.Name);
            }

            // Create the entity identity
            var identity = CreateEntityIdentity(entityType, entitySetIdColumnMap, keyColList);

            var result = new RefColumnMap(typeInfo.Type, name, identity);
            return result;
        }
 /// <summary>
 ///     Constructor for a record column map
 /// </summary>
 /// <param name="type"> Datatype of this column </param>
 /// <param name="name"> column name </param>
 /// <param name="properties"> List of ColumnMaps - one for each property </param>
 internal RecordColumnMap(TypeUsage type, string name, ColumnMap[] properties, SimpleColumnMap nullSentinel)
     : base(type, name, properties)
 {
     m_nullSentinel = nullSentinel;
 }
        /// <summary>
        ///     Build the entityColumnMap from a store datareader, a type and an entitySet and
        ///     a list ofproperties.
        /// </summary>
        /// <param name="storeDataReader"> </param>
        /// <param name="edmType"> </param>
        /// <param name="entitySet"> </param>
        /// <param name="propertyColumnMaps"> </param>
        /// <returns> </returns>
        private static EntityColumnMap CreateEntityTypeElementColumnMap(
            DbDataReader storeDataReader, EdmType edmType, EntitySet entitySet,
            ColumnMap[] propertyColumnMaps, Dictionary<string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping> renameList)
        {
            var entityType = (EntityType)edmType;

            // The tricky part here is
            // that the KeyColumns list must point at the same ColumnMap(s) that 
            // the properties list points to, so we build a quick array of 
            // ColumnMap(s) that are indexed by their ordinal; then we can walk
            // the list of keyMembers, and find the ordinal in the reader, and 
            // pick the same ColumnMap for it.

            // Build the ordinal -> ColumnMap index
            var ordinalToColumnMap = new ColumnMap[storeDataReader.FieldCount];

            foreach (var propertyColumnMap in propertyColumnMaps)
            {
                var ordinal = ((ScalarColumnMap)propertyColumnMap).ColumnPos;
                ordinalToColumnMap[ordinal] = propertyColumnMap;
            }

            // Now build the list of KeyColumns;
            IList<EdmMember> keyMembers = entityType.KeyMembers;
            var keyColumns = new SimpleColumnMap[keyMembers.Count];

            var keyMemberIndex = 0;
            foreach (var keyMember in keyMembers)
            {
                var keyOrdinal = GetMemberOrdinalFromReader(storeDataReader, keyMember, edmType, renameList);

                Debug.Assert(keyOrdinal >= 0, "keyMember for entity is not found by name in the data reader?");

                var keyColumnMap = ordinalToColumnMap[keyOrdinal];

                Debug.Assert(null != keyColumnMap, "keyMember for entity isn't in properties collection for the entity?");
                keyColumns[keyMemberIndex] = (SimpleColumnMap)keyColumnMap;
                keyMemberIndex++;
            }

            var entityIdentity = new SimpleEntityIdentity(entitySet, keyColumns);

            var result = new EntityColumnMap(TypeUsage.Create(edmType), edmType.Name, propertyColumnMaps, entityIdentity);
            return result;
        }
 private EntityIdentity CreateEntityIdentity(
     md.EntityType entityType,
     SimpleColumnMap entitySetIdColumnMap,
     SimpleColumnMap[] keyColumnMaps)
 {
     //
     // If we have an entitysetid (and therefore, a column map for the entitysetid), 
     // then use a discriminated entity identity; otherwise, we use a simpleentityidentity
     // instead
     //
     if (entitySetIdColumnMap != null)
     {
         return new DiscriminatedEntityIdentity(entitySetIdColumnMap, m_typeInfo.EntitySetIdToEntitySetMap, keyColumnMaps);
     }
     else
     {
         var entitySet = m_typeInfo.GetEntitySet(entityType);
         PlanCompiler.Assert(
             entitySet != null, "Expected non-null entitySet when no entity set ID is required. Entity type = " + entityType);
         return new SimpleEntityIdentity(entitySet, keyColumnMaps);
     }
 }