Skip to content

Commit 8c09b07

Browse files
committed
Added support for scale and precision.
Added support for negation of expressions.
1 parent 722fb81 commit 8c09b07

File tree

5 files changed

+434
-44
lines changed

5 files changed

+434
-44
lines changed

Lib/CSQLQueryExpress/CSQLQueryExpress.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<PropertyGroup>
44
<TargetFramework>netstandard2.0</TargetFramework>
55
<Title>CSQLQueryExpress</Title>
6-
<Version>1.3.3</Version>
6+
<Version>1.3.4</Version>
77
<Description>A simple c# library to compile TSQL queries</Description>
88
<PackageProjectUrl></PackageProjectUrl>
99
<PackageReadmeFile>README.md</PackageReadmeFile>

Lib/CSQLQueryExpress/Compiler/SQLQueryTranslator.cs

+210-43
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Reflection;
99
using System.Text;
1010
using System.Text.RegularExpressions;
11+
using System.Xml.Linq;
1112

1213
namespace CSQLQueryExpress
1314
{
@@ -710,6 +711,48 @@ private Expression VisitStringMethodCall(MethodCallExpression node)
710711
throw new NotSupportedException(string.Format("The method '{0}' is not supported.", node.Method.Name));
711712
}
712713

714+
private Expression VisitStringNegationMethodCall(MethodCallExpression node)
715+
{
716+
if (node.Method.Name == nameof(string.StartsWith))
717+
{
718+
_queryBuilder.Append("(");
719+
this.Visit(node.Object);
720+
_queryBuilder.Append(" NOT LIKE ");
721+
var valueExpression = (ConstantExpression)node.Arguments[0];
722+
var parameterName = _parametersBuilder.AddParameter($"{valueExpression.Value}%");
723+
_queryBuilder.Append(parameterName);
724+
_queryBuilder.Append(")");
725+
726+
return node;
727+
}
728+
else if (node.Method.Name == nameof(string.EndsWith))
729+
{
730+
_queryBuilder.Append("(");
731+
this.Visit(node.Object);
732+
_queryBuilder.Append(" NOT LIKE ");
733+
var valueExpression = (ConstantExpression)node.Arguments[0];
734+
var parameterName = _parametersBuilder.AddParameter($"%{valueExpression.Value}");
735+
_queryBuilder.Append(parameterName);
736+
_queryBuilder.Append(")");
737+
738+
return node;
739+
}
740+
else if (node.Method.Name == nameof(string.Contains))
741+
{
742+
_queryBuilder.Append("(");
743+
this.Visit(node.Object);
744+
_queryBuilder.Append(" NOT LIKE ");
745+
var valueExpression = (ConstantExpression)node.Arguments[0];
746+
var parameterName = _parametersBuilder.AddParameter($"%{valueExpression.Value}%");
747+
_queryBuilder.Append(parameterName);
748+
_queryBuilder.Append(")");
749+
750+
return node;
751+
}
752+
753+
throw new NotSupportedException(string.Format("The method '{0}' is not supported.", node.Method.Name));
754+
}
755+
713756
public Expression VisitQueryPaginationMethodCall(MethodCallExpression node)
714757
{
715758
if (node.Method.Name == nameof(SQLQueryPaginationExtensions.Offset))
@@ -976,6 +1019,21 @@ private Expression VisitQueryDefinitionMethodCall(MethodCallExpression node)
9761019

9771020
return node;
9781021
}
1022+
else if (node.Method.Name == nameof(SQLQueryDefinitionExtensions.Precision))
1023+
{
1024+
this.Visit(node.Arguments[0]);
1025+
1026+
if (node.Arguments.Count == 1)
1027+
{
1028+
_queryBuilder.Append($"({((ConstantExpression)node.Arguments[1]).Value})");
1029+
}
1030+
else
1031+
{
1032+
_queryBuilder.Append($"({((ConstantExpression)node.Arguments[1]).Value}, {((ConstantExpression)node.Arguments[2]).Value})");
1033+
}
1034+
1035+
return node;
1036+
}
9791037
if (node.Method.Name == nameof(SQLQueryDefinitionExtensions.Asc))
9801038
{
9811039
Visit(node.Arguments[0]);
@@ -998,50 +1056,25 @@ private Expression VisitQueryConditionMethodCall(MethodCallExpression node)
9981056
{
9991057
if (node.Method.Name == nameof(SQLQueryConditionExtension.IsNull))
10001058
{
1001-
if (node.Arguments.Count == 1)
1002-
{
1003-
_queryBuilder.Append("(");
1004-
this.Visit(node.Arguments[0]);
1005-
_queryBuilder.Append(" IS NULL");
1006-
_queryBuilder.Append(")");
1007-
}
1008-
else
1009-
{
1010-
_queryBuilder.Append("ISNULL(");
1011-
this.Visit(node.Arguments[0]);
1012-
_queryBuilder.Append(", ");
1013-
this.Visit(node.Arguments[1]);
1014-
_queryBuilder.Append(")");
1015-
}
1059+
TranslateIsNullCondition(node);
10161060

10171061
return node;
10181062
}
10191063
else if (node.Method.Name == nameof(SQLQueryConditionExtension.IsNotNull))
10201064
{
1021-
_queryBuilder.Append("(");
1022-
this.Visit(node.Arguments[0]);
1023-
_queryBuilder.Append(" IS NOT NULL");
1024-
_queryBuilder.Append(")");
1065+
TranslateIsNotNullCondition(node);
10251066

10261067
return node;
10271068
}
10281069
else if (node.Method.Name == nameof(SQLQueryConditionExtension.In))
10291070
{
1030-
_queryBuilder.Append("(");
1031-
this.Visit(node.Arguments[0]);
1032-
_queryBuilder.Append(" IN (");
1033-
this.Visit(node.Arguments[1]);
1034-
_queryBuilder.Append("))");
1071+
TranslateInCondition(node);
10351072

10361073
return node;
10371074
}
10381075
else if (node.Method.Name == nameof(SQLQueryConditionExtension.NotIn))
10391076
{
1040-
_queryBuilder.Append("(");
1041-
this.Visit(node.Arguments[0]);
1042-
_queryBuilder.Append(" NOT IN (");
1043-
this.Visit(node.Arguments[1]);
1044-
_queryBuilder.Append("))");
1077+
TranslateNotInCondition(node);
10451078

10461079
return node;
10471080
}
@@ -1054,42 +1087,161 @@ private Expression VisitQueryConditionMethodCall(MethodCallExpression node)
10541087
}
10551088
else if (node.Method.Name == nameof(SQLQueryConditionExtension.Exists))
10561089
{
1057-
_queryBuilder.Append("EXISTS ");
1058-
this.Visit(node.Arguments[1]);
1090+
TranslateExistsCondition(node);
10591091

10601092
return node;
10611093
}
10621094
else if (node.Method.Name == nameof(SQLQueryConditionExtension.NotExists))
10631095
{
1064-
_queryBuilder.Append("NOT EXISTS ");
1065-
this.Visit(node.Arguments[1]);
1096+
TranslateNotExistsCondition(node);
10661097

10671098
return node;
10681099
}
10691100
else if (node.Method.Name == nameof(SQLQueryConditionExtension.Between))
10701101
{
1071-
this.Visit(node.Arguments[0]);
1072-
_queryBuilder.Append(" BETWEEN ");
1073-
this.Visit(node.Arguments[1]);
1074-
_queryBuilder.Append(" AND ");
1075-
this.Visit(node.Arguments[2]);
1102+
TranslateBetweenCondition(node);
10761103

10771104
return node;
10781105
}
10791106
else if (node.Method.Name == nameof(SQLQueryConditionExtension.NotBetween))
10801107
{
1081-
this.Visit(node.Arguments[0]);
1082-
_queryBuilder.Append(" NOT BETWEEN ");
1083-
this.Visit(node.Arguments[1]);
1084-
_queryBuilder.Append(" AND ");
1085-
this.Visit(node.Arguments[2]);
1108+
TranslateNotBetweenCondition(node);
10861109

10871110
return node;
10881111
}
10891112

10901113
throw new NotSupportedException(string.Format("The method '{0}' is not supported.", node.Method.Name));
10911114
}
10921115

