Пример #1
0
 public virtual IList<MemberInfo> GetPrimaryKeys(TableExpression tableExpression, DataContext dataContext)
 {
     var tableDescription = dataContext.Mapping.GetTable(tableExpression.Type);
     if (tableDescription != null)
         return GetPrimaryKeys(tableDescription);
     return null;
 }
 public override bool IsEqualTo(TableExpression expression)
 {
     SubSelectExpression subSelectTable = expression as SubSelectExpression;
     if (subSelectTable == null)
         return false;
     return Name == expression.Name && JoinID == expression.JoinID && Select == subSelectTable.Select;
 }
 /// <summary>
 /// Returns a registered column, or null if not found
 /// This method requires the table to be already registered
 /// </summary>
 /// <param name="table"></param>
 /// <param name="name"></param>
 /// <param name="builderContext"></param>
 /// <returns></returns>
 protected virtual ColumnExpression GetRegisteredColumn(TableExpression table, string name,
                                                        BuilderContext builderContext)
 {
     return
         (from queryColumn in builderContext.EnumerateScopeColumns()
          where queryColumn.Table.IsEqualTo(table) && queryColumn.Name == name
          select queryColumn).SingleOrDefault();
 }
 public ColumnExpression(TableExpression table, string name, MemberInfo memberInfo)
     : base(ExpressionType, memberInfo.GetMemberType())
 {
     Table = table;
     Name = name;
     MemberInfo = memberInfo;
     RequestIndex = -1; // unused
 }
 public ColumnExpression(TableExpression table, MetaDataMember metaData)
     : base(ExpressionType, metaData.Member.GetMemberType()) // memberInfo.GetMemberType())
 {
     Table = table;
     Name = metaData.MappedName;
     MemberInfo = metaData.Member;
     StorageInfo = metaData.StorageMember;
     RequestIndex = -1; // unused
 }
Пример #6
0
 internal EntitySetExpression(TableExpression sourceTable, MemberInfo memberInfo, Type entitySetType, BuilderContext builderContext, ExpressionDispatcher dispatcher)
     : base(ExpressionType, entitySetType)
 {
     this.builderContext = builderContext;
     this.EntitySetType = entitySetType;
     this.dispatcher = dispatcher;
     this.sourceTable = sourceTable;
     this.memberInfo = memberInfo;
     ParseExpression(sourceTable);
 }
 /// <summary>
 /// Returns an existing table or registers the current one
 /// </summary>
 /// <param name="tableExpression"></param>
 /// <param name="builderContext"></param>
 /// <returns>A registered table or the current newly registered one</returns>
 public virtual TableExpression RegisterTable(TableExpression tableExpression, BuilderContext builderContext)
 {
     // 1. Find the table in current scope
     var foundTableExpression = (from t in builderContext.EnumerateScopeTables()
                                 where t.IsEqualTo(tableExpression)
                                 select t).SingleOrDefault();
     if (foundTableExpression != null)
         return foundTableExpression;
     // 2. Find it in all scopes, and promote it to current scope.
     foundTableExpression = PromoteTable(tableExpression, builderContext);
     if (foundTableExpression != null)
         return foundTableExpression;
     // 3. Add it
     builderContext.CurrentSelect.Tables.Add(tableExpression);
     return tableExpression;
 }
 /// <summary>
 /// Registers the table as returned by the SQL request.
 /// Actually, the table is split into its columns.
 /// </summary>
 /// <param name="tableExpression"></param>
 /// <param name="dataRecordParameter"></param>
 /// <param name="mappingContextParameter"></param>
 /// <param name="builderContext"></param>
 /// <returns></returns>
 protected virtual Expression GetOutputTableReader(TableExpression tableExpression,
                                                   ParameterExpression dataRecordParameter, ParameterExpression mappingContextParameter,
                                                   BuilderContext builderContext)
 {
     var bindings = new List<MemberBinding>();
     
     foreach (ColumnExpression columnExpression in RegisterAllColumns(tableExpression, builderContext))
     {
         MemberInfo memberInfo = columnExpression.StorageInfo ?? columnExpression.MemberInfo;
         PropertyInfo propertyInfo = memberInfo as PropertyInfo;
         if (propertyInfo == null || propertyInfo.CanWrite)
         {
             var parameterColumn = GetOutputValueReader(columnExpression,
                                                        dataRecordParameter, mappingContextParameter, builderContext);
             var binding = Expression.Bind(memberInfo, parameterColumn);
             bindings.Add(binding);
         }
     }
     var newExpression = Expression.New(tableExpression.Type);
     var initExpression = Expression.MemberInit(newExpression, bindings);
     return initExpression;
 }
        /// <summary>
        /// Promotes a table to a common parent between its current scope and our current scope
        /// </summary>
        /// <param name="tableExpression"></param>
        /// <param name="builderContext"></param>
        /// <returns></returns>
        protected virtual TableExpression PromoteTable(TableExpression tableExpression, BuilderContext builderContext)
        {
            int currentIndex = 0;
            SelectExpression oldSelect = null;
            SelectExpression commonScope = null;
            TableExpression foundTable = null;
            do
            {
                // take a select
                oldSelect = builderContext.SelectExpressions[currentIndex];

                // look for a common scope
                if (oldSelect != builderContext.CurrentSelect)
                {
                    commonScope = FindCommonScope(oldSelect, builderContext.CurrentSelect);
                    if (commonScope != null)
                        // if a common scope exists, look for an equivalent table in that select
                        for (int tableIndex = 0; tableIndex < oldSelect.Tables.Count && foundTable == null; tableIndex++)
                        {
                            if (oldSelect.Tables[tableIndex].IsEqualTo(tableExpression))
                            {
                                // found a matching table!
                                foundTable = oldSelect.Tables[tableIndex];
                            }
                        }
                }
                ++currentIndex;
            }
            while (currentIndex < builderContext.SelectExpressions.Count && foundTable == null);

            if (foundTable != null)
            {
                oldSelect.Tables.Remove(foundTable);
                commonScope.Tables.Add(foundTable);
            }
            return foundTable;
        }
