opencypher

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 28, 2023 License: Apache-2.0 Imports: 14 Imported by: 6

README

GoDoc Go Report Card Build Status

Embedded openCypher interpreter

openCypher is a query language for labeled property graphs. This Go module contains an openCypher interpreter (partial) that works on the Go LPG implementation given in https://github.com/cloudprivacylabs/lpg.

More information on openCypher can be found here:

https://opencypher.org/

openCypher

At this point, this library provides partial support for openCypher expressions. More support will be added as needed.

openCypher expressions are evaluated using an evaluation context.

Create Nodes

See examples/create directory.

import (
	"fmt"

	"github.com/cloudprivacylabs/opencypher"
	"github.com/cloudprivacylabs/lpg"
)

func main() {
	grph := graph.NewGraph()
	ectx := opencypher.NewEvalContext(grph)
	_, err := opencypher.ParseAndEvaluate(`CREATE (n:Person), (m)`, ectx)
	if err != nil {
		panic(err)
	}
	v, err := opencypher.ParseAndEvaluate(`MATCH (x:Person) return x as person`, ectx)
	if err != nil {
		panic(err)
	}
	fmt.Println(v.Get().(opencypher.ResultSet).Rows[0]["person"])
}
Evaluation Context

Variables defined in an expression will be in the evaluation context, and can be used to affect the results of subsequent expression.

See examples/context.

func main() {
	// Create an empty graph
	grph := graph.NewGraph()
	// Evaluation context knows the graph we are working on
	ectx := opencypher.NewEvalContext(grph)
	// CREATE a path
	_, err := opencypher.ParseAndEvaluate(`CREATE (andy {name:"Andy"})-[:KNOWS]-> (stephen {name:"Stephen"})`, ectx)
	if err != nil {
		panic(err)
	}
	// ectx knows andy and stephen. So this will only update stephen, and not andy
	v, err := opencypher.ParseAndEvaluate(`MATCH (stephen) SET stephen.age=34 return stephen`, ectx)
	if err != nil {
		panic(err)
	}
	age, _ := v.Get().(opencypher.ResultSet).Rows[0]["1"].Get().(*graph.Node).GetProperty("age")
	fmt.Println(age) // This will print 34
}
Querying and result sets

Using the example in https://neo4j.com/docs/cypher-manual/current/clauses/match/

	// Get all nodes
	ectx = opencypher.NewEvalContext(grph)
	res, err := opencypher.ParseAndEvaluate(`match (n) return n`, ectx)
	fmt.Println("match (n) return n:", res.Get().(opencypher.ResultSet).Rows)

	// Get all movies
	ectx = opencypher.NewEvalContext(grph)
	res, err = opencypher.ParseAndEvaluate(`match (n:Movie) return n.title`, ectx)
	fmt.Println("match (n:Movie) return n.title:", res.Get().(opencypher.ResultSet).Rows)

	// Get related node
	ectx = opencypher.NewEvalContext(grph)
	res, err = opencypher.ParseAndEvaluate(`match (director {name: 'Oliver Stone'}) --(movie:Movie) return movie.title`, ectx)
	fmt.Println("match (director {name: 'Oliver Stone'}) --(movie:Movie) return movie.title:", res.Get().(opencypher.ResultSet).Rows)
	ectx = opencypher.NewEvalContext(grph)
	res, err = opencypher.ParseAndEvaluate(`match (director {name: 'Oliver Stone'}) --> (movie:Movie) return movie.title`, ectx)
	fmt.Println("match (director {name: 'Oliver Stone'}) --> (movie:Movie) return movie.title:", res.Get().(opencypher.ResultSet).Rows)

	// Get relationship type
	ectx = opencypher.NewEvalContext(grph)
	res, err = opencypher.ParseAndEvaluate(`match (:Person {name: 'Oliver Stone'}) -[r]->(movie) return r`, ectx)
	fmt.Println("match (:Person {name: 'Oliver Stone'}) -[r]->(movie) return r:", res.Get().(opencypher.ResultSet).Rows)
Values

Opencypher expressions return an object of type Value. Value.Get returns the value contained in the value object. For most queries, this value is of type opencypher.ResultSet. A ResultSet contains Rows that are map[string]Value objects. If the query explicitly names its columns, the map will contains those names as the keys. Otherwise, the columns will be "1", "2", etc.

The number of rows in the result set:

rs:=value.Get().(opencypher.ResultSet)
numResults:=len(rs.Rows)

Iterate the results:

for _,row := range resultSet.Rows {
   for colName, colValue := range row {
      // colName is the column name
      // colValue is an opencypher.Value object
      fmt.Println(colName,value.Get())
   }
}

