The old way of doing this was using LISP:
Adding a new Memgraph-specific query
Adding a new query to Memgraph is not hard but it consists of multiple steps that affect different parts of code. Using a small example of adding a FREE MEMORY
query we will go through all the necessary steps while the additional functionalities like adding a query with a variable can be deduced by looking at the similar queries. The point of this tutorial is to only show you all the places you need to change to add a completely functional new query.
First step is adding the new keywords, if any, to the Memgraph's grammar.
For our query, we have two keywords: FREE
and MEMORY
.
We go to the src/query/frontend/opencypher/grammar/CypherLexer.g4
file and check if the keywords are already defined. We see that MEMORY
is actually defined but FREE
is missing.
Next we go to the src/query/frontend/opencypher/grammar/MemgraphCypherLexer.g4
file which contains Memgraph specific keywords. We also see that FREE
is not present so we add it here:
import CypherLexer ;
ALTER : A L T E R ;
ASYNC : A S Y N C ;
AUTH : A U T H ;
BAD : B A D ;
CLEAR : C L E A R ;
CSV : C S V ;
DATA : D A T A ;
DELIMITER : D E L I M I T E R ;
DATABASE : D A T A B A S E ;
DENY : D E N Y ;
DIRECTORY : D I R E C T O R Y ;
DROP : D R O P ;
DUMP : D U M P ;
FOR : F O R ;
FREE : F R E E ;
FROM : F R O M ;
GRANT : G R A N T ;
GRANTS : G R A N T S ;
HEADER : H E A D E R ;
IDENTIFIED : I D E N T I F I E D ;
IGNORE : I G N O R E ;
LOAD : L O A D ;
LOCK : L O C K ;
MAIN : M A I N ;
MODE : M O D E ;
NO : N O ;
PASSWORD : P A S S W O R D ;
PORT : P O R T ;
PRIVILEGES : P R I V I L E G E S ;
REGISTER : R E G I S T E R ;
REPLICA : R E P L I C A ;
REPLICAS : R E P L I C A S ;
REPLICATION : R E P L I C A T I O N ;
REVOKE : R E V O K E ;
ROLE : R O L E ;
ROLES : R O L E S ;
QUOTE : Q U O T E ;
STATS : S T A T S ;
SYNC : S Y N C ;
TIMEOUT : T I M E O U T ;
TO : T O ;
UNLOCK : U N L O C K ;
USER : U S E R ;
USERS : U S E R S ;
After that, we read the comment at the beginning of the file and notice that we need to add the new keyword to the kKeywords
in src/query/frontend/stripped_lexer_constants.hpp
:
const trie::Trie kKeywords = {
"union", "all", "optional", "match", "unwind", "as", "merge", "on", "create",
"set", "detach", "delete", "remove", "with", "distinct", "return", "order", "by",
"skip", "limit", "ascending", "asc", "descending", "desc", "where", "or", "xor",
"and", "not", "in", "starts", "ends", "contains", "is", "null", "case",
"when", "then", "else", "end", "count", "filter", "extract", "any", "none",
"single", "true", "false", "reduce", "coalesce", "user", "password", "alter", "drop",
"show", "stats", "unique", "explain", "profile", "storage", "index", "info", "exists",
"assert", "constraint", "node", "key", "dump", "database", "call", "yield", "memory",
"mb", "kb", "unlimited", "free"};
We added all the new keywords to Memgraph's grammar now we can define how our query actually looks like.
We go to the src/query/frontend/opencypher/grammar/MemgraphCypher.g4
and define our new query. Again, we need to add the new FREE
keyword:
memgraphCypherKeyword : cypherKeyword
| ALTER
| ASYNC
| AUTH
| BAD
| CLEAR
| CSV
| DATA
| DELIMITER
| DATABASE
| DENY
| DROP
| DUMP
| FOR
| FREE
| FROM
| GRANT
| HEADER
| IDENTIFIED
| LOAD
| LOCK
| MAIN
| MODE
| NO
| PASSWORD
| PORT
| PRIVILEGES
| REGISTER
| REPLICA
| REPLICAS
| REPLICATION
| REVOKE
| ROLE
| ROLES
| QUOTE
| STATS
| SYNC
| TIMEOUT
| TO
| UNLOCK
| USER
| USERS
;
Then we define the name of our query. In this case it will be freeMemoryQuery
and we add it to the query
:
query : cypherQuery
| indexQuery
| explainQuery
| profileQuery
| infoQuery
| constraintQuery
| authQuery
| dumpQuery
| replicationQuery
| lockPathQuery
| freeMemoryQuery
;
Add the end of the file, we simply define the query:
freeMemoryQuery : FREE MEMORY ;
You can take a look at the replication and authentication queries in the same file to see how to define more complex queries.