Пример #10
0
 public virtual bool IsEqualTo(TableExpression expression)
 {
     return Name == expression.Name && JoinID == expression.JoinID;
 }
Пример #11
0
 public virtual string GetColumnName(TableExpression tableExpression, MemberInfo memberInfo, DataContext dataContext)
 {
     return GetColumnName(tableExpression.Type, memberInfo, dataContext);
 }
 public ColumnExpression CreateColumn(TableExpression table, MemberInfo memberInfo, BuilderContext builderContext)
 {
     var dataMember = builderContext.QueryContext.DataContext.Mapping.GetTable(table.Type).RowType
         .GetDataMember(memberInfo);
     if (dataMember == null)
         return null;
     return new ColumnExpression(table, dataMember.MappedName, memberInfo);
 }
 /// <summary>
 /// Registers all columns of a table.
 /// </summary>
 /// <param name="tableExpression"></param>
 /// <param name="builderContext"></param>
 /// <returns></returns>
 public virtual IEnumerable<ColumnExpression> RegisterAllColumns(TableExpression tableExpression, BuilderContext builderContext)
 {
     foreach (var metaMember in builderContext.QueryContext.DataContext.Mapping.GetTable(tableExpression.Type).RowType.PersistentDataMembers)
     {
         yield return RegisterColumn(tableExpression, metaMember.Member, builderContext);
     }
 }
Пример #14
0
 /// <summary>
 /// Set table join
 /// </summary>
 /// <param name="joinType"></param>
 /// <param name="joinedTable"></param>
 /// <param name="joinExpression"></param>
 public void Join(TableJoinType joinType, TableExpression joinedTable, Expression joinExpression)
 {
     JoinExpression = joinExpression;
     JoinType = joinType;
     JoinedTable = joinedTable;
 }
 protected virtual SelectExpression FindTableScope(ref TableExpression tableExpression, BuilderContext builderContext)
 {
     foreach (var scope in builderContext.SelectExpressions)
     {
         for (int tableIndex = 0; tableIndex < scope.Tables.Count; tableIndex++)
         {
             if (scope.Tables[tableIndex].IsEqualTo(tableExpression))
             {
                 tableExpression = scope.Tables[tableIndex];
                 scope.Tables.RemoveAt(tableIndex);
                 return scope;
             }
         }
     }
     return null;
 }
 /// <summary>
 /// Replaces a table selection by a selection of all mapped columns (ColumnExpressions).
 /// ColumnExpressions will be replaced at a later time by the tier splitter
 /// </summary>
 /// <param name="tableExpression"></param>
 /// <param name="builderContext"></param>
 /// <returns></returns>
 protected virtual Expression GetSelectTableExpression(TableExpression tableExpression, BuilderContext builderContext)
 {
     var bindings = new List<MemberBinding>();
     foreach (var columnExpression in RegisterAllColumns(tableExpression, builderContext))
     {
         var binding = Expression.Bind((MethodInfo) columnExpression.MemberInfo, columnExpression);
         bindings.Add(binding);
     }
     var newExpression = Expression.New(tableExpression.Type);
     return Expression.MemberInit(newExpression, bindings);
 }
