Beispiel #1
0
        internal static SqlNode Reduce(SqlNode node, SqlNodeAnnotations annotations, Enum[] providerModesWithIncompatibilities)
        {
            Reducer r = new Reducer(providerModesWithIncompatibilities)
            {
                Annotations = annotations
            };

            return(r.Visit(node));
        }
		/// <summary>
		/// Checks whether the given node is supported on the given server.
		/// </summary>
		/// <param name="node">The node.</param>
		/// <param name="annotations">The annotations.</param>
		/// <param name="providerMode">The provider mode to check for.</param>
		internal static void ThrowIfUnsupported(SqlNode node, SqlNodeAnnotations annotations, Enum providerMode)
		{
			// Check to see whether there's at least one SqlServerCompatibilityAnnotation.
			if(annotations.HasAnnotationType(typeof(CompatibilityAnnotation)))
			{
				Visitor visitor = new Visitor(providerMode) {annotations = annotations};
				visitor.Visit(node);

				// If any messages were recorded, then throw an exception.
				if(visitor.reasons.Count > 0)
				{
					throw Error.ExpressionNotSupportedForSqlServerVersion(visitor.reasons);
				}
			}
		}
        /// <summary>
        /// Checks whether the given node is supported on the given server.
        /// </summary>
        /// <param name="node">The node.</param>
        /// <param name="annotations">The annotations.</param>
        /// <param name="providerMode">The provider mode to check for.</param>
        internal static void ThrowIfUnsupported(SqlNode node, SqlNodeAnnotations annotations, Enum providerMode)
        {
            // Check to see whether there's at least one SqlServerCompatibilityAnnotation.
            if (annotations.HasAnnotationType(typeof(CompatibilityAnnotation)))
            {
                Visitor visitor = new Visitor(providerMode)
                {
                    annotations = annotations
                };
                visitor.Visit(node);

                // If any messages were recorded, then throw an exception.
                if (visitor.reasons.Count > 0)
                {
                    throw Error.ExpressionNotSupportedForSqlServerVersion(visitor.reasons);
                }
            }
        }
Beispiel #4
0
		private IObjectReaderFactory GetDefaultFactory(MetaType rowType)
		{
			if(rowType == null)
			{
				throw Error.ArgumentNull("rowType");
			}
			SqlNodeAnnotations annotations = new SqlNodeAnnotations();
			Expression tmp = Expression.Constant(null);
			SqlUserQuery suq = new SqlUserQuery(string.Empty, null, null, tmp);
			if(TypeSystem.IsSimpleType(rowType.Type))
			{
				// if the element type is a simple type (int, bool, etc.) we create
				// a single column binding
				SqlUserColumn col = new SqlUserColumn(rowType.Type, _typeProvider.From(rowType.Type), suq, "", false, suq.SourceExpression);
				suq.Columns.Add(col);
				suq.Projection = col;
			}
			else
			{
				// ... otherwise we generate a default projection
				SqlUserRow rowExp = new SqlUserRow(rowType.InheritanceRoot, _typeProvider.GetApplicationType((int)ConverterSpecialTypes.Row), suq, tmp);
				suq.Projection = _translator.BuildProjection(rowExp, rowType, true, null, tmp);
			}
			Type resultType = TypeSystem.GetSequenceType(rowType.Type);
			QueryInfo[] qis = this.BuildQuery(ResultShape.Sequence, resultType, suq, null, annotations);
			return this.GetReaderFactory(qis[qis.Length - 1].Query, rowType.Type);
		}
