附录B:查询语言的完整正式语法

版本2.1

下面描述了GSQL语言的语法正式规则。它由一系列遵循EBNF范式的表达式组成。

定义语法所使用的表示法

我们用EBNF范式规则来定义本语言的语法。它的规则包含了终端符号和非终端符号。 终端符号(terminal symbol)是表示文字输出的最基本符号。 所有被单引号或双引号引用的字符(例如,“+”,“=”,“)”,“10”等)都是终端符号。 非终端符号(non-terminal symbol)是终端符号和非终端符号的组合。规则规定公式的左边始终是非终端符号; 因此规定实质上是在定义非终端符号。 例如在下面的例子中,assignmentStmt(即赋值语句的缩写)被写成一个名称,加一个等号,一个表达式,一个运算符,再加一个表示终止的分号的形式。 AssignmentStmt,name和expr都是非终端符号。 此外,所有关键词(KEYWORD)必须全部大写的,并且它们都是终端符号。 “:=”是EBNF的一部分,意思它的右侧内容是左侧内容的展开。

EBNF 范式语法的例子: 一条规则
assignmentStmt := name "=" expr op expr ";"

竖线“|”在EBNF范式中表示选项,即在竖线的两侧二选一。如果有一系列的竖线,则表示在竖线分割的选项中多选一。

EBNF 范式语法的例子: 竖线
op := "+" | "-" | "*" | "/"

方括号代表可选部分或者一组符号。而圆括号将一组符号聚集在一起。下面的例子演示了一个常数,它可以是一位数,两位数或者三位数,而在数字之前可以选择添加加减号。

EBNF 范式语法的例子: 方括号和圆括号
constant := ["+" | "-"] (digit | (digit digit) | (digit digit digit))

星号( *)和加号( +)是EBNF范式中位于结尾表示重复出现次数。 星号表示零次或多次出现,而加号表示一次或多次出现。 下例中的intConstant中,开头可以有可选的加号或减号,而后跟一位或多位数字。 而floatConstant的开头也为可选的加号或减号,后跟零位或多位数字,再后跟一位或多位小数。 星号和加号也可以应用于列表定义中的符号组。 比如下例中,非终端符号的list被定义为逗号分隔的表达式列表,并用圆括号括起来。 该列表至少有一个表达式,后面可以跟着零个或多个表达式,并用逗号分隔。

EBNF 范式语法的例子: 方括号和圆括号
intConstant := ["+" | "-"] digit+
floatConstant := ["+" | "-"] digit* "." digit+
list := "(" expr ["," expr]* ")"

大括号{}用于标识一个可选的符号组,它们可以重复出现零次或多次。 因此,大括号的使用等效于方括号或圆括号后跟星号的情况,以表示该符号组零次或多次重复出现。 以下所有表达式都是等效的:

list1 := expr ["," expr]*
list2 += expr ("," expr)*
list3 := expr {"," expr}

为简洁起见,我们有时在范式中不在逗号上添加引号:

list4 := expr {, expr}

GSQL 图形查询语言的EBNF范式

#########################################################
## EBNF for GSQL Query Language

createQuery := CREATE [DISTRIBUTED][OR REPLACE] QUERY name "(" [parameterList] ")" FOR GRAPH name
               [RETURNS "("  baseType | accumType ")"]
               [API "(" stringLiteral ")"]
               "{" [typedefs] [declStmts] [declExceptStmts] queryBodyStmts "}"

parameterValueList := parameterValue [, parameterValue]*
parameterValue := parameterConstant
                | "[" parameterValue [, parameterValue]* "]"  // BAG or SET
                | "(" stringLiteral, stringLiteral ")"        // a generic VERTEX value
parameterConstant := numeric | stringLiteral | TRUE | FALSE
parameterList := parameterType name ["=" constant] ["," parameterType name  ["=" constant]]*