Пример #17
0
 public override Expression Mutate(IList<Expression> newOperands)
 {
     if (newOperands.Count != 1)
         throw Error.BadArgument("S0063: Bad argument count");
     TableExpression = (TableExpression)newOperands[0];
     // ParseExpression(TableExpression);
     return this;
 }
Пример #18
0
 protected virtual bool MustDeclareAsJoin(TableExpression table)
 {
     return false;
 }
Пример #19
0
 /// <summary>
 /// Set table join
 /// </summary>
 /// <param name="joinType"></param>
 /// <param name="joinedTable"></param>
 /// <param name="joinExpression"></param>
 /// <param name="joinID"></param>
 public void Join(TableJoinType joinType, TableExpression joinedTable, Expression joinExpression, string joinID)
 {
     Join(joinType, joinedTable, joinExpression);
     JoinID = joinID;
 }
Пример #20
0
        /// <summary>
        /// Returns association definition, if any
        /// </summary>
        /// <param name="thisTableExpression">The table referenced by the assocation (the type holding the member)</param>
        /// <param name="memberInfo">The memberInfo related to association</param>
        /// <param name="thisKey">The keys in the joined table</param>
        /// <param name="otherKey">The keys in the associated table</param>
        /// <param name="joinType"></param>
        /// <param name="joinID"></param>
        /// <param name="dataContext"></param>
        /// <returns></returns>
        public virtual Type GetAssociation(TableExpression thisTableExpression, MemberInfo memberInfo,
                                           out IList<MemberInfo> thisKey, out IList<MemberInfo> otherKey,
                                           out TableJoinType joinType, out string joinID, DataContext dataContext)
        {
            var thisTableDescription = dataContext.Mapping.GetTable(thisTableExpression.Type);
            var thisAssociation =
                (from association in thisTableDescription.RowType.Associations
                 where association.ThisMember.Member == memberInfo
                 select association).SingleOrDefault();
            if (thisAssociation != null)
            {
                joinType = TableJoinType.Inner;
                joinID = thisAssociation.ThisMember.MappedName;
                if (string.IsNullOrEmpty(joinID))
                    throw Error.BadArgument("S0108: Association name is required to ensure join uniqueness");

                var otherType = thisAssociation.ThisMember.Type;
                if (otherType.IsGenericType) // TODO: something serious here
                    otherType = otherType.GetGenericArguments()[0];

                var otherTableDescription = dataContext.Mapping.GetTable(otherType);
                thisKey = GetAssociationKeys(thisTableDescription, thisAssociation.ThisKey, dataContext);
                otherKey = GetAssociationKeys(otherTableDescription, thisAssociation.OtherKey, dataContext);

                return otherType;
            }
            thisKey = null;
            otherKey = null;
            joinType = TableJoinType.Default;
            joinID = null;
            return null;
        }
Пример #21
0
 protected virtual bool MustDeclareAsJoin(IList<TableExpression> tables, TableExpression table)
 {
     // the first table can not be declared as join
     if (table == tables[0])
         return false;
     // we must declare as join, whatever the join is,
     // if some of the registered tables are registered as complex join
     if (tables.Any(t => t.JoinType != TableJoinType.Inner))
         return table.JoinExpression != null;
     return false;
 }
Пример #22
0
        private void ParseExpression(TableExpression sourceTable)
        {
            // var sourceTable = targetTable.JoinedTable;
            var entityType = EntitySetType.GetGenericArguments()[0];

            // BUG: This is ignoring External Mappings from XmlMappingSource.
            var mappingType = builderContext.QueryContext.DataContext.Mapping.GetMetaType(entityType);
            var foreignKeys = mappingType.Associations.Where(a => a.IsForeignKey && a.OtherType.Type == sourceTable.Type);

            foreach (var fk in foreignKeys)
            {
                var oke = fk.OtherKey.GetEnumerator();
                var tke = fk.ThisKey.GetEnumerator();
                bool ho, ht;
                while ((ho = oke.MoveNext()) && (ht = tke.MoveNext()))
                {
                    var ok = oke.Current;
                    var tk = tke.Current;
                    var column = dispatcher.RegisterColumn(sourceTable, ok.Member, builderContext);
                    Columns.Add(new KeyValuePair<ColumnExpression, MetaDataMember>(column, tk));
                }
            }
        }
 /// <summary>
 /// Promotes a table to a common parent between its current scope and our current scope
 /// </summary>
 /// <param name="tableExpression"></param>
 /// <param name="builderContext"></param>
 /// <returns></returns>
 protected virtual TableExpression PromoteTable(TableExpression tableExpression, BuilderContext builderContext)
 {
     // 1. Find the table ScopeExpression
     SelectExpression oldSelect = FindTableScope(ref tableExpression, builderContext);
     if (oldSelect == null)
         return null;
     // 2. Find a common ScopeExpression
     var commonScope = FindCommonScope(oldSelect, builderContext.CurrentSelect);
     commonScope.Tables.Add(tableExpression);
     return tableExpression;
 }
