internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc)
		{
			// process the arguments
			SqlExpression result = base.VisitFunctionCall(fc);
			if(result is SqlFunctionCall)
			{
				SqlFunctionCall resultFunctionCall = (SqlFunctionCall)result;

				if(resultFunctionCall.Name == sql.LengthFunctionName)
				{
					SqlExpression expr = resultFunctionCall.Arguments[0];

					if(expr.SqlType.IsLargeType && !expr.SqlType.SupportsLength)
					{
						result = sql.FunctionCallDataLength(expr);

						if(expr.SqlType.IsUnicodeType)
						{
							result = sql.ConvertToInt(sql.Divide(result, sql.ValueFromObject(2, expr.SourceExpression)));
						}
					}
				}

				// If the return type of the sql function is not compatible with
				// the expected CLR type of the function, inject a conversion. This
				// step must be performed AFTER SqlRetyper has run.
				Type clrType = resultFunctionCall.SqlType.GetClosestRuntimeType();
				bool skipConversion = SkipConversionForDateAdd(resultFunctionCall.Name,
																					resultFunctionCall.ClrType,
																					clrType);
				if((resultFunctionCall.ClrType != clrType) && !skipConversion)
				{
					result = sql.ConvertTo(resultFunctionCall.ClrType, resultFunctionCall);
				}
			}

			return result;
		}
예제 #2
0
 internal virtual SqlExpression VisitFunctionCall(SqlFunctionCall fc) {
     for (int i = 0, n = fc.Arguments.Count; i < n; i++) {
         fc.Arguments[i] = this.VisitExpression(fc.Arguments[i]);
     }
     return fc;
 }
		internal override ProviderType ReturnTypeOfFunction(SqlFunctionCall functionCall)
		{
			var argumentTypes = this.GetArgumentTypes(functionCall);

			SqlType arg0 = (SqlType)argumentTypes[0];
			SqlType arg1 = argumentTypes.Length > 1 ? (SqlType)argumentTypes[1] : (SqlType)null;

			switch(functionCall.Name)
			{
				case "LEN":
				case "DATALENGTH":
					switch(arg0.SqlDbType)
					{
						case SqlDbType.NVarChar:
						case SqlDbType.VarChar:
						case SqlDbType.VarBinary:
							if(arg0.IsLargeType)
							{
								return SqlTypeSystem.Create(SqlDbType.BigInt);
							}
							else
							{
								return SqlTypeSystem.Create(SqlDbType.Int);
							}
						default:
							return SqlTypeSystem.Create(SqlDbType.Int);
					}
				case "ABS":
				case "SIGN":
				case "ROUND":
				case "CEILING":
				case "FLOOR":
				case "POWER":
					switch(arg0.SqlDbType)
					{
						case SqlDbType.TinyInt:
						case SqlDbType.Int:
						case SqlDbType.SmallInt:
							return SqlTypeSystem.Create(SqlDbType.Int);
						case SqlDbType.Float:
						case SqlDbType.Real:
							return SqlTypeSystem.Create(SqlDbType.Float);
						default:
							return arg0;
					}
				case "PATINDEX":
				case "CHARINDEX":
					if(arg1.IsLargeType)
						return SqlTypeSystem.Create(SqlDbType.BigInt);
					return SqlTypeSystem.Create(SqlDbType.Int);
				case "SUBSTRING":
					if(functionCall.Arguments[2].NodeType == SqlNodeType.Value)
					{
						SqlValue val = (SqlValue)functionCall.Arguments[2];

						if(val.Value is int)
						{
							switch(arg0.SqlDbType)
							{
								case SqlDbType.NVarChar:
								case SqlDbType.NChar:
								case SqlDbType.VarChar:
								case SqlDbType.Char:
									return SqlTypeSystem.Create(arg0.SqlDbType, (int)val.Value);
								default:
									return null;
							}
						}
					}
					switch(arg0.SqlDbType)
					{
						case SqlDbType.NVarChar:
						case SqlDbType.NChar:
							return SqlTypeSystem.Create(SqlDbType.NVarChar);
						case SqlDbType.VarChar:
						case SqlDbType.Char:
							return SqlTypeSystem.Create(SqlDbType.VarChar);
						default:
							return null;
					}
				case "STUFF":
					// if the stuff call is an insertion  and is strictly additive
					// (no deletion of characters) the return type is the same as 
					// a concatenation
					if(functionCall.Arguments.Count == 4)
					{
						SqlValue delLength = functionCall.Arguments[2] as SqlValue;
						if(delLength != null && (int)delLength.Value == 0)
						{
							return PredictTypeForBinary(SqlNodeType.Concat,
								functionCall.Arguments[0].SqlType, functionCall.Arguments[3].SqlType);
						}
					}
					return null;
				case "LOWER":
				case "UPPER":
				case "RTRIM":
				case "LTRIM":
				case "INSERT":
				case "REPLACE":
				case "LEFT":
				case "RIGHT":
				case "REVERSE":
					return arg0;
				default:
					return null;
			}
		}
		private ProviderType[] GetArgumentTypes(SqlFunctionCall fc)
		{
			ProviderType[] array = new ProviderType[fc.Arguments.Count];
			for(int i = 0, n = array.Length; i < n; i++)
			{
				array[i] = fc.Arguments[i].SqlType;
			}
			return array;
		}