Beispiel #5
0
		private QueryInfo[] BuildQuery(ResultShape resultShape, Type resultType, SqlNode node, ReadOnlyCollection<System.Data.Linq.Provider.NodeTypes.SqlParameter> parentParameters, SqlNodeAnnotations annotations)
		{
			System.Diagnostics.Debug.Assert(resultType != null);
			System.Diagnostics.Debug.Assert(node != null);

			SqlSupersetValidator validator = new SqlSupersetValidator();

			// These are the rules that apply to every SQL tree.
			if(_checkQueries)
			{
				validator.AddValidator(new ColumnTypeValidator()); /* Column CLR Type must agree with its Expressions CLR Type */
				validator.AddValidator(new LiteralValidator()); /* Constrain literal Types */
			}

			validator.Validate(node);

			SqlColumnizer columnizer = new SqlColumnizer();

			// resolve member references
			bool canUseOuterApply = (this.Mode == SqlServerProviderMode.Sql2005 || this.Mode == SqlServerProviderMode.Sql2008 || this.Mode == SqlServerProviderMode.SqlCE);
			SqlBinder binder = new SqlBinder(_translator, _sqlFactory, _services.Model, _services.Context.LoadOptions, columnizer, canUseOuterApply);
			binder.OptimizeLinkExpansions = (_optimizationFlags & OptimizationFlags.OptimizeLinkExpansions) != 0;
			binder.SimplifyCaseStatements = (_optimizationFlags & OptimizationFlags.SimplifyCaseStatements) != 0;
			binder.PreBinder = delegate(SqlNode n)
			{
				// convert methods into known reversable operators
				return PreBindDotNetConverter.Convert(n, _sqlFactory, _services.Model);
			};
			node = binder.Bind(node);
			if(_checkQueries)
			{
				validator.AddValidator(new ExpectNoAliasRefs());
				validator.AddValidator(new ExpectNoSharedExpressions());
			}
			validator.Validate(node);

			node = PostBindDotNetConverter.Convert(node, _sqlFactory, this.Mode);

			// identify true flow of sql data types 
			SqlRetyper retyper = new SqlRetyper(new SqlFactory(_typeProvider, _services.Model));
			node = retyper.Retype(node);
			validator.Validate(node);

			// change CONVERT to special conversions like UNICODE,CHAR,...
			SqlTypeConverter converter = new SqlTypeConverter(_sqlFactory);
			node = converter.Visit(node);
			validator.Validate(node);

			// transform type-sensitive methods such as LEN (to DATALENGTH), ...
			SqlMethodTransformer methodTransformer = new SqlMethodTransformer(_sqlFactory);
			node = methodTransformer.Visit(node);
			validator.Validate(node);

			// convert multisets into separate queries
			SqlMultiplexerOptionType options = (this.Mode == SqlServerProviderMode.Sql2008 ||
											  this.Mode == SqlServerProviderMode.Sql2005 ||
											  this.Mode == SqlServerProviderMode.SqlCE)
				? SqlMultiplexerOptionType.EnableBigJoin : SqlMultiplexerOptionType.None;
			SqlMultiplexer mux = new SqlMultiplexer(options, parentParameters, _sqlFactory);
			node = mux.Multiplex(node);
			validator.Validate(node);

			// convert object construction expressions into flat row projections
			SqlFlattener flattener = new SqlFlattener(_sqlFactory, columnizer);
			node = flattener.Flatten(node);
			validator.Validate(node);

			if(_mode == SqlServerProviderMode.SqlCE)
			{
				SqlRewriteScalarSubqueries rss = new SqlRewriteScalarSubqueries(_sqlFactory);
				node = rss.Rewrite(node);
			}

			// Simplify case statements where all alternatives map to the same thing.
			// Doing this before deflator because the simplified results may lead to
			// more deflation opportunities.
			// Doing this before booleanizer because it may convert CASE statements (non-predicates) into
			// predicate expressions.
			// Doing this before reorderer because it may reduce some orders to constant nodes which should not
			// be passed onto ROW_NUMBER.
			node = SqlCaseSimplifier.Simplify(node, _sqlFactory);

			// Rewrite order-by clauses so that they only occur at the top-most select 
			// or in selects with TOP
			SqlReorderer reorderer = new SqlReorderer(_typeProvider, _sqlFactory);
			node = reorderer.Reorder(node);
			validator.Validate(node);

			// Inject code to turn predicates into bits, and bits into predicates where necessary
			node = SqlBooleanizer.Rationalize(node, _typeProvider, _services.Model);
			if(_checkQueries)
			{
				validator.AddValidator(new ExpectRationalizedBooleans()); /* From now on all boolean expressions should remain rationalized. */
			}
			validator.Validate(node);

			if(_checkQueries)
			{
				validator.AddValidator(new ExpectNoFloatingColumns());
			}

			// turning predicates into bits/ints can change Sql types, propagate changes            
			node = retyper.Retype(node);
			validator.Validate(node);

			// assign aliases to columns
			// we need to do this now so that the sql2k lifters will work
			SqlAliaser aliaser = new SqlAliaser();
			node = aliaser.AssociateColumnsWithAliases(node);
			validator.Validate(node);

			// SQL2K enablers.
			node = SqlLiftWhereClauses.Lift(node, new SqlFactory(_typeProvider, _services.Model));
			node = SqlLiftIndependentRowExpressions.Lift(node);
			node = SqlOuterApplyReducer.Reduce(node, _sqlFactory, annotations);
			node = SqlTopReducer.Reduce(node, annotations, _sqlFactory);

			// resolve references to columns in other scopes by adding them
			// to the intermediate selects
			SqlResolver resolver = new SqlResolver();
			node = resolver.Resolve(node);
			validator.Validate(node);

			// re-assign aliases after resolving (new columns may have been added)
			node = aliaser.AssociateColumnsWithAliases(node);
			validator.Validate(node);

			// fixup union projections
			node = SqlUnionizer.Unionize(node);

			// remove order-by of literals
			node = SqlRemoveConstantOrderBy.Remove(node);

			// throw out unused columns and redundant sub-queries...
			SqlDeflator deflator = new SqlDeflator();
			node = deflator.Deflate(node);
			validator.Validate(node);

			// Positioning after deflator because it may remove unnecessary columns
			// from SELECT projection lists and allow more CROSS APPLYs to be reduced
			// to CROSS JOINs.
			node = SqlCrossApplyToCrossJoin.Reduce(node, annotations, new Enum[] { SqlServerProviderMode.Sql2000 });

			// fixup names for aliases, columns, locals, etc..
			SqlNamer namer = new SqlNamer();
			node = namer.AssignNames(node);
			validator.Validate(node);

			// Convert [N]Text,Image to [N]VarChar(MAX),VarBinary(MAX) where necessary.
			// These new types do not exist on SQL2k, so add annotations.
			LongTypeConverter longTypeConverter = new LongTypeConverter(_sqlFactory);
			node = longTypeConverter.AddConversions(node, annotations);

			// final validation            
			validator.AddValidator(new ExpectNoMethodCalls());
			validator.AddValidator(new ValidateNoInvalidComparison());
			validator.Validate(node);

			SqlParameterizer parameterizer = new SqlParameterizer(_typeProvider, annotations);
			SqlFormatter formatter = new SqlFormatter();
			if(_mode == SqlServerProviderMode.SqlCE ||
				_mode == SqlServerProviderMode.Sql2005 ||
				_mode == SqlServerProviderMode.Sql2008)
			{
				formatter.ParenthesizeTop = true;
			}

			SqlBlock block = node as SqlBlock;
			if(block != null && _mode == SqlServerProviderMode.SqlCE)
			{
				// SQLCE cannot batch multiple statements.
				ReadOnlyCollection<ReadOnlyCollection<SqlParameterInfo>> parameters = parameterizer.ParameterizeBlock(block);
				string[] commands = formatter.FormatBlock(block, false);
				QueryInfo[] queries = new QueryInfo[commands.Length];
				for(int i = 0, n = commands.Length; i < n; i++)
				{
					queries[i] = new QueryInfo(
						block.Statements[i],
						commands[i],
						parameters[i],
						(i < n - 1) ? ResultShape.Return : resultShape,
						(i < n - 1) ? typeof(int) : resultType
						);
				}
				return queries;
			}
			else
			{
				// build only one result
				ReadOnlyCollection<SqlParameterInfo> parameters = parameterizer.Parameterize(node);
				string commandText = formatter.Format(node);
				return new QueryInfo[] {
                    new QueryInfo(node, commandText, parameters, resultShape, resultType)
                    };
			}
		}