Пример #24
0
 protected TableExpression(ExpressionType expressionType, TableExpression tableExpression)
     : base(expressionType, tableExpression.Type)
 {
     Name = tableExpression.Name;
 }
 /// <summary>
 /// Registers a column
 /// This method requires the table to be already registered
 /// </summary>
 /// <param name="table"></param>
 /// <param name="memberInfo"></param>
 /// <param name="name"></param>
 /// <param name="builderContext"></param>
 /// <returns></returns>
 public ColumnExpression RegisterColumn(TableExpression table,
                                        MemberInfo memberInfo, string name,
                                        BuilderContext builderContext)
 {
     if (memberInfo == null)
         return null;
     var queryColumn = GetRegisteredColumn(table, name, builderContext);
     if (queryColumn == null)
     {
         table = RegisterTable(table, builderContext);
         queryColumn = CreateColumn(table, memberInfo, builderContext);
         builderContext.CurrentSelect.Columns.Add(queryColumn);
     }
     return queryColumn;
 }
 public virtual bool IsEqualTo(TableExpression expression)
 {
     return Name == expression.Name && JoinID == expression.JoinID;
 }
        /// <summary>
        /// Registers an association
        /// </summary>
        /// <param name="tableExpression">The table holding the member, to become the joinedTable</param>
        /// <param name="tableMemberInfo"></param>
        /// <param name="builderContext"></param>
        /// <returns></returns>
        public virtual TableExpression RegisterAssociation(TableExpression tableExpression, MemberInfo tableMemberInfo,
                                                           BuilderContext builderContext)
        {
            IList<MemberInfo> theseKeys, otherKeys;
            TableJoinType joinType;
            string joinID;
            var otherTableType = DataMapper.GetAssociation(tableExpression, tableMemberInfo, out theseKeys, out otherKeys, 
                                                      out joinType, out joinID, builderContext.QueryContext.DataContext);
            // if the memberInfo has no corresponding association, we get a null, that we propagate
            if (otherTableType == null)
                return null;

            // the current table has the foreign key, the other table the referenced (usually primary) key
            if (theseKeys.Count != otherKeys.Count)
                throw Error.BadArgument("S0128: Association arguments (FK and ref'd PK) don't match");

            // we first create the table, with the JoinID, and we MUST complete the table later, with the Join() method
            var otherTableExpression = new TableExpression(otherTableType, DataMapper.GetTableName(otherTableType, builderContext.QueryContext.DataContext), joinID);

            Expression joinExpression = null;

            var createdColumns = new List<ColumnExpression>();
            for (int keyIndex = 0; keyIndex < theseKeys.Count; keyIndex++)
            {
                // joinedKey is registered, even if unused by final select (required columns will be filtered anyway)
                Expression otherKey = RegisterColumn(otherTableExpression, otherKeys[keyIndex], builderContext);
                // foreign is created, we will store it later if this assocation is registered too
                Expression thisKey = CreateColumn(tableExpression, theseKeys[keyIndex], builderContext);
                createdColumns.Add((ColumnExpression)thisKey);

                // if the key is nullable, then convert it
                // TODO: this will probably need to be changed
                if (otherKey.Type.IsNullable())
                    otherKey = Expression.Convert(otherKey, otherKey.Type.GetNullableType());
                if (thisKey.Type.IsNullable())
                    thisKey = Expression.Convert(thisKey, thisKey.Type.GetNullableType());
                var referenceExpression = Expression.Equal(thisKey, otherKey);

                // if we already have a join expression, then we have a double condition here, so "AND" it
                if (joinExpression != null)
                    joinExpression = Expression.And(joinExpression, referenceExpression);
                else
                    joinExpression = referenceExpression;
            }
            // we complete the table here, now that we have all join information
            otherTableExpression.Join(joinType, tableExpression, joinExpression);

            // our table is created, with the expressions
            // now check if we didn't register exactly the same
            if ((from t in builderContext.EnumerateScopeTables() where t.IsEqualTo(otherTableExpression) select t).SingleOrDefault() == null)
            {
                builderContext.CurrentSelect.Tables.Add(otherTableExpression);
                foreach (var createdColumn in createdColumns)
                    builderContext.CurrentSelect.Columns.Add(createdColumn);
            }

            return otherTableExpression;
        }
 /// <summary>
 /// Set table join
 /// </summary>
 /// <param name="joinType"></param>
 /// <param name="joinedTable"></param>
 /// <param name="joinExpression"></param>
 public void Join(TableJoinType joinType, TableExpression joinedTable, Expression joinExpression)
 {
     JoinExpression = joinExpression;
     JoinType = joinType;
     JoinedTable = joinedTable;
 }
 /// <summary>
 /// Registers the table as returned by the SQL request.
 /// Actually, the table is split into its columns.
 /// </summary>
 /// <param name="tableExpression"></param>
 /// <param name="dataRecordParameter"></param>
 /// <param name="mappingContextParameter"></param>
 /// <param name="builderContext"></param>
 /// <returns></returns>
 protected virtual Expression GetOutputTableReader(TableExpression tableExpression,
                                                   ParameterExpression dataRecordParameter, ParameterExpression mappingContextParameter,
                                                   BuilderContext builderContext)
 {
     var bindings = new List<MemberBinding>();
     foreach (var columnExpression in RegisterAllColumns(tableExpression, builderContext))
     {
         var parameterColumn = GetOutputValueReader(columnExpression,
                                                    dataRecordParameter, mappingContextParameter, builderContext);
         var binding = Expression.Bind(columnExpression.MemberInfo, parameterColumn);
         bindings.Add(binding);
     }
     var newExpression = Expression.New(tableExpression.Type);
     var initExpression = Expression.MemberInit(newExpression, bindings);
     return initExpression;
 }
 /// <summary>
 /// Set table join
 /// </summary>
 /// <param name="joinType"></param>
 /// <param name="joinedTable"></param>
 /// <param name="joinExpression"></param>
 /// <param name="joinID"></param>
 public void Join(TableJoinType joinType, TableExpression joinedTable, Expression joinExpression, string joinID)
 {
     Join(joinType, joinedTable, joinExpression);
     JoinID = joinID;
 }
 protected TableExpression(ExpressionType expressionType, TableExpression tableExpression)
     : base(expressionType, tableExpression.Type)
 {
     Name = tableExpression.Name;
 }