1116+
private Expression VisitQueryConditionNegationMethodCall(MethodCallExpression node)
1117+
{
1118+
if (node.Method.Name == nameof(SQLQueryConditionExtension.IsNull))
1119+
{
1120+
TranslateIsNotNullCondition(node);
1121+
1122+
return node;
1123+
}
1124+
else if (node.Method.Name == nameof(SQLQueryConditionExtension.IsNotNull))
1125+
{
1126+
TranslateIsNullCondition(node);
1127+
1128+
return node;
1129+
}
1130+
else if (node.Method.Name == nameof(SQLQueryConditionExtension.In))
1131+
{
1132+
TranslateNotInCondition(node);
1133+
1134+
return node;
1135+
}
1136+
else if (node.Method.Name == nameof(SQLQueryConditionExtension.NotIn))
1137+
{
1138+
TranslateInCondition(node);
1139+
1140+
return node;
1141+
}
1142+
else if (node.Method.Name == nameof(SQLQueryConditionExtension.Exists))
1143+
{
1144+
TranslateNotExistsCondition(node);
1145+
1146+
return node;
1147+
}
1148+
else if (node.Method.Name == nameof(SQLQueryConditionExtension.NotExists))
1149+
{
1150+
TranslateExistsCondition(node);
1151+
1152+
return node;
1153+
}
1154+
else if (node.Method.Name == nameof(SQLQueryConditionExtension.Between))
1155+
{
1156+
TranslateNotBetweenCondition(node);
1157+
1158+
return node;
1159+
}
1160+
else if (node.Method.Name == nameof(SQLQueryConditionExtension.NotBetween))
1161+
{
1162+
TranslateBetweenCondition(node);
1163+
1164+
return node;
1165+
}
1166+
1167+
throw new NotSupportedException(string.Format("The method '{0}' is not supported.", node.Method.Name));
1168+
}
1169+
1170+
private void TranslateBetweenCondition(MethodCallExpression methodCallExp)
1171+
{
1172+
this.Visit(methodCallExp.Arguments[0]);
1173+
_queryBuilder.Append(" BETWEEN ");
1174+
this.Visit(methodCallExp.Arguments[1]);
1175+
_queryBuilder.Append(" AND ");
1176+
this.Visit(methodCallExp.Arguments[2]);
1177+
}
1178+
1179+
private void TranslateNotBetweenCondition(MethodCallExpression methodCallExp)
1180+
{
1181+
this.Visit(methodCallExp.Arguments[0]);
1182+
_queryBuilder.Append(" NOT BETWEEN ");
1183+
this.Visit(methodCallExp.Arguments[1]);
1184+
_queryBuilder.Append(" AND ");
1185+
this.Visit(methodCallExp.Arguments[2]);
1186+
}
1187+
1188+
private void TranslateExistsCondition(MethodCallExpression methodCallExp)
1189+
{
1190+
_queryBuilder.Append("EXISTS ");
1191+
this.Visit(methodCallExp.Arguments[1]);
1192+
}
1193+
1194+
private void TranslateNotExistsCondition(MethodCallExpression methodCallExp)
1195+
{
1196+
_queryBuilder.Append("NOT EXISTS ");
1197+
this.Visit(methodCallExp.Arguments[1]);
1198+
}
1199+
1200+
private void TranslateInCondition(MethodCallExpression methodCallExp)
1201+
{
1202+
_queryBuilder.Append("(");
1203+
this.Visit(methodCallExp.Arguments[0]);
1204+
_queryBuilder.Append(" IN (");
1205+
this.Visit(methodCallExp.Arguments[1]);
1206+
_queryBuilder.Append("))");
1207+
}
1208+
1209+
private void TranslateNotInCondition(MethodCallExpression methodCallExp)
1210+
{
1211+
_queryBuilder.Append("(");
1212+
this.Visit(methodCallExp.Arguments[0]);
1213+
_queryBuilder.Append(" NOT IN (");
1214+
this.Visit(methodCallExp.Arguments[1]);
1215+
_queryBuilder.Append("))");
1216+
}
1217+
1218+
private void TranslateIsNullCondition(MethodCallExpression methodCallExp)
1219+
{
1220+
if (methodCallExp.Arguments.Count == 1)
1221+
{
1222+
_queryBuilder.Append("(");
1223+
this.Visit(methodCallExp.Arguments[0]);
1224+
_queryBuilder.Append(" IS NULL");
1225+
_queryBuilder.Append(")");
1226+
}
1227+
else
1228+
{
1229+
_queryBuilder.Append("ISNULL(");
1230+
this.Visit(methodCallExp.Arguments[0]);
1231+
_queryBuilder.Append(", ");
1232+
this.Visit(methodCallExp.Arguments[1]);
1233+
_queryBuilder.Append(")");
1234+
}
1235+
}
1236+
1237+
private void TranslateIsNotNullCondition(MethodCallExpression methodCallExp)
1238+
{
1239+
_queryBuilder.Append("(");
1240+
this.Visit(methodCallExp.Arguments[0]);
1241+
_queryBuilder.Append(" IS NOT NULL");
1242+
_queryBuilder.Append(")");
1243+
}
1244+
10931245
private Expression VisitQueryOperationMethodCall(MethodCallExpression node)
10941246
{
10951247
if (node.Method.Name == nameof(SQLQueryOperationExtensions.Sum))
@@ -1627,6 +1779,21 @@ protected override Expression VisitUnary(UnaryExpression node)
16271779

16281780
return node;
16291781
}
1782+
else if (_fragmentType == SQLQueryFragmentType.Where &&
1783+
node.NodeType == ExpressionType.Not &&
1784+
node.Operand.NodeType == ExpressionType.Call)
1785+
{
1786+
var methodCallExp = (MethodCallExpression)node.Operand;
1787+
var declaringType = methodCallExp.Method.DeclaringType;
1788+
if (declaringType == typeof(SQLQueryConditionExtension))
1789+
{
1790+
return VisitQueryConditionNegationMethodCall(methodCallExp);
1791+
}
1792+
else if (declaringType == typeof(string))
1793+
{
1794+
return VisitStringNegationMethodCall(methodCallExp);
1795+
}
1796+
}
16301797

16311798
return base.VisitUnary(node);
16321799
}

Lib/CSQLQueryExpress/Extensions/SQLQueryDefinitionExtensions.cs

+10
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ public static SqlDbType Size(this SqlDbType type, int size)
99
return default;
1010
}
1111

12+
public static SqlDbType Precision(this SqlDbType type, int precision)
13+
{
14+
return default;
15+
}
16+
17+
public static SqlDbType Precision(this SqlDbType type, int precision, int scale)
18+
{
19+
return default;
20+
}
21+
1222
public static SqlDbType Max(this SqlDbType type)
1323
{
1424
return default;

0 commit comments

Comments
 (0)