internal override SqlNode VisitLink(SqlLink link)
		{
			SqlExpression expansion = this.VisitExpression(link.Expansion);
			SqlExpression[] exprs = new SqlExpression[link.KeyExpressions.Count];
			for(int i = 0, n = exprs.Length; i < n; i++)
			{
				exprs[i] = this.VisitExpression(link.KeyExpressions[i]);
			}
			return new SqlLink(link.Id, link.RowType, link.ClrType, link.SqlType, link.Expression, link.Member, exprs, expansion, link.SourceExpression);
		}
		internal override SqlNode VisitLink(SqlLink link)
		{
			// Don't visit the Expression/Expansion for this link.
			// Any additional external refs in these expressions
			// should be ignored
			SqlExpression[] exprs = new SqlExpression[link.KeyExpressions.Count];
			for(int i = 0, n = exprs.Length; i < n; i++)
			{
				exprs[i] = this.VisitExpression(link.KeyExpressions[i]);
			}
			return new SqlLink(new object(), link.RowType, link.ClrType, link.SqlType, null, link.Member, exprs, null, link.SourceExpression);
		}
Example #3
0
        internal SqlSelect BuildDefaultQuery(MetaType rowType, bool allowDeferred, SqlLink link, Expression source) {
            System.Diagnostics.Debug.Assert(rowType != null && rowType.Table != null);
            if (rowType.HasInheritance && rowType.InheritanceRoot != rowType) {
                // RowType is expected to be an inheritance root.
                throw Error.ArgumentWrongValue("rowType");
            }
            SqlTable table = sql.Table(rowType.Table, rowType, source);
            SqlAlias tableAlias = new SqlAlias(table);
            SqlAliasRef tableAliasRef = new SqlAliasRef(tableAlias);

            SqlExpression projection = this.BuildProjection(tableAliasRef, table.RowType, allowDeferred, link, source);
            return new SqlSelect(projection, tableAlias, source);
        }
