This commit is contained in:
Jerry Liang 2019-07-25 11:32:32 -07:00
Родитель 073e9ad03f
Коммит 5ec98d81ea
75 изменённых файлов: 28252 добавлений и 1 удалений

3
.gitignore поставляемый
Просмотреть файл

@ -3,6 +3,9 @@
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# Project specific ignores
**/*.private.*
# User-specific files
*.suo
*.user

Просмотреть файл

@ -1,5 +1,54 @@
# openCypher Transpiler
# Contributing
This library help you to build an [openCypher](http://www.opencypher.org/) query layer on top of a relational database or structured data in data lakes. Built on top of this library, you can transpile openCypher query into a target query language used by the relational database. We have provided a sample target language renderer for [T-SQL](https://docs.microsoft.com/en-us/sql/t-sql/language-reference?view=sql-server-2017).
Originally we built this library to provide a [Property Graph](https://neo4j.com/developer/graph-database/#property-graph) data-layer for the petabyte-scale data assets in the Azure Data Lake. The property graph enables us to organize a vast catalog of data in an intuitive and traceable way. The openCypher query language allows data users that are already familiar with SQL-alike declarative query language to query the data assets with ease: in a graph where the relationship between data entities is a first class citizen, the data users no longer need to spend time on figuring out how individual data assets should be joined together. The data producers who are experts on their data would be the one to help define the relationship and is able to ensure its quality for downstream consumptions.
This library has three main components:
* A openCypher parser built on top of ANTLR4 and official openCypher grammar to parse and create an [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) to abstract the syntactical structure of the graph query;
* A logic planner transforms the AST into relational query logical plan similar to the [Relational Algebra](https://en.wikipedia.org/wiki/Relational_algebra);
* A query code renderer produces the actual query code from the logical plan. In this repository, we provides a T-SQL renderer.
The library, written in [.Net Core](https://dotnet.microsoft.com/download), is cross-platform.
## Using the library
```CSharp
// To Be Provided
```
## Build on top of this library
```CSharp
// To Be Provided
```
## Test designs
Transpiler is tested using the T-SQL target renderer and its results are compared against what is produced by Cypher from the [Neo4j Graph Database](https://neo4j.com/graph-database). Each test compares the query results from the transpiled query on [Microsoft SQL for Linux](https://www.microsoft.com/en-us/sql-server/sql-server-2017) against Cypher on Neo4j 3.x to ensure they are consistent in term of data type and contents.
To run the tests, simply run under the project root folder:
```batch
dotnet test
```
## Limitations To Be Addressed
* MATCH pattern with unspecified labels which cannot be implied to a single label/relationship type
* MATCH pattern with variable-length relationship
* The logical plan is currently not further optimized with assumption the underlying RDBMS engine does this work
* list,collect,UNWIND is currently not supported
* Source table must already been normalized to be used as graph node/edge
* Readonly query is supported. CALL and write (such as MERGE) is not supported.
## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us

72
oCTranspiler.sln Normal file
Просмотреть файл

@ -0,0 +1,72 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.572
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "openCypherParser", "src\openCypherParser\openCypherParser.csproj", "{81AECE85-4C3D-4921-93F3-0619B4691B9E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common", "src\Common\Common.csproj", "{7BAC3CBC-9B05-4E3D-A530-F909E2D1BE95}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogicalPlanner", "src\LogicalPlanner\LogicalPlanner.csproj", "{ECA217C3-9DAF-48CF-93B3-43B150D06434}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "openCypherParser.Test", "tests\openCypherParser.Test\openCypherParser.Test.csproj", "{1B8A8206-1D57-483E-8F62-C9E0E3DEC2A1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommonTest", "tests\CommonTest\CommonTest.csproj", "{D61781A2-CEAC-45E5-A16F-C07C76AB5B58}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogicalPlanner.Test", "tests\LogicalPlanner.Test\LogicalPlanner.Test.csproj", "{9FE97D48-A6A2-40B2-B373-BB6FC9E03989}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SQLRenderer", "src\SQLRenderer\SQLRenderer.csproj", "{6B944CB5-0E6E-41A8-A19B-CB9AC23FA65A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E43CA3A8-7668-47D1-ABD1-07A3F2497C59}"
ProjectSection(SolutionItems) = preProject
README.md = README.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLRenderer.Test", "tests\SQLRenderer.Test\SQLRenderer.Test.csproj", "{A4874F73-84FF-4633-925D-BB80823FF8CD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{81AECE85-4C3D-4921-93F3-0619B4691B9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{81AECE85-4C3D-4921-93F3-0619B4691B9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{81AECE85-4C3D-4921-93F3-0619B4691B9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{81AECE85-4C3D-4921-93F3-0619B4691B9E}.Release|Any CPU.Build.0 = Release|Any CPU
{7BAC3CBC-9B05-4E3D-A530-F909E2D1BE95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7BAC3CBC-9B05-4E3D-A530-F909E2D1BE95}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7BAC3CBC-9B05-4E3D-A530-F909E2D1BE95}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7BAC3CBC-9B05-4E3D-A530-F909E2D1BE95}.Release|Any CPU.Build.0 = Release|Any CPU
{ECA217C3-9DAF-48CF-93B3-43B150D06434}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ECA217C3-9DAF-48CF-93B3-43B150D06434}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ECA217C3-9DAF-48CF-93B3-43B150D06434}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ECA217C3-9DAF-48CF-93B3-43B150D06434}.Release|Any CPU.Build.0 = Release|Any CPU
{1B8A8206-1D57-483E-8F62-C9E0E3DEC2A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1B8A8206-1D57-483E-8F62-C9E0E3DEC2A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1B8A8206-1D57-483E-8F62-C9E0E3DEC2A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1B8A8206-1D57-483E-8F62-C9E0E3DEC2A1}.Release|Any CPU.Build.0 = Release|Any CPU
{D61781A2-CEAC-45E5-A16F-C07C76AB5B58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D61781A2-CEAC-45E5-A16F-C07C76AB5B58}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D61781A2-CEAC-45E5-A16F-C07C76AB5B58}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D61781A2-CEAC-45E5-A16F-C07C76AB5B58}.Release|Any CPU.Build.0 = Release|Any CPU
{9FE97D48-A6A2-40B2-B373-BB6FC9E03989}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9FE97D48-A6A2-40B2-B373-BB6FC9E03989}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9FE97D48-A6A2-40B2-B373-BB6FC9E03989}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9FE97D48-A6A2-40B2-B373-BB6FC9E03989}.Release|Any CPU.Build.0 = Release|Any CPU
{6B944CB5-0E6E-41A8-A19B-CB9AC23FA65A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6B944CB5-0E6E-41A8-A19B-CB9AC23FA65A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6B944CB5-0E6E-41A8-A19B-CB9AC23FA65A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6B944CB5-0E6E-41A8-A19B-CB9AC23FA65A}.Release|Any CPU.Build.0 = Release|Any CPU
{A4874F73-84FF-4633-925D-BB80823FF8CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A4874F73-84FF-4633-925D-BB80823FF8CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A4874F73-84FF-4633-925D-BB80823FF8CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A4874F73-84FF-4633-925D-BB80823FF8CD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {927270C0-4539-450F-B889-E8FF08FDAE54}
EndGlobalSection
EndGlobal

14
src/Common/Common.csproj Normal file
Просмотреть файл

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RootNamespace>Microsoft.GraphPlatform.Transpiler.Common</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Folder Include="Logging\" />
<Folder Include="GraphSchema\" />
<Folder Include="Utils\" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,19 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
namespace openCypherTranspiler.Common.Exceptions
{
/// <summary>
/// Exception during data source binding
/// </summary>
public class TranspilerBindingException : TranspilerException
{
public TranspilerBindingException(string bindingErrorMsg) :
base($"Data binding error error: {bindingErrorMsg}")
{
}
}
}

Просмотреть файл

@ -0,0 +1,21 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
namespace openCypherTranspiler.Common.Exceptions
{
/// <summary>
/// General exception thrown by the Transpiler
/// </summary>
public abstract class TranspilerException : Exception
{
public TranspilerException(string exceptionMsg) :
base(exceptionMsg)
{
}
}
}

Просмотреть файл

@ -0,0 +1,18 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
namespace openCypherTranspiler.Common.Exceptions
{
/// <summary>
/// Exception representing unexpected internal errors thrown by the transpiler
/// </summary>
public class TranspilerInternalErrorException : TranspilerException
{
public TranspilerInternalErrorException(string intErrMsg) : base($"Unexpected internal error: {intErrMsg}")
{
}
}
}

Просмотреть файл

@ -0,0 +1,21 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
namespace openCypherTranspiler.Common.Exceptions
{
/// <summary>
/// Specific exception thrown by scenarios that were explicitly blocked
/// </summary>
public class TranspilerNotSupportedException : Exception
{
public TranspilerNotSupportedException(string functionNotSupported) :
base($"{functionNotSupported} is not supported by the code generator.")
{
}
}
}

Просмотреть файл

@ -0,0 +1,21 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
namespace openCypherTranspiler.Common.Exceptions
{
/// <summary>
/// Exceptions raised from language syntax error
/// </summary>
public class TranspilerSyntaxErrorException : Exception
{
public TranspilerSyntaxErrorException(string syntaxErrorMsg) :
base($"Syntax error: {syntaxErrorMsg}")
{
}
}
}

Просмотреть файл

@ -0,0 +1,44 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
namespace openCypherTranspiler.Common.GraphSchema
{
public class EdgeSchema : EntitySchema
{
public static char Separator = '@';
public static string GetEdgeId(string verb, string nodeFromName, string nodeToName)
{
return $"{nodeFromName}{Separator}{verb}{Separator}{nodeToName}";
}
/// <summary>
/// The identifier of edge
/// </summary>
public override string Id
{
get
{
return GetEdgeId(Name, SourceNodeId, SinkNodeId);
}
}
public EntityProperty SourceIdProperty { get; set; }
public EntityProperty SinkIdProperty { get; set; }
/// <summary>
/// The identifier of the source node schema this edge schema links to
/// </summary>
public string SourceNodeId { get; set; }
/// <summary>
/// The identifier of the sink node schema this edge schema links to
/// </summary>
public string SinkNodeId { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
namespace openCypherTranspiler.Common.GraphSchema
{
public class EntityProperty
{
public enum PropertyDefinitionType
{
NodeJoinKey,
SourceNodeJoinKey,
SinkNodeJoinKey,
RegularProperty,
Label,
SourceNodeLabel,
SinkNodeLabel,
NodeSampleKey,
SourceNodeSampleKey,
SinkNodeSampleKey
};
public string PropertyName { get; set; }
public Type DataType { get; set; }
public PropertyDefinitionType PropertyType { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System.Collections.Generic;
namespace openCypherTranspiler.Common.GraphSchema
{
/// <summary>
/// Base class to descript a graph schema entity (can be a node or edge)
/// </summary>
public abstract class EntitySchema
{
/// <summary>
/// Unique name to the node/edge. For node it is nodename, for edge it is unique
/// combination of node from/to plus edge verb
/// </summary>
public abstract string Id { get; }
/// <summary>
/// Name of the node or edge. In case of edge it is the 'verb' only
/// </summary>
public string Name { get; set; }
/// <summary>
/// List of all properties on the node/edge (combining all parts)
/// </summary>
public IList<EntityProperty> Properties { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,35 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System.Collections.Generic;
using System.Threading.Tasks;
namespace openCypherTranspiler.Common.GraphSchema
{
/// <summary>
/// Implements by the Graph Schema provider to allow query the graph definition
/// </summary>
public interface IGraphSchemaProvider
{
/// <summary>
/// Return a NodeDefinition for the given node name.
/// </summary>
/// <param name="nodeName"></param>
/// <exception cref="KeyNotFoundException">if node name was not found</exception>
/// <returns></returns>
NodeSchema GetNodeDefinition(string nodeName);
/// <summary>
/// Return a NodeDefinition for the given edge verb, source and sink entity name.
/// </summary>
/// <param name="edgeVerb"></param>
/// <param name="fromNodeName"></param>
/// <param name="toNodeName"></param>
/// <exception cref="KeyNotFoundException">if node name was not found</exception>
/// <returns></returns>
EdgeSchema GetEdgeDefinition(string edgeVerb, string fromNodeName, string toNodeName);
}
}

Просмотреть файл

@ -0,0 +1,21 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
namespace openCypherTranspiler.Common.GraphSchema
{
public class NodeSchema : EntitySchema
{
public override string Id
{
get
{
return Name;
}
}
public EntityProperty NodeIdProperty { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,99 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
namespace openCypherTranspiler.Common.Logging
{
public abstract class BaseLogger : ILoggable
{
protected LoggingLevel _currentLogLevel = LoggingLevel.Normal;
public void SetLoggingLevel(LoggingLevel logLevel)
{
_currentLogLevel = logLevel;
}
public void Log(string msgFormat, params object[] msgArgs)
{
if (_currentLogLevel >= LoggingLevel.Normal)
{
LogMessage(msgFormat, msgArgs);
}
}
public void LogCritical(string msgFormat, params object[] msgArgs)
{
if (_currentLogLevel >= LoggingLevel.CriticalOnly)
{
LogMessage(msgFormat, msgArgs);
}
}
public void LogVerbose(string msgFormat, params object[] msgArgs)
{
if (_currentLogLevel >= LoggingLevel.Verbose)
{
LogMessage(msgFormat, msgArgs);
}
}
public void LogCritical(string msg)
{
LogCritical("{0}", msg);
}
public void Log(string msg)
{
Log("{0}", msg);
}
public void LogVerbose(string msg)
{
LogVerbose("{0}", msg);
}
public void LogFuncVerbose(
string msg,
[System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0
)
{
if (_currentLogLevel >= LoggingLevel.Verbose)
{
LogMessage("{0}: {1}", memberName, msg);
}
}
public void LogFunc(
string msg,
[System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0
)
{
if (_currentLogLevel >= LoggingLevel.Normal)
{
LogMessage("{0}: {1}", memberName, msg);
}
}
public void LogFuncCritical(string msg,
[System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0
)
{
LogMessage("{0}: {1}", memberName, msg);
}
/// <summary>
/// This is the only method that child logger class need to implement
/// </summary>
/// <param name="msgFormat"></param>
/// <param name="msgArgs"></param>
abstract protected void LogMessage(string msgFormat, params object[] msgArgs);
}
}

Просмотреть файл

@ -0,0 +1,52 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
namespace openCypherTranspiler.Common.Logging
{
public enum LoggingLevel
{
CriticalOnly,
Normal,
Verbose,
}
/// <summary>
/// Inteface for the logger used through out this project
/// </summary>
public interface ILoggable
{
void SetLoggingLevel(LoggingLevel logLevel);
// LogFunc* calls with log the msg with the function name as well
void LogFuncCritical(
string msg,
[System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0
);
void LogFunc(
string msg,
[System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0
);
void LogFuncVerbose(
string msg,
[System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0
);
void LogCritical(string msg);
void LogCritical(string msgFormat, params object[] msgArgs);
void Log(string msg);
void Log(string msgFormat, params object[] msgArgs);
void LogVerbose(string msg);
void LogVerbose(string msgFormat, params object[] msgArgs);
}
}

Просмотреть файл

@ -0,0 +1,63 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Linq;
namespace openCypherTranspiler.Common.Utils
{
public static class FNVHash
{
public static int GetFNVHash(params object[] objs)
{
// FNV hash
unchecked
{
int hash = (int)2166136261;
if (objs != null)
{
foreach (var o in objs)
{
hash = hash * 23 + (o?.GetHashCode() ?? 0);
}
return hash;
}
}
return 0;
}
public static int GetFNVHash(IEnumerable<object> objs)
{
// FNV hash
unchecked
{
int hash = (int)2166136261;
if (objs != null)
{
foreach (var o in objs)
{
hash = hash * 23 + (o?.GetHashCode() ?? 0);
}
return hash;
}
}
return 0;
}
public static uint GetFNVHashUInt(params object[] objs)
{
int hash = GetFNVHash(objs);
return (uint)hash; // this will, for example, convert -1 to 4294967295
}
public static uint GetFNVHashUInt(IEnumerable<object> objs)
{
int hash = GetFNVHash(objs);
return (uint)hash; // this will, for example, convert -1 to 4294967295
}
}
}

Просмотреть файл

@ -0,0 +1,63 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace openCypherTranspiler.Common.Utils
{
public static class TextHelper
{
/// <summary>
/// Helper function to use a regex pattern to clean up a dirty string for
/// certain restriction by another system/api
/// </summary>
/// <param name="originalStr"></param>
/// <param name="regexPat"></param>
/// <returns></returns>
public static string MakeCompliantString(string originalStr, string regexPat)
{
string compStr = "";
foreach (Match m in Regex.Matches(originalStr, regexPat))
{
compStr += m.Value;
}
return compStr;
}
/// <summary>
/// Add or remove indentation at line level
/// </summary>
/// <param name="orgStr"></param>
/// <param name="delta">Positive means adding indentation of delta unit, Negative means remove indentation of delta unit</param>
/// <param name="indentChar"></param>
/// <param name="indentUnitCnt"></param>
/// <returns></returns>
public static string ChangeIndentation(this string text, int delta, char indentChar = ' ', int indentUnitCnt = 4)
{
var lines = Regex.Split(text, "\r\n|\r|\n");
if (delta > 0)
{
var indentation = new string(indentChar, delta * indentUnitCnt);
return string.Join("\r\n", lines.Select(l => $"{indentation}{l}"));
}
else if (delta < 0)
{
var indentationUnit = new string(indentChar, indentUnitCnt);
return string.Join("\r\n", lines.Select(l => Regex.Replace(l, $"^({indentationUnit}){{0,{delta}}}", string.Empty)));
}
else
{
return text;
}
}
}
}

Просмотреть файл

@ -0,0 +1,115 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace openCypherTranspiler.Common.Utils
{
public class TypeHelper
{
/// <summary>
/// Check if null value can be assigned
/// E.g. IsNullableType(string) = true, IsNullableType(DateTime) = false
/// IsNullableType(
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static bool CanAssignNullToType(Type type)
{
if (!type.IsValueType)
{
return true; // ref-type can assign null value
}
if (IsSystemNullableType(type))
{
return true; // Nullable<T> can assign null value
}
return false;
}
/// <summary>
/// Check if a type is System.Nullable<T> or derived from System.Nullable<T>
/// E.g. IsNullableType(string) = false, IsNullableType(System.Nullable<int>) = true
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static bool IsSystemNullableType(Type type)
{
// NOTE: Nullable<T> is sealed type, so no class can derive from it
if (type != default(Type) && Nullable.GetUnderlyingType(type) != null)
{
return true;
}
return false;
}
/// <summary>
/// Given an non-nullable type, wrap it in a System.Nullable<> generic type
/// </summary>
/// <param name="type">Non nullable type</param>
/// <returns></returns>
/// <exception cref="InvalidCastException">Throws InvalidCastException, if type is already nullable.</exception>
public static Type GetNullableTypeForType(Type type)
{
if (CanAssignNullToType(type))
{
throw new InvalidCastException($"Type: {type} is already nullable");
}
return typeof(Nullable<>).MakeGenericType(type);
}
/// <summary>
/// Check if a type is derived from a generic type
/// E.g. class SubClass : Node<int> {} ;
/// IsSubclassOfRawGeneric(typeof(SubClass), Node<>) == true
/// </summary>
/// <param name="generic"></param>
/// <param name="toCheck"></param>
/// <returns></returns>
public static bool IsSubclassOfRawGeneric(Type toCheck, Type generic)
{
while (toCheck != null && toCheck != typeof(object))
{
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (generic == cur)
{
return true;
}
toCheck = toCheck.BaseType;
}
return false;
}
/// <summary>
/// Return the type itself, or for a nullable type, its unboxed type
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static Type GetUnderlyingTypeIfNullable(Type t)
{
var isNullable = IsSystemNullableType(t);
return isNullable ? Nullable.GetUnderlyingType(t) : t;
}
/// <summary>
/// Wrap unnullable type to nullable
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static Type MakeNullableIfNotAlready(Type t)
{
if (!CanAssignNullToType(t))
{
return typeof(Nullable<>).MakeGenericType(t);
}
else
{
return t;
}
}
}
}

Просмотреть файл

@ -0,0 +1,14 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using openCypherTranspiler.Common.GraphSchema;
namespace openCypherTranspiler.LogicalPlanner
{
interface IBindable
{
void Bind(IGraphSchemaProvider graphDefinition);
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,237 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using openCypherTranspiler.Common.Exceptions;
namespace openCypherTranspiler.LogicalPlanner
{
/// <summary>
/// a field of a schema
/// </summary>
public abstract class Field
{
public Field(string alias)
{
FieldAlias = alias;
}
/// <summary>
/// The local unique name (in current operator's context) to refer this field
/// </summary>
public string FieldAlias { get; set; }
/// <summary>
/// Create a deep copy of this Field object
/// </summary>
/// <returns></returns>
public abstract Field Clone();
/// <summary>
/// Copy the information from another field to itself (except for alias)
/// </summary>
public abstract void Copy(Field f);
}
/// <summary>
/// A field which is an entity (a set of columns forming a node or edge stream/stream group)
/// </summary>
public class EntityField : Field
{
private ISet<string> _referencedAliases = new HashSet<string>();
public EntityField(string alias, string entityName, EntityType type) : base(alias)
{
EntityName = entityName;
Type = type;
}
/// <summary>
/// Copy constructor
/// </summary>
/// <param name="field"></param>
public EntityField(EntityField field) : base(field.FieldAlias)
{
Copy(field);
}
public override void Copy(Field field)
{
var fieldSrc = field as EntityField;
Debug.Assert(fieldSrc != null);
this.EntityName = fieldSrc.EntityName;
this.Type = fieldSrc.Type;
this.BoundEntityName = fieldSrc.BoundEntityName;
this.BoundSourceEntityName = fieldSrc.BoundSourceEntityName;
this.BoundSinkEntityName = fieldSrc.BoundSinkEntityName;
this.NodeJoinField = fieldSrc.NodeJoinField?.Clone() as SingleField;
this.RelSinkJoinField = fieldSrc.RelSinkJoinField?.Clone() as SingleField;
this.RelSourceJoinField = fieldSrc.RelSourceJoinField?.Clone() as SingleField;
this.EncapsulatedFields = fieldSrc.EncapsulatedFields?.Select(f => f.Clone() as SingleField).ToList();
_referencedAliases.Clear();
this.AddReferenceFieldAliases(fieldSrc.ReferencedFieldAliases?.ToList());
}
public enum EntityType
{
Node,
Relationship
}
/// <summary>
/// For node this is node name, for edge this is the edge verb
/// </summary>
public string EntityName { get; set; }
/// <summary>
/// This is the name of the entity that this is eventually bound to in the graph definition
/// For node, it is usually same as EntityName, but for edge, it is the unique entity name
/// from the graph definition which is in the format of node_in-verb-node_out
/// </summary>
public string BoundEntityName { get; set; }
/// <summary>
/// This is the name of the source entity name for this relationship (in the graph definition)
/// Only non null for edge type of entity
/// </summary>
public string BoundSourceEntityName { get; set; }
/// <summary>
/// This is the name of the sink entity name for this relationship (in the graph definition)
/// Only non null for edge type of entity
/// </summary>
public string BoundSinkEntityName { get; set; }
/// <summary>
/// If this entity is node or edge
/// </summary>
public EntityType Type { get; set; }
/// <summary>
/// List of fields that this entity can expand into (namely, property reference)
/// </summary>
public IList<SingleField> EncapsulatedFields { get; set; }
/// <summary>
/// Used for keep tracking what properties of this entity were actually accessed
/// </summary>
public IReadOnlyCollection<string> ReferencedFieldAliases { get { return _referencedAliases.ToList().AsReadOnly(); } }
/// <summary>
/// The field name for the node's join key
/// </summary>
public SingleField NodeJoinField { get; set; }
/// <summary>
/// The field name for the edge's source join key
/// </summary>
public SingleField RelSourceJoinField { get; set; }
/// <summary>
/// The field name for the relationship's sink join key
/// </summary>
public SingleField RelSinkJoinField { get; set; }
public override string ToString()
{
return $"{Type}Field: {FieldAlias}({EntityName})";
}
public override Field Clone()
{
return new EntityField(this);
}
public void AddReferenceFieldAlias(string fieldAlias)
{
if(EncapsulatedFields.All(n => n.FieldAlias != fieldAlias))
{
throw new TranspilerSyntaxErrorException($"field alias {fieldAlias} not existed in entity:{EntityName}.");
}
else if(!_referencedAliases.Contains(fieldAlias))
{
_referencedAliases.Add(fieldAlias);
}
}
public void AddReferenceFieldAliases(IEnumerable<string> fieldAliases)
{
fieldAliases.ToList().ForEach(a => AddReferenceFieldAlias(a));
}
}
/// <summary>
/// A field which is a column
/// </summary>
public class SingleField : Field
{
public SingleField(string alias) : base(alias) { }
/// <summary>
/// Copy constructor
/// </summary>
/// <param name="field"></param>
public SingleField(SingleField field) : base(field.FieldAlias)
{
Copy(field);
}
public SingleField(string alias, Type fieldType) : base(alias)
{
FieldType = fieldType;
}
public override void Copy(Field field)
{
var fieldSrc = field as SingleField;
Debug.Assert(fieldSrc != null);
this.FieldType = fieldSrc.FieldType;
}
public Type FieldType { get; set; }
public override string ToString()
{
return $"Field: {FieldAlias}{(FieldType == default(Type) ? "(?)" : $"({FieldType.Name})")}";
}
public override Field Clone()
{
return new SingleField(this);
}
}
/// <summary>
/// a collection of fields represent the schema of input or output of a logical operator
/// </summary>
public class Schema : List<Field>
{
public Schema()
{
}
/// <summary>
/// Copy constructor
/// </summary>
/// <param name="field"></param>
public Schema(Schema schema)
{
AddRange(schema.Select(f => f.Clone()).ToList());
}
public Schema(IEnumerable<Field> fields)
{
AddRange(fields.ToList());
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RootNamespace>Microsoft.GraphPlatform.Transpiler.LogicalPlanner</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\openCypherParser\openCypherParser.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,90 @@
// Copyright(c) Microsoft Corporation
// All rights reserved.
//
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace openCypherTranspiler.LogicalPlanner.Utils
{
public static class ArrayExt
{
private static T Max<T>(T x, T y, IComparer<T> comparer)
{
if (comparer == null)
{
comparer = Comparer<T>.Default;
}
return (comparer.Compare(x, y) > 0) ? x : y;
}
private static T Min<T>(T x, T y, IComparer<T> comparer)
{
if (comparer == null)
{
comparer = Comparer<T>.Default;
}
return (comparer.Compare(x, y) < 0) ? x : y;
}
private static T[,] TransitiveClosureOnce<T>(this T[,] graph, IComparer<T> comparer = null) where T : IComparable
{
Debug.Assert(graph.GetLength(0) == graph.GetLength(1));
var dim = graph.GetLength(0);
var reach = new T[dim, dim];
int i, j, k;
for (i = 0; i < dim; i++)
{
for (j = 0; j < dim; j++)
{
reach[i, j] = graph[i, j];
}
}
for (k = 0; k < dim; k++)
{
for (i = 0; i < dim; i++)
{
for (j = 0; j < dim; j++)
{
reach[i, j] = Max(reach[i, j], Min(reach[i, k], reach[k, j], comparer), comparer);
}
}
}
return reach;
}
public static T[,] TransitiveClosure<T>(this T[,] graph, IComparer<T> comparer = null) where T : IComparable
{
return graph.TransitiveClosure(Math.Max(graph.GetLength(0), graph.GetLength(1)), comparer);
}
public static T[,] TransitiveClosure<T>(this T[,] graph, int folds, IComparer<T> comparer = null) where T: IComparable
{
var reach = graph;
for (var i = 0; i < folds; i++)
{
var newReach = reach.TransitiveClosureOnce(comparer);
var equal = Enumerable.Range(0, newReach.Rank).All(dimension => newReach.GetLength(dimension) == reach.GetLength(dimension))
&& newReach.Cast<T>().SequenceEqual(reach.Cast<T>());
if (equal)
{
return newReach;
}
else
{
reach = newReach;
}
}
return reach;
}
}
}

Просмотреть файл

@ -0,0 +1,15 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using openCypherTranspiler.Common.GraphSchema;
using System.Collections.Generic;
namespace openCypherTranspiler.SQLRenderer
{
public interface ISQLDBSchemaProvider : IGraphSchemaProvider
{
SQLTableDescriptor GetSQLTableDescriptors(string entityId);
}
}

Просмотреть файл

@ -0,0 +1,3 @@
# SQL Renderer
This project is an example code renderer that produces T-SQL code for parsed openCypher graph query logical plan.

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RootNamespace>Microsoft.GraphPlatform.Transpiler.SQLRenderer</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\LogicalPlanner\LogicalPlanner.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,18 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System.Text;
namespace openCypherTranspiler.SQLRenderer
{
static class SQLRendererHelpers
{
public static StringBuilder AppendLine(this StringBuilder sb, int indentUnits, string line)
{
return sb.AppendLine($"{new string(' ', indentUnits * 4)}{line}");
}
}
}

Просмотреть файл

@ -0,0 +1,14 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
namespace openCypherTranspiler.SQLRenderer
{
public class SQLTableDescriptor
{
public string EntityId { get; set; }
public string TableOrViewName { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,60 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using openCypherTranspiler.openCypherParser.Common;
namespace openCypherTranspiler.openCypherParser.AST
{
public static class AggregationFunctionReturnTypeTable
{
public static readonly IDictionary<(AggregationFunction, Type), Type> TypeMapTable = new Dictionary<(AggregationFunction, Type), Type>()
{
{ (AggregationFunction.Count, Type.GetType("System.Int32")), Type.GetType("System.Int64")},
{ (AggregationFunction.Count, Type.GetType("System.Double")), Type.GetType("System.Int64")},
{ (AggregationFunction.Count, Type.GetType("System.Int64")), Type.GetType("System.Int64")},
{ (AggregationFunction.Count, Type.GetType("System.Int16")), Type.GetType("System.Int64")},
{ (AggregationFunction.Count, Type.GetType("System.UInt16")), Type.GetType("System.Int64")},
{ (AggregationFunction.Count, Type.GetType("System.UInt64")), Type.GetType("System.Int64")},
{ (AggregationFunction.Count, Type.GetType("System.Byte")), Type.GetType("System.Int64")},
{ (AggregationFunction.Count, Type.GetType("System.Single")), Type.GetType("System.Int64")},
{ (AggregationFunction.Count, Type.GetType("System.UInt32")), Type.GetType("System.Int64")},
{ (AggregationFunction.Count, Type.GetType("System.SByte")), Type.GetType("System.Int64")},
{ (AggregationFunction.Count, Type.GetType("System.Decimal")), Type.GetType("System.Int64")},
{ (AggregationFunction.Count, Type.GetType("System.String")), Type.GetType("System.Int64")},
{ (AggregationFunction.Count, Type.GetType("System.Boolean")), Type.GetType("System.Int64")},
{ (AggregationFunction.Count, Type.GetType("System.DateTime")), Type.GetType("System.Int64")},
{ (AggregationFunction.Count, Type.GetType("System.Byte[]")), Type.GetType("System.Int64")},
{ (AggregationFunction.Count, Type.GetType("System.Object")), Type.GetType("System.Int64")},
{ (AggregationFunction.Count, default(Type)), Type.GetType("System.Int64")},
{ (AggregationFunction.Avg, Type.GetType("System.Int32")), Type.GetType("System.Nullable`1[System.Double]")},
{ (AggregationFunction.Avg, Type.GetType("System.Double")), Type.GetType("System.Nullable`1[System.Double]")},
{ (AggregationFunction.Avg, Type.GetType("System.Int64")), Type.GetType("System.Nullable`1[System.Double]")},
{ (AggregationFunction.Avg, Type.GetType("System.Int16")), Type.GetType("System.Nullable`1[System.Double]")},
{ (AggregationFunction.Avg, Type.GetType("System.UInt16")), Type.GetType("System.Nullable`1[System.Double]")},
{ (AggregationFunction.Avg, Type.GetType("System.UInt64")), Type.GetType("System.Nullable`1[System.Double]")},
{ (AggregationFunction.Avg, Type.GetType("System.Byte")), Type.GetType("System.Nullable`1[System.Double]")},
{ (AggregationFunction.Avg, Type.GetType("System.Single")), Type.GetType("System.Nullable`1[System.Double]")},
{ (AggregationFunction.Avg, Type.GetType("System.UInt32")), Type.GetType("System.Nullable`1[System.Double]")},
{ (AggregationFunction.Avg, Type.GetType("System.SByte")), Type.GetType("System.Nullable`1[System.Double]")},
{ (AggregationFunction.Avg, Type.GetType("System.Decimal")), Type.GetType("System.Nullable`1[System.Decimal]")},
{ (AggregationFunction.Sum, Type.GetType("System.Int32")),Type.GetType("System.Int64") },
{ (AggregationFunction.Sum, Type.GetType("System.Double")),Type.GetType("System.Double")},
{ (AggregationFunction.Sum, Type.GetType("System.Int64")),Type.GetType("System.Int64") },
{ (AggregationFunction.Sum, Type.GetType("System.Int16")),Type.GetType("System.Int64") },
{ (AggregationFunction.Sum, Type.GetType("System.UInt16")),Type.GetType("System.Int64") },
{ (AggregationFunction.Sum, Type.GetType("System.UInt64")),Type.GetType("System.Double")},
{ (AggregationFunction.Sum, Type.GetType("System.Byte")),Type.GetType("System.Int64") },
{ (AggregationFunction.Sum, Type.GetType("System.Single")),Type.GetType("System.Double")},
{ (AggregationFunction.Sum, Type.GetType("System.UInt32")),Type.GetType("System.Int64") },
{ (AggregationFunction.Sum, Type.GetType("System.SByte")),Type.GetType("System.Int64") },
{ (AggregationFunction.Sum, Type.GetType("System.Decimal")),Type.GetType("System.Decimal")},
};
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,190 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System.Collections.Generic;
using System.Linq;
using openCypherTranspiler.Common.Exceptions;
namespace openCypherTranspiler.openCypherParser.AST
{
/// <summary>
/// represents the parsed group of matched patterns
/// </summary>
public class MatchDataSource : TreeNode
{
#region Implements TreeNode
protected override IEnumerable<TreeNode> Children
{
get
{
return Enumerable.Empty<TreeNode>();
}
}
#endregion Implements TreeNode
/// <summary>
/// Return all the entities refered by the Match statement
/// with the same order it appears
/// </summary>
public IList<Entity> AllEntitiesOrdered
{
get
{
// can't use SelectMany if it doesn't guarantee order
// MatchPatterns?.SelectMany(p => p) ?? Enumerable.Empty<Entity>();
return MatchPatterns?.Aggregate(new List<Entity>(), (p, l) => { p.AddRange(l); return p; }) ?? new List<Entity>(0);
}
}
/// <summary>
/// A list of match patterns:
/// e.g. (a:device)-[]->(
/// </summary>
public IList<MatchPattern> MatchPatterns { get; set; }
/// <summary>
/// Return a new MatchDataSource mirrors the old one but with anonymous entities filled with
/// a place holder alias
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public MatchDataSource AssignGeneratedEntityAliasToAnonEntities(string anonVarPrefix)
{
var varIdx = 0;
var existingAliases = new HashSet<string>(MatchPatterns.SelectMany(p => p.Select(e => e.Alias)).Where(a => !string.IsNullOrEmpty(a)).Distinct());
if (existingAliases.Any(p => p.StartsWith(anonVarPrefix)))
{
throw new TranspilerSyntaxErrorException($"Banned prefix for variable aliases: {anonVarPrefix}. Please consider a different prefix.");
}
// creating a new DS with implied labels fixed up
var matchDsNew = new MatchDataSource()
{
MatchPatterns = MatchPatterns.Select(p => new MatchPattern(p.IsOptionalMatch, p.Select(e =>
{
var alias = e.Alias ?? $"{anonVarPrefix}{varIdx++}";
var entity = e.Clone();
entity.Alias = alias;
return entity;
}))).ToList()
};
return matchDsNew;
}
public override string ToString()
{
return $"Matches: Count={MatchPatterns?.Count ?? 0}, Patterns={string.Join(" ", MatchPatterns)}";
}
}
/// <summary>
/// A single match pattern is a traversal of entities (node and relationships)
/// </summary>
public class MatchPattern : List<Entity>, IList<Entity>
{
public MatchPattern(bool isOptional, IEnumerable<Entity> list) : base(list)
{
IsOptionalMatch = isOptional;
}
public bool IsOptionalMatch { get; set; }
public override string ToString()
{
return $"MatchPat: IsOptional={IsOptionalMatch}; Pattern={string.Join(",", this)}";
}
}
/// <summary>
/// Represents an entity of either node or edge
/// </summary>
public abstract class Entity
{
/// <summary>
/// Name of the entity, for edge this is just verb of the edge
/// </summary>
public string EntityName { get; set; }
/// <summary>
/// Alias used for refering the entity
/// </summary>
public string Alias { get; set; }
/// <summary>
/// Make a deep copy of the derived class of this type
/// </summary>
/// <returns></returns>
public abstract Entity Clone();
}
public class NodeEntity : Entity
{
public override Entity Clone()
{
return new NodeEntity()
{
Alias = this.Alias,
EntityName = this.EntityName
};
}
public override string ToString()
{
return $"({Alias}:{EntityName})";
}
}
/// <summary>
/// Edge is not unique by its verb during binding but depends on the node it connects
/// E.g. (:device)-[:runs]-(:app)
/// so we capture the in node (left) and out node of this edge (right)
/// </summary>
public class RelationshipEntity : Entity
{
public enum Direction
{
Both, // -[]-
Forward, // -[]->
Backward // <-[]-
}
/// <summary>
/// Left side node entity's name
/// Note that 'left' here the lexical order and not refelcting the direction
/// </summary>
public string LeftEntityName { get; set; }
/// <summary>
/// Right side node entity's name
/// Note that 'right' here the lexical order and not refelcting the direction
/// </summary>
public string RightEntityName { get; set; }
public override Entity Clone()
{
return new RelationshipEntity()
{
Alias = this.Alias,
EntityName = this.EntityName,
RelationshipDirection = this.RelationshipDirection,
LeftEntityName = this.LeftEntityName,
RightEntityName = this.RightEntityName,
};
}
/// <summary>
/// Name of the entity, for edge this is just verb of the edge
/// </summary>
public Direction RelationshipDirection { get; set; }
public override string ToString()
{
return $"{LeftEntityName}{(RelationshipDirection == Direction.Backward ? "<" : "")}-[{Alias}:{EntityName}]-{(RelationshipDirection == Direction.Forward ? ">" : "")}{RightEntityName}";
}
}
}

Просмотреть файл

@ -0,0 +1,638 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using openCypherTranspiler.Common.Exceptions;
using openCypherTranspiler.Common.Utils;
using openCypherTranspiler.openCypherParser.Common;
namespace openCypherTranspiler.openCypherParser.AST
{
/// <summary>
/// represents an expression appears in Graph Query language
/// </summary>
public abstract class QueryExpression : TreeNode
{
/// <summary>
/// Traversal helper to retrieve query expression of certain type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public IEnumerable<T> GetChildrenQueryExpressionType<T>() where T : QueryExpression
{
return GetChildrenOfType<T>();
}
/// <summary>
/// Compute the result's data type of the expression
/// </summary>
/// <returns></returns>
abstract public Type EvaluateType();
}
/// <summary>
/// represents a expression with an explicit alias, e.g. a AS b
/// </summary>
public class QueryExpressionWithAlias : QueryExpression
{
#region Implements TreeNode
protected override IEnumerable<TreeNode> Children
{
get
{
return new List<TreeNode>() { InnerExpression };
}
}
#endregion Implements TreeNode
public QueryExpression InnerExpression { get; set; }
public string Alias { get; set; }
public override string ToString()
{
return $"ExprWithAlias: {Alias}";
}
public override Type EvaluateType()
{
return InnerExpression.EvaluateType();
}
}
/// <summary>
/// represents a binary (a + b, or a = b, or a <= b) operation
/// </summary>
public partial class QueryExpressionBinary : QueryExpression
{
#region Implements TreeNode
protected override IEnumerable<TreeNode> Children
{
get
{
return new List<TreeNode>() { LeftExpression, RightExpression };
}
}
#endregion Implements TreeNode
public BinaryOperatorInfo Operator { get; set; }
public QueryExpression LeftExpression { get; set; }
public QueryExpression RightExpression { get; set; }
public override string ToString()
{
return $"ExprBinary: Op='{Operator}'";
}
public override Type EvaluateType()
{
var leftType = LeftExpression.EvaluateType();
var rightType = RightExpression.EvaluateType();
var leftTypeUnboxed = TypeHelper.GetUnderlyingTypeIfNullable(leftType);
var rightTypeUnboxed = TypeHelper.GetUnderlyingTypeIfNullable(rightType);
var anyNullable = TypeHelper.IsSystemNullableType(leftType) || TypeHelper.IsSystemNullableType(rightType);
Type resultedTypeRaw;
switch (Operator.Type)
{
case BinaryOperatorType.Logical:
// For logical comparison, we ensure that all operands' type are logical already
// The return type is always boolean (logical)
if (leftType != typeof(bool) || leftType != typeof(bool?) &&
rightType != typeof(bool) || rightType != typeof(bool?))
{
throw new TranspilerNotSupportedException($"Logical binary operator {Operator} operating must operate on bool types. Actual types: {leftType}, {rightType}");
}
return (anyNullable ? TypeHelper.MakeNullableIfNotAlready(typeof(bool)) : typeof(bool));
case BinaryOperatorType.Value:
// For value type operator, use the value type coercion table
if (!CoersionTables.CoersionTableForValueType.TryGetValue((Operator.Name, leftTypeUnboxed, rightTypeUnboxed), out resultedTypeRaw))
{
throw new TranspilerInternalErrorException($"Unexpected use of binary operator {Operator.Name} operating between types {leftTypeUnboxed} and {rightTypeUnboxed}");
}
if (resultedTypeRaw == default(Type))
{
throw new TranspilerNotSupportedException($"Binary operator {Operator.Name} operating between types {leftTypeUnboxed} and {rightTypeUnboxed}");
}
return (anyNullable ? TypeHelper.MakeNullableIfNotAlready(resultedTypeRaw) : resultedTypeRaw);
case BinaryOperatorType.Comparison:
// For comparison operators, use the equality/inequality type coercion table
if (Operator.Name == BinaryOperator.EQ || Operator.Name == BinaryOperator.NEQ)
{
if (!CoersionTables.CoersionTableEqualityComparison.TryGetValue((leftTypeUnboxed, rightTypeUnboxed), out resultedTypeRaw))
{
throw new TranspilerInternalErrorException($"Unexpected use of binary operator {Operator.Name} operating between types {leftTypeUnboxed} and {rightTypeUnboxed}");
}
}
else
{
if (!CoersionTables.CoersionTableInequalityComparison.TryGetValue((leftTypeUnboxed, rightTypeUnboxed), out resultedTypeRaw))
{
throw new TranspilerInternalErrorException($"Unexpected use of binary operator {Operator.Name} operating between types {leftTypeUnboxed} and {rightTypeUnboxed}");
}
}
if (resultedTypeRaw == default(Type))
{
throw new TranspilerNotSupportedException($"Binary operator {Operator.Name} operating between types {leftTypeUnboxed} and {rightTypeUnboxed}");
}
return (anyNullable ? TypeHelper.MakeNullableIfNotAlready(resultedTypeRaw) : resultedTypeRaw);
case BinaryOperatorType.Invalid:
default:
throw new TranspilerInternalErrorException($"Unexpected operator type: {Operator.Type}");
}
}
}
/// <summary>
/// represents a function call, like toFloat(expr)
/// </summary>
public class QueryExpressionFunction : QueryExpression
{
#region Implements TreeNode
protected override IEnumerable<TreeNode> Children
{
get
{
return new List<TreeNode>() { InnerExpression };
}
}
#endregion Implements TreeNode
public FunctionInfo Function { get; set; }
public QueryExpression InnerExpression { get; set; }
public IEnumerable<QueryExpression> AdditionalExpressions { get; set; }
public override string ToString()
{
return $"ExprFunc: {Function}(a)";
}
public override Type EvaluateType()
{
var innerType = InnerExpression.EvaluateType();
var isWrappedinNullable = TypeHelper.IsSystemNullableType(innerType);
switch (Function.FunctionName)
{
case Common.Function.ToFloat:
return isWrappedinNullable ? typeof(float?) : typeof(float);
case Common.Function.ToString:
return typeof(string);
case Common.Function.ToBoolean:
return isWrappedinNullable ? typeof(bool?) : typeof(bool);
case Common.Function.ToInteger:
return isWrappedinNullable ? typeof(int?) : typeof(int);
case Common.Function.ToDouble:
return isWrappedinNullable ? typeof(long?) : typeof(long);
case Common.Function.ToLong:
return isWrappedinNullable ? typeof(double?) : typeof(double);
case Common.Function.Not:
return isWrappedinNullable ? typeof(bool?) : typeof(bool);
case Common.Function.StringContains:
case Common.Function.StringStartsWith:
case Common.Function.StringEndsWith:
case Common.Function.IsNull:
case Common.Function.IsNotNull:
return typeof(bool);
case Common.Function.StringSize:
return typeof(int);
default:
// treat all the rest as type preserving, e.g.
// trim, ltrim ....
return InnerExpression.EvaluateType();
}
}
}
/// <summary>
/// represents a aggregation function call, like avg(expr)
/// </summary>
public partial class QueryExpressionAggregationFunction : QueryExpression
{
#region Implements TreeNode
protected override IEnumerable<TreeNode> Children
{
get
{
return new List<TreeNode>() { InnerExpression };
}
}
#endregion Implements TreeNode
public AggregationFunction AggregationFunction { get; set; }
public bool IsDistinct { get; set; }
public QueryExpression InnerExpression { get; set; }
public override string ToString()
{
return $"ExprAggFunc: {AggregationFunction}(a)";
}
public override Type EvaluateType()
{
var innerType = InnerExpression.EvaluateType();
var innerTypeUnboxed = TypeHelper.GetUnderlyingTypeIfNullable(innerType);
Type resultedType;
if (!AggregationFunctionReturnTypeTable.TypeMapTable.TryGetValue((AggregationFunction, innerTypeUnboxed), out resultedType))
{
// for any aggregation function that were not having specially handling, then it is considered to preserve the original type
return innerType;
}
return resultedType;
}
}
/// <summary>
/// represents a reference to a property (column), e.g. r.Score
/// </summary>
public class QueryExpressionProperty : QueryExpression
{
#region Implements TreeNode
protected override IEnumerable<TreeNode> Children
{
get
{
return Enumerable.Empty<TreeNode>();
}
}
#endregion Implements TreeNode
/// <summary>
/// For a property reference, this is the variable part, namely alias of alias.field
/// </summary>
public string VariableName { get; set; }
/// <summary>
/// For a property reference, this is the property part, namely alias of alias.field
/// </summary>
public string PropertyName { get; set; }
/// <summary>
/// For a node/relationship, this is the entity type reference
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public Entity Entity { get; set; }
/// <summary>
/// For a single field, this is the data type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public Type DataType { get; set; }
public override string ToString()
{
if (Entity != null)
{
return $"ExprProperty: {VariableName} {Entity}";
}
else
{
return $"ExprProperty: {VariableName}.{PropertyName}";
}
}
public override Type EvaluateType()
{
return DataType;
}
}
/// <summary>
/// represent a list of expressions
/// </summary>
public class QueryExpressionList : QueryExpression
{
#region Implements TreeNode
protected override IEnumerable<TreeNode> Children
{
get
{
return ExpressionList.Cast<TreeNode>();
}
}
#endregion Implements TreeNode
public IList<QueryExpression> ExpressionList { get; set; }
public override Type EvaluateType()
{
var types = ExpressionList?.Select(p => p.EvaluateType()).Distinct();
if (types.Count() == 1)
{
return typeof(IEnumerable<>).MakeGenericType(types.First());
}
else
{
return typeof(IEnumerable<object>);
}
}
}
/// <summary>
/// represents a literal value, such as a string, or number
/// </summary>
public class QueryExpressionValue : QueryExpression
{
#region Implements TreeNode
protected override IEnumerable<TreeNode> Children
{
get
{
return Enumerable.Empty<TreeNode>();
}
}
#endregion Implements TreeNode
private object _value;
/// <summary>
/// Holding the object value in a supported value-type
/// </summary>
public object Value
{
get
{
return _value;
}
set
{
if (!(value is string ||
value is bool ||
value is int ||
value is long ||
value is float ||
value is double ||
value is DateTime))
{
throw new TranspilerNotSupportedException($"Type {value.GetType()}");
}
_value = value;
}
}
public Type ValueType
{
get
{
return Value.GetType();
}
}
public bool BoolValue
{
get
{
return (Value is bool ? (bool)Value : Convert.ToBoolean(Value));
}
set
{
Value = value;
}
}
public int IntValue
{
get
{
return (Value is int ? (int)Value : Convert.ToInt32(Value));
}
set
{
Value = value;
}
}
public long LongValue
{
get
{
return (Value is long ? (long)Value : Convert.ToInt64(Value));
}
set
{
Value = value;
}
}
public double DoubleValue
{
get
{
return (Value is double ? (double)Value : Convert.ToDouble(Value));
}
set
{
Value = value;
}
}
public DateTime DateTimeValue
{
get
{
return (Value is DateTime ? (DateTime)Value : Convert.ToDateTime(Value));
}
set
{
Value = value;
}
}
public string StringValue
{
get
{
return (Value is string ? (string)Value : Value.ToString());
}
set
{
Value = value;
}
}
public override string ToString()
{
return $"ExprValue: t='{Value?.GetType()}'; v='{Value?.ToString()}'";
}
public override Type EvaluateType()
{
return ValueType;
}
}
public class QueryExpressionOrderBy : QueryExpression
{
#region Implements TreeNode
protected override IEnumerable<TreeNode> Children
{
get
{
return new List<TreeNode>() { InnerExpression };
}
}
#endregion Implements TreeNode
public QueryExpression InnerExpression { get; set; }
/// <summary>
/// indicator for sorting orders
/// </summary>
public bool IsDescending { get; set; }
/// <summary>
/// sorting keys
/// </summary>
public string Alias { get; set; }
public override string ToString()
{
return $"ExprOrderBy: {InnerExpression.GetChildrenQueryExpressionType<QueryExpressionProperty>().First().VariableName}";
}
public override Type EvaluateType()
{
return InnerExpression.EvaluateType();
}
}
public class QueryExpressionLimit : QueryExpression
{
#region Implements TreeNode
protected override IEnumerable<TreeNode> Children
{
get
{
return new List<TreeNode>() { InnerExpression };
}
}
#endregion Implements TreeNode
public QueryExpression InnerExpression { get; set; }
/// <summary>
/// stores how many rows to keep in "LIMIT" clause
/// </summary>
public int RowCount { get; set; }
public override string ToString()
{
return $"ExprLimit: {InnerExpression.GetChildrenQueryExpressionType<QueryExpressionProperty>().First().VariableName}";
}
public override Type EvaluateType()
{
return InnerExpression.EvaluateType();
}
}
public class QueryExpressionCaseExpression : QueryExpression
{
#region Implements TreeNode
protected override IEnumerable<TreeNode> Children
{
get
{
return new List<TreeNode>() { InitialCaseExpression, ElseExpression }.Union(CaseAlternatives).Where(n => n != null);
}
}
#endregion Implements TreeNode
// For "CASE" part in the case expression
public QueryExpression InitialCaseExpression { get; set; }
// For :"WHEN ... THEN" part in the case expression
// Can be null if "WHEN ... THEN ..." not specified in the query
public List<QueryExpressionCaseAlternative> CaseAlternatives { get; set; }
// For"ELSE ..." part in the case expression
public QueryExpression ElseExpression { get; set; }
public override string ToString()
{
return $"CaseExpr: Case when {CaseAlternatives.ToString()} Else:{ElseExpression}";
}
public override Type EvaluateType()
{
var hasElseExpression = (ElseExpression != null);
var distinctTypes = hasElseExpression ?
CaseAlternatives.Select(n => n.EvaluateType())
.Union(new List<Type> { ElseExpression.EvaluateType() })
.Distinct() :
CaseAlternatives.Select(n => n.EvaluateType())
.Distinct();
var anyNullable = distinctTypes.Any(t => TypeHelper.IsSystemNullableType(t))
// when Else statement is not provided resulting type becomes automatically nullable
|| !hasElseExpression;
var distinctUnboxedTypes = distinctTypes
.Select(t => TypeHelper.GetUnderlyingTypeIfNullable(t)).Distinct();
Type resultUnboxedType;
if (distinctUnboxedTypes.Count() > 1)
{
// During parsing, type evalution allows the max extent of type coercion
// which is what a + operator would do
resultUnboxedType = distinctUnboxedTypes.Aggregate((resType, nextType) =>
{
Type resultedTypeRaw;
if (!CoersionTables.CoersionTableForValueType.TryGetValue((BinaryOperator.Plus, resType, nextType), out resultedTypeRaw))
{
throw new TranspilerInternalErrorException($"Unexpected use of CASE WHEN operating between types {resType} and {nextType}");
}
if (resultedTypeRaw == default(Type))
{
throw new TranspilerNotSupportedException($"Case WHEN operating between types {resType} and {nextType}");
}
return resultedTypeRaw;
});
}
else
{
resultUnboxedType = distinctUnboxedTypes.First();
}
return (anyNullable ? TypeHelper.MakeNullableIfNotAlready(resultUnboxedType) : resultUnboxedType);
}
}
public class QueryExpressionCaseAlternative : QueryExpression
{
#region Implements TreeNode
protected override IEnumerable<TreeNode> Children
{
get
{
return new List<TreeNode>() { WhenExpression, ThenExpression };
}
}
#endregion Implements TreeNode
public QueryExpression WhenExpression { get; set; }
public QueryExpression ThenExpression { get; set; }
public override string ToString()
{
return $"ExprCaseAlter: when ->{WhenExpression.ToString()} Then -> {ThenExpression.ToString()}";
}
public override Type EvaluateType()
{
return ThenExpression.EvaluateType();
}
}
}

Просмотреть файл

@ -0,0 +1,28 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using openCypherTranspiler.openCypherParser.AST;
namespace openCypherTranspiler.openCypherParser.AST
{
public static class QueryExpressionHelper
{
/// <summary>
/// If expr is a direct return of an entity, return it, otherwise, return null
/// </summary>
/// <param name="expr"></param>
/// <returns></returns>
public static Entity TryGetDirectlyExposedEntity(this QueryExpression expr)
{
if (expr is QueryExpressionProperty)
{
var queryEntityExpr = expr as QueryExpressionProperty;
var entity = queryEntityExpr.Entity;
return entity;
}
return null;
}
}
}

Просмотреть файл

@ -0,0 +1,170 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace openCypherTranspiler.openCypherParser.AST
{
/// <summary>
/// holds a query or a union of sub queires
/// </summary>
public abstract class QueryTreeNode : TreeNode
{
}
/// <summary>
/// represents union of leaf-node queries: multiple queries can be unioned or unioned_all together
/// </summary>
public class InfixQueryTreeNode : QueryTreeNode
{
#region Implements TreeNode
protected override IEnumerable<TreeNode> Children
{
get
{
return new List<TreeNode>() { LeftQueryTreeNode, RightQueryTreeNode };
}
}
#endregion Implements TreeNode
public enum QueryOperator
{
Union, // dup removal
UnionAll, // no dup removal
}
public QueryOperator Operator { get; set; }
public QueryTreeNode LeftQueryTreeNode { get; set; }
public QueryTreeNode RightQueryTreeNode { get; set; }
public override string ToString()
{
return $"QueryInfix: {Operator}";
}
}
/// <summary>
/// the final part of the query that has raw or nested input, conditions and output
/// </summary>
public class SingleQueryTreeNode : QueryTreeNode
{
#region Implements TreeNode
protected override IEnumerable<TreeNode> Children
{
get
{
return new List<TreeNode>() { PipedData }
.Union(EntityPropertySelected.Cast<TreeNode>())
.Union(EntityPropertyOrderBy??new List<QueryExpressionOrderBy>())
.Union(EntityRowsLimit??new List<QueryExpressionLimit>())
.Where(p => p != null);
}
}
#endregion Implements TreeNode
/// <summary>
/// The input of the query. Can be either graph data (from a match statement) or output from an intermediate query
/// </summary>
public PartialQueryTreeNode PipedData { get; set; }
/// <summary>
/// Expressions in the return or with
/// </summary>
public IList<QueryExpressionWithAlias> EntityPropertySelected { get; set; }
/// <summary>
/// If return is called with DISTINCT modifier
/// </summary>
public bool IsDistinct { get; set; }
/// <summary>
/// Order by items in return or in with clause
/// </summary>
public IList<QueryExpressionOrderBy> EntityPropertyOrderBy { get; set; }
/// <summary>
/// For "LIMIT" modifier, holding numbers of rows to be selected in the data
/// </summary>
public IList<QueryExpressionLimit> EntityRowsLimit { get; set; }
public override string ToString()
{
return $"QuerySingle: Props={string.Join(",", EntityPropertySelected.Select(p => p.Alias))}; Distinct={IsDistinct} ;OrderBy={string.Join(",", EntityPropertyOrderBy?.Select(p => p.Alias))} ; Limit={string.Join(",", EntityRowsLimit?.Select(p => p.RowCount))} ";
}
}
/// <summary>
/// represents match/querypart / match/querypart-with / match/querypart-with-where / match/querypart/where-with-where
/// </summary>
public class PartialQueryTreeNode : TreeNode
{
#region Implements TreeNode
protected override IEnumerable<TreeNode> Children
{
get
{
return new List<TreeNode>() { PipedData, MatchData }
.Union(ProjectedExpressions)
.Union(new List<TreeNode>() { PostCondition})
.Union(OrderByExpression??new List<QueryExpressionOrderBy>())
.Union(LimitExpression??new List<QueryExpressionLimit>())
.Where(p => p != null);
}
}
#endregion Implements TreeNode
/// <summary>
/// represents the data flow from previous partial query in the chain
/// </summary>
public PartialQueryTreeNode PipedData { get; set; }
/// <summary>
/// represents the (additional) match statements
/// </summary>
public MatchDataSource MatchData { get; set; }
/// <summary>
/// the attributes/entities to be returned to next part of the query chain
/// </summary>
public IList<QueryExpressionWithAlias> ProjectedExpressions { get; set; }
/// <summary>
/// Indicate if this query part has no WITH (hence the ProjectedExpressions are implied to be return all aliased nodes)
/// </summary>
public bool IsImplicitProjection { get; set; }
/// <summary>
/// the attributes/entities to be returned to next part of the query chain
/// </summary>
public bool IsDistinct { get; set; }
/// <summary>
/// if the next query part can be a non-optional match or not
/// </summary>
public bool CanChainNonOptionalMatch { get; set; }
/// <summary>
/// query conditions post projection
/// </summary>
public QueryExpression PostCondition { get; set; }
/// <summary>
/// ORDER BY under WITH statement
/// </summary>
public IList<QueryExpressionOrderBy> OrderByExpression { get; set; }
/// <summary>
/// LIMIT N under WITH statement
/// </summary>
public IList<QueryExpressionLimit> LimitExpression { get; set; }
public override string ToString()
{
return $"QueryPart: HasMatch={MatchData != null}; IsImplicitProj={IsImplicitProjection}; HasCond={PostCondition != null}; Props={string.Join(",", ProjectedExpressions?.Select(p => p.Alias))}, Distinct={IsDistinct}, HasOrderBy={OrderByExpression!= null}, HasLimit = {LimitExpression != null}";
}
}
}

Просмотреть файл

@ -0,0 +1,53 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System.Collections.Generic;
using System.Linq;
using System.Text;
using openCypherTranspiler.Common.Utils;
namespace openCypherTranspiler.openCypherParser.AST
{
public abstract class TreeNode
{
protected abstract IEnumerable<TreeNode> Children { get; }
/// <summary>
/// Debugging purpose: dump the tree in textual format into a string
/// </summary>
/// <param name="depth"></param>
/// <returns></returns>
public virtual string DumpTree(int depth = 0)
{
var sb = new StringBuilder();
sb.AppendLine($"+{this.GetType().Name}".ChangeIndentation(depth));
sb.AppendLine($"|{this.ToString()}".ChangeIndentation(depth));
foreach (var child in Children ?? Enumerable.Empty<TreeNode>())
{
sb.Append(child.DumpTree(depth + 1));
}
return sb.ToString();
}
/// <summary>
/// Traversal helper to retrieve node of certain type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public IEnumerable<T> GetChildrenOfType<T>() where T : TreeNode
{
if (this is T)
{
return new List<T>(1) { this as T }
.Union(Children?.SelectMany(c => c.GetChildrenOfType<T>()) ?? Enumerable.Empty<T>());
}
else
{
return Children?
.SelectMany(c => c.GetChildrenOfType<T>()) ?? Enumerable.Empty<T>();
}
}
}
}

Просмотреть файл

@ -0,0 +1,87 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
namespace openCypherTranspiler.openCypherParser.Common
{
/// <summary>
/// Enum type for aggregation functions supported by this code generator
/// </summary>
public enum AggregationFunction
{
Invalid,
None,
Sum,
Avg,
Count,
Max,
Min,
First,
Last,
PercentileCont,
PercentileDisc,
StDev,
StDevP
}
class AggregationFunctionHelper
{
/// <summary>
/// Parse a function into aggregation function enum
/// </summary>
/// <param name="functionName"></param>
/// <param name="aggFunc"></param>
/// <returns></returns>
public static bool TryParse(string functionName, out AggregationFunction aggFunc)
{
string lowerCaseFunctionName = functionName.ToLower();
switch (lowerCaseFunctionName)
{
case "avg":
aggFunc = AggregationFunction.Avg;
break;
case "sum":
aggFunc = AggregationFunction.Sum;
break;
case "count":
aggFunc = AggregationFunction.Count;
break;
case "max":
aggFunc = AggregationFunction.Max;
break;
case "min":
aggFunc = AggregationFunction.Min;
break;
case "first":
// not supported by cypher but cosmos
aggFunc = AggregationFunction.First;
break;
case "last":
// not supported by cypher but cosmos
aggFunc = AggregationFunction.Last;
break;
case "percentilecont":
aggFunc = AggregationFunction.PercentileCont;
break;
case "percentiledisc":
aggFunc = AggregationFunction.PercentileDisc;
break;
case "stdev":
aggFunc = AggregationFunction.StDev;
break;
case "stdevp":
aggFunc = AggregationFunction.StDevP;
break;
default:
// treat it as non-aggregating functions
aggFunc = AggregationFunction.Invalid;
return false;
}
// indicating it is an aggregating function
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,106 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System.Collections.Generic;
using System.Linq;
namespace openCypherTranspiler.openCypherParser.Common
{
public enum BinaryOperator
{
Invalid = 0,
// numerical
Plus,
Minus,
Multiply,
Divide,
Modulo,
Exponentiation,
// logical
AND,
OR,
XOR,
// comparison
LT,
LEQ,
GT,
GEQ,
EQ,
NEQ,
REGMATCH,
IN
}
public enum BinaryOperatorType
{
Invalid,
Value, // takes value type (string or numeric) and output value type
Logical, // takes logical type (bool) and output logical type
Comparison // takes value type (string or numeric) and output logical type
}
public class BinaryOperatorInfo
{
public BinaryOperatorInfo(BinaryOperator name, BinaryOperatorType type)
{
Name = name;
Type = type;
}
public BinaryOperator Name { get; private set; }
public BinaryOperatorType Type { get; private set; }
public override string ToString()
{
return Name.ToString();
}
}
public class OperatorHelper
{
private static Dictionary<string, BinaryOperatorInfo> Operators = new Dictionary<string, BinaryOperatorInfo>()
{
{ "+", new BinaryOperatorInfo(name: BinaryOperator.Plus,type: BinaryOperatorType.Value) },
{ "-", new BinaryOperatorInfo(name: BinaryOperator.Minus, type: BinaryOperatorType.Value) },
{ "*", new BinaryOperatorInfo(name: BinaryOperator.Multiply, type: BinaryOperatorType.Value) },
{ "/", new BinaryOperatorInfo(name: BinaryOperator.Divide, type: BinaryOperatorType.Value) },
{ "%", new BinaryOperatorInfo(name: BinaryOperator.Modulo, type: BinaryOperatorType.Value) },
{ "^", new BinaryOperatorInfo(name: BinaryOperator.Exponentiation, type: BinaryOperatorType.Value) },
{ "<>", new BinaryOperatorInfo(name: BinaryOperator.NEQ, type: BinaryOperatorType.Comparison) },
{ "=", new BinaryOperatorInfo(name: BinaryOperator.EQ, type: BinaryOperatorType.Comparison) },
{ "<", new BinaryOperatorInfo(name: BinaryOperator.LT, type: BinaryOperatorType.Comparison) },
{ ">", new BinaryOperatorInfo(name: BinaryOperator.GT, type: BinaryOperatorType.Comparison) },
{ "<=", new BinaryOperatorInfo(name: BinaryOperator.LEQ, type: BinaryOperatorType.Comparison) },
{ ">=", new BinaryOperatorInfo(name: BinaryOperator.GEQ, type: BinaryOperatorType.Comparison) },
{ "=~", new BinaryOperatorInfo(name: BinaryOperator.REGMATCH, type: BinaryOperatorType.Comparison) },
{ "in", new BinaryOperatorInfo(name: BinaryOperator.IN, type: BinaryOperatorType.Comparison) },
{ "and", new BinaryOperatorInfo(name: BinaryOperator.AND, type: BinaryOperatorType.Logical) },
{ "or", new BinaryOperatorInfo(name: BinaryOperator.OR, type: BinaryOperatorType.Logical) },
{ "xor", new BinaryOperatorInfo(name: BinaryOperator.XOR, type: BinaryOperatorType.Logical) },
};
public static BinaryOperatorInfo TryGetOperator(string op)
{
string lcOperator = op?.ToLower();
BinaryOperatorInfo opInfo;
if (Operators.TryGetValue(lcOperator, out opInfo))
{
return opInfo;
}
return null;
}
public static BinaryOperatorInfo GetOperator(BinaryOperator opEnum)
{
return Operators.Values.FirstOrDefault(op => op.Name == opEnum);
}
}
}

Просмотреть файл

@ -0,0 +1,317 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Linq;
using openCypherTranspiler.Common.Exceptions;
namespace openCypherTranspiler.openCypherParser.Common
{
public enum Function
{
Invalid = 0,
// Unary operators
Positive,
Negative,
Not,
// Type conversion functions:
ToFloat,
ToString,
ToBoolean,
ToInteger,
ToLong, // non standard oC functions but supported by us
ToDouble, // non standard oC functions but supported by us
// String functions
StringStartsWith,
StringEndsWith,
StringContains,
StringLeft,
StringRight,
StringTrim,
StringLTrim,
StringRTrim,
StringToUpper,
StringToLower,
StringSize,
// misc functions:
IsNull,
IsNotNull
}
public class FunctionInfo
{
public Function FunctionName { get; set; }
public int RequiredParameters { get; set; }
public int OptionalParameters { get; set; }
/// <summary>
/// A function that
/// </summary>
public Action<FunctionInfo, IEnumerable<Type>> ParameterChecker { get; set; }
}
public class FunctionHelper
{
private static void EnsureParameterCount(FunctionInfo info, int actCnt)
{
var paramCountMin = info.RequiredParameters;
var paramCountMax = paramCountMin + info.OptionalParameters;
if (actCnt <= paramCountMin || actCnt > paramCountMax)
{
throw new TranspilerSyntaxErrorException($"Function {info.FunctionName} expects {paramCountMin}{(paramCountMax > paramCountMin ? $" - {paramCountMax}" : "")} parameter(s)");
}
}
private static void EnsureNumericType(FunctionInfo info, Type type)
{
if (!(
type == typeof(int) || type == typeof(int?) ||
type == typeof(long) || type == typeof(long?) ||
type == typeof(float) || type == typeof(float?) ||
type == typeof(double) || type == typeof(double?)
))
{
throw new TranspilerNotSupportedException($"Function {info.FunctionName} parameter of type {type.Name}");
}
}
private static void EnsureBooleanType(FunctionInfo info, Type type)
{
if (!(
type == typeof(bool) || type == typeof(bool?)
))
{
throw new TranspilerNotSupportedException($"Function {info.FunctionName} parameter of type {type.Name}");
}
}
private static Action<FunctionInfo, IEnumerable<Type>> EnsureParameterCountChecker = (info, types) =>
{
EnsureParameterCount(info, types.Count());
};
private static Dictionary<string, FunctionInfo> _funcInfoMap = new Dictionary<string, FunctionInfo>()
{
{ "+", new FunctionInfo()
{
FunctionName = Function.Positive,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = (info, types) =>
{
EnsureParameterCount(info, types.Count());
EnsureNumericType(info, types.First());
}
}
},
{ "-", new FunctionInfo()
{
FunctionName = Function.Negative,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = (info, types) =>
{
EnsureParameterCount(info, types.Count());
EnsureNumericType(info, types.First());
}
}
},
{ "not", new FunctionInfo()
{
FunctionName = Function.Not,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = (info, types) =>
{
EnsureParameterCount(info, types.Count());
EnsureBooleanType(info, types.First());
}
}
},
{ "tofloat", new FunctionInfo()
{
FunctionName = Function.ToFloat,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "tostring", new FunctionInfo()
{
FunctionName = Function.ToString,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "toboolean", new FunctionInfo()
{
FunctionName = Function.ToBoolean,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "tointeger", new FunctionInfo()
{
FunctionName = Function.ToInteger,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "tolong", new FunctionInfo()
{
FunctionName = Function.ToLong,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "todouble", new FunctionInfo()
{
FunctionName = Function.ToDouble,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "stringstartswith", new FunctionInfo()
{
FunctionName = Function.StringStartsWith,
RequiredParameters = 2,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "stringendswith", new FunctionInfo()
{
FunctionName = Function.StringEndsWith,
RequiredParameters = 2,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "stringcontains", new FunctionInfo()
{
FunctionName = Function.StringContains,
RequiredParameters = 2,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "isnull", new FunctionInfo()
{
FunctionName = Function.IsNull,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "isnotnull", new FunctionInfo()
{
FunctionName = Function.IsNotNull,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "left", new FunctionInfo()
{
FunctionName = Function.StringLeft,
RequiredParameters = 2,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "right", new FunctionInfo()
{
FunctionName = Function.StringRight,
RequiredParameters = 2,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "trim", new FunctionInfo()
{
FunctionName = Function.StringTrim,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "ltrim", new FunctionInfo()
{
FunctionName = Function.StringLTrim,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "rtrim", new FunctionInfo()
{
FunctionName = Function.StringRTrim,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "toupper", new FunctionInfo()
{
FunctionName = Function.StringToUpper,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "tolower", new FunctionInfo()
{
FunctionName = Function.StringToLower,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
{ "size", new FunctionInfo()
{
FunctionName = Function.StringSize,
RequiredParameters = 1,
OptionalParameters = 0,
ParameterChecker = EnsureParameterCountChecker
}
},
};
/// <summary>
/// Helper to check if a given function is supported or not
/// </summary>
/// <param name="functionName"></param>
/// <exception cref="TranspilerNotSupportedException">throws not supported exception if a function is not supported</exception>
/// <returns>Return function info object, or if no match, return null</returns>
public static FunctionInfo TryGetFunctionInfo(string functionName)
{
string lowerCaseFunctionName = functionName.ToLower();
FunctionInfo funcInfo = null;
if (_funcInfoMap.TryGetValue(functionName?.ToLower(), out funcInfo))
{
return funcInfo;
}
return null;
}
public static FunctionInfo GetFunctionInfo(Function functionNameEnum)
{
return _funcInfoMap.Values.FirstOrDefault(fi => fi.FunctionName == functionNameEnum);
}
}
}

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -0,0 +1,173 @@
T__0=1
T__1=2
T__2=3
T__3=4
T__4=5
T__5=6
T__6=7
T__7=8
T__8=9
T__9=10
T__10=11
T__11=12
T__12=13
T__13=14
T__14=15
T__15=16
T__16=17
T__17=18
T__18=19
T__19=20
T__20=21
T__21=22
T__22=23
T__23=24
T__24=25
T__25=26
T__26=27
T__27=28
T__28=29
T__29=30
T__30=31
T__31=32
T__32=33
T__33=34
T__34=35
T__35=36
T__36=37
T__37=38
T__38=39
T__39=40
T__40=41
T__41=42
T__42=43
T__43=44
T__44=45
UNION=46
ALL=47
OPTIONAL=48
MATCH=49
UNWIND=50
AS=51
MERGE=52
ON=53
CREATE=54
SET=55
DETACH=56
DELETE=57
REMOVE=58
CALL=59
YIELD=60
WITH=61
DISTINCT=62
RETURN=63
ORDER=64
BY=65
L_SKIP=66
LIMIT=67
ASCENDING=68
ASC=69
DESCENDING=70
DESC=71
WHERE=72
OR=73
XOR=74
AND=75
NOT=76
IN=77
STARTS=78
ENDS=79
CONTAINS=80
IS=81
NULL=82
COUNT=83
FILTER=84
EXTRACT=85
ANY=86
NONE=87
SINGLE=88
TRUE=89
FALSE=90
EXISTS=91
CASE=92
ELSE=93
END=94
WHEN=95
THEN=96
StringLiteral=97
EscapedChar=98
HexInteger=99
DecimalInteger=100
OctalInteger=101
HexLetter=102
HexDigit=103
Digit=104
NonZeroDigit=105
NonZeroOctDigit=106
OctDigit=107
ZeroDigit=108
ExponentDecimalReal=109
RegularDecimalReal=110
CONSTRAINT=111
DO=112
FOR=113
REQUIRE=114
UNIQUE=115
MANDATORY=116
SCALAR=117
OF=118
ADD=119
DROP=120
UnescapedSymbolicName=121
IdentifierStart=122
IdentifierPart=123
EscapedSymbolicName=124
SP=125
WHITESPACE=126
Comment=127
';'=1
','=2
'='=3
'+='=4
'-'=5
'*'=6
'('=7
')'=8
'['=9
']'=10
':'=11
'|'=12
'..'=13
'+'=14
'/'=15
'%'=16
'^'=17
'<>'=18
'<'=19
'>'=20
'<='=21
'>='=22
'.'=23
'{'=24
'}'=25
'$'=26
'⟨'=27
'〈'=28
'﹤'=29
'<'=30
'⟩'=31
'〉'=32
'ï¹¥'=33
'>'=34
'­'=35
'�'=36
'‑'=37
'‒'=38
'–'=39
'�'=40
'―'=41
'−'=42
'﹘'=43
'ï¹£'=44
'�'=45
'0'=108

Просмотреть файл

@ -0,0 +1,998 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// ANTLR Version: 4.7.2
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
// Generated from Cypher.g4 by ANTLR 4.7.2
// Unreachable code detected
#pragma warning disable 0162
// The variable '...' is assigned but its value is never used
#pragma warning disable 0219
// Missing XML comment for publicly visible type or member '...'
#pragma warning disable 1591
// Ambiguous reference in cref attribute
#pragma warning disable 419
namespace openCypherTranspiler.openCypherParser.ANTLR {
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Tree;
using IToken = Antlr4.Runtime.IToken;
using ParserRuleContext = Antlr4.Runtime.ParserRuleContext;
/// <summary>
/// This class provides an empty implementation of <see cref="ICypherVisitor{Result}"/>,
/// which can be extended to create a visitor which only needs to handle a subset
/// of the available methods.
/// </summary>
/// <typeparam name="Result">The return type of the visit operation.</typeparam>
[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.7.2")]
[System.CLSCompliant(false)]
public partial class CypherBaseVisitor<Result> : AbstractParseTreeVisitor<Result>, ICypherVisitor<Result> {
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Cypher"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Cypher([NotNull] CypherParser.OC_CypherContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Statement"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Statement([NotNull] CypherParser.OC_StatementContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Query"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Query([NotNull] CypherParser.OC_QueryContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RegularQuery"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_RegularQuery([NotNull] CypherParser.OC_RegularQueryContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Union"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Union([NotNull] CypherParser.OC_UnionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_SingleQuery"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_SingleQuery([NotNull] CypherParser.OC_SingleQueryContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_SinglePartQuery"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_SinglePartQuery([NotNull] CypherParser.OC_SinglePartQueryContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_MultiPartQuery"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_MultiPartQuery([NotNull] CypherParser.OC_MultiPartQueryContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_UpdatingClause"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_UpdatingClause([NotNull] CypherParser.OC_UpdatingClauseContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ReadingClause"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_ReadingClause([NotNull] CypherParser.OC_ReadingClauseContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Match"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Match([NotNull] CypherParser.OC_MatchContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Unwind"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Unwind([NotNull] CypherParser.OC_UnwindContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Merge"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Merge([NotNull] CypherParser.OC_MergeContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_MergeAction"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_MergeAction([NotNull] CypherParser.OC_MergeActionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Create"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Create([NotNull] CypherParser.OC_CreateContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Set"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Set([NotNull] CypherParser.OC_SetContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_SetItem"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_SetItem([NotNull] CypherParser.OC_SetItemContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Delete"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Delete([NotNull] CypherParser.OC_DeleteContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Remove"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Remove([NotNull] CypherParser.OC_RemoveContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RemoveItem"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_RemoveItem([NotNull] CypherParser.OC_RemoveItemContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_InQueryCall"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_InQueryCall([NotNull] CypherParser.OC_InQueryCallContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_StandaloneCall"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_StandaloneCall([NotNull] CypherParser.OC_StandaloneCallContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_YieldItems"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_YieldItems([NotNull] CypherParser.OC_YieldItemsContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_YieldItem"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_YieldItem([NotNull] CypherParser.OC_YieldItemContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_With"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_With([NotNull] CypherParser.OC_WithContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Return"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Return([NotNull] CypherParser.OC_ReturnContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ReturnBody"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_ReturnBody([NotNull] CypherParser.OC_ReturnBodyContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ReturnItems"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_ReturnItems([NotNull] CypherParser.OC_ReturnItemsContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ReturnItem"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_ReturnItem([NotNull] CypherParser.OC_ReturnItemContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Order"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Order([NotNull] CypherParser.OC_OrderContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Skip"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Skip([NotNull] CypherParser.OC_SkipContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Limit"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Limit([NotNull] CypherParser.OC_LimitContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_SortItem"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_SortItem([NotNull] CypherParser.OC_SortItemContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Where"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Where([NotNull] CypherParser.OC_WhereContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Pattern"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Pattern([NotNull] CypherParser.OC_PatternContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PatternPart"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_PatternPart([NotNull] CypherParser.OC_PatternPartContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_AnonymousPatternPart"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_AnonymousPatternPart([NotNull] CypherParser.OC_AnonymousPatternPartContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PatternElement"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_PatternElement([NotNull] CypherParser.OC_PatternElementContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_NodePattern"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_NodePattern([NotNull] CypherParser.OC_NodePatternContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PatternElementChain"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_PatternElementChain([NotNull] CypherParser.OC_PatternElementChainContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RelationshipPattern"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_RelationshipPattern([NotNull] CypherParser.OC_RelationshipPatternContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RelationshipDetail"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_RelationshipDetail([NotNull] CypherParser.OC_RelationshipDetailContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Properties"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Properties([NotNull] CypherParser.OC_PropertiesContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RelationshipTypes"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_RelationshipTypes([NotNull] CypherParser.OC_RelationshipTypesContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_NodeLabels"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_NodeLabels([NotNull] CypherParser.OC_NodeLabelsContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_NodeLabel"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_NodeLabel([NotNull] CypherParser.OC_NodeLabelContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RangeLiteral"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_RangeLiteral([NotNull] CypherParser.OC_RangeLiteralContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_LabelName"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_LabelName([NotNull] CypherParser.OC_LabelNameContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RelTypeName"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_RelTypeName([NotNull] CypherParser.OC_RelTypeNameContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Expression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Expression([NotNull] CypherParser.OC_ExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_OrExpression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_OrExpression([NotNull] CypherParser.OC_OrExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_XorExpression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_XorExpression([NotNull] CypherParser.OC_XorExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_AndExpression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_AndExpression([NotNull] CypherParser.OC_AndExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_NotExpression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_NotExpression([NotNull] CypherParser.OC_NotExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ComparisonExpression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_ComparisonExpression([NotNull] CypherParser.OC_ComparisonExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_AddOrSubtractExpression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_AddOrSubtractExpression([NotNull] CypherParser.OC_AddOrSubtractExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_MultiplyDivideModuloExpression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_MultiplyDivideModuloExpression([NotNull] CypherParser.OC_MultiplyDivideModuloExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PowerOfExpression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_PowerOfExpression([NotNull] CypherParser.OC_PowerOfExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_UnaryAddOrSubtractExpression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_UnaryAddOrSubtractExpression([NotNull] CypherParser.OC_UnaryAddOrSubtractExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_StringListNullOperatorExpression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_StringListNullOperatorExpression([NotNull] CypherParser.OC_StringListNullOperatorExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PropertyOrLabelsExpression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_PropertyOrLabelsExpression([NotNull] CypherParser.OC_PropertyOrLabelsExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Atom"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Atom([NotNull] CypherParser.OC_AtomContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Literal"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Literal([NotNull] CypherParser.OC_LiteralContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_BooleanLiteral"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_BooleanLiteral([NotNull] CypherParser.OC_BooleanLiteralContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ListLiteral"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_ListLiteral([NotNull] CypherParser.OC_ListLiteralContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PartialComparisonExpression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_PartialComparisonExpression([NotNull] CypherParser.OC_PartialComparisonExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ParenthesizedExpression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_ParenthesizedExpression([NotNull] CypherParser.OC_ParenthesizedExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RelationshipsPattern"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_RelationshipsPattern([NotNull] CypherParser.OC_RelationshipsPatternContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_FilterExpression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_FilterExpression([NotNull] CypherParser.OC_FilterExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_IdInColl"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_IdInColl([NotNull] CypherParser.OC_IdInCollContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_FunctionInvocation"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_FunctionInvocation([NotNull] CypherParser.OC_FunctionInvocationContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_FunctionName"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_FunctionName([NotNull] CypherParser.OC_FunctionNameContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ExplicitProcedureInvocation"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_ExplicitProcedureInvocation([NotNull] CypherParser.OC_ExplicitProcedureInvocationContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ImplicitProcedureInvocation"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_ImplicitProcedureInvocation([NotNull] CypherParser.OC_ImplicitProcedureInvocationContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ProcedureResultField"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_ProcedureResultField([NotNull] CypherParser.OC_ProcedureResultFieldContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ProcedureName"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_ProcedureName([NotNull] CypherParser.OC_ProcedureNameContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Namespace"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Namespace([NotNull] CypherParser.OC_NamespaceContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ListComprehension"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_ListComprehension([NotNull] CypherParser.OC_ListComprehensionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PatternComprehension"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_PatternComprehension([NotNull] CypherParser.OC_PatternComprehensionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PropertyLookup"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_PropertyLookup([NotNull] CypherParser.OC_PropertyLookupContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_CaseExpression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_CaseExpression([NotNull] CypherParser.OC_CaseExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_CaseAlternatives"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_CaseAlternatives([NotNull] CypherParser.OC_CaseAlternativesContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Variable"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Variable([NotNull] CypherParser.OC_VariableContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_NumberLiteral"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_NumberLiteral([NotNull] CypherParser.OC_NumberLiteralContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_MapLiteral"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_MapLiteral([NotNull] CypherParser.OC_MapLiteralContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Parameter"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Parameter([NotNull] CypherParser.OC_ParameterContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PropertyExpression"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_PropertyExpression([NotNull] CypherParser.OC_PropertyExpressionContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PropertyKeyName"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_PropertyKeyName([NotNull] CypherParser.OC_PropertyKeyNameContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_IntegerLiteral"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_IntegerLiteral([NotNull] CypherParser.OC_IntegerLiteralContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_DoubleLiteral"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_DoubleLiteral([NotNull] CypherParser.OC_DoubleLiteralContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_SchemaName"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_SchemaName([NotNull] CypherParser.OC_SchemaNameContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ReservedWord"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_ReservedWord([NotNull] CypherParser.OC_ReservedWordContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_SymbolicName"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_SymbolicName([NotNull] CypherParser.OC_SymbolicNameContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_LeftArrowHead"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_LeftArrowHead([NotNull] CypherParser.OC_LeftArrowHeadContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RightArrowHead"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_RightArrowHead([NotNull] CypherParser.OC_RightArrowHeadContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Dash"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitOC_Dash([NotNull] CypherParser.OC_DashContext context) { return VisitChildren(context); }
}
} // namespace openCypherTranspiler.openCypherParser.ANTLR

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -0,0 +1,173 @@
T__0=1
T__1=2
T__2=3
T__3=4
T__4=5
T__5=6
T__6=7
T__7=8
T__8=9
T__9=10
T__10=11
T__11=12
T__12=13
T__13=14
T__14=15
T__15=16
T__16=17
T__17=18
T__18=19
T__19=20
T__20=21
T__21=22
T__22=23
T__23=24
T__24=25
T__25=26
T__26=27
T__27=28
T__28=29
T__29=30
T__30=31
T__31=32
T__32=33
T__33=34
T__34=35
T__35=36
T__36=37
T__37=38
T__38=39
T__39=40
T__40=41
T__41=42
T__42=43
T__43=44
T__44=45
UNION=46
ALL=47
OPTIONAL=48
MATCH=49
UNWIND=50
AS=51
MERGE=52
ON=53
CREATE=54
SET=55
DETACH=56
DELETE=57
REMOVE=58
CALL=59
YIELD=60
WITH=61
DISTINCT=62
RETURN=63
ORDER=64
BY=65
L_SKIP=66
LIMIT=67
ASCENDING=68
ASC=69
DESCENDING=70
DESC=71
WHERE=72
OR=73
XOR=74
AND=75
NOT=76
IN=77
STARTS=78
ENDS=79
CONTAINS=80
IS=81
NULL=82
COUNT=83
FILTER=84
EXTRACT=85
ANY=86
NONE=87
SINGLE=88
TRUE=89
FALSE=90
EXISTS=91
CASE=92
ELSE=93
END=94
WHEN=95
THEN=96
StringLiteral=97
EscapedChar=98
HexInteger=99
DecimalInteger=100
OctalInteger=101
HexLetter=102
HexDigit=103
Digit=104
NonZeroDigit=105
NonZeroOctDigit=106
OctDigit=107
ZeroDigit=108
ExponentDecimalReal=109
RegularDecimalReal=110
CONSTRAINT=111
DO=112
FOR=113
REQUIRE=114
UNIQUE=115
MANDATORY=116
SCALAR=117
OF=118
ADD=119
DROP=120
UnescapedSymbolicName=121
IdentifierStart=122
IdentifierPart=123
EscapedSymbolicName=124
SP=125
WHITESPACE=126
Comment=127
';'=1
','=2
'='=3
'+='=4
'-'=5
'*'=6
'('=7
')'=8
'['=9
']'=10
':'=11
'|'=12
'..'=13
'+'=14
'/'=15
'%'=16
'^'=17
'<>'=18
'<'=19
'>'=20
'<='=21
'>='=22
'.'=23
'{'=24
'}'=25
'$'=26
'⟨'=27
'〈'=28
'﹤'=29
'<'=30
'⟩'=31
'〉'=32
'ï¹¥'=33
'>'=34
'­'=35
'�'=36
'‑'=37
'‒'=38
'–'=39
'�'=40
'―'=41
'−'=42
'﹘'=43
'ï¹£'=44
'�'=45
'0'=108

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,612 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// ANTLR Version: 4.7.2
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
// Generated from Cypher.g4 by ANTLR 4.7.2
// Unreachable code detected
#pragma warning disable 0162
// The variable '...' is assigned but its value is never used
#pragma warning disable 0219
// Missing XML comment for publicly visible type or member '...'
#pragma warning disable 1591
// Ambiguous reference in cref attribute
#pragma warning disable 419
namespace openCypherTranspiler.openCypherParser.ANTLR {
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Tree;
using IToken = Antlr4.Runtime.IToken;
/// <summary>
/// This interface defines a complete generic visitor for a parse tree produced
/// by <see cref="CypherParser"/>.
/// </summary>
/// <typeparam name="Result">The return type of the visit operation.</typeparam>
[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.7.2")]
[System.CLSCompliant(false)]
public interface ICypherVisitor<Result> : IParseTreeVisitor<Result> {
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Cypher"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Cypher([NotNull] CypherParser.OC_CypherContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Statement"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Statement([NotNull] CypherParser.OC_StatementContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Query"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Query([NotNull] CypherParser.OC_QueryContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RegularQuery"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_RegularQuery([NotNull] CypherParser.OC_RegularQueryContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Union"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Union([NotNull] CypherParser.OC_UnionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_SingleQuery"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_SingleQuery([NotNull] CypherParser.OC_SingleQueryContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_SinglePartQuery"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_SinglePartQuery([NotNull] CypherParser.OC_SinglePartQueryContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_MultiPartQuery"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_MultiPartQuery([NotNull] CypherParser.OC_MultiPartQueryContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_UpdatingClause"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_UpdatingClause([NotNull] CypherParser.OC_UpdatingClauseContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ReadingClause"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_ReadingClause([NotNull] CypherParser.OC_ReadingClauseContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Match"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Match([NotNull] CypherParser.OC_MatchContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Unwind"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Unwind([NotNull] CypherParser.OC_UnwindContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Merge"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Merge([NotNull] CypherParser.OC_MergeContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_MergeAction"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_MergeAction([NotNull] CypherParser.OC_MergeActionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Create"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Create([NotNull] CypherParser.OC_CreateContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Set"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Set([NotNull] CypherParser.OC_SetContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_SetItem"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_SetItem([NotNull] CypherParser.OC_SetItemContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Delete"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Delete([NotNull] CypherParser.OC_DeleteContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Remove"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Remove([NotNull] CypherParser.OC_RemoveContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RemoveItem"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_RemoveItem([NotNull] CypherParser.OC_RemoveItemContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_InQueryCall"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_InQueryCall([NotNull] CypherParser.OC_InQueryCallContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_StandaloneCall"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_StandaloneCall([NotNull] CypherParser.OC_StandaloneCallContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_YieldItems"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_YieldItems([NotNull] CypherParser.OC_YieldItemsContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_YieldItem"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_YieldItem([NotNull] CypherParser.OC_YieldItemContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_With"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_With([NotNull] CypherParser.OC_WithContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Return"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Return([NotNull] CypherParser.OC_ReturnContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ReturnBody"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_ReturnBody([NotNull] CypherParser.OC_ReturnBodyContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ReturnItems"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_ReturnItems([NotNull] CypherParser.OC_ReturnItemsContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ReturnItem"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_ReturnItem([NotNull] CypherParser.OC_ReturnItemContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Order"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Order([NotNull] CypherParser.OC_OrderContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Skip"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Skip([NotNull] CypherParser.OC_SkipContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Limit"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Limit([NotNull] CypherParser.OC_LimitContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_SortItem"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_SortItem([NotNull] CypherParser.OC_SortItemContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Where"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Where([NotNull] CypherParser.OC_WhereContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Pattern"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Pattern([NotNull] CypherParser.OC_PatternContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PatternPart"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_PatternPart([NotNull] CypherParser.OC_PatternPartContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_AnonymousPatternPart"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_AnonymousPatternPart([NotNull] CypherParser.OC_AnonymousPatternPartContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PatternElement"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_PatternElement([NotNull] CypherParser.OC_PatternElementContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_NodePattern"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_NodePattern([NotNull] CypherParser.OC_NodePatternContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PatternElementChain"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_PatternElementChain([NotNull] CypherParser.OC_PatternElementChainContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RelationshipPattern"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_RelationshipPattern([NotNull] CypherParser.OC_RelationshipPatternContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RelationshipDetail"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_RelationshipDetail([NotNull] CypherParser.OC_RelationshipDetailContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Properties"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Properties([NotNull] CypherParser.OC_PropertiesContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RelationshipTypes"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_RelationshipTypes([NotNull] CypherParser.OC_RelationshipTypesContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_NodeLabels"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_NodeLabels([NotNull] CypherParser.OC_NodeLabelsContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_NodeLabel"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_NodeLabel([NotNull] CypherParser.OC_NodeLabelContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RangeLiteral"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_RangeLiteral([NotNull] CypherParser.OC_RangeLiteralContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_LabelName"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_LabelName([NotNull] CypherParser.OC_LabelNameContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RelTypeName"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_RelTypeName([NotNull] CypherParser.OC_RelTypeNameContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Expression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Expression([NotNull] CypherParser.OC_ExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_OrExpression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_OrExpression([NotNull] CypherParser.OC_OrExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_XorExpression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_XorExpression([NotNull] CypherParser.OC_XorExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_AndExpression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_AndExpression([NotNull] CypherParser.OC_AndExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_NotExpression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_NotExpression([NotNull] CypherParser.OC_NotExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ComparisonExpression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_ComparisonExpression([NotNull] CypherParser.OC_ComparisonExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_AddOrSubtractExpression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_AddOrSubtractExpression([NotNull] CypherParser.OC_AddOrSubtractExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_MultiplyDivideModuloExpression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_MultiplyDivideModuloExpression([NotNull] CypherParser.OC_MultiplyDivideModuloExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PowerOfExpression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_PowerOfExpression([NotNull] CypherParser.OC_PowerOfExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_UnaryAddOrSubtractExpression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_UnaryAddOrSubtractExpression([NotNull] CypherParser.OC_UnaryAddOrSubtractExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_StringListNullOperatorExpression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_StringListNullOperatorExpression([NotNull] CypherParser.OC_StringListNullOperatorExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PropertyOrLabelsExpression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_PropertyOrLabelsExpression([NotNull] CypherParser.OC_PropertyOrLabelsExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Atom"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Atom([NotNull] CypherParser.OC_AtomContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Literal"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Literal([NotNull] CypherParser.OC_LiteralContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_BooleanLiteral"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_BooleanLiteral([NotNull] CypherParser.OC_BooleanLiteralContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ListLiteral"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_ListLiteral([NotNull] CypherParser.OC_ListLiteralContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PartialComparisonExpression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_PartialComparisonExpression([NotNull] CypherParser.OC_PartialComparisonExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ParenthesizedExpression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_ParenthesizedExpression([NotNull] CypherParser.OC_ParenthesizedExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RelationshipsPattern"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_RelationshipsPattern([NotNull] CypherParser.OC_RelationshipsPatternContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_FilterExpression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_FilterExpression([NotNull] CypherParser.OC_FilterExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_IdInColl"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_IdInColl([NotNull] CypherParser.OC_IdInCollContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_FunctionInvocation"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_FunctionInvocation([NotNull] CypherParser.OC_FunctionInvocationContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_FunctionName"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_FunctionName([NotNull] CypherParser.OC_FunctionNameContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ExplicitProcedureInvocation"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_ExplicitProcedureInvocation([NotNull] CypherParser.OC_ExplicitProcedureInvocationContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ImplicitProcedureInvocation"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_ImplicitProcedureInvocation([NotNull] CypherParser.OC_ImplicitProcedureInvocationContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ProcedureResultField"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_ProcedureResultField([NotNull] CypherParser.OC_ProcedureResultFieldContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ProcedureName"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_ProcedureName([NotNull] CypherParser.OC_ProcedureNameContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Namespace"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Namespace([NotNull] CypherParser.OC_NamespaceContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ListComprehension"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_ListComprehension([NotNull] CypherParser.OC_ListComprehensionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PatternComprehension"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_PatternComprehension([NotNull] CypherParser.OC_PatternComprehensionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PropertyLookup"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_PropertyLookup([NotNull] CypherParser.OC_PropertyLookupContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_CaseExpression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_CaseExpression([NotNull] CypherParser.OC_CaseExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_CaseAlternatives"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_CaseAlternatives([NotNull] CypherParser.OC_CaseAlternativesContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Variable"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Variable([NotNull] CypherParser.OC_VariableContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_NumberLiteral"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_NumberLiteral([NotNull] CypherParser.OC_NumberLiteralContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_MapLiteral"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_MapLiteral([NotNull] CypherParser.OC_MapLiteralContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Parameter"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Parameter([NotNull] CypherParser.OC_ParameterContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PropertyExpression"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_PropertyExpression([NotNull] CypherParser.OC_PropertyExpressionContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_PropertyKeyName"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_PropertyKeyName([NotNull] CypherParser.OC_PropertyKeyNameContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_IntegerLiteral"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_IntegerLiteral([NotNull] CypherParser.OC_IntegerLiteralContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_DoubleLiteral"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_DoubleLiteral([NotNull] CypherParser.OC_DoubleLiteralContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_SchemaName"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_SchemaName([NotNull] CypherParser.OC_SchemaNameContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_ReservedWord"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_ReservedWord([NotNull] CypherParser.OC_ReservedWordContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_SymbolicName"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_SymbolicName([NotNull] CypherParser.OC_SymbolicNameContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_LeftArrowHead"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_LeftArrowHead([NotNull] CypherParser.OC_LeftArrowHeadContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_RightArrowHead"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_RightArrowHead([NotNull] CypherParser.OC_RightArrowHeadContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="CypherParser.oC_Dash"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitOC_Dash([NotNull] CypherParser.OC_DashContext context);
}
} // namespace openCypherTranspiler.openCypherParser.ANTLR

Просмотреть файл

@ -0,0 +1 @@
java org.antlr.v4.Tool %*

Просмотреть файл

@ -0,0 +1,30 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using Antlr4.Runtime;
using openCypherTranspiler.Common.Logging;
using openCypherTranspiler.openCypherParser.ANTLR;
using openCypherTranspiler.openCypherParser.AST;
namespace openCypherTranspiler.openCypherParser
{
public class OpenCypherParser
{
private OpenCypherParser()
{ }
public static QueryTreeNode Parse(string cypherQueryText, ILoggable logger = null)
{
var lexer = new CypherLexer(new AntlrInputStream(cypherQueryText));
var tokens = new CommonTokenStream(lexer);
var parser = new CypherParser(tokens);
var visitor = new CypherVisitor(logger);
var result = visitor.Visit(parser.oC_Cypher()) as QueryTreeNode;
return result;
}
}
}

Просмотреть файл

@ -0,0 +1,35 @@
# openCypherParser
The 'Grammar' sub-folder contains [ANTLR4](https://github.com/antlr) generated visitors using the g4 grammar file published by [openCypher project](http://www.opencypher.org/).
To regenerate the grammar file in the event of openCypher specification updates, please follow the steps below.
## Prerequisites
Before building project, make sure you have:
* Java 8 SDK. E.g. on Windows
* Dotnet Core SDK 2.2
* Latest ANTLR4 Tools (download and use [ANTLR4 tools](https://github.com/antlr/antlr4/blob/master/doc/getting-started.md))
E.g. on Windows:
```batch
REM Download and install dependencies
choco install dotnetcore-sdk openjdk curl
REM Get ANTLR4 tools
mkdir %USERPROFILE%\javalibs
cd /d %USERPROFILE%\javalibs
curl https://www.antlr.org/download/antlr-4.7.2-complete.jar --output antlr-4.7.2-complete.jar
SET CLASSPATH=%CLASSPATH%%USERPROFILE%\javalibs\antlr-4.7.2-complete.jar;
setx CLASSPATH %CLASSPATH%
```
## (Re)Build Cypher visitor base
To rebuild the grammar classes do:
```batch
cd <ProjectFolder>\openCypherParser\Grammar
antlr4 -package openCypherTranspiler.openCypherParser.ANTLR -Dlanguage=CSharp -no-listener -visitor Cypher.g4
```

Просмотреть файл

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RootNamespace>Microsoft.GraphPlatform.Transpiler.openCypherParser</RootNamespace>
<NoWarn>CS3021</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Logical\**" />
<EmbeddedResource Remove="Logical\**" />
<None Remove="Logical\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Antlr4.Runtime.Standard" Version="4.7.2" />
</ItemGroup>
<ItemGroup>
<Folder Include="Common\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common\Common.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RootNamespace>Microsoft.GraphPlatform.Transpiler.CommonTest</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Common\Common.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,108 @@
/*---------------------------------------------------------------------------------------------
* Copyright(c) Microsoft Corporation.All rights reserved.
* Licensed under the MIT License.See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
using openCypherTranspiler.Common.GraphSchema;
namespace openCypherTranspiler.CommonTest
{
public class JSONGraphSchema : IGraphSchemaProvider
{
private IList<NodeSchema> _allNodeDefinions;
private IList<EdgeSchema> _allEdgeDefinions;
public JSONGraphSchema(string file)
{
LoadFromFile(file);
}
private void LoadFromFile(string file)
{
var res = JsonConvert.DeserializeObject<dynamic>(File.ReadAllText(file));
var allnodes = new Dictionary<string, NodeSchema>();
foreach (var n in res.Nodes)
{
var nodeName = n.Name.ToString();
var nodeDef = new NodeSchema()
{
Name = nodeName,
Properties = (n.Properties?.ToObject<List<dynamic>>() as List<dynamic> ?? Enumerable.Empty<dynamic>())
.Select(s => (new EntityProperty()
{
PropertyName = s.PropertyName.ToString(),
DataType = Type.GetType(s.PropertyType.ToString()),
PropertyType = EntityProperty.PropertyDefinitionType.RegularProperty
})).ToList(),
NodeIdProperty = new EntityProperty()
{
PropertyName = n.IdProperty.PropertyName.ToString(),
DataType = Type.GetType(n.IdProperty.PropertyType.ToString()),
PropertyType = EntityProperty.PropertyDefinitionType.NodeJoinKey
},
};
allnodes.Add(nodeName, nodeDef);
}
_allNodeDefinions = allnodes.Values.ToList();
_allEdgeDefinions = new List<EdgeSchema>();
foreach (var e in res.Edges)
{
_allEdgeDefinions.Add(new EdgeSchema()
{
Name = e.Name.ToString(),
SourceNodeId= e.FromNode.ToString(),
SinkNodeId = e.ToNode.ToString(),
Properties = (e.Properties?.ToObject<List<dynamic>>() as List<dynamic> ?? Enumerable.Empty<dynamic>())
.Select(s => (new EntityProperty()
{
PropertyName = s.PropertyName.ToString(),
DataType = Type.GetType(s.PropertyType.ToString())
})).ToList(),
SourceIdProperty = new EntityProperty()
{
PropertyName = e.SourceIdProperty.PropertyName.ToString(),
DataType = Type.GetType(e.SourceIdProperty.PropertyType.ToString()),
PropertyType = EntityProperty.PropertyDefinitionType.NodeJoinKey
},
SinkIdProperty = new EntityProperty()
{
PropertyName = e.SinkIdProperty.PropertyName.ToString(),
DataType = Type.GetType(e.SinkIdProperty.PropertyType.ToString()),
PropertyType = EntityProperty.PropertyDefinitionType.NodeJoinKey
},
});
}
}
public EdgeSchema GetEdgeDefinition(string edgeVerb, string fromNodeName, string toNodeName)
{
var edge = _allEdgeDefinions?.Where(n => n.Name == edgeVerb && n.SourceNodeId == fromNodeName && n.SinkNodeId == toNodeName).FirstOrDefault();
if (edge == null)
{
throw new KeyNotFoundException($"Edge with edgeverb = {edgeVerb}, fromNodeName = {fromNodeName} and toNodename = {toNodeName} not found!");
}
return edge;
}
public NodeSchema GetNodeDefinition(string nodeName)
{
var node = _allNodeDefinions?.Where(n => n.Name == nodeName).FirstOrDefault();
if (node == null)
{
throw new KeyNotFoundException($"Node with name = {nodeName} not found!");
}
return node;
}
}
}

Просмотреть файл

@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
using System.Diagnostics;
using openCypherTranspiler.Common.Logging;
namespace openCypherTranspiler.CommonTest
{
public class TestLogger : BaseLogger, ILoggable
{
public TestLogger(LoggingLevel logLevel = LoggingLevel.Verbose)
{
SetLoggingLevel(logLevel);
}
protected override void LogMessage(string msgFormat, params object[] msgArgs)
{
Console.WriteLine(msgFormat, msgArgs);
#if DEBUG
Debug.WriteLine(msgFormat, msgArgs);
#endif
}
}
}

Просмотреть файл

@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
<RootNamespace>Microsoft.GraphPlatform.Transpiler.LogicalPlanner.Test</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.3.2" />
<PackageReference Include="MSTest.TestFramework" Version="1.3.2" />
</ItemGroup>
<ItemGroup>
<Folder Include="TestData\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CommonTest\CommonTest.csproj" />
<ProjectReference Include="..\..\src\LogicalPlanner\LogicalPlanner.csproj" />
<ProjectReference Include="..\..\src\openCypherParser\openCypherParser.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="TestData\MovieGraph.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,419 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using openCypherTranspiler.Common.Exceptions;
using openCypherTranspiler.Common.GraphSchema;
using openCypherTranspiler.Common.Logging;
using openCypherTranspiler.CommonTest;
using openCypherTranspiler.LogicalPlanner.Utils;
using openCypherTranspiler.openCypherParser;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq;
using JT = openCypherTranspiler.LogicalPlanner.JoinOperator.JoinType;
namespace openCypherTranspiler.LogicalPlanner.Test
{
/// <summary>
/// Test the logical planner (which turns parsed cypher statement into
/// relational algebra
/// </summary>
[TestClass]
public class LogicalPlannerTest
{
private ILoggable _logger = new TestLogger();
private bool MatrixEquals<T>(T[,] data1, T[,] data2)
{
var equal =
data1.Rank == data2.Rank &&
Enumerable.Range(0, data1.Rank).All(dimension => data1.GetLength(dimension) == data2.GetLength(dimension)) &&
data1.Cast<T>().SequenceEqual(data2.Cast<T>());
return equal;
}
private LogicalPlan RunQueryAndDumpTree(IGraphSchemaProvider graphDef, string cypherQueryText)
{
var queryNode = OpenCypherParser.Parse(cypherQueryText, _logger);
var planner = LogicalPlan.ProcessQueryTree(queryNode, graphDef);
Assert.IsNotNull(planner.StartingOperators);
Assert.IsNotNull(planner.TerminalOperators);
// Dump both parse tree and logical plan
var tree = queryNode.DumpTree();
var logical = planner.DumpGraph();
return planner;
}
[TestMethod]
public void TestTransitiveClosureHelper()
{
{
// equivalent of MATCH (a)-[b]-(c), (d)
var startMat = new JT[4, 4]
{
{ JT.Inner, JT.Inner, JT.Cross, JT.Cross },
{ JT.Inner, JT.Inner, JT.Inner, JT.Cross },
{ JT.Cross, JT.Inner, JT.Inner, JT.Cross },
{ JT.Cross, JT.Cross, JT.Cross, JT.Inner },
};
var expectedMat = new JT[4, 4]
{
{ JT.Inner, JT.Inner, JT.Inner, JT.Cross },
{ JT.Inner, JT.Inner, JT.Inner, JT.Cross },
{ JT.Inner, JT.Inner, JT.Inner, JT.Cross },
{ JT.Cross, JT.Cross, JT.Cross, JT.Inner },
};
var actualMat = startMat.TransitiveClosure();
Assert.IsTrue(MatrixEquals(expectedMat, actualMat));
}
{
// equivalent of MATCH (a)-[b]-(c),
// OPTIONAL MATCH (c)-[d]-(e)
var startMat = new JT[5, 5]
{
{ JT.Inner, JT.Inner, JT.Cross, JT.Cross, JT.Cross },
{ JT.Inner, JT.Inner, JT.Inner, JT.Cross, JT.Cross },
{ JT.Cross, JT.Inner, JT.Inner, JT.Left, JT.Cross },
{ JT.Cross, JT.Cross, JT.Left, JT.Inner, JT.Left },
{ JT.Cross, JT.Cross, JT.Cross, JT.Left, JT.Inner },
};
var expectedMat = new JT[5, 5]
{
{ JT.Inner, JT.Inner, JT.Inner, JT.Left, JT.Left },
{ JT.Inner, JT.Inner, JT.Inner, JT.Left, JT.Left },
{ JT.Inner, JT.Inner, JT.Inner, JT.Left, JT.Left },
{ JT.Left, JT.Left, JT.Left, JT.Inner, JT.Left },
{ JT.Left, JT.Left, JT.Left, JT.Left, JT.Inner },
};
var actualMat = startMat.TransitiveClosure();
Assert.IsTrue(MatrixEquals(expectedMat, actualMat));
}
{
// equivalent of MATCH (a)-[b]-(c),
// MATCH (c)-[d]-(a)
// OPTIONAL MATCH (c)-[e]-(a)
var startMat = new JT[5, 5]
{
{ JT.Inner, JT.Inner, JT.Cross, JT.Inner, JT.Left },
{ JT.Inner, JT.Inner, JT.Inner, JT.Cross, JT.Cross },
{ JT.Cross, JT.Inner, JT.Inner, JT.Inner, JT.Left },
{ JT.Inner, JT.Cross, JT.Inner, JT.Inner, JT.Cross },
{ JT.Left, JT.Cross, JT.Left, JT.Cross, JT.Inner },
};
var expectedMat = new JT[5, 5]
{
{ JT.Inner, JT.Inner, JT.Inner, JT.Inner, JT.Left },
{ JT.Inner, JT.Inner, JT.Inner, JT.Inner, JT.Left },
{ JT.Inner, JT.Inner, JT.Inner, JT.Inner, JT.Left },
{ JT.Inner, JT.Inner, JT.Inner, JT.Inner, JT.Left },
{ JT.Left, JT.Left, JT.Left, JT.Left, JT.Inner },
};
var actualMat = startMat.TransitiveClosure();
Assert.IsTrue(MatrixEquals(expectedMat, actualMat));
}
}
[TestMethod]
public void BasicTestLogicalPlanner()
{
IGraphSchemaProvider graphDef = new JSONGraphSchema(@"./TestData/MovieGraph.json");
// Basic test with no WITH and OPTIONAL
{
var lp = RunQueryAndDumpTree(graphDef, @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
RETURN p.Name, m.Title
"
);
// TODO: structural verification
Assert.IsTrue(lp.StartingOperators.Count() > 0);
Assert.IsTrue(lp.TerminalOperators.Count() == 1);
}
// Basic test with optional match
{
var lp = RunQueryAndDumpTree(graphDef, @"
MATCH (p:Person)-[r:REVIEWED]->(m:Movie)
OPTIONAL MATCH (p)<-[:FOLLOWS]-(p2:Person)-[r2:REVIEWED]->(m)
return p.Name as Name1, p2.Name as Name2, m.Title as Title, r.Rating as Rating1, r2.Rating as Rating2
"
);
// TODO: structural verification
Assert.IsTrue(lp.StartingOperators.Count() > 0);
Assert.IsTrue(lp.TerminalOperators.Count() == 1);
// nullable no change after optional match
Assert.IsTrue((lp.TerminalOperators.First().OutputSchema.First(f => f.FieldAlias == "Name1") as SingleField).FieldType == typeof(string));
Assert.IsTrue((lp.TerminalOperators.First().OutputSchema.First(f => f.FieldAlias == "Name2") as SingleField).FieldType == typeof(string));
// non nullable changed to nullable after optional match
Assert.IsTrue((lp.TerminalOperators.First().OutputSchema.First(f => f.FieldAlias == "Rating1") as SingleField).FieldType == typeof(int));
Assert.IsTrue((lp.TerminalOperators.First().OutputSchema.First(f => f.FieldAlias == "Rating2") as SingleField).FieldType == typeof(int?));
}
// Basic test with WITH and OPTIONAL match
{
var lp = RunQueryAndDumpTree(graphDef, @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WITH p, m
OPTIONAL MATCH (p)-[d:DIRECTED]->(m)
RETURN p.Name, m.Title
"
);
// TODO: structural verification
Assert.IsTrue(lp.StartingOperators.Count() > 0);
Assert.IsTrue(lp.TerminalOperators.Count() == 1);
}
// Basic test with plan tree optimization that collapse pure MATCHes
{
var lp = RunQueryAndDumpTree(graphDef, @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
MATCH (p)-[p2:PRODUCED]->(m)
OPTIONAL MATCH (p)-[d:DIRECTED]->(m)
RETURN p.Name, m.Title
"
);
// TODO: structural verification
Assert.IsTrue(lp.StartingOperators.Count() > 0);
Assert.IsTrue(lp.TerminalOperators.Count() == 1);
}
// Duplicated match patterns
{
var lp = RunQueryAndDumpTree(graphDef, @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie), (p)-[p2:PRODUCED]->(m)
MATCH (p)-[p2:PRODUCED]->(m)
OPTIONAL MATCH (p)-[d:DIRECTED]->(m)
RETURN p.Name, m.Title
"
);
// TODO: structural verification
Assert.IsTrue(lp.StartingOperators.Count() > 0);
Assert.IsTrue(lp.TerminalOperators.Count() == 1);
}
// Functions and WITH with additional returns
{
var lp = RunQueryAndDumpTree(graphDef, @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie), (p)-[p2:PRODUCED]->(m)
WITH a.Roles as ActedRoles, p, m
OPTIONAL MATCH (p)-[d:REVIEWED]->(m)
WITH d.Summary as ReviewSummary, d.Rating as ReviewRating, p, m, ActedRoles
RETURN p.Name, m.Title, ActedRoles, ReviewRating, ReviewSummary
"
);
// TODO: structural verification
Assert.IsTrue(lp.StartingOperators.Count() > 0);
Assert.IsTrue(lp.TerminalOperators.Count() == 1);
}
// Twisted alias for with/return entities
{
var lp = RunQueryAndDumpTree(graphDef, @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WITH p as m, m as p
MATCH (m)-[a:DIRECTED]->(p)
RETURN m.Name, p.Title
"
);
// TODO: structural verification
Assert.IsTrue(lp.StartingOperators.Count() > 0);
Assert.IsTrue(lp.TerminalOperators.Count() == 1);
}
// Join two already joined patterns
{
var lp = RunQueryAndDumpTree(graphDef, @"
MATCH (p:Person)-[:REVIEWED]->(m:Movie)
MATCH (p2:Person)-[:REVIEWED]->(m2:Movie)
MATCH (p:Person)-[:FOLLOWS]->(p2:Person)
RETURN p.Name as Name1, m.Title as Title1, p2.Name as Name2, m2.Title as Title2
"
);
// TODO: structural verification
Assert.IsTrue(lp.StartingOperators.Count() > 0);
Assert.IsTrue(lp.TerminalOperators.Count() == 1);
}
// basic WHERE test
{
var lp = RunQueryAndDumpTree(graphDef, @"
MATCH (p:Person)-[:REVIEWED]->(m:Movie)
WHERE p.Name = 'Tom Hanks'
RETURN p.Name as Name
"
);
// TODO: structural verification
Assert.IsTrue(lp.StartingOperators.Count() > 0);
Assert.IsTrue(lp.TerminalOperators.Count() == 1);
}
// WHERE attached to optional match
{
var lp = RunQueryAndDumpTree(graphDef, @"
MATCH (p:Person)
OPTIONAL MATCH (p:Person)-[:REVIEWED]->(m:Movie)
WHERE p.Name = 'Tom Hanks'
RETURN p.Name as Name
"
);
// TODO: structural verification
Assert.IsTrue(lp.StartingOperators.Count() > 0);
Assert.IsTrue(lp.TerminalOperators.Count() == 1);
}
// WHERE attached to WITH projection
{
var lp = RunQueryAndDumpTree(graphDef, @"
MATCH (p:Person)
OPTIONAL MATCH (p:Person)-[:REVIEWED]->(m:Movie)
WITH p, m
WHERE p.Name = 'Tom Hanks'
RETURN p.Name as Name
"
);
// TODO: structural verification
Assert.IsTrue(lp.StartingOperators.Count() > 0);
Assert.IsTrue(lp.TerminalOperators.Count() == 1);
}
}
[TestMethod]
public void AdvancedTestLogicalPlanner()
{
IGraphSchemaProvider graphDef = new JSONGraphSchema(@"./TestData/MovieGraph.json");
// Duplicate (or overlapping) match pattern across WITH barrier
{
// join is outter then upgraded to inner after WITH barrier
// Today, we have less optimized plan by not allow the join
// to propagate up past the WITH barrier.
var lp = RunQueryAndDumpTree(graphDef, @"
match (n: Person), (m: Movie)
where n.Name = 'Tom Hanks'
with n, m
optional match(n)-[:ACTED_IN]-(m)
with n, m
match(n)-[:ACTED_IN]-(m)
return distinct n.Name, m.Title
"
);
// TODO: structural verification
Assert.IsTrue(lp.StartingOperators.Count() > 0);
Assert.IsTrue(lp.TerminalOperators.Count() == 1);
}
// More complicated pattern in a single match clause that requires inequality conditions to be added
{
// implicit condition to be added is ACTED_IN should not be the same by its 2 key ids
var lp = RunQueryAndDumpTree(graphDef, @"
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)<-[:ACTED_IN]-(p2:Person)
RETURN p.Name AS Name, p2.Name as CoStarName
"
);
Assert.IsTrue(lp.StartingOperators.Count() > 0);
Assert.IsTrue(lp.TerminalOperators.Count() == 1);
// make sure that the selection condition is added
var conditionOpsAdded = lp.TerminalOperators.First().GetAllUpstreamOperatorsOfType<SelectionOperator>();
Assert.IsTrue(conditionOpsAdded.Count() == 1);
Assert.IsTrue(conditionOpsAdded.First().UnexpandedEntityInequalityConditions.Count() == 1);
Assert.IsTrue(conditionOpsAdded.First().FilterExpression != null);
}
}
public void NegativeTestLogicalPlanner()
{
IGraphSchemaProvider graphDef = new JSONGraphSchema(@".\TestData\Movie\MovieGraph.json");
// Our implementation block of returning whole entity instead of its fields
// We don't support packing whole entity into JSON today, as JSON blob in Cosmos
// is not very useful for any further computations
{
try
{
var lp = RunQueryAndDumpTree(graphDef, @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie), (p)-[p2:PRODUCED]->(m)
MATCH (p)-[p2:PRODUCED]->(m)
OPTIONAL MATCH (p)-[d:DIRECTED]->(m)
RETURN p
"
);
Assert.Fail("Didn't failed as expected.");
}
catch (TranspilerNotSupportedException e)
{
Assert.IsTrue(e.Message.Contains("Query final return body returns the whole entity"));
}
}
// repeated relationship pattern on the same match statement
// NOTE: repeated relationship pattern not on the same match statement is still supported
{
try
{
var lp = RunQueryAndDumpTree(graphDef, @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie), (p2:Person)-[a:ACTED_IN]->(m2:Movie)
RETURN p.Name, m.Title
"
);
Assert.Fail("Didn't failed as expected.");
}
catch (TranspilerNotSupportedException e)
{
Assert.IsTrue(e.Message.Contains("Cannot use the same relationship variable 'a'"));
}
}
}
public void NegativeTestLogicalPlannerSchemaBinding()
{
IGraphSchemaProvider graphDef = new JSONGraphSchema(@"./TestData/MovieGraph.json");
// Binding to non exist node
{
try
{
var lp = RunQueryAndDumpTree(graphDef, @"
MATCH (p:Actor)
RETURN p
"
);
Assert.Fail("Didn't failed as expected.");
}
catch (TranspilerBindingException e)
{
Assert.IsTrue(e.Message.Contains("Actor"));
}
try
{
var lp = RunQueryAndDumpTree(graphDef, @"
MATCH (p:Person)-[:Performed]-(m:Movie)
RETURN p
"
);
Assert.Fail("Didn't failed as expected.");
}
catch (TranspilerBindingException e)
{
Assert.IsTrue(e.Message.Contains("Performed"));
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,150 @@
{
"Nodes": [
{
"Id": "Person",
"Name": "Person",
"IdProperty": {
"PropertyName": "id",
"PropertyType": "System.String"
},
"Properties": [
{
"PropertyName": "Name",
"PropertyType": "System.String"
},
{
"PropertyName": "Born",
"PropertyType": "System.Nullable`1[System.Int32]"
}
]
},
{
"Id": "Movie",
"Name": "Movie",
"IdProperty": {
"PropertyName": "id",
"PropertyType": "System.String"
},
"Properties": [
{
"PropertyName": "Title",
"PropertyType": "System.String"
},
{
"PropertyName": "Tagline",
"PropertyType": "System.String"
},
{
"PropertyName": "Released",
"PropertyType": "System.Int32"
}
]
}
],
"Edges": [
{
"Id": "Person@ACTED_IN@Movie",
"Name": "ACTED_IN",
"FromNode": "Person",
"ToNode": "Movie",
"SourceIdProperty": {
"PropertyName": "_vertexId",
"PropertyType": "System.String"
},
"SinkIdProperty": {
"PropertyName": "_sink",
"PropertyType": "System.String"
},
"Properties": [
{
"PropertyName": "Roles",
"PropertyType": "System.String"
}
]
},
{
"Id": "Person@REVIEWED@Movie",
"Name": "REVIEWED",
"FromNode": "Person",
"ToNode": "Movie",
"SourceIdProperty": {
"PropertyName": "_vertexId",
"PropertyType": "System.String"
},
"SinkIdProperty": {
"PropertyName": "_sink",
"PropertyType": "System.String"
},
"Properties": [
{
"PropertyName": "Summary",
"PropertyType": "System.String"
},
{
"PropertyName": "Rating",
"PropertyType": "System.Int32"
}
]
},
{
"Id": "Person@DIRECTED@Movie",
"Name": "DIRECTED",
"FromNode": "Person",
"ToNode": "Movie",
"SourceIdProperty": {
"PropertyName": "_vertexId",
"PropertyType": "System.String"
},
"SinkIdProperty": {
"PropertyName": "_sink",
"PropertyType": "System.String"
},
"Properties": []
},
{
"Id": "Person@PRODUCED@Movie",
"Name": "PRODUCED",
"FromNode": "Person",
"ToNode": "Movie",
"SourceIdProperty": {
"PropertyName": "_vertexId",
"PropertyType": "System.String"
},
"SinkIdProperty": {
"PropertyName": "_sink",
"PropertyType": "System.String"
},
"Properties": []
},
{
"Id": "Person@WROTE@Movie",
"Name": "WROTE",
"FromNode": "Person",
"ToNode": "Movie",
"SourceIdProperty": {
"PropertyName": "_vertexId",
"PropertyType": "System.String"
},
"SinkIdProperty": {
"PropertyName": "_sink",
"PropertyType": "System.String"
},
"Properties": []
},
{
"Id": "Person@FOLLOWS@Person",
"Name": "FOLLOWS",
"FromNode": "Person",
"ToNode": "Person",
"SourceIdProperty": {
"PropertyName": "_vertexId",
"PropertyType": "System.String"
},
"SinkIdProperty": {
"PropertyName": "_sink",
"PropertyType": "System.String"
},
"Properties": []
}
]
}

Просмотреть файл

@ -0,0 +1,183 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace openCypherTranspiler.SQLRenderer.Test
{
public class DataTableComparisonHelper
{
/// <summary>
/// Since Neo4j result is not strictly typed, hence we have an approximate comparer to match up columns
/// </summary>
class ApproximateColumnComparer : IEqualityComparer<Tuple<string, Type>>
{
public static Dictionary<Type, Type> EqualityGroups = new Dictionary<Type, Type>()
{
{ typeof(bool), typeof(bool) },
{ typeof(int), typeof(Int64) },
{ typeof(Int16), typeof(Int64) },
{ typeof(Int64), typeof(Int64) },
{ typeof(uint), typeof(Int64) },
{ typeof(UInt16), typeof(Int64) },
{ typeof(UInt64), typeof(Int64) },
{ typeof(string), typeof(string) },
{ typeof(float), typeof(double) },
{ typeof(double), typeof(double) },
{ typeof(object), typeof(object) },
};
public bool Equals(Tuple<string, Type> x, Tuple<string, Type> y)
{
return x.Item1 == y.Item1 && EqualityGroups[x.Item2] == EqualityGroups[y.Item2];
}
public int GetHashCode(Tuple<string, Type> obj)
{
return obj.Item1.GetHashCode() ^ EqualityGroups[obj.Item2].GetHashCode();
}
}
private bool ApproximateValueComparer(object x, object y)
{
var eqTypes = ApproximateColumnComparer.EqualityGroups;
if (x == DBNull.Value || y == DBNull.Value)
{
// special case for string as our test data creation tool cannot handle
// "" vs null for string case
if (x.GetType() == typeof(string) || y.GetType() == typeof(string))
{
var isXEmptyOrNullStr = x == DBNull.Value ? true : string.IsNullOrEmpty((string)x);
var isYEmptyOrNullStr = y == DBNull.Value ? true : string.IsNullOrEmpty((string)y);
return isXEmptyOrNullStr == isYEmptyOrNullStr;
}
return x == DBNull.Value && y == DBNull.Value;
}
Assert.IsTrue(eqTypes[x.GetType()] == eqTypes[y.GetType()]);
var tarType = eqTypes[x.GetType()];
if (tarType == typeof(Int64))
{
var x_c = Convert.ToInt64(x);
var y_c = Convert.ToInt64(y);
return x_c == y_c;
}
else if (tarType == typeof(bool))
{
var x_c = Convert.ToBoolean(x);
var y_c = Convert.ToBoolean(y);
return x_c == y_c;
}
else if (tarType == typeof(double))
{
var x_c = Convert.ToDouble(x);
var y_c = Convert.ToDouble(y);
return Math.Abs(x_c - y_c) / Math.Max(Math.Abs(x_c), Math.Abs(y_c)) < 0.0001;
}
else if (tarType == typeof(string))
{
var x_c = x is string ? (string)x : x.ToString();
var y_c = y is string ? (string)y : y.ToString();
return x_c.Equals(y_c);
}
else
{
return x.Equals(y);
}
}
public void CompareDataTables(DataTable leftTable, DataTable rightTable, bool compareOrder = false)
{
// Shallow test to ensure cardinatlity is the same at least
Assert.IsTrue(leftTable.Columns.Count == rightTable.Columns.Count && leftTable.Rows.Count == rightTable.Rows.Count);
// Neo4j returns no data type at all if no result, if it happens, only compare record count
if (leftTable.Rows.Count > 0)
{
// Schema test
var leftSchema = leftTable.Columns.Cast<DataColumn>().Select(c => new Tuple<string, Type>(c.ColumnName, c.DataType)).OrderBy(n => n.Item1).ToList();
var rightSchema = rightTable.Columns.Cast<DataColumn>().Select(c => new Tuple<string, Type>(c.ColumnName, c.DataType)).OrderBy(n => n.Item1).ToList();
Assert.IsTrue(leftSchema.SequenceEqual(rightSchema, new ApproximateColumnComparer()));
// Row by row comparison
if (compareOrder)
{
throw new NotImplementedException("Ordered comparison is not implemented");
}
else
{
var leftSchemaColumns = leftSchema.Select(c => c.Item1).ToList();
var orderBy = string.Join(", ", leftSchemaColumns);
DataView leftSorted = new DataView(leftTable);
leftSorted.Sort = orderBy;
DataView rightSorted = new DataView(rightTable);
rightSorted.Sort = orderBy;
// change the order of columns
leftSorted.SetColumnsOrder(leftSchemaColumns);
rightSorted.SetColumnsOrder(leftSchemaColumns);
for (int i = 0; i < leftSorted.Count; i++)
{
var leftRow = leftSorted[i];
var rightRow = rightSorted[i];
for (int j = 0; j < leftSchema.Count; j++)
{
var leftVal = leftRow[j];
var rightVal = rightRow[j];
if (leftVal == null || rightVal == null)
{
Assert.IsTrue(leftVal == rightVal);
}
else
{
var isValueSimilar = ApproximateValueComparer(leftRow[j], rightRow[j]);
if (!isValueSimilar)
{
Debug.WriteLine($"Comparison failed for row: {i} col {j}({leftSchema[j].Item1}):");
Debug.WriteLine($" rightVal: {rightRow[j]}, leftVal: {leftRow[j]}");
}
Assert.IsTrue(isValueSimilar);
}
}
}
}
}
else
{
Assert.IsTrue(rightTable.Rows.Count == 0);
}
}
}
public static class DataViewExtensions
{
public static void SetColumnsOrder(this DataView view, IList<string> columnNames)
{
int columnIndex = 0;
foreach (var columnName in columnNames)
{
view.Table.Columns[columnName].SetOrdinal(columnIndex);
columnIndex++;
}
}
}
}

Просмотреть файл

@ -0,0 +1,256 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Threading.Tasks;
using Docker.DotNet;
using Docker.DotNet.Models;
using openCypherTranspiler.Common.Logging;
namespace openCypherTranspiler.SQLRenderer.Test
{
/// <summary>
/// Docker container helper class (mini docker-compose)
/// </summary>
public class DockerContainer
{
private DockerClient _client;
private ILoggable _logger;
private IDictionary<string, string> _environmentVariables = new Dictionary<string, string>();
private IDictionary<int, int> _tcpPortMapping = new Dictionary<int, int>(); // <containerport, hostport>
class Progress : IProgress<JSONMessage>
{
private Action<JSONMessage> _onCalled;
private ILoggable _logger;
public Progress(Action<JSONMessage> action = null, ILoggable logger = null)
{
_onCalled = action;
_logger = logger;
}
void IProgress<JSONMessage>.Report(JSONMessage value)
{
_logger?.LogVerbose($"{value.Status}: {value.ProgressMessage}");
_onCalled?.Invoke(value);
}
}
protected DockerContainer(DockerClient client, ILoggable logger)
{
_client = client;
_logger = logger;
}
public static DockerContainer On(DockerClient client, ILoggable logger = null)
{
return new DockerContainer(client, logger);
}
public string Image { get; private set; }
public string Tag { get; private set; } = "latest";
public DockerContainer UseImage(string image, string tag = "latest")
{
Image = image;
Tag = tag;
return this;
}
public string Name { get; private set; }
public DockerContainer SetName(string name)
{
Name = name;
return this;
}
public IReadOnlyCollection<(string, string)> Env { get { return _environmentVariables.Select(kv => (kv.Key, kv.Value)).ToList().AsReadOnly(); } }
public DockerContainer AddEnv(string key, string value)
{
_environmentVariables.Add(key, value);
return this;
}
public IReadOnlyCollection<(string, string)> Port { get { return _tcpPortMapping.Select(kv => ($"{kv.Key}/tcp", $"{kv.Value}")).ToList().AsReadOnly(); } }
public DockerContainer AddTcpPort(int containerPort, int hostPort)
{
_tcpPortMapping.Add(containerPort, hostPort);
return this;
}
public async Task Up(bool rebuildIfExists = false, bool waitForAllTcpPorts = false)
{
// parameter checks
if (string.IsNullOrEmpty(Image))
{
throw new ArgumentException("Must provide Image");
}
if (string.IsNullOrEmpty(Name))
{
throw new ArgumentException("Must provide container name");
}
var imageNameWithTag = $"{Image}{(string.IsNullOrEmpty(Tag) ? "" : $":{Tag}")}";
// pull the specified image if not already
_logger?.LogVerbose($"Pulling {imageNameWithTag} ...");
await _client.Images.CreateImageAsync(
new ImagesCreateParameters
{
FromImage = Image,
Tag = Tag,
},
null,
new Progress(null, _logger)
);
_logger?.LogVerbose($"Successfuly pulled {imageNameWithTag}.");
// check if a matching container already exists
var containers = await _client.Containers.ListContainersAsync(
new ContainersListParameters()
{
All = true
});
var matchingContainer = containers.FirstOrDefault(c => c.Names.Contains($"/{Name}"));
var mismatchInfo = new List<string>();
if (matchingContainer != null)
{
// check exsitng matching container spec satisfy the requirements, if
// not, either fail, or delete it, depending on user's preference
if (matchingContainer.Image != $"{imageNameWithTag}")
{
mismatchInfo.Add($"Container {Name} does not have matching image: {matchingContainer.Image}, where {Image} is expected");
}
if (_tcpPortMapping.Count > 0 &&
!_tcpPortMapping.All(kv => matchingContainer.Ports
.Any(p => p.Type == "tcp" && p.PublicPort == kv.Value && p.PrivatePort == kv.Key)))
{
mismatchInfo.Add($"Container {Name} does not satisfy all port mappings: " +
$"{string.Join(",", matchingContainer.Ports.Select(p => $"{p.PublicPort}/{p.Type}:{p.PrivatePort}"))}, " +
$"where {string.Join(",", _tcpPortMapping.Select(p => $"{p.Value}/tcp:{p.Key}"))} is expected");
}
if (mismatchInfo.Count > 0)
{
if (rebuildIfExists)
{
if (matchingContainer.Status == "running")
{
await _client.Containers.StopContainerAsync(matchingContainer.ID, new ContainerStopParameters());
}
await _client.Containers.RemoveContainerAsync(matchingContainer.ID, new ContainerRemoveParameters());
matchingContainer = null;
}
else
{
throw new ArgumentException($"Conflicting container with same name '{Name}' already exists.");
}
}
}
// create a new instance of the container if it does not exists or was destroyed
if (matchingContainer == null)
{
_logger?.LogVerbose($"Creating container {Name}...");
await _client.Containers.CreateContainerAsync(
new CreateContainerParameters()
{
Image = imageNameWithTag,
Name = Name,
Env = _environmentVariables.Select(ev => $"{ev.Key}={ev.Value}").ToList(),
HostConfig = new HostConfig()
{
PortBindings = _tcpPortMapping.ToDictionary(
kv => $"{kv.Key}/tcp",
kv => new List<PortBinding>()
{
new PortBinding()
{
HostPort = kv.Value.ToString()
}
} as IList<PortBinding>)
}
}
);
// get the list of recently created containers and find the one we just created
containers = await _client.Containers.ListContainersAsync(new ContainersListParameters()
{
All = true,
Filters = new Dictionary<string, IDictionary<string, bool>>()
{
{
"status", new Dictionary<string, bool>()
{
{ "created", true }
}
}
}
});
matchingContainer = containers.FirstOrDefault(c => c.Names.Contains($"/{Name}"));
if (matchingContainer != null)
{
_logger?.LogVerbose($"Container {Name} created.");
}
else
{
throw new InvalidOperationException($"Failed to start container {Name}");
}
}
// start the created container
if (matchingContainer.State != "running")
{
_logger?.LogVerbose($"Starting container {Name}...");
await _client.Containers.StartContainerAsync(Name, new ContainerStartParameters());
_logger?.LogVerbose($"Container {Name} started.");
}
// if requested, wait for container services is fully up
if (waitForAllTcpPorts)
{
_logger?.LogVerbose($"Checking for service ports ...");
foreach (var port in _tcpPortMapping.Values)
{
TestPortConnection(port, TimeSpan.FromSeconds(300));
}
_logger?.LogVerbose($"All service ports have responded.");
}
}
private void TestPortConnection(int port, TimeSpan timeout)
{
DateTime startTime = DateTime.Now;
using (TcpClient tcpClient = new TcpClient())
{
bool connected = false;
while (!connected)
{
try
{
tcpClient.Connect("127.0.0.1", port);
connected = true;
}
catch (Exception)
{
if (DateTime.Now - startTime < timeout)
{
Task.Delay(2000).Wait(1000);
}
else
{
throw new ApplicationException($"Timeout after trying to wait for port {port}");
}
}
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,66 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using openCypherTranspiler.Common.GraphSchema;
using openCypherTranspiler.CommonTest;
using Newtonsoft.Json;
namespace openCypherTranspiler.SQLRenderer.Test
{
class JSONGraphSQLSchema : ISQLDBSchemaProvider
{
private JSONGraphSchema _schemaHelper;
private IDictionary<string, SQLTableDescriptor> _tableDescs;
public JSONGraphSQLSchema(string jsonDefFile)
{
_schemaHelper = new JSONGraphSchema(jsonDefFile);
LoadFromFile(jsonDefFile);
}
private (string Verb, string NodeFrom, string NodeTo) ParseEntityId(string entityId)
{
var splits = entityId.Split('@');
return (Verb: splits[1], NodeFrom: splits[0], NodeTo: splits[2]);
}
private void LoadFromFile(string jsonDefFile)
{
var res = JsonConvert.DeserializeObject<dynamic>(File.ReadAllText(jsonDefFile));
var allnodes = ((IEnumerable<dynamic>)res.Nodes).Select(n => (string)n.Id.ToString());
var tableDescs = ((IEnumerable<dynamic>)res.TableDescriptors).Select(d =>
new SQLTableDescriptor()
{
EntityId = d.EntityId.ToString(),
TableOrViewName = d.TableOrViewName.ToString()
});
_tableDescs = tableDescs.ToDictionary(kv => kv.EntityId, kv => kv);
}
public EdgeSchema GetEdgeDefinition(string edgeVerb, string fromNodeName, string toNodeName)
{
return _schemaHelper.GetEdgeDefinition(edgeVerb, fromNodeName, toNodeName);
}
public NodeSchema GetNodeDefinition(string nodeName)
{
return _schemaHelper.GetNodeDefinition(nodeName);
}
public SQLTableDescriptor GetSQLTableDescriptors(string entityId)
{
return _tableDescs[entityId];
}
}
}

Просмотреть файл

@ -0,0 +1,47 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
<RootNamespace>Microsoft.GraphPlatform.Transpiler.SQLRenderer.Test</RootNamespace>
</PropertyGroup>
<ItemGroup>
<None Remove="appsettings.json" />
<None Remove="appsettings.private.json" />
</ItemGroup>
<ItemGroup>
<Content Include="appsettings*.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Docker.DotNet" Version="3.125.2" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.3.2" />
<PackageReference Include="MSTest.TestFramework" Version="1.3.2" />
<PackageReference Include="Neo4j.Driver.Signed" Version="1.7.2" />
<PackageReference Include="System.Data.SqlClient" Version="4.6.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\SQLRenderer\SQLRenderer.csproj" />
<ProjectReference Include="..\CommonTest\CommonTest.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="TestData\" />
</ItemGroup>
<ItemGroup>
<None Update="TestData\**" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,801 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
using System.IO;
using System.Linq;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Neo4j.Driver.V1;
using Docker.DotNet;
using Docker.DotNet.Models;
using openCypherTranspiler.Common.Exceptions;
using openCypherTranspiler.Common.Logging;
using openCypherTranspiler.CommonTest;
using openCypherTranspiler.openCypherParser;
using openCypherTranspiler.LogicalPlanner;
using Microsoft.Extensions.Configuration;
namespace openCypherTranspiler.SQLRenderer.Test
{
/// <summary>
/// Tests for SQLRenderer
///
/// References:
/// - Docker.DotNet how to use PortBindings of HostConfig:
/// https://github.com/Microsoft/Docker-PowerShell/issues/174
/// - Docker REST API doc:
/// https://docs.docker.com/engine/api/v1.39/
/// - appsettings:
/// https://blog.bitscry.com/2017/05/30/appsettings-json-in-net-core-console-app/
/// https://www.humankode.com/asp-net-core/asp-net-core-configuration-best-practices-for-keeping-secrets-out-of-source-control
/// </summary>
[TestClass]
public class SQLRendererTest
{
private ISQLDBSchemaProvider _graphDef;
private readonly ILoggable _logger = new TestLogger(LoggingLevel.Normal);
private IDriver _driver;
private Func<SqlConnection> _conn;
private Func<SqlConnection> _conn_init;
#region Test initialization and clean up
//
// Use ClassInitialize to run code before running the first test in the class
[ClassInitialize()]
public static void MyClassInitialize(TestContext testContext) { }
//
// Use ClassCleanup to run code after all tests in a class have run
// [ClassCleanup()]
public static void MyClassCleanup() { }
//
// Use TestInitialize to run code before running each test
[TestInitialize()]
public void TestInitialize()
{
// load graph definition and connect to the servers
_graphDef = new JSONGraphSQLSchema(@"./TestData/MovieGraph.json");
// setup neo4j and sql drivers
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("./appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile("./appsettings.private.json", optional: true, reloadOnChange: true);
IConfigurationRoot configuration = builder.Build();
var useDocker = bool.Parse(configuration
.GetSection("appSettings")
.GetSection("createLocalDockerImages").Value);
var neo4jHost = configuration
.GetSection("appSettings")
.GetSection("neo4jHost").Value;
var neo4jPort = int.Parse(configuration
.GetSection("appSettings")
.GetSection("neo4jPort").Value);
var neo4jUser = configuration
.GetSection("appSettings")
.GetSection("neo4jUser").Value;
var neo4jPassword = configuration
.GetSection("appSettings")
.GetSection("neo4jPassword").Value;
var sqlHost = configuration
.GetSection("appSettings")
.GetSection("sqlHost").Value;
var sqlPort = int.Parse(configuration
.GetSection("appSettings")
.GetSection("sqlPort").Value);
var sqlPassword = configuration
.GetSection("appSettings")
.GetSection("sqlPassword").Value;
var neo4jBoltUrl = $"bolt://{neo4jHost}:{neo4jPort}";
var sqlConnStrInit = $"Data Source={sqlHost},{sqlPort};User id=SA;Password={sqlPassword};";
var sqlConnStr = $"Data Source={sqlHost},{sqlPort};Initial Catalog=octestdb;User id=SA;Password={sqlPassword};";
_driver = GraphDatabase.Driver(neo4jBoltUrl, AuthTokens.Basic(neo4jUser, neo4jPassword));
_conn = () => new SqlConnection(sqlConnStr);
_conn_init = () => new SqlConnection(sqlConnStrInit);
// initialize test harness
if (!File.Exists("./TestInitDone.tmp"))
{
if (useDocker)
{
// create and start test harness containers containers
CreateTestHarnessContainers(
neo4jUser,
neo4jPassword,
neo4jPort,
sqlHost,
sqlPort,
sqlPassword
).ConfigureAwait(false).GetAwaiter().GetResult();
}
// initialize neo4j db
InitializeNeo4jDB();
// initialize sql db
InitializeSQLDB();
Console.WriteLine("Test Initialization completed.");
File.WriteAllText("./TestInitDone.tmp", DateTime.UtcNow.ToString());
}
else
{
// Depending the cached the initialization state to speed up unit test
Console.WriteLine("Test Initialization skipped. To redo test initialization, remove './TestInitDone.tmp'.");
}
}
#endregion Test initialization and clean up
private async Task PullDockerImage(DockerClient client, string imageName, string tagName = "")
{
await client.Images.CreateImageAsync(
new ImagesCreateParameters
{
FromImage = imageName,
Tag = tagName,
},
null,
null);
}
private async Task CreateTestHarnessContainers(
string neo4jUser,
string neo4jPassword,
int neo4jBoltPort,
string sqlHost,
int sqlPort,
string sqlPassword
)
{
var dockerClient = new DockerClientConfiguration(
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
new Uri("npipe://./pipe/docker_engine") :
new Uri("unix:///var/run/docker.sock")
).CreateClient();
// start Neo4j test instance
// Bolt: 10087
// HTTP: 10074
await DockerContainer.On(dockerClient, _logger)
.UseImage("neo4j")
.SetName("neo4j_unittest_1")
//.AddTcpPort(7474, 10074)
.AddTcpPort(7687, neo4jBoltPort)
.AddEnv("NEO4J_AUTH", $"{neo4jUser}/{neo4jPassword}")
.Up(rebuildIfExists: true, waitForAllTcpPorts: true);
// start Microsoft SQL test instance
await DockerContainer.On(dockerClient, _logger)
.UseImage("mcr.microsoft.com/mssql/server", "2017-latest")
.SetName("mssql_unittest_1")
.AddTcpPort(1433, sqlPort)
.AddEnv("ACCEPT_EULA", "y")
.AddEnv("SA_PASSWORD", sqlPassword)
.Up(rebuildIfExists: true, waitForAllTcpPorts: true);
}
private void InitializeNeo4jDB()
{
using (var session = _driver.Session())
{
session.Run("MATCH (n) DETACH DELETE n");
var movieDbCreationScript = File.ReadAllText(@"./TestData/MovieGraphNeo4jQuery.txt");
session.Run(movieDbCreationScript);
}
}
private void InitializeSQLDB()
{
var movieDbCreationScript = File.ReadAllLines(@"./TestData/MovieDBSQLCmds.sql");
var goLines = movieDbCreationScript.Select(
(l, i) => string.Compare(l.Trim(), "go", true) == 0 || string.Compare(l.Trim(), "go;", true) == 0 ?
i : -1
).Where(idx => idx >= 0).Append(movieDbCreationScript.Length);
using (var con = _conn_init())
{
con.Open();
var startIdx = 0;
foreach (var endIdx in goLines)
{
var cmdText = string.Join("\r\n", movieDbCreationScript.Skip(startIdx).Take(endIdx - startIdx));
if (!string.IsNullOrWhiteSpace(cmdText.Trim()))
{
using (var command = new SqlCommand(cmdText, con))
{
command.ExecuteNonQuery();
}
}
startIdx = endIdx + 1;
}
con.Close();
}
}
private DataTable RunQueryInCypherAndGetResult(string cypherQueryText)
{
var dataTable = new DataTable();
var typeOrder = new Type[] { typeof(bool), typeof(byte), typeof(char), typeof(int), typeof(DateTime), typeof(long), typeof(double), typeof(string), typeof(object) };
var typeOrderDict = typeOrder.Select((t, i) => (t:t, i:i)).ToDictionary(kv => kv.t, kv => kv.i);
using (var session = _driver.Session())
{
var result = session.Run(cypherQueryText).ToList();
var resultFirstRec = result.FirstOrDefault();
// get type for each column
if (resultFirstRec != null)
{
// try to find most generous type that can accommodate the data
var colTypes = new Type[resultFirstRec.Keys.Count];
foreach (var record in result)
{
foreach (var v in record.Values.Select((v, i) => (v:v, i:i)))
{
colTypes[v.i] = v.v.Value != null ?
typeOrder[Math.Max(typeOrderDict[v.v.Value.GetType()], typeOrderDict[colTypes[v.i] ?? typeOrder.First()])] :
colTypes[v.i];
};
}
foreach (var col in resultFirstRec.Keys.Select((v, i) => (v:v, i:i)))
{
dataTable.Columns.Add(col.v, colTypes[col.i] ?? typeof(object));
}
foreach (var record in result)
{
var dataRow = dataTable.NewRow();
foreach (var v in record.Values)
{
dataRow[v.Key] = v.Value ?? DBNull.Value;
};
dataTable.Rows.Add(dataRow);
}
}
}
return dataTable;
}
private DataTable RunQueryInSQLAndGetResult(string sqlQueryText)
{
var dataTable = new DataTable();
using (var con = _conn())
{
con.Open();
Stopwatch sw = new Stopwatch();
sw.Start();
using (var command = new SqlCommand(sqlQueryText, con))
{
var dataReader = command.ExecuteReader();
dataTable.Load(dataReader);
}
sw.Stop();
_logger?.Log("SQL Query elapsed={0}", sw.Elapsed);
if (sw.Elapsed.TotalSeconds > 5)
{
_logger?.LogCritical("Following generated query took a long time to run:");
_logger?.LogCritical(sqlQueryText);
}
con.Close();
}
return dataTable;
}
private string TranspileToSQL(string cypherQueryText)
{
var plan = LogicalPlan.ProcessQueryTree(
OpenCypherParser.Parse(cypherQueryText, _logger),
_graphDef,
_logger);
var sqlRender = new SQLRenderer(_graphDef, _logger);
return sqlRender.RenderPlan(plan);
}
private DataTable RunQueryTranspiledToSQLAndGetResult(string cypherQueryText)
{
var sqlQueryText = TranspileToSQL(cypherQueryText);
return RunQueryInSQLAndGetResult(sqlQueryText);
}
private void RunQueryAndCompare(string cypherQueryText, bool compareOrder = false)
{
_logger?.Log($"----------------------------------------");
_logger?.Log($"Running cypher query:\n{cypherQueryText}");
var resultNeo4j = RunQueryInCypherAndGetResult(cypherQueryText);
var resultSQL = RunQueryTranspiledToSQLAndGetResult(cypherQueryText);
var comparisonHelper = new DataTableComparisonHelper();
comparisonHelper.CompareDataTables(resultNeo4j, resultSQL, compareOrder);
_logger?.Log($"----------------------------------------");
}
[TestMethod]
public void SanityQueryTest()
{
// really basic sanity test
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WHERE p.Name = 'Tom Hanks'
RETURN p.Name as Name, m.Title as Title
";
RunQueryAndCompare(queryText);
}
[TestMethod]
public void AdvancedPatternMatchTest()
{
// Check if implicit inequality was added if same type of relationships are referred
// in a single match statement
{
var queryText = @"
MATCH (p:Person)-[:ACTED_IN]->(m:Movie), (p2:Person)-[:ACTED_IN]->(m:Movie)
WHERE p.Name = 'Tom Hanks'
RETURN p.Name as Name, m.Title as Title, p2.Name as CoStarName
";
RunQueryAndCompare(queryText);
}
}
[TestMethod]
public void CaseWhenExpressionTest()
{
// basic test
{
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WITH p.Name as PersonName, m.Title as MovieTitle, CASE WHEN p.Name = 'Tom Hanks' THEN 1 WHEN p.Name starts with 'Tom' THEN 2 WHEN p.Name starts with 'T' THEN 3 ELSE 0 END as NameFlag
WHERE PersonName starts with 'T'
RETURN PersonName, MovieTitle,NameFlag,
CASE WHEN PersonName = 'Tom Hanks' THEN 1 WHEN PersonName starts with 'Tom' THEN 2 WHEN PersonName starts with 'T' THEN 3 ELSE 0 END as NameFlag2
ORDER BY PersonName, MovieTitle
LIMIT 100
";
RunQueryAndCompare(queryText);
}
// swiching entities aliases
{
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WITH p as m, m as p
MATCH (m)-[a:DIRECTED]->(p)
RETURN m.Name as Name, p.Title as Title, Case when m.Name = 'Tom Hanks' then 'This is Tom Hanks' else 'This is not Tom Hanks' end as Flag
";
RunQueryAndCompare(queryText);
}
// type casting help for case when
{
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WITH p as m, m as p
MATCH (m)-[a:DIRECTED]->(p)
RETURN m.Name as Name, p.Title as Title,
Case when m.Name = 'Tom Hanks' then 1.1 else 'This is not Tom Hanks' end as Flags
";
RunQueryAndCompare(queryText);
}
}
[TestMethod]
public void OptionalMatchTest()
{
// optional match basic test
{
var queryText = @"
MATCH (p:Person)-[r:REVIEWED]->(m:Movie)
OPTIONAL MATCH (p)<-[:FOLLOWS]-(p2:Person)-[r2:REVIEWED]->(m)
return p.Name as Name1, p2.Name as Name2, m.Title as Title, r.Rating as Rating1, r2.Rating as Rating2
";
RunQueryAndCompare(queryText);
}
{
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
OPTIONAL MATCH (p)-[d:DIRECTED]->(m)
WITH p, a, m, d
WHERE p.Name = 'Tom Hanks'
RETURN p.Name as Name, m.Title as Title, count(d) > 0 as IsDirector
";
RunQueryAndCompare(queryText);
}
// optional match attached to optional match
// TODO:
// This query took long time to run on MS T-SQL w/ long RESOURCE_SEMAPHORE. Investigate.
{
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
OPTIONAL MATCH (p)-[d:DIRECTED]->(m) WHERE p.Name = 'Tom Hanks'
RETURN p.Name as Name, m.Title as Title, count(d) > 0 as IsDirector
";
RunQueryAndCompare(queryText);
}
// multiple optional matches
{
var queryText = @"
match (p:Person) where p.Name = 'Tom Hanks' or p.Name = 'Meg Ryan'
optional match (p:Person)-[:ACTED_IN]-(m:Movie) where p.Name = 'Meg Ryan'
optional match (p:Person)-[:ACTED_IN]->(m) where p.Name = 'Tom Hanks'
return p.Name as Name, m.Title as Title
";
RunQueryAndCompare(queryText);
}
// multiple optional matches (Var 2)
{
var queryText = @"
match (p:Person) where p.Name = 'Tom Hanks' or p.Name = 'Meg Ryan'
optional match (p:Person)-[:ACTED_IN]-(m1:Movie) where p.Name = 'Meg Ryan'
optional match (p:Person)-[:ACTED_IN]->(m2:Movie) where p.Name = 'Tom Hanks'
return p.Name as Name, m1.Title as Title1, m2.Title as Title2
";
RunQueryAndCompare(queryText);
}
}
[TestMethod]
public void DistinctSanityTest()
{
// distinct test
{
// distinct fields
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
RETURN DISTINCT p.Name as Name
";
RunQueryAndCompare(queryText);
}
{
// distinct entity
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WITH DISTINCT p
RETURN p.Name as Name
";
RunQueryAndCompare(queryText);
}
}
[TestMethod]
public void DistinctAdvancedTest()
{
{
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
RETURN p.Name as Name, Count(Distinct m.Title) as TitleCount
ORDER BY Name
LIMIT 20
";
RunQueryAndCompare(queryText);
}
{
// distinct properties under "WITH"
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WITH DISTINCT m.Title as Title, p.Name as Name
ORDER BY Title ASC, Name DESC
LIMIT 20
WHERE Title <> 'A'
RETURN Title, Name
";
RunQueryAndCompare(queryText);
}
{
// distinct properties under "RETURN"
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WITH m.Title as Title, p.Name as Name
WHERE Title <> 'A'
RETURN DISTINCT Title, Name
ORDER BY Title, Name DESC
LIMIT 20
";
RunQueryAndCompare(queryText);
}
{
// negative test
// match where/order by clause field not listed in the data source
var expectedExceptionThrown = false;
try
{
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WITH DISTINCT m.Title as Title, p.Name as Name
WHERE a.Title <> 'A'
RETURN Title, Name
";
TranspileToSQL(queryText);
}
catch (TranspilerSyntaxErrorException e)
{
Assert.IsTrue(e.Message.Contains("entity field: \"a\" not exsit"));
expectedExceptionThrown = true;
}
Assert.IsTrue(expectedExceptionThrown);
}
{
// negative test
// match where/order by clause field not listed in the data source
var expectedExceptionThrown = false;
try
{
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WITH DISTINCT m.Title as Title, p.Name as Name
WHERE Titl <> 'A'
RETURN Title, Name
";
TranspileToSQL(queryText);
}
catch (TranspilerSyntaxErrorException e)
{
Assert.IsTrue(e.Message.Contains("Titl not existed"));
expectedExceptionThrown = true;
}
Assert.IsTrue(expectedExceptionThrown);
}
}
[TestMethod]
public void OperatorTest()
{
// Test various operators
// +, -, *, /, ^, IN
{
var queryText = @"
MATCH (p:Person)-[:ACTED_IN]-(m:Movie)
WHERE p.Name in ['Tom Hanks', 'Meg Ryan'] and m.Released >= 1990
RETURN p.Name as Name, m.Title AS Title, m.Released % 100 as ReleasedYear2Digit, m.Released - 2000 as YearSinceY2k, m.Released * 1 / 1 ^ 1 AS TestReleasedYear
";
RunQueryAndCompare(queryText);
}
}
[TestMethod]
public void StringFunctionTest()
{
// Basic string function test
// left
// right
// ltrim
// rtrim
// trim
// toLower
// toUpper
// contains
// size
{
var queryText = @"
MATCH (p:Person)
WHERE p.Name contains 'Tom' OR left(p.Name, 3) = 'Meg' OR right(p.Name, 3) = 'nks'
RETURN p.Name as Name, toLower(p.Name) as LName, toUpper(p.Name) as UName, size(p.Name) as NameSize,
trim(' ' + p.Name + ' ') AS TrimmedName,
ltrim(' ' + p.Name + ' ') AS LTrimmedName,
rtrim(' ' + p.Name + ' ') AS RTrimmedName
";
RunQueryAndCompare(queryText);
}
}
[TestMethod]
public void AggregationFunctionTest()
{
// Currently supported
// avg
// sum
// max
// min
// count
// test basic aggregates
{
var queryText = @"
MATCH (p:Person)-[r:REVIEWED]->(m:Movie)
return m.Title as Title, AVG(r.Rating) as AvgRating, MAX(r.Rating) as HighestRating, MIN(r.Rating) as LowestRating, COUNT(r.Rating) as NumberOfReviews, SUM(r.Rating) as TotalRating, COUNT(r.Rating) / SUM(r.Rating) as AvgRating2
";
RunQueryAndCompare(queryText);
}
// test count(distinct())
{
var queryText = @"
MATCH (p:Person)-[r:REVIEWED]->(m:Movie)
return COUNT(r.Rating) as NumberOfRatings, COUNT(DISTINCT(r.Rating)) as NumberOfUniqueRatings, COUNT(DISTINCT(m)) as NumberOfUniqueMovies
";
RunQueryAndCompare(queryText);
}
// test stdev/stdevp aggregates
// NOTE: neo4j returns 0 for STDEV for when popsize = 1, where SQL (correctly) return Null
// so for now, we skip comparing STDEV for this special case
{
var queryText = @"
MATCH (p:Person)-[r:REVIEWED]->(m:Movie)
WITH m.Title as Title, STDEV(r.Rating) as RatingStdDev, STDEVP(r.Rating) as RatingStdDevP, COUNT(DISTINCT(p)) AS PopSize
WHERE PopSize > 1
RETURN Title, RatingStdDev, RatingStdDevP, PopSize
";
RunQueryAndCompare(queryText);
}
// negative test case: nested aggregations
{
var queryText = @"
MATCH (p:Person)-[r:REVIEWED]->(m:Movie)
return COUNT(MAX(r.Rating)) as CountOfMaxRatings
";
try
{
TranspileToSQL(queryText);
Assert.Fail("Negative test case passed unexpectedly.");
}
catch (TranspilerNotSupportedException)
{ }
}
// TODO: following is not supported/tested yet
// - percentileCount
// - percentileDisc
}
[TestMethod]
public void EdgeDirectionTest()
{
// forward
{
var queryText = @"
MATCH (p:Person)-[:FOLLOWS]->(p2:Person)
return p.Name as Name1, p2.Name as Name2
";
RunQueryAndCompare(queryText);
}
// backward
{
var queryText = @"
MATCH (p:Person)<-[:FOLLOWS]-(p2:Person)
return p.Name as Name1, p2.Name as Name2
";
RunQueryAndCompare(queryText);
}
// either direction (automatically inferred)
{
var queryText = @"
MATCH (p:Person)-[:DIRECTED]-(m:Movie)
return p.Name as Name, m.Title as Title
";
RunQueryAndCompare(queryText);
}
// negative test case (wrong direction)
{
var queryText = @"
MATCH (p:Person)<-[:DIRECTED]-(m:Movie)
return p.Name as Name, m.Title as Title
";
try
{
TranspileToSQL(queryText);
Assert.Fail("Negative test case passed unexpectedly.");
}
catch (TranspilerBindingException)
{ }
}
// negative test case of both direction with same type of src/sink
{
// right now we block the case of ambiguity edges (while neo4j support it right now
// by union the match from either direction)
var queryText = @"
MATCH (p:Person)-[:FOLLOWS]-(p2:Person)
return p.Name as Name1, p2.Name as Name2
";
try
{
TranspileToSQL(queryText);
Assert.Fail("Negative test case passed unexpectedly.");
}
catch (TranspilerNotSupportedException)
{ }
}
}
[TestMethod]
public void OrderByLimitClauseTest()
{
// basic case 1
{
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WITH p.Name as Name, m.Title as Title
ORDER BY Name
LIMIT 11
RETURN Name
";
RunQueryAndCompare(queryText);
}
// basic case 2
{
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
RETURN p.Name as Name, m.Title as Title
ORDER BY Name
LIMIT 11
";
RunQueryAndCompare(queryText);
}
// order by nested under with statement
{
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WHERE p.Name = 'Tom Hanks'
WITH p.Name+""B"" AS Name2, m.Title AS Title
ORDER BY m.Tagline, Name2, m.Title ASC
LIMIT 10
Where p.Name starts with 'T' and Name2 starts with 'T'
RETURN Name2, Title
";
RunQueryAndCompare(queryText);
}
// order by nested undet return statement
{
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WHERE p.Name = 'Tom Hanks'
WITH p.Name AS Name2, m.Title AS Title
RETURN Name2, Title
ORDER BY Name2
LIMIT 20
";
RunQueryAndCompare(queryText);
}
// order by nested undet return statement
{
var queryText = @"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WHERE p.Name = 'Tom Hanks'
RETURN p.Name as Name2 ,m.Title as Title
ORDER BY Name2
LIMIT 20
";
RunQueryAndCompare(queryText);
}
}
}
}

Просмотреть файл

@ -0,0 +1,32 @@
@echo off
del MovieDBSQLCmds.sql
echo IF db_id('octestdb') is null CREATE DATABASE octestdb; > MovieDBSQLCmds.sql
echo GO >> MovieDBSQLCmds.sql
echo >> MovieDBSQLCmds.sql
echo USE octestdb; >> MovieDBSQLCmds.sql
echo GO >> MovieDBSQLCmds.sql
echo >> MovieDBSQLCmds.sql
CALL :CONVERT_SQL person.csv Person MovieDBSQLCmds.sql
CALL :CONVERT_SQL movie.csv Movie MovieDBSQLCmds.sql
CALL :CONVERT_SQL acted_in.csv ActedIn MovieDBSQLCmds.sql
CALL :CONVERT_SQL produced.csv Produced MovieDBSQLCmds.sql
CALL :CONVERT_SQL directed.csv Directed MovieDBSQLCmds.sql
CALL :CONVERT_SQL wrote.csv Wrote MovieDBSQLCmds.sql
CALL :CONVERT_SQL reviewed.csv Reviewed MovieDBSQLCmds.sql
CALL :CONVERT_SQL follows.csv Follows MovieDBSQLCmds.sql
GOTO :EOF
REM %1 is CSV file
REM %2 is the table name
REM %3 is the resulting SQL file
:CONVERT_SQL
echo python ConvertToSQLCmds.py %1 true %2 %3
python ConvertToSQLCmds.py %1 true %2 %3
GOTO :EOF
:EOF

Просмотреть файл

@ -0,0 +1,319 @@
import unicodedata, re
import sys
import operator
import csv
from datetime import datetime
from io import StringIO
# read file, determine if it is csv or tsv, then extract the data and automatically determine the best
# type for each field. Eventually output a .ss file that can be run with Cosmos run time to
# actually convert the csv/tsv file into .ss file
# parameters:
# [1]: file to read
# [2]: first row is header
# [3]: script file to generate
# Contants
# supported delimiters and how to represent it in Scope code
delims = {
# (Delimiter, C# representation)
',': ',',
'\t': '\\t'
}
# supported type and represent it in Scope code
type_tests = {
# type name : (Test, DowngradeTo, StringTypeName, StringTypeNameIfNullable)
int: ([int], float, "int", "int"),
float: ([float], datetime, "float", "float"),
datetime: (
[
lambda value: datetime.strptime(value, "%m/%d/%Y"),
lambda value: datetime.strptime(value, "%Y-%m-%d"),
lambda value: datetime.strptime(value, "%m/%d/%Y %H:%M:%S"),
lambda value: datetime.strptime(value, "%Y-%m-%d %I:%M:%S.%f %p")
], str, "datetime", "datetime"),
str: ([str], str, "varchar(MAX)", "varchar(100)")
}
# default type that is most restrictive to start with
type_most_restrictive = int
# read first 10 rows and use majority vote to determine the deliminator
def get_delim(content_file):
supported_delims = [k for k, v in delims.items()]
num_lines_hasSep = {k:0 for k, v in delims.items()}
total_hasSep = {k:0 for k, v in delims.items()}
is_header_row = True
total_rows_read = 0
num_rows_to_test = 10
# collect sample rows
#with open(readFileName, 'r', encoding='utf8') as content_file:
line = content_file.readline()
while (line != ''):
#for line in content_file:
if (is_header_row) :
is_header_row = False
for c in supported_delims:
cnt = line.count(c)
num_lines_hasSep[c] += (1 if cnt > 0 else 0)
total_hasSep[c] += cnt
total_rows_read+=1
#print(line)
if (total_rows_read >= num_rows_to_test) :
break
else:
line = content_file.readline()
# determine delimiters
# first, each row should have the delim, if one doesn't filter it out
survive_delim = {key:value for key, value in num_lines_hasSep.items() if value >= total_rows_read}
#print(survive_delim)
if (len(survive_delim) <= 0):
# no deliminator? should be one row case. we use default as delimiter
return supported_delims[0]
else:
return sorted(survive_delim.items(), key=operator.itemgetter(1), reverse=True)[0][0]
def regulate_token(str):
# for now regulating column name means remove all splitter strings, and replace , with _
return str.replace(" ", "").replace(",", "_")
def get_mostprefered_type(curtype, value):
typ = curtype
while (typ != str):
typobj = type_tests[typ]
for typtest in typobj[0]:
try:
typtest(value)
return typ
except ValueError:
# try next
pass
typ = typobj[1]
return str
def get_type_rep(type, isnullable, iskey):
if (iskey):
return f"""{type_tests[type][3]}{" NULL" if isnullable else ""}"""
else:
return f"""{type_tests[type][2]}{" NULL" if isnullable else ""}"""
# read a string file and extract columns and label it with types
# return (cols, rows)
def extract_from_csv(content_file, delim, has_header):
# read the csv file row by row
reader = csv.reader(content_file, delimiter=delim)
num_cols = 0
rowid = 0
colmap = {}
rows = []
for row in reader:
rowid+=1
if (num_cols == 0):
num_cols = len(row)
# seen first row, create column definitions
if (has_header):
for id, col in enumerate(row):
colmap[id] = {'colname':col, 'type':type_most_restrictive, 'nullable':False, 'confirmed':False} # col name, type, nullable?, confirmed?
# header read. move to next line
continue
else:
for id, col in enumerate(row):
regname = regulate_token(col)
colmap[id] = {'colname':("Column%d" % (id+1)), 'type':type_most_restrictive, 'nullable':False, 'confirmed':False}
elif len(row) == 0:
# skip empty rows
continue
elif num_cols != len(row):
#col inconsistent
raise ValueError('Line %d has inconsistent number of cols %d, expect %d. Line content:\n%s' % (rowid, len(row), num_cols, row))
elif (row is not None):
# see normal row. Fall through to do the common processing
pass
else:
raise Exception("Unhandled situation")
# the common processing: update column type for each column
for id, col in enumerate(row):
curT = colmap[id]['type']
is_confirmed = colmap[id]['confirmed']
if ( (not is_confirmed) or
(curT is not str) ):
# string cannot be downgraded anymore, other types can
# unless, we haven't seen the first confirmable data yet
if (col == ''):
# col is nullable
colmap[id]['nullable'] = True
else:
# check the type
colmap[id]['type'] = get_mostprefered_type(curT, col)
colmap[id]['confirmed'] = True
rows.append(row)
return colmap, rows
# helper function to parse boolean
def parse_bool(s):
return (s in ['true', '1', 't', 'y', 'yes'])
def create_table_insert(table_name, colmap, pkcols):
script = f"DROP TABLE IF EXISTS dbo.{table_name};\nGO;\n"
script += f"CREATE TABLE dbo.{table_name}\n"
script += "(\n"
# construct the type string
cols = sorted(colmap.items(), key=operator.itemgetter(0))
first = True
for col in cols:
script += f""" {"" if first else ", "}{col[1]['colname']} {get_type_rep(col[1]['type'], col[1]['nullable'], col[1]['colname'] in pkcols)}\n"""
first = False
pkcols_exists = [ pkcol for pkcol in pkcols if pkcol in [col[1]['colname'] for col in cols] ]
if len(pkcols_exists) > 0:
script += f""" , CONSTRAINT PK_{table_name.upper()}\n"""
script += f""" PRIMARY KEY CLUSTERED ({", ".join(pkcols_exists)})\n"""
script += f""" WITH (IGNORE_DUP_KEY = OFF)\n"""
script += ");\nGO;\n"
return script
def formatvalue(val, coltype):
if coltype is str:
return f"""'{val.replace("'", "''")}'"""
else:
return "NULL" if val is None or val == "" else val
def create_insert(table_name, colmap, rows):
script = ""
cols = sorted(colmap.items(), key=operator.itemgetter(0))
for row in rows:
script += f"""INSERT INTO {table_name} ({", ".join([col[1]['colname'] for col in cols])})\n"""
row_quoted = [ formatvalue(row[i], cols[i][1]['type']) for i in range(len(cols)) ]
script += f""" VALUES ({", ".join(row_quoted)})\n"""
script += "GO;\n"
return script
# Test code
def run_test() :
# expect ,
testFile = "A,B,C\n1,str,str2\n2,str3,str4"
testFileDummy = StringIO(testFile)
testres = get_delim(testFileDummy)
print("delimiter is %s" % testres)
assert(testres == ',')
# expect <tab>
testFile = "A\tB\tC\n1\tstr\tstr2\n2\tstr3\tstr4"
testFileDummy = StringIO(testFile)
testres = get_delim(testFileDummy)
print("delimiter is %s" % '<\\t>' if testres == '\t' else get_delim(testFileDummy))
assert(testres == '\t')
# expect <tab>
testFile = "A\tB,C\tD\n1\tstr\tstr2\n2\tstr3,str4\tstr5"
testFileDummy = StringIO(testFile)
testres = get_delim(testFileDummy)
print("delimiter is %s" % '<\\t>' if testres == '\t' else get_delim(testFileDummy))
assert(testres == '\t')
def run_test2() :
testStr = "my col name"
testres = regulate_token(testStr)
print("%s --> %s" % (testStr, testres))
assert(testres == 'mycolname')
testStr = "my col name, name2"
testres = regulate_token(testStr)
print("%s --> %s" % (testStr, testres))
assert(testres == 'mycolname_name2')
def run_test3() :
#expect: A:int, B:str, C:str
testFile = "A,B,C\n1,str,str2\n2,str3,str4"
testFileDummy = StringIO(testFile)
testres, testrows = extract_from_csv(testFileDummy, ',', True)
print(testres)
assert(len(testres.items()) == 3)
# TODO: more asserts
#expect: Column1:int, Column2:str, Column3:str
testFile = "1,str,str2\n2,str3,str4"
testFileDummy = StringIO(testFile)
testres, testrows = extract_from_csv(testFileDummy, ',', False)
print(testres)
assert(len(testres.items()) == 3)
# TODO: more asserts
# read a file, filter out the bad chars in memory, write the cleaned file back
def process(csv_file, has_header, outtable, outfile):
print(f"Reading {csv_file} ...")
print(f"""The CSV file should{"" if has_header else " not"} contain header""")
# peek the csv file and mine the column type
colmap = {}
with open(csv_file, 'r', encoding='utf8') as content_file:
delim = get_delim(content_file)
# TODO: this is not optimal, we can do one pass instead of 2 pass here
with open(csv_file, 'r', encoding='utf8') as content_file:
colmap, rows = extract_from_csv(content_file, delim, has_header)
# Generate table creation statement
table_name = outtable
full_script = create_table_insert(table_name, colmap, ["id", "_vertexId", "_sink"])
full_script += create_insert(table_name, colmap, rows)
with open(outfile, 'a', encoding='utf8') as target_file:
target_file.write(full_script)
print("Done")
def main():
if len(sys.argv) < 2 :
print("Error: must provide the csv/tsv file name to peek at")
return
if len(sys.argv) < 3 :
print("Error: must provide true or false that the csv file contains header")
return
if len(sys.argv) < 4 :
print("Error: must provide a table name file to write to")
return
if len(sys.argv) < 5 :
print("Error: must provide a script file to write to (or append to)")
return
csv_file = sys.argv[1]
has_header = parse_bool(sys.argv[2])
out_table = sys.argv[3]
out_file = sys.argv[4]
process(csv_file, has_header, out_table, out_file)
# main operations
#run_test()
#run_test2()
#run_test3()
main()

Просмотреть файл

@ -0,0 +1,45 @@
set NEODB=https://jerrylia-home-2-wifi:7473
set USER=neo4j
set PW=neo4jtest
Setlocal
CALL :DOWNLOAD_AS_CSV "match (p:Person) return p.id as id, p.Name as Name, p.Born as Born" person.csv
CALL :DOWNLOAD_AS_CSV "match (m:Movie) return m.id as id, m.Title as Title, m.Tagline as Tagline, m.Released as Released" movie.csv
CALL :DOWNLOAD_AS_CSV_CUSTOMJQ "match (m:Person)-[r:ACTED_IN]->(n:Movie) return m.id as _vertexId, n.id as _sink, r.Roles as Roles" acted_in.csv acted_in.jq.txt
CALL :DOWNLOAD_AS_CSV "match (m:Person)-[r:PRODUCED]->(n:Movie) return m.id as _vertexId, n.id as _sink" produced.csv
CALL :DOWNLOAD_AS_CSV "match (m:Person)-[r:DIRECTED]->(n:Movie) return m.id as _vertexId, n.id as _sink" directed.csv
CALL :DOWNLOAD_AS_CSV "match (m:Person)-[r:WROTE]->(n:Movie) return m.id as _vertexId, n.id as _sink" wrote.csv
CALL :DOWNLOAD_AS_CSV "match (m:Person)-[r:REVIEWED]->(n:Movie) return m.id as _vertexId, n.id as _sink, r.Summary as Summary, r.Rating as Rating" reviewed.csv
CALL :DOWNLOAD_AS_CSV "match (m:Person)-[r:FOLLOWS]->(n:Person) return m.id as _vertexId, n.id as _sink" follows.csv
goto :EOF
REM %1 is the cypher command
REM %2 is the output file
:DOWNLOAD_AS_CSV
echo {"statements":[{"statement":"%~1"}]} > dn.req.temp.txt
curl --insecure -u %USER%:%PW% ^
-H accept:application/json -H content-type:application/json ^
-d @dn.req.temp.txt ^
%NEODB%/db/data/transaction/commit ^
| jq -r "(.results[0]) | .columns,.data[].row | @csv" ^
> %~2
GOTO:EOF
REM %1 is the cypher command
REM %2 is the output file
REM %3 is the JQ command file when the command doesn't work well over command line interface
:DOWNLOAD_AS_CSV_CUSTOMJQ
echo {"statements":[{"statement":"%~1"}]} > dn.req.temp.txt
curl --insecure -u %USER%:%PW% ^
-H accept:application/json -H content-type:application/json ^
-d @dn.req.temp.txt ^
%NEODB%/db/data/transaction/commit ^
| jq -f %~3 -r ^
> %~2
GOTO:EOF
:EOF

Просмотреть файл

@ -0,0 +1,932 @@
IF db_id('octestdb') is null CREATE DATABASE octestdb;
GO
USE octestdb;
GO
DROP TABLE IF EXISTS dbo.Person
CREATE TABLE dbo.Person
(
id varchar(100)
, Name varchar(MAX)
, Born int NULL
, CONSTRAINT PK_PERSON
PRIMARY KEY CLUSTERED (id)
WITH (IGNORE_DUP_KEY = OFF)
)
INSERT INTO Person (id, Name, Born)
VALUES ('Keanu Reeves', 'Keanu Reeves', 1964)
INSERT INTO Person (id, Name, Born)
VALUES ('Carrie-Anne Moss', 'Carrie-Anne Moss', 1967)
INSERT INTO Person (id, Name, Born)
VALUES ('Laurence Fishburne', 'Laurence Fishburne', 1961)
INSERT INTO Person (id, Name, Born)
VALUES ('Hugo Weaving', 'Hugo Weaving', 1960)
INSERT INTO Person (id, Name, Born)
VALUES ('Lilly Wachowski', 'Lilly Wachowski', 1967)
INSERT INTO Person (id, Name, Born)
VALUES ('Lana Wachowski', 'Lana Wachowski', 1965)
INSERT INTO Person (id, Name, Born)
VALUES ('Joel Silver', 'Joel Silver', 1952)
INSERT INTO Person (id, Name, Born)
VALUES ('Emil Eifrem', 'Emil Eifrem', 1978)
INSERT INTO Person (id, Name, Born)
VALUES ('Charlize Theron', 'Charlize Theron', 1975)
INSERT INTO Person (id, Name, Born)
VALUES ('Al Pacino', 'Al Pacino', 1940)
INSERT INTO Person (id, Name, Born)
VALUES ('Taylor Hackford', 'Taylor Hackford', 1944)
INSERT INTO Person (id, Name, Born)
VALUES ('Tom Cruise', 'Tom Cruise', 1962)
INSERT INTO Person (id, Name, Born)
VALUES ('Jack Nicholson', 'Jack Nicholson', 1937)
INSERT INTO Person (id, Name, Born)
VALUES ('Demi Moore', 'Demi Moore', 1962)
INSERT INTO Person (id, Name, Born)
VALUES ('Kevin Bacon', 'Kevin Bacon', 1958)
INSERT INTO Person (id, Name, Born)
VALUES ('Kiefer Sutherland', 'Kiefer Sutherland', 1966)
INSERT INTO Person (id, Name, Born)
VALUES ('Noah Wyle', 'Noah Wyle', 1971)
INSERT INTO Person (id, Name, Born)
VALUES ('Cuba Gooding Jr.', 'Cuba Gooding Jr.', 1968)
INSERT INTO Person (id, Name, Born)
VALUES ('Kevin Pollak', 'Kevin Pollak', 1957)
INSERT INTO Person (id, Name, Born)
VALUES ('J.T. Walsh', 'J.T. Walsh', 1943)
INSERT INTO Person (id, Name, Born)
VALUES ('James Marshall', 'James Marshall', 1967)
INSERT INTO Person (id, Name, Born)
VALUES ('Christopher Guest', 'Christopher Guest', 1948)
INSERT INTO Person (id, Name, Born)
VALUES ('Rob Reiner', 'Rob Reiner', 1947)
INSERT INTO Person (id, Name, Born)
VALUES ('Aaron Sorkin', 'Aaron Sorkin', 1961)
INSERT INTO Person (id, Name, Born)
VALUES ('Kelly McGillis', 'Kelly McGillis', 1957)
INSERT INTO Person (id, Name, Born)
VALUES ('Val Kilmer', 'Val Kilmer', 1959)
INSERT INTO Person (id, Name, Born)
VALUES ('Anthony Edwards', 'Anthony Edwards', 1962)
INSERT INTO Person (id, Name, Born)
VALUES ('Tom Skerritt', 'Tom Skerritt', 1933)
INSERT INTO Person (id, Name, Born)
VALUES ('Meg Ryan', 'Meg Ryan', 1961)
INSERT INTO Person (id, Name, Born)
VALUES ('Tony Scott', 'Tony Scott', 1944)
INSERT INTO Person (id, Name, Born)
VALUES ('Jim Cash', 'Jim Cash', 1941)
INSERT INTO Person (id, Name, Born)
VALUES ('Renee Zellweger', 'Renee Zellweger', 1969)
INSERT INTO Person (id, Name, Born)
VALUES ('Kelly Preston', 'Kelly Preston', 1962)
INSERT INTO Person (id, Name, Born)
VALUES ('Jerry O''Connell', 'Jerry O''Connell', 1974)
INSERT INTO Person (id, Name, Born)
VALUES ('Jay Mohr', 'Jay Mohr', 1970)
INSERT INTO Person (id, Name, Born)
VALUES ('Bonnie Hunt', 'Bonnie Hunt', 1961)
INSERT INTO Person (id, Name, Born)
VALUES ('Regina King', 'Regina King', 1971)
INSERT INTO Person (id, Name, Born)
VALUES ('Jonathan Lipnicki', 'Jonathan Lipnicki', 1996)
INSERT INTO Person (id, Name, Born)
VALUES ('Cameron Crowe', 'Cameron Crowe', 1957)
INSERT INTO Person (id, Name, Born)
VALUES ('River Phoenix', 'River Phoenix', 1970)
INSERT INTO Person (id, Name, Born)
VALUES ('Corey Feldman', 'Corey Feldman', 1971)
INSERT INTO Person (id, Name, Born)
VALUES ('Wil Wheaton', 'Wil Wheaton', 1972)
INSERT INTO Person (id, Name, Born)
VALUES ('John Cusack', 'John Cusack', 1966)
INSERT INTO Person (id, Name, Born)
VALUES ('Marshall Bell', 'Marshall Bell', 1942)
INSERT INTO Person (id, Name, Born)
VALUES ('Helen Hunt', 'Helen Hunt', 1963)
INSERT INTO Person (id, Name, Born)
VALUES ('Greg Kinnear', 'Greg Kinnear', 1963)
INSERT INTO Person (id, Name, Born)
VALUES ('James L. Brooks', 'James L. Brooks', 1940)
INSERT INTO Person (id, Name, Born)
VALUES ('Annabella Sciorra', 'Annabella Sciorra', 1960)
INSERT INTO Person (id, Name, Born)
VALUES ('Max von Sydow', 'Max von Sydow', 1929)
INSERT INTO Person (id, Name, Born)
VALUES ('Werner Herzog', 'Werner Herzog', 1942)
INSERT INTO Person (id, Name, Born)
VALUES ('Robin Williams', 'Robin Williams', 1951)
INSERT INTO Person (id, Name, Born)
VALUES ('Vincent Ward', 'Vincent Ward', 1956)
INSERT INTO Person (id, Name, Born)
VALUES ('Ethan Hawke', 'Ethan Hawke', 1970)
INSERT INTO Person (id, Name, Born)
VALUES ('Rick Yune', 'Rick Yune', 1971)
INSERT INTO Person (id, Name, Born)
VALUES ('James Cromwell', 'James Cromwell', 1940)
INSERT INTO Person (id, Name, Born)
VALUES ('Scott Hicks', 'Scott Hicks', 1953)
INSERT INTO Person (id, Name, Born)
VALUES ('Parker Posey', 'Parker Posey', 1968)
INSERT INTO Person (id, Name, Born)
VALUES ('Dave Chappelle', 'Dave Chappelle', 1973)
INSERT INTO Person (id, Name, Born)
VALUES ('Steve Zahn', 'Steve Zahn', 1967)
INSERT INTO Person (id, Name, Born)
VALUES ('Tom Hanks', 'Tom Hanks', 1956)
INSERT INTO Person (id, Name, Born)
VALUES ('Nora Ephron', 'Nora Ephron', 1941)
INSERT INTO Person (id, Name, Born)
VALUES ('Rita Wilson', 'Rita Wilson', 1956)
INSERT INTO Person (id, Name, Born)
VALUES ('Bill Pullman', 'Bill Pullman', 1953)
INSERT INTO Person (id, Name, Born)
VALUES ('Victor Garber', 'Victor Garber', 1949)
INSERT INTO Person (id, Name, Born)
VALUES ('Rosie O''Donnell', 'Rosie O''Donnell', 1962)
INSERT INTO Person (id, Name, Born)
VALUES ('John Patrick Stanley', 'John Patrick Stanley', 1950)
INSERT INTO Person (id, Name, Born)
VALUES ('Nathan Lane', 'Nathan Lane', 1956)
INSERT INTO Person (id, Name, Born)
VALUES ('Billy Crystal', 'Billy Crystal', 1948)
INSERT INTO Person (id, Name, Born)
VALUES ('Carrie Fisher', 'Carrie Fisher', 1956)
INSERT INTO Person (id, Name, Born)
VALUES ('Bruno Kirby', 'Bruno Kirby', 1949)
INSERT INTO Person (id, Name, Born)
VALUES ('Liv Tyler', 'Liv Tyler', 1977)
INSERT INTO Person (id, Name, Born)
VALUES ('Brooke Langton', 'Brooke Langton', 1970)
INSERT INTO Person (id, Name, Born)
VALUES ('Gene Hackman', 'Gene Hackman', 1930)
INSERT INTO Person (id, Name, Born)
VALUES ('Orlando Jones', 'Orlando Jones', 1968)
INSERT INTO Person (id, Name, Born)
VALUES ('Howard Deutch', 'Howard Deutch', 1950)
INSERT INTO Person (id, Name, Born)
VALUES ('Christian Bale', 'Christian Bale', 1974)
INSERT INTO Person (id, Name, Born)
VALUES ('Zach Grenier', 'Zach Grenier', 1954)
INSERT INTO Person (id, Name, Born)
VALUES ('Mike Nichols', 'Mike Nichols', 1931)
INSERT INTO Person (id, Name, Born)
VALUES ('Richard Harris', 'Richard Harris', 1930)
INSERT INTO Person (id, Name, Born)
VALUES ('Clint Eastwood', 'Clint Eastwood', 1930)
INSERT INTO Person (id, Name, Born)
VALUES ('Takeshi Kitano', 'Takeshi Kitano', 1947)
INSERT INTO Person (id, Name, Born)
VALUES ('Dina Meyer', 'Dina Meyer', 1968)
INSERT INTO Person (id, Name, Born)
VALUES ('Ice-T', 'Ice-T', 1958)
INSERT INTO Person (id, Name, Born)
VALUES ('Robert Longo', 'Robert Longo', 1953)
INSERT INTO Person (id, Name, Born)
VALUES ('Halle Berry', 'Halle Berry', 1966)
INSERT INTO Person (id, Name, Born)
VALUES ('Jim Broadbent', 'Jim Broadbent', 1949)
INSERT INTO Person (id, Name, Born)
VALUES ('Tom Tykwer', 'Tom Tykwer', 1965)
INSERT INTO Person (id, Name, Born)
VALUES ('David Mitchell', 'David Mitchell', 1969)
INSERT INTO Person (id, Name, Born)
VALUES ('Stefan Arndt', 'Stefan Arndt', 1961)
INSERT INTO Person (id, Name, Born)
VALUES ('Ian McKellen', 'Ian McKellen', 1939)
INSERT INTO Person (id, Name, Born)
VALUES ('Audrey Tautou', 'Audrey Tautou', 1976)
INSERT INTO Person (id, Name, Born)
VALUES ('Paul Bettany', 'Paul Bettany', 1971)
INSERT INTO Person (id, Name, Born)
VALUES ('Ron Howard', 'Ron Howard', 1954)
INSERT INTO Person (id, Name, Born)
VALUES ('Natalie Portman', 'Natalie Portman', 1981)
INSERT INTO Person (id, Name, Born)
VALUES ('Stephen Rea', 'Stephen Rea', 1946)
INSERT INTO Person (id, Name, Born)
VALUES ('John Hurt', 'John Hurt', 1940)
INSERT INTO Person (id, Name, Born)
VALUES ('', 'Ben Miles', 1967)
INSERT INTO Person (id, Name, Born)
VALUES ('Emile Hirsch', 'Emile Hirsch', 1985)
INSERT INTO Person (id, Name, Born)
VALUES ('John Goodman', 'John Goodman', 1960)
INSERT INTO Person (id, Name, Born)
VALUES ('Susan Sarandon', 'Susan Sarandon', 1946)
INSERT INTO Person (id, Name, Born)
VALUES ('Matthew Fox', 'Matthew Fox', 1966)
INSERT INTO Person (id, Name, Born)
VALUES ('Christina Ricci', 'Christina Ricci', 1980)
INSERT INTO Person (id, Name, Born)
VALUES ('Rain', 'Rain', 1982)
INSERT INTO Person (id, Name, Born)
VALUES ('Naomie Harris', 'Naomie Harris', NULL)
INSERT INTO Person (id, Name, Born)
VALUES ('Michael Clarke Duncan', 'Michael Clarke Duncan', 1957)
INSERT INTO Person (id, Name, Born)
VALUES ('David Morse', 'David Morse', 1953)
INSERT INTO Person (id, Name, Born)
VALUES ('Sam Rockwell', 'Sam Rockwell', 1968)
INSERT INTO Person (id, Name, Born)
VALUES ('Gary Sinise', 'Gary Sinise', 1955)
INSERT INTO Person (id, Name, Born)
VALUES ('Patricia Clarkson', 'Patricia Clarkson', 1959)
INSERT INTO Person (id, Name, Born)
VALUES ('Frank Darabont', 'Frank Darabont', 1959)
INSERT INTO Person (id, Name, Born)
VALUES ('Frank Langella', 'Frank Langella', 1938)
INSERT INTO Person (id, Name, Born)
VALUES ('Michael Sheen', 'Michael Sheen', 1969)
INSERT INTO Person (id, Name, Born)
VALUES ('Oliver Platt', 'Oliver Platt', 1960)
INSERT INTO Person (id, Name, Born)
VALUES ('Danny DeVito', 'Danny DeVito', 1944)
INSERT INTO Person (id, Name, Born)
VALUES ('John C. Reilly', 'John C. Reilly', 1965)
INSERT INTO Person (id, Name, Born)
VALUES ('Ed Harris', 'Ed Harris', 1950)
INSERT INTO Person (id, Name, Born)
VALUES ('Bill Paxton', 'Bill Paxton', 1955)
INSERT INTO Person (id, Name, Born)
VALUES ('Philip Seymour Hoffman', 'Philip Seymour Hoffman', 1967)
INSERT INTO Person (id, Name, Born)
VALUES ('Jan de Bont', 'Jan de Bont', 1943)
INSERT INTO Person (id, Name, Born)
VALUES ('Robert Zemeckis', 'Robert Zemeckis', 1951)
INSERT INTO Person (id, Name, Born)
VALUES ('Milos Forman', 'Milos Forman', 1932)
INSERT INTO Person (id, Name, Born)
VALUES ('Diane Keaton', 'Diane Keaton', 1946)
INSERT INTO Person (id, Name, Born)
VALUES ('Nancy Meyers', 'Nancy Meyers', 1949)
INSERT INTO Person (id, Name, Born)
VALUES ('Chris Columbus', 'Chris Columbus', 1958)
INSERT INTO Person (id, Name, Born)
VALUES ('Julia Roberts', 'Julia Roberts', 1967)
INSERT INTO Person (id, Name, Born)
VALUES ('Madonna', 'Madonna', 1954)
INSERT INTO Person (id, Name, Born)
VALUES ('Geena Davis', 'Geena Davis', 1956)
INSERT INTO Person (id, Name, Born)
VALUES ('Lori Petty', 'Lori Petty', 1963)
INSERT INTO Person (id, Name, Born)
VALUES ('Penny Marshall', 'Penny Marshall', 1943)
INSERT INTO Person (id, Name, Born)
VALUES ('Paul Blythe', 'Paul Blythe', NULL)
INSERT INTO Person (id, Name, Born)
VALUES ('Angela Scope', 'Angela Scope', NULL)
INSERT INTO Person (id, Name, Born)
VALUES ('Jessica Thompson', 'Jessica Thompson', NULL)
INSERT INTO Person (id, Name, Born)
VALUES ('James Thompson', 'James Thompson', NULL)
DROP TABLE IF EXISTS dbo.Movie
CREATE TABLE dbo.Movie
(
id varchar(100)
, Title varchar(MAX)
, Tagline varchar(MAX)
, Released int
, CONSTRAINT PK_MOVIE
PRIMARY KEY CLUSTERED (id)
WITH (IGNORE_DUP_KEY = OFF)
)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('The Matrix', 'The Matrix', 'Welcome to the Real World', 1999)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('The Matrix Reloaded', 'The Matrix Reloaded', 'Free your mind', 2003)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('The Matrix Revolutions', 'The Matrix Revolutions', 'Everything that has a beginning has an end', 2003)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('The Devil''s Advocate', 'The Devil''s Advocate', 'Evil has its winning ways', 1997)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('A Few Good Men', 'A Few Good Men', 'In the heart of the nation''s capital, in a courthouse of the U.S. government, one man will stop at nothing to keep his honor, and one will stop at nothing to find the truth.', 1992)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Top Gun', 'Top Gun', 'I feel the need, the need for speed.', 1986)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Jerry Maguire', 'Jerry Maguire', 'The rest of his life begins now.', 2000)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Stand By Me', 'Stand By Me', 'For some, it''s the last real taste of innocence, and the first real taste of life. But for everyone, it''s the time that memories are made of.', 1986)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('As Good as It Gets', 'As Good as It Gets', 'A comedy from the heart that goes for the throat.', 1997)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('What Dreams May Come', 'What Dreams May Come', 'After life there is more. The end is just the beginning.', 1998)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Snow Falling on Cedars', 'Snow Falling on Cedars', 'First loves last. Forever.', 1999)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('You''ve Got Mail', 'You''ve Got Mail', 'At odds in life... in love on-line.', 1998)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Sleepless in Seattle', 'Sleepless in Seattle', 'What if someone you never met, someone you never saw, someone you never knew was the only someone for you?', 1993)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Joe Versus the Volcano', 'Joe Versus the Volcano', 'A story of love, lava and burning desire.', 1990)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('When Harry Met Sally', 'When Harry Met Sally', 'At odds in life... in love on-line.', 1998)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('That Thing You Do', 'That Thing You Do', 'In every life there comes a time when that thing you dream becomes that thing you do', 1996)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('The Replacements', 'The Replacements', 'Pain heals, Chicks dig scars... Glory lasts forever', 2000)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('RescueDawn', 'RescueDawn', 'Based on the extraordinary true story of one man''s fight for freedom', 2006)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('The Birdcage', 'The Birdcage', 'Come as you are', 1996)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Unforgiven', 'Unforgiven', 'It''s a hell of a thing, killing a man', 1992)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Johnny Mnemonic', 'Johnny Mnemonic', 'The hottest data on earth. In the coolest head in town', 1995)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Cloud Atlas', 'Cloud Atlas', 'Everything is connected', 2012)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('The Da Vinci Code', 'The Da Vinci Code', 'Break The Codes', 2006)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('V for Vendetta', 'V for Vendetta', 'Freedom! Forever!', 2006)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Speed Racer', 'Speed Racer', 'Speed has no limits', 2008)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Ninja Assassin', 'Ninja Assassin', 'Prepare to enter a secret world of assassins', 2009)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('The Green Mile', 'The Green Mile', 'Walk a mile you''ll never forget.', 1999)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Frost/Nixon', 'Frost/Nixon', '400 million people were waiting for the truth.', 2008)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Hoffa', 'Hoffa', 'He didn''t want law. He wanted justice.', 1992)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Apollo 13', 'Apollo 13', 'Houston, we have a problem.', 1995)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Twister', 'Twister', 'Don''t Breathe. Don''t Look Back.', 1996)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Cast Away', 'Cast Away', 'At the edge of the world, his journey begins.', 2000)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('One Flew Over the Cuckoo''s Nest', 'One Flew Over the Cuckoo''s Nest', 'If he''s crazy, what does that make you?', 1975)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Something''s Gotta Give', 'Something''s Gotta Give', '', 2003)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Bicentennial Man', 'Bicentennial Man', 'One robot''s 200 year journey to become an ordinary man.', 1999)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('Charlie Wilson''s War', 'Charlie Wilson''s War', 'A stiff drink. A little mascara. A lot of nerve. Who said they couldn''t bring down the Soviet empire.', 2007)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('The Polar Express', 'The Polar Express', 'This Holiday Season… Believe', 2004)
INSERT INTO Movie (id, Title, Tagline, Released)
VALUES ('A League of Their Own', 'A League of Their Own', 'Once in a lifetime you get a chance to do something different.', 1992)
DROP TABLE IF EXISTS dbo.ActedIn
CREATE TABLE dbo.ActedIn
(
_vertexId varchar(100)
, _sink varchar(100)
, Roles varchar(MAX)
, CONSTRAINT PK_ACTEDIN
PRIMARY KEY CLUSTERED (_vertexId, _sink)
WITH (IGNORE_DUP_KEY = OFF)
)
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Emil Eifrem', 'The Matrix', 'Emil')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Hugo Weaving', 'The Matrix', 'Agent Smith')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Laurence Fishburne', 'The Matrix', 'Morpheus')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Carrie-Anne Moss', 'The Matrix', 'Trinity')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Keanu Reeves', 'The Matrix', 'Neo')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Hugo Weaving', 'The Matrix Reloaded', 'Agent Smith')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Laurence Fishburne', 'The Matrix Reloaded', 'Morpheus')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Carrie-Anne Moss', 'The Matrix Reloaded', 'Trinity')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Keanu Reeves', 'The Matrix Reloaded', 'Neo')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Hugo Weaving', 'The Matrix Revolutions', 'Agent Smith')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Laurence Fishburne', 'The Matrix Revolutions', 'Morpheus')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Carrie-Anne Moss', 'The Matrix Revolutions', 'Trinity')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Keanu Reeves', 'The Matrix Revolutions', 'Neo')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Al Pacino', 'The Devil''s Advocate', 'John Milton')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Charlize Theron', 'The Devil''s Advocate', 'Mary Ann Lomax')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Keanu Reeves', 'The Devil''s Advocate', 'Kevin Lomax')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('James Marshall', 'A Few Good Men', 'Pfc. Louden Downey')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Kevin Pollak', 'A Few Good Men', 'Lt. Sam Weinberg')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('J.T. Walsh', 'A Few Good Men', 'Lt. Col. Matthew Andrew Markinson')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Aaron Sorkin', 'A Few Good Men', 'Man in Bar')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Cuba Gooding Jr.', 'A Few Good Men', 'Cpl. Carl Hammaker')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Christopher Guest', 'A Few Good Men', 'Dr. Stone')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Noah Wyle', 'A Few Good Men', 'Cpl. Jeffrey Barnes')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Kiefer Sutherland', 'A Few Good Men', 'Lt. Jonathan Kendrick')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Kevin Bacon', 'A Few Good Men', 'Capt. Jack Ross')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Demi Moore', 'A Few Good Men', 'Lt. Cdr. JoAnne Galloway')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Jack Nicholson', 'A Few Good Men', 'Col. Nathan R. Jessup')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Tom Cruise', 'A Few Good Men', 'Lt. Daniel Kaffee')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Val Kilmer', 'Top Gun', 'Iceman')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Meg Ryan', 'Top Gun', 'Carole')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Tom Skerritt', 'Top Gun', 'Viper')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Kelly McGillis', 'Top Gun', 'Charlie')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Tom Cruise', 'Top Gun', 'Maverick')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Anthony Edwards', 'Top Gun', 'Goose')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Jerry O''Connell', 'Jerry Maguire', 'Frank Cushman')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Bonnie Hunt', 'Jerry Maguire', 'Laurel Boyd')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Jay Mohr', 'Jerry Maguire', 'Bob Sugar')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Cuba Gooding Jr.', 'Jerry Maguire', 'Rod Tidwell')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Jonathan Lipnicki', 'Jerry Maguire', 'Ray Boyd')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Renee Zellweger', 'Jerry Maguire', 'Dorothy Boyd')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Kelly Preston', 'Jerry Maguire', 'Avery Bishop')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Regina King', 'Jerry Maguire', 'Marcee Tidwell')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Tom Cruise', 'Jerry Maguire', 'Jerry Maguire')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Jerry O''Connell', 'Stand By Me', 'Vern Tessio')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('River Phoenix', 'Stand By Me', 'Chris Chambers')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Marshall Bell', 'Stand By Me', 'Mr. Lachance')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Wil Wheaton', 'Stand By Me', 'Gordie Lachance')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Kiefer Sutherland', 'Stand By Me', 'Ace Merrill')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('John Cusack', 'Stand By Me', 'Denny Lachance')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Corey Feldman', 'Stand By Me', 'Teddy Duchamp')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Helen Hunt', 'As Good as It Gets', 'Carol Connelly')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Jack Nicholson', 'As Good as It Gets', 'Melvin Udall')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Cuba Gooding Jr.', 'As Good as It Gets', 'Frank Sachs')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Greg Kinnear', 'As Good as It Gets', 'Simon Bishop')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Robin Williams', 'What Dreams May Come', 'Chris Nielsen')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Cuba Gooding Jr.', 'What Dreams May Come', 'Albert Lewis')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Max von Sydow', 'What Dreams May Come', 'The Tracker')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Werner Herzog', 'What Dreams May Come', 'The Face')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Annabella Sciorra', 'What Dreams May Come', 'Annie Collins-Nielsen')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Ethan Hawke', 'Snow Falling on Cedars', 'Ishmael Chambers')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Rick Yune', 'Snow Falling on Cedars', 'Kazuo Miyamoto')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Max von Sydow', 'Snow Falling on Cedars', 'Nels Gudmundsson')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('James Cromwell', 'Snow Falling on Cedars', 'Judge Fielding')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Tom Hanks', 'You''ve Got Mail', 'Joe Fox')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Parker Posey', 'You''ve Got Mail', 'Patricia Eden')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Greg Kinnear', 'You''ve Got Mail', 'Frank Navasky')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Meg Ryan', 'You''ve Got Mail', 'Kathleen Kelly')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Steve Zahn', 'You''ve Got Mail', 'George Pappas')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Dave Chappelle', 'You''ve Got Mail', 'Kevin Jackson')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Meg Ryan', 'Sleepless in Seattle', 'Annie Reed')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Victor Garber', 'Sleepless in Seattle', 'Greg')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Tom Hanks', 'Sleepless in Seattle', 'Sam Baldwin')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Bill Pullman', 'Sleepless in Seattle', 'Walter')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Rita Wilson', 'Sleepless in Seattle', 'Suzy')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Rosie O''Donnell', 'Sleepless in Seattle', 'Becky')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Tom Hanks', 'Joe Versus the Volcano', 'Joe Banks')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Nathan Lane', 'Joe Versus the Volcano', 'Baw')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Meg Ryan', 'Joe Versus the Volcano', 'DeDe|Angelica Graynamore|Patricia Graynamore')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Carrie Fisher', 'When Harry Met Sally', 'Marie')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Billy Crystal', 'When Harry Met Sally', 'Harry Burns')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Bruno Kirby', 'When Harry Met Sally', 'Jess')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Meg Ryan', 'When Harry Met Sally', 'Sally Albright')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Tom Hanks', 'That Thing You Do', 'Mr. White')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Liv Tyler', 'That Thing You Do', 'Faye Dolan')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Charlize Theron', 'That Thing You Do', 'Tina')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Brooke Langton', 'The Replacements', 'Annabelle Farrell')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Keanu Reeves', 'The Replacements', 'Shane Falco')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Orlando Jones', 'The Replacements', 'Clifford Franklin')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Gene Hackman', 'The Replacements', 'Jimmy McGinty')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Zach Grenier', 'RescueDawn', 'Squad Leader')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Steve Zahn', 'RescueDawn', 'Duane')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Christian Bale', 'RescueDawn', 'Dieter Dengler')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Marshall Bell', 'RescueDawn', 'Admiral')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Robin Williams', 'The Birdcage', 'Armand Goldman')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Nathan Lane', 'The Birdcage', 'Albert Goldman')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Gene Hackman', 'The Birdcage', 'Sen. Kevin Keeley')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Clint Eastwood', 'Unforgiven', 'Bill Munny')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Gene Hackman', 'Unforgiven', 'Little Bill Daggett')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Richard Harris', 'Unforgiven', 'English Bob')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Ice-T', 'Johnny Mnemonic', 'J-Bone')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Dina Meyer', 'Johnny Mnemonic', 'Jane')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Keanu Reeves', 'Johnny Mnemonic', 'Johnny Mnemonic')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Takeshi Kitano', 'Johnny Mnemonic', 'Takahashi')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Tom Hanks', 'Cloud Atlas', 'Zachry|Dr. Henry Goose|Isaac Sachs|Dermot Hoggins')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Jim Broadbent', 'Cloud Atlas', 'Vyvyan Ayrs|Captain Molyneux|Timothy Cavendish')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Halle Berry', 'Cloud Atlas', 'Luisa Rey|Jocasta Ayrs|Ovid|Meronym')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Hugo Weaving', 'Cloud Atlas', 'Bill Smoke|Haskell Moore|Tadeusz Kesselring|Nurse Noakes|Boardman Mephi|Old Georgie')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Tom Hanks', 'The Da Vinci Code', 'Dr. Robert Langdon')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Ian McKellen', 'The Da Vinci Code', 'Sir Leight Teabing')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Audrey Tautou', 'The Da Vinci Code', 'Sophie Neveu')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Paul Bettany', 'The Da Vinci Code', 'Silas')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('John Hurt', 'V for Vendetta', 'High Chancellor Adam Sutler')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Stephen Rea', 'V for Vendetta', 'Eric Finch')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Natalie Portman', 'V for Vendetta', 'Evey Hammond')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Hugo Weaving', 'V for Vendetta', 'V')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('', 'V for Vendetta', 'Dascomb')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Emile Hirsch', 'Speed Racer', 'Speed Racer')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Rain', 'Speed Racer', 'Taejo Togokahn')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Christina Ricci', 'Speed Racer', 'Trixie')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('', 'Speed Racer', 'Cass Jones')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Susan Sarandon', 'Speed Racer', 'Mom')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('John Goodman', 'Speed Racer', 'Pops')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Matthew Fox', 'Speed Racer', 'Racer X')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Rain', 'Ninja Assassin', 'Raizo')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('', 'Ninja Assassin', 'Ryan Maslow')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Rick Yune', 'Ninja Assassin', 'Takeshi')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Naomie Harris', 'Ninja Assassin', 'Mika Coretti')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Sam Rockwell', 'The Green Mile', '"Wild Bill" Wharton')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Bonnie Hunt', 'The Green Mile', 'Jan Edgecomb')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Patricia Clarkson', 'The Green Mile', 'Melinda Moores')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('James Cromwell', 'The Green Mile', 'Warden Hal Moores')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Tom Hanks', 'The Green Mile', 'Paul Edgecomb')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Michael Clarke Duncan', 'The Green Mile', 'John Coffey')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('David Morse', 'The Green Mile', 'Brutus "Brutal" Howell')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Gary Sinise', 'The Green Mile', 'Burt Hammersmith')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Sam Rockwell', 'Frost/Nixon', 'James Reston, Jr.')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Michael Sheen', 'Frost/Nixon', 'David Frost')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Frank Langella', 'Frost/Nixon', 'Richard Nixon')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Oliver Platt', 'Frost/Nixon', 'Bob Zelnick')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Kevin Bacon', 'Frost/Nixon', 'Jack Brennan')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('John C. Reilly', 'Hoffa', 'Peter "Pete" Connelly')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Danny DeVito', 'Hoffa', 'Robert "Bobby" Ciaro')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('J.T. Walsh', 'Hoffa', 'Frank Fitzsimmons')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Jack Nicholson', 'Hoffa', 'Hoffa')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Tom Hanks', 'Apollo 13', 'Jim Lovell')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Ed Harris', 'Apollo 13', 'Gene Kranz')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Gary Sinise', 'Apollo 13', 'Ken Mattingly')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Kevin Bacon', 'Apollo 13', 'Jack Swigert')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Bill Paxton', 'Apollo 13', 'Fred Haise')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Helen Hunt', 'Twister', 'Dr. Jo Harding')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Bill Paxton', 'Twister', 'Bill Harding')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Philip Seymour Hoffman', 'Twister', 'Dustin "Dusty" Davis')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Zach Grenier', 'Twister', 'Eddie')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Helen Hunt', 'Cast Away', 'Kelly Frears')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Tom Hanks', 'Cast Away', 'Chuck Noland')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Danny DeVito', 'One Flew Over the Cuckoo''s Nest', 'Martini')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Jack Nicholson', 'One Flew Over the Cuckoo''s Nest', 'Randle McMurphy')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Keanu Reeves', 'Something''s Gotta Give', 'Julian Mercer')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Diane Keaton', 'Something''s Gotta Give', 'Erica Barry')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Jack Nicholson', 'Something''s Gotta Give', 'Harry Sanborn')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Robin Williams', 'Bicentennial Man', 'Andrew Marin')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Oliver Platt', 'Bicentennial Man', 'Rupert Burns')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Julia Roberts', 'Charlie Wilson''s War', 'Joanne Herring')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Tom Hanks', 'Charlie Wilson''s War', 'Rep. Charlie Wilson')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Philip Seymour Hoffman', 'Charlie Wilson''s War', 'Gust Avrakotos')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Tom Hanks', 'The Polar Express', 'Hero Boy|Father|Conductor|Hobo|Scrooge|Santa Claus')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Tom Hanks', 'A League of Their Own', 'Jimmy Dugan')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Madonna', 'A League of Their Own', '"All the Way" Mae Mordabito')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Rosie O''Donnell', 'A League of Their Own', 'Doris Murphy')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Geena Davis', 'A League of Their Own', 'Dottie Hinson')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Bill Paxton', 'A League of Their Own', 'Bob Hinson')
INSERT INTO ActedIn (_vertexId, _sink, Roles)
VALUES ('Lori Petty', 'A League of Their Own', 'Kit Keller')
DROP TABLE IF EXISTS dbo.Produced
CREATE TABLE dbo.Produced
(
_vertexId varchar(100)
, _sink varchar(100)
, CONSTRAINT PK_PRODUCED
PRIMARY KEY CLUSTERED (_vertexId, _sink)
WITH (IGNORE_DUP_KEY = OFF)
)
INSERT INTO Produced (_vertexId, _sink)
VALUES ('Joel Silver', 'The Matrix')
INSERT INTO Produced (_vertexId, _sink)
VALUES ('Joel Silver', 'The Matrix Reloaded')
INSERT INTO Produced (_vertexId, _sink)
VALUES ('Joel Silver', 'The Matrix Revolutions')
INSERT INTO Produced (_vertexId, _sink)
VALUES ('Cameron Crowe', 'Jerry Maguire')
INSERT INTO Produced (_vertexId, _sink)
VALUES ('Nora Ephron', 'When Harry Met Sally')
INSERT INTO Produced (_vertexId, _sink)
VALUES ('Rob Reiner', 'When Harry Met Sally')
INSERT INTO Produced (_vertexId, _sink)
VALUES ('Stefan Arndt', 'Cloud Atlas')
INSERT INTO Produced (_vertexId, _sink)
VALUES ('Lana Wachowski', 'V for Vendetta')
INSERT INTO Produced (_vertexId, _sink)
VALUES ('Lilly Wachowski', 'V for Vendetta')
INSERT INTO Produced (_vertexId, _sink)
VALUES ('Joel Silver', 'V for Vendetta')
INSERT INTO Produced (_vertexId, _sink)
VALUES ('Joel Silver', 'Speed Racer')
INSERT INTO Produced (_vertexId, _sink)
VALUES ('Lana Wachowski', 'Ninja Assassin')
INSERT INTO Produced (_vertexId, _sink)
VALUES ('Joel Silver', 'Ninja Assassin')
INSERT INTO Produced (_vertexId, _sink)
VALUES ('Lilly Wachowski', 'Ninja Assassin')
INSERT INTO Produced (_vertexId, _sink)
VALUES ('Nancy Meyers', 'Something''s Gotta Give')
DROP TABLE IF EXISTS dbo.Directed
CREATE TABLE dbo.Directed
(
_vertexId varchar(100)
, _sink varchar(100)
, CONSTRAINT PK_DIRECTED
PRIMARY KEY CLUSTERED (_vertexId, _sink)
WITH (IGNORE_DUP_KEY = OFF)
)
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Lana Wachowski', 'The Matrix')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Lilly Wachowski', 'The Matrix')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Lana Wachowski', 'The Matrix Reloaded')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Lilly Wachowski', 'The Matrix Reloaded')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Lana Wachowski', 'The Matrix Revolutions')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Lilly Wachowski', 'The Matrix Revolutions')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Taylor Hackford', 'The Devil''s Advocate')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Rob Reiner', 'A Few Good Men')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Tony Scott', 'Top Gun')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Cameron Crowe', 'Jerry Maguire')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Rob Reiner', 'Stand By Me')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('James L. Brooks', 'As Good as It Gets')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Vincent Ward', 'What Dreams May Come')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Scott Hicks', 'Snow Falling on Cedars')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Nora Ephron', 'You''ve Got Mail')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Nora Ephron', 'Sleepless in Seattle')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('John Patrick Stanley', 'Joe Versus the Volcano')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Rob Reiner', 'When Harry Met Sally')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Tom Hanks', 'That Thing You Do')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Howard Deutch', 'The Replacements')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Werner Herzog', 'RescueDawn')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Mike Nichols', 'The Birdcage')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Clint Eastwood', 'Unforgiven')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Robert Longo', 'Johnny Mnemonic')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Tom Tykwer', 'Cloud Atlas')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Lana Wachowski', 'Cloud Atlas')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Lilly Wachowski', 'Cloud Atlas')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Ron Howard', 'The Da Vinci Code')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('James Marshall', 'V for Vendetta')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Lana Wachowski', 'Speed Racer')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Lilly Wachowski', 'Speed Racer')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('James Marshall', 'Ninja Assassin')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Frank Darabont', 'The Green Mile')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Ron Howard', 'Frost/Nixon')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Danny DeVito', 'Hoffa')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Ron Howard', 'Apollo 13')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Jan de Bont', 'Twister')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Robert Zemeckis', 'Cast Away')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Milos Forman', 'One Flew Over the Cuckoo''s Nest')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Nancy Meyers', 'Something''s Gotta Give')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Chris Columbus', 'Bicentennial Man')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Mike Nichols', 'Charlie Wilson''s War')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Robert Zemeckis', 'The Polar Express')
INSERT INTO Directed (_vertexId, _sink)
VALUES ('Penny Marshall', 'A League of Their Own')
DROP TABLE IF EXISTS dbo.Wrote
CREATE TABLE dbo.Wrote
(
_vertexId varchar(100)
, _sink varchar(100)
, CONSTRAINT PK_WROTE
PRIMARY KEY CLUSTERED (_vertexId, _sink)
WITH (IGNORE_DUP_KEY = OFF)
)
INSERT INTO Wrote (_vertexId, _sink)
VALUES ('Aaron Sorkin', 'A Few Good Men')
INSERT INTO Wrote (_vertexId, _sink)
VALUES ('Jim Cash', 'Top Gun')
INSERT INTO Wrote (_vertexId, _sink)
VALUES ('Cameron Crowe', 'Jerry Maguire')
INSERT INTO Wrote (_vertexId, _sink)
VALUES ('Nora Ephron', 'When Harry Met Sally')
INSERT INTO Wrote (_vertexId, _sink)
VALUES ('David Mitchell', 'Cloud Atlas')
INSERT INTO Wrote (_vertexId, _sink)
VALUES ('Lana Wachowski', 'V for Vendetta')
INSERT INTO Wrote (_vertexId, _sink)
VALUES ('Lilly Wachowski', 'V for Vendetta')
INSERT INTO Wrote (_vertexId, _sink)
VALUES ('Lana Wachowski', 'Speed Racer')
INSERT INTO Wrote (_vertexId, _sink)
VALUES ('Lilly Wachowski', 'Speed Racer')
INSERT INTO Wrote (_vertexId, _sink)
VALUES ('Nancy Meyers', 'Something''s Gotta Give')
DROP TABLE IF EXISTS dbo.Reviewed
CREATE TABLE dbo.Reviewed
(
_vertexId varchar(100)
, _sink varchar(100)
, Summary varchar(MAX)
, Rating int
, CONSTRAINT PK_REVIEWED
PRIMARY KEY CLUSTERED (_vertexId, _sink)
WITH (IGNORE_DUP_KEY = OFF)
)
INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating)
VALUES ('Jessica Thompson', 'Jerry Maguire', 'You had me at Jerry', 92)
INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating)
VALUES ('James Thompson', 'The Replacements', 'The coolest football movie ever', 100)
INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating)
VALUES ('Angela Scope', 'The Replacements', 'Pretty funny at times', 62)
INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating)
VALUES ('Jessica Thompson', 'The Replacements', 'Silly, but fun', 65)
INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating)
VALUES ('Jessica Thompson', 'The Birdcage', 'Slapstick redeemed only by the Robin Williams and Gene Hackman''s stellar performances', 45)
INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating)
VALUES ('Jessica Thompson', 'Unforgiven', 'Dark, but compelling', 85)
INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating)
VALUES ('Jessica Thompson', 'Cloud Atlas', 'An amazing journey', 95)
INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating)
VALUES ('Jessica Thompson', 'The Da Vinci Code', 'A solid romp', 68)
INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating)
VALUES ('James Thompson', 'The Da Vinci Code', 'Fun, but a little far fetched', 65)
DROP TABLE IF EXISTS dbo.Follows
CREATE TABLE dbo.Follows
(
_vertexId varchar(100)
, _sink varchar(100)
, CONSTRAINT PK_FOLLOWS
PRIMARY KEY CLUSTERED (_vertexId, _sink)
WITH (IGNORE_DUP_KEY = OFF)
)
INSERT INTO Follows (_vertexId, _sink)
VALUES ('Paul Blythe', 'Angela Scope')
INSERT INTO Follows (_vertexId, _sink)
VALUES ('Angela Scope', 'Jessica Thompson')
INSERT INTO Follows (_vertexId, _sink)
VALUES ('James Thompson', 'Jessica Thompson')

Просмотреть файл

@ -0,0 +1,202 @@
{
"Nodes": [
{
"Id": "Person",
"Name": "Person",
"IdProperty": {
"PropertyName": "id",
"PropertyType": "System.String"
},
"Properties": [
{
"PropertyName": "Name",
"PropertyType": "System.String"
},
{
"PropertyName": "Born",
"PropertyType": "System.Nullable`1[System.Int32]"
}
]
},
{
"Id": "Movie",
"Name": "Movie",
"IdProperty": {
"PropertyName": "id",
"PropertyType": "System.String"
},
"Properties": [
{
"PropertyName": "Title",
"PropertyType": "System.String"
},
{
"PropertyName": "Tagline",
"PropertyType": "System.String"
},
{
"PropertyName": "Released",
"PropertyType": "System.Int32"
}
]
}
],
"Edges": [
{
"Id": "Person@ACTED_IN@Movie",
"Name": "ACTED_IN",
"FromNode": "Person",
"ToNode": "Movie",
"SourceIdProperty": {
"PropertyName": "_vertexId",
"PropertyType": "System.String"
},
"SinkIdProperty": {
"PropertyName": "_sink",
"PropertyType": "System.String"
},
"Properties": [
{
"PropertyName": "Roles",
"PropertyType": "System.String"
}
]
},
{
"Id": "Person@REVIEWED@Movie",
"Name": "REVIEWED",
"FromNode": "Person",
"ToNode": "Movie",
"SourceIdProperty": {
"PropertyName": "_vertexId",
"PropertyType": "System.String"
},
"SinkIdProperty": {
"PropertyName": "_sink",
"PropertyType": "System.String"
},
"Properties": [
{
"PropertyName": "Summary",
"PropertyType": "System.String"
},
{
"PropertyName": "Rating",
"PropertyType": "System.Int32"
}
]
},
{
"Id": "Person@DIRECTED@Movie",
"Name": "DIRECTED",
"FromNode": "Person",
"ToNode": "Movie",
"SourceIdProperty": {
"PropertyName": "_vertexId",
"PropertyType": "System.String"
},
"SinkIdProperty": {
"PropertyName": "_sink",
"PropertyType": "System.String"
},
"Properties": []
},
{
"Id": "Person@PRODUCED@Movie",
"Name": "PRODUCED",
"FromNode": "Person",
"ToNode": "Movie",
"SourceIdProperty": {
"PropertyName": "_vertexId",
"PropertyType": "System.String"
},
"SinkIdProperty": {
"PropertyName": "_sink",
"PropertyType": "System.String"
},
"Properties": []
},
{
"Id": "Person@WROTE@Movie",
"Name": "WROTE",
"FromNode": "Person",
"ToNode": "Movie",
"SourceIdProperty": {
"PropertyName": "_vertexId",
"PropertyType": "System.String"
},
"SinkIdProperty": {
"PropertyName": "_sink",
"PropertyType": "System.String"
},
"Properties": []
},
{
"Id": "Person@FOLLOWS@Person",
"Name": "FOLLOWS",
"FromNode": "Person",
"ToNode": "Person",
"SourceIdProperty": {
"PropertyName": "_vertexId",
"PropertyType": "System.String"
},
"SinkIdProperty": {
"PropertyName": "_sink",
"PropertyType": "System.String"
},
"Properties": []
}
],
"TableDescriptors": [
{
"EntityId": "Person",
"Properties": [
"Name",
"Born"
],
"TableOrViewName": "[dbo].[Person]"
},
{
"EntityId": "Movie",
"Properties": [
"Title",
"Tagline",
"Released"
],
"TableOrViewName": "[dbo].[Movie]"
},
{
"EntityId": "Person@ACTED_IN@Movie",
"Properties": [],
"TableOrViewName": "[dbo].[ActedIn]"
},
{
"EntityId": "Person@REVIEWED@Movie",
"Properties": [
"Summary",
"Rating"
],
"TableOrViewName": "[dbo].[Reviewed]"
},
{
"EntityId": "Person@DIRECTED@Movie",
"Properties": [],
"TableOrViewName": "[dbo].[Directed]"
},
{
"EntityId": "Person@PRODUCED@Movie",
"Properties": [],
"TableOrViewName": "[dbo].[Produced]"
},
{
"EntityId": "Person@WROTE@Movie",
"Properties": [],
"TableOrViewName": "[dbo].[Wrote]"
},
{
"EntityId": "Person@FOLLOWS@Person",
"Properties": [],
"TableOrViewName": "[dbo].[Follows]"
}
]
}

Просмотреть файл

@ -0,0 +1,509 @@
CREATE (TheMatrix:Movie {id:'The Matrix', Title:'The Matrix', Released:1999, Tagline:'Welcome to the Real World'})
CREATE (Keanu:Person {id:'Keanu Reeves', Name:'Keanu Reeves', Born:1964})
CREATE (Carrie:Person {id:'Carrie-Anne Moss', Name:'Carrie-Anne Moss', Born:1967})
CREATE (Laurence:Person {id:'Laurence Fishburne', Name:'Laurence Fishburne', Born:1961})
CREATE (Hugo:Person {id:'Hugo Weaving', Name:'Hugo Weaving', Born:1960})
CREATE (LillyW:Person {id:'Lilly Wachowski', Name:'Lilly Wachowski', Born:1967})
CREATE (LanaW:Person {id:'Lana Wachowski', Name:'Lana Wachowski', Born:1965})
CREATE (JoelS:Person {id:'Joel Silver', Name:'Joel Silver', Born:1952})
CREATE
(Keanu)-[:ACTED_IN {Roles:['Neo']}]->(TheMatrix),
(Carrie)-[:ACTED_IN {Roles:['Trinity']}]->(TheMatrix),
(Laurence)-[:ACTED_IN {Roles:['Morpheus']}]->(TheMatrix),
(Hugo)-[:ACTED_IN {Roles:['Agent Smith']}]->(TheMatrix),
(LillyW)-[:DIRECTED]->(TheMatrix),
(LanaW)-[:DIRECTED]->(TheMatrix),
(JoelS)-[:PRODUCED]->(TheMatrix)
CREATE (Emil:Person {id:"Emil Eifrem", Name:"Emil Eifrem", Born:1978})
CREATE (Emil)-[:ACTED_IN {Roles:["Emil"]}]->(TheMatrix)
CREATE (TheMatrixReloaded:Movie {id:'The Matrix Reloaded', Title:'The Matrix Reloaded', Released:2003, Tagline:'Free your mind'})
CREATE
(Keanu)-[:ACTED_IN {Roles:['Neo']}]->(TheMatrixReloaded),
(Carrie)-[:ACTED_IN {Roles:['Trinity']}]->(TheMatrixReloaded),
(Laurence)-[:ACTED_IN {Roles:['Morpheus']}]->(TheMatrixReloaded),
(Hugo)-[:ACTED_IN {Roles:['Agent Smith']}]->(TheMatrixReloaded),
(LillyW)-[:DIRECTED]->(TheMatrixReloaded),
(LanaW)-[:DIRECTED]->(TheMatrixReloaded),
(JoelS)-[:PRODUCED]->(TheMatrixReloaded)
CREATE (TheMatrixRevolutions:Movie {id:'The Matrix Revolutions', Title:'The Matrix Revolutions', Released:2003, Tagline:'Everything that has a beginning has an end'})
CREATE
(Keanu)-[:ACTED_IN {Roles:['Neo']}]->(TheMatrixRevolutions),
(Carrie)-[:ACTED_IN {Roles:['Trinity']}]->(TheMatrixRevolutions),
(Laurence)-[:ACTED_IN {Roles:['Morpheus']}]->(TheMatrixRevolutions),
(Hugo)-[:ACTED_IN {Roles:['Agent Smith']}]->(TheMatrixRevolutions),
(LillyW)-[:DIRECTED]->(TheMatrixRevolutions),
(LanaW)-[:DIRECTED]->(TheMatrixRevolutions),
(JoelS)-[:PRODUCED]->(TheMatrixRevolutions)
CREATE (TheDevilsAdvocate:Movie {id:"The Devil's Advocate", Title:"The Devil's Advocate", Released:1997, Tagline:'Evil has its winning ways'})
CREATE (Charlize:Person {id:'Charlize Theron', Name:'Charlize Theron', Born:1975})
CREATE (Al:Person {id:'Al Pacino', Name:'Al Pacino', Born:1940})
CREATE (Taylor:Person {id:'Taylor Hackford', Name:'Taylor Hackford', Born:1944})
CREATE
(Keanu)-[:ACTED_IN {Roles:['Kevin Lomax']}]->(TheDevilsAdvocate),
(Charlize)-[:ACTED_IN {Roles:['Mary Ann Lomax']}]->(TheDevilsAdvocate),
(Al)-[:ACTED_IN {Roles:['John Milton']}]->(TheDevilsAdvocate),
(Taylor)-[:DIRECTED]->(TheDevilsAdvocate)
CREATE (AFewGoodMen:Movie {id:"A Few Good Men", Title:"A Few Good Men", Released:1992, Tagline:"In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at nothing to keep his honor, and one will stop at nothing to find the truth."})
CREATE (TomC:Person {id:'Tom Cruise', Name:'Tom Cruise', Born:1962})
CREATE (JackN:Person {id:'Jack Nicholson', Name:'Jack Nicholson', Born:1937})
CREATE (DemiM:Person {id:'Demi Moore', Name:'Demi Moore', Born:1962})
CREATE (KevinB:Person {id:'Kevin Bacon', Name:'Kevin Bacon', Born:1958})
CREATE (KieferS:Person {id:'Kiefer Sutherland', Name:'Kiefer Sutherland', Born:1966})
CREATE (NoahW:Person {id:'Noah Wyle', Name:'Noah Wyle', Born:1971})
CREATE (CubaG:Person {id:'Cuba Gooding Jr.', Name:'Cuba Gooding Jr.', Born:1968})
CREATE (KevinP:Person {id:'Kevin Pollak', Name:'Kevin Pollak', Born:1957})
CREATE (JTW:Person {id:'J.T. Walsh', Name:'J.T. Walsh', Born:1943})
CREATE (JamesM:Person {id:'James Marshall', Name:'James Marshall', Born:1967})
CREATE (ChristopherG:Person {id:'Christopher Guest', Name:'Christopher Guest', Born:1948})
CREATE (RobR:Person {id:'Rob Reiner', Name:'Rob Reiner', Born:1947})
CREATE (AaronS:Person {id:'Aaron Sorkin', Name:'Aaron Sorkin', Born:1961})
CREATE
(TomC)-[:ACTED_IN {Roles:['Lt. Daniel Kaffee']}]->(AFewGoodMen),
(JackN)-[:ACTED_IN {Roles:['Col. Nathan R. Jessup']}]->(AFewGoodMen),
(DemiM)-[:ACTED_IN {Roles:['Lt. Cdr. JoAnne Galloway']}]->(AFewGoodMen),
(KevinB)-[:ACTED_IN {Roles:['Capt. Jack Ross']}]->(AFewGoodMen),
(KieferS)-[:ACTED_IN {Roles:['Lt. Jonathan Kendrick']}]->(AFewGoodMen),
(NoahW)-[:ACTED_IN {Roles:['Cpl. Jeffrey Barnes']}]->(AFewGoodMen),
(CubaG)-[:ACTED_IN {Roles:['Cpl. Carl Hammaker']}]->(AFewGoodMen),
(KevinP)-[:ACTED_IN {Roles:['Lt. Sam Weinberg']}]->(AFewGoodMen),
(JTW)-[:ACTED_IN {Roles:['Lt. Col. Matthew Andrew Markinson']}]->(AFewGoodMen),
(JamesM)-[:ACTED_IN {Roles:['Pfc. Louden Downey']}]->(AFewGoodMen),
(ChristopherG)-[:ACTED_IN {Roles:['Dr. Stone']}]->(AFewGoodMen),
(AaronS)-[:ACTED_IN {Roles:['Man in Bar']}]->(AFewGoodMen),
(RobR)-[:DIRECTED]->(AFewGoodMen),
(AaronS)-[:WROTE]->(AFewGoodMen)
CREATE (TopGun:Movie {id:"Top Gun", Title:"Top Gun", Released:1986, Tagline:'I feel the need, the need for speed.'})
CREATE (KellyM:Person {id:'Kelly McGillis', Name:'Kelly McGillis', Born:1957})
CREATE (ValK:Person {id:'Val Kilmer', Name:'Val Kilmer', Born:1959})
CREATE (AnthonyE:Person {id:'Anthony Edwards', Name:'Anthony Edwards', Born:1962})
CREATE (TomS:Person {id:'Tom Skerritt', Name:'Tom Skerritt', Born:1933})
CREATE (MegR:Person {id:'Meg Ryan', Name:'Meg Ryan', Born:1961})
CREATE (TonyS:Person {id:'Tony Scott', Name:'Tony Scott', Born:1944})
CREATE (JimC:Person {id:'Jim Cash', Name:'Jim Cash', Born:1941})
CREATE
(TomC)-[:ACTED_IN {Roles:['Maverick']}]->(TopGun),
(KellyM)-[:ACTED_IN {Roles:['Charlie']}]->(TopGun),
(ValK)-[:ACTED_IN {Roles:['Iceman']}]->(TopGun),
(AnthonyE)-[:ACTED_IN {Roles:['Goose']}]->(TopGun),
(TomS)-[:ACTED_IN {Roles:['Viper']}]->(TopGun),
(MegR)-[:ACTED_IN {Roles:['Carole']}]->(TopGun),
(TonyS)-[:DIRECTED]->(TopGun),
(JimC)-[:WROTE]->(TopGun)
CREATE (JerryMaguire:Movie {id:'Jerry Maguire', Title:'Jerry Maguire', Released:2000, Tagline:'The rest of his life begins now.'})
CREATE (ReneeZ:Person {id:'Renee Zellweger', Name:'Renee Zellweger', Born:1969})
CREATE (KellyP:Person {id:'Kelly Preston', Name:'Kelly Preston', Born:1962})
CREATE (JerryO:Person {id:"Jerry O'Connell", Name:"Jerry O'Connell", Born:1974})
CREATE (JayM:Person {id:'Jay Mohr', Name:'Jay Mohr', Born:1970})
CREATE (BonnieH:Person {id:'Bonnie Hunt', Name:'Bonnie Hunt', Born:1961})
CREATE (ReginaK:Person {id:'Regina King', Name:'Regina King', Born:1971})
CREATE (JonathanL:Person {id:'Jonathan Lipnicki', Name:'Jonathan Lipnicki', Born:1996})
CREATE (CameronC:Person {id:'Cameron Crowe', Name:'Cameron Crowe', Born:1957})
CREATE
(TomC)-[:ACTED_IN {Roles:['Jerry Maguire']}]->(JerryMaguire),
(CubaG)-[:ACTED_IN {Roles:['Rod Tidwell']}]->(JerryMaguire),
(ReneeZ)-[:ACTED_IN {Roles:['Dorothy Boyd']}]->(JerryMaguire),
(KellyP)-[:ACTED_IN {Roles:['Avery Bishop']}]->(JerryMaguire),
(JerryO)-[:ACTED_IN {Roles:['Frank Cushman']}]->(JerryMaguire),
(JayM)-[:ACTED_IN {Roles:['Bob Sugar']}]->(JerryMaguire),
(BonnieH)-[:ACTED_IN {Roles:['Laurel Boyd']}]->(JerryMaguire),
(ReginaK)-[:ACTED_IN {Roles:['Marcee Tidwell']}]->(JerryMaguire),
(JonathanL)-[:ACTED_IN {Roles:['Ray Boyd']}]->(JerryMaguire),
(CameronC)-[:DIRECTED]->(JerryMaguire),
(CameronC)-[:PRODUCED]->(JerryMaguire),
(CameronC)-[:WROTE]->(JerryMaguire)
CREATE (StandByMe:Movie {id:"Stand By Me", Title:"Stand By Me", Released:1986, Tagline:"For some, it's the last real taste of innocence, and the first real taste of life. But for everyone, it's the time that memories are made of."})
CREATE (RiverP:Person {id:'River Phoenix', Name:'River Phoenix', Born:1970})
CREATE (CoreyF:Person {id:'Corey Feldman', Name:'Corey Feldman', Born:1971})
CREATE (WilW:Person {id:'Wil Wheaton', Name:'Wil Wheaton', Born:1972})
CREATE (JohnC:Person {id:'John Cusack', Name:'John Cusack', Born:1966})
CREATE (MarshallB:Person {id:'Marshall Bell', Name:'Marshall Bell', Born:1942})
CREATE
(WilW)-[:ACTED_IN {Roles:['Gordie Lachance']}]->(StandByMe),
(RiverP)-[:ACTED_IN {Roles:['Chris Chambers']}]->(StandByMe),
(JerryO)-[:ACTED_IN {Roles:['Vern Tessio']}]->(StandByMe),
(CoreyF)-[:ACTED_IN {Roles:['Teddy Duchamp']}]->(StandByMe),
(JohnC)-[:ACTED_IN {Roles:['Denny Lachance']}]->(StandByMe),
(KieferS)-[:ACTED_IN {Roles:['Ace Merrill']}]->(StandByMe),
(MarshallB)-[:ACTED_IN {Roles:['Mr. Lachance']}]->(StandByMe),
(RobR)-[:DIRECTED]->(StandByMe)
CREATE (AsGoodAsItGets:Movie {id:'As Good as It Gets', Title:'As Good as It Gets', Released:1997, Tagline:'A comedy from the heart that goes for the throat.'})
CREATE (HelenH:Person {id:'Helen Hunt', Name:'Helen Hunt', Born:1963})
CREATE (GregK:Person {id:'Greg Kinnear', Name:'Greg Kinnear', Born:1963})
CREATE (JamesB:Person {id:'James L. Brooks', Name:'James L. Brooks', Born:1940})
CREATE
(JackN)-[:ACTED_IN {Roles:['Melvin Udall']}]->(AsGoodAsItGets),
(HelenH)-[:ACTED_IN {Roles:['Carol Connelly']}]->(AsGoodAsItGets),
(GregK)-[:ACTED_IN {Roles:['Simon Bishop']}]->(AsGoodAsItGets),
(CubaG)-[:ACTED_IN {Roles:['Frank Sachs']}]->(AsGoodAsItGets),
(JamesB)-[:DIRECTED]->(AsGoodAsItGets)
CREATE (WhatDreamsMayCome:Movie {id:'What Dreams May Come', Title:'What Dreams May Come', Released:1998, Tagline:'After life there is more. The end is just the beginning.'})
CREATE (AnnabellaS:Person {id:'Annabella Sciorra', Name:'Annabella Sciorra', Born:1960})
CREATE (MaxS:Person {id:'Max von Sydow', Name:'Max von Sydow', Born:1929})
CREATE (WernerH:Person {id:'Werner Herzog', Name:'Werner Herzog', Born:1942})
CREATE (Robin:Person {id:'Robin Williams', Name:'Robin Williams', Born:1951})
CREATE (VincentW:Person {id:'Vincent Ward', Name:'Vincent Ward', Born:1956})
CREATE
(Robin)-[:ACTED_IN {Roles:['Chris Nielsen']}]->(WhatDreamsMayCome),
(CubaG)-[:ACTED_IN {Roles:['Albert Lewis']}]->(WhatDreamsMayCome),
(AnnabellaS)-[:ACTED_IN {Roles:['Annie Collins-Nielsen']}]->(WhatDreamsMayCome),
(MaxS)-[:ACTED_IN {Roles:['The Tracker']}]->(WhatDreamsMayCome),
(WernerH)-[:ACTED_IN {Roles:['The Face']}]->(WhatDreamsMayCome),
(VincentW)-[:DIRECTED]->(WhatDreamsMayCome)
CREATE (SnowFallingonCedars:Movie {id:'Snow Falling on Cedars', Title:'Snow Falling on Cedars', Released:1999, Tagline:'First loves last. Forever.'})
CREATE (EthanH:Person {id:'Ethan Hawke', Name:'Ethan Hawke', Born:1970})
CREATE (RickY:Person {id:'Rick Yune', Name:'Rick Yune', Born:1971})
CREATE (JamesC:Person {id:'James Cromwell', Name:'James Cromwell', Born:1940})
CREATE (ScottH:Person {id:'Scott Hicks', Name:'Scott Hicks', Born:1953})
CREATE
(EthanH)-[:ACTED_IN {Roles:['Ishmael Chambers']}]->(SnowFallingonCedars),
(RickY)-[:ACTED_IN {Roles:['Kazuo Miyamoto']}]->(SnowFallingonCedars),
(MaxS)-[:ACTED_IN {Roles:['Nels Gudmundsson']}]->(SnowFallingonCedars),
(JamesC)-[:ACTED_IN {Roles:['Judge Fielding']}]->(SnowFallingonCedars),
(ScottH)-[:DIRECTED]->(SnowFallingonCedars)
CREATE (YouveGotMail:Movie {id:"You've Got Mail", Title:"You've Got Mail", Released:1998, Tagline:'At odds in life... in love on-line.'})
CREATE (ParkerP:Person {id:'Parker Posey', Name:'Parker Posey', Born:1968})
CREATE (DaveC:Person {id:'Dave Chappelle', Name:'Dave Chappelle', Born:1973})
CREATE (SteveZ:Person {id:'Steve Zahn', Name:'Steve Zahn', Born:1967})
CREATE (TomH:Person {id:'Tom Hanks', Name:'Tom Hanks', Born:1956})
CREATE (NoraE:Person {id:'Nora Ephron', Name:'Nora Ephron', Born:1941})
CREATE
(TomH)-[:ACTED_IN {Roles:['Joe Fox']}]->(YouveGotMail),
(MegR)-[:ACTED_IN {Roles:['Kathleen Kelly']}]->(YouveGotMail),
(GregK)-[:ACTED_IN {Roles:['Frank Navasky']}]->(YouveGotMail),
(ParkerP)-[:ACTED_IN {Roles:['Patricia Eden']}]->(YouveGotMail),
(DaveC)-[:ACTED_IN {Roles:['Kevin Jackson']}]->(YouveGotMail),
(SteveZ)-[:ACTED_IN {Roles:['George Pappas']}]->(YouveGotMail),
(NoraE)-[:DIRECTED]->(YouveGotMail)
CREATE (SleeplessInSeattle:Movie {id:'Sleepless in Seattle', Title:'Sleepless in Seattle', Released:1993, Tagline:'What if someone you never met, someone you never saw, someone you never knew was the only someone for you?'})
CREATE (RitaW:Person {id:'Rita Wilson', Name:'Rita Wilson', Born:1956})
CREATE (BillPull:Person {id:'Bill Pullman', Name:'Bill Pullman', Born:1953})
CREATE (VictorG:Person {id:'Victor Garber', Name:'Victor Garber', Born:1949})
CREATE (RosieO:Person {id:"Rosie O'Donnell", Name:"Rosie O'Donnell", Born:1962})
CREATE
(TomH)-[:ACTED_IN {Roles:['Sam Baldwin']}]->(SleeplessInSeattle),
(MegR)-[:ACTED_IN {Roles:['Annie Reed']}]->(SleeplessInSeattle),
(RitaW)-[:ACTED_IN {Roles:['Suzy']}]->(SleeplessInSeattle),
(BillPull)-[:ACTED_IN {Roles:['Walter']}]->(SleeplessInSeattle),
(VictorG)-[:ACTED_IN {Roles:['Greg']}]->(SleeplessInSeattle),
(RosieO)-[:ACTED_IN {Roles:['Becky']}]->(SleeplessInSeattle),
(NoraE)-[:DIRECTED]->(SleeplessInSeattle)
CREATE (JoeVersustheVolcano:Movie {id:'Joe Versus the Volcano', Title:'Joe Versus the Volcano', Released:1990, Tagline:'A story of love, lava and burning desire.'})
CREATE (JohnS:Person {id:'John Patrick Stanley', Name:'John Patrick Stanley', Born:1950})
CREATE (Nathan:Person {id:'Nathan Lane', Name:'Nathan Lane', Born:1956})
CREATE
(TomH)-[:ACTED_IN {Roles:['Joe Banks']}]->(JoeVersustheVolcano),
(MegR)-[:ACTED_IN {Roles:['DeDe', 'Angelica Graynamore', 'Patricia Graynamore']}]->(JoeVersustheVolcano),
(Nathan)-[:ACTED_IN {Roles:['Baw']}]->(JoeVersustheVolcano),
(JohnS)-[:DIRECTED]->(JoeVersustheVolcano)
CREATE (WhenHarryMetSally:Movie {id:'When Harry Met Sally', Title:'When Harry Met Sally', Released:1998, Tagline:'At odds in life... in love on-line.'})
CREATE (BillyC:Person {id:'Billy Crystal', Name:'Billy Crystal', Born:1948})
CREATE (CarrieF:Person {id:'Carrie Fisher', Name:'Carrie Fisher', Born:1956})
CREATE (BrunoK:Person {id:'Bruno Kirby', Name:'Bruno Kirby', Born:1949})
CREATE
(BillyC)-[:ACTED_IN {Roles:['Harry Burns']}]->(WhenHarryMetSally),
(MegR)-[:ACTED_IN {Roles:['Sally Albright']}]->(WhenHarryMetSally),
(CarrieF)-[:ACTED_IN {Roles:['Marie']}]->(WhenHarryMetSally),
(BrunoK)-[:ACTED_IN {Roles:['Jess']}]->(WhenHarryMetSally),
(RobR)-[:DIRECTED]->(WhenHarryMetSally),
(RobR)-[:PRODUCED]->(WhenHarryMetSally),
(NoraE)-[:PRODUCED]->(WhenHarryMetSally),
(NoraE)-[:WROTE]->(WhenHarryMetSally)
CREATE (ThatThingYouDo:Movie {id:'That Thing You Do', Title:'That Thing You Do', Released:1996, Tagline:'In every life there comes a time when that thing you dream becomes that thing you do'})
CREATE (LivT:Person {id:'Liv Tyler', Name:'Liv Tyler', Born:1977})
CREATE
(TomH)-[:ACTED_IN {Roles:['Mr. White']}]->(ThatThingYouDo),
(LivT)-[:ACTED_IN {Roles:['Faye Dolan']}]->(ThatThingYouDo),
(Charlize)-[:ACTED_IN {Roles:['Tina']}]->(ThatThingYouDo),
(TomH)-[:DIRECTED]->(ThatThingYouDo)
CREATE (TheReplacements:Movie {id:'The Replacements', Title:'The Replacements', Released:2000, Tagline:'Pain heals, Chicks dig scars... Glory lasts forever'})
CREATE (Brooke:Person {id:'Brooke Langton', Name:'Brooke Langton', Born:1970})
CREATE (Gene:Person {id:'Gene Hackman', Name:'Gene Hackman', Born:1930})
CREATE (Orlando:Person {id:'Orlando Jones', Name:'Orlando Jones', Born:1968})
CREATE (Howard:Person {id:'Howard Deutch', Name:'Howard Deutch', Born:1950})
CREATE
(Keanu)-[:ACTED_IN {Roles:['Shane Falco']}]->(TheReplacements),
(Brooke)-[:ACTED_IN {Roles:['Annabelle Farrell']}]->(TheReplacements),
(Gene)-[:ACTED_IN {Roles:['Jimmy McGinty']}]->(TheReplacements),
(Orlando)-[:ACTED_IN {Roles:['Clifford Franklin']}]->(TheReplacements),
(Howard)-[:DIRECTED]->(TheReplacements)
CREATE (RescueDawn:Movie {id:'RescueDawn', Title:'RescueDawn', Released:2006, Tagline:"Based on the extraordinary true story of one man's fight for freedom"})
CREATE (ChristianB:Person {id:'Christian Bale', Name:'Christian Bale', Born:1974})
CREATE (ZachG:Person {id:'Zach Grenier', Name:'Zach Grenier', Born:1954})
CREATE
(MarshallB)-[:ACTED_IN {Roles:['Admiral']}]->(RescueDawn),
(ChristianB)-[:ACTED_IN {Roles:['Dieter Dengler']}]->(RescueDawn),
(ZachG)-[:ACTED_IN {Roles:['Squad Leader']}]->(RescueDawn),
(SteveZ)-[:ACTED_IN {Roles:['Duane']}]->(RescueDawn),
(WernerH)-[:DIRECTED]->(RescueDawn)
CREATE (TheBirdcage:Movie {id:'The Birdcage', Title:'The Birdcage', Released:1996, Tagline:'Come as you are'})
CREATE (MikeN:Person {id:'Mike Nichols', Name:'Mike Nichols', Born:1931})
CREATE
(Robin)-[:ACTED_IN {Roles:['Armand Goldman']}]->(TheBirdcage),
(Nathan)-[:ACTED_IN {Roles:['Albert Goldman']}]->(TheBirdcage),
(Gene)-[:ACTED_IN {Roles:['Sen. Kevin Keeley']}]->(TheBirdcage),
(MikeN)-[:DIRECTED]->(TheBirdcage)
CREATE (Unforgiven:Movie {id:'Unforgiven', Title:'Unforgiven', Released:1992, Tagline:"It's a hell of a thing, killing a man"})
CREATE (RichardH:Person {id:'Richard Harris', Name:'Richard Harris', Born:1930})
CREATE (ClintE:Person {id:'Clint Eastwood', Name:'Clint Eastwood', Born:1930})
CREATE
(RichardH)-[:ACTED_IN {Roles:['English Bob']}]->(Unforgiven),
(ClintE)-[:ACTED_IN {Roles:['Bill Munny']}]->(Unforgiven),
(Gene)-[:ACTED_IN {Roles:['Little Bill Daggett']}]->(Unforgiven),
(ClintE)-[:DIRECTED]->(Unforgiven)
CREATE (JohnnyMnemonic:Movie {id:'Johnny Mnemonic', Title:'Johnny Mnemonic', Released:1995, Tagline:'The hottest data on earth. In the coolest head in town'})
CREATE (Takeshi:Person {id:'Takeshi Kitano', Name:'Takeshi Kitano', Born:1947})
CREATE (Dina:Person {id:'Dina Meyer', Name:'Dina Meyer', Born:1968})
CREATE (IceT:Person {id:'Ice-T', Name:'Ice-T', Born:1958})
CREATE (RobertL:Person {id:'Robert Longo', Name:'Robert Longo', Born:1953})
CREATE
(Keanu)-[:ACTED_IN {Roles:['Johnny Mnemonic']}]->(JohnnyMnemonic),
(Takeshi)-[:ACTED_IN {Roles:['Takahashi']}]->(JohnnyMnemonic),
(Dina)-[:ACTED_IN {Roles:['Jane']}]->(JohnnyMnemonic),
(IceT)-[:ACTED_IN {Roles:['J-Bone']}]->(JohnnyMnemonic),
(RobertL)-[:DIRECTED]->(JohnnyMnemonic)
CREATE (CloudAtlas:Movie {id:'Cloud Atlas', Title:'Cloud Atlas', Released:2012, Tagline:'Everything is connected'})
CREATE (HalleB:Person {id:'Halle Berry', Name:'Halle Berry', Born:1966})
CREATE (JimB:Person {id:'Jim Broadbent', Name:'Jim Broadbent', Born:1949})
CREATE (TomT:Person {id:'Tom Tykwer', Name:'Tom Tykwer', Born:1965})
CREATE (DavidMitchell:Person {id:'David Mitchell', Name:'David Mitchell', Born:1969})
CREATE (StefanArndt:Person {id:'Stefan Arndt', Name:'Stefan Arndt', Born:1961})
CREATE
(TomH)-[:ACTED_IN {Roles:['Zachry', 'Dr. Henry Goose', 'Isaac Sachs', 'Dermot Hoggins']}]->(CloudAtlas),
(Hugo)-[:ACTED_IN {Roles:['Bill Smoke', 'Haskell Moore', 'Tadeusz Kesselring', 'Nurse Noakes', 'Boardman Mephi', 'Old Georgie']}]->(CloudAtlas),
(HalleB)-[:ACTED_IN {Roles:['Luisa Rey', 'Jocasta Ayrs', 'Ovid', 'Meronym']}]->(CloudAtlas),
(JimB)-[:ACTED_IN {Roles:['Vyvyan Ayrs', 'Captain Molyneux', 'Timothy Cavendish']}]->(CloudAtlas),
(TomT)-[:DIRECTED]->(CloudAtlas),
(LillyW)-[:DIRECTED]->(CloudAtlas),
(LanaW)-[:DIRECTED]->(CloudAtlas),
(DavidMitchell)-[:WROTE]->(CloudAtlas),
(StefanArndt)-[:PRODUCED]->(CloudAtlas)
CREATE (TheDaVinciCode:Movie {id:'The Da Vinci Code', Title:'The Da Vinci Code', Released:2006, Tagline:'Break The Codes'})
CREATE (IanM:Person {id:'Ian McKellen', Name:'Ian McKellen', Born:1939})
CREATE (AudreyT:Person {id:'Audrey Tautou', Name:'Audrey Tautou', Born:1976})
CREATE (PaulB:Person {id:'Paul Bettany', Name:'Paul Bettany', Born:1971})
CREATE (RonH:Person {id:'Ron Howard', Name:'Ron Howard', Born:1954})
CREATE
(TomH)-[:ACTED_IN {Roles:['Dr. Robert Langdon']}]->(TheDaVinciCode),
(IanM)-[:ACTED_IN {Roles:['Sir Leight Teabing']}]->(TheDaVinciCode),
(AudreyT)-[:ACTED_IN {Roles:['Sophie Neveu']}]->(TheDaVinciCode),
(PaulB)-[:ACTED_IN {Roles:['Silas']}]->(TheDaVinciCode),
(RonH)-[:DIRECTED]->(TheDaVinciCode)
CREATE (VforVendetta:Movie {id:'V for Vendetta', Title:'V for Vendetta', Released:2006, Tagline:'Freedom! Forever!'})
CREATE (NatalieP:Person {id:'Natalie Portman', Name:'Natalie Portman', Born:1981})
CREATE (StephenR:Person {id:'Stephen Rea', Name:'Stephen Rea', Born:1946})
CREATE (JohnH:Person {id:'John Hurt', Name:'John Hurt', Born:1940})
CREATE (BenM:Person {Name: 'Ben Miles', Born:1967})
CREATE
(Hugo)-[:ACTED_IN {Roles:['V']}]->(VforVendetta),
(NatalieP)-[:ACTED_IN {Roles:['Evey Hammond']}]->(VforVendetta),
(StephenR)-[:ACTED_IN {Roles:['Eric Finch']}]->(VforVendetta),
(JohnH)-[:ACTED_IN {Roles:['High Chancellor Adam Sutler']}]->(VforVendetta),
(BenM)-[:ACTED_IN {Roles:['Dascomb']}]->(VforVendetta),
(JamesM)-[:DIRECTED]->(VforVendetta),
(LillyW)-[:PRODUCED]->(VforVendetta),
(LanaW)-[:PRODUCED]->(VforVendetta),
(JoelS)-[:PRODUCED]->(VforVendetta),
(LillyW)-[:WROTE]->(VforVendetta),
(LanaW)-[:WROTE]->(VforVendetta)
CREATE (SpeedRacer:Movie {id:'Speed Racer', Title:'Speed Racer', Released:2008, Tagline:'Speed has no limits'})
CREATE (EmileH:Person {id:'Emile Hirsch', Name:'Emile Hirsch', Born:1985})
CREATE (JohnG:Person {id:'John Goodman', Name:'John Goodman', Born:1960})
CREATE (SusanS:Person {id:'Susan Sarandon', Name:'Susan Sarandon', Born:1946})
CREATE (MatthewF:Person {id:'Matthew Fox', Name:'Matthew Fox', Born:1966})
CREATE (ChristinaR:Person {id:'Christina Ricci', Name:'Christina Ricci', Born:1980})
CREATE (Rain:Person {id:'Rain', Name:'Rain', Born:1982})
CREATE
(EmileH)-[:ACTED_IN {Roles:['Speed Racer']}]->(SpeedRacer),
(JohnG)-[:ACTED_IN {Roles:['Pops']}]->(SpeedRacer),
(SusanS)-[:ACTED_IN {Roles:['Mom']}]->(SpeedRacer),
(MatthewF)-[:ACTED_IN {Roles:['Racer X']}]->(SpeedRacer),
(ChristinaR)-[:ACTED_IN {Roles:['Trixie']}]->(SpeedRacer),
(Rain)-[:ACTED_IN {Roles:['Taejo Togokahn']}]->(SpeedRacer),
(BenM)-[:ACTED_IN {Roles:['Cass Jones']}]->(SpeedRacer),
(LillyW)-[:DIRECTED]->(SpeedRacer),
(LanaW)-[:DIRECTED]->(SpeedRacer),
(LillyW)-[:WROTE]->(SpeedRacer),
(LanaW)-[:WROTE]->(SpeedRacer),
(JoelS)-[:PRODUCED]->(SpeedRacer)
CREATE (NinjaAssassin:Movie {id:'Ninja Assassin', Title:'Ninja Assassin', Released:2009, Tagline:'Prepare to enter a secret world of assassins'})
CREATE (NaomieH:Person {id:'Naomie Harris', Name:'Naomie Harris'})
CREATE
(Rain)-[:ACTED_IN {Roles:['Raizo']}]->(NinjaAssassin),
(NaomieH)-[:ACTED_IN {Roles:['Mika Coretti']}]->(NinjaAssassin),
(RickY)-[:ACTED_IN {Roles:['Takeshi']}]->(NinjaAssassin),
(BenM)-[:ACTED_IN {Roles:['Ryan Maslow']}]->(NinjaAssassin),
(JamesM)-[:DIRECTED]->(NinjaAssassin),
(LillyW)-[:PRODUCED]->(NinjaAssassin),
(LanaW)-[:PRODUCED]->(NinjaAssassin),
(JoelS)-[:PRODUCED]->(NinjaAssassin)
CREATE (TheGreenMile:Movie {id:'The Green Mile', Title:'The Green Mile', Released:1999, Tagline:"Walk a mile you'll never forget."})
CREATE (MichaelD:Person {id:'Michael Clarke Duncan', Name:'Michael Clarke Duncan', Born:1957})
CREATE (DavidM:Person {id:'David Morse', Name:'David Morse', Born:1953})
CREATE (SamR:Person {id:'Sam Rockwell', Name:'Sam Rockwell', Born:1968})
CREATE (GaryS:Person {id:'Gary Sinise', Name:'Gary Sinise', Born:1955})
CREATE (PatriciaC:Person {id:'Patricia Clarkson', Name:'Patricia Clarkson', Born:1959})
CREATE (FrankD:Person {id:'Frank Darabont', Name:'Frank Darabont', Born:1959})
CREATE
(TomH)-[:ACTED_IN {Roles:['Paul Edgecomb']}]->(TheGreenMile),
(MichaelD)-[:ACTED_IN {Roles:['John Coffey']}]->(TheGreenMile),
(DavidM)-[:ACTED_IN {Roles:['Brutus "Brutal" Howell']}]->(TheGreenMile),
(BonnieH)-[:ACTED_IN {Roles:['Jan Edgecomb']}]->(TheGreenMile),
(JamesC)-[:ACTED_IN {Roles:['Warden Hal Moores']}]->(TheGreenMile),
(SamR)-[:ACTED_IN {Roles:['"Wild Bill" Wharton']}]->(TheGreenMile),
(GaryS)-[:ACTED_IN {Roles:['Burt Hammersmith']}]->(TheGreenMile),
(PatriciaC)-[:ACTED_IN {Roles:['Melinda Moores']}]->(TheGreenMile),
(FrankD)-[:DIRECTED]->(TheGreenMile)
CREATE (FrostNixon:Movie {id:'Frost/Nixon', Title:'Frost/Nixon', Released:2008, Tagline:'400 million people were waiting for the truth.'})
CREATE (FrankL:Person {id:'Frank Langella', Name:'Frank Langella', Born:1938})
CREATE (MichaelS:Person {id:'Michael Sheen', Name:'Michael Sheen', Born:1969})
CREATE (OliverP:Person {id:'Oliver Platt', Name:'Oliver Platt', Born:1960})
CREATE
(FrankL)-[:ACTED_IN {Roles:['Richard Nixon']}]->(FrostNixon),
(MichaelS)-[:ACTED_IN {Roles:['David Frost']}]->(FrostNixon),
(KevinB)-[:ACTED_IN {Roles:['Jack Brennan']}]->(FrostNixon),
(OliverP)-[:ACTED_IN {Roles:['Bob Zelnick']}]->(FrostNixon),
(SamR)-[:ACTED_IN {Roles:['James Reston, Jr.']}]->(FrostNixon),
(RonH)-[:DIRECTED]->(FrostNixon)
CREATE (Hoffa:Movie {id:'Hoffa', Title:'Hoffa', Released:1992, Tagline:"He didn't want law. He wanted justice."})
CREATE (DannyD:Person {id:'Danny DeVito', Name:'Danny DeVito', Born:1944})
CREATE (JohnR:Person {id:'John C. Reilly', Name:'John C. Reilly', Born:1965})
CREATE
(JackN)-[:ACTED_IN {Roles:['Hoffa']}]->(Hoffa),
(DannyD)-[:ACTED_IN {Roles:['Robert "Bobby" Ciaro']}]->(Hoffa),
(JTW)-[:ACTED_IN {Roles:['Frank Fitzsimmons']}]->(Hoffa),
(JohnR)-[:ACTED_IN {Roles:['Peter "Pete" Connelly']}]->(Hoffa),
(DannyD)-[:DIRECTED]->(Hoffa)
CREATE (Apollo13:Movie {id:'Apollo 13', Title:'Apollo 13', Released:1995, Tagline:'Houston, we have a problem.'})
CREATE (EdH:Person {id:'Ed Harris', Name:'Ed Harris', Born:1950})
CREATE (BillPax:Person {id:'Bill Paxton', Name:'Bill Paxton', Born:1955})
CREATE
(TomH)-[:ACTED_IN {Roles:['Jim Lovell']}]->(Apollo13),
(KevinB)-[:ACTED_IN {Roles:['Jack Swigert']}]->(Apollo13),
(EdH)-[:ACTED_IN {Roles:['Gene Kranz']}]->(Apollo13),
(BillPax)-[:ACTED_IN {Roles:['Fred Haise']}]->(Apollo13),
(GaryS)-[:ACTED_IN {Roles:['Ken Mattingly']}]->(Apollo13),
(RonH)-[:DIRECTED]->(Apollo13)
CREATE (Twister:Movie {id:'Twister', Title:'Twister', Released:1996, Tagline:"Don't Breathe. Don't Look Back."})
CREATE (PhilipH:Person {id:'Philip Seymour Hoffman', Name:'Philip Seymour Hoffman', Born:1967})
CREATE (JanB:Person {id:'Jan de Bont', Name:'Jan de Bont', Born:1943})
CREATE
(BillPax)-[:ACTED_IN {Roles:['Bill Harding']}]->(Twister),
(HelenH)-[:ACTED_IN {Roles:['Dr. Jo Harding']}]->(Twister),
(ZachG)-[:ACTED_IN {Roles:['Eddie']}]->(Twister),
(PhilipH)-[:ACTED_IN {Roles:['Dustin "Dusty" Davis']}]->(Twister),
(JanB)-[:DIRECTED]->(Twister)
CREATE (CastAway:Movie {id:'Cast Away', Title:'Cast Away', Released:2000, Tagline:'At the edge of the world, his journey begins.'})
CREATE (RobertZ:Person {id:'Robert Zemeckis', Name:'Robert Zemeckis', Born:1951})
CREATE
(TomH)-[:ACTED_IN {Roles:['Chuck Noland']}]->(CastAway),
(HelenH)-[:ACTED_IN {Roles:['Kelly Frears']}]->(CastAway),
(RobertZ)-[:DIRECTED]->(CastAway)
CREATE (OneFlewOvertheCuckoosNest:Movie {id:"One Flew Over the Cuckoo's Nest", Title:"One Flew Over the Cuckoo's Nest", Released:1975, Tagline:"If he's crazy, what does that make you?"})
CREATE (MilosF:Person {id:'Milos Forman', Name:'Milos Forman', Born:1932})
CREATE
(JackN)-[:ACTED_IN {Roles:['Randle McMurphy']}]->(OneFlewOvertheCuckoosNest),
(DannyD)-[:ACTED_IN {Roles:['Martini']}]->(OneFlewOvertheCuckoosNest),
(MilosF)-[:DIRECTED]->(OneFlewOvertheCuckoosNest)
CREATE (SomethingsGottaGive:Movie {id:"Something's Gotta Give", Title:"Something's Gotta Give", Released:2003})
CREATE (DianeK:Person {id:'Diane Keaton', Name:'Diane Keaton', Born:1946})
CREATE (NancyM:Person {id:'Nancy Meyers', Name:'Nancy Meyers', Born:1949})
CREATE
(JackN)-[:ACTED_IN {Roles:['Harry Sanborn']}]->(SomethingsGottaGive),
(DianeK)-[:ACTED_IN {Roles:['Erica Barry']}]->(SomethingsGottaGive),
(Keanu)-[:ACTED_IN {Roles:['Julian Mercer']}]->(SomethingsGottaGive),
(NancyM)-[:DIRECTED]->(SomethingsGottaGive),
(NancyM)-[:PRODUCED]->(SomethingsGottaGive),
(NancyM)-[:WROTE]->(SomethingsGottaGive)
CREATE (BicentennialMan:Movie {id:'Bicentennial Man', Title:'Bicentennial Man', Released:1999, Tagline:"One robot's 200 year journey to become an ordinary man."})
CREATE (ChrisC:Person {id:'Chris Columbus', Name:'Chris Columbus', Born:1958})
CREATE
(Robin)-[:ACTED_IN {Roles:['Andrew Marin']}]->(BicentennialMan),
(OliverP)-[:ACTED_IN {Roles:['Rupert Burns']}]->(BicentennialMan),
(ChrisC)-[:DIRECTED]->(BicentennialMan)
CREATE (CharlieWilsonsWar:Movie {id:"Charlie Wilson's War", Title:"Charlie Wilson's War", Released:2007, Tagline:"A stiff drink. A little mascara. A lot of nerve. Who said they couldn't bring down the Soviet empire."})
CREATE (JuliaR:Person {id:'Julia Roberts', Name:'Julia Roberts', Born:1967})
CREATE
(TomH)-[:ACTED_IN {Roles:['Rep. Charlie Wilson']}]->(CharlieWilsonsWar),
(JuliaR)-[:ACTED_IN {Roles:['Joanne Herring']}]->(CharlieWilsonsWar),
(PhilipH)-[:ACTED_IN {Roles:['Gust Avrakotos']}]->(CharlieWilsonsWar),
(MikeN)-[:DIRECTED]->(CharlieWilsonsWar)
CREATE (ThePolarExpress:Movie {id:'The Polar Express', Title:'The Polar Express', Released:2004, Tagline:'This Holiday Season… Believe'})
CREATE
(TomH)-[:ACTED_IN {Roles:['Hero Boy', 'Father', 'Conductor', 'Hobo', 'Scrooge', 'Santa Claus']}]->(ThePolarExpress),
(RobertZ)-[:DIRECTED]->(ThePolarExpress)
CREATE (ALeagueofTheirOwn:Movie {id:'A League of Their Own', Title:'A League of Their Own', Released:1992, Tagline:'Once in a lifetime you get a chance to do something different.'})
CREATE (Madonna:Person {id:'Madonna', Name:'Madonna', Born:1954})
CREATE (GeenaD:Person {id:'Geena Davis', Name:'Geena Davis', Born:1956})
CREATE (LoriP:Person {id:'Lori Petty', Name:'Lori Petty', Born:1963})
CREATE (PennyM:Person {id:'Penny Marshall', Name:'Penny Marshall', Born:1943})
CREATE
(TomH)-[:ACTED_IN {Roles:['Jimmy Dugan']}]->(ALeagueofTheirOwn),
(GeenaD)-[:ACTED_IN {Roles:['Dottie Hinson']}]->(ALeagueofTheirOwn),
(LoriP)-[:ACTED_IN {Roles:['Kit Keller']}]->(ALeagueofTheirOwn),
(RosieO)-[:ACTED_IN {Roles:['Doris Murphy']}]->(ALeagueofTheirOwn),
(Madonna)-[:ACTED_IN {Roles:['"All the Way" Mae Mordabito']}]->(ALeagueofTheirOwn),
(BillPax)-[:ACTED_IN {Roles:['Bob Hinson']}]->(ALeagueofTheirOwn),
(PennyM)-[:DIRECTED]->(ALeagueofTheirOwn)
CREATE (PaulBlythe:Person {id:'Paul Blythe', Name:'Paul Blythe'})
CREATE (AngelaScope:Person {id:'Angela Scope', Name:'Angela Scope'})
CREATE (JessicaThompson:Person {id:'Jessica Thompson', Name:'Jessica Thompson'})
CREATE (JamesThompson:Person {id:'James Thompson', Name:'James Thompson'})
CREATE
(JamesThompson)-[:FOLLOWS]->(JessicaThompson),
(AngelaScope)-[:FOLLOWS]->(JessicaThompson),
(PaulBlythe)-[:FOLLOWS]->(AngelaScope)
CREATE
(JessicaThompson)-[:REVIEWED {Summary:'An amazing journey', Rating:95}]->(CloudAtlas),
(JessicaThompson)-[:REVIEWED {Summary:'Silly, but fun', Rating:65}]->(TheReplacements),
(JamesThompson)-[:REVIEWED {Summary:'The coolest football movie ever', Rating:100}]->(TheReplacements),
(AngelaScope)-[:REVIEWED {Summary:'Pretty funny at times', Rating:62}]->(TheReplacements),
(JessicaThompson)-[:REVIEWED {Summary:'Dark, but compelling', Rating:85}]->(Unforgiven),
(JessicaThompson)-[:REVIEWED {Summary:"Slapstick redeemed only by the Robin Williams and Gene Hackman's stellar performances", Rating:45}]->(TheBirdcage),
(JessicaThompson)-[:REVIEWED {Summary:'A solid romp', Rating:68}]->(TheDaVinciCode),
(JamesThompson)-[:REVIEWED {Summary:'Fun, but a little far fetched', Rating:65}]->(TheDaVinciCode),
(JessicaThompson)-[:REVIEWED {Summary:'You had me at Jerry', Rating:92}]->(JerryMaguire)
WITH TomH as a
MATCH (a)-[:ACTED_IN]->(m)<-[:DIRECTED]-(d) RETURN a,m,d LIMIT 10
;

Просмотреть файл

@ -0,0 +1 @@
.results[0] | { cols: .columns, rows: [.data[].row | {a: .[0], b: .[1], c: .[2] | join("|")} ] } | {cols: .cols, rows: [.rows[] | [.a, .b, .c]]} | .cols, .rows[] | @csv

Просмотреть файл

@ -0,0 +1,12 @@
{
"appSettings": {
"createLocalDockerImages": true,
"neo4jHost": "localhost",
"neo4jPort": 10087,
"neo4jUser": "neo4j",
"neo4jPassword": "test",
"sqlHost": "localhost",
"sqlPort": 10033,
"sqlPassword": "AVeryStrong!123TestPassword"
}
}

Просмотреть файл

@ -0,0 +1,271 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System.Diagnostics;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using openCypherTranspiler.Common.Logging;
using openCypherTranspiler.openCypherParser.Common;
using openCypherTranspiler.openCypherParser.AST;
using openCypherTranspiler.CommonTest;
using openCypherTranspiler.Common.Exceptions;
namespace openCypherTranspiler.openCypherParser.Test
{
/// <summary>
/// Tests for OpenCypherParser (openCypher ANTLR4 Parser + AST builder)
/// </summary>
[TestClass]
public class OpenCypherParserTest
{
private readonly ILoggable _logger = new TestLogger();
private QueryTreeNode RunQueryAndDumpTree(string cypherQueryText)
{
var queryNode = OpenCypherParser.Parse(cypherQueryText, _logger);
var tree = queryNode.DumpTree();
Debug.WriteLine(tree);
return queryNode;
}
[TestMethod]
public void BasicParsingTest()
{
var tree = RunQueryAndDumpTree(@"
MATCH (person:Person)-[r:KNOWS]->(friend:Person)
WITH toFloat(r.score + r.score_delta) AS score2, friend.Name, person.level AS number
WHERE friend.Name='bnitta' OR (person.number >= 1 AND person.number <= 10)
RETURN sum(score2), avg(score2+1) AS scoreShift1
"
);
// TODO: structural verifications
Assert.IsNotNull(tree);
}
[TestMethod]
public void BasicExpressionParsingTest()
{
var tree = RunQueryAndDumpTree(@"
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE (p.Name = 'Meg Ryan' OR p.Name = 'Tom Hanks') AND m.Title = 'Apollo 13'
RETURN m.Title AS Title, p.Name AS Name
"
);
var expressionParsed = tree.GetChildrenOfType<QueryExpressionBinary>();
Assert.IsNotNull(tree.GetChildrenOfType<QueryExpressionBinary>().Count() == 2);
Assert.IsNotNull(tree.GetChildrenOfType<QueryExpressionValue>().Any(expr => expr.StringValue == "Meg Ryan"));
Assert.IsNotNull(tree.GetChildrenOfType<QueryExpressionValue>().Any(expr => expr.StringValue == "Tom Hanks"));
Assert.IsNotNull(tree.GetChildrenOfType<QueryExpressionValue>().Any(expr => expr.StringValue == "Apollo 13"));
}
[TestMethod]
public void MatchPatternAdvancedTest()
{
{
// multiple matches
var tree = RunQueryAndDumpTree(@"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
MATCH (p)-[d:DIRECTED]->(m)
MATCH (p)-[a]->(m2:Movie)
RETURN p.Name, m.Title
"
);
// TODO: structural verifications
Assert.IsNotNull(tree);
}
{
// piped queries
var tree = RunQueryAndDumpTree(@"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WITH p, m
MATCH (p)-[d:DIRECTED]->(m)
RETURN p.Name, m.Title
"
);
// TODO: structural verifications
Assert.IsNotNull(tree);
}
{
// optional match
var tree = RunQueryAndDumpTree(@"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
OPTIONAL MATCH (p)-[d:DIRECTED]->(m)
RETURN p.Name, m.Title
"
);
// TODO: structural verifications
Assert.IsNotNull(tree);
}
{
// match followed by local where
var tree = RunQueryAndDumpTree(@"
match (p:Person)
where p.Name = 'Tom Hanks'
optional match (p)-[:ACTED_IN]-(m:Movie)
with p, m
where p.Name = 'Tom Hanks'
return p.Name, m.Title
"
);
// TODO: structural verifications
Assert.IsNotNull(tree);
}
{
// optional match case 2: the second subquery is optional
var tree = RunQueryAndDumpTree(@"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WITH p, m
OPTIONAL MATCH (p)-[d:DIRECTED]->(m)
RETURN p.Name, m.Title
"
);
// TODO: structural verifications
Assert.IsNotNull(tree);
}
}
[TestMethod]
public void OperatorTest()
{
var tree = RunQueryAndDumpTree(@"
MATCH (p:Person)
WHERE p.Name in ['Tom Hanks', 'Meg Ryan']
RETURN p.Name as Name
"
);
Assert.IsNotNull(tree);
var expressionParsed = tree.GetChildrenOfType<QueryExpressionBinary>();
Assert.IsTrue(expressionParsed.Any(expr => expr.Operator.Name == BinaryOperator.IN));
Assert.IsTrue(tree.GetChildrenOfType<QueryExpressionList>().Any(expr => expr.ExpressionList.Count == 2));
}
[TestMethod]
public void StringFunctionTest()
{
var tree = RunQueryAndDumpTree(@"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WHERE p.Name STARTS WITH 'Tom' AND (m.Title CONTAINS '13' OR m.Title ENDS WITH 'Mail')
RETURN toUpper(p.Name) as NameCapital, toLower(m.Title) as TitleLC
"
);
Assert.IsNotNull(tree);
Assert.IsTrue(tree.GetChildrenOfType<QueryExpressionFunction>().Count() == 5);
Assert.IsTrue(tree.GetChildrenOfType<QueryExpressionFunction>().Any(expr => expr.Function.FunctionName == Function.StringContains));
Assert.IsTrue(tree.GetChildrenOfType<QueryExpressionFunction>().Any(expr => expr.Function.FunctionName == Function.StringStartsWith));
Assert.IsTrue(tree.GetChildrenOfType<QueryExpressionFunction>().Any(expr => expr.Function.FunctionName == Function.StringEndsWith));
Assert.IsTrue(tree.GetChildrenOfType<QueryExpressionFunction>().Any(expr => expr.Function.FunctionName == Function.StringToUpper));
Assert.IsTrue(tree.GetChildrenOfType<QueryExpressionFunction>().Any(expr => expr.Function.FunctionName == Function.StringToLower));
}
[TestMethod]
public void OtherWeirdSyntaxTest()
{
{
// reuse the same alias in piped query. the second alias is a new alias
// in below case, m in first match is not the m in second match due to WITH in between
// the query will return all folks who acted in any movie and directed any movie as well, but
// not necessarily the same movie
var tree = RunQueryAndDumpTree(@"
MATCH (p:Person)-[a:ACTED_IN]->(m:Movie)
WITH p, m.Title as ActedMovieTitle
MATCH (p)-[d:DIRECTED]->(m:Movie)
RETURN p.Name, m.Title AS DirectedMovieTitle, ActedMovieTitle
"
);
// TODO: structural verifications
Assert.IsNotNull(tree);
}
}
[TestMethod]
public void NegativeTest()
{
{
// duplicate returned names
var expectedExceptionThrown = false;
try
{
var tree = RunQueryAndDumpTree(@"
MATCH (p:Person)
RETURN p.Name, p.Name
"
);
}
catch (TranspilerSyntaxErrorException)
{
expectedExceptionThrown = true;
}
Assert.IsTrue(expectedExceptionThrown);
}
{
//Node/Edge attached with properties. Not supported
var expectedExceptionThrown = false;
try
{
var tree = RunQueryAndDumpTree(@"
MATCH (person:Person {name:'jerrylia'})-[r:KNOWS]->(friend:Person)
WITH toFloat(r.score + r.score_delta) AS score2
WHERE friend.Name='bnitta'
RETURN sum(score2), avg(score2+1) AS scoreShift1
"
);
}
catch (TranspilerNotSupportedException)
{
expectedExceptionThrown = true;
}
Assert.IsTrue(expectedExceptionThrown);
}
{
// match after optional match
var expectedExceptionThrown = false;
try
{
var tree = RunQueryAndDumpTree(@"
match (p:Person), (m:Movie)
optional match (p)-[:ACTED_IN]->(m)
match (p)-[:ACTED_IN]->(m)
return p.Name, m.Title
"
);
}
catch (TranspilerSyntaxErrorException e)
{
Assert.IsTrue(e.Message.Contains("MATCH cannot follow OPTIONAL MATCH"));
expectedExceptionThrown = true;
}
Assert.IsTrue(expectedExceptionThrown);
}
}
[TestMethod]
public void CaseExpressionParsingTest()
{
var tree = RunQueryAndDumpTree(@"
MATCH (person:Person)-[r:KNOWS]->(friend:Person)
WITH toFloat(r.score + r.score_delta) AS score2, friend.Name, person.level AS number
WHERE friend.Name='bnitta' OR (person.number >= 1 AND person.number <= 10)
RETURN sum(score2), avg(score2+1) AS scoreShift1,
case when friend.Name = 'bnitta' then 1 else 0 end as friendFlag
"
);
// TODO: structural verifications
Assert.IsNotNull(tree);
}
}
}

Просмотреть файл

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
<RootNamespace>openCypherTranspiler.openCypherParser.Test</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.3.2" />
<PackageReference Include="MSTest.TestFramework" Version="1.3.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CommonTest\CommonTest.csproj" />
<ProjectReference Include="..\..\src\openCypherParser\openCypherParser.csproj" />
</ItemGroup>
</Project>