The return type of Value.Get is one of the following:

  • int
  • float64
  • bool
  • string
  • Duration
  • Date
  • Time
  • LocalDateTime
  • LocalTime
  • []Value
  • map[string]Value
  • lpg.StringSet
  • *lpg.Node
  • *lpg.Path
  • ResultSet

This Go module is part of the Layered Schema Architecture.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrDivideByZero                   = errors.New("Divide by zero")
	ErrInvalidUnaryOperation          = errors.New("Invalid unary operation")
	ErrInvalidPowerOperation          = errors.New("Invalid power operation")
	ErrInvalidMultiplicativeOperation = errors.New("Invalid multiplicative operation")
	ErrInvalidDurationOperation       = errors.New("Invalid duration operation")
	ErrOperationWithNull              = errors.New("Operation with null")
	ErrInvalidStringOperation         = errors.New("Invalid string operation")
	ErrInvalidDateOperation           = errors.New("Invalid date operation")
	ErrInvalidAdditiveOperation       = errors.New("Invalid additive operation")
	ErrInvalidComparison              = errors.New("Invalid comparison")
	ErrInvalidListIndex               = errors.New("Invalid list index")
	ErrNotAList                       = errors.New("Not a list")
	ErrNotABooleanExpression          = errors.New("Not a boolean expression")
	ErrMapKeyNotString                = errors.New("Map key is not a string")
	ErrInvalidMapKey                  = errors.New("Invalid map key")
	ErrNotAStringSet                  = errors.New("Not a string set")
	ErrIntValueRequired               = errors.New("Int value required")
	ErrStringValueRequired            = errors.New("String value required")
	ErrNeo4jDateValueRequired         = errors.New("Neo4j Date value required")
	ErrNeo4jDateTimeValueRequired     = errors.New("Neo4j LocalDateTime value required")
	ErrExpectingResultSet             = errors.New("Expecting a result set")
	ErrPropertiesParameterExpected    = errors.New("Parameter value cannot be used for properties")
	ErrPropertiesExpected             = errors.New("Value cannot be used for properties")
	ErrNotAnLValue                    = errors.New("Not and lvalue")
)
View Source
var ErrIncompatibleCells = errors.New("Incompatible result set cells")
View Source
var ErrRowsHaveDifferentSizes = errors.New("Rows have different sizes")

Functions

func BuildPatternSymbols

func BuildPatternSymbols(ctx *EvalContext, pattern lpg.Pattern) (map[string]*lpg.PatternSymbol, error)

BuildPatternSymbols copies all the symbols referenced in the pattern from the context, and puts them in a map.

func EscapeLabelLiteral

func EscapeLabelLiteral(s string) string

EscapeLabelLiteral escape a literal that can be used as a label. It returns `s`

func EscapePropertyKeyLiteral

func EscapePropertyKeyLiteral(s string) string

EscapePropertyKeyLiteral escapes a literal that can be used as a property key. Returns `s`

func EscapeStringLiteral

func EscapeStringLiteral(s string) string

EscapeStringLiteral returns "s" where backslashes and quotes in s are escaped

func GetParser

func GetParser(input string) *parser.CypherParser

GetParser returns a parser that will parse the input string

func IsNamedResult

func IsNamedResult(name string) bool

IsNamedResult checks if the given name is a symbol name (i.e. it does not start with a number)

func IsNamedVar

func IsNamedVar(name string) bool

func IsValuePrimitive

func IsValuePrimitive(v Value) bool

IsValuePrimitive returns true if the value is int, float64, bool, string, duration, date, datetime, localDateTime, or localTime

func IsValueSame

func IsValueSame(v, v2 Value) bool

IsValueSame compares two values and decides if the two are the same

func RegisterGlobalFunc

func RegisterGlobalFunc(fn ...Function)

func ValueAsBool

func ValueAsBool(v Value) (bool, bool)

ValueAsBool returns the bool value, or if it is not bool, false,false

func ValueAsInt

func ValueAsInt(v Value, err ...error) (int, error)

ValueAsInt returns the int value. If value is not int, returns ErrIntValueRequired. If an err argument is given, that error is returned.

func ValueAsString

func ValueAsString(v Value, err ...error) (string, error)

ValueAsString returns the string value. If value is not string, rReturns ErrStringValueRequired. If an err argument is given, that error is returned.

Types

type Date

type Date time.Time // Date value, without a time zone and time related components.

func NewDate

func NewDate(t time.Time) Date

NewDate creates a Date Hour, minute, second and nanoseconds are set to zero and location is set to UTC.

func (Date) String

func (t Date) String() string

func (Date) Time

func (t Date) Time() time.Time

Time casts Date to time.Time

type Duration

type Duration struct {
	Months  int64
	Days    int64
	Seconds int64
	Nanos   int
}