Beispiel #6
0
		internal QueryInfo[] BuildQuery(Expression query, SqlNodeAnnotations annotations)
		{
			this.CheckDispose();

			// apply maximal funcletization
			query = Funcletizer.Funcletize(query);

			// convert query nodes into sql nodes
			QueryConverter converter = new QueryConverter(_services, _typeProvider, _translator, _sqlFactory);
			switch(this.Mode)
			{
				case SqlServerProviderMode.Sql2000:
					converter.ConverterStrategy =
						ConverterStrategy.CanUseScopeIdentity |
						ConverterStrategy.CanUseJoinOn |
						ConverterStrategy.CanUseRowStatus;
					break;
				case SqlServerProviderMode.Sql2005:
				case SqlServerProviderMode.Sql2008:
					converter.ConverterStrategy =
						ConverterStrategy.CanUseScopeIdentity |
						ConverterStrategy.SkipWithRowNumber |
						ConverterStrategy.CanUseRowStatus |
						ConverterStrategy.CanUseJoinOn |
						ConverterStrategy.CanUseOuterApply |
						ConverterStrategy.CanOutputFromInsert;
					break;
				case SqlServerProviderMode.SqlCE:
					converter.ConverterStrategy = ConverterStrategy.CanUseOuterApply;
					// Can't set ConverterStrategy.CanUseJoinOn because scalar subqueries in the ON clause
					// can't be converted into anything.
					break;
			}
			SqlNode node = converter.ConvertOuter(query);

			return this.BuildQuery(this.GetResultShape(query), this.GetResultType(query), node, null, annotations);
		}
