\r
using System;\r
using System.Collections.Generic;\r
+using System.Diagnostics;\r
using System.Linq;\r
using System.Linq.Expressions;\r
+using System.Text.RegularExpressions;\r
\r
-#if MONO_STRICT\r
-using System.Data.Linq.Sugar.ExpressionMutator;\r
-using System.Data.Linq.Sugar.Expressions;\r
-#else\r
using DbLinq.Data.Linq.Sugar.ExpressionMutator;\r
using DbLinq.Data.Linq.Sugar.Expressions;\r
-#endif\r
-using System.Text.RegularExpressions;\r
using DbLinq.Factory;\r
using DbLinq.Util;\r
-using System.Diagnostics;\r
\r
-#if MONO_STRICT\r
-namespace System.Data.Linq.Sugar.Implementation\r
-#else\r
namespace DbLinq.Data.Linq.Sugar.Implementation\r
-#endif\r
{\r
/// <summary>\r
/// Full query builder, with cache management\r
protected virtual IList<Expression> FindExpressionsByName(string name, BuilderContext builderContext)\r
{\r
var expressions = new List<Expression>();\r
- expressions.AddRange(from t in builderContext.EnumerateAllTables() where t.Alias == name select (Expression)t);\r
+ expressions.AddRange((from t in builderContext.EnumerateAllTables() where t.Alias == name select (Expression)t).Distinct());\r
expressions.AddRange(from c in builderContext.EnumerateScopeColumns() where c.Alias == name select (Expression)c);\r
return expressions;\r
}\r
/// <param name="builderContext"></param>\r
protected virtual void CheckTablesAlias(BuilderContext builderContext)\r
{\r
- var tables = builderContext.EnumerateAllTables().ToList();\r
+ var tables = builderContext.EnumerateAllTables().Distinct().ToList();\r
// just to be nice: if we have only one table involved, there's no need to alias it\r
if (tables.Count == 1)\r
{\r
do\r
{\r
externalParameterExpression.Alias = MakeTableName(aliasBase, ++anonymousIndex, builderContext);\r
- } while (FindExpressionsByName(externalParameterExpression.Alias, builderContext).Count != 1);\r
+ } while (FindParametersByName(externalParameterExpression.Alias, builderContext).Count > 1);\r
}\r
}\r
}\r
/// <returns></returns>\r
protected Expression BuildExpressionQuery(ExpressionChain expressions, Expression tableExpression, BuilderContext builderContext)\r
{\r
- var last = expressions.Last();\r
- foreach (var expression in expressions)\r
- {\r
- if (expression == last)\r
- builderContext.IsExternalInExpressionChain = true;\r
-\r
- // write full debug\r
-#if DEBUG && !MONO_STRICT\r
- var log = builderContext.QueryContext.DataContext.Log;\r
- if (log != null)\r
- log.WriteExpression(expression);\r
-#endif\r
- // Convert linq Expressions to QueryOperationExpressions and QueryConstantExpressions \r
- // Query expressions language identification\r
- var currentExpression = ExpressionLanguageParser.Parse(expression, builderContext);\r
- // Query expressions query identification \r
- currentExpression = ExpressionDispatcher.Analyze(currentExpression, tableExpression, builderContext);\r
-\r
- tableExpression = currentExpression;\r
- }\r
+ tableExpression = ExpressionDispatcher.Analyze(expressions, tableExpression, builderContext);\r
ExpressionDispatcher.BuildSelect(tableExpression, builderContext);\r
return tableExpression;\r
}\r
var scopeExpression = builderContext.SelectExpressions[scopeExpressionIndex];\r
\r
// where clauses\r
+ List<int> whereToRemove = new List<int>(); // List of where clausole evaluating TRUE (could be ignored and so removed)\r
+ bool falseWhere = false; // true when the full where evaluate to FALSE\r
for (int whereIndex = 0; whereIndex < scopeExpression.Where.Count; whereIndex++)\r
{\r
- scopeExpression.Where[whereIndex] = processor(scopeExpression.Where[whereIndex], builderContext);\r
+ Expression whereClausole = processor(scopeExpression.Where[whereIndex], builderContext);\r
+ ConstantExpression constantWhereClausole = whereClausole as ConstantExpression;\r
+ if (constantWhereClausole != null)\r
+ {\r
+ if (constantWhereClausole.Value.Equals(false))\r
+ {\r
+ falseWhere = true;\r
+ break;\r
+ }\r
+ else if (constantWhereClausole.Value.Equals(true))\r
+ {\r
+ whereToRemove.Add(whereIndex);\r
+ continue;\r
+ }\r
+ }\r
+ scopeExpression.Where[whereIndex] = whereClausole;\r
+ }\r
+ if (scopeExpression.Where.Count > 0)\r
+ {\r
+ if (falseWhere)\r
+ {\r
+ scopeExpression.Where.Clear();\r
+ scopeExpression.Where.Add(Expression.Equal(Expression.Constant(true), Expression.Constant(false)));\r
+ }\r
+ else\r
+ foreach (int whereIndex in whereToRemove)\r
+ scopeExpression.Where.RemoveAt(whereIndex);\r
}\r
\r
// limit clauses\r
protected virtual SelectQuery GetFromSelectCache(ExpressionChain expressions)\r
{\r
var cache = QueryCache;\r
- lock (cache)\r
- return cache.GetFromSelectCache(expressions);\r
+ return cache.GetFromSelectCache(expressions);\r
}\r
\r
protected virtual void SetInSelectCache(ExpressionChain expressions, SelectQuery sqlSelectQuery)\r
{\r
var cache = QueryCache;\r
- lock (cache)\r
- cache.SetInSelectCache(expressions, sqlSelectQuery);\r
+ cache.SetInSelectCache(expressions, sqlSelectQuery);\r
}\r
\r
protected virtual Delegate GetFromTableReaderCache(Type tableType, IList<string> columns)\r
{\r
var cache = QueryCache;\r
- lock (cache)\r
- return cache.GetFromTableReaderCache(tableType, columns);\r
+ return cache.GetFromTableReaderCache(tableType, columns);\r
}\r
\r
protected virtual void SetInTableReaderCache(Type tableType, IList<string> columns, Delegate tableReader)\r
{\r
var cache = queryCache;\r
- lock (cache)\r
- cache.SetInTableReaderCache(tableType, columns, tableReader);\r
+ cache.SetInTableReaderCache(tableType, columns, tableReader);\r
}\r
\r
/// <summary>\r
/// <returns></returns>\r
public SelectQuery GetSelectQuery(ExpressionChain expressions, QueryContext queryContext)\r
{\r
- var query = GetFromSelectCache(expressions);\r
+ SelectQuery query = null;\r
+ if (queryContext.DataContext.QueryCacheEnabled)\r
+ {\r
+ query = GetFromSelectCache(expressions);\r
+ }\r
if (query == null)\r
{\r
- var timer = new Stopwatch();\r
- timer.Start();\r
+ Profiler.At("START: GetSelectQuery(), building Expression query");\r
var expressionsQuery = BuildExpressionQuery(expressions, queryContext);\r
- timer.Stop();\r
- long expressionBuildTime = timer.ElapsedMilliseconds;\r
+ Profiler.At("END: GetSelectQuery(), building Expression query");\r
\r
- timer.Reset();\r
- timer.Start();\r
+ Profiler.At("START: GetSelectQuery(), building Sql query");\r
query = BuildSqlQuery(expressionsQuery, queryContext);\r
- timer.Stop();\r
- long sqlBuildTime = timer.ElapsedMilliseconds;\r
+ Profiler.At("END: GetSelectQuery(), building Sql query");\r
\r
-#if DEBUG && !MONO_STRICT\r
- // generation time statistics\r
- var log = queryContext.DataContext.Log;\r
- if (log != null)\r
+ if (queryContext.DataContext.QueryCacheEnabled)\r
{\r
- log.WriteLine("Select Expression build: {0}ms", expressionBuildTime);\r
- log.WriteLine("Select SQL build: {0}ms", sqlBuildTime);\r
+ SetInSelectCache(expressions, query);\r
}\r
-#endif\r
- SetInSelectCache(expressions, query);\r
+ }\r
+ else if (query.InputParameters.Count > 0)\r
+ {\r
+ Profiler.At("START: GetSelectQuery(), building Expression parameters of cached query");\r
+ var parameters = BuildExpressionParameters(expressions, queryContext);\r
+ query = new SelectQuery(queryContext.DataContext, query.Sql, parameters, query.RowObjectCreator, query.ExecuteMethodName);\r
+ Profiler.At("END: GetSelectQuery(), building Expression parameters of cached query");\r
}\r
return query;\r
}\r
\r
+ IList<InputParameterExpression> BuildExpressionParameters(ExpressionChain expressions, QueryContext queryContext)\r
+ {\r
+ var builderContext = new BuilderContext(queryContext);\r
+ var previousExpression = ExpressionDispatcher.CreateTableExpression(expressions.Expressions[0], builderContext);\r
+ previousExpression = BuildExpressionQuery(expressions, previousExpression, builderContext);\r
+ BuildOffsetsAndLimits(builderContext);\r
+ // then prepare Parts for SQL translation\r
+ PrepareSqlOperands(builderContext);\r
+ return builderContext.ExpressionQuery.Parameters;\r
+ }\r
+\r
/// <summary>\r
/// Returns a Delegate to create a row for a given IDataRecord\r
/// The Delegate is Func<IDataRecord,MappingContext,"tableType">\r
/// <returns></returns>\r
public virtual Delegate GetTableReader(Type tableType, IList<string> parameters, QueryContext queryContext)\r
{\r
- var reader = GetFromTableReaderCache(tableType, parameters);\r
+ Delegate reader = null;\r
+ if (queryContext.DataContext.QueryCacheEnabled)\r
+ {\r
+ reader = GetFromTableReaderCache(tableType, parameters);\r
+ }\r
if (reader == null)\r
{\r
var lambda = ExpressionDispatcher.BuildTableReader(tableType, parameters,\r
new BuilderContext(queryContext));\r
reader = lambda.Compile();\r
- SetInTableReaderCache(tableType, parameters, reader);\r
+ if (queryContext.DataContext.QueryCacheEnabled)\r
+ {\r
+ SetInTableReaderCache(tableType, parameters, reader);\r
+ }\r
}\r
return reader;\r
}\r