typedefs := (typedef ";")+
declStmts := (declStmt ";")+
declStmt := baseDeclStat | accumDeclStmt | fileDeclStmt
declExceptStmts := (declExceptStmt ";")+
queryBodyStmts := (queryBodyStmt ";")+
queryBodyStmt := assignStmt           // Assignment
               | vSetVarDeclStmt      // Declaration
               | gAccumAssignStmt     // Assignment
               | gAccumAccumStmt      // Assignment
               | funcCallStmt         // Function Call
               | selectStmt           // Select 
               | queryBodyCaseStmt    // Control Flow
               | queryBodyIfStmt      // Control Flow
               | queryBodyWhileStmt   // Control Flow
               | queryBodyForEachStmt // Control Flow
               | BREAK                // Control Flow
               | CONTINUE             // Control Flow
               | updateStmt           // Data Modification
               | insertStmt           // Data Modification
               | queryBodyDeleteStmt  // Data Modification
               | printStmt            // Output
               | printlnStmt          // Output
               | logStmt              // Output
               | returnStmt           // Output
               | raiseStmt            // Exception
               | tryStmt              // Exception

installQuery := INSTALL QUERY [installOptions] ( "*" | ALL |name [, name]* )
runQuery := RUN QUERY [runOptions] name "(" parameterValueList ")"

showQuery := SHOW QUERY name
dropQuery := DROP QUERY ( "*" | ALL | name [, name]* )
  
#########################################################
## Types and names

lowercase          := [a-z]
uppercase          := [A-Z]
letter             := lowercase | uppercase
digit              := [0-9]
integer            := ["-"]digit+
real               := ["-"]("." digit+) | ["-"](digit+ "." digit*)