Duration represents a duration in opencypher. Copied from neo4j driver.

func (Duration) Equal

func (d1 Duration) Equal(d2 Duration) bool

func (Duration) String

func (d Duration) String() string

type ErrInvalidAssignment

type ErrInvalidAssignment string

func (ErrInvalidAssignment) Error

func (e ErrInvalidAssignment) Error() string

type ErrInvalidExpression

type ErrInvalidExpression string

func (ErrInvalidExpression) Error

func (e ErrInvalidExpression) Error() string

type ErrInvalidFunctionCall

type ErrInvalidFunctionCall struct {
	Msg string
}

func (ErrInvalidFunctionCall) Error

func (e ErrInvalidFunctionCall) Error() string

type ErrInvalidIndirection

type ErrInvalidIndirection string

func (ErrInvalidIndirection) Error

func (e ErrInvalidIndirection) Error() string

type ErrInvalidValueReferenceInPattern

type ErrInvalidValueReferenceInPattern struct {
	Symbol string
}

func (ErrInvalidValueReferenceInPattern) Error

type ErrSyntax

type ErrSyntax string

func (ErrSyntax) Error

func (e ErrSyntax) Error() string

type ErrUnknownFunction

type ErrUnknownFunction struct {
	Name string
}

func (ErrUnknownFunction) Error

func (e ErrUnknownFunction) Error() string

type ErrUnknownParameter

type ErrUnknownParameter struct {
	Key string
}

func (ErrUnknownParameter) Error

func (e ErrUnknownParameter) Error() string

type ErrUnknownVariable

type ErrUnknownVariable struct {
	Name string
}

func (ErrUnknownVariable) Error

func (e ErrUnknownVariable) Error() string

type ErrValueDoesNotHaveProperties

type ErrValueDoesNotHaveProperties struct {
	Value    interface{}
	Property string
}

func (ErrValueDoesNotHaveProperties) Error

type EvalContext

type EvalContext struct {

	// If this function is non-nil, it will be called to filter property
	// values when setting properties of nodes or edges
	PropertyValueFromNativeFilter func(string, interface{}) interface{}
	// contains filtered or unexported fields
}

func NewEvalContext

func NewEvalContext(graph *lpg.Graph) *EvalContext

func (*EvalContext) GetFunction

func (ctx *EvalContext) GetFunction(name []string) (Function, error)

func (*EvalContext) GetParameter

func (ctx *EvalContext) GetParameter(key string) (Value, error)

func (*EvalContext) GetVar

func (ctx *EvalContext) GetVar(name string) (Value, error)

func (*EvalContext) GetVarsNearestScope

func (ctx *EvalContext) GetVarsNearestScope() map[string]Value

func (*EvalContext) PropertyValueFromNative

func (ctx *EvalContext) PropertyValueFromNative(key string, value interface{}) interface{}

PropertyValueFromNative calls the ctx.PropertyValueFromNativeFilter to give the caller a chance to change property values

func (*EvalContext) RemoveVar

func (ctx *EvalContext) RemoveVar(name string)

func (*EvalContext) SetParameter

func (ctx *EvalContext) SetParameter(key string, value Value) *EvalContext

SetParameter sets a parameter to be used in expressions

func (*EvalContext) SetVar

func (ctx *EvalContext) SetVar(name string, value Value)

func (*EvalContext) SetVars

func (ctx *EvalContext) SetVars(m map[string]Value)

func (*EvalContext) SubContext

func (ctx *EvalContext) SubContext() *EvalContext

SubContext creates a new subcontext with a new variable set

type Evaluatable

type Evaluatable interface {
	Evaluate(*EvalContext) (Value, error)
}

func Parse

func Parse(input string) (Evaluatable, error)

GetEvaluatable returns an evaluatable object

type Expression

type Expression interface {
	Evaluatable
}

type Function

type Function struct {
	Name      string
	MinArgs   int
	MaxArgs   int
	Func      func(*EvalContext, []Evaluatable) (Value, error)
	ValueFunc func(*EvalContext, []Value) (Value, error)
}

Function describes a function

type LValue

type LValue struct {
	// contains filtered or unexported fields
}

LValue is a pointer to a value

func NewLValue

func NewLValue(v Value) LValue

NewLValue returns an LValue from the given value

func (LValue) Evaluate

func (v LValue) Evaluate(*EvalContext) (Value, error)

func (LValue) Get

func (v LValue) Get() interface{}

func (LValue) IsConst

func (LValue) IsConst() bool

func (LValue) Set

func (v LValue) Set(val interface{})

type LocalDateTime

type LocalDateTime time.Time // Date and time in local timezone

func NewLocalDateTime

func NewLocalDateTime(t time.Time) LocalDateTime

