DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
TableQueryProvider.cs
Go to the documentation of this file.
1 //
2 // Copyright 2010-2015 Deveel
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 using System;
18 using System.Linq;
19 using System.Linq.Expressions;
20 using System.Reflection;
21 
22 using Deveel.Data.Sql;
23 
24 namespace Deveel.Data.Linq {
25  class TableQueryProvider : IQueryProvider {
26  public TableQueryProvider(ITable table) {
27  if (table == null)
28  throw new ArgumentNullException("table");
29 
30  Table = table;
31  }
32 
33  public ITable Table { get; private set; }
34 
35  public IQueryable CreateQuery(Expression expression) {
36  var elementType = TypeSystem.GetElementType(expression.Type);
37 
38  try {
39  var type = typeof (QueryableTable<>).MakeGenericType(elementType);
40  return (IQueryable) Activator.CreateInstance(type, new object[] {this, expression});
41  } catch (TargetInvocationException ex) {
42  throw ex.InnerException;
43  }
44  }
45 
46  public IQueryable<TElement> CreateQuery<TElement>(Expression expression) {
47  return new QueryableTable<TElement>(this, expression);
48  }
49 
50  public object Execute(Expression expression) {
51  return Execute(expression, false);
52  }
53 
54 
55  private object Execute(Expression expression, bool isEnum) {
56  // The expression must represent a query over the data source.
57  if (!IsQueryOverDataSource(expression))
58  throw new InvalidProgramException("No query over the data source was specified.");
59 
60  var elementType = TypeSystem.GetElementType(expression.Type);
61 
62  IQueryable queryResult;
63 
64  var builder = new QueryBuilder();
65 
66  // Find the call to Where() and get the lambda expression predicate.
67  var whereFinder = new InnermostWhereFinder();
68  var whereExpression = whereFinder.GetInnermostWhere(expression);
69 
70  if (whereExpression == null) {
71  var query = builder.Build();
72  queryResult = query.Execute(elementType, Table).AsQueryable();
73  } else {
74  var lambdaExpression = (LambdaExpression)((UnaryExpression)(whereExpression.Arguments[1])).Operand;
75 
76  // Send the lambda expression through the partial evaluator.
77  lambdaExpression = (LambdaExpression)Evaluator.PartialEval(lambdaExpression);
78 
79  var query = builder.Build(lambdaExpression.Body);
80  queryResult = query.Execute(elementType, Table).AsQueryable();
81  }
82 
83  // Copy the expression tree that was passed in, changing only the first
84  // argument of the innermost MethodCallExpression.
85  var treeCopier = new ExpressionTreeModifier(queryResult, elementType);
86  var newExpressionTree = treeCopier.Visit(expression);
87 
88  // This step creates an IQueryable that executes by replacing Queryable methods with Enumerable methods.
89  if (isEnum)
90  return queryResult.Provider.CreateQuery(newExpressionTree);
91 
92  return queryResult.Provider.Execute(newExpressionTree);
93  }
94 
95  private static bool IsQueryOverDataSource(Expression expression) {
96  // If expression represents an unqueried IQueryable data source instance,
97  // expression is of type ConstantExpression, not MethodCallExpression.
98  return (expression is MethodCallExpression);
99  }
100 
101  public TResult Execute<TResult>(Expression expression) {
102  bool isEnum = (typeof(TResult).Name == "IEnumerable`1");
103  return (TResult) Execute(expression, isEnum);
104  }
105 
106  public string GetQueryText(Expression expression) {
107  throw new NotImplementedException();
108  }
109  }
110 }
object Execute(Expression expression)
object Execute(Expression expression, bool isEnum)
static bool IsQueryOverDataSource(Expression expression)
static Type GetElementType(Type seqType)
Definition: TypeSystem.cs:22
static Expression PartialEval(Expression expression, Func< Expression, bool > fnCanBeEvaluated)
Performs evaluation & replacement of independent sub-trees
Definition: Evaluator.cs:29
A TABLE object in a database.
string GetQueryText(Expression expression)
IQueryable CreateQuery(Expression expression)