numeric            := integer | real
stringLiteral      := '"' [~["] | '\\' ('"' | '\\')]* '"'

name := (letter | "_") [letter | digit | "_"]*   // Can be a single "_" or start with "_"

type := baseType | name | accumType | STRING COMPRESS

baseType := INT
          | UINT
          | FLOAT
          | DOUBLE
          | STRING
          | BOOL
          | VERTEX ["<" name ">"]
          | EDGE
          | JSONOBJECT
          | JSONARRAY
          | DATETIME

filePath := name | stringLiteral

typedef := TYPEDEF TUPLE "<" tupleType ">" name

tupleType := (baseType name) | (name baseType) ["," (baseType name) | (name baseType)]*

parameterType := baseType
               | [ SET | BAG ] "<" baseType ">"
               | FILE

#########################################################
## Accumulators

accumDeclStmt := accumType "@"name ["=" constant][, "@"name ["=" constant]]*
               | "@"name ["=" constant][, "@"name ["=" constant]]* accumType
               | [STATIC] accumType "@@"name ["=" constant][, "@@"name ["=" constant]]*
               | [STATIC] "@@"name ["=" constant][, "@@"name ["=" constant]]* accumType


accumType := "SumAccum" "<" ( INT | FLOAT | DOUBLE | STRING | STRING COMPRESS) ">"
		   | "MaxAccum" "<" ( INT | FLOAT | DOUBLE ) ">"
 	       | "MinAccum" "<" ( INT | FLOAT | DOUBLE ) ">"
     	   | "AvgAccum"
		   | "OrAccum"
		   | "AndAccum"
           | "BitwiseOrAccum"
           | "BitwiseAndAccum"
		   | "ListAccum" "<" type ">"
		   | "SetAccum"  "<" elementType ">"      
		   | "BagAccum"  "<" elementType ">"      
           | "MapAccum"  "<" elementType "," type ">"   
           | "HeapAccum" "<" name ">" "(" (integer | name) "," name [ASC | DESC] ["," name [ASC | DESC]]* ")"
		   | "GroupByAccum" "<" elementType name ["," elementType name]* , accumType name ["," accumType name]* ">"
           | "ArrayAccum" "<" name ">"

elementType := baseType | name | STRING COMPRESS

gAccumAccumStmt := "@@"name "+=" expr
																				 
###############################################################################
## Operators, Functions, and Expressions

constant := numeric | stringLiteral | TRUE | FALSE | GSQL_UINT_MAX
          | GSQL_INT_MAX | GSQL_INT_MIN | TO_DATETIME "(" stringLiteral ")"
 
mathOperator := "*" | "/" | "%" | "+" | "-" | "<<" | ">>" | "&" | "|"
 
condition := expr
           | expr comparisonOperator expr
           | expr [ NOT ] IN setBagExpr
           | expr IS [ NOT ] NULL
           | expr BETWEEN expr AND expr
           | "(" condition ")"
           | NOT condition
           | condition (AND | OR) condition
           | (TRUE | FALSE)

comparisonOperator := "<" | "<=" | ">" | ">=" | "==" | "!="

expr :=   ["@@"]name
		| name "." "type"
		| name "." ["@"]name
		| name "." "@"name ["\'"]
		| name "." name "." name "(" [argList] ")"
        | name "." name "(" [argList] ")" [ ".".FILTER "(" condition ")" ]
		| name ["<" type ["," type"]* ">"] "(" [argList] ")"
		| name "." "@"name ("." name "(" [argList] ")")+ ["." name]
		| "@@"name ("." name "(" [argList] ")")+ ["." name]
		| COALESCE "(" [argList] ")"
		| ( COUNT | ISEMPTY | MAX | MIN | AVG | SUM ) "(" setBagExpr ")"
		| expr mathOperator expr
		| "-" expr
		| "(" expr ")"
		| "(" argList "->" argList ")"	// key value pair for MapAccum
		| "[" argList "]"               // a list
		| constant
		| setBagExpr
		| name "(" argList ")"          // function call or a tuple object 
		
setBagExpr := ["@@"]name 
    	    | name "." ["@"]name
		    | name "." "@"name ("." name "(" [argList] ")")+
		    | name "." name "(" [argList] ")" [ ".".FILTER "(" condition ")" ]
		    | "@@"name ("." name "(" [argList] ")")+
		    | setBagExpr (UNION | INTERSECT | MINUS) setBagExpr
		    | "(" argList ")"
		    | "(" setBagExpr ")"

#########################################################
## Declarations and Assignments ##

## Declarations ##
baseDeclStmt    := baseType name ["=" constant][, name ["=" constant]]*
fileDeclStmt := FILE fileVar "(" filePath ")"
fileVar := name

localVarDeclStmt := baseType name "=" expr

vSetVarDeclStmt := name ["(" vertexEdgeType ")"] "=" (seedSet | simpleSet | selectBlock)

simpleSet := name | "(" simpleSet ")" | simpleSet (UNION | INTERSECT | MINUS) simpleSet

seedSet := "{" [seed ["," seed ]*] "}"
seed := '_' 
      | ANY
      | ["@@"]name
      | name ".*"
      | "SelectVertex" selectVertParams

selectVertParams := "(" filePath "," columnId "," (columnId | name) ","
                 stringLiteral "," (TRUE | FALSE) ")" [".".FILTER "(" condition ")"]

columnId := "$" (integer | stringLiteral)

## Assignment Statements ##
assignStmt := name "=" expr
            | name "." name "=" expr
            | name "." "@"name ("+="| "=") expr

gAccumAssignStmt :=  "@@"name ("+=" | "=") expr

loadAccumStmt := "@@"name "=" "{" "LOADACCUM" loadAccumParams ["," "LOADACCUM" loadAccumParams]* "}"

loadAccumParams := "(" filePath "," columnId "," [columnId ","]*
                stringLiteral "," (TRUE | FALSE) ")" [".".FILTER "(" condition ")"]

## Function Call Statement ##
funcCallStmt := name ["<" type ["," type"]* ">"] "(" [argList] ")"
              | "@@"name ("." name "(" [argList] ")")+
           
argList := expr ["," expr]*


#########################################################
## Select Statement
 
selectStmt  := name "=" selectBlock
 
selectBlock := SELECT name FROM ( edgeSet | vertexSet )
                    [sampleClause]
                    [whereClause]
                    [accumClause]
                    [postAccumClause]
                    [havingClause]
                    [orderClause]
                    [limitClause]
  
vertexSet := name [":" name]
 
edgeSet   := name [":" name]
             "-" "(" [vertexEdgeType] [":" name] ")" "->"
             [vertexEdgeType] [":" name]

vertexEdgeType := "_" | ANY | name | ( "(" name ["|" name]* ")" )

sampleClause := SAMPLE ( expr | expr "%" ) EDGE WHEN condition
              | SAMPLE expr TARGET WHEN condition
              | SAMPLE expr "%" TARGET PINNED WHEN condition
 
whereClause := WHERE condition

accumClause := ACCUM DMLSubStmtList
 
postAccumClause := POST-ACCUM DMLSubStmtList
    
DMLSubStmtList := DMLSubStmt ["," DMLSubStmt]*

DMLSubStmt := assignStmt           // Assignment   
            | funcCallStmt         // Function Call
            | gAccumAccumStmt      // Assignment
            | vAccumFuncCall       // Function Call
            | localVarDeclStmt     // Declaration
            | DMLSubCaseStmt       // Control Flow
            | DMLSubIfStmt         // Control Flow
            | DMLSubWhileStmt      // Control Flow
            | DMLSubForEachStmt    // Control Flow
            | BREAK                // Control Flow
            | CONTINUE             // Control Flow
            | insertStmt           // Data Modification
            | DMLSubDeleteStmt     // Data Modification
            | printlnStmt          // Output
            | logStmt              // Output

vAccumFuncCall := name "." "@"name ("." name "(" [argList] ")")+

havingClause := HAVING condition
 
orderClause := ORDER BY expr [ASC | DESC] ["," expr [ASC | DESC]]*
 
limitClause := LIMIT ( expr | expr "," expr | expr OFFSET expr )

#########################################################
## Control Flow Statements ##

queryBodyIfStmt := IF condition THEN queryBodyStmts [ELSE IF condition THEN queryBodyStmts ]* [ELSE queryBodyStmts ] END
DMLSubIfStmt :=    IF condition THEN DMLSubStmtList [ELSE IF condition THEN DMLSubStmtList ]* [ELSE DMLSubStmtList ] END

queryBodyCaseStmt := CASE      (WHEN condition THEN queryBodyStmts)+ [ELSE queryBodyStmts] END
    	           | CASE expr (WHEN constant  THEN queryBodyStmts)+ [ELSE queryBodyStmts] END
DMLSubCaseStmt := CASE      (WHEN condition THEN DMLSubStmtList)+ [ELSE DMLSubStmtList] END
                | CASE expr (WHEN constant  THEN DMLSubStmtList)+ [ELSE DMLSubStmtList] END

queryBodyWhileStmt := WHILE  condition  [LIMIT (name | integer)] DO queryBodyStmts END
DMLSubWhileStmt :=    WHILE  condition  [LIMIT (name | integer)] DO DMLSubStmtList END

queryBodyForEachStmt := FOREACH  forEachControl  DO  queryBodyStmts  END
DMLSubForEachStmt :=    FOREACH  forEachControl  DO  DMLSubStmtList  END
 
forEachControl := ( name | "(" name (, name)+ ")") (IN | ":") setBagExpr
                | name IN RANGE "[" expr , expr"]" [".STEP(" expr ")"]

#########################################################
## Other Data Modifications Statements ##

queryBodyDeleteStmt := DELETE name FROM ( edgeSet | vertexSet ) [whereClause] 
DMLSubDeleteStmt := DELETE "(" name ")" 

updateStmt := UPDATE name FROM ( edgeSet | vertexSet ) SET DMLSubStmtList [whereClause] 
 
insertStmt := INSERT INTO name ["(" ( PRIMARY_ID | FROM "," TO ) ["," name]* ")"] 
                  VALUES "(" ( "_" | expr ) [name] ["," ( "_" | expr ) [name] ["," ("_" | expr)]*] ")"

#########################################################
## Output Statements ##

printStmt := PRINT printExpr {, printExpr} [WHERE condition] [TO_CSV (filePath | fileVar)]
printExpr := (expr | vExprSet) [ AS name]
vExprSet  := expr "[" vSetProj {, vSetProj} "]"
vSetProj  := expr [ AS name]

printlnStmt := fileVar".println" "(" expr {, expr} ")"

logStmt := LOG "(" condition "," argList ")"

returnStmt := RETURN expr

#########################################################
## Exception Statements ##

declExceptStmt := EXCEPTION exceptVarName "(" errorInt ")"
exceptVarName  := name
errorInt      := integer


raiseStmt       := RAISE exceptVarName [errorMsg]
errorMsg        := "(" expr ")"


tryStmt         := TRY queryBodyStmts EXCEPTION caseExceptBlock+ [elseExceptBlock] END ";"
caseExceptBlock := WHEN exceptVarName THEN queryBodyStmts
elseExceptBlock := ELSE queryBodyStmts

Last updated