Skip to content

Commit

Permalink
Merge pull request #453 from MarkMpn/executeas
Browse files Browse the repository at this point in the history
String Truncation error
  • Loading branch information
MarkMpn authored Apr 17, 2024
2 parents 052d59c + 9a484e9 commit 748a3d0
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 14 deletions.
4 changes: 2 additions & 2 deletions MarkMpn.Sql4Cds.Engine/Ado/Sql4CdsError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -317,9 +317,9 @@ internal static Sql4CdsError InvalidArgumentType(TSqlFragment fragment, DataType
return Create(8116, fragment, Collation.USEnglish.ToSqlString(GetTypeName(type)), (SqlInt32)paramNum, Collation.USEnglish.ToSqlString(function));
}

internal static Sql4CdsError StringTruncation(TSqlFragment fragment)
internal static Sql4CdsError StringTruncation(TSqlFragment fragment, string table, string column, string value)
{
return Create(8152, fragment);
return Create(2628, fragment, (SqlInt32)table.Length, Collation.USEnglish.ToSqlString(table), (SqlInt32)column.Length, Collation.USEnglish.ToSqlString(column), (SqlInt32)value.Length, Collation.USEnglish.ToSqlString(value));
}

internal static Sql4CdsError ConversionError(TSqlFragment fragment, DataTypeReference from, DataTypeReference to)
Expand Down
2 changes: 1 addition & 1 deletion MarkMpn.Sql4Cds.Engine/ExecutionPlan/BaseDmlNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ protected Dictionary<string, Func<Entity, object>> CompileColumnMappings(DataSou
{
// Convert to destination SQL type - don't do this if we're converting from an EntityReference to a PartyList so
// we don't lose the entity name during the conversion via a string
expr = SqlTypeConverter.Convert(expr, sourceSqlType, destSqlType, throwOnTruncate: true);
expr = SqlTypeConverter.Convert(expr, sourceSqlType, destSqlType, throwOnTruncate: true, table: logicalName, column: destAttributeName);
}

// Convert to final .NET SDK type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ private static int FaultCodeToSqlError(OrganizationServiceFault fault)
{
switch (fault.ErrorCode)
{
case -2146892759: return 2628;
case -2147204303:
case -2147204288: return 8152;
case -2147217098: return 8115;
case -2147204304:
Expand Down
24 changes: 13 additions & 11 deletions MarkMpn.Sql4Cds.Engine/ExecutionPlan/SqlTypeConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ private static SqlString ApplyCollation(Collation collation, SqlString sqlString
/// <param name="styleType">An optional parameter defining the type of the <paramref name="style"/> expression</param>
/// <param name="convert">An optional parameter containing the SQL CONVERT() function call to report any errors against</param>
/// <returns>An expression to generate values of the required type</returns>
public static Expression Convert(Expression expr, DataTypeReference from, DataTypeReference to, Expression style = null, DataTypeReference styleType = null, TSqlFragment convert = null, bool throwOnTruncate = false)
public static Expression Convert(Expression expr, DataTypeReference from, DataTypeReference to, Expression style = null, DataTypeReference styleType = null, TSqlFragment convert = null, bool throwOnTruncate = false, string table = null, string column = null)
{
if (from.IsSameAs(to))
return expr;
Expand Down Expand Up @@ -683,30 +683,30 @@ public static Expression Convert(Expression expr, DataTypeReference from, DataTy

// Truncate the value to the specified length, but some special cases
string valueOnTruncate = null;
Exception exceptionOnTruncate = null;
Func<string,Sql4CdsError> errorOnTruncate = null;

if (sourceType == typeof(SqlInt32) || sourceType == typeof(SqlInt16) || sourceType == typeof(SqlByte))
{
if (toSqlType.SqlDataTypeOption == SqlDataTypeOption.Char || toSqlType.SqlDataTypeOption == SqlDataTypeOption.VarChar)
valueOnTruncate = "*";
else if (toSqlType.SqlDataTypeOption == SqlDataTypeOption.NChar || toSqlType.SqlDataTypeOption == SqlDataTypeOption.NVarChar)
exceptionOnTruncate = new QueryExecutionException(Sql4CdsError.ArithmeticOverflow(from, toSqlType));
errorOnTruncate = _ => Sql4CdsError.ArithmeticOverflow(from, toSqlType);
}
else if ((sourceType == typeof(SqlMoney) || sourceType == typeof(SqlDecimal) || sourceType == typeof(SqlSingle)) &&
(toSqlType.SqlDataTypeOption == SqlDataTypeOption.Char || toSqlType.SqlDataTypeOption == SqlDataTypeOption.VarChar || toSqlType.SqlDataTypeOption == SqlDataTypeOption.NChar || toSqlType.SqlDataTypeOption == SqlDataTypeOption.NVarChar))
{
exceptionOnTruncate = new QueryExecutionException(Sql4CdsError.ArithmeticOverflow(from, toSqlType));
errorOnTruncate = _ => Sql4CdsError.ArithmeticOverflow(from, toSqlType);
}
else if (throwOnTruncate)
{
exceptionOnTruncate = new QueryExecutionException(Sql4CdsError.StringTruncation(convert));
errorOnTruncate = truncated => Sql4CdsError.StringTruncation(convert, table, column, truncated);
}

expr = Expr.Call(() => Truncate(Expr.Arg<SqlString>(), Expr.Arg<int>(), Expr.Arg<string>(), Expr.Arg<Exception>()),
expr = Expr.Call(() => Truncate(Expr.Arg<SqlString>(), Expr.Arg<int>(), Expr.Arg<string>(), Expr.Arg<Func<string,Sql4CdsError>>()),
expr,
Expression.Constant(maxLength),
Expression.Constant(valueOnTruncate, typeof(string)),
Expression.Constant(exceptionOnTruncate, typeof(Exception)));
Expression.Constant(errorOnTruncate, typeof(Func<string,Sql4CdsError>)));
}
else if (toSqlType.Parameters[0].LiteralType != LiteralType.Max)
{
Expand Down Expand Up @@ -782,7 +782,7 @@ public static SqlString ConvertCollation(SqlString value, Collation collation)
return collation.ToSqlString(value.Value);
}

private static SqlString Truncate(SqlString value, int maxLength, string valueOnTruncate, Exception exceptionOnTruncate)
private static SqlString Truncate(SqlString value, int maxLength, string valueOnTruncate, Func<string,Sql4CdsError> errorOnTruncate)
{
if (value.IsNull)
return value;
Expand All @@ -793,10 +793,12 @@ private static SqlString Truncate(SqlString value, int maxLength, string valueOn
if (valueOnTruncate != null)
return new SqlString(valueOnTruncate, value.LCID, value.SqlCompareOptions);

if (exceptionOnTruncate != null)
throw exceptionOnTruncate;
var truncated = value.Value.Substring(0, maxLength);

return new SqlString(value.Value.Substring(0, maxLength), value.LCID, value.SqlCompareOptions);
if (errorOnTruncate != null)
throw new QueryExecutionException(errorOnTruncate(truncated));

return new SqlString(truncated, value.LCID, value.SqlCompareOptions);
}

private static EntityCollection CreateEntityCollection(SqlEntityReference value)
Expand Down

0 comments on commit 748a3d0

Please sign in to comment.