in System.Data.Entity/System/Data/Common/EntitySql/SemanticAnalyzer.cs [4371:5196]
private static Dictionary<AST.BuiltInKind, BuiltInExprConverter> CreateBuiltInExprConverter()
{
Dictionary<AST.BuiltInKind, BuiltInExprConverter> builtInExprConverter = new Dictionary<AST.BuiltInKind, BuiltInExprConverter>(sizeof(AST.BuiltInKind));
////////////////////////////
// Arithmetic Expressions
////////////////////////////
//
// e1 + e2
//
#region e1 + e2
builtInExprConverter.Add(AST.BuiltInKind.Plus, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertPlusOperands(bltInExpr, sr);
if (TypeSemantics.IsNumericType(args.Left.ResultType))
{
return args.Left.Plus(args.Right);
}
else
{
//
// fold '+' operator into concat canonical function
//
MetadataFunctionGroup function;
if (!sr.TypeResolver.TryGetFunctionFromMetadata("Edm", "Concat", out function))
{
throw EntityUtil.EntitySqlError(bltInExpr.ErrCtx, Strings.ConcatBuiltinNotSupported);
}
List<TypeUsage> argTypes = new List<TypeUsage>(2);
argTypes.Add(args.Left.ResultType);
argTypes.Add(args.Right.ResultType);
bool isAmbiguous = false;
EdmFunction concatFunction = SemanticResolver.ResolveFunctionOverloads(
function.FunctionMetadata,
argTypes,
false /* isGroupAggregate */,
out isAmbiguous);
if (null == concatFunction || isAmbiguous)
{
throw EntityUtil.EntitySqlError(bltInExpr.ErrCtx, Strings.ConcatBuiltinNotSupported);
}
return concatFunction.Invoke(new[] { args.Left, args.Right });
}
});
#endregion
//
// e1 - e2
//
#region e1 - e2
builtInExprConverter.Add(AST.BuiltInKind.Minus, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertArithmeticArgs(bltInExpr, sr);
return args.Left.Minus(args.Right);
});
#endregion
//
// e1 * e2
//
#region e1 * e2
builtInExprConverter.Add(AST.BuiltInKind.Multiply, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertArithmeticArgs(bltInExpr, sr);
return args.Left.Multiply(args.Right);
});
#endregion
//
// e1 / e2
//
#region e1 / e2
builtInExprConverter.Add(AST.BuiltInKind.Divide, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertArithmeticArgs(bltInExpr, sr);
return args.Left.Divide(args.Right);
});
#endregion
//
// e1 % e2
//
#region e1 % e2
builtInExprConverter.Add(AST.BuiltInKind.Modulus, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertArithmeticArgs(bltInExpr, sr);
return args.Left.Modulo(args.Right);
});
#endregion
//
// - e
//
#region - e
builtInExprConverter.Add(AST.BuiltInKind.UnaryMinus, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
DbExpression argument = ConvertArithmeticArgs(bltInExpr, sr).Left;
if (TypeSemantics.IsUnsignedNumericType(argument.ResultType))
{
TypeUsage closestPromotableType = null;
if (!TypeHelpers.TryGetClosestPromotableType(argument.ResultType, out closestPromotableType))
{
throw EntityUtil.EntitySqlError(Strings.InvalidUnsignedTypeForUnaryMinusOperation(argument.ResultType.EdmType.FullName));
}
}
DbExpression unaryExpr = argument.UnaryMinus();
return unaryExpr;
});
#endregion
//
// + e
//
#region + e
builtInExprConverter.Add(AST.BuiltInKind.UnaryPlus, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
return ConvertArithmeticArgs(bltInExpr, sr).Left;
});
#endregion
////////////////////////////
// Logical Expressions
////////////////////////////
//
// e1 AND e2
// e1 && e2
//
#region e1 AND e2
builtInExprConverter.Add(AST.BuiltInKind.And, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = SemanticAnalyzer.ConvertLogicalArgs(bltInExpr, sr);
return args.Left.And(args.Right);
});
#endregion
//
// e1 OR e2
// e1 || e2
//
#region e1 OR e2
builtInExprConverter.Add(AST.BuiltInKind.Or, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = SemanticAnalyzer.ConvertLogicalArgs(bltInExpr, sr);
return args.Left.Or(args.Right);
});
#endregion
//
// NOT e
// ! e
//
#region NOT e
builtInExprConverter.Add(AST.BuiltInKind.Not, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
return ConvertLogicalArgs(bltInExpr, sr).Left.Not();
});
#endregion
////////////////////////////
// Comparison Expressions
////////////////////////////
//
// e1 == e2 | e1 = e2
//
#region e1 == e2
builtInExprConverter.Add(AST.BuiltInKind.Equal, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertEqualCompArgs(bltInExpr, sr);
return args.Left.Equal(args.Right);
});
#endregion
//
// e1 != e2 | e1 <> e2
//
#region e1 != e2
builtInExprConverter.Add(AST.BuiltInKind.NotEqual, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertEqualCompArgs(bltInExpr, sr);
//
return args.Left.Equal(args.Right).Not();
});
#endregion
//
// e1 >= e2
//
#region e1 >= e2
builtInExprConverter.Add(AST.BuiltInKind.GreaterEqual, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertOrderCompArgs(bltInExpr, sr);
return args.Left.GreaterThanOrEqual(args.Right);
});
#endregion
//
// e1 > e2
//
#region e1 > e2
builtInExprConverter.Add(AST.BuiltInKind.GreaterThan, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertOrderCompArgs(bltInExpr, sr);
return args.Left.GreaterThan(args.Right);
});
#endregion
//
// e1 <= e2
//
#region e1 <= e2
builtInExprConverter.Add(AST.BuiltInKind.LessEqual, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertOrderCompArgs(bltInExpr, sr);
return args.Left.LessThanOrEqual(args.Right);
});
#endregion
//
// e1 < e2
//
#region e1 < e2
builtInExprConverter.Add(AST.BuiltInKind.LessThan, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertOrderCompArgs(bltInExpr, sr);
return args.Left.LessThan(args.Right);
});
#endregion
////////////////////////////
// SET EXPRESSIONS
////////////////////////////
//
// e1 UNION e2
//
#region e1 UNION e2
builtInExprConverter.Add(AST.BuiltInKind.Union, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertSetArgs(bltInExpr, sr);
return args.Left.UnionAll(args.Right).Distinct();
});
#endregion
//
// e1 UNION ALL e2
//
#region e1 UNION ALL e2
builtInExprConverter.Add(AST.BuiltInKind.UnionAll, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertSetArgs(bltInExpr, sr);
return args.Left.UnionAll(args.Right);
});
#endregion
//
// e1 INTERSECT e2
//
#region e1 INTERSECT e2
builtInExprConverter.Add(AST.BuiltInKind.Intersect, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertSetArgs(bltInExpr, sr);
return args.Left.Intersect(args.Right);
});
#endregion
//
// e1 OVERLAPS e2
//
#region e1 OVERLAPS e1
builtInExprConverter.Add(AST.BuiltInKind.Overlaps, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertSetArgs(bltInExpr, sr);
return args.Left.Intersect(args.Right).IsEmpty().Not();
});
#endregion
//
// ANYELEMENT( e )
//
#region ANYELEMENT( e )
builtInExprConverter.Add(AST.BuiltInKind.AnyElement, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
return ConvertSetArgs(bltInExpr, sr).Left.Element();
});
#endregion
//
// ELEMENT( e )
//
#region ELEMENT( e ) - NOT SUPPORTED IN ORCAS TIMEFRAME
builtInExprConverter.Add(AST.BuiltInKind.Element, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
throw EntityUtil.NotSupported(Strings.ElementOperatorIsNotSupported);
});
#endregion
//
// e1 EXCEPT e2
//
#region e1 EXCEPT e2
builtInExprConverter.Add(AST.BuiltInKind.Except, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertSetArgs(bltInExpr, sr);
return args.Left.Except(args.Right);
});
#endregion
//
// EXISTS( e )
//
#region EXISTS( e )
builtInExprConverter.Add(AST.BuiltInKind.Exists, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
return ConvertSetArgs(bltInExpr, sr).Left.IsEmpty().Not();
});
#endregion
//
// FLATTEN( e )
//
#region FLATTEN( e )
builtInExprConverter.Add(AST.BuiltInKind.Flatten, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
DbExpression elemExpr = ConvertValueExpression(bltInExpr.Arg1, sr);
if (!TypeSemantics.IsCollectionType(elemExpr.ResultType))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.InvalidFlattenArgument);
}
if (!TypeSemantics.IsCollectionType(TypeHelpers.GetElementTypeUsage(elemExpr.ResultType)))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.InvalidFlattenArgument);
}
DbExpressionBinding leftExpr = elemExpr.BindAs(sr.GenerateInternalName("l_flatten"));
DbExpressionBinding rightExpr = leftExpr.Variable.BindAs(sr.GenerateInternalName("r_flatten"));
DbExpressionBinding applyBinding = leftExpr.CrossApply(rightExpr).BindAs(sr.GenerateInternalName("flatten"));
return applyBinding.Project(applyBinding.Variable.Property(rightExpr.VariableName));
});
#endregion
//
// e1 IN e2
//
#region e1 IN e2
builtInExprConverter.Add(AST.BuiltInKind.In, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertInExprArgs(bltInExpr, sr);
//
// Convert "x in multiset(y1, y2, ..., yn)" into x = y1 or x = y2 or x = y3 ...
//
if (args.Right.ExpressionKind == DbExpressionKind.NewInstance)
{
return ConvertSimpleInExpression(sr, args.Left, args.Right);
}
else
{
DbExpressionBinding rSet = args.Right.BindAs(sr.GenerateInternalName("in-filter"));
DbExpression leftIn = args.Left;
DbExpression rightSet = rSet.Variable;
DbExpression exists = rSet.Filter(leftIn.Equal(rightSet)).IsEmpty().Not();
List<DbExpression> whenExpr = new List<DbExpression>(1);
whenExpr.Add(leftIn.IsNull());
List<DbExpression> thenExpr = new List<DbExpression>(1);
thenExpr.Add(DbExpressionBuilder.Null(sr.TypeResolver.BooleanType));
DbExpression left = DbExpressionBuilder.Case(whenExpr, thenExpr, DbExpressionBuilder.False);
DbExpression converted = left.Or(exists);
return converted;
}
});
#endregion
//
// e1 NOT IN e1
//
#region e1 NOT IN e1
builtInExprConverter.Add(AST.BuiltInKind.NotIn, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertInExprArgs(bltInExpr, sr);
if (args.Right.ExpressionKind == DbExpressionKind.NewInstance)
{
return ConvertSimpleInExpression(sr, args.Left, args.Right).Not();
}
else
{
DbExpressionBinding rSet = args.Right.BindAs(sr.GenerateInternalName("in-filter"));
DbExpression leftIn = args.Left;
DbExpression rightSet = rSet.Variable;
DbExpression exists = rSet.Filter(leftIn.Equal(rightSet)).IsEmpty();
List<DbExpression> whenExpr = new List<DbExpression>(1);
whenExpr.Add(leftIn.IsNull());
List<DbExpression> thenExpr = new List<DbExpression>(1);
thenExpr.Add(DbExpressionBuilder.Null(sr.TypeResolver.BooleanType));
DbExpression left = DbExpressionBuilder.Case(whenExpr, thenExpr, DbExpressionBuilder.True);
DbExpression converted = left.And(exists);
return converted;
}
});
#endregion
//
// SET( e ) - DISTINCT( e ) before
//
#region SET( e )
builtInExprConverter.Add(AST.BuiltInKind.Distinct, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
Pair<DbExpression, DbExpression> args = ConvertSetArgs(bltInExpr, sr);
return args.Left.Distinct();
});
#endregion
////////////////////////////
// Nullabity Expressions
////////////////////////////
//
// e IS NULL
//
#region e IS NULL
builtInExprConverter.Add(AST.BuiltInKind.IsNull, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
DbExpression isNullExpr = ConvertValueExpressionAllowUntypedNulls(bltInExpr.Arg1, sr);
//
// Ensure expression type is valid for this operation.
//
if (isNullExpr != null && !TypeHelpers.IsValidIsNullOpType(isNullExpr.ResultType))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.IsNullInvalidType);
}
return isNullExpr != null ? (DbExpression)isNullExpr.IsNull() : DbExpressionBuilder.True;
});
#endregion
//
// e IS NOT NULL
//
#region e IS NOT NULL
builtInExprConverter.Add(AST.BuiltInKind.IsNotNull, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
DbExpression isNullExpr = ConvertValueExpressionAllowUntypedNulls(bltInExpr.Arg1, sr);
//
// Ensure expression type is valid for this operation.
//
if (isNullExpr != null && !TypeHelpers.IsValidIsNullOpType(isNullExpr.ResultType))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.IsNullInvalidType);
}
return isNullExpr != null ? (DbExpression)isNullExpr.IsNull().Not() : DbExpressionBuilder.False;
});
#endregion
////////////////////////////
// Type Expressions
////////////////////////////
//
// e IS OF ( [ONLY] T )
//
#region e IS OF ( [ONLY] T )
builtInExprConverter.Add(AST.BuiltInKind.IsOf, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
var exprToFilter = ConvertValueExpression(bltInExpr.Arg1, sr);
var typeToFilterTo = ConvertTypeName(bltInExpr.Arg2, sr);
bool isOnly = (bool)((AST.Literal)bltInExpr.Arg3).Value;
bool isNot = (bool)((AST.Literal)bltInExpr.Arg4).Value;
bool isNominalTypeAllowed = sr.ParserOptions.ParserCompilationMode == ParserOptions.CompilationMode.RestrictedViewGenerationMode;
if (!isNominalTypeAllowed && !TypeSemantics.IsEntityType(exprToFilter.ResultType))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx,
Strings.ExpressionTypeMustBeEntityType(Strings.CtxIsOf,
exprToFilter.ResultType.EdmType.BuiltInTypeKind.ToString(),
exprToFilter.ResultType.EdmType.FullName));
}
else if (isNominalTypeAllowed && !TypeSemantics.IsNominalType(exprToFilter.ResultType))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx,
Strings.ExpressionTypeMustBeNominalType(Strings.CtxIsOf,
exprToFilter.ResultType.EdmType.BuiltInTypeKind.ToString(),
exprToFilter.ResultType.EdmType.FullName));
}
if (!isNominalTypeAllowed && !TypeSemantics.IsEntityType(typeToFilterTo))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx, Strings.TypeMustBeEntityType(Strings.CtxIsOf,
typeToFilterTo.EdmType.BuiltInTypeKind.ToString(),
typeToFilterTo.EdmType.FullName));
}
else if (isNominalTypeAllowed && !TypeSemantics.IsNominalType(typeToFilterTo))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx, Strings.TypeMustBeNominalType(Strings.CtxIsOf,
typeToFilterTo.EdmType.BuiltInTypeKind.ToString(),
typeToFilterTo.EdmType.FullName));
}
if (!TypeSemantics.IsPolymorphicType(exprToFilter.ResultType))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.TypeMustBeInheritableType);
}
if (!TypeSemantics.IsPolymorphicType(typeToFilterTo))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx, Strings.TypeMustBeInheritableType);
}
if (!IsSubOrSuperType(exprToFilter.ResultType, typeToFilterTo))
{
throw EntityUtil.EntitySqlError(bltInExpr.ErrCtx, Strings.NotASuperOrSubType(exprToFilter.ResultType.EdmType.FullName,
typeToFilterTo.EdmType.FullName));
}
typeToFilterTo = TypeHelpers.GetReadOnlyType(typeToFilterTo);
DbExpression retExpr = null;
if (isOnly)
{
retExpr = exprToFilter.IsOfOnly(typeToFilterTo);
}
else
{
retExpr = exprToFilter.IsOf(typeToFilterTo);
}
if (isNot)
{
retExpr = retExpr.Not();
}
return retExpr;
});
#endregion
//
// TREAT( e as T )
//
#region TREAT( e as T )
builtInExprConverter.Add(AST.BuiltInKind.Treat, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
var exprToTreat = ConvertValueExpressionAllowUntypedNulls(bltInExpr.Arg1, sr);
var typeToTreatTo = ConvertTypeName(bltInExpr.Arg2, sr);
bool isNominalTypeAllowed = sr.ParserOptions.ParserCompilationMode == ParserOptions.CompilationMode.RestrictedViewGenerationMode;
if (!isNominalTypeAllowed && !TypeSemantics.IsEntityType(typeToTreatTo))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx,
Strings.TypeMustBeEntityType(Strings.CtxTreat,
typeToTreatTo.EdmType.BuiltInTypeKind.ToString(),
typeToTreatTo.EdmType.FullName));
}
else if (isNominalTypeAllowed && !TypeSemantics.IsNominalType(typeToTreatTo))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx,
Strings.TypeMustBeNominalType(Strings.CtxTreat,
typeToTreatTo.EdmType.BuiltInTypeKind.ToString(),
typeToTreatTo.EdmType.FullName));
}
if (exprToTreat == null)
{
exprToTreat = DbExpressionBuilder.Null(typeToTreatTo);
}
else if (!isNominalTypeAllowed && !TypeSemantics.IsEntityType(exprToTreat.ResultType))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx,
Strings.ExpressionTypeMustBeEntityType(Strings.CtxTreat,
exprToTreat.ResultType.EdmType.BuiltInTypeKind.ToString(),
exprToTreat.ResultType.EdmType.FullName));
}
else if (isNominalTypeAllowed && !TypeSemantics.IsNominalType(exprToTreat.ResultType))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx,
Strings.ExpressionTypeMustBeNominalType(Strings.CtxTreat,
exprToTreat.ResultType.EdmType.BuiltInTypeKind.ToString(),
exprToTreat.ResultType.EdmType.FullName));
}
if (!TypeSemantics.IsPolymorphicType(exprToTreat.ResultType))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.TypeMustBeInheritableType);
}
if (!TypeSemantics.IsPolymorphicType(typeToTreatTo))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx, Strings.TypeMustBeInheritableType);
}
if (!IsSubOrSuperType(exprToTreat.ResultType, typeToTreatTo))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.NotASuperOrSubType(exprToTreat.ResultType.EdmType.FullName,
typeToTreatTo.EdmType.FullName));
}
return exprToTreat.TreatAs(TypeHelpers.GetReadOnlyType(typeToTreatTo));
});
#endregion
//
// CAST( e AS T )
//
#region CAST( e AS T )
builtInExprConverter.Add(AST.BuiltInKind.Cast, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
var exprToCast = ConvertValueExpressionAllowUntypedNulls(bltInExpr.Arg1, sr);
var typeToCastTo = ConvertTypeName(bltInExpr.Arg2, sr);
//
// Ensure CAST target type is scalar.
//
if (!TypeSemantics.IsScalarType(typeToCastTo))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx, Strings.InvalidCastType);
}
if (exprToCast == null)
{
return DbExpressionBuilder.Null(typeToCastTo);
}
//
// Ensure CAST source type is scalar.
//
if (!TypeSemantics.IsScalarType(exprToCast.ResultType))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.InvalidCastExpressionType);
}
if (!TypeSemantics.IsCastAllowed(exprToCast.ResultType, typeToCastTo))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.InvalidCast(exprToCast.ResultType.EdmType.FullName, typeToCastTo.EdmType.FullName));
}
return exprToCast.CastTo(TypeHelpers.GetReadOnlyType(typeToCastTo));
});
#endregion
//
// OFTYPE( [ONLY] e, T )
//
#region OFTYPE( [ONLY] e, T )
builtInExprConverter.Add(AST.BuiltInKind.OfType, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
var exprToFilter = ConvertValueExpression(bltInExpr.Arg1, sr);
var typeToFilterTo = ConvertTypeName(bltInExpr.Arg2, sr);
bool isOnly = (bool)((AST.Literal)bltInExpr.Arg3).Value;
bool isNominalTypeAllowed = sr.ParserOptions.ParserCompilationMode == ParserOptions.CompilationMode.RestrictedViewGenerationMode;
if (!TypeSemantics.IsCollectionType(exprToFilter.ResultType))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.ExpressionMustBeCollection);
}
TypeUsage elementType = TypeHelpers.GetElementTypeUsage(exprToFilter.ResultType);
if (!isNominalTypeAllowed && !TypeSemantics.IsEntityType(elementType))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx,
Strings.OfTypeExpressionElementTypeMustBeEntityType(elementType.EdmType.BuiltInTypeKind.ToString(), elementType));
}
else if (isNominalTypeAllowed && !TypeSemantics.IsNominalType(elementType))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx,
Strings.OfTypeExpressionElementTypeMustBeNominalType(elementType.EdmType.BuiltInTypeKind.ToString(), elementType));
}
if (!isNominalTypeAllowed && !TypeSemantics.IsEntityType(typeToFilterTo))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx,
Strings.TypeMustBeEntityType(Strings.CtxOfType, typeToFilterTo.EdmType.BuiltInTypeKind.ToString(), typeToFilterTo.EdmType.FullName));
}
else if (isNominalTypeAllowed && !TypeSemantics.IsNominalType(typeToFilterTo))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx,
Strings.TypeMustBeNominalType(Strings.CtxOfType, typeToFilterTo.EdmType.BuiltInTypeKind.ToString(), typeToFilterTo.EdmType.FullName));
}
if (isOnly && typeToFilterTo.EdmType.Abstract)
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx, Strings.OfTypeOnlyTypeArgumentCannotBeAbstract(typeToFilterTo.EdmType.FullName));
}
if (!IsSubOrSuperType(elementType, typeToFilterTo))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.NotASuperOrSubType(elementType.EdmType.FullName, typeToFilterTo.EdmType.FullName));
}
DbExpression ofTypeExpression = null;
if (isOnly)
{
ofTypeExpression = exprToFilter.OfTypeOnly(TypeHelpers.GetReadOnlyType(typeToFilterTo));
}
else
{
ofTypeExpression = exprToFilter.OfType(TypeHelpers.GetReadOnlyType(typeToFilterTo));
}
return ofTypeExpression;
});
#endregion
//
// e LIKE pattern [ESCAPE escape]
//
#region e LIKE pattern [ESCAPE escape]
builtInExprConverter.Add(AST.BuiltInKind.Like, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
DbExpression likeExpr = null;
DbExpression matchExpr = ConvertValueExpressionAllowUntypedNulls(bltInExpr.Arg1, sr);
if (matchExpr == null)
{
matchExpr = DbExpressionBuilder.Null(sr.TypeResolver.StringType);
}
else if (!IsStringType(matchExpr.ResultType))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.LikeArgMustBeStringType);
}
DbExpression patternExpr = ConvertValueExpressionAllowUntypedNulls(bltInExpr.Arg2, sr);
if (patternExpr == null)
{
patternExpr = DbExpressionBuilder.Null(sr.TypeResolver.StringType);
}
else if (!IsStringType(patternExpr.ResultType))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx, Strings.LikeArgMustBeStringType);
}
if (3 == bltInExpr.ArgCount)
{
DbExpression escapeExpr = ConvertValueExpressionAllowUntypedNulls(bltInExpr.Arg3, sr);
if (escapeExpr == null)
{
escapeExpr = DbExpressionBuilder.Null(sr.TypeResolver.StringType);
}
else if (!IsStringType(escapeExpr.ResultType))
{
throw EntityUtil.EntitySqlError(bltInExpr.Arg3.ErrCtx, Strings.LikeArgMustBeStringType);
}
likeExpr = matchExpr.Like(patternExpr, escapeExpr);
}
else
{
likeExpr = matchExpr.Like(patternExpr);
}
return likeExpr;
});
#endregion
//
// e BETWEEN e1 AND e2
//
#region e BETWEEN e1 AND e2
builtInExprConverter.Add(AST.BuiltInKind.Between, ConvertBetweenExpr);
#endregion
//
// e NOT BETWEEN e1 AND e2
//
#region e NOT BETWEEN e1 AND e2
builtInExprConverter.Add(AST.BuiltInKind.NotBetween, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
{
return ConvertBetweenExpr(bltInExpr, sr).Not();
});
#endregion
return builtInExprConverter;
}