1 using System;
2 using System.Collections.ObjectModel;
3 using System.Text;
4 
5 namespace System.Data.Linq.SqlClient {
6 
7     /// <summary>
8     /// Methods for checking whethe a query was compatible with the
9     /// server it will be sent to.
10     /// </summary>
11     static internal class SqlServerCompatibilityCheck {
12 
13         /// <summary>
14         /// Private visitor class checks each node for compatibility annotations.
15         /// </summary>
16         private class Visitor : SqlVisitor {
17 
18             private SqlProvider.ProviderMode provider;
19             internal SqlNodeAnnotations annotations;
20 
Visitor(SqlProvider.ProviderMode provider)21             internal Visitor(SqlProvider.ProviderMode provider) {
22                 this.provider = provider;
23             }
24 
25             /// <summary>
26             /// The reasons why this query is not 2K compatible.
27             /// </summary>
28             internal Collection<string> reasons = new Collection<string>();
29 
Visit(SqlNode node)30             internal override SqlNode Visit(SqlNode node) {
31                 if (annotations.NodeIsAnnotated(node)) {
32                     foreach (SqlNodeAnnotation annotation in annotations.Get(node)) {
33                         SqlServerCompatibilityAnnotation ssca = annotation as SqlServerCompatibilityAnnotation;
34                         if (ssca != null && ssca.AppliesTo(provider)) {
35                             reasons.Add(annotation.Message);
36                         }
37                     }
38                 }
39                 return base.Visit(node);
40             }
41         }
42 
43         /// <summary>
44         /// Checks whether the given node is supported on the given server.
45         /// </summary>
ThrowIfUnsupported(SqlNode node, SqlNodeAnnotations annotations, SqlProvider.ProviderMode provider)46         internal static void ThrowIfUnsupported(SqlNode node, SqlNodeAnnotations annotations, SqlProvider.ProviderMode provider) {
47             // Check to see whether there's at least one SqlServerCompatibilityAnnotation.
48             if (annotations.HasAnnotationType(typeof(SqlServerCompatibilityAnnotation))) {
49                 Visitor visitor = new Visitor(provider);
50                 visitor.annotations = annotations;
51                 visitor.Visit(node);
52 
53                 // If any messages were recorded, then throw an exception.
54                 if (visitor.reasons.Count > 0) {
55                     throw Error.ExpressionNotSupportedForSqlServerVersion(visitor.reasons);
56                 }
57             }
58         }
59     }
60 }
61