better param checks for built-in value functions (#8)
This commit is contained in:
Родитель
bc9fcc694d
Коммит
4a661c7358
|
@ -10,10 +10,10 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="openCypherTranspiler.Common" Version="0.1.0" />
|
||||
<PackageReference Include="openCypherTranspiler.openCypherParser" Version="0.1.0" />
|
||||
<PackageReference Include="openCypherTranspiler.LogicalPlanner" Version="0.1.0" />
|
||||
<PackageReference Include="openCypherTranspiler.SQLRenderer" Version="0.1.0" />
|
||||
<PackageReference Include="openCypherTranspiler.Common" Version="0.1.1" />
|
||||
<PackageReference Include="openCypherTranspiler.openCypherParser" Version="0.1.1" />
|
||||
<PackageReference Include="openCypherTranspiler.LogicalPlanner" Version="0.1.1" />
|
||||
<PackageReference Include="openCypherTranspiler.SQLRenderer" Version="0.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<PackageTags>openCypher transpiler graph C# .NET</PackageTags>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/microsoft/openCypherTranspiler/tree/master/src/openCypherParser</RepositoryUrl>
|
||||
<VersionPrefix>0.1.0</VersionPrefix>
|
||||
<VersionPrefix>0.1.1</VersionPrefix>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace openCypherTranspiler.Common.Utils
|
|||
/// <summary>
|
||||
/// Check if null value can be assigned
|
||||
/// E.g. IsNullableType(string) = true, IsNullableType(DateTime) = false
|
||||
/// IsNullableType(
|
||||
/// IsNullableType(System.Nullable<int>) = true
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<PackageTags>openCypher transpiler graph C# .NET</PackageTags>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/microsoft/openCypherTranspiler/tree/master/src/LogicalPlanner</RepositoryUrl>
|
||||
<VersionPrefix>0.1.0</VersionPrefix>
|
||||
<VersionPrefix>0.1.1</VersionPrefix>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<PackageTags>openCypher transpiler graph C# .NET</PackageTags>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/microsoft/openCypherTranspiler/tree/master/src/openCypherParser</RepositoryUrl>
|
||||
<VersionPrefix>0.1.0</VersionPrefix>
|
||||
<VersionPrefix>0.1.1</VersionPrefix>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -39,23 +39,23 @@ namespace openCypherTranspiler.openCypherParser.AST
|
|||
public override Type EvaluateType()
|
||||
{
|
||||
var innerType = InnerExpression.EvaluateType();
|
||||
var isWrappedinNullable = TypeHelper.IsSystemNullableType(innerType);
|
||||
var canBeNull = TypeHelper.CanAssignNullToType(innerType);
|
||||
switch (Function.FunctionName)
|
||||
{
|
||||
case Common.Function.ToFloat:
|
||||
return isWrappedinNullable ? typeof(float?) : typeof(float);
|
||||
return canBeNull ? typeof(float?) : typeof(float);
|
||||
case Common.Function.ToString:
|
||||
return typeof(string);
|
||||
case Common.Function.ToBoolean:
|
||||
return isWrappedinNullable ? typeof(bool?) : typeof(bool);
|
||||
return canBeNull ? typeof(bool?) : typeof(bool);
|
||||
case Common.Function.ToInteger:
|
||||
return isWrappedinNullable ? typeof(int?) : typeof(int);
|
||||
return canBeNull ? typeof(int?) : typeof(int);
|
||||
case Common.Function.ToDouble:
|
||||
return isWrappedinNullable ? typeof(long?) : typeof(long);
|
||||
return canBeNull ? typeof(long?) : typeof(long);
|
||||
case Common.Function.ToLong:
|
||||
return isWrappedinNullable ? typeof(double?) : typeof(double);
|
||||
return canBeNull ? typeof(double?) : typeof(double);
|
||||
case Common.Function.Not:
|
||||
return isWrappedinNullable ? typeof(bool?) : typeof(bool);
|
||||
return canBeNull ? typeof(bool?) : typeof(bool);
|
||||
case Common.Function.StringContains:
|
||||
case Common.Function.StringStartsWith:
|
||||
case Common.Function.StringEndsWith:
|
||||
|
|
|
@ -82,6 +82,26 @@ namespace openCypherTranspiler.openCypherParser.Common
|
|||
}
|
||||
}
|
||||
|
||||
private static void EnsureStringType(FunctionInfo info, Type type)
|
||||
{
|
||||
if (!(
|
||||
type == typeof(string)
|
||||
))
|
||||
{
|
||||
throw new TranspilerNotSupportedException($"Function {info.FunctionName} parameter of type {type.Name}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsureLengthType(FunctionInfo info, Type type)
|
||||
{
|
||||
if (!(
|
||||
type == typeof(int) || type == typeof(long)
|
||||
))
|
||||
{
|
||||
throw new TranspilerNotSupportedException($"Function {info.FunctionName} parameter of type {type.Name}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsureBooleanType(FunctionInfo info, Type type)
|
||||
{
|
||||
if (!(
|
||||
|
@ -188,7 +208,11 @@ namespace openCypherTranspiler.openCypherParser.Common
|
|||
FunctionName = Function.StringStartsWith,
|
||||
RequiredParameters = 2,
|
||||
OptionalParameters = 0,
|
||||
ParameterChecker = EnsureParameterCountChecker
|
||||
ParameterChecker = (info, types) => {
|
||||
EnsureParameterCount(info, types.Count());
|
||||
EnsureStringType(info, types.First());
|
||||
EnsureStringType(info, types.Skip(1).First());
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "stringendswith", new FunctionInfo()
|
||||
|
@ -196,7 +220,11 @@ namespace openCypherTranspiler.openCypherParser.Common
|
|||
FunctionName = Function.StringEndsWith,
|
||||
RequiredParameters = 2,
|
||||
OptionalParameters = 0,
|
||||
ParameterChecker = EnsureParameterCountChecker
|
||||
ParameterChecker = (info, types) => {
|
||||
EnsureParameterCount(info, types.Count());
|
||||
EnsureStringType(info, types.First());
|
||||
EnsureStringType(info, types.Skip(1).First());
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "stringcontains", new FunctionInfo()
|
||||
|
@ -204,7 +232,11 @@ namespace openCypherTranspiler.openCypherParser.Common
|
|||
FunctionName = Function.StringContains,
|
||||
RequiredParameters = 2,
|
||||
OptionalParameters = 0,
|
||||
ParameterChecker = EnsureParameterCountChecker
|
||||
ParameterChecker = (info, types) => {
|
||||
EnsureParameterCount(info, types.Count());
|
||||
EnsureStringType(info, types.First());
|
||||
EnsureStringType(info, types.Skip(1).First());
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "isnull", new FunctionInfo()
|
||||
|
@ -228,7 +260,11 @@ namespace openCypherTranspiler.openCypherParser.Common
|
|||
FunctionName = Function.StringLeft,
|
||||
RequiredParameters = 2,
|
||||
OptionalParameters = 0,
|
||||
ParameterChecker = EnsureParameterCountChecker
|
||||
ParameterChecker = (info, types) => {
|
||||
EnsureParameterCount(info, types.Count());
|
||||
EnsureStringType(info, types.First());
|
||||
EnsureLengthType(info, types.Skip(1).First());
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "right", new FunctionInfo()
|
||||
|
@ -236,7 +272,11 @@ namespace openCypherTranspiler.openCypherParser.Common
|
|||
FunctionName = Function.StringRight,
|
||||
RequiredParameters = 2,
|
||||
OptionalParameters = 0,
|
||||
ParameterChecker = EnsureParameterCountChecker
|
||||
ParameterChecker = (info, types) => {
|
||||
EnsureParameterCount(info, types.Count());
|
||||
EnsureStringType(info, types.First());
|
||||
EnsureLengthType(info, types.Skip(1).First());
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "trim", new FunctionInfo()
|
||||
|
@ -244,7 +284,10 @@ namespace openCypherTranspiler.openCypherParser.Common
|
|||
FunctionName = Function.StringTrim,
|
||||
RequiredParameters = 1,
|
||||
OptionalParameters = 0,
|
||||
ParameterChecker = EnsureParameterCountChecker
|
||||
ParameterChecker = (info, types) => {
|
||||
EnsureParameterCount(info, types.Count());
|
||||
EnsureStringType(info, types.First());
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "ltrim", new FunctionInfo()
|
||||
|
@ -252,7 +295,10 @@ namespace openCypherTranspiler.openCypherParser.Common
|
|||
FunctionName = Function.StringLTrim,
|
||||
RequiredParameters = 1,
|
||||
OptionalParameters = 0,
|
||||
ParameterChecker = EnsureParameterCountChecker
|
||||
ParameterChecker = (info, types) => {
|
||||
EnsureParameterCount(info, types.Count());
|
||||
EnsureStringType(info, types.First());
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "rtrim", new FunctionInfo()
|
||||
|
@ -260,7 +306,10 @@ namespace openCypherTranspiler.openCypherParser.Common
|
|||
FunctionName = Function.StringRTrim,
|
||||
RequiredParameters = 1,
|
||||
OptionalParameters = 0,
|
||||
ParameterChecker = EnsureParameterCountChecker
|
||||
ParameterChecker = (info, types) => {
|
||||
EnsureParameterCount(info, types.Count());
|
||||
EnsureStringType(info, types.First());
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "toupper", new FunctionInfo()
|
||||
|
@ -268,7 +317,10 @@ namespace openCypherTranspiler.openCypherParser.Common
|
|||
FunctionName = Function.StringToUpper,
|
||||
RequiredParameters = 1,
|
||||
OptionalParameters = 0,
|
||||
ParameterChecker = EnsureParameterCountChecker
|
||||
ParameterChecker = (info, types) => {
|
||||
EnsureParameterCount(info, types.Count());
|
||||
EnsureStringType(info, types.First());
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "tolower", new FunctionInfo()
|
||||
|
@ -276,7 +328,10 @@ namespace openCypherTranspiler.openCypherParser.Common
|
|||
FunctionName = Function.StringToLower,
|
||||
RequiredParameters = 1,
|
||||
OptionalParameters = 0,
|
||||
ParameterChecker = EnsureParameterCountChecker
|
||||
ParameterChecker = (info, types) => {
|
||||
EnsureParameterCount(info, types.Count());
|
||||
EnsureStringType(info, types.First());
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "size", new FunctionInfo()
|
||||
|
@ -284,7 +339,10 @@ namespace openCypherTranspiler.openCypherParser.Common
|
|||
FunctionName = Function.StringSize,
|
||||
RequiredParameters = 1,
|
||||
OptionalParameters = 0,
|
||||
ParameterChecker = EnsureParameterCountChecker
|
||||
ParameterChecker = (info, types) => {
|
||||
EnsureParameterCount(info, types.Count());
|
||||
EnsureStringType(info, types.First());
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<PackageTags>openCypher transpiler graph C# .NET</PackageTags>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/microsoft/openCypherTranspiler/tree/master/src/openCypherParser</RepositoryUrl>
|
||||
<VersionPrefix>0.1.0</VersionPrefix>
|
||||
<VersionPrefix>0.1.1</VersionPrefix>
|
||||
<NoWarn>CS3021</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ using openCypherTranspiler.openCypherParser;
|
|||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Linq;
|
||||
using JT = openCypherTranspiler.LogicalPlanner.JoinOperator.JoinType;
|
||||
using System;
|
||||
|
||||
namespace openCypherTranspiler.LogicalPlanner.Test
|
||||
{
|
||||
|
@ -352,6 +353,30 @@ ORDER BY p.Name LIMIT 3
|
|||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TypeEvaluationTest()
|
||||
{
|
||||
IGraphSchemaProvider graphDef = new JSONGraphSchema(@"./TestData/MovieGraph.json");
|
||||
// Basic test covers type coercion and type evaluation
|
||||
{
|
||||
var lp = RunQueryAndDumpTree(graphDef, @"
|
||||
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
|
||||
WITH toString(m.Released) as ReleasedStr, m.Released as ReleasedInt
|
||||
RETURN toInteger(ReleasedStr) as Released, toFloat(ReleasedStr) as ReleasedFloat, toFloat(ReleasedStr)/10.0 as ReleasedDouble, toBoolean(""true"") as ReleasedBool, toFloat(ReleasedStr)+ReleasedInt as ReleasedFloat2
|
||||
"
|
||||
);
|
||||
|
||||
Assert.IsTrue(lp.StartingOperators.Count() > 0);
|
||||
Assert.IsTrue(lp.TerminalOperators.Count() == 1);
|
||||
Assert.IsTrue(lp.TerminalOperators.First().OutputSchema.Count == 5);
|
||||
Assert.IsTrue(lp.TerminalOperators.First().OutputSchema.Any(o => o.FieldAlias == "Released" && ((o as ValueField)?.FieldType ?? default(Type)) == typeof(int?)));
|
||||
Assert.IsTrue(lp.TerminalOperators.First().OutputSchema.Any(o => o.FieldAlias == "ReleasedFloat" && ((o as ValueField)?.FieldType ?? default(Type)) == typeof(float?)));
|
||||
Assert.IsTrue(lp.TerminalOperators.First().OutputSchema.Any(o => o.FieldAlias == "ReleasedDouble" && ((o as ValueField)?.FieldType ?? default(Type)) == typeof(double?)));
|
||||
Assert.IsTrue(lp.TerminalOperators.First().OutputSchema.Any(o => o.FieldAlias == "ReleasedBool" && ((o as ValueField)?.FieldType ?? default(Type)) == typeof(bool?)));
|
||||
Assert.IsTrue(lp.TerminalOperators.First().OutputSchema.Any(o => o.FieldAlias == "ReleasedFloat2" && ((o as ValueField)?.FieldType ?? default(Type)) == typeof(float?)));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AdvancedTestLogicalPlanner()
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче