You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Data.Linq.SqlClient {
|
||||
internal abstract class DbFormatter {
|
||||
internal abstract string Format(SqlNode node, bool isDebug);
|
||||
internal abstract string Format(SqlNode node);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq.Expressions;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Data.Linq;
|
||||
|
||||
namespace System.Data.Linq.SqlClient {
|
||||
|
||||
// SQL Client extensions to ExpressionType
|
||||
internal enum InternalExpressionType {
|
||||
Known = 2000,
|
||||
LinkedTable = 2001
|
||||
}
|
||||
|
||||
abstract internal class InternalExpression : Expression {
|
||||
#pragma warning disable 618 // Disable the 'obsolete' warning.
|
||||
internal InternalExpression(InternalExpressionType nt, Type type)
|
||||
: base ((ExpressionType)nt, type) {
|
||||
}
|
||||
#pragma warning restore 618
|
||||
internal static KnownExpression Known(SqlExpression expr) {
|
||||
return new KnownExpression(expr, expr.ClrType);
|
||||
}
|
||||
internal static KnownExpression Known(SqlNode node, Type type) {
|
||||
return new KnownExpression(node, type);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class KnownExpression : InternalExpression {
|
||||
SqlNode node;
|
||||
internal KnownExpression(SqlNode node, Type type)
|
||||
: base(InternalExpressionType.Known, type) {
|
||||
this.node = node;
|
||||
}
|
||||
internal SqlNode Node {
|
||||
get { return this.node; }
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class LinkedTableExpression : InternalExpression {
|
||||
private SqlLink link;
|
||||
private ITable table;
|
||||
internal LinkedTableExpression(SqlLink link, ITable table, Type type)
|
||||
: base(InternalExpressionType.LinkedTable, type) {
|
||||
this.link = link;
|
||||
this.table = table;
|
||||
}
|
||||
internal SqlLink Link {
|
||||
get {return this.link;}
|
||||
}
|
||||
internal ITable Table {
|
||||
get {return this.table;}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
|
||||
namespace System.Data.Linq.SqlClient {
|
||||
|
||||
internal interface IConnectionManager {
|
||||
DbConnection UseConnection(IConnectionUser user);
|
||||
void ReleaseConnection(IConnectionUser user);
|
||||
}
|
||||
|
||||
internal interface IConnectionUser {
|
||||
void CompleteUse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Data.Linq.Mapping;
|
||||
using System.Data.Linq.Provider;
|
||||
|
||||
namespace System.Data.Linq.SqlClient {
|
||||
/// <summary>
|
||||
/// This class defines the rules for inheritance behaviors. The rules:
|
||||
///
|
||||
/// (1) The same field may not be mapped to different database columns.
|
||||
/// The DistinguishedMemberName and AreSameMember methods describe what 'same' means between two MemberInfos.
|
||||
/// (2) Discriminators held in fixed-length fields in the database don't need
|
||||
/// to be manually padded in inheritance mapping [InheritanceMapping(Code='x')].
|
||||
///
|
||||
/// </summary>
|
||||
static class InheritanceRules {
|
||||
/// <summary>
|
||||
/// Creates a name that is the same when the member should be considered 'same'
|
||||
/// for the purposes of the inheritance feature.
|
||||
/// </summary>
|
||||
internal static object DistinguishedMemberName(MemberInfo mi) {
|
||||
PropertyInfo pi = mi as PropertyInfo;
|
||||
FieldInfo fi = mi as FieldInfo;
|
||||
if (fi != null) {
|
||||
// Human readable variant:
|
||||
// return "fi:" + mi.Name + ":" + mi.DeclaringType;
|
||||
return new MetaPosition(mi);
|
||||
}
|
||||
else if (pi != null) {
|
||||
MethodInfo meth = null;
|
||||
|
||||
if (pi.CanRead) {
|
||||
meth = pi.GetGetMethod();
|
||||
}
|
||||
if (meth == null && pi.CanWrite) {
|
||||
meth = pi.GetSetMethod();
|
||||
}
|
||||
bool isVirtual = meth != null && meth.IsVirtual;
|
||||
|
||||
// Human readable variant:
|
||||
// return "pi:" + mi.Name + ":" + (isVirtual ? "virtual" : mi.DeclaringType.ToString());
|
||||
|
||||
if (isVirtual) {
|
||||
return mi.Name;
|
||||
} else {
|
||||
return new MetaPosition(mi);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw Error.ArgumentOutOfRange("mi");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares two MemberInfos for 'same-ness'.
|
||||
/// </summary>
|
||||
internal static bool AreSameMember(MemberInfo mi1, MemberInfo mi2) {
|
||||
return DistinguishedMemberName(mi1).Equals(DistinguishedMemberName(mi2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The representation of a inheritance code when mapped to a specific provider type.
|
||||
/// </summary>
|
||||
internal static object InheritanceCodeForClientCompare(object rawCode, System.Data.Linq.SqlClient.ProviderType providerType) {
|
||||
// If its a fixed-size string type in the store then pad it with spaces so that
|
||||
// comparing the string on the client agrees with the value returnd on the store.
|
||||
if (providerType.IsFixedSize && rawCode.GetType()==typeof(string)) {
|
||||
string s = (string) rawCode;
|
||||
if (providerType.Size.HasValue && s.Length!=providerType.Size) {
|
||||
s = s.PadRight(providerType.Size.Value).Substring(0,providerType.Size.Value);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
return rawCode;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Data.Linq.SqlClient {
|
||||
|
||||
/// <summary>
|
||||
/// Annotation about a particular SqlNode.
|
||||
/// </summary>
|
||||
internal abstract class SqlNodeAnnotation {
|
||||
string message;
|
||||
internal SqlNodeAnnotation(string message) {
|
||||
this.message = message;
|
||||
}
|
||||
internal string Message {
|
||||
get {return this.message;}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Data.Linq.SqlClient {
|
||||
|
||||
/// <summary>
|
||||
/// Associate annotations with SqlNodes.
|
||||
/// </summary>
|
||||
internal class SqlNodeAnnotations {
|
||||
Dictionary<SqlNode, List<SqlNodeAnnotation>> annotationMap = new Dictionary<SqlNode, List<SqlNodeAnnotation>>();
|
||||
Dictionary<Type, string> uniqueTypes = new Dictionary<Type, string>();
|
||||
|
||||
/// <summary>
|
||||
/// Add an annotation to the given node.
|
||||
/// </summary>
|
||||
internal void Add(SqlNode node, SqlNodeAnnotation annotation) {
|
||||
List<SqlNodeAnnotation> list = null;
|
||||
|
||||
if (!this.annotationMap.TryGetValue(node, out list)) {
|
||||
list = new List<SqlNodeAnnotation>();
|
||||
this.annotationMap[node]=list;
|
||||
}
|
||||
|
||||
uniqueTypes[annotation.GetType()] = String.Empty;
|
||||
|
||||
list.Add(annotation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the annotations for the given node. Null if none.
|
||||
/// </summary>
|
||||
internal List<SqlNodeAnnotation> Get(SqlNode node) {
|
||||
List<SqlNodeAnnotation> list = null;
|
||||
this.annotationMap.TryGetValue(node, out list);
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the given node has annotations.
|
||||
/// </summary>
|
||||
internal bool NodeIsAnnotated(SqlNode node) {
|
||||
if (node == null)
|
||||
return false;
|
||||
return this.annotationMap.ContainsKey(node);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether there's at least one annotation of the given type.
|
||||
/// </summary>
|
||||
internal bool HasAnnotationType(Type type) {
|
||||
return this.uniqueTypes.ContainsKey(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace System.Data.Linq.SqlClient {
|
||||
internal static class SqlNodeTypeOperators {
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the given unary operator node type returns a value that
|
||||
/// is predicate.
|
||||
/// </summary>
|
||||
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification="These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")]
|
||||
internal static bool IsPredicateUnaryOperator(this SqlNodeType nodeType) {
|
||||
switch (nodeType) {
|
||||
case SqlNodeType.Not:
|
||||
case SqlNodeType.Not2V:
|
||||
case SqlNodeType.IsNull:
|
||||
case SqlNodeType.IsNotNull:
|
||||
return true;
|
||||
case SqlNodeType.Negate:
|
||||
case SqlNodeType.BitNot:
|
||||
case SqlNodeType.Count:
|
||||
case SqlNodeType.LongCount:
|
||||
case SqlNodeType.Max:
|
||||
case SqlNodeType.Min:
|
||||
case SqlNodeType.Sum:
|
||||
case SqlNodeType.Avg:
|
||||
case SqlNodeType.Stddev:
|
||||
case SqlNodeType.Convert:
|
||||
case SqlNodeType.ValueOf:
|
||||
case SqlNodeType.OuterJoinedValue:
|
||||
case SqlNodeType.ClrLength:
|
||||
return false;
|
||||
default:
|
||||
throw Error.UnexpectedNode(nodeType);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the given unary operator expects a predicate as input.
|
||||
/// </summary>
|
||||
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification="These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")]
|
||||
internal static bool IsUnaryOperatorExpectingPredicateOperand(this SqlNodeType nodeType) {
|
||||
switch (nodeType) {
|
||||
case SqlNodeType.Not:
|
||||
case SqlNodeType.Not2V:
|
||||
return true;
|
||||
case SqlNodeType.IsNull:
|
||||
case SqlNodeType.IsNotNull:
|
||||
case SqlNodeType.Negate:
|
||||
case SqlNodeType.BitNot:
|
||||
case SqlNodeType.Count:
|
||||
case SqlNodeType.LongCount:
|
||||
case SqlNodeType.Max:
|
||||
case SqlNodeType.Min:
|
||||
case SqlNodeType.Sum:
|
||||
case SqlNodeType.Avg:
|
||||
case SqlNodeType.Stddev:
|
||||
case SqlNodeType.Convert:
|
||||
case SqlNodeType.ValueOf:
|
||||
case SqlNodeType.OuterJoinedValue:
|
||||
case SqlNodeType.ClrLength:
|
||||
return false;
|
||||
default:
|
||||
throw Error.UnexpectedNode(nodeType);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the given binary operator node type returns a value that
|
||||
/// is a predicate boolean.
|
||||
/// </summary>
|
||||
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification="These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")]
|
||||
internal static bool IsPredicateBinaryOperator(this SqlNodeType nodeType) {
|
||||
switch (nodeType) {
|
||||
case SqlNodeType.GE:
|
||||
case SqlNodeType.GT:
|
||||
case SqlNodeType.LE:
|
||||
case SqlNodeType.LT:
|
||||
case SqlNodeType.EQ:
|
||||
case SqlNodeType.NE:
|
||||
case SqlNodeType.EQ2V:
|
||||
case SqlNodeType.NE2V:
|
||||
case SqlNodeType.And:
|
||||
case SqlNodeType.Or:
|
||||
return true;
|
||||
case SqlNodeType.Add:
|
||||
case SqlNodeType.Sub:
|
||||
case SqlNodeType.Mul:
|
||||
case SqlNodeType.Div:
|
||||
case SqlNodeType.Mod:
|
||||
case SqlNodeType.BitAnd:
|
||||
case SqlNodeType.BitOr:
|
||||
case SqlNodeType.BitXor:
|
||||
case SqlNodeType.Concat:
|
||||
case SqlNodeType.Coalesce:
|
||||
return false;
|
||||
default:
|
||||
throw Error.UnexpectedNode(nodeType);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Determines whether this operator is a binary comparison operator (i.e. >, =>, ==, etc)
|
||||
/// </summary>
|
||||
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")]
|
||||
internal static bool IsComparisonOperator(this SqlNodeType nodeType)
|
||||
{
|
||||
switch (nodeType)
|
||||
{
|
||||
case SqlNodeType.GE:
|
||||
case SqlNodeType.GT:
|
||||
case SqlNodeType.LE:
|
||||
case SqlNodeType.LT:
|
||||
case SqlNodeType.EQ:
|
||||
case SqlNodeType.NE:
|
||||
case SqlNodeType.EQ2V:
|
||||
case SqlNodeType.NE2V:
|
||||
return true;
|
||||
case SqlNodeType.And:
|
||||
case SqlNodeType.Or:
|
||||
case SqlNodeType.Add:
|
||||
case SqlNodeType.Sub:
|
||||
case SqlNodeType.Mul:
|
||||
case SqlNodeType.Div:
|
||||
case SqlNodeType.Mod:
|
||||
case SqlNodeType.BitAnd:
|
||||
case SqlNodeType.BitOr:
|
||||
case SqlNodeType.BitXor:
|
||||
case SqlNodeType.Concat:
|
||||
case SqlNodeType.Coalesce:
|
||||
return false;
|
||||
default:
|
||||
throw Error.UnexpectedNode(nodeType);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the given binary operator node type returns a value that
|
||||
/// is a predicate boolean.
|
||||
/// </summary>
|
||||
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification="These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")]
|
||||
internal static bool IsBinaryOperatorExpectingPredicateOperands(this SqlNodeType nodeType) {
|
||||
switch (nodeType) {
|
||||
case SqlNodeType.And:
|
||||
case SqlNodeType.Or:
|
||||
return true;
|
||||
case SqlNodeType.EQ:
|
||||
case SqlNodeType.EQ2V:
|
||||
case SqlNodeType.GE:
|
||||
case SqlNodeType.GT:
|
||||
case SqlNodeType.LE:
|
||||
case SqlNodeType.LT:
|
||||
case SqlNodeType.NE:
|
||||
case SqlNodeType.NE2V:
|
||||
case SqlNodeType.Add:
|
||||
case SqlNodeType.Sub:
|
||||
case SqlNodeType.Mul:
|
||||
case SqlNodeType.Div:
|
||||
case SqlNodeType.Mod:
|
||||
case SqlNodeType.BitAnd:
|
||||
case SqlNodeType.BitOr:
|
||||
case SqlNodeType.BitXor:
|
||||
case SqlNodeType.Concat:
|
||||
case SqlNodeType.Coalesce:
|
||||
return false;
|
||||
default:
|
||||
throw Error.UnexpectedNode(nodeType);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the given node requires support on the client for evaluation.
|
||||
/// For example, LINK nodes may be delay-executed only when the user requests the result.
|
||||
/// </summary>
|
||||
internal static bool IsClientAidedExpression(this SqlExpression expr) {
|
||||
switch (expr.NodeType) {
|
||||
case SqlNodeType.Link:
|
||||
case SqlNodeType.Element:
|
||||
case SqlNodeType.Multiset:
|
||||
case SqlNodeType.ClientQuery:
|
||||
case SqlNodeType.TypeCase:
|
||||
case SqlNodeType.New:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Data.Linq.SqlClient {
|
||||
|
||||
/// <summary>
|
||||
/// Annotation which indicates that the given node will cause a compatibility problem
|
||||
/// for the indicated set of providers.
|
||||
/// </summary>
|
||||
internal class SqlServerCompatibilityAnnotation : SqlNodeAnnotation {
|
||||
SqlProvider.ProviderMode[] providers;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="message">The compatibility message.</param>
|
||||
/// <param name="providers">The set of providers this compatibility issue applies to.</param>
|
||||
internal SqlServerCompatibilityAnnotation(string message, params SqlProvider.ProviderMode[] providers)
|
||||
: base(message) {
|
||||
this.providers = providers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this annotation applies to the specified provider.
|
||||
/// </summary>
|
||||
internal bool AppliesTo(SqlProvider.ProviderMode provider) {
|
||||
foreach (SqlProvider.ProviderMode p in providers) {
|
||||
if (p == provider) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Data.Linq.SqlClient {
|
||||
|
||||
/// <summary>
|
||||
/// Methods for checking whethe a query was compatible with the
|
||||
/// server it will be sent to.
|
||||
/// </summary>
|
||||
static internal class SqlServerCompatibilityCheck {
|
||||
|
||||
/// <summary>
|
||||
/// Private visitor class checks each node for compatibility annotations.
|
||||
/// </summary>
|
||||
private class Visitor : SqlVisitor {
|
||||
|
||||
private SqlProvider.ProviderMode provider;
|
||||
internal SqlNodeAnnotations annotations;
|
||||
|
||||
internal Visitor(SqlProvider.ProviderMode provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The reasons why this query is not 2K compatible.
|
||||
/// </summary>
|
||||
internal Collection<string> reasons = new Collection<string>();
|
||||
|
||||
internal override SqlNode Visit(SqlNode node) {
|
||||
if (annotations.NodeIsAnnotated(node)) {
|
||||
foreach (SqlNodeAnnotation annotation in annotations.Get(node)) {
|
||||
SqlServerCompatibilityAnnotation ssca = annotation as SqlServerCompatibilityAnnotation;
|
||||
if (ssca != null && ssca.AppliesTo(provider)) {
|
||||
reasons.Add(annotation.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
return base.Visit(node);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the given node is supported on the given server.
|
||||
/// </summary>
|
||||
internal static void ThrowIfUnsupported(SqlNode node, SqlNodeAnnotations annotations, SqlProvider.ProviderMode provider) {
|
||||
// Check to see whether there's at least one SqlServerCompatibilityAnnotation.
|
||||
if (annotations.HasAnnotationType(typeof(SqlServerCompatibilityAnnotation))) {
|
||||
Visitor visitor = new Visitor(provider);
|
||||
visitor.annotations = annotations;
|
||||
visitor.Visit(node);
|
||||
|
||||
// If any messages were recorded, then throw an exception.
|
||||
if (visitor.reasons.Count > 0) {
|
||||
throw Error.ExpressionNotSupportedForSqlServerVersion(visitor.reasons);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,302 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using System.Collections;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Linq;
|
||||
|
||||
namespace System.Data.Linq.SqlClient {
|
||||
internal static class TypeSystem {
|
||||
|
||||
internal static bool IsSequenceType(Type seqType) {
|
||||
return seqType != typeof(string)
|
||||
&& seqType != typeof(byte[])
|
||||
&& seqType != typeof(char[])
|
||||
&& FindIEnumerable(seqType) != null;
|
||||
}
|
||||
internal static bool HasIEnumerable(Type seqType) {
|
||||
return FindIEnumerable(seqType) != null;
|
||||
}
|
||||
private static Type FindIEnumerable(Type seqType) {
|
||||
if (seqType == null || seqType == typeof(string))
|
||||
return null;
|
||||
if (seqType.IsArray)
|
||||
return typeof(IEnumerable<>).MakeGenericType(seqType.GetElementType());
|
||||
if (seqType.IsGenericType) {
|
||||
foreach (Type arg in seqType.GetGenericArguments()) {
|
||||
Type ienum = typeof(IEnumerable<>).MakeGenericType(arg);
|
||||
if (ienum.IsAssignableFrom(seqType)) {
|
||||
return ienum;
|
||||
}
|
||||
}
|
||||
}
|
||||
Type[] ifaces = seqType.GetInterfaces();
|
||||
if (ifaces != null && ifaces.Length > 0) {
|
||||
foreach (Type iface in ifaces) {
|
||||
Type ienum = FindIEnumerable(iface);
|
||||
if (ienum != null) return ienum;
|
||||
}
|
||||
}
|
||||
if (seqType.BaseType != null && seqType.BaseType != typeof(object)) {
|
||||
return FindIEnumerable(seqType.BaseType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
internal static Type GetFlatSequenceType(Type elementType) {
|
||||
Type ienum = FindIEnumerable(elementType);
|
||||
if (ienum != null) return ienum;
|
||||
return typeof(IEnumerable<>).MakeGenericType(elementType);
|
||||
}
|
||||
internal static Type GetSequenceType(Type elementType) {
|
||||
return typeof(IEnumerable<>).MakeGenericType(elementType);
|
||||
}
|
||||
internal static Type GetElementType(Type seqType) {
|
||||
Type ienum = FindIEnumerable(seqType);
|
||||
if (ienum == null) return seqType;
|
||||
return ienum.GetGenericArguments()[0];
|
||||
}
|
||||
internal static bool IsNullableType(Type type) {
|
||||
return type != null && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
|
||||
}
|
||||
internal static bool IsNullAssignable(Type type) {
|
||||
return !type.IsValueType || IsNullableType(type);
|
||||
}
|
||||
internal static Type GetNonNullableType(Type type) {
|
||||
if (IsNullableType(type)) {
|
||||
return type.GetGenericArguments()[0];
|
||||
}
|
||||
return type;
|
||||
}
|
||||
internal static Type GetMemberType(MemberInfo mi) {
|
||||
FieldInfo fi = mi as FieldInfo;
|
||||
if (fi != null) return fi.FieldType;
|
||||
PropertyInfo pi = mi as PropertyInfo;
|
||||
if (pi != null) return pi.PropertyType;
|
||||
EventInfo ei = mi as EventInfo;
|
||||
if (ei != null) return ei.EventHandlerType;
|
||||
return null;
|
||||
}
|
||||
internal static IEnumerable<FieldInfo> GetAllFields(Type type, BindingFlags flags) {
|
||||
Dictionary<MetaPosition, FieldInfo> seen = new Dictionary<MetaPosition, FieldInfo>();
|
||||
Type currentType = type;
|
||||
do {
|
||||
foreach (FieldInfo fi in currentType.GetFields(flags)) {
|
||||
if (fi.IsPrivate || type == currentType) {
|
||||
MetaPosition mp = new MetaPosition(fi);
|
||||
seen[mp] = fi;
|
||||
}
|
||||
}
|
||||
currentType = currentType.BaseType;
|
||||
} while (currentType != null);
|
||||
return seen.Values;
|
||||
}
|
||||
internal static IEnumerable<PropertyInfo> GetAllProperties(Type type, BindingFlags flags) {
|
||||
Dictionary<MetaPosition, PropertyInfo> seen = new Dictionary<MetaPosition, PropertyInfo>();
|
||||
Type currentType = type;
|
||||
do {
|
||||
foreach (PropertyInfo pi in currentType.GetProperties(flags)) {
|
||||
if (type == currentType || IsPrivate(pi)) {
|
||||
MetaPosition mp = new MetaPosition(pi);
|
||||
seen[mp] = pi;
|
||||
}
|
||||
}
|
||||
currentType = currentType.BaseType;
|
||||
} while (currentType != null);
|
||||
return seen.Values;
|
||||
}
|
||||
|
||||
private static bool IsPrivate(PropertyInfo pi) {
|
||||
MethodInfo mi = pi.GetGetMethod() ?? pi.GetSetMethod();
|
||||
if (mi != null) {
|
||||
return mi.IsPrivate;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static ILookup<string, MethodInfo> _sequenceMethods;
|
||||
internal static MethodInfo FindSequenceMethod(string name, Type[] args, params Type[] typeArgs) {
|
||||
if (_sequenceMethods == null) {
|
||||
_sequenceMethods = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).ToLookup(m => m.Name);
|
||||
}
|
||||
MethodInfo mi = _sequenceMethods[name].FirstOrDefault(m => ArgsMatchExact(m, args, typeArgs));
|
||||
if (mi == null)
|
||||
return null;
|
||||
if (typeArgs != null)
|
||||
return mi.MakeGenericMethod(typeArgs);
|
||||
return mi;
|
||||
}
|
||||
internal static MethodInfo FindSequenceMethod(string name, IEnumerable sequence) {
|
||||
return FindSequenceMethod(name, new Type[] {sequence.GetType()}, new Type[] {GetElementType(sequence.GetType())});
|
||||
}
|
||||
|
||||
private static ILookup<string, MethodInfo> _queryMethods;
|
||||
internal static MethodInfo FindQueryableMethod(string name, Type[] args, params Type[] typeArgs) {
|
||||
if (_queryMethods == null) {
|
||||
_queryMethods = typeof(Queryable).GetMethods(BindingFlags.Static | BindingFlags.Public).ToLookup(m => m.Name);
|
||||
}
|
||||
MethodInfo mi = _queryMethods[name].FirstOrDefault(m => ArgsMatchExact(m, args, typeArgs));
|
||||
if (mi == null)
|
||||
throw Error.NoMethodInTypeMatchingArguments(typeof(Queryable));
|
||||
if (typeArgs != null)
|
||||
return mi.MakeGenericMethod(typeArgs);
|
||||
return mi;
|
||||
}
|
||||
|
||||
internal static MethodInfo FindStaticMethod(Type type, string name, Type[] args, params Type[] typeArgs) {
|
||||
MethodInfo mi = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
|
||||
.FirstOrDefault(m => m.Name == name && ArgsMatchExact(m, args, typeArgs));
|
||||
if (mi == null)
|
||||
throw Error.NoMethodInTypeMatchingArguments(type);
|
||||
if (typeArgs != null)
|
||||
return mi.MakeGenericMethod(typeArgs);
|
||||
return mi;
|
||||
}
|
||||
|
||||
private static bool ArgsMatchExact(MethodInfo m, Type[] argTypes, Type[] typeArgs) {
|
||||
ParameterInfo[] mParams = m.GetParameters();
|
||||
if (mParams.Length != argTypes.Length)
|
||||
return false;
|
||||
if (!m.IsGenericMethodDefinition && m.IsGenericMethod && m.ContainsGenericParameters) {
|
||||
m = m.GetGenericMethodDefinition();
|
||||
}
|
||||
if (m.IsGenericMethodDefinition) {
|
||||
if (typeArgs == null || typeArgs.Length == 0)
|
||||
return false;
|
||||
if (m.GetGenericArguments().Length != typeArgs.Length)
|
||||
return false;
|
||||
m = m.MakeGenericMethod(typeArgs);
|
||||
mParams = m.GetParameters();
|
||||
}
|
||||
else if (typeArgs != null && typeArgs.Length > 0) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0, n = argTypes.Length; i < n; i++) {
|
||||
Type parameterType = mParams[i].ParameterType;
|
||||
if (parameterType == null)
|
||||
return false;
|
||||
Type argType = argTypes[i];
|
||||
if (!parameterType.IsAssignableFrom(argType))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the type is one of the built in simple types.
|
||||
/// </summary>
|
||||
internal static bool IsSimpleType(Type type)
|
||||
{
|
||||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||
type = type.GetGenericArguments()[0];
|
||||
|
||||
if (type.IsEnum)
|
||||
return true;
|
||||
|
||||
if (type == typeof(Guid))
|
||||
return true;
|
||||
|
||||
TypeCode tc = Type.GetTypeCode(type);
|
||||
switch (tc)
|
||||
{
|
||||
case TypeCode.Byte:
|
||||
case TypeCode.SByte:
|
||||
case TypeCode.Int16:
|
||||
case TypeCode.Int32:
|
||||
case TypeCode.Int64:
|
||||
case TypeCode.UInt16:
|
||||
case TypeCode.UInt32:
|
||||
case TypeCode.UInt64:
|
||||
case TypeCode.Single:
|
||||
case TypeCode.Double:
|
||||
case TypeCode.Decimal:
|
||||
case TypeCode.Char:
|
||||
case TypeCode.String:
|
||||
case TypeCode.Boolean:
|
||||
case TypeCode.DateTime:
|
||||
return true;
|
||||
case TypeCode.Object:
|
||||
return (typeof(TimeSpan) == type) || (typeof(DateTimeOffset) == type);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hashable MetaDataToken+Assembly. This type uniquely describes a metadata element
|
||||
/// like a MemberInfo. MetaDataToken by itself is not sufficient because its only
|
||||
/// unique within a single assembly.
|
||||
/// </summary>
|
||||
internal struct MetaPosition : IEqualityComparer<MetaPosition>, IEqualityComparer {
|
||||
private int metadataToken;
|
||||
private Assembly assembly;
|
||||
internal MetaPosition(MemberInfo mi)
|
||||
: this(mi.DeclaringType.Assembly, mi.MetadataToken) {
|
||||
}
|
||||
private MetaPosition(Assembly assembly, int metadataToken) {
|
||||
this.assembly = assembly;
|
||||
this.metadataToken = metadataToken;
|
||||
}
|
||||
|
||||
// Equality is implemented here according to the advice in
|
||||
// CLR via C# 2ed, J. Richter, p 146. In particular, ValueType.Equals
|
||||
// should not be called for perf reasons.
|
||||
|
||||
#region Object Members
|
||||
public override bool Equals(object obj) {
|
||||
if (obj == null)
|
||||
return false;
|
||||
|
||||
if (obj.GetType() != this.GetType())
|
||||
return false;
|
||||
|
||||
return AreEqual(this, (MetaPosition)obj);
|
||||
}
|
||||
public override int GetHashCode() {
|
||||
return metadataToken;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEqualityComparer<MetaPosition> Members
|
||||
public bool Equals(MetaPosition x, MetaPosition y) {
|
||||
return AreEqual(x, y);
|
||||
}
|
||||
|
||||
public int GetHashCode(MetaPosition obj) {
|
||||
return obj.metadataToken;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEqualityComparer Members
|
||||
bool IEqualityComparer.Equals(object x, object y) {
|
||||
return this.Equals((MetaPosition)x, (MetaPosition)y);
|
||||
}
|
||||
int IEqualityComparer.GetHashCode(object obj) {
|
||||
return this.GetHashCode((MetaPosition) obj);
|
||||
}
|
||||
#endregion
|
||||
|
||||
private static bool AreEqual(MetaPosition x, MetaPosition y) {
|
||||
return (x.metadataToken == y.metadataToken)
|
||||
&& (x.assembly == y.assembly);
|
||||
}
|
||||
|
||||
// Since MetaPositions are immutable, we overload the equality operator
|
||||
// to test for value equality, rather than reference equality
|
||||
public static bool operator==(MetaPosition x, MetaPosition y) {
|
||||
return AreEqual(x, y);
|
||||
}
|
||||
public static bool operator !=(MetaPosition x, MetaPosition y) {
|
||||
return !AreEqual(x, y);
|
||||
}
|
||||
|
||||
internal static bool AreSameMember(MemberInfo x, MemberInfo y) {
|
||||
if (x.MetadataToken != y.MetadataToken || x.DeclaringType.Assembly != y.DeclaringType.Assembly) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Data.Linq.SqlClient {
|
||||
|
||||
/// <summary>
|
||||
/// Abstracts the provider side type system. Encapsulates:
|
||||
/// - Mapping from runtime types to provider types.
|
||||
/// - Parsing type strings in the provider's language.
|
||||
/// - Handling application defined (opaque) types.
|
||||
/// - Type coercion precedence rules.
|
||||
/// - Type family organization.
|
||||
/// </summary>
|
||||
internal abstract class TypeSystemProvider {
|
||||
|
||||
internal abstract ProviderType PredictTypeForUnary(SqlNodeType unaryOp, ProviderType operandType);
|
||||
|
||||
internal abstract ProviderType PredictTypeForBinary(SqlNodeType binaryOp, ProviderType leftType, ProviderType rightType);
|
||||
|
||||
/// <summary>
|
||||
/// Return the provider type corresponding to the given clr type.
|
||||
/// </summary>
|
||||
internal abstract ProviderType From(Type runtimeType);
|
||||
|
||||
/// <summary>
|
||||
/// Return the provider type corresponding to the given object instance.
|
||||
/// </summary>
|
||||
internal abstract ProviderType From(object o);
|
||||
|
||||
/// <summary>
|
||||
/// Return the provider type corresponding to the given clr type and size.
|
||||
/// </summary>
|
||||
internal abstract ProviderType From(Type type, int? size);
|
||||
|
||||
/// <summary>
|
||||
/// Return a type by parsing a string. The format of the string is
|
||||
/// provider specific.
|
||||
/// </summary>
|
||||
internal abstract ProviderType Parse(string text);
|
||||
|
||||
/// <summary>
|
||||
/// Return a type understood only by the application.
|
||||
/// Each call with the same index will return the same ProviderType.
|
||||
/// </summary>
|
||||
internal abstract ProviderType GetApplicationType(int index);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the most precise type in the family of the type given.
|
||||
/// A family is a group types that serve similar functions. For example,
|
||||
/// in SQL SmallInt and Int are part of one family.
|
||||
/// </summary>
|
||||
internal abstract ProviderType MostPreciseTypeInFamily(ProviderType type);
|
||||
|
||||
/// <summary>
|
||||
/// For LOB data types that have large type equivalents, this function returns the equivalent large
|
||||
/// data type. If the type is not an LOB or cannot be converted, the function returns the current type.
|
||||
/// For example SqlServer defines the 'Image' LOB type, whose large type equivalent is VarBinary(MAX).
|
||||
/// </summary>
|
||||
internal abstract ProviderType GetBestLargeType(ProviderType type);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a type that can be used to hold values for both the current
|
||||
/// type and the specified type without data loss.
|
||||
/// </summary>
|
||||
internal abstract ProviderType GetBestType(ProviderType typeA, ProviderType typeB);
|
||||
|
||||
internal abstract ProviderType ReturnTypeOfFunction(SqlFunctionCall functionCall);
|
||||
|
||||
/// <summary>
|
||||
/// Get a type that can hold the same information but belongs to a different type family.
|
||||
/// For example, to represent a SQL NChar as an integer type, we need to use the type int.
|
||||
/// (SQL smallint would not be able to contain characters with unicode >32768)
|
||||
/// </summary>
|
||||
/// <param name="toType">Type of the target type family</param>
|
||||
/// <returns>Smallest type of target type family that can hold equivalent information</returns>
|
||||
internal abstract ProviderType ChangeTypeFamilyTo(ProviderType type, ProviderType typeWithFamily);
|
||||
|
||||
internal abstract void InitializeParameter(ProviderType type, System.Data.Common.DbParameter parameter, object value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flags control the format of string returned by ToQueryString().
|
||||
/// </summary>
|
||||
[Flags]
|
||||
internal enum QueryFormatOptions {
|
||||
None = 0,
|
||||
SuppressSize = 1
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An abstract type exposed by the TypeSystemProvider.
|
||||
/// </summary>
|
||||
internal abstract class ProviderType {
|
||||
|
||||
/// <summary>
|
||||
/// True if this type is a Unicode type (eg, ntext, etc).
|
||||
/// </summary>
|
||||
internal abstract bool IsUnicodeType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// For a unicode type, return it's non-unicode equivalent.
|
||||
/// </summary>
|
||||
internal abstract ProviderType GetNonUnicodeEquivalent();
|
||||
|
||||
/// <summary>
|
||||
/// True if this type has only a CLR representation and no provider representation.
|
||||
/// </summary>
|
||||
internal abstract bool IsRuntimeOnlyType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// True if this type is an application defined type.
|
||||
/// </summary>
|
||||
internal abstract bool IsApplicationType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether this is the given application type.
|
||||
/// </summary>
|
||||
internal abstract bool IsApplicationTypeOf(int index);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the CLR type which most closely corresponds to this provider type.
|
||||
/// </summary>
|
||||
internal abstract Type GetClosestRuntimeType();
|
||||
|
||||
/// <summary>
|
||||
/// Compare implicit type coercion precedence.
|
||||
/// -1 means there is an implicit conversion from this->type.
|
||||
/// 0 means there is a two way implicit conversion from this->type
|
||||
/// 1 means there is an implicit conversion from type->this.
|
||||
/// </summary>
|
||||
internal abstract int ComparePrecedenceTo(ProviderType type);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether two types are in the same type family.
|
||||
/// A family is a group types that serve similar functions. For example,
|
||||
/// in SQL SmallInt and Int are part of one family.
|
||||
/// </summary>
|
||||
internal abstract bool IsSameTypeFamily(ProviderType type);
|
||||
|
||||
/// <summary>
|
||||
/// Used to indicate if the type supports comparison in provider.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if type supports comparison in provider.</returns>
|
||||
internal abstract bool SupportsComparison { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to indicate if the types supports Length function (LEN in T-SQL).
|
||||
/// </summary>
|
||||
/// <returns>Returns true if type supports use of length function on the type.</returns>
|
||||
internal abstract bool SupportsLength { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given values will be equal to eachother for this type.
|
||||
/// </summary>
|
||||
internal abstract bool AreValuesEqual(object o1, object o2);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this type is a LOB (large object) type, or an equivalent type.
|
||||
/// For example, on SqlServer, Image and VarChar(MAX) among others are considered large types.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal abstract bool IsLargeType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Convert this type into a string that can be used in a query.
|
||||
/// </summary>
|
||||
internal abstract string ToQueryString();
|
||||
|
||||
/// <summary>
|
||||
/// Convert this type into a string that can be used in a query.
|
||||
/// </summary>
|
||||
internal abstract string ToQueryString(QueryFormatOptions formatOptions);
|
||||
|
||||
/// <summary>
|
||||
/// Whether this type is fixed size or not.
|
||||
/// </summary>
|
||||
internal abstract bool IsFixedSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The type has a size or is large.
|
||||
/// </summary>
|
||||
internal abstract bool HasSizeOrIsLarge { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The size of this type.
|
||||
/// </summary>
|
||||
internal abstract int? Size { get; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the type can be ordered.
|
||||
/// </summary>
|
||||
internal abstract bool IsOrderable { get; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the type can be grouped.
|
||||
/// </summary>
|
||||
internal abstract bool IsGroupable { get; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the type can appear in a column
|
||||
/// </summary>
|
||||
internal abstract bool CanBeColumn { get; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the type can appear as a parameter
|
||||
/// </summary>
|
||||
internal abstract bool CanBeParameter { get; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the type is a single character type.
|
||||
/// </summary>
|
||||
internal abstract bool IsChar { get; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the type is a multi-character type.
|
||||
/// </summary>
|
||||
internal abstract bool IsString { get; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the type is a number.
|
||||
/// </summary>
|
||||
internal abstract bool IsNumeric { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the type uses precision and scale. For example, returns true
|
||||
/// for SqlDBTypes Decimal, Float and Real.
|
||||
/// </summary>
|
||||
internal abstract bool HasPrecisionAndScale { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines if it is safe to suppress size specifications for
|
||||
/// the operand of a cast/convert. For example, when casting to string,
|
||||
/// all these types have length less than the default sized used by SqlServer,
|
||||
/// so the length specification can be omitted without fear of truncation.
|
||||
/// </summary>
|
||||
internal abstract bool CanSuppressSizeForConversionToString{ get; }
|
||||
|
||||
public static bool operator ==(ProviderType typeA, ProviderType typeB) {
|
||||
if ((object)typeA == (object)typeB)
|
||||
return true;
|
||||
if ((object)typeA != null)
|
||||
return typeA.Equals(typeB);
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool operator != (ProviderType typeA, ProviderType typeB) {
|
||||
if ((object)typeA == (object)typeB)
|
||||
return false;
|
||||
if ((object)typeA != null)
|
||||
return !typeA.Equals(typeB);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj) {
|
||||
return base.Equals(obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode() {
|
||||
return base.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user