Beispiel #7
0
		DbCommand IProvider.GetCommand(Expression query)
		{
			this.CheckDispose();
			this.CheckInitialized();
			if(query == null)
			{
				throw Error.ArgumentNull("query");
			}
			this.InitializeProviderMode();
			SqlNodeAnnotations annotations = new SqlNodeAnnotations();
			QueryInfo[] qis = this.BuildQuery(query, annotations);
			QueryInfo qi = qis[qis.Length - 1];
			DbCommand cmd = _conManager.Connection.CreateCommand();
			cmd.CommandText = qi.CommandText;
			cmd.Transaction = _conManager.Transaction;
			cmd.CommandTimeout = _commandTimeout;
			AssignParameters(cmd, qi.Parameters, null, null);
			return cmd;
		}
Beispiel #8
0
		/// <summary>
		/// Executes the query specified as a LINQ expression tree.
		/// </summary>
		/// <param name="query"></param>
		/// <returns>
		/// A result object from which you can obtain the return value and output parameters.
		/// </returns>
		private IExecuteResult Execute(Expression query)
		{
			this.CheckDispose();
			this.CheckInitialized();
			this.CheckNotDeleted();
			if(query == null)
			{
				throw Error.ArgumentNull("query");
			}
			this.InitializeProviderMode();
			query = Funcletizer.Funcletize(query);

			if(this.EnableCacheLookup)
			{
				IExecuteResult cached = this.GetCachedResult(query);
				if(cached != null)
				{
					return cached;
				}
			}
			SqlNodeAnnotations annotations = new SqlNodeAnnotations();
			QueryInfo[] qis = this.BuildQuery(query, annotations);
			CheckSqlCompatibility(qis, annotations);

			LambdaExpression lambda = query as LambdaExpression;
			if(lambda != null)
			{
				query = lambda.Body;
			}

			IObjectReaderFactory factory = null;
			ICompiledSubQuery[] subQueries = null;
			QueryInfo qi = qis[qis.Length - 1];
			if(qi.ResultShape == ResultShape.Singleton)
			{
				subQueries = this.CompileSubQueries(qi.Query);
				factory = this.GetReaderFactory(qi.Query, qi.ResultType);
			}
			else if(qi.ResultShape == ResultShape.Sequence)
			{
				subQueries = this.CompileSubQueries(qi.Query);
				factory = this.GetReaderFactory(qi.Query, TypeSystem.GetElementType(qi.ResultType));
			}

			IExecuteResult result = this.ExecuteAll(query, qis, factory, null, subQueries);
			return result;
		}
Beispiel #9
0
		/// <summary>
		/// Look for compatibility annotations for the set of providers we
		/// add annotations for.
		/// </summary>
		private void CheckSqlCompatibility(QueryInfo[] queries, SqlNodeAnnotations annotations)
		{
			if(this.Mode == SqlServerProviderMode.Sql2000 ||
				this.Mode == SqlServerProviderMode.SqlCE)
			{
				for(int i = 0, n = queries.Length; i < n; i++)
				{
					CompatibilityCheck.ThrowIfUnsupported(queries[i].Query, annotations, this.Mode);
				}
			}
		}
 internal Visitor(NodeFactory factory, SqlNodeAnnotations annotations)
 {
     this.factory     = factory;
     this.annotations = annotations;
 }
        internal static SqlNode Reduce(SqlNode node, NodeFactory factory, SqlNodeAnnotations annotations)
        {
            Visitor r = new Visitor(factory, annotations);

            return(r.Visit(node));
        }
			internal Visitor(NodeFactory factory, SqlNodeAnnotations annotations)
			{
				this.factory = factory;
				this.annotations = annotations;
			}
		internal static SqlNode Reduce(SqlNode node, NodeFactory factory, SqlNodeAnnotations annotations)
		{
			Visitor r = new Visitor(factory, annotations);
			return r.Visit(node);
		}
