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/MemgraphCypherLexer.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.
After we defined the query we now need to add the logic for it. First, we need to define the class which can be accessed by the visitor. By doing so, we can add a more complex parsing logic for our queries.