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,185 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Data.Linq;
|
||||
using System.Data.Linq.Mapping;
|
||||
using System.Data.Linq.Provider;
|
||||
using System.Linq;
|
||||
using System.Data.Linq.SqlClient;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace System.Data.Linq.SqlClient {
|
||||
|
||||
// partions select expressions and common subexpressions into scalar and non-scalar pieces by
|
||||
// wrapping scalar pieces floating column nodes.
|
||||
internal class SqlColumnizer {
|
||||
ColumnNominator nominator;
|
||||
ColumnDeclarer declarer;
|
||||
|
||||
internal SqlColumnizer() {
|
||||
this.nominator = new ColumnNominator();
|
||||
this.declarer = new ColumnDeclarer();
|
||||
}
|
||||
|
||||
internal SqlExpression ColumnizeSelection(SqlExpression selection) {
|
||||
return this.declarer.Declare(selection, this.nominator.Nominate(selection));
|
||||
}
|
||||
|
||||
internal static bool CanBeColumn(SqlExpression expression) {
|
||||
return ColumnNominator.CanBeColumn(expression);
|
||||
}
|
||||
|
||||
class ColumnDeclarer : SqlVisitor {
|
||||
HashSet<SqlExpression> candidates;
|
||||
|
||||
internal ColumnDeclarer() {
|
||||
}
|
||||
|
||||
internal SqlExpression Declare(SqlExpression expression, HashSet<SqlExpression> candidates) {
|
||||
this.candidates = candidates;
|
||||
return (SqlExpression)this.Visit(expression);
|
||||
}
|
||||
|
||||
internal override SqlNode Visit(SqlNode node) {
|
||||
SqlExpression expr = node as SqlExpression;
|
||||
if (expr != null) {
|
||||
if (this.candidates.Contains(expr)) {
|
||||
if (expr.NodeType == SqlNodeType.Column ||
|
||||
expr.NodeType == SqlNodeType.ColumnRef) {
|
||||
return expr;
|
||||
}
|
||||
else {
|
||||
return new SqlColumn(expr.ClrType, expr.SqlType, null, null, expr, expr.SourceExpression);
|
||||
}
|
||||
}
|
||||
}
|
||||
return base.Visit(node);
|
||||
}
|
||||
}
|
||||
|
||||
class ColumnNominator : SqlVisitor {
|
||||
bool isBlocked;
|
||||
HashSet<SqlExpression> candidates;
|
||||
|
||||
internal HashSet<SqlExpression> Nominate(SqlExpression expression) {
|
||||
this.candidates = new HashSet<SqlExpression>();
|
||||
this.isBlocked = false;
|
||||
this.Visit(expression);
|
||||
return this.candidates;
|
||||
}
|
||||
|
||||
internal override SqlNode Visit(SqlNode node) {
|
||||
SqlExpression expression = node as SqlExpression;
|
||||
if (expression != null) {
|
||||
bool saveIsBlocked = this.isBlocked;
|
||||
this.isBlocked = false;
|
||||
if (CanRecurseColumnize(expression)) {
|
||||
base.Visit(expression);
|
||||
}
|
||||
if (!this.isBlocked) {
|
||||
if (CanBeColumn(expression)) {
|
||||
this.candidates.Add(expression);
|
||||
}
|
||||
else {
|
||||
this.isBlocked = true;
|
||||
}
|
||||
}
|
||||
this.isBlocked |= saveIsBlocked;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
internal override SqlExpression VisitSimpleCase(SqlSimpleCase c) {
|
||||
c.Expression = this.VisitExpression(c.Expression);
|
||||
for (int i = 0, n = c.Whens.Count; i < n; i++) {
|
||||
// Don't walk down the match side. This can't be a column.
|
||||
c.Whens[i].Value = this.VisitExpression(c.Whens[i].Value);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
internal override SqlExpression VisitTypeCase(SqlTypeCase tc) {
|
||||
tc.Discriminator = this.VisitExpression(tc.Discriminator);
|
||||
for (int i = 0, n = tc.Whens.Count; i < n; i++) {
|
||||
// Don't walk down the match side. This can't be a column.
|
||||
tc.Whens[i].TypeBinding = this.VisitExpression(tc.Whens[i].TypeBinding);
|
||||
}
|
||||
return tc;
|
||||
}
|
||||
|
||||
internal override SqlExpression VisitClientCase(SqlClientCase c) {
|
||||
c.Expression = this.VisitExpression(c.Expression);
|
||||
for (int i = 0, n = c.Whens.Count; i < n; i++) {
|
||||
// Don't walk down the match side. This can't be a column.
|
||||
c.Whens[i].Value = this.VisitExpression(c.Whens[i].Value);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private static bool CanRecurseColumnize(SqlExpression expr) {
|
||||
switch (expr.NodeType) {
|
||||
case SqlNodeType.AliasRef:
|
||||
case SqlNodeType.ColumnRef:
|
||||
case SqlNodeType.Column:
|
||||
case SqlNodeType.Multiset:
|
||||
case SqlNodeType.Element:
|
||||
case SqlNodeType.ScalarSubSelect:
|
||||
case SqlNodeType.Exists:
|
||||
case SqlNodeType.ClientQuery:
|
||||
case SqlNodeType.SharedExpressionRef:
|
||||
case SqlNodeType.Link:
|
||||
case SqlNodeType.Nop:
|
||||
case SqlNodeType.Value:
|
||||
case SqlNodeType.Select:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[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.")]
|
||||
private static bool IsClientOnly(SqlExpression expr) {
|
||||
switch (expr.NodeType) {
|
||||
case SqlNodeType.ClientCase:
|
||||
case SqlNodeType.TypeCase:
|
||||
case SqlNodeType.ClientArray:
|
||||
case SqlNodeType.Grouping:
|
||||
case SqlNodeType.DiscriminatedType:
|
||||
case SqlNodeType.SharedExpression:
|
||||
case SqlNodeType.SimpleExpression:
|
||||
case SqlNodeType.AliasRef:
|
||||
case SqlNodeType.Multiset:
|
||||
case SqlNodeType.Element:
|
||||
case SqlNodeType.ClientQuery:
|
||||
case SqlNodeType.SharedExpressionRef:
|
||||
case SqlNodeType.Link:
|
||||
case SqlNodeType.Nop:
|
||||
return true;
|
||||
case SqlNodeType.OuterJoinedValue:
|
||||
return IsClientOnly(((SqlUnary)expr).Operand);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool CanBeColumn(SqlExpression expression) {
|
||||
if (!IsClientOnly(expression)
|
||||
&& expression.NodeType != SqlNodeType.Column
|
||||
&& expression.SqlType.CanBeColumn) {
|
||||
|
||||
switch (expression.NodeType) {
|
||||
case SqlNodeType.MethodCall:
|
||||
case SqlNodeType.Member:
|
||||
case SqlNodeType.New:
|
||||
return PostBindDotNetConverter.CanConvert(expression);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user