예제 #5
0
		internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc)
		{
			if(fc.Name.Contains("."))
			{
				// Assume UDF -- bracket the name.
				this.WriteName(fc.Name);
			}
			else
			{
				// No ".", so we assume it's a system function name and leave it alone.
				_commandStringBuilder.Append(fc.Name);
			}

			_commandStringBuilder.Append("(");
			for(int i = 0, n = fc.Arguments.Count; i < n; i++)
			{
				if(i > 0)
					_commandStringBuilder.Append(", ");
				this.Visit(fc.Arguments[i]);
			}
			_commandStringBuilder.Append(")");
			return fc;
		}
예제 #6
0
		internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc)
		{
			SqlExpression[] args = new SqlExpression[fc.Arguments.Count];
			for(int i = 0, n = fc.Arguments.Count; i < n; i++)
			{
				args[i] = this.VisitExpression(fc.Arguments[i]);
			}
			return new SqlFunctionCall(fc.ClrType, fc.SqlType, fc.Name, args, fc.SourceExpression);
		}
예제 #7
0
 internal abstract ProviderType ReturnTypeOfFunction(SqlFunctionCall functionCall);
예제 #8
0
		internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc)
		{
			for(int i = 0, n = fc.Arguments.Count; i < n; i++)
			{
				fc.Arguments[i] = this.VisitExpression(fc.Arguments[i]);
			}
			if(fc.Arguments.Count > 0)
			{
				ProviderType oldType = fc.Arguments[0].SqlType;
				// if this has a real argument (not e.g. the symbol "DAY" in DATEDIFF(DAY,...))
				if(oldType != null)
				{
					ProviderType newType = this.typeProvider.ReturnTypeOfFunction(fc);
					if(newType != null)
					{
						fc.SetSqlType(newType);
					}
				}
			}
			return fc;
		}
예제 #9
0
		internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc) {
			for (int i = 0, n = fc.Arguments.Count; i < n; i++) {
				fc.Arguments[i] = this.FetchExpression(fc.Arguments[i]);
			}
			return fc;
		}
예제 #10
0
			internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc)
			{
				if(fc.Name == "LEN")
				{
					bool changed;
					fc.Arguments[0] = ConvertToMax(fc.Arguments[0], out changed);
					if(fc.Arguments[0].SqlType.IsLargeType)
					{
						this.annotations.Add(fc, new CompatibilityAnnotation(
												   Strings.LenOfTextOrNTextNotSupported(fc.SourceExpression), SqlServerProviderMode.Sql2000));
					}
				}
				return base.VisitFunctionCall(fc);
			}