Beispiel #14
0
		ICompiledQuery IProvider.Compile(Expression query)
		{
			this.CheckDispose();
			this.CheckInitialized();
			if(query == null)
			{
				throw Error.ArgumentNull("query");
			}
			this.InitializeProviderMode();

#warning [FB] POSSIBLE CLONE OF CODE FOUND IN IProvider.Execute
			SqlNodeAnnotations annotations = new SqlNodeAnnotations();
			QueryInfo[] qis = this.BuildQuery(query, annotations);
			CheckSqlCompatibility(qis, annotations);

			LambdaExpression lambda = query as LambdaExpression;
			if(lambda != null)
			{
				query = lambda.Body;
			}

			IObjectReaderFactory factory = null;
			ICompiledSubQuery[] subQueries = null;
			QueryInfo qi = qis[qis.Length - 1];
			if(qi.ResultShape == ResultShape.Singleton)
			{
				subQueries = this.CompileSubQueries(qi.Query);
				factory = this.GetReaderFactory(qi.Query, qi.ResultType);
			}
			else if(qi.ResultShape == ResultShape.Sequence)
			{
				subQueries = this.CompileSubQueries(qi.Query);
				factory = this.GetReaderFactory(qi.Query, TypeSystem.GetElementType(qi.ResultType));
			}

			return new AdoCompiledQuery(this, query, qis, factory, subQueries);
		}
Beispiel #15
0
			internal Visitor(SqlNodeAnnotations annotations, NodeFactory sql)
			{
				this.annotations = annotations;
				this.sql = sql;
			}
Beispiel #16
0
		private ICompiledSubQuery CompileSubQuery(SqlNode query, Type elementType, ReadOnlyCollection<System.Data.Linq.Provider.NodeTypes.SqlParameter> parameters)
		{
			query = SqlDuplicator.Copy(query);
			SqlNodeAnnotations annotations = new SqlNodeAnnotations();

			QueryInfo[] qis = this.BuildQuery(ResultShape.Sequence, TypeSystem.GetSequenceType(elementType), query, parameters, annotations);
			System.Diagnostics.Debug.Assert(qis.Length == 1);
			QueryInfo qi = qis[0];
			ICompiledSubQuery[] subQueries = this.CompileSubQueries(qi.Query);
			IObjectReaderFactory factory = this.GetReaderFactory(qi.Query, elementType);

			CheckSqlCompatibility(qis, annotations);

			return new CompiledSubQuery(qi, factory, parameters, subQueries);
		}
Beispiel #17
0
		internal static SqlNode Reduce(SqlNode node, SqlNodeAnnotations annotations, NodeFactory sql)
		{
			return new Visitor(annotations, sql).Visit(node);
		}
Beispiel #18
0
		string IProvider.GetQueryText(Expression query)
		{
			this.CheckDispose();
			this.CheckInitialized();
			if(query == null)
			{
				throw Error.ArgumentNull("query");
			}
			this.InitializeProviderMode();
			SqlNodeAnnotations annotations = new SqlNodeAnnotations();
			QueryInfo[] qis = this.BuildQuery(query, annotations);

			StringBuilder sb = new StringBuilder();
			for(int i = 0, n = qis.Length; i < n; i++)
			{
				QueryInfo qi = qis[i];
#if DEBUG
				StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture);
				DbCommand cmd = _conManager.Connection.CreateCommand();
				cmd.CommandText = qi.CommandText;
				AssignParameters(cmd, qi.Parameters, null, null);
				LogCommand(writer, cmd);
				sb.Append(writer.ToString());
#else
                sb.Append(qi.CommandText);
                sb.AppendLine();
#endif
			}
			return sb.ToString();
		}
		internal SqlParameterizer(TypeSystemProvider typeProvider, SqlNodeAnnotations annotations)
		{
			this._typeProvider = typeProvider;
			this._annotations = annotations;
		}
		internal static SqlNode Reduce(SqlNode node, SqlNodeAnnotations annotations, Enum[] providerModesWithIncompatibilities)
		{
			Reducer r = new Reducer(providerModesWithIncompatibilities) {Annotations = annotations};
			return r.Visit(node);
		}
		internal SqlNode AddConversions(SqlNode node, SqlNodeAnnotations annotations)
		{
			visitor.Annotations = annotations;
			return visitor.Visit(node);
		}