Permalink
Browse files

allow specifying expressions for a field based on connection dialect …

…type, for example [Expression("CONCAT(A, B)"), Expression("A || B", Dialect = "Sqlite")], match with longest dialect name wins
  • Loading branch information...
1 parent f9fd290 commit 8c1d78a314fe08cb62b4cde896b5c4cef93defca @volkanceylan committed Jan 11, 2017
@@ -185,6 +185,82 @@ protected virtual void AfterInitialize()
}
+ private static readonly char[] comma = new char[] { ',' };
+
+ private ExpressionAttribute GetBestMatchingExpression(IEnumerable<ExpressionAttribute> expressions,
+ ref string dialectServerType, ref string dialectTypeName)
+ {
+ if (!expressions.Any(x => !string.IsNullOrEmpty(x.Dialect)))
+ return expressions.FirstOrDefault();
+
+ if (dialectTypeName == null)
+ {
+ ISqlDialect dialect = null;
+
+ if (!string.IsNullOrEmpty(connectionKey))
+ {
+ var csi = SqlConnections.TryGetConnectionString(connectionKey);
+ if (csi != null)
+ dialect = csi.Dialect;
+ }
+
+ dialect = dialect ?? SqlSettings.DefaultDialect;
+ dialectServerType = dialect.ServerType;
+ dialectTypeName = dialect.GetType().Name;
+ }
+
+ var st = dialectServerType;
+ var tn = dialectTypeName;
+
+ Func<string, bool> isMatch = s =>
+ {
+ return st.StartsWith(s, StringComparison.OrdinalIgnoreCase) ||
+ tn.StartsWith(s, StringComparison.OrdinalIgnoreCase);
+ };
+
+ Dictionary<ExpressionAttribute, int> weight = null;
+
+ var bestMatch = expressions.Where(x =>
+ {
+ if (string.IsNullOrEmpty(x.Dialect))
+ return true;
+
+ if (x.Dialect.IndexOf(',') < 0)
+ return isMatch(x.Dialect);
+
+ var best = x.Dialect.Split(comma, StringSplitOptions.RemoveEmptyEntries)
+ .Select(z => z.Trim())
+ .Where(z => isMatch(z))
+ .OrderByDescending(z => z.Length)
+ .FirstOrDefault();
+
+ if (best != null)
+ {
+ if (weight == null)
+ weight = new Dictionary<ExpressionAttribute, int>();
+
+ weight[x] = best.Length;
+ return true;
+ }
+
+ return false;
+ })
+ .OrderByDescending(x =>
+ {
+ if (string.IsNullOrEmpty(x.Dialect))
+ return 0;
+
+ int w;
+ if (weight != null && weight.TryGetValue(x, out w))
+ return w;
+
+ return x.Dialect.Length;
+ })
+ .FirstOrDefault();
+
+ return bestMatch;
+ }
+
public void Initialize()
{
if (isInitialized)
@@ -225,12 +301,19 @@ public void Initialize()
FieldFlags addFlags = (FieldFlags)0;
FieldFlags removeFlags = (FieldFlags)0;
+ string dialectServerType = null;
+ string dialectTypeName = null;
+
if (property != null)
{
column = property.GetCustomAttribute<ColumnAttribute>(false);
display = property.GetCustomAttribute<DisplayNameAttribute>(false);
size = property.GetCustomAttribute<SizeAttribute>(false);
- expression = property.GetCustomAttribute<ExpressionAttribute>(false);
+
+ var expressions = property.GetCustomAttributes<ExpressionAttribute>(false);
+ if (expressions.Any())
+ expression = GetBestMatchingExpression(expressions, ref dialectServerType, ref dialectTypeName);
+
scale = property.GetCustomAttribute<ScaleAttribute>(false);
selectLevel = property.GetCustomAttribute<MinSelectLevelAttribute>(false);
foreignKey = property.GetCustomAttribute<ForeignKeyAttribute>(false);
@@ -6,6 +6,7 @@ namespace Serenity.Data.Mapping
/// Specifies SQL expression this property corresponds to.
/// You may use brackets ([]) to escape identifiers. Brackets will be converted to database specific quotes.
/// </summary>
+ [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ExpressionAttribute : Attribute
{
/// <summary>
@@ -18,5 +19,6 @@ public ExpressionAttribute(string value)
}
public string Value { get; private set; }
+ public string Dialect { get; set; }
}
}
@@ -17,7 +17,7 @@
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
- <ProjectGuid>6f13b7f5-3f1e-4a7f-962d-59ebd3118e83</ProjectGuid>
+ <ProjectGuid>c7fa0438-36aa-4b56-9188-9af75f9cb1a1</ProjectGuid>
<RootNamespace>Serenity.Core</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>

1 comment on commit 8c1d78a

@dfaruque
Contributor

Thank you. I need it.

Please sign in to comment.