diff --git a/src/Umbraco.Core/Persistence/Querying/BaseExpressionHelper.cs b/src/Umbraco.Core/Persistence/Querying/BaseExpressionHelper.cs index 73fa98b275..08a08e49d3 100644 --- a/src/Umbraco.Core/Persistence/Querying/BaseExpressionHelper.cs +++ b/src/Umbraco.Core/Persistence/Querying/BaseExpressionHelper.cs @@ -1,5 +1,6 @@ using System; using System.Globalization; +using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Querying { @@ -25,7 +26,7 @@ namespace Umbraco.Core.Persistence.Querying { //if (TypeSerializer.CanCreateFromString(fieldType)) //{ - // return "'" + EscapeParam(TypeSerializer.SerializeToString(value)) + "'"; + // return "'" + escapeCallback(TypeSerializer.SerializeToString(value)) + "'"; //} throw new NotSupportedException( @@ -46,27 +47,24 @@ namespace Umbraco.Core.Persistence.Querying if (fieldType == typeof(DateTime)) { - return "'" + EscapeParam(((DateTime)value).ToIsoString()) + "'"; + return "'" + escapeCallback(((DateTime)value).ToIsoString()) + "'"; } if (fieldType == typeof(bool)) return ((bool)value) ? Convert.ToString(1, CultureInfo.InvariantCulture) : Convert.ToString(0, CultureInfo.InvariantCulture); - return ShouldQuoteValue(fieldType) - ? "'" + EscapeParam(value) + "'" + return shouldQuoteCallback(fieldType) + ? "'" + escapeCallback(value) + "'" : value.ToString(); } public virtual string EscapeParam(object paramValue) { - return paramValue.ToString().Replace("'", "''"); + return paramValue == null + ? string.Empty + : SqlSyntaxContext.SqlSyntaxProvider.EscapeString(paramValue.ToString()); } - - public virtual string EscapeAtArgument(string exp) - { - return PetaPocoExtensions.EscapeAtSymbols(exp); - } - + public virtual bool ShouldQuoteValue(Type fieldType) { return true; diff --git a/src/Umbraco.Core/Persistence/Querying/ModelToSqlExpressionHelper.cs b/src/Umbraco.Core/Persistence/Querying/ModelToSqlExpressionHelper.cs index 4dba620ab0..c7797d1a20 100644 --- a/src/Umbraco.Core/Persistence/Querying/ModelToSqlExpressionHelper.cs +++ b/src/Umbraco.Core/Persistence/Querying/ModelToSqlExpressionHelper.cs @@ -205,13 +205,12 @@ namespace Umbraco.Core.Persistence.Querying { if (c.Value == null) return "null"; - else if (c.Value.GetType() == typeof(bool)) + if (c.Value is bool) { object o = GetQuotedValue(c.Value, c.Value.GetType()); return string.Format("({0}={1})", GetQuotedTrueValue(), o); } - else - return GetQuotedValue(c.Value, c.Value.GetType()); + return GetQuotedValue(c.Value, c.Value.GetType()); } protected virtual string VisitUnary(UnaryExpression u) @@ -233,15 +232,15 @@ namespace Umbraco.Core.Persistence.Querying switch (verb) { case "SqlWildcard": - return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnWildcardComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType); + return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnWildcardComparison(col, EscapeParam(RemoveQuote(val)), columnType); case "Equals": - return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEqualComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType); + return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEqualComparison(col, EscapeParam(RemoveQuote(val)), columnType); case "StartsWith": - return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnStartsWithComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType); + return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnStartsWithComparison(col, EscapeParam(RemoveQuote(val)), columnType); case "EndsWith": - return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEndsWithComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType); + return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEndsWithComparison(col, EscapeParam(RemoveQuote(val)), columnType); case "Contains": - return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnContainsComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType); + return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnContainsComparison(col, EscapeParam(RemoveQuote(val)), columnType); case "InvariantEquals": case "SqlEquals": //recurse diff --git a/src/Umbraco.Core/Persistence/Querying/PocoToSqlExpressionHelper.cs b/src/Umbraco.Core/Persistence/Querying/PocoToSqlExpressionHelper.cs index 6c2f7e6727..22bfed1e82 100644 --- a/src/Umbraco.Core/Persistence/Querying/PocoToSqlExpressionHelper.cs +++ b/src/Umbraco.Core/Persistence/Querying/PocoToSqlExpressionHelper.cs @@ -254,11 +254,11 @@ namespace Umbraco.Core.Persistence.Querying case "ToLower": return string.Format("lower({0})", r); case "StartsWith": - return string.Format("upper({0}) like '{1}%'", r, EscapeAtArgument(RemoveQuote(args[0].ToString().ToUpper()))); + return string.Format("upper({0}) like '{1}%'", r, EscapeParam(RemoveQuote(args[0].ToString().ToUpper()))); case "EndsWith": - return string.Format("upper({0}) like '%{1}'", r, EscapeAtArgument(RemoveQuote(args[0].ToString()).ToUpper())); + return string.Format("upper({0}) like '%{1}'", r, EscapeParam(RemoveQuote(args[0].ToString()).ToUpper())); case "Contains": - return string.Format("upper({0}) like '%{1}%'", r, EscapeAtArgument(RemoveQuote(args[0].ToString()).ToUpper())); + return string.Format("upper({0}) like '%{1}%'", r, EscapeParam(RemoveQuote(args[0].ToString()).ToUpper())); case "Substring": var startIndex = Int32.Parse(args[0].ToString()) + 1; if (args.Count == 2) diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs index 2b31fb2032..c62fa1a923 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs @@ -11,6 +11,8 @@ namespace Umbraco.Core.Persistence.SqlSyntax /// public interface ISqlSyntaxProvider { + string EscapeString(string val); + string GetStringColumnEqualComparison(string column, string value, TextColumnType columnType); string GetStringColumnStartsWithComparison(string column, string value, TextColumnType columnType); string GetStringColumnEndsWithComparison(string column, string value, TextColumnType columnType); diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs index 5f5d412ab3..0b8d80a21f 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs @@ -327,5 +327,10 @@ namespace Umbraco.Core.Persistence.SqlSyntax // add message to check with their hosting provider return supportsCaseInsensitiveQueries; } + + public override string EscapeString(string val) + { + return PetaPocoExtensions.EscapeAtSymbols(MySql.Data.MySqlClient.MySqlHelper.EscapeString(val)); + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs index 8f9a84437c..004aabfc70 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs @@ -103,6 +103,11 @@ namespace Umbraco.Core.Persistence.SqlSyntax DbTypeMap.Set(DbType.Binary, BlobColumnDefinition); } + public virtual string EscapeString(string val) + { + return PetaPocoExtensions.EscapeAtSymbols(val.Replace("'", "''")); + } + public virtual string GetStringColumnEqualComparison(string column, string value, TextColumnType columnType) { //use the 'upper' method to always ensure strings are matched without case sensitivity no matter what the db setting. diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index b96e6db308..b9e13a86fd 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -45,6 +45,10 @@ ..\packages\MiniProfiler.2.1.0\lib\net40\MiniProfiler.dll + + False + ..\packages\MySql.Data.6.8.3\lib\net40\MySql.Data.dll + ..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll diff --git a/src/Umbraco.Core/packages.config b/src/Umbraco.Core/packages.config index f1d5aa83c6..3b2d7e5ca2 100644 --- a/src/Umbraco.Core/packages.config +++ b/src/Umbraco.Core/packages.config @@ -6,6 +6,7 @@ + \ No newline at end of file