Пример #32
0
        /// <summary>
        /// Returns association definition, if any
        /// </summary>
        /// <param name="thisTableExpression">The table referenced by the assocation (the type holding the member)</param>
        /// <param name="memberInfo">The memberInfo related to association</param>
        /// <param name="otherType"></param>
        /// <param name="otherKey">The keys in the associated table</param>
        /// <param name="joinType"></param>
        /// <param name="joinID"></param>
        /// <param name="dataContext"></param>
        /// <returns>ThisKey</returns>
        public virtual IList<MemberInfo> GetAssociation(TableExpression thisTableExpression, MemberInfo memberInfo, Type otherType, out IList<MemberInfo> otherKey, out TableJoinType joinType, out string joinID, DataContext dataContext)
        {
            var thisTableDescription = dataContext.Mapping.GetTable(thisTableExpression.Type);
            var thisAssociation =
                (from association in thisTableDescription.RowType.Associations
                 where association.ThisMember.Member == memberInfo
                 select association).SingleOrDefault();
            if (thisAssociation != null)
            {
                // by default, join is inner
                joinType = TableJoinType.Inner;
                joinID = thisAssociation.ThisMember.MappedName;
                if (string.IsNullOrEmpty(joinID))
                    throw Error.BadArgument("S0108: Association name is required to ensure join uniqueness");

                var otherTableDescription = dataContext.Mapping.GetTable(otherType);
                bool thisKeyHasNullables, otherKeyHasNullables;
                var thisKey = GetAssociationKeys(thisTableDescription, thisAssociation.ThisKey, dataContext,
                                                 out thisKeyHasNullables);
                otherKey = GetAssociationKeys(otherTableDescription, thisAssociation.OtherKey, dataContext,
                                              out otherKeyHasNullables);

                // we just test here the left join (since associations are symmetric,
                //        we can only find left joins here, and the otherKeyHasNullables is
                //        always equal to thisKeyHasNullables)
                if (thisKeyHasNullables)
                    joinType |= TableJoinType.LeftOuter;

                return thisKey;
            }
            otherKey = null;
            joinType = TableJoinType.Default;
            joinID = null;
            return null;
        }