Exemplo n.º 1
0
		SqlInfo[] ConvertToIndexInternal(Expression? expression, int level, ConvertFlags flags)
		{
			if (IsScalar)
			{
				if (Body.NodeType == ExpressionType.Parameter)
					for (var i = 0; i < Sequence.Length; i++)
						if (Body == Lambda.Parameters[i])
							return Sequence[i].ConvertToIndex(expression, level, flags);

				if (expression == null)
				{
					var key = Tuple.Create((MemberInfo?)null, flags);

					if (!_memberIndex.TryGetValue(key, out var idx))
					{
						idx = ConvertToSql(null, 0, flags);

						foreach (var info in idx)
							SetInfo(info, null);

						_memberIndex.Add(key, idx);
					}

					return idx;
				}

				switch (flags)
				{
					case ConvertFlags.Field :
					case ConvertFlags.Key   :
					case ConvertFlags.All   :
						return ProcessScalar(
							expression,
							level,
							(ctx, ex, l) => ctx.ConvertToIndex(ex, l, flags),
							() => GetSequence(expression, level)!.ConvertToIndex(expression, level + 1, flags));
				}
			}
			else
			{
				if (expression == null)
				{
					switch (flags)
					{
						case ConvertFlags.Field :
						case ConvertFlags.Key   :
						case ConvertFlags.All   :
							{
								var p = Expression.Parameter(Body.Type, "p");
								var q =
									from m in Members.Keys
									where !(m is MethodInfo || EagerLoading.IsDetailsMember(m))
									select new SqlData
									{
										Sql    = ConvertToIndex(Expression.MakeMemberAccess(p, m), 1, flags),
										Member = m
									} into mm
									from m in mm.Sql.Select(s => s.Clone(mm.Member))
									select m;

								return q.ToArray();
							}
					}
				}

				switch (flags)
				{
					case ConvertFlags.All   :
					case ConvertFlags.Key   :
					case ConvertFlags.Field :
						{
							if (level == 0)
							{
								var idx = Builder.ConvertExpressions(this, expression!, flags);

								foreach (var info in idx)
									SetInfo(info, null);

								return idx;
							}

							var levelExpression = expression!.GetLevelExpression(Builder.MappingSchema, level);

							switch (levelExpression.NodeType)
							{
								case ExpressionType.MemberAccess :
									{
										if (levelExpression == expression)
										{
											var member = Tuple.Create((MemberInfo?)((MemberExpression)levelExpression).Member, flags);

											if (!_memberIndex.TryGetValue(member, out var idx))
											{
												idx = ConvertToSql(expression, level, flags);

												if (flags == ConvertFlags.Field && idx.Length != 1)
													throw new InvalidOperationException();

												foreach (var info in idx)
													SetInfo(info, member.Item1);

												_memberIndex.Add(member, idx);
											}

											return idx;
										}

										return ProcessMemberAccess(
											expression!,
											(MemberExpression)levelExpression,
											level,
											(n, ctx, ex, l, _) => n == 0 ?
												GetSequence(expression!, level)!.ConvertToIndex(expression, level + 1, flags) :
												ctx.ConvertToIndex(ex, l, flags));
									}

								case ExpressionType.Parameter:
								case ExpressionType.Extension:

									if (levelExpression != expression)
										return GetSequence(expression!, level)!.ConvertToIndex(expression, level + 1, flags);
									break;
							}

							break;
						}
				}
			}

			throw new NotImplementedException();
		}
Exemplo n.º 2
0
		public virtual SqlInfo[] ConvertToSql(Expression? expression, int level, ConvertFlags flags)
		{
			if (expression != null && level > 0 && expression.NodeType == ExpressionType.Call)
			{
				var e = (MethodCallExpression)expression;

				if (e.Method.DeclaringType == typeof(Enumerable) && !typeof(IGrouping<,>).IsSameOrParentOf(e.Arguments[0].Type))
				{
					return new[] { new SqlInfo { Sql = Builder.SubQueryToSql(this, e) } };
				}
			}

			if (IsScalar)
			{
				if (expression == null)
					return Builder.ConvertExpressions(this, Body, flags);

				switch (flags)
				{
					case ConvertFlags.Field :
					case ConvertFlags.Key   :
					case ConvertFlags.All   :
						{
							if (Body.NodeType != ExpressionType.Parameter && level == 0)
							{
								var levelExpression = expression.GetLevelExpression(Builder.MappingSchema, level);

								if (levelExpression != expression)
									if (flags != ConvertFlags.Field && IsExpression(expression, level, RequestFor.Field).Result)
										flags = ConvertFlags.Field;
							}

							return ProcessScalar(
								expression,
								level,
								(ctx, ex, l) => ctx.ConvertToSql(ex, l, flags),
								() => new[] { new SqlInfo { Sql = Builder.ConvertToSql(this, expression) } });
						}
				}
			}
			else
			{
				if (expression == null)
				{
					if (flags != ConvertFlags.Field)
					{
						var q =
							from m in Members
							where !(m.Key is MethodInfo || EagerLoading.IsDetailsMember(m.Key))
							select ConvertMember(m.Key, m.Value, flags) into mm
							from m in mm
							select m;

						return q.ToArray();
					}

					throw new NotImplementedException();
				}

				switch (flags)
				{
					case ConvertFlags.All   :
					case ConvertFlags.Key   :
					case ConvertFlags.Field :
						{
							var levelExpression = expression.GetLevelExpression(Builder.MappingSchema, level);
							levelExpression = levelExpression.Unwrap();

							switch (levelExpression.NodeType)
							{
								case ExpressionType.MemberAccess :
									{
										if (level != 0 && levelExpression == expression)
										{
											var member = ((MemberExpression)levelExpression).Member;

											if (!_sql.TryGetValue(member, out var sql))
											{
												var memberExpression = GetMemberExpression(
													member, levelExpression == expression, levelExpression.Type, expression);

												sql = ConvertExpressions(memberExpression, flags)
													.Select(si => si.Clone(member)).ToArray();

												_sql.Add(member, sql);
											}

											return sql;
										}

										return ProcessMemberAccess(
											expression, (MemberExpression)levelExpression, level,
											(n,ctx,ex,l,mex) =>
											{
												switch (n)
												{
													case 0 :
														var buildExpression = GetExpression(expression, levelExpression, mex);
														return ConvertExpressions(buildExpression, flags);
													default:
														return ctx.ConvertToSql(ex, l, flags);
												}
											});
									}

								case ExpressionType.Parameter:
									if (levelExpression != expression)
										return GetSequence(expression, level)!.ConvertToSql(expression, level + 1, flags);

									if (level == 0)
										return GetSequence(expression, level)!.ConvertToSql(null, 0, flags);

									break;

								case ExpressionType.Extension:
									{
										if (levelExpression is ContextRefExpression)
										{
											if (levelExpression != expression)
												return GetSequence(expression, level)!.ConvertToSql(expression,
													level + 1,
													flags);

											if (level == 0)
												return GetSequence(expression, level)!.ConvertToSql(null, 0, flags);
										}

										goto default;
									}

								default:
									if (level == 0)
										return Builder.ConvertExpressions(this, expression, flags);
									break;
							}

							break;
						}
				}
			}

			throw new NotImplementedException();
		}