Example #4
0
        internal SqlExpression BuildProjection(SqlExpression item, MetaType rowType, bool allowDeferred, SqlLink link, Expression source) {
            if (!rowType.HasInheritance) {
                return this.BuildProjectionInternal(item, rowType, (rowType.Table != null) ? rowType.PersistentDataMembers : rowType.DataMembers, allowDeferred, link, source);
            }
            else {
                // Build a type case that represents a switch between the various type.
                List<MetaType> mappedTypes = new List<MetaType>(rowType.InheritanceTypes);
                List<SqlTypeCaseWhen> whens = new List<SqlTypeCaseWhen>();
                SqlTypeCaseWhen @else = null;

                MetaType root = rowType.InheritanceRoot;
                MetaDataMember discriminator = root.Discriminator;
                Type dt = discriminator.Type;
                SqlMember dm = sql.Member(item, discriminator.Member);

                foreach (MetaType type in mappedTypes) {
                    if (type.HasInheritanceCode) {
                        SqlNew defaultProjection = this.BuildProjectionInternal(item, type, type.PersistentDataMembers, allowDeferred, link, source);
                        if (type.IsInheritanceDefault) {
                            @else = new SqlTypeCaseWhen(null, defaultProjection);
                        }
                        // Add an explicit case even for the default.
                        // Redundant results will be optimized out later.
                        object code = InheritanceRules.InheritanceCodeForClientCompare(type.InheritanceCode, dm.SqlType);
                        SqlExpression match = sql.Value(dt, sql.Default(discriminator), code, true, source);
                        whens.Add(new SqlTypeCaseWhen(match, defaultProjection));
                    }
                }
                if (@else == null) {
                    throw Error.EmptyCaseNotSupported();
                }
                whens.Add(@else);   // Add the else at the end.
                
                return sql.TypeCase(root.Type, root, dm, whens.ToArray(), source);
            }
        }
		private SqlExpression ExpandTogether(List<SqlExpression> exprs)
		{
			switch(exprs[0].NodeType)
			{
				case SqlNodeType.MethodCall:
				{
					SqlMethodCall[] mcs = new SqlMethodCall[exprs.Count];
					for(int i = 0; i < mcs.Length; ++i)
					{
						mcs[i] = (SqlMethodCall)exprs[i];
					}

					List<SqlExpression> expandedArgs = new List<SqlExpression>();

					for(int i = 0; i < mcs[0].Arguments.Count; ++i)
					{
						List<SqlExpression> args = new List<SqlExpression>();
						for(int j = 0; j < mcs.Length; ++j)
						{
							args.Add(mcs[j].Arguments[i]);
						}
						SqlExpression expanded = this.ExpandTogether(args);
						expandedArgs.Add(expanded);
					}
					return factory.MethodCall(mcs[0].Method, mcs[0].Object, expandedArgs.ToArray(), mcs[0].SourceExpression);
				}
				case SqlNodeType.ClientCase:
				{
					// Are they all the same?
					SqlClientCase[] scs = new SqlClientCase[exprs.Count];
					scs[0] = (SqlClientCase)exprs[0];
					for(int i = 1; i < scs.Length; ++i)
					{
						scs[i] = (SqlClientCase)exprs[i];
					}

					// Expand expressions together.
					List<SqlExpression> expressions = new List<SqlExpression>();
					for(int i = 0; i < scs.Length; ++i)
					{
						expressions.Add(scs[i].Expression);
					}
					SqlExpression expression = this.ExpandTogether(expressions);

					// Expand individual expressions together.
					List<SqlClientWhen> whens = new List<SqlClientWhen>();
					for(int i = 0; i < scs[0].Whens.Count; ++i)
					{
						List<SqlExpression> scos = new List<SqlExpression>();
						for(int j = 0; j < scs.Length; ++j)
						{
							SqlClientWhen when = scs[j].Whens[i];
							scos.Add(when.Value);
						}
						whens.Add(new SqlClientWhen(scs[0].Whens[i].Match, this.ExpandTogether(scos)));
					}

					return new SqlClientCase(scs[0].ClrType, expression, whens, scs[0].SourceExpression);
				}
				case SqlNodeType.TypeCase:
				{
					// Are they all the same?
					SqlTypeCase[] tcs = new SqlTypeCase[exprs.Count];
					tcs[0] = (SqlTypeCase)exprs[0];
					for(int i = 1; i < tcs.Length; ++i)
					{
						tcs[i] = (SqlTypeCase)exprs[i];
					}

					// Expand discriminators together.
					List<SqlExpression> discriminators = new List<SqlExpression>();
					for(int i = 0; i < tcs.Length; ++i)
					{
						discriminators.Add(tcs[i].Discriminator);
					}
					SqlExpression discriminator = this.ExpandTogether(discriminators);
					// Write expanded discriminators back in.
					for(int i = 0; i < tcs.Length; ++i)
					{
						tcs[i].Discriminator = discriminators[i];
					}
					// Expand individual type bindings together.
					List<SqlTypeCaseWhen> whens = new List<SqlTypeCaseWhen>();
					for(int i = 0; i < tcs[0].Whens.Count; ++i)
					{
						List<SqlExpression> scos = new List<SqlExpression>();
						for(int j = 0; j < tcs.Length; ++j)
						{
							SqlTypeCaseWhen when = tcs[j].Whens[i];
							scos.Add(when.TypeBinding);
						}
						SqlExpression expanded = this.ExpandTogether(scos);
						whens.Add(new SqlTypeCaseWhen(tcs[0].Whens[i].Match, expanded));
					}

					return factory.TypeCase(tcs[0].ClrType, tcs[0].RowType, discriminator, whens, tcs[0].SourceExpression);
				}
				case SqlNodeType.New:
				{
					// first verify all are similar client objects...
					SqlNew[] cobs = new SqlNew[exprs.Count];
					cobs[0] = (SqlNew)exprs[0];
					for(int i = 1, n = exprs.Count; i < n; i++)
					{
						if(exprs[i] == null || exprs[i].NodeType != SqlNodeType.New)
							throw Error.UnionIncompatibleConstruction();
						cobs[i] = (SqlNew)exprs[1];
						if(cobs[i].Members.Count != cobs[0].Members.Count)
							throw Error.UnionDifferentMembers();
						for(int m = 0, mn = cobs[0].Members.Count; m < mn; m++)
						{
							if(cobs[i].Members[m].Member != cobs[0].Members[m].Member)
							{
								throw Error.UnionDifferentMemberOrder();
							}
						}
					}
					SqlMemberAssign[] bindings = new SqlMemberAssign[cobs[0].Members.Count];
					for(int m = 0, mn = bindings.Length; m < mn; m++)
					{
						List<SqlExpression> mexprs = new List<SqlExpression>();
						for(int i = 0, n = exprs.Count; i < n; i++)
						{
							mexprs.Add(cobs[i].Members[m].Expression);
						}
						bindings[m] = new SqlMemberAssign(cobs[0].Members[m].Member, this.ExpandTogether(mexprs));
						for(int i = 0, n = exprs.Count; i < n; i++)
						{
							cobs[i].Members[m].Expression = mexprs[i];
						}
					}
					SqlExpression[] arguments = new SqlExpression[cobs[0].Args.Count];
					for(int m = 0, mn = arguments.Length; m < mn; ++m)
					{
						List<SqlExpression> mexprs = new List<SqlExpression>();
						for(int i = 0, n = exprs.Count; i < n; i++)
						{
							mexprs.Add(cobs[i].Args[m]);
						}
						arguments[m] = ExpandTogether(mexprs);
					}
					return factory.New(cobs[0].MetaType, cobs[0].Constructor, arguments, cobs[0].ArgMembers, bindings, exprs[0].SourceExpression);
				}
				case SqlNodeType.Link:
				{
					SqlLink[] links = new SqlLink[exprs.Count];
					links[0] = (SqlLink)exprs[0];
					for(int i = 1, n = exprs.Count; i < n; i++)
					{
						if(exprs[i] == null || exprs[i].NodeType != SqlNodeType.Link)
							throw Error.UnionIncompatibleConstruction();
						links[i] = (SqlLink)exprs[i];
						if(links[i].KeyExpressions.Count != links[0].KeyExpressions.Count ||
						   links[i].Member != links[0].Member ||
						   (links[i].Expansion != null) != (links[0].Expansion != null))
							throw Error.UnionIncompatibleConstruction();
					}
					SqlExpression[] kexprs = new SqlExpression[links[0].KeyExpressions.Count];
					List<SqlExpression> lexprs = new List<SqlExpression>();
					for(int k = 0, nk = links[0].KeyExpressions.Count; k < nk; k++)
					{
						lexprs.Clear();
						for(int i = 0, n = exprs.Count; i < n; i++)
						{
							lexprs.Add(links[i].KeyExpressions[k]);
						}
						kexprs[k] = this.ExpandTogether(lexprs);
						for(int i = 0, n = exprs.Count; i < n; i++)
						{
							links[i].KeyExpressions[k] = lexprs[i];
						}
					}
					SqlExpression expansion = null;
					if(links[0].Expansion != null)
					{
						lexprs.Clear();
						for(int i = 0, n = exprs.Count; i < n; i++)
						{
							lexprs.Add(links[i].Expansion);
						}
						expansion = this.ExpandTogether(lexprs);
						for(int i = 0, n = exprs.Count; i < n; i++)
						{
							links[i].Expansion = lexprs[i];
						}
					}
					return new SqlLink(links[0].Id, links[0].RowType, links[0].ClrType, links[0].SqlType, links[0].Expression, links[0].Member, kexprs, expansion, links[0].SourceExpression);
				}
				case SqlNodeType.Value:
				{
					/*
							* ExprSet of all literals of the same value reduce to just a single literal.
							*/
					SqlValue val0 = (SqlValue)exprs[0];
					for(int i = 1; i < exprs.Count; ++i)
					{
						SqlValue val = (SqlValue)exprs[i];
						if(!Equals(val.Value, val0.Value))
							return this.ExpandIntoExprSet(exprs);
					}
					return val0;
				}
				case SqlNodeType.OptionalValue:
				{
					if(exprs[0].SqlType.CanBeColumn)
					{
						goto default;
					}
					List<SqlExpression> hvals = new List<SqlExpression>(exprs.Count);
					List<SqlExpression> vals = new List<SqlExpression>(exprs.Count);
					for(int i = 0, n = exprs.Count; i < n; i++)
					{
						if(exprs[i] == null || exprs[i].NodeType != SqlNodeType.OptionalValue)
						{
							throw Error.UnionIncompatibleConstruction();
						}
						SqlOptionalValue sov = (SqlOptionalValue)exprs[i];
						hvals.Add(sov.HasValue);
						vals.Add(sov.Value);
					}
					return new SqlOptionalValue(this.ExpandTogether(hvals), this.ExpandTogether(vals));
				}
				case SqlNodeType.OuterJoinedValue:
				{
					if(exprs[0].SqlType.CanBeColumn)
					{
						goto default;
					}
					List<SqlExpression> values = new List<SqlExpression>(exprs.Count);
					for(int i = 0, n = exprs.Count; i < n; i++)
					{
						if(exprs[i] == null || exprs[i].NodeType != SqlNodeType.OuterJoinedValue)
						{
							throw Error.UnionIncompatibleConstruction();
						}
						SqlUnary su = (SqlUnary)exprs[i];
						values.Add(su.Operand);
					}
					return factory.Unary(SqlNodeType.OuterJoinedValue, this.ExpandTogether(values));
				}
				case SqlNodeType.DiscriminatedType:
				{
					SqlDiscriminatedType sdt0 = (SqlDiscriminatedType)exprs[0];
					List<SqlExpression> foos = new List<SqlExpression>(exprs.Count);
					foos.Add(sdt0.Discriminator);
					for(int i = 1, n = exprs.Count; i < n; i++)
					{
						SqlDiscriminatedType sdtN = (SqlDiscriminatedType)exprs[i];
						if(sdtN.TargetType != sdt0.TargetType)
						{
							throw Error.UnionIncompatibleConstruction();
						}
						foos.Add(sdtN.Discriminator);
					}
					return factory.DiscriminatedType(this.ExpandTogether(foos), ((SqlDiscriminatedType)exprs[0]).TargetType);
				}
				case SqlNodeType.ClientQuery:
				case SqlNodeType.Multiset:
				case SqlNodeType.Element:
				case SqlNodeType.Grouping:
					throw Error.UnionWithHierarchy();
				default:
					return this.ExpandIntoExprSet(exprs);
			}
		}
		private Type GenerateLink(SqlLink link, LocalBuilder locInstance)
		{
			gen.Emit(OpCodes.Ldarg_0);

			// iGlobalLink arg
			int iGlobalLink = this.AddGlobal(typeof(MetaDataMember), link.Member);
			this.GenerateConstInt(iGlobalLink);

			// iLocalFactory arg
			int iLocalFactory = this.AllocateLocal();
			this.GenerateConstInt(iLocalFactory);

			Type elemType = link.Member.IsAssociation && link.Member.Association.IsMany
				? TypeSystem.GetElementType(link.Member.Type)
				: link.Member.Type;

			MethodInfo mi = null;
			if(locInstance != null)
			{
				// load instance for 'instance' arg
				gen.Emit(OpCodes.Ldloc, locInstance);

				// call GetNestedLinkSource on ObjectReaderBase
				mi = typeof(ObjectMaterializer<>).MakeGenericType(this.compiler.DataReaderType).GetMethod("GetNestedLinkSource", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				Diagnostics.Debug.Assert(mi != null);
				MethodInfo miGLS = mi.MakeGenericMethod(elemType);
				gen.Emit(GetMethodCallOpCode(miGLS), miGLS);
			}
			else
			{
				// create array of key values for 'keyValues' arg
				this.GenerateConstInt(link.KeyExpressions.Count);
				gen.Emit(OpCodes.Newarr, typeof(object));

				// intialize key values
				for(int i = 0, n = link.KeyExpressions.Count; i < n; i++)
				{
					gen.Emit(OpCodes.Dup);
					this.GenerateConstInt(i);
					this.GenerateExpressionForType(link.KeyExpressions[i], typeof(object));
					this.GenerateArrayAssign(typeof(object));
				}

				// call GetLinkSource on ObjectReaderBase
				mi = typeof(ObjectMaterializer<>).MakeGenericType(this.compiler.DataReaderType).GetMethod("GetLinkSource", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				Diagnostics.Debug.Assert(mi != null);
				MethodInfo miGLS = mi.MakeGenericMethod(elemType);
				gen.Emit(GetMethodCallOpCode(miGLS), miGLS);
			}

			return typeof(IEnumerable<>).MakeGenericType(elemType);
		}
		internal LinkedTableExpression(SqlLink link, ITable table, Type type) 
			: base(InternalExpressionType.LinkedTable, type) {
			this.link = link;
			this.table = table;
			}
		internal override SqlNode VisitLink(SqlLink link)
		{
			// don't visit expansion...
			for(int i = 0, n = link.KeyExpressions.Count; i < n; i++)
			{
				link.KeyExpressions[i] = this.VisitExpression(link.KeyExpressions[i]);
			}
			return link;
		}
		internal override SqlNode VisitLink(SqlLink link)
		{
			if(!_isDebugMode)
			{
				throw Error.InvalidFormatNode("Link");
			}
			if(link.Expansion != null)
			{
				_commandStringBuilder.Append("LINK(");
				this.Visit(link.Expansion);
				_commandStringBuilder.Append(")");
			}
			else
			{
				_commandStringBuilder.Append("LINK(");
				for(int i = 0, n = link.KeyExpressions.Count; i < n; i++)
				{
					if(i > 0) _commandStringBuilder.Append(", ");
					this.Visit(link.KeyExpressions[i]);
				}
				_commandStringBuilder.Append(")");
			}
			return link;
		}
Example #10
0
	    internal SqlNode TranslateLink(SqlLink link, List<SqlExpression> keyExpressions, bool asExpression) {
            MetaDataMember mm = link.Member;

            if (mm.IsAssociation) {
                // Create the row source.
                MetaType otherType = mm.Association.OtherType;
                Type tableType = otherType.InheritanceRoot.Type;
                ITable table = this.services.Context.GetTable(tableType);
                Expression source = new LinkedTableExpression(link, table, typeof(IQueryable<>).MakeGenericType(otherType.Type));
                // Build key expression nodes.
                Expression[] keyExprs = new Expression[keyExpressions.Count];
                for (int i = 0; i < keyExpressions.Count; ++i) {
                    MetaDataMember metaMember = mm.Association.OtherKey[i];
                    Type memberType = TypeSystem.GetMemberType(metaMember.Member);
                    keyExprs[i] = InternalExpression.Known(keyExpressions[i], memberType);
                }
                Expression lex = link.Expression != null 
                    ? (Expression)InternalExpression.Known(link.Expression) 
                    : (Expression)Expression.Constant(null, link.Member.Member.DeclaringType);
                Expression expr = TranslateAssociation(this.services.Context, mm.Association, source, keyExprs, lex);
                // Convert
                QueryConverter qc = new QueryConverter(this.services, this.typeProvider, this, this.sql);
                SqlSelect sel = (SqlSelect)qc.ConvertInner(expr, link.SourceExpression);
                // Turn it into an expression is necessary
                SqlNode result = sel;
                if (asExpression) {
                    if (mm.Association.IsMany) {
                        result = new SqlSubSelect(SqlNodeType.Multiset, link.ClrType, link.SqlType, sel);
                    }
                    else {
                        result = new SqlSubSelect(SqlNodeType.Element, link.ClrType, link.SqlType, sel);
                    }
                }
                return result;
            }
            else {
                System.Diagnostics.Debug.Assert(link.Expansion != null);
                System.Diagnostics.Debug.Assert(link.KeyExpressions == keyExpressions);
                // deferred expression already defined...
                return link.Expansion;
            }
        }
		internal override SqlNode VisitLink(SqlLink link) {
			link = (SqlLink)base.VisitLink(link);

			// prefetch all 'LoadWith' links
			if (!this.disableInclude && this.shape != null && this.alreadyIncluded != null) {
				MetaDataMember mdm = link.Member;
				MemberInfo mi = mdm.Member;
				if (this.shape.IsPreloaded(mi) && mdm.LoadMethod == null) {
					// Is the other side of the relation in the list already?
					MetaType otherType = mdm.DeclaringType.InheritanceRoot;
					if (!this.alreadyIncluded.Contains(otherType)) {
						this.alreadyIncluded.Add(otherType);
						SqlNode fetched = this.ConvertToFetchedExpression(link);
						this.alreadyIncluded.Remove(otherType);
						return fetched;
					}
				}
			}

			if (this.inGroupBy && link.Expansion != null) {
				return this.VisitLinkExpansion(link);
			}

			return link;
		}
		private SqlExpression VisitLinkExpansion(SqlLink link) {
			SqlAliasRef aref = link.Expansion as SqlAliasRef;
			if (aref != null && aref.Alias.Node.NodeType == SqlNodeType.Table) {
				SqlAlias outerAlias;
				if (this.outerAliasMap.TryGetValue(aref.Alias, out outerAlias)) {
					return this.VisitAliasRef(new SqlAliasRef(outerAlias));
				}
				// should not happen
				Diagnostics.Debug.Assert(false);
			}
			return this.VisitExpression(link.Expansion);
		}
Example #13
0
 private SqlNew BuildProjectionInternal(SqlExpression item, MetaType rowType, IEnumerable<MetaDataMember> members, bool allowDeferred, SqlLink link, Expression source) {
     List<SqlMemberAssign> bindings = new List<SqlMemberAssign>();
     foreach (MetaDataMember mm in members) {
         if (allowDeferred && (mm.IsAssociation || mm.IsDeferred)) {
             // check if this member is the reverse association to the supplied link
             if (link != null && mm != link.Member && mm.IsAssociation
                 && mm.MappedName == link.Member.MappedName
                 && !mm.Association.IsMany
                 && !IsPreloaded(link.Member.Member)) {
                 // place a new link here with an expansion that is previous link's root expression.
                 // this will allow joins caused by reverse association references to 'melt' away. :-)
                 SqlLink mlink = this.BuildLink(item, mm, source);
                 mlink.Expansion = link.Expression;
                 bindings.Add(new SqlMemberAssign(mm.Member, mlink));
             }
             else {
                 bindings.Add(new SqlMemberAssign(mm.Member, this.BuildLink(item, mm, source)));
             }
         } 
         else if (!mm.IsAssociation) {
             bindings.Add(new SqlMemberAssign(mm.Member, sql.Member(item, mm)));
         }
     }
     ConstructorInfo cons = rowType.Type.GetConstructor(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic, null, System.Type.EmptyTypes, null);
     if (cons == null) {
         throw Error.MappedTypeMustHaveDefaultConstructor(rowType.Type);
     }
     return sql.New(rowType, cons, null, null, bindings, source);
 }
Example #14
0
		/// <summary>
		/// Convert ITable into SqlNodes. If the hierarchy involves inheritance then 
		/// a type case is built. Abstractly, a type case is a CASE where each WHEN is a possible
		/// a typebinding that may be instantianted. 
		/// </summary>
		private SqlNode TranslateConstantTable(ITable table, SqlLink link)
		{
			if(table.Context != _services.Context)
			{
				throw Error.WrongDataContext();
			}
			MetaTable metaTable = _services.Model.GetTable(table.ElementType);
			return _translator.BuildDefaultQuery(metaTable.RowType, _allowDeferred, link, _dominatingExpression);
		}
		internal override SqlNode VisitLink(SqlLink link)
		{
			SqlExpression[] exprs = new SqlExpression[link.KeyExpressions.Count];
			for(int i = 0, n = exprs.Length; i < n; i++)
			{
				exprs[i] = this.VisitExpression(link.KeyExpressions[i]);
			}
			SqlLink newLink = new SqlLink(new object(), link.RowType, link.ClrType, link.SqlType, null, link.Member, exprs, null, link.SourceExpression);
			this.nodeMap[link] = newLink;
			// break the potential cyclic tree by visiting these after adding to the map
			newLink.Expression = this.VisitExpression(link.Expression);
			newLink.Expansion = this.VisitExpression(link.Expansion);
			return newLink;
		}
Example #16
0
 internal virtual SqlNode VisitLink(SqlLink link) {
     // Don't visit the link's Expansion
     for (int i = 0, n = link.KeyExpressions.Count; i < n; i++) {
         link.KeyExpressions[i] = this.VisitExpression(link.KeyExpressions[i]);
     }
     return link;
 }
Example #17
0
 internal SqlNode TranslateLink(SqlLink link, bool asExpression) {
     return this.TranslateLink(link, link.KeyExpressions, asExpression);
 }