NewLocalDateTime creates a LocalDateTime from time.Time.

func (LocalDateTime) String

func (t LocalDateTime) String() string

func (LocalDateTime) Time

func (t LocalDateTime) Time() time.Time

Time casts LocalDateTime to time.Time

type LocalTime

type LocalTime time.Time // Time since start of day in local timezone

func NewLocalTime

func NewLocalTime(t time.Time) LocalTime

NewLocalTime creates a LocalTime from time.Time. Year, month and day are set to zero and location is set to local.

func (LocalTime) String

func (t LocalTime) String() string

func (LocalTime) Time

func (t LocalTime) Time() time.Time

Time casts LocalTime to time.Time

type Match

type Match struct {
	Optional bool
	Pattern  Pattern
	Where    Expression
}

func (Match) GetResults

func (match Match) GetResults(ctx *EvalContext) (ResultSet, error)

type NodeLabels

type NodeLabels []schemaName

type Parameter

type Parameter string

func (Parameter) Evaluate

func (expr Parameter) Evaluate(ctx *EvalContext) (Value, error)

type Pattern

type Pattern struct {
	Parts []PatternPart
}

type PatternPart

type PatternPart struct {
	// contains filtered or unexported fields
}

func ParsePatternExpr

func ParsePatternExpr(expr string) (PatternPart, error)

ParsePatternExpr parses the pattern expression that starts at the current node named 'this', and describes a path reaching one or more nodes named 'target'. For instance:

(this)-[]->(target)

will return all nodes reachable from the current node by one step.

This expression:

(this)<[a]-()-[]->(target :x)

will start from the current node, go back one nore following an edge with label `a`, and then move to a node with label `x`

func (PatternPart) Create

func (part PatternPart) Create(ctx *EvalContext) (*lpg.Node, *lpg.Path, error)

func (PatternPart) FindRelative

func (p PatternPart) FindRelative(this *lpg.Node) ([]*lpg.Node, error)

FindRelative evaluates a pattern expression starting at the given node. It may return zero or more nodes reached from the node

type Properties

type Properties struct {
	Map   *mapLiteral
	Param *Parameter
}

func (Properties) AsLiteral

func (properties Properties) AsLiteral(ctx *EvalContext) ([]mapKeyValue, error)

type RValue

type RValue struct {
	Value interface{}
	Const bool
}

RValue is a value

func (RValue) Evaluate

func (v RValue) Evaluate(*EvalContext) (Value, error)

func (RValue) Get

func (v RValue) Get() interface{}

func (RValue) IsConst

func (v RValue) IsConst() bool

func (RValue) String

func (v RValue) String() string

type ReadingClause

type ReadingClause interface {
	GetResults(*EvalContext) (ResultSet, error)
}

type ResultSet

type ResultSet struct {
	Nodes lpg.NodeSet
	Edges lpg.EdgeSet

	Cols []string
	Rows []map[string]Value
}

ResultSet is a table of values

func CartesianProduct

func CartesianProduct(resultsets []ResultSet, all bool, filter func(map[string]Value) bool) ResultSet

CartesianProuduct builds the product of all the resultsets

func NewResultSet

func NewResultSet() *ResultSet

func (*ResultSet) Add

func (r *ResultSet) Add(rs ResultSet)

func (*ResultSet) AddPath

func (r *ResultSet) AddPath(node *lpg.Node, edges []*lpg.Edge)

func (*ResultSet) Append

func (r *ResultSet) Append(row map[string]Value) error

Append the row to the resultset.

func (ResultSet) CartesianProduct

func (r ResultSet) CartesianProduct(f func(map[string]Value) bool) bool

CartesianProduct calls f with all permutations of rows until f returns false. The map passed to f is reused, so copy if you need a copy of it.

func (*ResultSet) Column

func (r *ResultSet) Column(key string) []Value

Column returns a column of results as a value

func (ResultSet) String

func (r ResultSet) String() string

func (*ResultSet) Union

func (r *ResultSet) Union(src ResultSet, all bool) error

Union adds the src resultset to this. If all is set, it adds all rows, otherwise, it adds unique rows

type Time

type Time time.Time // Time since start of day with timezone information

func (Time) String

func (t Time) String() string

func (Time) Time

func (t Time) Time() time.Time

Time casts Time to time.Time

type UpdatingClause

type UpdatingClause interface {
	Update(*EvalContext, ResultSet) (Value, error)
	TopLevelUpdate(*EvalContext) (Value, error)
}

type Value

type Value interface {
	Evaluatable
	Get() interface{}
	IsConst() bool
}

func ParseAndEvaluate

func ParseAndEvaluate(input string, ctx *EvalContext) (Value, error)

func ValueOf

func ValueOf(in interface{}) Value

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL