From 0e7e84b9953e5bf815900d4d750a46997cf1a6e5 Mon Sep 17 00:00:00 2001
From: dutor <440396+dutor@users.noreply.github.com>
Date: Sun, 16 Dec 2018 21:23:28 +0800
Subject: [PATCH] Refactor the source tree (#41)

---
 CMakeLists.txt                                | 151 ++++++-------
 CONTRIBUTING.md                               | 168 --------------
 conf/CMakeLists.txt                           |   1 +
 conf/nebula-graphd.conf.default               |  28 +++
 src/CMakeLists.txt                            |  11 +
 src/README.md                                 |   1 +
 src/console/CMakeLists.txt                    |  10 +-
 src/console/CliManager.cpp                    |  15 +-
 src/console/CliManager.h                      |   8 +-
 src/console/CmdProcessor.cpp                  |   8 +-
 src/console/CmdProcessor.h                    |  14 +-
 .../{GraphDbConsole.cpp => NebulaConsole.cpp} |   6 +-
 src/console/README.md                         |   1 +
 src/daemons/CMakeLists.txt                    |  33 +++
 src/daemons/GraphDaemon.cpp                   | 123 ++++++++++
 src/daemons/README.md                         |   1 +
 src/executor/AlterEdgeExecutor.cpp            |  31 +++
 src/executor/AlterEdgeExecutor.h              |  35 +++
 src/executor/AlterTagExecutor.cpp             |  31 +++
 src/executor/AlterTagExecutor.h               |  36 +++
 src/executor/Authenticator.h                  |  26 +++
 src/executor/CMakeLists.txt                   |  33 +++
 src/executor/ClientSession.cpp                |  33 +++
 src/executor/ClientSession.h                  |  69 ++++++
 src/executor/CompoundExecutor.cpp             |  74 ++++++
 src/executor/CompoundExecutor.h               |  41 ++++
 src/executor/DefineEdgeExecutor.cpp           |  36 +++
 src/executor/DefineEdgeExecutor.h             |  35 +++
 src/executor/DefineTagExecutor.cpp            |  34 +++
 src/executor/DefineTagExecutor.h              |  36 +++
 src/executor/DescribeEdgeExecutor.cpp         |  75 +++++++
 src/executor/DescribeEdgeExecutor.h           |  38 ++++
 src/executor/DescribeTagExecutor.cpp          |  59 +++++
 src/executor/DescribeTagExecutor.h            |  39 ++++
 src/executor/ExecutionContext.cpp             |  15 ++
 src/executor/ExecutionContext.h               |  56 +++++
 src/executor/ExecutionEngine.cpp              |  36 +++
 src/executor/ExecutionEngine.h                |  42 ++++
 src/executor/ExecutionPlan.cpp                |  78 +++++++
 src/executor/ExecutionPlan.h                  |  62 +++++
 src/executor/Executor.cpp                     |  75 +++++++
 src/executor/Executor.h                       |  85 +++++++
 src/executor/GoExecutor.cpp                   | 212 ++++++++++++++++++
 src/executor/GoExecutor.h                     |  66 ++++++
 src/executor/GraphFlags.cpp                   |  21 ++
 src/executor/GraphFlags.h                     |  26 +++
 src/executor/GraphService.cpp                 | 104 +++++++++
 src/executor/GraphService.h                   |  43 ++++
 src/executor/InsertEdgeExecutor.cpp           |  55 +++++
 src/executor/InsertEdgeExecutor.h             |  42 ++++
 src/executor/InsertVertexExecutor.cpp         |  50 +++++
 src/executor/InsertVertexExecutor.h           |  40 ++++
 src/executor/PipeExecutor.cpp                 | 112 +++++++++
 src/executor/PipeExecutor.h                   |  50 +++++
 src/executor/README.md                        |   1 +
 src/executor/RequestContext.h                 |  95 ++++++++
 src/executor/SessionManager.cpp               | 105 +++++++++
 src/executor/SessionManager.h                 |  60 +++++
 src/executor/SimpleAuthenticator.h            |  32 +++
 src/executor/TraverseExecutor.cpp             |  37 +++
 src/executor/TraverseExecutor.h               |  97 ++++++++
 src/executor/UseExecutor.cpp                  |  34 +++
 src/executor/UseExecutor.h                    |  36 +++
 src/executor/mock/EdgeSchema.cpp              |  32 +++
 src/executor/mock/EdgeSchema.h                |  89 ++++++++
 src/executor/mock/PropertiesSchema.cpp        |  55 +++++
 src/executor/mock/PropertiesSchema.h          |  42 ++++
 src/executor/mock/SchemaManager.cpp           |  70 ++++++
 src/executor/mock/SchemaManager.h             |  43 ++++
 src/executor/mock/StorageService.cpp          | 107 +++++++++
 src/executor/mock/StorageService.h            |  86 +++++++
 src/executor/mock/TagSchema.cpp               |  34 +++
 src/executor/mock/TagSchema.h                 |  51 +++++
 src/executor/test/CMakeLists.txt              |  71 ++++++
 src/executor/test/DefineSchemaTest.cpp        | 122 ++++++++++
 src/executor/test/SessionManagerTest.cpp      |  82 +++++++
 src/executor/test/TestBase.cpp                |  21 ++
 src/executor/test/TestBase.h                  | 204 +++++++++++++++++
 src/executor/test/TestEnv.cpp                 |  69 ++++++
 src/executor/test/TestEnv.h                   |  51 +++++
 src/executor/test/TestMain.cpp                |  21 ++
 src/parser/.gitignore                         |   6 +-
 src/parser/CMakeLists.txt                     |   6 +-
 src/parser/Clauses.cpp                        |   4 +-
 src/parser/Clauses.h                          |   2 +-
 src/parser/CompoundSentence.cpp               |   4 +-
 src/parser/CompoundSentence.h                 |   8 +-
 src/parser/Expressions.cpp                    |   4 +-
 src/parser/Expressions.h                      |   4 +-
 src/parser/GQLParser.cpp                      |   4 +-
 src/parser/GQLParser.h                        |  12 +-
 .../{VGraphScanner.h => GraphScanner.h}       |  24 +-
 src/parser/MaintainSentences.cpp              |   4 +-
 src/parser/MaintainSentences.h                |   4 +-
 src/parser/MutateSentences.cpp                |   4 +-
 src/parser/MutateSentences.h                  |   4 +-
 src/parser/README.md                          |   1 +
 src/parser/Sentence.h                         |   4 +-
 src/parser/TraverseSentences.cpp              |   4 +-
 src/parser/TraverseSentences.h                |   4 +-
 src/parser/parser.yy                          |  72 +++---
 src/parser/scanner.lex                        |   8 +-
 src/parser/test/ParserTest.cpp                |   4 +-
 src/parser/test/ScannerTest.cpp               |  18 +-
 104 files changed, 4189 insertions(+), 377 deletions(-)
 delete mode 100644 CONTRIBUTING.md
 create mode 100644 conf/CMakeLists.txt
 create mode 100644 conf/nebula-graphd.conf.default
 create mode 100644 src/CMakeLists.txt
 create mode 100644 src/README.md
 rename src/console/{GraphDbConsole.cpp => NebulaConsole.cpp} (78%)
 create mode 100644 src/console/README.md
 create mode 100644 src/daemons/CMakeLists.txt
 create mode 100644 src/daemons/GraphDaemon.cpp
 create mode 100644 src/daemons/README.md
 create mode 100644 src/executor/AlterEdgeExecutor.cpp
 create mode 100644 src/executor/AlterEdgeExecutor.h
 create mode 100644 src/executor/AlterTagExecutor.cpp
 create mode 100644 src/executor/AlterTagExecutor.h
 create mode 100644 src/executor/Authenticator.h
 create mode 100644 src/executor/CMakeLists.txt
 create mode 100644 src/executor/ClientSession.cpp
 create mode 100644 src/executor/ClientSession.h
 create mode 100644 src/executor/CompoundExecutor.cpp
 create mode 100644 src/executor/CompoundExecutor.h
 create mode 100644 src/executor/DefineEdgeExecutor.cpp
 create mode 100644 src/executor/DefineEdgeExecutor.h
 create mode 100644 src/executor/DefineTagExecutor.cpp
 create mode 100644 src/executor/DefineTagExecutor.h
 create mode 100644 src/executor/DescribeEdgeExecutor.cpp
 create mode 100644 src/executor/DescribeEdgeExecutor.h
 create mode 100644 src/executor/DescribeTagExecutor.cpp
 create mode 100644 src/executor/DescribeTagExecutor.h
 create mode 100644 src/executor/ExecutionContext.cpp
 create mode 100644 src/executor/ExecutionContext.h
 create mode 100644 src/executor/ExecutionEngine.cpp
 create mode 100644 src/executor/ExecutionEngine.h
 create mode 100644 src/executor/ExecutionPlan.cpp
 create mode 100644 src/executor/ExecutionPlan.h
 create mode 100644 src/executor/Executor.cpp
 create mode 100644 src/executor/Executor.h
 create mode 100644 src/executor/GoExecutor.cpp
 create mode 100644 src/executor/GoExecutor.h
 create mode 100644 src/executor/GraphFlags.cpp
 create mode 100644 src/executor/GraphFlags.h
 create mode 100644 src/executor/GraphService.cpp
 create mode 100644 src/executor/GraphService.h
 create mode 100644 src/executor/InsertEdgeExecutor.cpp
 create mode 100644 src/executor/InsertEdgeExecutor.h
 create mode 100644 src/executor/InsertVertexExecutor.cpp
 create mode 100644 src/executor/InsertVertexExecutor.h
 create mode 100644 src/executor/PipeExecutor.cpp
 create mode 100644 src/executor/PipeExecutor.h
 create mode 100644 src/executor/README.md
 create mode 100644 src/executor/RequestContext.h
 create mode 100644 src/executor/SessionManager.cpp
 create mode 100644 src/executor/SessionManager.h
 create mode 100644 src/executor/SimpleAuthenticator.h
 create mode 100644 src/executor/TraverseExecutor.cpp
 create mode 100644 src/executor/TraverseExecutor.h
 create mode 100644 src/executor/UseExecutor.cpp
 create mode 100644 src/executor/UseExecutor.h
 create mode 100644 src/executor/mock/EdgeSchema.cpp
 create mode 100644 src/executor/mock/EdgeSchema.h
 create mode 100644 src/executor/mock/PropertiesSchema.cpp
 create mode 100644 src/executor/mock/PropertiesSchema.h
 create mode 100644 src/executor/mock/SchemaManager.cpp
 create mode 100644 src/executor/mock/SchemaManager.h
 create mode 100644 src/executor/mock/StorageService.cpp
 create mode 100644 src/executor/mock/StorageService.h
 create mode 100644 src/executor/mock/TagSchema.cpp
 create mode 100644 src/executor/mock/TagSchema.h
 create mode 100644 src/executor/test/CMakeLists.txt
 create mode 100644 src/executor/test/DefineSchemaTest.cpp
 create mode 100644 src/executor/test/SessionManagerTest.cpp
 create mode 100644 src/executor/test/TestBase.cpp
 create mode 100644 src/executor/test/TestBase.h
 create mode 100644 src/executor/test/TestEnv.cpp
 create mode 100644 src/executor/test/TestEnv.h
 create mode 100644 src/executor/test/TestMain.cpp
 rename src/parser/{VGraphScanner.h => GraphScanner.h} (53%)
 create mode 100644 src/parser/README.md

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 24cdcc0b..159990dd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,17 +9,17 @@
 #   CMAKE_C_COMPILER        -- Specify the compiler for C language
 #   CMAKE_CXX_COMPILER      -- Specify the compiler for C++ language
 #   FLEX_EXECUTABLE         -- Specify the full path of flex executable
-#   VGRAPH_GPERF_BIN_DIR    -- Specify the full path to the directory
+#   NEBULA_GPERF_BIN_DIR    -- Specify the full path to the directory
 #                              containing gperf binary
 #
-#   VGRAPH_KRB5_ROOT        -- Specify the root directory for KRB5
-#   VGRAPH_LIBUNWIND_ROOT   -- Specify the root directory for libunwind
-#   VGRAPH_OPENSSL_ROOT     -- Specify the root directory for openssl
-#   VGRAPH_BOOST_ROOT       -- Specify the root directory for boost
+#   NEBULA_KRB5_ROOT        -- Specify the root directory for KRB5
+#   NEBULA_LIBUNWIND_ROOT   -- Specify the root directory for libunwind
+#   NEBULA_OPENSSL_ROOT     -- Specify the root directory for openssl
+#   NEBULA_BOOST_ROOT       -- Specify the root directory for boost
 #
 cmake_minimum_required(VERSION 3.0.0)
 
-project("vGraph" C CXX)
+project("Nebula Graph" C CXX)
 
 set(CMAKE_SKIP_RPATH TRUE)
 
@@ -35,6 +35,10 @@ set(CMAKE_CXX_STANDARD 14)
 
 set(CMAKE_EXE_LINKER_FLAGS "-static-libstdc++")
 
+if (NOT THIRD_PARTY_JOBS)
+    set(THIRD_PARTY_JOBS 2)
+endif(NOT THIRD_PARTY_JOBS)
+
 # Possible values are Debug, Release, RelWithDebInfo, MinSizeRel
 if(NOT CMAKE_BUILD_TYPE)
     set(CMAKE_BUILD_TYPE "Debug")
@@ -46,39 +50,39 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "_build")
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "_build")
 
 # Set the project home dir
-set(VGRAPH_HOME ${CMAKE_CURRENT_SOURCE_DIR})
+set(NEBULA_HOME ${CMAKE_CURRENT_SOURCE_DIR})
 
 # To include customized FindXXX.cmake modules
-set(CMAKE_MODULE_PATH "${VGRAPH_HOME}/cmake" ${CMAKE_MODULE_PATH})
+set(CMAKE_MODULE_PATH "${NEBULA_HOME}/cmake" ${CMAKE_MODULE_PATH})
 
-if(NOT ${VGRAPH_KRB5_ROOT} STREQUAL "")
-    message(STATUS "Specified VGRAPH_KRB5_ROOT: " ${VGRAPH_KRB5_ROOT})
-    list(APPEND CMAKE_INCLUDE_PATH ${VGRAPH_KRB5_ROOT}/include)
-    list(APPEND CMAKE_LIBRARY_PATH ${VGRAPH_KRB5_ROOT}/lib)
-    list(APPEND CMAKE_PROGRAM_PATH ${VGRAPH_KRB5_ROOT}/bin)
+if(NOT ${NEBULA_KRB5_ROOT} STREQUAL "")
+    message(STATUS "Specified NEBULA_KRB5_ROOT: " ${NEBULA_KRB5_ROOT})
+    list(APPEND CMAKE_INCLUDE_PATH ${NEBULA_KRB5_ROOT}/include)
+    list(APPEND CMAKE_LIBRARY_PATH ${NEBULA_KRB5_ROOT}/lib)
+    list(APPEND CMAKE_PROGRAM_PATH ${NEBULA_KRB5_ROOT}/bin)
 endif()
 
-if(NOT ${VGRAPH_LIBUNWIND_ROOT} STREQUAL "")
-    message(STATUS "Specified VGRAPH_LIBUNWIND_ROOT: " ${VGRAPH_LIBUNWIND_ROOT})
-    list(APPEND CMAKE_INCLUDE_PATH ${VGRAPH_LIBUNWIND_ROOT}/include)
-    list(APPEND CMAKE_LIBRARY_PATH ${VGRAPH_LIBUNWIND_ROOT}/lib)
+if(NOT ${NEBULA_LIBUNWIND_ROOT} STREQUAL "")
+    message(STATUS "Specified NEBULA_LIBUNWIND_ROOT: " ${NEBULA_LIBUNWIND_ROOT})
+    list(APPEND CMAKE_INCLUDE_PATH ${NEBULA_LIBUNWIND_ROOT}/include)
+    list(APPEND CMAKE_LIBRARY_PATH ${NEBULA_LIBUNWIND_ROOT}/lib)
 endif()
 
-if(NOT ${VGRAPH_OPENSSL_ROOT} STREQUAL "")
-    message(STATUS "Specified VGRAPH_OPENSSL_ROOT: " ${VGRAPH_OPENSSL_ROOT})
-    list(APPEND CMAKE_INCLUDE_PATH ${VGRAPH_OPENSSL_ROOT}/include)
-    list(APPEND CMAKE_LIBRARY_PATH ${VGRAPH_OPENSSL_ROOT}/lib)
+if(NOT ${NEBULA_OPENSSL_ROOT} STREQUAL "")
+    message(STATUS "Specified NEBULA_OPENSSL_ROOT: " ${NEBULA_OPENSSL_ROOT})
+    list(APPEND CMAKE_INCLUDE_PATH ${NEBULA_OPENSSL_ROOT}/include)
+    list(APPEND CMAKE_LIBRARY_PATH ${NEBULA_OPENSSL_ROOT}/lib)
 endif()
 
-if(NOT ${VGRAPH_BOOST_ROOT} STREQUAL "")
-    message(STATUS "Specified VGRAPH_BOOST_ROOT: " ${VGRAPH_BOOST_ROOT})
-    list(APPEND CMAKE_INCLUDE_PATH ${VGRAPH_BOOST_ROOT}/include)
-    list(APPEND CMAKE_LIBRARY_PATH ${VGRAPH_BOOST_ROOT}/lib)
+if(NOT ${NEBULA_BOOST_ROOT} STREQUAL "")
+    message(STATUS "Specified NEBULA_BOOST_ROOT: " ${NEBULA_BOOST_ROOT})
+    list(APPEND CMAKE_INCLUDE_PATH ${NEBULA_BOOST_ROOT}/include)
+    list(APPEND CMAKE_LIBRARY_PATH ${NEBULA_BOOST_ROOT}/lib)
 endif()
 
-if(NOT ${VGRAPH_GPERF_BIN_DIR} STREQUAL "")
-    message(STATUS "Specified VGRAPH_GPERF_BIN_DIR: " ${VGRAPH_GPERF_BIN_DIR})
-    list(APPEND CMAKE_PROGRAM_PATH ${VGRAPH_GPERF_BIN_DIR})
+if(NOT ${NEBULA_GPERF_BIN_DIR} STREQUAL "")
+    message(STATUS "Specified NEBULA_GPERF_BIN_DIR: " ${NEBULA_GPERF_BIN_DIR})
+    list(APPEND CMAKE_PROGRAM_PATH ${NEBULA_GPERF_BIN_DIR})
 endif()
 
 message(STATUS "CMAKE_INCLUDE_PATH: " ${CMAKE_INCLUDE_PATH})
@@ -98,53 +102,53 @@ find_package(Readline REQUIRED)
 add_compile_options(-Winvalid-pch)
 add_compile_options(-Wall)
 add_compile_options(-Werror)
-add_compile_options(-Wno-error=sign-compare)
+add_compile_options(-Wunused-parameter)
 add_compile_options(-Wshadow)
 
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/bzip2/_install/include)
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/double-conversion/_install/include)
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/fatal/_install/include)
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/fbthrift/_install/include)
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/folly/_install/include)
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/gflags/_install/include)
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/glog/_install/include)
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/googletest/_install/include)
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/jemalloc/_install/include)
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/libevent/_install/include)
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/mstch/_install/include)
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/proxygen/_install/include)
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/rocksdb/_install/include)
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/snappy/_install/include)
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/wangle/_install/include)
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/zlib/_install/include)
-include_directories(SYSTEM ${VGRAPH_HOME}/third-party/zstd/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/bzip2/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/double-conversion/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/fatal/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/fbthrift/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/folly/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/gflags/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/glog/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/googletest/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/jemalloc/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/libevent/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/mstch/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/proxygen/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/rocksdb/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/snappy/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/wangle/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/zlib/_install/include)
+include_directories(SYSTEM ${NEBULA_HOME}/third-party/zstd/_install/include)
 include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
 include_directories(SYSTEM ${OPENSSL_INCLUDE_DIR})
 include_directories(SYSTEM ${KRB5_INCLUDE_DIRS})
 include_directories(SYSTEM ${FLEX_INCLUDE_DIRS})
 include_directories(SYSTEM ${Readline_INCLUDE_DIR})
-include_directories(AFTER common)
-include_directories(AFTER interface)
-include_directories(AFTER ${VGRAPH_HOME})
+include_directories(AFTER ${NEBULA_HOME}/src)
+include_directories(AFTER src/common)
+include_directories(AFTER src/interface)
 
 link_directories(
-    ${VGRAPH_HOME}/third-party/bzip2/_install/lib
-    ${VGRAPH_HOME}/third-party/double-conversion/_install/lib
-    ${VGRAPH_HOME}/third-party/fatal/_install/lib
-    ${VGRAPH_HOME}/third-party/fbthrift/_install/lib
-    ${VGRAPH_HOME}/third-party/folly/_install/lib
-    ${VGRAPH_HOME}/third-party/gflags/_install/lib
-    ${VGRAPH_HOME}/third-party/glog/_install/lib
-    ${VGRAPH_HOME}/third-party/googletest/_install/lib
-    ${VGRAPH_HOME}/third-party/jemalloc/_install/lib
-    ${VGRAPH_HOME}/third-party/libevent/_install/lib
-    ${VGRAPH_HOME}/third-party/mstch/_install/lib
-    ${VGRAPH_HOME}/third-party/proxygen/_install/lib
-    ${VGRAPH_HOME}/third-party/rocksdb/_install/lib64
-    ${VGRAPH_HOME}/third-party/snappy/_install/lib
-    ${VGRAPH_HOME}/third-party/wangle/_install/lib
-    ${VGRAPH_HOME}/third-party/zlib/_install/lib
-    ${VGRAPH_HOME}/third-party/zstd/_install/lib
+    ${NEBULA_HOME}/third-party/bzip2/_install/lib
+    ${NEBULA_HOME}/third-party/double-conversion/_install/lib
+    ${NEBULA_HOME}/third-party/fatal/_install/lib
+    ${NEBULA_HOME}/third-party/fbthrift/_install/lib
+    ${NEBULA_HOME}/third-party/folly/_install/lib
+    ${NEBULA_HOME}/third-party/gflags/_install/lib
+    ${NEBULA_HOME}/third-party/glog/_install/lib
+    ${NEBULA_HOME}/third-party/googletest/_install/lib
+    ${NEBULA_HOME}/third-party/jemalloc/_install/lib
+    ${NEBULA_HOME}/third-party/libevent/_install/lib
+    ${NEBULA_HOME}/third-party/mstch/_install/lib
+    ${NEBULA_HOME}/third-party/proxygen/_install/lib
+    ${NEBULA_HOME}/third-party/rocksdb/_install/lib64
+    ${NEBULA_HOME}/third-party/snappy/_install/lib
+    ${NEBULA_HOME}/third-party/wangle/_install/lib
+    ${NEBULA_HOME}/third-party/zlib/_install/lib
+    ${NEBULA_HOME}/third-party/zstd/_install/lib
     ${Boost_LIBRARY_DIRS}
     ${KRB5_LIBRARY_DIRS}
 )
@@ -163,22 +167,15 @@ set(THRIFT_LIBRARIES
     thrift-core
 )
 
-set(ROCKSDB_LIBRARIES ${VGRAPH_HOME}/third-party/rocksdb/_install/lib64/librocksdb.a)
+set(ROCKSDB_LIBRARIES ${NEBULA_HOME}/third-party/rocksdb/_install/lib64/librocksdb.a)
 
 # All compression libraries
 set(COMPRESSION_LIBRARIES bz2 snappy zstd z)
 
 add_subdirectory(third-party)
-add_subdirectory(interface)
-add_subdirectory(common)
-add_subdirectory(meta)
-add_subdirectory(dataman)
-add_subdirectory(client)
-add_subdirectory(vgraphd)
-add_subdirectory(console)
-add_subdirectory(raftex)
-add_subdirectory(storage)
-add_subdirectory(parser)
+add_subdirectory(src)
+add_subdirectory(etc)
+add_subdirectory(scripts)
 
 add_dependencies(common third-party)
 #add_dependencies(storage_engines common)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index 28e15eac..00000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,168 +0,0 @@
-## Workflow
-
-### Step 1: Fork in the cloud
-
-1. Visit https://github.com/vesoft-inc/vgraph
-2. Click `Fork` button (top right) to establish a cloud-based fork.
-
-### Step 2: Clone fork to local storage
-
-Define a local working directory:
-
-```sh
-# Define your working directory
-working_dir=$HOME/Workspace
-```
-
-Set `user` to match your github profile name:
-
-```sh
-user={your github profile name}
-```
-
-Create your clone:
-
-```sh
-mkdir -p $working_dir
-cd $working_dir
-git clone https://github.com/$user/vgraph.git
-# the following is recommended
-# or: git clone git@github.com:$user/vgraph.git
-
-cd $working_dir/vgraph
-git remote add upstream https://github.com/vesoft-inc/vgraph.git
-# or: git remote add upstream git@github.com:vesoft-inc/vgraph.git
-
-# Never push to upstream master since you do not have write access.
-git remote set-url --push upstream no_push
-
-# Confirm that your remotes make sense:
-# It should look like:
-# origin    git@github.com:$(user)/vgraph.git (fetch)
-# origin    git@github.com:$(user)/vgraph.git (push)
-# upstream  https://github.com/vesoft-inc/vgraph (fetch)
-# upstream  no_push (push)
-git remote -v
-```
-
-#### Define a pre-commit hook
-
-Please link the vGraph pre-commit hook into your `.git` directory.
-
-This hook checks your commits for formatting, building, doc generation, etc.
-
-```sh
-cd $working_dir/vgraph/.git/hooks
-ln -s ../../hooks/pre-commit .
-```
-Sometime, pre-commit hook can not be executable. In such case, you have to make it executable manually.
-
-```sh
-cd $working_dir/vgraph/.git/hooks
-chmod +x pre-commit
-```
-
-### Step 3: Branch
-
-Get your local master up to date:
-
-```sh
-cd $working_dir/vgraph
-git fetch upstream
-git checkout master
-git rebase upstream/master
-```
-
-Branch from master:
-
-```sh
-git checkout -b myfeature
-```
-**NOTE**: Because your PR often consists of several commits, which might be squashed while being merged into upstream,
-we strongly suggest you open a separate topic branch to make your changes on. After merged,
-this topic branch could be just abandoned, thus you could synchronize your master branch with
-upstream easily with a rebase like above. Otherwise, if you commit your changes directly into master,
-maybe you must use a hard reset on the master branch, like:
-
-```sh
-git fetch upstream
-git checkout master
-git reset --hard upstream/master
-git push --force origin master
-```
-
-### Step 4: Develop
-
-#### Edit the code
-
-You can now edit the code on the `myfeature` branch. Please follow the coding style guidance [here](docs/cpp-coding-style.md)
-
-#### Run stand-alone mode
-
-If you want to reproduce and investigate an issue, you may need
-to run vGraph in stand-alone mode.
-
-```sh
-# Build the binary.
-make server
-
-# Run in stand-alone mode.
-vgraphd
-```
-
-Then you can connect the vGraph console to your local server
-```sh
-vgraph
-```
-
-#### Run Test
-
-```sh
-# Run unit test to make sure all test passed.
-```
-
-### Step 5: Keep your branch in sync
-
-```sh
-# While on your myfeature branch.
-git fetch upstream
-git rebase upstream/master
-```
-
-### Step 6: Commit
-
-Commit your changes.
-
-```sh
-git commit
-```
-
-Likely you'll go back and edit/build/test some more than `commit --amend`
-in a few cycles.
-
-### Step 7: Push
-
-When ready to review (or just to establish an offsite backup or your work),
-push your branch to your fork on `github.com`:
-
-```sh
-git push -f origin myfeature
-```
-
-### Step 8: Create a pull request
-
-1. Visit your fork at https://github.com/$user/vgraph (replace `$user` obviously).
-2. Click the `Compare & pull request` button next to your `myfeature` branch.
-
-### Step 9: Get a code review
-
-Once your pull request has been opened, it will be assigned to at least one
-reviewers. Those reviewers will do a thorough code review, looking for
-correctness, bugs, opportunities for improvement, documentation and comments,
-and style.
-
-Commit changes made in response to review comments to the same branch on your
-fork.
-
-Very small PRs are easy to review. Very large PRs are very difficult to
-review.
diff --git a/conf/CMakeLists.txt b/conf/CMakeLists.txt
new file mode 100644
index 00000000..4e7e2cbe
--- /dev/null
+++ b/conf/CMakeLists.txt
@@ -0,0 +1 @@
+install(FILES nebula-graphd.conf.default DESTINATION etc)
diff --git a/conf/nebula-graphd.conf.default b/conf/nebula-graphd.conf.default
new file mode 100644
index 00000000..9edf937d
--- /dev/null
+++ b/conf/nebula-graphd.conf.default
@@ -0,0 +1,28 @@
+########## logging ##########
+--log_dir=/tmp/nebula-graphd
+# 0, 1, 2, 3 for INFO, WARNING, ERROR, FATAL respectively
+--minloglevel=0
+# verbose loging level, 1, 2, 3, 4, the higher of the level, the more verbose of the logging
+--v=4
+# maximum seconds to buffer the log messages
+--logbufsecs=0
+# Whether to redirect stdout and stderr to separate output files
+--redirect_stdout=true
+# Destination filename of stdout and stderr, which will also reside in log_dir.
+--stdout_log_file=stdout.log
+--stderr_log_file=stderr.log
+
+########## networking ##########
+--port=3699
+# seconds before we close the idle connections, 0 for infinite
+--client_idle_timeout_secs=0
+# seconds before we expire the idle sessions, 0 for inifnite
+--session_idle_timeout_secs=60000
+# number of threads to accept incoming connections
+--num_accept_threads=1
+# number of networking IO threads, 0 for number of physical CPU cores
+--num_netio_threads=0
+# turn on SO_REUSEPORT or not
+--reuse_port=false
+# Backlog of the listen socket, adjust this together with net.core.somaxconn
+--listen_backlog=1024
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 00000000..60f73183
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_subdirectory(common)
+add_subdirectory(interface)
+add_subdirectory(client)
+add_subdirectory(meta)
+add_subdirectory(console)
+add_subdirectory(raftex)
+add_subdirectory(storage)
+add_subdirectory(parser)
+add_subdirectory(dataman)
+add_subdirectory(graph)
+add_subdirectory(daemons)
diff --git a/src/README.md b/src/README.md
new file mode 100644
index 00000000..07dd0c5c
--- /dev/null
+++ b/src/README.md
@@ -0,0 +1 @@
+# Overview
diff --git a/src/console/CMakeLists.txt b/src/console/CMakeLists.txt
index a35963b3..43177149 100644
--- a/src/console/CMakeLists.txt
+++ b/src/console/CMakeLists.txt
@@ -2,17 +2,17 @@ add_library(console_obj OBJECT CliManager.cpp CmdProcessor.cpp)
 add_dependencies(console_obj common)
 
 add_executable(
-    vgraph
-    GraphDbConsole.cpp
+    nebula
+    NebulaConsole.cpp
     $<TARGET_OBJECTS:console_obj>
     $<TARGET_OBJECTS:client_cpp_obj>
     $<TARGET_OBJECTS:base_obj>
-    $<TARGET_OBJECTS:vgraph_thrift_obj>
+    $<TARGET_OBJECTS:graph_thrift_obj>
     $<TARGET_OBJECTS:time_obj>
     $<TARGET_OBJECTS:thread_obj>
 )
 target_link_libraries(
-    vgraph
+    nebula
     thriftcpp2
     thrift
     thrift-core
@@ -44,5 +44,7 @@ target_link_libraries(
     -pthread
 )
 
+install(TARGETS nebula DESTINATION bin)
+
 #add_subdirectory(test)
 
diff --git a/src/console/CliManager.cpp b/src/console/CliManager.cpp
index bebc3038..9afde2af 100644
--- a/src/console/CliManager.cpp
+++ b/src/console/CliManager.cpp
@@ -8,10 +8,10 @@
 #include <readline/readline.h>
 #include <readline/history.h>
 #include "console/CliManager.h"
-#include "client/cpp/GraphDbClient.h"
+#include "client/cpp/GraphClient.h"
 
-namespace vesoft {
-namespace vgraph {
+namespace nebula {
+namespace graph {
 
 const int32_t kMaxAuthInfoRetries = 3;
 const int32_t kMaxUsernameLen = 16;
@@ -61,10 +61,10 @@ bool CliManager::connect(const std::string& addr,
     port_ = port;
     username_ = user;
 
-    auto client = std::make_unique<GraphDbClient>(addr_, port_);
+    auto client = std::make_unique<GraphClient>(addr_, port_);
     cpp2::ErrorCode res = client->connect(user, pass);
     if (res == cpp2::ErrorCode::SUCCEEDED) {
-        std::cerr << "\nWelcome to vGraph (Version 0.1)\n\n";
+        std::cerr << "\nWelcome to Nebula Graph (Version 0.1)\n\n";
         cmdProcessor_ = std::make_unique<CmdProcessor>(std::move(client));
         return true;
     } else {
@@ -76,6 +76,7 @@ bool CliManager::connect(const std::string& addr,
 
 
 void CliManager::batch(const std::string& filename) {
+    UNUSED(filename);
 }
 
 
@@ -190,5 +191,5 @@ void CliManager::loadHistory() {
     ::fclose(file);
 }
 
-}  // namespace vgraph
-}  // namespace vesoft
+}  // namespace graph
+}  // namespace nebula
diff --git a/src/console/CliManager.h b/src/console/CliManager.h
index dc48f865..fac2b8bc 100644
--- a/src/console/CliManager.h
+++ b/src/console/CliManager.h
@@ -10,8 +10,8 @@
 #include "base/Base.h"
 #include "console/CmdProcessor.h"
 
-namespace vesoft {
-namespace vgraph {
+namespace nebula {
+namespace graph {
 
 class CliManager final {
 public:
@@ -43,6 +43,6 @@ private:
     std::unique_ptr<CmdProcessor> cmdProcessor_;
 };
 
-}  // namespace vgraph
-}  // namespace vesoft
+}  // namespace graph
+}  // namespace nebula
 #endif  // CONSOLE_CLIMANAGER_H_
diff --git a/src/console/CmdProcessor.cpp b/src/console/CmdProcessor.cpp
index 4afa6f3a..79c5250b 100644
--- a/src/console/CmdProcessor.cpp
+++ b/src/console/CmdProcessor.cpp
@@ -8,8 +8,8 @@
 #include "console/CmdProcessor.h"
 #include "time/Duration.h"
 
-namespace vesoft {
-namespace vgraph {
+namespace nebula {
+namespace graph {
 
 #define GET_VALUE_WIDTH(VT, FN, FMT) \
     VT val = col.get_ ## FN(); \
@@ -377,6 +377,6 @@ bool CmdProcessor::process(folly::StringPiece cmd) {
     return true;
 }
 
-}  // namespace vgraph
-}  // namespace vesoft
+}  // namespace graph
+}  // namespace nebula
 
diff --git a/src/console/CmdProcessor.h b/src/console/CmdProcessor.h
index 8de95f7c..7bff6829 100644
--- a/src/console/CmdProcessor.h
+++ b/src/console/CmdProcessor.h
@@ -8,14 +8,14 @@
 #define CONSOLE_CMDPROCESSOR_H_
 
 #include "base/Base.h"
-#include "client/cpp/GraphDbClient.h"
+#include "client/cpp/GraphClient.h"
 
-namespace vesoft {
-namespace vgraph {
+namespace nebula {
+namespace graph {
 
 class CmdProcessor final {
 public:
-    explicit CmdProcessor(std::unique_ptr<GraphDbClient> client)
+    explicit CmdProcessor(std::unique_ptr<GraphClient> client)
         : client_(std::move(client)) {}
     ~CmdProcessor() = default;
 
@@ -26,7 +26,7 @@ public:
     bool process(folly::StringPiece cmd);
 
 private:
-    std::unique_ptr<GraphDbClient> client_;
+    std::unique_ptr<GraphClient> client_;
 
     // The method returns true if the given command is a client command
     // and has been processed. Otherwise, the method returns false
@@ -47,6 +47,6 @@ private:
                    const std::vector<std::string>& formats) const;
 };
 
-}  // namespace vgraph
-}  // namespace vesoft
+}  // namespace graph
+}  // namespace nebula
 #endif  // CONSOLE_CMDPROCESSOR_H_
diff --git a/src/console/GraphDbConsole.cpp b/src/console/NebulaConsole.cpp
similarity index 78%
rename from src/console/GraphDbConsole.cpp
rename to src/console/NebulaConsole.cpp
index 2d5ab9ef..30f68c05 100644
--- a/src/console/GraphDbConsole.cpp
+++ b/src/console/NebulaConsole.cpp
@@ -7,8 +7,8 @@
 #include "base/Base.h"
 #include "console/CliManager.h"
 
-DEFINE_string(addr, "127.0.0.1", "GraphDB daemon IP address");
-DEFINE_int32(port, 34500, "GraphDB daemon listening port");
+DEFINE_string(addr, "127.0.0.1", "Nebula daemon IP address");
+DEFINE_int32(port, 34500, "Nebula daemon listening port");
 DEFINE_string(username, "", "Username used to authenticate");
 DEFINE_string(password, "", "Password used to authenticate");
 
@@ -16,7 +16,7 @@ DEFINE_string(password, "", "Password used to authenticate");
 int main(int argc, char *argv[]) {
     folly::init(&argc, &argv, true);
 
-    using namespace vesoft::vgraph;
+    using namespace nebula::graph;
 
     CliManager cli;
     if (!cli.connect(FLAGS_addr, FLAGS_port, FLAGS_username, FLAGS_password)) {
diff --git a/src/console/README.md b/src/console/README.md
new file mode 100644
index 00000000..07dd0c5c
--- /dev/null
+++ b/src/console/README.md
@@ -0,0 +1 @@
+# Overview
diff --git a/src/daemons/CMakeLists.txt b/src/daemons/CMakeLists.txt
new file mode 100644
index 00000000..835f9932
--- /dev/null
+++ b/src/daemons/CMakeLists.txt
@@ -0,0 +1,33 @@
+
+add_executable(
+    nebula-graphd
+    GraphDaemon.cpp
+    $<TARGET_OBJECTS:graph_obj>
+    $<TARGET_OBJECTS:base_obj>
+    $<TARGET_OBJECTS:graph_thrift_obj>
+    $<TARGET_OBJECTS:time_obj>
+    $<TARGET_OBJECTS:fs_obj>
+    $<TARGET_OBJECTS:thread_obj>
+    $<TARGET_OBJECTS:parser_obj>
+)
+
+target_link_libraries(
+    nebula-graphd
+    ${THRIFT_LIBRARIES}
+    wangle
+    folly
+    boost_system
+    boost_context
+    ${OPENSSL_LIBRARIES}
+    ${KRB5_LIBRARIES}
+    glog
+    gflags
+    event
+    ${COMPRESSION_LIBRARIES}
+    resolv
+    double-conversion
+    dl
+    -pthread
+)
+
+install(TARGETS nebula-graphd DESTINATION bin)
diff --git a/src/daemons/GraphDaemon.cpp b/src/daemons/GraphDaemon.cpp
new file mode 100644
index 00000000..1846ce38
--- /dev/null
+++ b/src/daemons/GraphDaemon.cpp
@@ -0,0 +1,123 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include <signal.h>
+#include "base/Base.h"
+#include "base/Status.h"
+#include "fs/FileUtils.h"
+#include <thrift/lib/cpp2/server/ThriftServer.h>
+#include "graph/GraphService.h"
+#include "graph/GraphFlags.h"
+
+using namespace nebula;
+using namespace nebula::graph;
+using namespace nebula::fs;
+
+static std::unique_ptr<apache::thrift::ThriftServer> gServer;
+
+static void signalHandler(int sig);
+static Status setupSignalHandler();
+static Status setupLogging();
+
+int main(int argc, char *argv[]) {
+    folly::init(&argc, &argv, true);
+
+    auto status = setupLogging();
+    if (!status.ok()) {
+        LOG(ERROR) << status;
+        return EXIT_FAILURE;
+    }
+
+    status = setupSignalHandler();
+    if (!status.ok()) {
+        LOG(ERROR) << status;
+        return EXIT_FAILURE;
+    }
+
+    auto interface = std::make_shared<GraphService>();
+    gServer = std::make_unique<apache::thrift::ThriftServer>();
+
+    gServer->setInterface(interface);
+    gServer->setPort(FLAGS_port);
+    gServer->setReusePort(FLAGS_reuse_port);
+    gServer->setIdleTimeout(std::chrono::seconds(FLAGS_client_idle_timeout_secs));
+
+    // TODO(dutor) This only take effects on NORMAL priority threads
+    gServer->setNumCPUWorkerThreads(1);
+
+    gServer->setCPUWorkerThreadName("executor");
+    gServer->setNumAcceptThreads(FLAGS_num_accept_threads);
+    gServer->setListenBacklog(FLAGS_listen_backlog);
+    gServer->setThreadStackSizeMB(5);
+    if (FLAGS_num_netio_threads != 0) {
+        gServer->setNumIOWorkerThreads(FLAGS_num_netio_threads);
+    }
+
+    FLOG_INFO("Starting nebula-graphd on port %d\n", FLAGS_port);
+    try {
+        gServer->serve();  // Blocking wait until shut down via gServer->stop()
+    } catch (const std::exception &e) {
+        FLOG_ERROR("Exception thrown while starting the RPC server: %s", e.what());
+        return EXIT_FAILURE;
+    }
+
+    FLOG_INFO("nebula-graphd on port %d has been stopped", FLAGS_port);
+
+    return EXIT_SUCCESS;
+}
+
+
+Status setupSignalHandler() {
+    ::signal(SIGPIPE, SIG_IGN);
+    ::signal(SIGINT, signalHandler);
+    ::signal(SIGTERM, signalHandler);
+    return Status::OK();
+}
+
+
+void signalHandler(int sig) {
+    switch (sig) {
+        case SIGINT:
+        case SIGTERM:
+            FLOG_INFO("Signal %d(%s) received, stopping this server", sig, ::strsignal(sig));
+            gServer->stop();
+            break;
+        default:
+            FLOG_ERROR("Signal %d(%s) received but ignored", sig, ::strsignal(sig));
+    }
+}
+
+
+Status setupLogging() {
+    auto dup = [] (const std::string &filename, FILE *stream) -> Status {
+        auto path = FLAGS_log_dir + "/" + filename;
+        auto fd = ::open(path.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644);
+        if (fd == -1) {
+            return Status::Error("Failed to create or open `%s': %s",
+                                 path.c_str(), ::strerror(errno));
+        }
+        if (::dup2(fd, ::fileno(stream)) == -1) {
+            return Status::Error("Failed to ::dup2 from `%s' to stdout: %s",
+                                 path.c_str(), ::strerror(errno));
+        }
+        ::close(fd);
+        return Status::OK();
+    };
+
+    Status status = Status::OK();
+    do {
+        status = dup(FLAGS_stdout_log_file, stdout);
+        if (!status.ok()) {
+            break;
+        }
+        status = dup(FLAGS_stderr_log_file, stderr);
+        if (!status.ok()) {
+            break;
+        }
+    } while (false);
+
+    return status;
+}
diff --git a/src/daemons/README.md b/src/daemons/README.md
new file mode 100644
index 00000000..07dd0c5c
--- /dev/null
+++ b/src/daemons/README.md
@@ -0,0 +1 @@
+# Overview
diff --git a/src/executor/AlterEdgeExecutor.cpp b/src/executor/AlterEdgeExecutor.cpp
new file mode 100644
index 00000000..dec97e6e
--- /dev/null
+++ b/src/executor/AlterEdgeExecutor.cpp
@@ -0,0 +1,31 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/AlterEdgeExecutor.h"
+
+namespace nebula {
+namespace graph {
+
+AlterEdgeExecutor::AlterEdgeExecutor(Sentence *sentence,
+                                     ExecutionContext *ectx) : Executor(ectx) {
+    sentence_ = static_cast<AlterEdgeSentence*>(sentence);
+}
+
+
+Status AlterEdgeExecutor::prepare() {
+    return Status::OK();
+}
+
+
+void AlterEdgeExecutor::execute() {
+    if (onFinish_) {
+        onFinish_();
+    }
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/AlterEdgeExecutor.h b/src/executor/AlterEdgeExecutor.h
new file mode 100644
index 00000000..fb9dd9b0
--- /dev/null
+++ b/src/executor/AlterEdgeExecutor.h
@@ -0,0 +1,35 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_ALTEREDGEEXECUTOR_H_
+#define GRAPH_ALTEREDGEEXECUTOR_H_
+
+#include "base/Base.h"
+#include "graph/Executor.h"
+
+namespace nebula {
+namespace graph {
+
+class AlterEdgeExecutor final : public Executor {
+public:
+    AlterEdgeExecutor(Sentence *sentence, ExecutionContext *ectx);
+
+    const char* name() const override {
+        return "AlterEdgeExecutor";
+    }
+
+    Status VE_MUST_USE_RESULT prepare() override;
+
+    void execute() override;
+
+private:
+    AlterEdgeSentence                          *sentence_{nullptr};
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_ALTEREDGEEXECUTOR_H_
diff --git a/src/executor/AlterTagExecutor.cpp b/src/executor/AlterTagExecutor.cpp
new file mode 100644
index 00000000..ea53610a
--- /dev/null
+++ b/src/executor/AlterTagExecutor.cpp
@@ -0,0 +1,31 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/AlterTagExecutor.h"
+
+namespace nebula {
+namespace graph {
+
+AlterTagExecutor::AlterTagExecutor(Sentence *sentence,
+                                   ExecutionContext *ectx) : Executor(ectx) {
+    sentence_ = static_cast<AlterTagSentence*>(sentence);
+}
+
+
+Status AlterTagExecutor::prepare() {
+    return Status::OK();
+}
+
+
+void AlterTagExecutor::execute() {
+    if (onFinish_) {
+        onFinish_();
+    }
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/AlterTagExecutor.h b/src/executor/AlterTagExecutor.h
new file mode 100644
index 00000000..4c4cbbca
--- /dev/null
+++ b/src/executor/AlterTagExecutor.h
@@ -0,0 +1,36 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_ALTERTAGEXECUTOR_H_
+#define GRAPH_ALTERTAGEXECUTOR_H_
+
+#include "base/Base.h"
+#include "graph/Executor.h"
+
+namespace nebula {
+namespace graph {
+
+class AlterTagExecutor final : public Executor {
+public:
+    AlterTagExecutor(Sentence *sentence, ExecutionContext *ectx);
+
+    const char* name() const override {
+        return "AlterTagExecutor";
+    }
+
+    Status VE_MUST_USE_RESULT prepare() override;
+
+    void execute() override;
+
+private:
+    AlterTagSentence                           *sentence_{nullptr};
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+
+#endif  // GRAPH_ALTERTAGEXECUTOR_H_
diff --git a/src/executor/Authenticator.h b/src/executor/Authenticator.h
new file mode 100644
index 00000000..3ee24c60
--- /dev/null
+++ b/src/executor/Authenticator.h
@@ -0,0 +1,26 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_AUTHENTICATOR_H_
+#define GRAPH_AUTHENTICATOR_H_
+
+#include "base/Base.h"
+
+namespace nebula {
+namespace graph {
+
+class Authenticator {
+public:
+    virtual ~Authenticator() {};
+
+    virtual bool VE_MUST_USE_RESULT auth(const std::string &user,
+                                         const std::string &password) = 0;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_AUTHENTICATOR_H_
diff --git a/src/executor/CMakeLists.txt b/src/executor/CMakeLists.txt
new file mode 100644
index 00000000..76712f32
--- /dev/null
+++ b/src/executor/CMakeLists.txt
@@ -0,0 +1,33 @@
+add_library(
+    graph_obj
+    OBJECT
+    GraphFlags.cpp
+    GraphService.cpp
+    ClientSession.cpp
+    SessionManager.cpp
+    ExecutionEngine.cpp
+    ExecutionContext.cpp
+    ExecutionPlan.cpp
+    Executor.cpp
+    TraverseExecutor.cpp
+    CompoundExecutor.cpp
+    UseExecutor.cpp
+    GoExecutor.cpp
+    PipeExecutor.cpp
+    DefineEdgeExecutor.cpp
+    DefineTagExecutor.cpp
+    AlterEdgeExecutor.cpp
+    AlterTagExecutor.cpp
+    DescribeTagExecutor.cpp
+    DescribeEdgeExecutor.cpp
+    InsertVertexExecutor.cpp
+    InsertEdgeExecutor.cpp
+    mock/PropertiesSchema.cpp
+    mock/EdgeSchema.cpp
+    mock/TagSchema.cpp
+    mock/SchemaManager.cpp
+    mock/StorageService.cpp
+)
+add_dependencies(graph_obj common parser_obj graph_thrift_obj)
+
+add_subdirectory(test)
diff --git a/src/executor/ClientSession.cpp b/src/executor/ClientSession.cpp
new file mode 100644
index 00000000..b17c5634
--- /dev/null
+++ b/src/executor/ClientSession.cpp
@@ -0,0 +1,33 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/ClientSession.h"
+
+
+namespace nebula {
+namespace graph {
+
+ClientSession::ClientSession(int64_t id) {
+    id_ = id;
+}
+
+std::shared_ptr<ClientSession> ClientSession::create(int64_t id) {
+    // return std::make_shared<ClientSession>(id);
+    // `std::make_shared' cannot access ClientSession's construtor
+    return std::shared_ptr<ClientSession>(new ClientSession(id));
+}
+
+void ClientSession::charge() {
+    idleDuration_.reset();
+}
+
+uint64_t ClientSession::idleSeconds() const {
+    return idleDuration_.elapsedInSec();
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/ClientSession.h b/src/executor/ClientSession.h
new file mode 100644
index 00000000..24610991
--- /dev/null
+++ b/src/executor/ClientSession.h
@@ -0,0 +1,69 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_CLIENTSESSION_H_
+#define GRAPH_CLIENTSESSION_H_
+
+#include "base/Base.h"
+#include "time/Duration.h"
+
+/**
+ * A ClientSession holds the context informations of a session opened by a client.
+ */
+
+namespace nebula {
+namespace graph {
+
+class ClientSession final {
+public:
+    int64_t id() const {
+        return id_;
+    }
+
+    void setId(int64_t id) {
+        id_ = id;
+    }
+
+    const std::string& space() const {
+        return space_;
+    }
+
+    void setSpace(std::string space) {
+        space_ = std::move(space);
+    }
+
+    uint64_t idleSeconds() const;
+
+    const std::string& user() const {
+        return user_;
+    }
+
+    void setUser(std::string user) {
+        user_ = std::move(user);
+    }
+
+    void charge();
+
+private:
+    // ClientSession could only be created via SessionManager
+    friend class SessionManager;
+    ClientSession() = default;
+    explicit ClientSession(int64_t id);
+
+    static std::shared_ptr<ClientSession> create(int64_t id);
+
+
+private:
+    int64_t             id_{0};
+    time::Duration      idleDuration_;
+    std::string         space_;
+    std::string         user_;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_CLIENTSESSION_H_
diff --git a/src/executor/CompoundExecutor.cpp b/src/executor/CompoundExecutor.cpp
new file mode 100644
index 00000000..860c57db
--- /dev/null
+++ b/src/executor/CompoundExecutor.cpp
@@ -0,0 +1,74 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/CompoundExecutor.h"
+#include "graph/GoExecutor.h"
+#include "graph/PipeExecutor.h"
+#include "graph/UseExecutor.h"
+
+namespace nebula {
+namespace graph {
+
+CompoundExecutor::CompoundExecutor(CompoundSentence *compound,
+                                   ExecutionContext *ectx) : Executor(ectx) {
+    compound_ = compound;
+}
+
+
+Status CompoundExecutor::prepare() {
+    for (auto i = 0U; i < compound_->sentences_.size(); i++) {
+        auto *sentence = compound_->sentences_[i].get();
+        auto executor = makeExecutor(sentence);
+        DCHECK(executor != nullptr);
+        auto status = executor->prepare();
+        if (!status.ok()) {
+            FLOG_ERROR("Prepare executor `%s' failed: %s",
+                        executor->name(), status.toString().c_str());
+            return status;
+        }
+        executors_.emplace_back(std::move(executor));
+    }
+    /**
+     * For the time being, we execute sentences one by one. We may allow concurrent
+     * or out of order execution in the future.
+     */
+    // For an executor except the last one, it executes the next one on finished.
+    // If any fails, the whole execution would abort.
+    auto onError = [this] (Status status) {
+        DCHECK(onError_);
+        onError_(std::move(status));
+    };
+    for (auto i = 0U; i < executors_.size() - 1; i++) {
+        auto onFinish = [this, next = i + 1] () {
+            executors_[next]->execute();
+        };
+        executors_[i]->setOnFinish(onFinish);
+        executors_[i]->setOnError(onError);
+    }
+    // The whole execution is done upon the last executor finishes.
+    auto onFinish = [this] () {
+        DCHECK(onFinish_);
+        onFinish_();
+    };
+    executors_.back()->setOnFinish(onFinish);
+    executors_.back()->setOnError(onError);
+
+    return Status::OK();
+}
+
+
+void CompoundExecutor::execute() {
+    executors_.front()->execute();
+}
+
+
+void CompoundExecutor::setupResponse(cpp2::ExecutionResponse &resp) {
+    executors_.back()->setupResponse(resp);
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/CompoundExecutor.h b/src/executor/CompoundExecutor.h
new file mode 100644
index 00000000..259e5e53
--- /dev/null
+++ b/src/executor/CompoundExecutor.h
@@ -0,0 +1,41 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_COMPOUNDEXECUTOR_H_
+#define GRAPH_COMPOUNDEXECUTOR_H_
+
+#include "base/Base.h"
+#include "graph/Executor.h"
+
+
+namespace nebula {
+namespace graph {
+
+class CompoundExecutor final : public Executor {
+public:
+    CompoundExecutor(CompoundSentence *compound, ExecutionContext *ectx);
+
+    const char* name() const override {
+        return "CompoundExecutor";
+    }
+
+    Status VE_MUST_USE_RESULT prepare() override;
+
+    void execute() override;
+
+    void setupResponse(cpp2::ExecutionResponse &resp) override;
+
+private:
+    CompoundSentence                           *compound_{nullptr};
+    std::vector<std::unique_ptr<Executor>>      executors_;
+};
+
+
+}   // namespace graph
+}   // namespace nebula
+
+
+#endif  // GRAPH_COMPOUNDEXECUTOR_H_
diff --git a/src/executor/DefineEdgeExecutor.cpp b/src/executor/DefineEdgeExecutor.cpp
new file mode 100644
index 00000000..d574c4d5
--- /dev/null
+++ b/src/executor/DefineEdgeExecutor.cpp
@@ -0,0 +1,36 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/DefineEdgeExecutor.h"
+
+namespace nebula {
+namespace graph {
+
+DefineEdgeExecutor::DefineEdgeExecutor(Sentence *sentence,
+                                       ExecutionContext *ectx) : Executor(ectx) {
+    sentence_ = static_cast<DefineEdgeSentence*>(sentence);
+}
+
+
+Status DefineEdgeExecutor::prepare() {
+    return Status::OK();
+}
+
+
+void DefineEdgeExecutor::execute() {
+    auto *sm = ectx()->schemaManager();
+    auto *name = sentence_->name();
+    auto *src = sentence_->src();
+    auto *dst = sentence_->dst();
+    auto specs = sentence_->columnSpecs();
+    sm->addEdgeSchema(*name, *src, *dst, specs);
+    DCHECK(onFinish_);
+    onFinish_();
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/DefineEdgeExecutor.h b/src/executor/DefineEdgeExecutor.h
new file mode 100644
index 00000000..ec983bc5
--- /dev/null
+++ b/src/executor/DefineEdgeExecutor.h
@@ -0,0 +1,35 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_DEFINEEDGEEXECUTOR_H_
+#define GRAPH_DEFINEEDGEEXECUTOR_H_
+
+#include "base/Base.h"
+#include "graph/Executor.h"
+
+namespace nebula {
+namespace graph {
+
+class DefineEdgeExecutor final : public Executor {
+public:
+    DefineEdgeExecutor(Sentence *sentence, ExecutionContext *ectx);
+
+    const char* name() const override {
+        return "DefineEdgeExecutor";
+    }
+
+    Status VE_MUST_USE_RESULT prepare() override;
+
+    void execute() override;
+
+private:
+    DefineEdgeSentence                         *sentence_{nullptr};
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_DEFINEEDGEEXECUTOR_H_
diff --git a/src/executor/DefineTagExecutor.cpp b/src/executor/DefineTagExecutor.cpp
new file mode 100644
index 00000000..cd2b2427
--- /dev/null
+++ b/src/executor/DefineTagExecutor.cpp
@@ -0,0 +1,34 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/DefineTagExecutor.h"
+
+namespace nebula {
+namespace graph {
+
+DefineTagExecutor::DefineTagExecutor(Sentence *sentence,
+                                     ExecutionContext *ectx) : Executor(ectx) {
+    sentence_ = static_cast<DefineTagSentence*>(sentence);
+}
+
+
+Status DefineTagExecutor::prepare() {
+    return Status::OK();
+}
+
+
+void DefineTagExecutor::execute() {
+    auto *sm = ectx()->schemaManager();
+    auto *name = sentence_->name();
+    auto specs = sentence_->columnSpecs();
+    sm->addTagSchema(*name, specs);
+    DCHECK(onFinish_);
+    onFinish_();
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/DefineTagExecutor.h b/src/executor/DefineTagExecutor.h
new file mode 100644
index 00000000..e92fb3f2
--- /dev/null
+++ b/src/executor/DefineTagExecutor.h
@@ -0,0 +1,36 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_DEFINETAGEXECUTOR_H_
+#define GRAPH_DEFINETAGEXECUTOR_H_
+
+#include "base/Base.h"
+#include "graph/Executor.h"
+
+namespace nebula {
+namespace graph {
+
+class DefineTagExecutor final : public Executor {
+public:
+    DefineTagExecutor(Sentence *sentence, ExecutionContext *ectx);
+
+    const char* name() const override {
+        return "DefineTagExecutor";
+    }
+
+    Status VE_MUST_USE_RESULT prepare() override;
+
+    void execute() override;
+
+private:
+    DefineTagSentence                          *sentence_{nullptr};
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+
+#endif  // GRAPH_DEFINETAGEXECUTOR_H_
diff --git a/src/executor/DescribeEdgeExecutor.cpp b/src/executor/DescribeEdgeExecutor.cpp
new file mode 100644
index 00000000..a2d2331a
--- /dev/null
+++ b/src/executor/DescribeEdgeExecutor.cpp
@@ -0,0 +1,75 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/DescribeEdgeExecutor.h"
+
+namespace nebula {
+namespace graph {
+
+DescribeEdgeExecutor::DescribeEdgeExecutor(Sentence *sentence,
+                                           ExecutionContext *ectx) : Executor(ectx) {
+    sentence_ = static_cast<DescribeEdgeSentence*>(sentence);
+}
+
+
+Status DescribeEdgeExecutor::prepare() {
+    return Status::OK();
+}
+
+
+void DescribeEdgeExecutor::execute() {
+    auto *sm = ectx()->schemaManager();
+    auto *name = sentence_->name();
+    auto *schema = sm->getEdgeSchema(*name);
+    resp_ = std::make_unique<cpp2::ExecutionResponse>();
+
+    do {
+        if (schema == nullptr) {
+            onError_(Status::Error("Schema not found for edge `%s'", name->c_str()));
+            return;
+        }
+        std::vector<std::string> header{"SrcTag", "DstTag", "Column", "Type"};
+        auto &src = schema->srcTag();
+        auto &dst = schema->dstTag();
+        auto &items = schema->getPropertiesSchema()->getItems();
+        std::vector<cpp2::RowValue> rows;
+        for (auto &item : items) {
+            std::vector<cpp2::ColumnValue> row;
+            row.resize(4);
+            row[0].set_str(src);
+            row[1].set_str(dst);
+            row[2].set_str(item.name_);
+            row[3].set_str(columnTypeToString(item.type_));
+            rows.emplace_back();
+            rows.back().set_columns(std::move(row));
+        }
+        if (!rows.empty()) {
+            resp_->set_column_names(std::move(header));
+        } else {     // no columns
+            header.resize(header.size() - 2);
+            resp_->set_column_names(std::move(header));
+            std::vector<cpp2::ColumnValue> row;
+            row.resize(2);
+            row[0].set_str(src);
+            row[1].set_str(dst);
+            rows.resize(1);
+            rows[0].set_columns(std::move(row));
+        }
+        resp_->set_rows(std::move(rows));
+    } while (false);
+
+    DCHECK(onFinish_);
+    onFinish_();
+}
+
+
+void DescribeEdgeExecutor::setupResponse(cpp2::ExecutionResponse &resp) {
+    resp = std::move(*resp_);
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/DescribeEdgeExecutor.h b/src/executor/DescribeEdgeExecutor.h
new file mode 100644
index 00000000..2f084628
--- /dev/null
+++ b/src/executor/DescribeEdgeExecutor.h
@@ -0,0 +1,38 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_DESCRIBEEDGEEXECUTOR_H_
+#define GRAPH_DESCRIBEEDGEEXECUTOR_H_
+
+#include "base/Base.h"
+#include "graph/Executor.h"
+
+namespace nebula {
+namespace graph {
+
+class DescribeEdgeExecutor final : public Executor {
+public:
+    DescribeEdgeExecutor(Sentence *sentence, ExecutionContext *ectx);
+
+    const char* name() const override {
+        return "DescribeEdgeExecutor";
+    }
+
+    Status VE_MUST_USE_RESULT prepare() override;
+
+    void execute() override;
+
+    void setupResponse(cpp2::ExecutionResponse &resp) override;
+
+private:
+    DescribeEdgeSentence                       *sentence_{nullptr};
+    std::unique_ptr<cpp2::ExecutionResponse>    resp_;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_DESCRIBEEDGEEXECUTOR_H_
diff --git a/src/executor/DescribeTagExecutor.cpp b/src/executor/DescribeTagExecutor.cpp
new file mode 100644
index 00000000..d332aa69
--- /dev/null
+++ b/src/executor/DescribeTagExecutor.cpp
@@ -0,0 +1,59 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/DescribeTagExecutor.h"
+
+namespace nebula {
+namespace graph {
+
+DescribeTagExecutor::DescribeTagExecutor(Sentence *sentence,
+                                         ExecutionContext *ectx) : Executor(ectx) {
+    sentence_ = static_cast<DescribeTagSentence*>(sentence);
+}
+
+
+Status DescribeTagExecutor::prepare() {
+    return Status::OK();
+}
+
+
+void DescribeTagExecutor::execute() {
+    auto *sm = ectx()->schemaManager();
+    auto *name = sentence_->name();
+    resp_ = std::make_unique<cpp2::ExecutionResponse>();
+    auto *schema = sm->getTagSchema(*name);
+    do {
+        if (schema == nullptr) {
+            onError_(Status::Error("Schema not found for tag `%s'", name->c_str()));
+            return;
+        }
+        std::vector<std::string> header{"Column", "Type"};
+        resp_->set_column_names(std::move(header));
+        auto &items = schema->getPropertiesSchema()->getItems();
+        std::vector<cpp2::RowValue> rows;
+        for (auto &item : items) {
+            std::vector<cpp2::ColumnValue> row;
+            row.resize(2);
+            row[0].set_str(item.name_);
+            row[1].set_str(columnTypeToString(item.type_));
+            rows.emplace_back();
+            rows.back().set_columns(std::move(row));
+        }
+        resp_->set_rows(std::move(rows));
+    } while (false);
+
+    DCHECK(onFinish_);
+    onFinish_();
+}
+
+
+void DescribeTagExecutor::setupResponse(cpp2::ExecutionResponse &resp) {
+    resp = std::move(*resp_);
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/DescribeTagExecutor.h b/src/executor/DescribeTagExecutor.h
new file mode 100644
index 00000000..2c865aa5
--- /dev/null
+++ b/src/executor/DescribeTagExecutor.h
@@ -0,0 +1,39 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_DESCRIBETAGEXECUTOR_H_
+#define GRAPH_DESCRIBETAGEXECUTOR_H_
+
+#include "base/Base.h"
+#include "graph/Executor.h"
+
+namespace nebula {
+namespace graph {
+
+class DescribeTagExecutor final : public Executor {
+public:
+    DescribeTagExecutor(Sentence *sentence, ExecutionContext *ectx);
+
+    const char* name() const override {
+        return "DescribeTagExecutor";
+    }
+
+    Status VE_MUST_USE_RESULT prepare() override;
+
+    void execute() override;
+
+    void setupResponse(cpp2::ExecutionResponse &resp) override;
+
+private:
+    DescribeTagSentence                        *sentence_{nullptr};
+    std::string                                *tag_{nullptr};
+    std::unique_ptr<cpp2::ExecutionResponse>    resp_;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_DESCRIBETAGEXECUTOR_H_
diff --git a/src/executor/ExecutionContext.cpp b/src/executor/ExecutionContext.cpp
new file mode 100644
index 00000000..279fee13
--- /dev/null
+++ b/src/executor/ExecutionContext.cpp
@@ -0,0 +1,15 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/ExecutionContext.h"
+
+namespace nebula {
+namespace graph {
+
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/ExecutionContext.h b/src/executor/ExecutionContext.h
new file mode 100644
index 00000000..65d02bd0
--- /dev/null
+++ b/src/executor/ExecutionContext.h
@@ -0,0 +1,56 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_EXECUTIONCONTEXT_H_
+#define GRAPH_EXECUTIONCONTEXT_H_
+
+#include "base/Base.h"
+#include "cpp/helpers.h"
+#include "graph/RequestContext.h"
+#include "parser/CompoundSentence.h"
+#include "graph/mock/SchemaManager.h"
+#include "graph/mock/StorageService.h"
+
+/**
+ * ExecutionContext holds context infos in the execution process, e.g. clients of storage or meta services.
+ */
+
+namespace nebula {
+namespace graph {
+
+class ExecutionContext final : public cpp::NonCopyable, public cpp::NonMovable {
+public:
+    using RequestContextPtr = std::unique_ptr<RequestContext<cpp2::ExecutionResponse>>;
+    ExecutionContext(RequestContextPtr rctx, SchemaManager *sm, StorageService *storage) {
+        rctx_ = std::move(rctx);
+        sm_ = sm;
+        storage_ = storage;
+    }
+
+    ~ExecutionContext() = default;
+
+    RequestContext<cpp2::ExecutionResponse>* rctx() const {
+        return rctx_.get();
+    }
+
+    SchemaManager* schemaManager() const {
+        return sm_;
+    }
+
+    StorageService* storage() const {
+        return storage_;
+    }
+
+private:
+    RequestContextPtr                           rctx_;
+    SchemaManager                              *sm_{nullptr};
+    StorageService                             *storage_{nullptr};
+};
+
+}   // namespace graph
+}   // namespace graph
+
+#endif  // GRAPH_EXECUTIONCONTEXT_H_
diff --git a/src/executor/ExecutionEngine.cpp b/src/executor/ExecutionEngine.cpp
new file mode 100644
index 00000000..7acd8647
--- /dev/null
+++ b/src/executor/ExecutionEngine.cpp
@@ -0,0 +1,36 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/ExecutionEngine.h"
+#include "graph/ExecutionContext.h"
+#include "graph/ExecutionPlan.h"
+
+namespace nebula {
+namespace graph {
+
+ExecutionEngine::ExecutionEngine() {
+    schemaManager_ = std::make_unique<SchemaManager>();
+    storage_ = std::make_unique<StorageService>(schemaManager_.get());
+}
+
+
+ExecutionEngine::~ExecutionEngine() {
+}
+
+
+void ExecutionEngine::execute(RequestContextPtr rctx) {
+    auto ectx = std::make_unique<ExecutionContext>(std::move(rctx),
+                                                   schemaManager_.get(),
+                                                   storage_.get());
+    // TODO(dutor) add support to execution plan
+    auto plan = new ExecutionPlan(std::move(ectx));
+
+    plan->execute();
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/ExecutionEngine.h b/src/executor/ExecutionEngine.h
new file mode 100644
index 00000000..a515d7f0
--- /dev/null
+++ b/src/executor/ExecutionEngine.h
@@ -0,0 +1,42 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_EXECUTION_ENGINE_H_
+#define GRAPH_EXECUTION_ENGINE_H_
+
+#include "base/Base.h"
+#include "cpp/helpers.h"
+#include "graph/RequestContext.h"
+#include "gen-cpp2/GraphService.h"
+#include "graph/mock/SchemaManager.h"
+#include "graph/mock/StorageService.h"
+
+/**
+ * ExecutinoEngine is responsible to create and manage ExecutionPlan.
+ * For the time being, we don't have the execution plan cache support,
+ * instead we create a plan for each query, and destroy it upon finish.
+ */
+
+namespace nebula {
+namespace graph {
+
+class ExecutionEngine final : public cpp::NonCopyable, public cpp::NonMovable {
+public:
+    ExecutionEngine();
+    ~ExecutionEngine();
+
+    using RequestContextPtr = std::unique_ptr<RequestContext<cpp2::ExecutionResponse>>;
+    void execute(RequestContextPtr rctx);
+
+private:
+    std::unique_ptr<SchemaManager>              schemaManager_;
+    std::unique_ptr<StorageService>             storage_;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_EXECUTION_ENGINE_H_
diff --git a/src/executor/ExecutionPlan.cpp b/src/executor/ExecutionPlan.cpp
new file mode 100644
index 00000000..f0bea9be
--- /dev/null
+++ b/src/executor/ExecutionPlan.cpp
@@ -0,0 +1,78 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/ExecutionPlan.h"
+
+namespace nebula {
+namespace graph {
+
+void ExecutionPlan::execute() {
+    auto *rctx = ectx()->rctx();
+    FLOG_INFO("Parsing query: %s", rctx->query().c_str());
+
+    Status status;
+    do {
+        auto result = GQLParser().parse(rctx->query());
+        if (!result.ok()) {
+            status = std::move(result).status();
+            break;
+        }
+
+        compound_ = std::move(result).value();
+        executor_ = std::make_unique<CompoundExecutor>(compound_.get(), ectx());
+        status = executor_->prepare();
+        if (!status.ok()) {
+            break;
+        }
+    } while (false);
+
+    // Prepare failed
+    if (!status.ok()) {
+        onError(std::move(status));
+        return;
+    }
+
+    // Prepared
+    auto onFinish = [this] () {
+        this->onFinish();
+    };
+    auto onError = [this] (Status s) {
+        this->onError(std::move(s));
+    };
+    executor_->setOnFinish(std::move(onFinish));
+    executor_->setOnError(std::move(onError));
+
+    executor_->execute();
+}
+
+
+void ExecutionPlan::onFinish() {
+    executor_->setupResponse(ectx()->rctx()->resp());
+    ectx()->rctx()->finish();
+
+    // The `ExecutionPlan' is the root node holding all resources during the execution.
+    // When the whole query process is done, it's safe to release this object, as long as
+    // no other contexts have chances to access these resources later on,
+    // e.g. previously launched uncompleted async sub-tasks, EVEN on failures.
+    delete this;
+}
+
+
+void ExecutionPlan::onError(Status status) {
+    auto *rctx = ectx()->rctx();
+    if (status.isSyntaxError()) {
+        rctx->resp().set_error_code(cpp2::ErrorCode::E_SYNTAX_ERROR);
+    } else {
+        rctx->resp().set_error_code(cpp2::ErrorCode::E_EXECUTION_ERROR);
+    }
+    rctx->resp().set_error_msg(status.toString());
+    rctx->finish();
+    delete this;
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/ExecutionPlan.h b/src/executor/ExecutionPlan.h
new file mode 100644
index 00000000..888f4111
--- /dev/null
+++ b/src/executor/ExecutionPlan.h
@@ -0,0 +1,62 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_EXECUTIONPLAN_H_
+#define GRAPH_EXECUTIONPLAN_H_
+
+#include "base/Base.h"
+#include "base/Status.h"
+#include "cpp/helpers.h"
+#include "parser/GQLParser.h"
+#include "graph/ExecutionContext.h"
+#include "graph/CompoundExecutor.h"
+
+/**
+ * ExecutionPlan coordinates the execution process,
+ * i.e. parse a query into a parsing tree, analyze the tree,
+ * initiate and finalize the execution.
+ */
+
+namespace nebula {
+namespace graph {
+
+class ExecutionPlan final : public cpp::NonCopyable, public cpp::NonMovable {
+public:
+    explicit ExecutionPlan(std::unique_ptr<ExecutionContext> ectx) {
+        ectx_ = std::move(ectx);
+    }
+
+    ~ExecutionPlan() = default;
+
+    void execute();
+
+    /**
+     * If the whole execution was done, `onFinish' would be invoked.
+     * All `onFinish' should do is to ask `executor_' to fill the `ectx()->rctx()->resp()',
+     * which in turn asks the last sub-executor to do the actual job.
+     */
+    void onFinish();
+
+    /**
+     * If any error occurred during the execution, `onError' should
+     * be invoked with a status to indicate the reason.
+     */
+    void onError(Status);
+
+    ExecutionContext* ectx() const {
+        return ectx_.get();
+    }
+
+private:
+    std::unique_ptr<CompoundSentence>           compound_;
+    std::unique_ptr<ExecutionContext>           ectx_;
+    std::unique_ptr<CompoundExecutor>           executor_;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_EXECUTIONPLAN_H_
diff --git a/src/executor/Executor.cpp b/src/executor/Executor.cpp
new file mode 100644
index 00000000..e4184e45
--- /dev/null
+++ b/src/executor/Executor.cpp
@@ -0,0 +1,75 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/Executor.h"
+#include "parser/TraverseSentences.h"
+#include "parser/MutateSentences.h"
+#include "parser/MaintainSentences.h"
+#include "graph/GoExecutor.h"
+#include "graph/UseExecutor.h"
+#include "graph/PipeExecutor.h"
+#include "graph/DefineTagExecutor.h"
+#include "graph/DefineEdgeExecutor.h"
+#include "graph/AlterTagExecutor.h"
+#include "graph/AlterEdgeExecutor.h"
+#include "graph/DescribeTagExecutor.h"
+#include "graph/DescribeEdgeExecutor.h"
+#include "graph/InsertVertexExecutor.h"
+#include "graph/InsertEdgeExecutor.h"
+
+namespace nebula {
+namespace graph {
+
+std::unique_ptr<Executor> Executor::makeExecutor(Sentence *sentence) {
+    auto kind = sentence->kind();
+    std::unique_ptr<Executor> executor;
+    switch (kind) {
+        case Sentence::Kind::kGo:
+            executor = std::make_unique<GoExecutor>(sentence, ectx());
+            break;
+        case Sentence::Kind::kUse:
+            executor = std::make_unique<UseExecutor>(sentence, ectx());
+            break;
+        case Sentence::Kind::kPipe:
+            executor = std::make_unique<PipeExecutor>(sentence, ectx());
+            break;
+        case Sentence::Kind::kDefineTag:
+            executor = std::make_unique<DefineTagExecutor>(sentence, ectx());
+            break;
+        case Sentence::Kind::kDefineEdge:
+            executor = std::make_unique<DefineEdgeExecutor>(sentence, ectx());
+            break;
+        case Sentence::Kind::kAlterTag:
+            executor = std::make_unique<AlterTagExecutor>(sentence, ectx());
+            break;
+        case Sentence::Kind::kAlterEdge:
+            executor = std::make_unique<AlterEdgeExecutor>(sentence, ectx());
+            break;
+        case Sentence::Kind::kDescribeTag:
+            executor = std::make_unique<DescribeTagExecutor>(sentence, ectx());
+            break;
+        case Sentence::Kind::kDescribeEdge:
+            executor = std::make_unique<DescribeEdgeExecutor>(sentence, ectx());
+            break;
+        case Sentence::Kind::kInsertVertex:
+            executor = std::make_unique<InsertVertexExecutor>(sentence, ectx());
+            break;
+        case Sentence::Kind::kInsertEdge:
+            executor = std::make_unique<InsertEdgeExecutor>(sentence, ectx());
+            break;
+        case Sentence::Kind::kUnknown:
+            LOG(FATAL) << "Sentence kind unknown";
+            break;
+        default:
+            LOG(FATAL) << "Sentence kind illegal: " << kind;
+            break;
+    }
+    return executor;
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/Executor.h b/src/executor/Executor.h
new file mode 100644
index 00000000..f4b14701
--- /dev/null
+++ b/src/executor/Executor.h
@@ -0,0 +1,85 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_EXECUTOR_H_
+#define GRAPH_EXECUTOR_H_
+
+#include "base/Base.h"
+#include "base/Status.h"
+#include "cpp/helpers.h"
+#include "graph/ExecutionContext.h"
+
+
+/**
+ * Executor is the interface of kinds of specific executors that do the actual execution.
+ */
+
+namespace nebula {
+namespace graph {
+
+class Executor : public cpp::NonCopyable, public cpp::NonMovable {
+public:
+    explicit Executor(ExecutionContext *ectx) {
+        ectx_ = ectx;
+    }
+
+    virtual ~Executor() {}
+
+    /**
+     * Do some preparatory works, such as sanitize checking, dependency setup, etc.
+     *
+     * `prepare' succeeds only if all its sub-executors are prepared.
+     * `prepare' works in a synchronous way, once the executor is prepared, it will
+     * be executed.
+     */
+    virtual Status VE_MUST_USE_RESULT prepare() = 0;
+
+    virtual void execute() = 0;
+
+    virtual const char* name() const = 0;
+
+    /**
+     * Set callback to be invoked when this executor is finished(normally).
+     */
+    void setOnFinish(std::function<void()> onFinish) {
+        onFinish_ = onFinish;
+    }
+    /**
+     * When some error happens during an executor's execution, it should invoke its
+     * `onError_' with a Status that indicates the reason.
+     *
+     * An executor terminates its execution via invoking either `onFinish_' or `onError_',
+     * but should never call them both.
+     */
+    void setOnError(std::function<void(Status)> onError) {
+        onError_ = onError;
+    }
+    /**
+     * Upon finished successfully, `setupResponse' would be invoked on the last executor.
+     * Any Executor implementation, which wants to send its meaningful result to the client,
+     * should override this method.
+     */
+    virtual void setupResponse(cpp2::ExecutionResponse &resp) {
+        resp.set_error_code(cpp2::ErrorCode::SUCCEEDED);
+    }
+
+    ExecutionContext* ectx() const {
+        return ectx_;
+    }
+
+protected:
+    std::unique_ptr<Executor> makeExecutor(Sentence *sentence);
+
+protected:
+    ExecutionContext                           *ectx_;
+    std::function<void()>                       onFinish_;
+    std::function<void(Status)>                 onError_;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_EXECUTOR_H_
diff --git a/src/executor/GoExecutor.cpp b/src/executor/GoExecutor.cpp
new file mode 100644
index 00000000..0062e2e9
--- /dev/null
+++ b/src/executor/GoExecutor.cpp
@@ -0,0 +1,212 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/GoExecutor.h"
+
+
+namespace nebula {
+namespace graph {
+
+GoExecutor::GoExecutor(Sentence *sentence, ExecutionContext *ectx) : TraverseExecutor(ectx) {
+    // The RTTI is guaranteed by Sentence::Kind,
+    // so we use `static_cast' instead of `dynamic_cast' for the sake of efficiency.
+    sentence_ = static_cast<GoSentence*>(sentence);
+}
+
+
+Status GoExecutor::prepare() {
+    DCHECK(sentence_ != nullptr);
+    Status status;
+    expctx_ = std::make_unique<ExpressionContext>();
+    do {
+        status = prepareStep();
+        if (!status.ok()) {
+            break;
+        }
+        status = prepareFrom();
+        if (!status.ok()) {
+            break;
+        }
+        status = prepareOver();
+        if (!status.ok()) {
+            break;
+        }
+        status = prepareWhere();
+        if (!status.ok()) {
+            break;
+        }
+        status = prepareYield();
+        if (!status.ok()) {
+            break;
+        }
+        status = prepareResultSchema();
+        if (!status.ok()) {
+            break;
+        }
+        status = prepareNeededProps();
+        if (!status.ok()) {
+            break;
+        }
+    } while (false);
+
+    if (!status.ok()) {
+        return status;
+    }
+
+    expctx_->print();
+
+    if (!onResult_) {
+        onResult_ = [this] (TraverseRecords records) {
+            this->cacheResult(std::move(records));
+        };
+    }
+
+    return status;
+}
+
+
+void GoExecutor::execute() {
+    FLOG_INFO("Executing Go: %s", sentence_->toString().c_str());
+    using Result = StatusOr<storage::cpp2::QueryResponse>;
+    auto eprops = expctx_->edgePropNames();
+    auto vprops = expctx_->srcNodePropNames();
+    auto *edge = edges_[0]->edge();
+    auto future = ectx()->storage()->getOutBound(starts_, edge, eprops, vprops);
+    auto *runner = ectx()->rctx()->runner();
+    std::move(future).via(runner).then([this] (Result result) {
+        if (!result.ok()) {
+            auto &resp = ectx()->rctx()->resp();
+            auto status = result.status();
+            resp.set_error_code(cpp2::ErrorCode::E_EXECUTION_ERROR);
+            resp.set_error_msg(status.toString());
+        }
+        if (onFinish_) {
+            onFinish_();
+        }
+    });
+}
+
+
+void GoExecutor::feedResult(TraverseRecords records) {
+    inputs_.reserve(records.size());
+    for (auto &record : records) {
+        inputs_.push_back(std::move(record));
+    }
+}
+
+
+Status GoExecutor::prepareResultSchema() {
+    resultSchema_ = std::make_unique<ResultSchema>();
+    for (auto *column : yields_) {
+        resultSchema_->addColumn(*column->alias());
+    }
+    return Status::OK();
+}
+
+
+Status GoExecutor::prepareStep() {
+    auto *clause = sentence_->stepClause();
+    if (clause != nullptr) {
+        steps_ = clause->steps();
+        upto_ = clause->isUpto();
+    }
+    return Status::OK();
+}
+
+
+Status GoExecutor::prepareFrom() {
+    Status status = Status::OK();
+    auto *clause = sentence_->fromClause();
+    do {
+        if (clause == nullptr) {
+            break;
+        }
+        auto *alias = clause->alias();
+        if (alias == nullptr) {
+            break;
+        }
+        expctx_->addAlias(*alias, AliasKind::SourceNode);
+        starts_ = clause->srcNodeList()->nodeIds();
+    } while (false);
+    return status;
+}
+
+
+Status GoExecutor::prepareOver() {
+    Status status = Status::OK();
+    auto *clause = sentence_->overClause();
+    do {
+        if (clause == nullptr) {
+            break;
+        }
+        edges_ = clause->edges();
+        reversely_ = clause->isReversely();
+        if (edges_.empty()) {
+            break;
+        }
+        for (auto *item : edges_) {
+            expctx_->addAlias(*item->alias(), AliasKind::Edge, *item->edge());
+
+        }
+    } while (false);
+    return status;
+}
+
+
+Status GoExecutor::prepareWhere() {
+    auto *clause = sentence_->whereClause();
+    if (clause != nullptr) {
+        filter_ = clause->filter();
+    }
+    return Status::OK();
+}
+
+
+Status GoExecutor::prepareYield() {
+    auto *clause = sentence_->yieldClause();
+    if (clause != nullptr) {
+        yields_ = clause->columns();
+    }
+    return Status::OK();
+}
+
+
+Status GoExecutor::prepareNeededProps() {
+    auto status = Status::OK();
+    do {
+        if (filter_ != nullptr) {
+            status = filter_->prepare(expctx_.get());
+            if (!status.ok()) {
+                break;
+            }
+        }
+        if (yields_.empty()) {
+            break;
+        }
+        for (auto *col : yields_) {
+            status = col->expr()->prepare(expctx_.get());
+            if (!status.ok()) {
+                break;
+            }
+        }
+    } while (false);
+
+    return status;
+}
+
+
+void GoExecutor::cacheResult(TraverseRecords records) {
+    UNUSED(records);
+}
+
+
+void GoExecutor::setupResponse(cpp2::ExecutionResponse &resp) {
+    UNUSED(resp);
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/GoExecutor.h b/src/executor/GoExecutor.h
new file mode 100644
index 00000000..31c3ea6a
--- /dev/null
+++ b/src/executor/GoExecutor.h
@@ -0,0 +1,66 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_GOEXECUTOR_H_
+#define GRAPH_GOEXECUTOR_H_
+
+#include "base/Base.h"
+#include "graph/TraverseExecutor.h"
+
+namespace nebula {
+namespace graph {
+
+class GoExecutor final : public TraverseExecutor {
+public:
+    GoExecutor(Sentence *sentence, ExecutionContext *ectx);
+
+    const char* name() const override {
+        return "GoExecutor";
+    }
+
+    Status VE_MUST_USE_RESULT prepare() override;
+
+    void execute() override;
+
+    void feedResult(TraverseRecords records) override;
+
+    void setupResponse(cpp2::ExecutionResponse &resp) override;
+
+private:
+    Status prepareResultSchema();
+
+    Status prepareStep();
+
+    Status prepareFrom();
+
+    Status prepareOver();
+
+    Status prepareWhere();
+
+    Status prepareYield();
+
+    Status prepareNeededProps();
+
+    void cacheResult(TraverseRecords records);
+
+private:
+    GoSentence                                 *sentence_{nullptr};
+    uint32_t                                    steps_{1};
+    bool                                        upto_{false};
+    bool                                        reversely_{false};
+    std::vector<EdgeItem*>                      edges_;
+    Expression                                 *filter_{nullptr};
+    std::vector<YieldColumn*>                   yields_;
+    TraverseRecords                             inputs_;
+    std::unique_ptr<ExpressionContext>          expctx_;
+    std::vector<int64_t>                        starts_;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+
+#endif  // GRAPH_GOEXECUTOR_H_
diff --git a/src/executor/GraphFlags.cpp b/src/executor/GraphFlags.cpp
new file mode 100644
index 00000000..c4ca13e6
--- /dev/null
+++ b/src/executor/GraphFlags.cpp
@@ -0,0 +1,21 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/GraphFlags.h"
+
+DEFINE_int32(port, 34500, "Nebula Graph daemon's listen port");
+DEFINE_int32(client_idle_timeout_secs, 0, "Seconds before we close the idle connections, 0 for infinite");
+DEFINE_int32(session_idle_timeout_secs, 600, "Seconds before we expire the idle sessions, 0 for infinite");
+DEFINE_int32(session_reclaim_interval_secs, 10, "Period we try to reclaim expired sessions");
+DEFINE_int32(num_netio_threads, 0, "Number of networking threads, 0 for number of physical CPU cores");
+DEFINE_int32(num_accept_threads, 1, "Number of threads to accept incoming connections");
+DEFINE_bool(reuse_port, true, "Whether to turn on the SO_REUSEPORT option");
+DEFINE_int32(listen_backlog, 1024, "Backlog of the listen socket");
+
+DEFINE_bool(redirect_stdout, true, "Whether to redirect stdout and stderr to separate files");
+DEFINE_string(stdout_log_file, "graphd-stdout.log", "Destination filename of stdout");
+DEFINE_string(stderr_log_file, "graphd-stderr.log", "Destination filename of stderr");
diff --git a/src/executor/GraphFlags.h b/src/executor/GraphFlags.h
new file mode 100644
index 00000000..445a1a97
--- /dev/null
+++ b/src/executor/GraphFlags.h
@@ -0,0 +1,26 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_GRAPHFLAGS_H_
+#define GRAPH_GRAPHFLAGS_H_
+
+#include "base/Base.h"
+
+DECLARE_int32(port);
+DECLARE_int32(client_idle_timeout_secs);
+DECLARE_int32(session_idle_timeout_secs);
+DECLARE_int32(session_reclaim_interval_secs);
+DECLARE_int32(num_netio_threads);
+DECLARE_int32(num_accept_threads);
+DECLARE_bool(reuse_port);
+DECLARE_int32(listen_backlog);
+
+DECLARE_bool(redirect_stdout);
+DECLARE_string(stdout_log_file);
+DECLARE_string(stderr_log_file);
+
+
+#endif  // GRAPH_GRAPHFLAGS_H_
diff --git a/src/executor/GraphService.cpp b/src/executor/GraphService.cpp
new file mode 100644
index 00000000..b06e8a26
--- /dev/null
+++ b/src/executor/GraphService.cpp
@@ -0,0 +1,104 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/GraphService.h"
+#include "time/Duration.h"
+#include "graph/RequestContext.h"
+#include "graph/SimpleAuthenticator.h"
+
+namespace nebula {
+namespace graph {
+
+GraphService::GraphService() {
+    sessionManager_ = std::make_unique<SessionManager>();
+    executionEngine_ = std::make_unique<ExecutionEngine>();
+    authenticator_ = std::make_unique<SimpleAuthenticator>();
+}
+
+GraphService::~GraphService() {
+}
+
+folly::Future<cpp2::AuthResponse> GraphService::future_authenticate(
+        const std::string& username,
+        const std::string& password) {
+    auto *peer = getConnectionContext()->getPeerAddress();
+    FVLOG2("Authenticating user %s from %s", username.c_str(), peer->describe().c_str());
+
+    RequestContext<cpp2::AuthResponse> ctx;
+    auto session = sessionManager_->createSession();
+    session->setUser(username);
+    ctx.setSession(std::move(session));
+
+    if (authenticator_->auth(username, password)) {
+        ctx.resp().set_error_code(cpp2::ErrorCode::SUCCEEDED);
+        ctx.resp().set_session_id(ctx.session()->id());
+    } else {
+        sessionManager_->removeSession(ctx.session()->id());
+        ctx.resp().set_error_code(cpp2::ErrorCode::E_BAD_USERNAME_PASSWORD);
+        ctx.resp().set_error_msg(getErrorStr(cpp2::ErrorCode::E_BAD_USERNAME_PASSWORD));
+    }
+
+    ctx.finish();
+    return ctx.future();
+}
+
+
+void GraphService::signout(int64_t sessionId) {
+    VLOG(2) << "Sign out session " << sessionId;
+    sessionManager_->removeSession(sessionId);
+}
+
+
+folly::Future<cpp2::ExecutionResponse>
+GraphService::future_execute(int64_t sessionId, const std::string& query) {
+    auto ctx = std::make_unique<RequestContext<cpp2::ExecutionResponse>>();
+    ctx->setQuery(query);
+    ctx->setRunner(getThreadManager());
+    auto future = ctx->future();
+    {
+        auto result = sessionManager_->findSession(sessionId);
+        if (!result.ok()) {
+            FLOG_ERROR("Session not found, id[%ld]", sessionId);
+            ctx->resp().set_error_code(cpp2::ErrorCode::E_SESSION_INVALID);
+            ctx->resp().set_error_msg(result.status().toString());
+            ctx->finish();
+            return future;
+        }
+        ctx->setSession(std::move(result).value());
+    }
+    executionEngine_->execute(std::move(ctx));
+
+    return future;
+}
+
+
+const char* GraphService::getErrorStr(cpp2::ErrorCode result) {
+    switch (result) {
+    case cpp2::ErrorCode::SUCCEEDED:
+        return "Succeeded";
+    /**********************
+     * Server side errors
+     **********************/
+    case cpp2::ErrorCode::E_BAD_USERNAME_PASSWORD:
+        return "Bad username/password";
+    case cpp2::ErrorCode::E_SESSION_INVALID:
+        return "The session is invalid";
+    case cpp2::ErrorCode::E_SESSION_TIMEOUT:
+        return "The session timed out";
+    case cpp2::ErrorCode::E_SYNTAX_ERROR:
+        return "Syntax error";
+    /**********************
+     * Unknown error
+     **********************/
+    default:
+        return "Unknown error";
+    }
+}
+
+}  // namespace graph
+}  // namespace nebula
+
diff --git a/src/executor/GraphService.h b/src/executor/GraphService.h
new file mode 100644
index 00000000..13c12611
--- /dev/null
+++ b/src/executor/GraphService.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_GRAPHSERVICE_H_
+#define GRAPH_GRAPHSERVICE_H_
+
+#include "base/Base.h"
+#include "gen-cpp2/GraphService.h"
+#include "graph/SessionManager.h"
+#include "graph/ExecutionEngine.h"
+#include "graph/Authenticator.h"
+
+namespace nebula {
+namespace graph {
+
+class GraphService final : public cpp2::GraphServiceSvIf {
+public:
+    GraphService();
+    ~GraphService();
+    folly::Future<cpp2::AuthResponse> future_authenticate(
+        const std::string& username,
+        const std::string& password) override;
+
+    void signout(int64_t /*sessionId*/) override;
+
+    folly::Future<cpp2::ExecutionResponse> future_execute(
+        int64_t sessionId,
+        const std::string& stmt) override;
+
+    const char* getErrorStr(cpp2::ErrorCode result);
+
+private:
+    std::unique_ptr<SessionManager>             sessionManager_;
+    std::unique_ptr<ExecutionEngine>            executionEngine_;
+    std::unique_ptr<Authenticator>              authenticator_;
+};
+
+}  // namespace graph
+}  // namespace nebula
+#endif  // GRAPH_GRAPHSERVICE_H_
diff --git a/src/executor/InsertEdgeExecutor.cpp b/src/executor/InsertEdgeExecutor.cpp
new file mode 100644
index 00000000..73303859
--- /dev/null
+++ b/src/executor/InsertEdgeExecutor.cpp
@@ -0,0 +1,55 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/InsertEdgeExecutor.h"
+
+namespace nebula {
+namespace graph {
+
+InsertEdgeExecutor::InsertEdgeExecutor(Sentence *sentence,
+                                       ExecutionContext *ectx) : Executor(ectx) {
+    sentence_ = static_cast<InsertEdgeSentence*>(sentence);
+}
+
+
+Status InsertEdgeExecutor::prepare() {
+    overwritable_ = sentence_->overwritable();
+    srcid_ = sentence_->srcid();
+    dstid_ = sentence_->dstid();
+    edge_ = sentence_->edge();
+    rank_ = sentence_->rank();
+    properties_ = sentence_->properties();
+    values_ = sentence_->values();
+    // TODO(dutor) check on property names and types
+    if (properties_.size() != values_.size()) {
+        return Status::Error("Number of property names and values not match");
+    }
+    return Status::OK();
+}
+
+
+void InsertEdgeExecutor::execute() {
+    std::vector<VariantType> values;
+    values.resize(values_.size());
+    auto eval = [] (auto *expr) { return expr->eval(); };
+    std::transform(values_.begin(), values_.end(), values.begin(), eval);
+
+    auto future = ectx()->storage()->addEdge(edge_, srcid_, dstid_, properties_, values);
+    auto *runner = ectx()->rctx()->runner();
+    std::move(future).via(runner).then([this] (Status status) {
+        if (!status.ok()) {
+            auto &resp = ectx()->rctx()->resp();
+            resp.set_error_code(cpp2::ErrorCode::E_EXECUTION_ERROR);
+            resp.set_error_msg(status.toString());
+        }
+        DCHECK(onFinish_);
+        onFinish_();
+    });
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/InsertEdgeExecutor.h b/src/executor/InsertEdgeExecutor.h
new file mode 100644
index 00000000..b5560148
--- /dev/null
+++ b/src/executor/InsertEdgeExecutor.h
@@ -0,0 +1,42 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_INSERTEDGEEXECUTOR_H_
+#define GRAPH_INSERTEDGEEXECUTOR_H_
+
+#include "base/Base.h"
+#include "graph/Executor.h"
+
+namespace nebula {
+namespace graph {
+
+class InsertEdgeExecutor final : public Executor {
+public:
+    InsertEdgeExecutor(Sentence *sentence, ExecutionContext *ectx);
+
+    const char* name() const override {
+        return "InsertEdgeExecutor";
+    }
+
+    Status VE_MUST_USE_RESULT prepare() override;
+
+    void execute() override;
+
+private:
+    InsertEdgeSentence                         *sentence_{nullptr};
+    bool                                        overwritable_{true};
+    int64_t                                     srcid_{0};
+    int64_t                                     dstid_{0};
+    int64_t                                     rank_{0};
+    std::string                                *edge_{nullptr};
+    std::vector<std::string*>                   properties_;
+    std::vector<Expression*>                    values_;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_INSERTEDGEEXECUTOR_H_
diff --git a/src/executor/InsertVertexExecutor.cpp b/src/executor/InsertVertexExecutor.cpp
new file mode 100644
index 00000000..3542b036
--- /dev/null
+++ b/src/executor/InsertVertexExecutor.cpp
@@ -0,0 +1,50 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/InsertVertexExecutor.h"
+
+namespace nebula {
+namespace graph {
+
+InsertVertexExecutor::InsertVertexExecutor(Sentence *sentence,
+                                           ExecutionContext *ectx) : Executor(ectx) {
+    sentence_ = static_cast<InsertVertexSentence*>(sentence);
+}
+
+
+Status InsertVertexExecutor::prepare() {
+    overwritable_ = sentence_->overwritable();
+    id_ = sentence_->id();
+    vertex_ = sentence_->vertex();
+    properties_ = sentence_->properties();
+    values_ = sentence_->values();
+    // TODO(dutor) check on property names and types
+    if (properties_.size() != values_.size()) {
+        return Status::Error("Number of property names and values not match");
+    }
+    return Status::OK();
+}
+
+
+void InsertVertexExecutor::execute() {
+    std::vector<VariantType> values;
+    values.resize(values_.size());
+    auto eval = [] (auto *expr) { return expr->eval(); };
+    std::transform(values_.begin(), values_.end(), values.begin(), eval);
+
+    auto future = ectx()->storage()->addTag(vertex_, id_, properties_, values);
+    auto *runner = ectx()->rctx()->runner();
+    std::move(future).via(runner).then([this] (Status status) {
+        // TODO(dutor) error handling
+        UNUSED(status);
+        DCHECK(onFinish_);
+        onFinish_();
+    });
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/InsertVertexExecutor.h b/src/executor/InsertVertexExecutor.h
new file mode 100644
index 00000000..9092adf1
--- /dev/null
+++ b/src/executor/InsertVertexExecutor.h
@@ -0,0 +1,40 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_INSERTVERTEXEXECUTOR_H_
+#define GRAPH_INSERTVERTEXEXECUTOR_H_
+
+#include "base/Base.h"
+#include "graph/Executor.h"
+
+namespace nebula {
+namespace graph {
+
+class InsertVertexExecutor final : public Executor {
+public:
+    InsertVertexExecutor(Sentence *sentence, ExecutionContext *ectx);
+
+    const char* name() const override {
+        return "InsertVertexExecutor";
+    }
+
+    Status VE_MUST_USE_RESULT prepare() override;
+
+    void execute() override;
+
+private:
+    InsertVertexSentence                       *sentence_{nullptr};
+    bool                                        overwritable_{true};
+    int64_t                                     id_{0};
+    std::string                                *vertex_{nullptr};
+    std::vector<std::string*>                   properties_;
+    std::vector<Expression*>                    values_;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_INSERTVERTEXEXECUTOR_H_
diff --git a/src/executor/PipeExecutor.cpp b/src/executor/PipeExecutor.cpp
new file mode 100644
index 00000000..25cfa16c
--- /dev/null
+++ b/src/executor/PipeExecutor.cpp
@@ -0,0 +1,112 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/PipeExecutor.h"
+
+namespace nebula {
+namespace graph {
+
+PipeExecutor::PipeExecutor(Sentence *sentence,
+                           ExecutionContext *ectx) : TraverseExecutor(ectx) {
+    sentence_ = static_cast<PipedSentence*>(sentence);
+}
+
+
+Status PipeExecutor::prepare() {
+    left_ = makeTraverseExecutor(sentence_->left());
+    right_ = makeTraverseExecutor(sentence_->right());
+    DCHECK(left_ != nullptr);
+    DCHECK(right_ != nullptr);
+
+    auto status = left_->prepare();
+    if (!status.ok()) {
+        FLOG_ERROR("Prepare executor `%s' failed: %s",
+                    left_->name(), status.toString().c_str());
+        return status;
+    }
+
+    right_->setInputResultSchema(left_->resultSchema());
+
+    status = right_->prepare();
+    if (!status.ok()) {
+        FLOG_ERROR("Prepare executor `%s' failed: %s",
+                    right_->name(), status.toString().c_str());
+        return status;
+    }
+
+    auto onError = [this] (Status s) {
+        /**
+         * TODO(dutor)
+         * If we allow concurrent execution of both sides, we must wait for all their
+         * internal on-fly async-requests' to arrive before call `onError_'.
+         * For the sake of simplicity, we don't allow the pipeline way for now.
+         */
+        onError_(std::move(s));
+    };
+
+    // Setup dependencies
+    {
+        auto onFinish = [this] () {
+            // Start executing `right_' when `left_' is finished.
+            right_->execute();
+        };
+        left_->setOnFinish(onFinish);
+
+        auto onResult = [this] (TraverseRecords records) {
+            // Feed results from `left_' to `right_'
+            right_->feedResult(std::move(records));
+        };
+        left_->setOnResult(onResult);
+
+        left_->setOnError(onError);
+    }
+    {
+        auto onFinish = [this] () {
+            // This executor is done when `right_' finishes.
+            DCHECK(onFinish_);
+            onFinish_();
+        };
+        right_->setOnFinish(onFinish);
+
+        if (onResult_) {
+            auto onResult = [this] (TraverseRecords records) {
+                // This executor takes results of `right_' as results.
+                onResult_(std::move(records));
+            };
+            right_->setOnResult(onResult);
+        } else {
+            // `right_' is the right most part of the pipeline
+        }
+
+        right_->setOnError(onError);
+    }
+
+    return Status::OK();
+}
+
+
+void PipeExecutor::execute() {
+    left_->execute();
+}
+
+
+void PipeExecutor::feedResult(TraverseRecords records) {
+    left_->feedResult(std::move(records));
+}
+
+
+void PipeExecutor::setupResponse(cpp2::ExecutionResponse &resp) {
+    /**
+     * `setupResponse()' could be invoked if and only if this executor
+     * is the right most one, i.e. `onResult_' wasn't set.
+     */
+    DCHECK(!onResult_);
+    right_->setupResponse(resp);
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/PipeExecutor.h b/src/executor/PipeExecutor.h
new file mode 100644
index 00000000..89443540
--- /dev/null
+++ b/src/executor/PipeExecutor.h
@@ -0,0 +1,50 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_PIPEEXECUTOR_H_
+#define GRAPH_PIPEEXECUTOR_H_
+
+#include "base/Base.h"
+#include "graph/TraverseExecutor.h"
+
+namespace nebula {
+namespace graph {
+
+class PipeExecutor final : public TraverseExecutor {
+public:
+    PipeExecutor(Sentence *sentence, ExecutionContext *ectx);
+
+    const char* name() const override {
+        return "PipeExecutor";
+    }
+
+    Status VE_MUST_USE_RESULT prepare() override;
+
+    void execute() override;
+
+    void feedResult(TraverseRecords records) override;
+
+    void setupResponse(cpp2::ExecutionResponse &resp) override;
+
+    ResultSchema* resultSchema() const override {
+        return right_->resultSchema();
+    }
+
+    void setInputResultSchema(ResultSchema *schema) override {
+        left_->setInputResultSchema(schema);
+    }
+
+private:
+    PipedSentence                              *sentence_{nullptr};
+    std::unique_ptr<TraverseExecutor>           left_;
+    std::unique_ptr<TraverseExecutor>           right_;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+
+#endif  // GRAPH_PIPEEXECUTOR_H_
diff --git a/src/executor/README.md b/src/executor/README.md
new file mode 100644
index 00000000..07dd0c5c
--- /dev/null
+++ b/src/executor/README.md
@@ -0,0 +1 @@
+# Overview
diff --git a/src/executor/RequestContext.h b/src/executor/RequestContext.h
new file mode 100644
index 00000000..13e0397d
--- /dev/null
+++ b/src/executor/RequestContext.h
@@ -0,0 +1,95 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_REQUESTCONTEXT_H_
+#define GRAPH_REQUESTCONTEXT_H_
+
+#include "base/Base.h"
+#include "gen-cpp2/GraphService.h"
+#include "cpp/helpers.h"
+#include "time/Duration.h"
+#include "graph/ClientSession.h"
+
+/**
+ * RequestContext holds context infos of a specific request from a client.
+ * The typical use is:
+ *  1. Create a RequestContext, with statement, session, etc.
+ *  2. Obtain a Future from the context, which is to be returned back to the Thrift framework.
+ *  3. Prepare the Response when the request is complished.
+ *  4. Call `finish' to send the response to the client.
+ */
+
+namespace nebula {
+namespace graph {
+
+template <typename Response>
+class RequestContext final : public cpp::NonCopyable, public cpp::NonMovable {
+public:
+    RequestContext() = default;
+    ~RequestContext() {
+        if (session_ != nullptr) {
+            // keep the session active
+            session_->charge();
+        }
+    }
+
+    void setQuery(std::string query) {
+        query_ = std::move(query);
+    }
+
+    const std::string& query() const {
+        return query_;
+    }
+
+    Response& resp() {
+        return resp_;
+    }
+
+    folly::Future<Response> future() {
+        return promise_.getFuture();
+    }
+
+    void setSession(std::shared_ptr<ClientSession> session) {
+        session_ = std::move(session);
+        if (session_ != nullptr) {
+            // keep the session active
+            session_->charge();
+        }
+    }
+
+    ClientSession* session() const {
+        return session_.get();
+    }
+
+    folly::Executor* runner() const {
+        return runner_;
+    }
+
+    void setRunner(folly::Executor *runner) {
+        runner_ = runner;
+    }
+
+    const time::Duration& duration() const {
+        return duration_;
+    }
+
+    void finish() {
+        promise_.setValue(std::move(resp_));
+    }
+
+private:
+    time::Duration                              duration_;
+    std::string                                 query_;
+    Response                                    resp_;
+    folly::Promise<Response>                    promise_;
+    std::shared_ptr<ClientSession>              session_;
+    folly::Executor                            *runner_{nullptr};
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_REQUESTCONTEXT_H_
diff --git a/src/executor/SessionManager.cpp b/src/executor/SessionManager.cpp
new file mode 100644
index 00000000..6f3ddf3c
--- /dev/null
+++ b/src/executor/SessionManager.cpp
@@ -0,0 +1,105 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/SessionManager.h"
+#include "graph/GraphFlags.h"
+
+namespace nebula {
+namespace graph {
+
+SessionManager::SessionManager() {
+    scavenger_ = std::make_unique<thread::GenericWorker>();
+    auto ok = scavenger_->start("session-manager");
+    DCHECK(ok);
+    auto bound = std::bind(&SessionManager::reclaimExpiredSessions, this);
+    scavenger_->addRepeatTask(FLAGS_session_reclaim_interval_secs * 1000, std::move(bound));
+}
+
+
+SessionManager::~SessionManager() {
+    if (scavenger_ != nullptr) {
+        scavenger_->stop();
+        scavenger_->wait();
+        scavenger_.reset();
+    }
+}
+
+
+StatusOr<std::shared_ptr<ClientSession>>
+SessionManager::findSession(int64_t id) {
+    folly::RWSpinLock::ReadHolder holder(rwlock_);
+    auto iter = activeSessions_.find(id);
+    if (iter == activeSessions_.end()) {
+        return Status::Error("Session `%ld' has expired", id);
+    }
+    return iter->second;
+}
+
+
+std::shared_ptr<ClientSession> SessionManager::createSession() {
+    folly::RWSpinLock::WriteHolder holder(rwlock_);
+    auto sid = newSessionId();
+    while (true) {
+        if (activeSessions_.count(sid) == 0UL) {
+            break;
+        }
+        // This ID is in use already, try another one
+        sid = newSessionId();
+    }
+    DCHECK(sid != 0L);
+    auto session = ClientSession::create(sid);
+    activeSessions_[sid] = session;
+    session->charge();
+    return session;
+}
+
+
+std::shared_ptr<ClientSession> SessionManager::removeSession(int64_t id) {
+    folly::RWSpinLock::WriteHolder holder(rwlock_);
+    auto iter = activeSessions_.find(id);
+    if (iter == activeSessions_.end()) {
+        return nullptr;
+    }
+    auto session = std::move(iter->second);
+    activeSessions_.erase(iter);
+    return session;
+}
+
+
+int64_t SessionManager::newSessionId() {
+    int64_t id = ++nextId_;
+    if (id == 0) {
+        id = ++nextId_;
+    }
+    return id;
+}
+
+
+// TODO(dutor) Now we do a brute-force scanning, of course we could make it more efficient.
+void SessionManager::reclaimExpiredSessions() {
+    folly::RWSpinLock::WriteHolder holder(rwlock_);
+    if (activeSessions_.empty()) {
+        return;
+    }
+
+    FVLOG3("Try to reclaim expired sessions out of %lu ones", activeSessions_.size());
+    auto iter = activeSessions_.begin();
+    auto end = activeSessions_.end();
+    while (iter != end) {
+        auto *session = iter->second.get();
+        int32_t idleSecs = session->idleSeconds();
+        if (idleSecs < FLAGS_session_idle_timeout_secs) {
+            ++iter;
+            continue;
+        }
+        FLOG_INFO("Session %ld has expired", session->id());
+        iter = activeSessions_.erase(iter);
+    }
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/SessionManager.h b/src/executor/SessionManager.h
new file mode 100644
index 00000000..4fb3d11a
--- /dev/null
+++ b/src/executor/SessionManager.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_SESSIONMANAGER_H_
+#define GRAPH_SESSIONMANAGER_H_
+
+#include "base/Base.h"
+#include "base/StatusOr.h"
+#include "graph/ClientSession.h"
+#include "thread/GenericWorker.h"
+
+/**
+ * SessionManager manages the client sessions, e.g. create new, find existing and drop expired.
+ */
+
+namespace nebula {
+namespace graph {
+
+class SessionManager final {
+public:
+    SessionManager();
+    ~SessionManager();
+
+    using SessionPtr = std::shared_ptr<ClientSession>;
+    /**
+     * Find an existing session
+     */
+    StatusOr<SessionPtr> findSession(int64_t id);
+    /**
+     * Create a new session
+     */
+    SessionPtr createSession();
+    /**
+     * Remove a session
+     */
+    SessionPtr removeSession(int64_t id);
+
+private:
+    /**
+     * Generate a non-zero number
+     */
+    int64_t newSessionId();
+
+    void reclaimExpiredSessions();
+
+private:
+    std::atomic<int64_t>                        nextId_{0};
+    folly::RWSpinLock                           rwlock_;        // TODO(dutor) writer might starve
+    std::unordered_map<int64_t, SessionPtr>     activeSessions_;
+    std::unique_ptr<thread::GenericWorker>      scavenger_;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+
+#endif  // GRAPH_SESSIONMANAGER_H_
diff --git a/src/executor/SimpleAuthenticator.h b/src/executor/SimpleAuthenticator.h
new file mode 100644
index 00000000..475e726f
--- /dev/null
+++ b/src/executor/SimpleAuthenticator.h
@@ -0,0 +1,32 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_SIMPLEAUTHENTICATOR_H_
+#define GRAPH_SIMPLEAUTHENTICATOR_H_
+
+#include "base/Base.h"
+#include "graph/Authenticator.h"
+
+namespace nebula {
+namespace graph {
+
+class SimpleAuthenticator final : public Authenticator {
+public:
+    bool VE_MUST_USE_RESULT auth(const std::string &user,
+                                 const std::string &password) override {
+        if (user == "user" && password == "password") {
+            return true;
+        }
+        return false;
+    }
+
+private:
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_SIMPLEAUTHENTICATOR_H_
diff --git a/src/executor/TraverseExecutor.cpp b/src/executor/TraverseExecutor.cpp
new file mode 100644
index 00000000..cf4e84c7
--- /dev/null
+++ b/src/executor/TraverseExecutor.cpp
@@ -0,0 +1,37 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/TraverseExecutor.h"
+#include "parser/TraverseSentences.h"
+#include "graph/GoExecutor.h"
+#include "graph/PipeExecutor.h"
+
+namespace nebula {
+namespace graph {
+
+std::unique_ptr<TraverseExecutor> TraverseExecutor::makeTraverseExecutor(Sentence *sentence) {
+    auto kind = sentence->kind();
+    std::unique_ptr<TraverseExecutor> executor;
+    switch (kind) {
+        case Sentence::Kind::kGo:
+            executor = std::make_unique<GoExecutor>(sentence, ectx());
+            break;
+        case Sentence::Kind::kPipe:
+            executor = std::make_unique<PipeExecutor>(sentence, ectx());
+            break;
+        case Sentence::Kind::kUnknown:
+            LOG(FATAL) << "Sentence kind unknown";
+            break;
+        default:
+            LOG(FATAL) << "Sentence kind illegal: " << kind;
+            break;
+    }
+    return executor;
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/TraverseExecutor.h b/src/executor/TraverseExecutor.h
new file mode 100644
index 00000000..dbbfb3dc
--- /dev/null
+++ b/src/executor/TraverseExecutor.h
@@ -0,0 +1,97 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_TRAVERSEEXECUTOR_H_
+#define GRAPH_TRAVERSEEXECUTOR_H_
+
+#include "base/Base.h"
+#include "graph/Executor.h"
+
+namespace nebula {
+namespace graph {
+
+class ResultSchema final {
+public:
+    struct Column {
+        std::string                             name_;
+        // TODO(dutor) type
+    };
+
+    void addColumn(std::string name) {
+        columns_.emplace_back();
+        columns_.back().name_ = std::move(name);
+
+    }
+
+    std::string toString() const {
+        std::string buf;
+        buf.reserve(256);
+        for (auto &column : columns_) {
+            if (column.name_.empty()) {
+                buf += "NULL";
+            } else {
+                buf += column.name_;
+            }
+            buf += "\t";
+        }
+        if (!buf.empty()) {
+            buf.resize(buf.size() - 1);
+        }
+        return buf;
+    }
+
+private:
+    std::vector<Column>                         columns_;
+};
+
+
+class TraverseExecutor : public Executor {
+public:
+    TraverseExecutor(ExecutionContext *ectx) : Executor(ectx) {
+    }
+
+    using TraverseRecord = std::vector<VariantType>;
+    using TraverseRecords = std::vector<TraverseRecord>;
+    using OnResult = std::function<void(TraverseRecords)>;
+
+    virtual void feedResult(TraverseRecords records) = 0;
+
+    /**
+     * `onResult_' must be set except for the right most executor
+     * inside the chain of pipeline.
+     *
+     * For any TraverseExecutor, if `onResult_' is set, it means that
+     * some other executor depends on its execution result. Otherwise,
+     * it means that this executor is the right most one, whose results must
+     * be cached during its execution and are to be used to fill `ExecutionResponse'
+     * upon `setupResponse()'s invoke.
+     */
+    void setOnResult(OnResult onResult) {
+        onResult_ = std::move(onResult);
+    }
+
+    virtual ResultSchema* resultSchema() const {
+        return resultSchema_.get();
+    }
+
+    virtual void setInputResultSchema(ResultSchema *schema) {
+        inputResultSchema_ = schema;
+    }
+
+protected:
+    std::unique_ptr<TraverseExecutor> makeTraverseExecutor(Sentence *sentence);
+
+protected:
+    OnResult                                    onResult_;
+    std::unique_ptr<ResultSchema>               resultSchema_;
+    ResultSchema                               *inputResultSchema_{nullptr};
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+
+#endif  // GRAPH_TRAVERSEEXECUTOR_H_
diff --git a/src/executor/UseExecutor.cpp b/src/executor/UseExecutor.cpp
new file mode 100644
index 00000000..4dc41a24
--- /dev/null
+++ b/src/executor/UseExecutor.cpp
@@ -0,0 +1,34 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/UseExecutor.h"
+
+namespace nebula {
+namespace graph {
+
+UseExecutor::UseExecutor(Sentence *sentence, ExecutionContext *ectx) : Executor(ectx) {
+    sentence_ = static_cast<UseSentence*>(sentence);
+}
+
+
+Status UseExecutor::prepare() {
+    return Status::OK();
+}
+
+
+void UseExecutor::execute() {
+    auto *session = ectx()->rctx()->session();
+
+    // TODO(dutor) Check space's validness and map to type of integer
+    session->setSpace(sentence_->space());
+    FLOG_INFO("Graph space switched to `%s'", sentence_->space().c_str());
+
+    onFinish_();
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/UseExecutor.h b/src/executor/UseExecutor.h
new file mode 100644
index 00000000..05d637c3
--- /dev/null
+++ b/src/executor/UseExecutor.h
@@ -0,0 +1,36 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_USEEXECUTOR_H_
+#define GRAPH_USEEXECUTOR_H_
+
+#include "base/Base.h"
+#include "graph/Executor.h"
+
+namespace nebula {
+namespace graph {
+
+class UseExecutor final : public Executor {
+public:
+    UseExecutor(Sentence *sentence, ExecutionContext *ectx);
+
+    const char* name() const override {
+        return "UseExecutor";
+    }
+
+    Status VE_MUST_USE_RESULT prepare() override;
+
+    void execute() override;
+
+private:
+    UseSentence                                *sentence_{nullptr};
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+
+#endif  // GRAPH_USEEXECUTOR_H_
diff --git a/src/executor/mock/EdgeSchema.cpp b/src/executor/mock/EdgeSchema.cpp
new file mode 100644
index 00000000..e85e65ed
--- /dev/null
+++ b/src/executor/mock/EdgeSchema.cpp
@@ -0,0 +1,32 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/mock/EdgeSchema.h"
+
+namespace nebula {
+namespace graph {
+
+void EdgeSchema::addProperty(std::string name, ColumnType type) {
+    properties_.addProperty(std::move(name), type);
+}
+
+
+const PropertyItem* EdgeSchema::getProperty(const std::string &name) {
+    return properties_.getProperty(name);
+}
+
+
+std::string EdgeSchema::toString() const {
+    return folly::stringPrintf("%s[%u] %s[%u]->%s[%u] %s",
+                               name_.c_str(), id_,
+                               srcTag_.c_str(), srcId_,
+                               dstTag_.c_str(), dstId_,
+                               properties_.toString().c_str());
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/mock/EdgeSchema.h b/src/executor/mock/EdgeSchema.h
new file mode 100644
index 00000000..7cd1f850
--- /dev/null
+++ b/src/executor/mock/EdgeSchema.h
@@ -0,0 +1,89 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_EDGESCHEMA_H_
+#define GRAPH_EDGESCHEMA_H_
+
+#include "base/Base.h"
+#include "graph/mock/PropertiesSchema.h"
+
+namespace nebula {
+namespace graph {
+
+class EdgeSchema final {
+public:
+    uint32_t id() const {
+        return id_;
+    }
+
+    void setId(uint32_t id) {
+        id_ = id;
+    }
+
+    const std::string& name() const {
+        return name_;
+    }
+
+    void setName(std::string name) {
+        name_ = std::move(name);
+    }
+
+    const std::string& srcTag() const {
+        return srcTag_;
+    }
+
+    void setSrcTag(std::string tag) {
+        srcTag_ = tag;
+    }
+
+    const std::string& dstTag() const {
+        return dstTag_;
+    }
+
+    void setDstTag(std::string tag) {
+        dstTag_ = tag;
+    }
+
+    uint32_t srcId() const {
+        return srcId_;
+    }
+
+    void setSrcId(uint32_t id) {
+        srcId_ = id;
+    }
+
+    uint32_t dstId() const {
+        return dstId_;
+    }
+
+    void setDstId(uint32_t id) {
+        dstId_ = id;
+    }
+
+    void addProperty(std::string name, ColumnType type);
+
+    const PropertyItem* getProperty(const std::string &name);
+
+    const PropertiesSchema* getPropertiesSchema() const {
+        return &properties_;
+    }
+
+    std::string toString() const;
+
+private:
+    uint32_t                                    id_{0};
+    uint32_t                                    srcId_{0};
+    uint32_t                                    dstId_{0};
+    std::string                                 name_;
+    std::string                                 srcTag_;
+    std::string                                 dstTag_;
+    PropertiesSchema                            properties_;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_EDGESCHEMA_H_
diff --git a/src/executor/mock/PropertiesSchema.cpp b/src/executor/mock/PropertiesSchema.cpp
new file mode 100644
index 00000000..3d8f477c
--- /dev/null
+++ b/src/executor/mock/PropertiesSchema.cpp
@@ -0,0 +1,55 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/mock/PropertiesSchema.h"
+
+namespace nebula {
+namespace graph {
+
+void PropertiesSchema::addProperty(std::string name, ColumnType type) {
+    auto index = properties_.size();
+    properties_.emplace_back();
+    auto &item = properties_.back();
+    item.index_ = index;
+    item.name_ = std::move(name);
+    item.type_ = type;
+    mapping_[name] = &item;
+}
+
+
+const PropertyItem* PropertiesSchema::getProperty(const std::string &name) const {
+    auto iter = mapping_.find(name);
+    if (iter != mapping_.end()) {
+        return nullptr;
+    }
+    return iter->second;
+}
+
+
+const std::vector<PropertyItem>& PropertiesSchema::getItems() const {
+    return properties_;
+}
+
+
+std::string PropertiesSchema::toString() const {
+    std::string buf;
+    for (auto &item : properties_) {
+        buf += item.name_;
+        buf += "[";
+        buf += std::to_string(item.index_);
+        buf += "] ";
+        buf += columnTypeToString(item.type_);
+        buf += ",";
+    }
+    if (!buf.empty()) {
+        buf.resize(buf.size() - 1);
+    }
+    return buf;
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/mock/PropertiesSchema.h b/src/executor/mock/PropertiesSchema.h
new file mode 100644
index 00000000..643e01c7
--- /dev/null
+++ b/src/executor/mock/PropertiesSchema.h
@@ -0,0 +1,42 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_PROPERTIESSCHEMA_H_
+#define GRAPH_PROPERTIESSCHEMA_H_
+
+#include "base/Base.h"
+#include "parser/Expressions.h"
+
+namespace nebula {
+namespace graph {
+
+struct PropertyItem {
+    uint32_t                                    index_{0};
+    std::string                                 name_;
+    ColumnType                                  type_;
+};
+
+
+class PropertiesSchema final {
+public:
+    void addProperty(std::string name, ColumnType type);
+
+    const PropertyItem* getProperty(const std::string &name) const;
+
+    const std::vector<PropertyItem>& getItems() const;
+
+    std::string toString() const;
+
+private:
+    using MappingType = std::unordered_map<std::string, const PropertyItem*>;
+    std::vector<PropertyItem>                   properties_;
+    MappingType                                 mapping_;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_PROPERTIESSCHEMA_H_
diff --git a/src/executor/mock/SchemaManager.cpp b/src/executor/mock/SchemaManager.cpp
new file mode 100644
index 00000000..823b627c
--- /dev/null
+++ b/src/executor/mock/SchemaManager.cpp
@@ -0,0 +1,70 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/mock/SchemaManager.h"
+
+namespace nebula {
+namespace graph {
+
+void SchemaManager::addEdgeSchema(const std::string &name,
+                                  const std::string &src,
+                                  const std::string &dst,
+                                  const std::vector<ColumnSpecification*> &specs) {
+    // TODO(dutor) check existence of src & dst tag
+    auto &schema = edges_[name];
+    schema.setId(nextEdgeId_++);
+    schema.setName(name);
+    schema.setSrcTag(src);
+    schema.setDstTag(dst);
+    schema.setSrcId(tags_[src].id());
+    schema.setDstId(tags_[dst].id());
+    for (auto *spec : specs) {
+        schema.addProperty(*spec->name(), spec->type());
+    }
+}
+
+
+void SchemaManager::addTagSchema(const std::string &name,
+                                 const std::vector<ColumnSpecification*> &specs) {
+    auto &schema = tags_[name];
+    schema.setId(nextTagId_++);
+    schema.setName(name);
+    for (auto *spec : specs) {
+        schema.addProperty(*spec->name(), spec->type());
+    }
+}
+
+
+const EdgeSchema* SchemaManager::getEdgeSchema(const std::string &name) {
+    auto iter = edges_.find(name);
+    if (iter == edges_.end()) {
+        return nullptr;
+    }
+    return &iter->second;
+}
+
+
+const TagSchema* SchemaManager::getTagSchema(const std::string &name) {
+    auto iter = tags_.find(name);
+    if (iter == tags_.end()) {
+        return nullptr;
+    }
+    return &iter->second;
+}
+
+
+void SchemaManager::print() const {
+    for (auto &entry : edges_) {
+        FLOG_INFO("Edge `%s': \n%s", entry.first.c_str(), entry.second.toString().c_str());
+    }
+    for (auto &entry : tags_) {
+        FLOG_INFO("Tag `%s': \n%s", entry.first.c_str(), entry.second.toString().c_str());
+    }
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/mock/SchemaManager.h b/src/executor/mock/SchemaManager.h
new file mode 100644
index 00000000..bc88f270
--- /dev/null
+++ b/src/executor/mock/SchemaManager.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_SCHEMAMANAGER_H_
+#define GRAPH_SCHEMAMANAGER_H_
+
+#include "base/Base.h"
+#include "graph/mock/EdgeSchema.h"
+#include "graph/mock/TagSchema.h"
+#include "parser/MaintainSentences.h"
+
+namespace nebula {
+namespace graph {
+
+class SchemaManager final {
+public:
+    void addEdgeSchema(const std::string &name,
+                       const std::string &src,
+                       const std::string &dst,
+                       const std::vector<ColumnSpecification*> &specs);
+    void addTagSchema(const std::string &name,
+                      const std::vector<ColumnSpecification*> &specs);
+
+    const EdgeSchema* getEdgeSchema(const std::string &name);
+
+    const TagSchema* getTagSchema(const std::string &name);
+
+    void print() const;
+
+private:
+    uint32_t                                    nextEdgeId_{0};
+    uint32_t                                    nextTagId_{0};
+    std::unordered_map<std::string, EdgeSchema> edges_;
+    std::unordered_map<std::string, TagSchema>  tags_;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_SCHEMAMANAGER_H_
diff --git a/src/executor/mock/StorageService.cpp b/src/executor/mock/StorageService.cpp
new file mode 100644
index 00000000..555aaa42
--- /dev/null
+++ b/src/executor/mock/StorageService.cpp
@@ -0,0 +1,107 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/mock/StorageService.h"
+
+namespace nebula {
+namespace graph {
+
+StorageService::StorageService(SchemaManager *sm) {
+    pool_ = std::make_unique<thread::GenericThreadPool>();
+    pool_->start(4, "storage-svc");
+    sm_ = sm;
+}
+
+
+folly::SemiFuture<Status>
+StorageService::addTag(const std::string *tag,
+                       int64_t id,
+                       const std::vector<std::string*> &names,
+                       const std::vector<VariantType> &values) {
+    auto task = [this, tag, id, names, values] () -> Status {
+        auto *schema = sm_->getTagSchema(*tag);
+        if (schema == nullptr) {
+            return Status::Error("Tag `%s' not defined", tag->c_str());
+        }
+        TagKey key;
+        key.id_ = id;
+        key.type_ = schema->id();
+        auto &props = tags_[key];
+        for (auto i = 0u; i < names.size(); i++) {
+            props[*names[i]] = values[i];
+        }
+        return Status::OK();
+    };
+    return pool_->addTask(std::move(task));
+}
+
+
+folly::SemiFuture<Status>
+StorageService::addEdge(const std::string *edge,
+                        int64_t srcid, int64_t dstid,
+                        const std::vector<std::string*> &names,
+                        const std::vector<VariantType> &values) {
+    auto task = [this, edge, srcid, dstid, names, values] () -> Status {
+        auto *schema = sm_->getEdgeSchema(*edge);
+        if (schema == nullptr) {
+            return Status::Error("Edge `%s' not defined", edge->c_str());
+        }
+        EdgeKey key;
+        key.srcid_ = srcid;
+        key.dstid_ = dstid;
+        key.type_ = schema->id();
+        auto  &props = edges_[key];
+        for (auto i = 0u; i < names.size(); i++) {
+            props[*names[i]] = values[i];
+        }
+        return Status::OK();
+    };
+
+    return pool_->addTask(std::move(task));
+}
+
+folly::SemiFuture<StorageService::OutBoundResult>
+StorageService::getOutBound(const std::vector<int64_t> &ids,
+                            const std::string *edge,
+                            const std::vector<std::string> &eprops,
+                            const std::vector<std::string> &vprops) {
+    auto task = [this, ids, edge, eprops, vprops] () -> OutBoundResult {
+        OutBoundResult result;
+        auto *schema = sm_->getEdgeSchema(*edge);
+        if (schema == nullptr) {
+            return Status::Error("Edge `%s' not defined", edge->c_str());
+        }
+        //storage::cpp2::QueryResponse resp;
+        for (auto id : ids) {
+            EdgeKey start, end;
+            start.srcid_ = id;
+            start.type_ = schema->id();
+            start.dstid_ = -1;
+            end.srcid_ = id;
+            end.type_ = start.type_ + 1;
+            end.dstid_ = -1;
+            auto left = edges_.lower_bound(start);
+            auto right = edges_.lower_bound(end);
+            for (auto iter = left; iter != right; ++iter) {
+                if (iter->first.srcid_ != id) {
+                    break;
+                }
+                if (iter->first.type_ != start.type_) {
+                    break;
+                }
+                //auto &properties = iter->second;
+                FLOG_INFO("%ld -%s-> %ld", id, edge->c_str(), iter->first.dstid_);
+            }
+        }
+        return result;
+    };
+
+    return pool_->addTask(std::move(task));
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/mock/StorageService.h b/src/executor/mock/StorageService.h
new file mode 100644
index 00000000..632d90c8
--- /dev/null
+++ b/src/executor/mock/StorageService.h
@@ -0,0 +1,86 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_MOCK_STORAGESERVICE_H_
+#define GRAPH_MOCK_STORAGESERVICE_H_
+
+#include "base/Base.h"
+#include "base/Status.h"
+#include "base/StatusOr.h"
+#include "gen-cpp2/StorageService.h"
+#include "thread/GenericThreadPool.h"
+#include "graph/mock/SchemaManager.h"
+
+namespace nebula {
+namespace graph {
+
+class StorageService {
+public:
+    StorageService(SchemaManager *sm);
+
+    folly::SemiFuture<Status> addTag(const std::string *tag,
+                                     int64_t id,
+                                     const std::vector<std::string*> &names,
+                                     const std::vector<VariantType> &values);
+
+    folly::SemiFuture<Status> addEdge(const std::string *edge,
+                                      int64_t srcid, int64_t dstid,
+                                      const std::vector<std::string*> &names,
+                                      const std::vector<VariantType> &values);
+    using OutBoundResult = StatusOr<storage::cpp2::QueryResponse>;
+    folly::SemiFuture<OutBoundResult> getOutBound(const std::vector<int64_t> &ids,
+                                                  const std::string *edge,
+                                                  const std::vector<std::string> &eprops,
+                                                  const std::vector<std::string> &vprops);
+
+private:
+    struct TagKey {
+        int64_t     id_{0};
+        int64_t     type_{0};
+    };
+
+    struct EdgeKey {
+        int64_t     srcid_{0};
+        int64_t     dstid_{0};
+        int32_t     type_{0};
+    };
+
+    struct TagLess {
+        bool operator()(const TagKey &lhs, const TagKey &rhs) const {
+            if (lhs.id_ != rhs.id_) {
+                return lhs.id_ < rhs.id_;
+            }
+            return lhs.type_ < rhs.type_;
+        }
+    };
+
+    struct EdgeLess {
+        bool operator()(const EdgeKey &lhs, const EdgeKey &rhs) const {
+            if (lhs.srcid_ != rhs.srcid_) {
+                return lhs.srcid_ < rhs.dstid_;
+            }
+            if (lhs.type_ != rhs.type_) {
+                return lhs.type_ < rhs.type_;
+            }
+            return lhs.dstid_ < rhs.dstid_;
+        }
+    };
+
+    using PropertiesType = std::unordered_map<std::string, VariantType>;
+    using TagsType = std::map<TagKey, PropertiesType, TagLess>;
+    using EdgesType = std::map<EdgeKey, PropertiesType, EdgeLess>;
+
+private:
+    TagsType                                    tags_;
+    EdgesType                                   edges_;
+    std::unique_ptr<thread::GenericThreadPool>  pool_;
+    SchemaManager                              *sm_;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif
diff --git a/src/executor/mock/TagSchema.cpp b/src/executor/mock/TagSchema.cpp
new file mode 100644
index 00000000..d4649b3a
--- /dev/null
+++ b/src/executor/mock/TagSchema.cpp
@@ -0,0 +1,34 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/mock/TagSchema.h"
+
+namespace nebula {
+namespace graph {
+
+void TagSchema::addProperty(std::string name, ColumnType type) {
+    properties_.addProperty(std::move(name), type);
+}
+
+
+const PropertyItem* TagSchema::getProperty(const std::string &name) const {
+    return properties_.getProperty(name);
+}
+
+
+std::string TagSchema::toString() const {
+    return folly::stringPrintf("%s[%u] %s",
+                               name_.c_str(), id_, properties_.toString().c_str());
+}
+
+
+const PropertiesSchema* TagSchema::getPropertiesSchema() const {
+    return &properties_;
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/mock/TagSchema.h b/src/executor/mock/TagSchema.h
new file mode 100644
index 00000000..7e979928
--- /dev/null
+++ b/src/executor/mock/TagSchema.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_TAGSCHEMA_H_
+#define GRAPH_TAGSCHEMA_H_
+
+#include "base/Base.h"
+#include "graph/mock/PropertiesSchema.h"
+
+namespace nebula {
+namespace graph {
+
+class TagSchema final {
+public:
+    uint32_t id() const {
+        return id_;
+    }
+
+    void setId(uint32_t id) {
+        id_ = id;
+    }
+
+    const std::string &name() const {
+        return name_;
+    }
+
+    void setName(std::string name) {
+        name_ = std::move(name);
+    }
+
+    void addProperty(std::string name, ColumnType type);
+
+    const PropertyItem* getProperty(const std::string &name) const;
+
+    const PropertiesSchema* getPropertiesSchema() const;
+
+    std::string toString() const;
+
+private:
+    uint32_t                                    id_{0};
+    std::string                                 name_;
+    PropertiesSchema                            properties_;
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_TAGSCHEMA_H_
diff --git a/src/executor/test/CMakeLists.txt b/src/executor/test/CMakeLists.txt
new file mode 100644
index 00000000..b277b297
--- /dev/null
+++ b/src/executor/test/CMakeLists.txt
@@ -0,0 +1,71 @@
+add_executable(
+    session_manager_test
+    SessionManagerTest.cpp
+    $<TARGET_OBJECTS:graph_obj>
+    $<TARGET_OBJECTS:base_obj>
+    $<TARGET_OBJECTS:graph_thrift_obj>
+    $<TARGET_OBJECTS:time_obj>
+    $<TARGET_OBJECTS:fs_obj>
+    $<TARGET_OBJECTS:thread_obj>
+    $<TARGET_OBJECTS:parser_obj>
+)
+target_link_libraries(
+    session_manager_test
+    ${THRIFT_LIBRARIES}
+    wangle
+    folly
+    boost_system
+    boost_context
+    ${OPENSSL_LIBRARIES}
+    ${KRB5_LIBRARIES}
+    gtest
+    gtest_main
+    glog
+    gflags
+    event
+    ${COMPRESSION_LIBRARIES}
+    resolv
+    double-conversion
+    dl
+    -pthread
+)
+
+add_test(NAME session_manager_test COMMAND session_manager_test)
+
+
+add_executable(
+    query_engine_test
+    TestMain.cpp
+    TestEnv.cpp
+    TestBase.cpp
+    DefineSchemaTest.cpp
+    $<TARGET_OBJECTS:graph_obj>
+    $<TARGET_OBJECTS:client_cpp_obj>
+    $<TARGET_OBJECTS:base_obj>
+    $<TARGET_OBJECTS:graph_thrift_obj>
+    $<TARGET_OBJECTS:time_obj>
+    $<TARGET_OBJECTS:fs_obj>
+    $<TARGET_OBJECTS:thread_obj>
+    $<TARGET_OBJECTS:parser_obj>
+)
+target_link_libraries(
+    query_engine_test
+    ${THRIFT_LIBRARIES}
+    wangle
+    folly
+    boost_system
+    boost_context
+    ${OPENSSL_LIBRARIES}
+    ${KRB5_LIBRARIES}
+    gtest
+    gtest_main
+    glog
+    gflags
+    event
+    ${COMPRESSION_LIBRARIES}
+    resolv
+    double-conversion
+    dl
+    -pthread
+)
+add_test(NAME query_engine_test COMMAND query_engine_test)
diff --git a/src/executor/test/DefineSchemaTest.cpp b/src/executor/test/DefineSchemaTest.cpp
new file mode 100644
index 00000000..09cffe7b
--- /dev/null
+++ b/src/executor/test/DefineSchemaTest.cpp
@@ -0,0 +1,122 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/test/TestEnv.h"
+#include "graph/test/TestBase.h"
+
+
+namespace nebula {
+namespace graph {
+
+class DefineSchemaTest : public TestBase {
+protected:
+    void SetUp() override {
+        TestBase::SetUp();
+        // ...
+    }
+
+    void TearDown() override {
+        // ...
+        TestBase::TearDown();
+    }
+
+};
+
+
+TEST_F(DefineSchemaTest, Simple) {
+    auto client = gEnv->getClient();
+    ASSERT_NE(nullptr, client);
+    {
+        cpp2::ExecutionResponse resp;
+        std::string query = "DEFINE TAG person(name string, email string, age int16, gender string)";
+        auto code = client->execute(query, resp);
+        ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
+    }
+    {
+        cpp2::ExecutionResponse resp;
+        std::string query = "DESCRIBE TAG person";
+        client->execute(query, resp);
+        std::vector<uniform_tuple_t<std::string, 2>> expected{
+            {"email", "string"},
+            {"name", "string"},
+            {"age", "int16"},
+            {"gender", "string"},
+        };
+        ASSERT_TRUE(verifyResult(resp, expected));
+    }
+    {
+        cpp2::ExecutionResponse resp;
+        std::string query = "DEFINE TAG account(id int64, balance double)";
+        auto code = client->execute(query, resp);
+        ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
+    }
+    {
+        cpp2::ExecutionResponse resp;
+        std::string query = "DESCRIBE TAG account";
+        client->execute(query, resp);
+        std::vector<uniform_tuple_t<std::string, 2>> expected{
+            {"id", "int64"},
+            {"balance", "double"},
+        };
+        ASSERT_TRUE(verifyResult(resp, expected));
+    }
+    {
+        cpp2::ExecutionResponse resp;
+        std::string query = "DEFINE EDGE friend_of person -> person()";
+        auto code = client->execute(query, resp);
+        ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
+    }
+    {
+        cpp2::ExecutionResponse resp;
+        std::string query = "DESCRIBE EDGE friend_of";
+        client->execute(query, resp);
+        std::vector<uniform_tuple_t<std::string, 2>> expected{
+            {"person", "person"},
+        };
+        ASSERT_TRUE(verifyResult(resp, expected));
+    }
+    {
+        cpp2::ExecutionResponse resp;
+        std::string query = "DEFINE EDGE transfer "
+                            "account -> account(amount double, time int64)";
+        auto code = client->execute(query, resp);
+        ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
+    }
+    {
+        cpp2::ExecutionResponse resp;
+        std::string query = "DESCRIBE EDGE transfer";
+        client->execute(query, resp);
+        std::vector<uniform_tuple_t<std::string, 4>> expected{
+            {"account", "account", "amount", "double"},
+            {"account", "account", "time", "int64"},
+        };
+        ASSERT_TRUE(verifyResult(resp, expected));
+    }
+    // compound sentences
+    {
+        cpp2::ExecutionResponse resp;
+        std::string query = "DESCRIBE EDGE friend_of; DESCRIBE EDGE transfer";
+        client->execute(query, resp);
+        std::vector<uniform_tuple_t<std::string, 4>> expected{
+            {"account", "account", "amount", "double"},
+            {"account", "account", "time", "int64"},
+        };
+        ASSERT_TRUE(verifyResult(resp, expected));
+    }
+    {
+        cpp2::ExecutionResponse resp;
+        std::string query = "DESCRIBE EDGE transfer; DESCRIBE EDGE friend_of";
+        client->execute(query, resp);
+        std::vector<uniform_tuple_t<std::string, 2>> expected{
+            {"person", "person"},
+        };
+        ASSERT_TRUE(verifyResult(resp, expected));
+    }
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/test/SessionManagerTest.cpp b/src/executor/test/SessionManagerTest.cpp
new file mode 100644
index 00000000..5de7ae8a
--- /dev/null
+++ b/src/executor/test/SessionManagerTest.cpp
@@ -0,0 +1,82 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include <gtest/gtest.h>
+#include "graph/SessionManager.h"
+#include "graph/GraphFlags.h"
+#include "thread/GenericWorker.h"
+
+using nebula::thread::GenericWorker;
+
+namespace nebula {
+namespace graph {
+
+TEST(SessionManager, Basic) {
+    auto sm = std::make_shared<SessionManager>();
+
+    auto session = sm->createSession();
+    ASSERT_NE(nullptr, session);
+    ASSERT_NE(0, session->id());
+
+    auto result = sm->findSession(session->id());
+    ASSERT_TRUE(result.ok());
+    ASSERT_EQ(session.get(), result.value().get());
+}
+
+TEST(SessionManager, ExpiredSession) {
+    FLAGS_session_idle_timeout_secs = 3;
+    FLAGS_session_reclaim_interval_secs = 1;
+
+    auto sm = std::make_shared<SessionManager>();
+
+    auto worker = std::make_shared<GenericWorker>();
+    ASSERT_TRUE(worker->start());
+
+    auto idle = sm->createSession();
+    auto active = sm->createSession();
+    ASSERT_NE(nullptr, idle);
+    ASSERT_NE(nullptr, active);
+    ASSERT_NE(idle.get(), active.get());
+    ASSERT_NE(idle->id(), active->id());
+
+    // keep `active' active
+    auto charger = [&] () {
+        active->charge();
+    };
+    worker->addRepeatTask(1000/*ms*/, charger);
+
+    // assert `idle' not expired
+    auto check_not_expired = [&] () {
+        auto result = sm->findSession(idle->id());
+        ASSERT_TRUE(result.ok());
+        ASSERT_NE(nullptr, result.value());
+    };
+
+    // assert `idle' has expired
+    auto check_already_expired = [&] () {
+        auto result = sm->findSession(idle->id());
+        ASSERT_FALSE(result.ok());
+    };
+
+    auto timeout = FLAGS_session_idle_timeout_secs;
+    auto future1 = worker->addDelayTask((timeout - 1) * 1000 - 50/*ms*/, check_not_expired);
+    auto future2 = worker->addDelayTask((timeout + 1) * 1000 + 50/*ms*/, check_already_expired);
+
+    std::move(future1).get();
+    std::move(future2).get();
+
+    auto result = sm->findSession(active->id());
+    ASSERT_TRUE(result.ok());
+    ASSERT_NE(nullptr, result.value());
+    ASSERT_EQ(active.get(), result.value().get());
+
+    worker->stop();
+    worker->wait();
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/test/TestBase.cpp b/src/executor/test/TestBase.cpp
new file mode 100644
index 00000000..6c8d02a3
--- /dev/null
+++ b/src/executor/test/TestBase.cpp
@@ -0,0 +1,21 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/test/TestBase.h"
+
+namespace nebula {
+namespace graph {
+
+void TestBase::SetUp() {
+}
+
+
+void TestBase::TearDown() {
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/test/TestBase.h b/src/executor/test/TestBase.h
new file mode 100644
index 00000000..97d514dd
--- /dev/null
+++ b/src/executor/test/TestBase.h
@@ -0,0 +1,204 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_TEST_TESTBASE_H_
+#define GRAPH_TEST_TESTBASE_H_
+
+#include "base/Base.h"
+#include <gtest/gtest.h>
+#include "gen-cpp2/GraphService.h"
+
+/**
+ * According to the ADL(Argument-dependent Lookup) rules,
+ * we have to define operator<< for `std::tuple<...>' in the global scope or `std'
+ */
+namespace std {
+
+template <typename Tuple, size_t...Is>
+void printTupleImpl(std::ostream &os, const Tuple &tuple, std::index_sequence<Is...>) {
+    auto flags = os.flags();
+    os << std::boolalpha;
+
+    using DumyType = int[];
+    (void)DumyType{(void(os << (Is == 0 ? "" : ", ") << std::get<Is>(tuple)), 0)...};
+
+    os.flags(flags);
+}
+
+
+template <typename Tuple>
+void printTuple(std::ostream &os, const Tuple &tuple) {
+    printTupleImpl(os, tuple, std::make_index_sequence<std::tuple_size<Tuple>::value>());
+}
+
+
+template <typename...Args>
+std::ostream& operator<<(std::ostream &os, const std::tuple<Args...> &tuple) {
+    os << "[";
+    printTuple(os, tuple);
+    os << "]";
+    return os;
+}
+
+}   // namespace std
+
+
+namespace nebula {
+namespace graph {
+
+class TestBase : public ::testing::Test {
+protected:
+    void SetUp() override;
+
+    void TearDown() override;
+
+    using AssertionResult = ::testing::AssertionResult;
+    using ColumnType = cpp2::ColumnValue::Type;
+    using Row = std::vector<cpp2::ColumnValue>;
+    using Rows = std::vector<Row>;
+
+    template <typename, typename>
+    struct uniform_tuple_impl;
+    template <typename T, size_t...Is>
+    struct uniform_tuple_impl<T, std::index_sequence<Is...>> {
+        template <size_t>
+        using IndexedType = T;
+        using type = std::tuple<IndexedType<Is>...>;
+    };
+
+    template <typename T, size_t N>
+    struct uniform_tuple {
+        using type = typename uniform_tuple_impl<T, std::make_index_sequence<N>>::type;
+    };
+
+    template <typename T, size_t N>
+    using uniform_tuple_t = typename uniform_tuple<T, N>::type;
+
+    Rows respToRecords(const cpp2::ExecutionResponse &resp) {
+        CHECK(resp.get_rows() != nullptr);
+        Rows result;
+        for (auto &row : *resp.get_rows()) {
+            auto &columns = row.get_columns();
+            result.emplace_back();
+            result.back().assign(columns.begin(), columns.end());
+        }
+        return result;
+    }
+
+    /**
+     * Convert `ColumnValue' to its cooresponding type
+     */
+    template <typename T>
+    std::enable_if_t<std::is_integral<T>::value, T>
+    convert(const cpp2::ColumnValue &v) {
+        switch (v.getType()) {
+            case ColumnType::integer:
+                return v.get_integer();
+            case ColumnType::timestamp:
+                return v.get_timestamp();
+            case ColumnType::id:
+                return v.get_id();
+            case ColumnType::boolean:
+                return v.get_boolean();
+            default:
+                throw TestError() << "Cannot convert unknown dynamic column type to integer: "
+                                  << static_cast<int32_t>(v.getType());
+        }
+        return T();     // suppress the no-return waring
+    }
+
+    template <typename T>
+    std::enable_if_t<std::is_same<T, std::string>::value, T>
+    convert(const cpp2::ColumnValue &v) {
+        switch (v.getType()) {
+            case ColumnType::str:
+                return v.get_str();
+            default:
+                throw TestError() << "Cannot convert unknown dynamic column type to string: "
+                                  << static_cast<int32_t>(v.getType());
+        }
+        return T();     // suppress the no-return warning
+    }
+
+    /**
+     * Transform rows of dynamic type to tuples of static type
+     */
+    template <typename Tuple, size_t...Is>
+    auto rowToTupleImpl(const Row &row, std::index_sequence<Is...>) {
+        return std::make_tuple(convert<std::tuple_element_t<Is, Tuple>>(row[Is])...);
+    }
+
+    template <typename Tuple>
+    auto rowToTuple(const Row &row) {
+        constexpr auto tupleSize = std::tuple_size<Tuple>::value;
+        return rowToTupleImpl<Tuple>(row, std::make_index_sequence<tupleSize>());
+    }
+
+    template <typename Tuple>
+    auto rowsToTuples(const Rows &rows) {
+        std::vector<Tuple> result;
+        if (rows.empty()) {
+            return result;
+        }
+        if (rows.back().size() != std::tuple_size<Tuple>::value) {
+            throw TestError() << "Column count not match: "
+                              << rows.back().size() << " vs. "
+                              << std::tuple_size<Tuple>::value;
+        }
+        for (auto &row : rows) {
+            result.emplace_back(rowToTuple<Tuple>(row));
+        }
+        return result;
+    }
+
+    template <typename Tuple>
+    AssertionResult verifyResult(const cpp2::ExecutionResponse &resp,
+                                 std::vector<Tuple> &expected) {
+        if (resp.get_error_code() != cpp2::ErrorCode::SUCCEEDED) {
+            auto *errmsg = resp.get_error_msg();
+            return TestError() << "Query failed with `"
+                               << static_cast<int32_t>(resp.get_error_code())
+                               << (errmsg == nullptr ? "'" : "': " + *errmsg);
+        }
+
+        std::vector<Tuple> rows;
+        try {
+            rows = rowsToTuples<Tuple>(respToRecords(resp));
+        } catch (const AssertionResult &e) {
+            return e;
+        } catch (const std::exception &e) {
+            return TestError() << "Unknown exception thrown: " << e.what();
+        }
+
+        if (expected.size() != rows.size()) {
+            return TestError() << "Rows' count not match: "
+                               << rows.size() << " vs. " << expected.size();
+        }
+
+        if (expected.empty()) {
+            return TestOK();
+        }
+
+        std::sort(rows.begin(), rows.end());
+        std::sort(expected.begin(), expected.end());
+
+        for (auto i = 0u; i < rows.size(); i++) {
+            if (rows[i] != expected[i]) {
+                return TestError() << rows[i] << " vs. " << expected[i];
+            }
+        }
+        return TestOK();
+    }
+
+protected:
+    std::function<AssertionResult()> TestOK = [] { return ::testing::AssertionSuccess(); };
+    std::function<AssertionResult()> TestError = [] { return ::testing::AssertionFailure(); };
+};
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_TEST_TESTBASE_H_
diff --git a/src/executor/test/TestEnv.cpp b/src/executor/test/TestEnv.cpp
new file mode 100644
index 00000000..647503ae
--- /dev/null
+++ b/src/executor/test/TestEnv.cpp
@@ -0,0 +1,69 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include "graph/test/TestEnv.h"
+
+namespace nebula {
+namespace graph {
+
+
+TestEnv *gEnv = nullptr;
+
+TestEnv::TestEnv() {
+}
+
+
+TestEnv::~TestEnv() {
+}
+
+
+void TestEnv::SetUp() {
+    auto interface = std::make_shared<GraphService>();
+    using ThriftServer = apache::thrift::ThriftServer;
+    server_ = std::make_unique<ThriftServer>();
+    server_->setInterface(std::move(interface));
+    server_->setPort(0);    // Let the system choose an available port for us
+
+    auto serve = [this] {
+        server_->serve();
+    };
+
+    thread_ = std::make_unique<thread::NamedThread>("", serve);
+    // busy waiting for `thread_' to enter the loop
+    while (!server_->getServeEventBase() || !server_->getServeEventBase()->isRunning()) {
+        ;
+    }
+}
+
+
+void TestEnv::TearDown() {
+    if (server_ != nullptr) {
+        server_->stop();
+    }
+    if (thread_ != nullptr) {
+        thread_->join();
+    }
+    server_ = nullptr;
+    thread_ = nullptr;
+}
+
+
+uint16_t TestEnv::serverPort() const {
+    return server_->getAddress().getPort();
+}
+
+
+std::unique_ptr<GraphClient> TestEnv::getClient() const {
+    auto client = std::make_unique<GraphClient>("127.0.0.1", serverPort());
+    if (cpp2::ErrorCode::SUCCEEDED != client->connect("user", "password")) {
+        return nullptr;
+    }
+    return client;
+}
+
+}   // namespace graph
+}   // namespace nebula
diff --git a/src/executor/test/TestEnv.h b/src/executor/test/TestEnv.h
new file mode 100644
index 00000000..52727aa4
--- /dev/null
+++ b/src/executor/test/TestEnv.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#ifndef GRAPH_TEST_TESTENV_H_
+#define GRAPH_TEST_TESTENV_H_
+
+#include "base/Base.h"
+#include <gtest/gtest.h>
+#include "thread/NamedThread.h"
+#include <thrift/lib/cpp2/server/ThriftServer.h>
+#include "graph/GraphService.h"
+#include "client/cpp/GraphClient.h"
+
+namespace apache {
+namespace thrift {
+class ThriftServer;
+}
+}
+
+namespace nebula {
+namespace graph {
+
+class GraphClient;
+class TestEnv : public ::testing::Environment {
+public:
+    TestEnv();
+    virtual ~TestEnv();
+
+    void SetUp() override;
+
+    void TearDown() override;
+    // Obtain the system assigned listening port
+    uint16_t serverPort() const;
+
+    std::unique_ptr<GraphClient> getClient() const;
+
+private:
+    std::unique_ptr<apache::thrift::ThriftServer>   server_;
+    std::unique_ptr<thread::NamedThread>            thread_;
+};
+
+
+extern TestEnv *gEnv;
+
+}   // namespace graph
+}   // namespace nebula
+
+#endif  // GRAPH_TEST_TESTENV_H_
diff --git a/src/executor/test/TestMain.cpp b/src/executor/test/TestMain.cpp
new file mode 100644
index 00000000..082415bf
--- /dev/null
+++ b/src/executor/test/TestMain.cpp
@@ -0,0 +1,21 @@
+/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
+ *
+ * This source code is licensed under Apache 2.0 License
+ *  (found in the LICENSE.Apache file in the root directory)
+ */
+
+#include "base/Base.h"
+#include <gtest/gtest.h>
+#include "graph/test/TestEnv.h"
+
+using namespace nebula::graph;
+
+int main(int argc, char **argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    folly::init(&argc, &argv, true);
+
+    gEnv = new TestEnv();   // gtest will delete this env object for us
+    ::testing::AddGlobalTestEnvironment(gEnv);
+
+    return RUN_ALL_TESTS();
+}
diff --git a/src/parser/.gitignore b/src/parser/.gitignore
index 8ca6e678..11b3d6df 100644
--- a/src/parser/.gitignore
+++ b/src/parser/.gitignore
@@ -1,6 +1,6 @@
-VGraphParser.cpp
-VGraphParser.hpp
-VGraphScanner.cpp
+GraphParser.cpp
+GraphParser.hpp
+GraphScanner.cpp
 location.hh
 position.hh
 stack.hh
diff --git a/src/parser/CMakeLists.txt b/src/parser/CMakeLists.txt
index d1b72c97..ab231294 100644
--- a/src/parser/CMakeLists.txt
+++ b/src/parser/CMakeLists.txt
@@ -1,11 +1,13 @@
 include_directories(${CMAKE_CURRENT_SOURCE_DIR})
 include_directories(${CMAKE_CURRENT_BINARY_DIR})
 
-bison_target(Parser parser.yy ${CMAKE_CURRENT_BINARY_DIR}/VGraphParser.cpp COMPILE_FLAGS "-Werror")
-flex_target(Scanner scanner.lex ${CMAKE_CURRENT_BINARY_DIR}/VGraphScanner.cpp)
+bison_target(Parser parser.yy ${CMAKE_CURRENT_BINARY_DIR}/GraphParser.cpp COMPILE_FLAGS "-Werror")
+flex_target(Scanner scanner.lex ${CMAKE_CURRENT_BINARY_DIR}/GraphScanner.cpp)
 
 add_flex_bison_dependency(Scanner Parser)
 
+add_compile_options(-Wno-error=sign-compare)
+
 add_library(
         parser_obj
         OBJECT
diff --git a/src/parser/Clauses.cpp b/src/parser/Clauses.cpp
index b50e7467..7330d18b 100644
--- a/src/parser/Clauses.cpp
+++ b/src/parser/Clauses.cpp
@@ -7,7 +7,7 @@
 #include "base/Base.h"
 #include "parser/Clauses.h"
 
-namespace vesoft {
+namespace nebula {
 
 
 std::string StepClause::toString() const {
@@ -110,4 +110,4 @@ std::string YieldClause::toString() const {
     return buf;
 }
 
-}   // namespace vesoft
+}   // namespace nebula
diff --git a/src/parser/Clauses.h b/src/parser/Clauses.h
index 78322653..24f7562e 100644
--- a/src/parser/Clauses.h
+++ b/src/parser/Clauses.h
@@ -9,7 +9,7 @@
 #include "base/Base.h"
 #include "parser/Expressions.h"
 
-namespace vesoft {
+namespace nebula {
 
 class StepClause final {
 public:
diff --git a/src/parser/CompoundSentence.cpp b/src/parser/CompoundSentence.cpp
index cc161da3..b1ad2c42 100644
--- a/src/parser/CompoundSentence.cpp
+++ b/src/parser/CompoundSentence.cpp
@@ -7,7 +7,7 @@
 #include "base/Base.h"
 #include "parser/CompoundSentence.h"
 
-namespace vesoft {
+namespace nebula {
 
 std::string CompoundSentence::toString() const {
     std::string buf;
@@ -21,4 +21,4 @@ std::string CompoundSentence::toString() const {
     return buf;
 }
 
-}   // namespace vesoft
+}   // namespace nebula
diff --git a/src/parser/CompoundSentence.h b/src/parser/CompoundSentence.h
index 8b8e82da..01f277ee 100644
--- a/src/parser/CompoundSentence.h
+++ b/src/parser/CompoundSentence.h
@@ -11,9 +11,9 @@
 #include "parser/TraverseSentences.h"
 #include "parser/MutateSentences.h"
 
-namespace vesoft {
+namespace nebula {
 
-namespace vgraph {
+namespace graph {
 class CompoundExecutor;
 }
 
@@ -30,11 +30,11 @@ public:
     std::string toString() const;
 
 private:
-    friend class vesoft::vgraph::CompoundExecutor;
+    friend class nebula::graph::CompoundExecutor;
     std::vector<std::unique_ptr<Sentence>>        sentences_;
 };
 
 
-}   // namespace vesoft
+}   // namespace nebula
 
 #endif  // PARSER_COMPOUNDSENTENCE_H_
diff --git a/src/parser/Expressions.cpp b/src/parser/Expressions.cpp
index 3dec79a3..fe48344c 100644
--- a/src/parser/Expressions.cpp
+++ b/src/parser/Expressions.cpp
@@ -7,7 +7,7 @@
 #include "base/Base.h"
 #include "parser/Expressions.h"
 
-namespace vesoft {
+namespace nebula {
 
 void ExpressionContext::print() const {
     for (auto &entry : aliasInfo_) {
@@ -899,4 +899,4 @@ Status LogicalExpression::prepare(ExpressionContext *context) {
     return Status::OK();
 }
 
-}   // namespace vesoft
+}   // namespace nebula
diff --git a/src/parser/Expressions.h b/src/parser/Expressions.h
index 5bbefdf3..a52457e6 100644
--- a/src/parser/Expressions.h
+++ b/src/parser/Expressions.h
@@ -10,7 +10,7 @@
 #include "base/Status.h"
 #include <boost/variant.hpp>
 
-namespace vesoft {
+namespace nebula {
 
 enum ColumnType {
     INT8, INT16, INT32, INT64,
@@ -767,6 +767,6 @@ private:
     std::unique_ptr<Expression>                 right_;
 };
 
-}   // namespace vesoft
+}   // namespace nebula
 
 #endif  // PARSER_EXPRESSIONS_H_
diff --git a/src/parser/GQLParser.cpp b/src/parser/GQLParser.cpp
index f1f17641..bb291d2b 100644
--- a/src/parser/GQLParser.cpp
+++ b/src/parser/GQLParser.cpp
@@ -7,6 +7,6 @@
 #include "base/Base.h"
 #include "GQLParser.h"
 
-namespace vesoft {
-}   // namespace vesoft
+namespace nebula {
+}   // namespace nebula
 
diff --git a/src/parser/GQLParser.h b/src/parser/GQLParser.h
index 9be210f1..a75472d0 100644
--- a/src/parser/GQLParser.h
+++ b/src/parser/GQLParser.h
@@ -8,10 +8,10 @@
 
 #include "base/Base.h"
 #include "base/StatusOr.h"
-#include "VGraphParser.hpp"
-#include "VGraphScanner.h"
+#include "GraphParser.hpp"
+#include "GraphScanner.h"
 
-namespace vesoft {
+namespace nebula {
 
 class GQLParser {
 public:
@@ -37,12 +37,12 @@ public:
     }
 
 private:
-    vesoft::VGraphScanner           scanner_;
-    vesoft::VGraphParser            parser_;
+    nebula::GraphScanner            scanner_;
+    nebula::GraphParser             parser_;
     std::string                     error_;
     CompoundSentence               *compound_ = nullptr;
 };
 
-}   // namespace vesoft
+}   // namespace nebula
 
 #endif  // PARSER_GQLPARSER_H_
diff --git a/src/parser/VGraphScanner.h b/src/parser/GraphScanner.h
similarity index 53%
rename from src/parser/VGraphScanner.h
rename to src/parser/GraphScanner.h
index bbd7e510..1b3774be 100644
--- a/src/parser/VGraphScanner.h
+++ b/src/parser/GraphScanner.h
@@ -3,8 +3,8 @@
  * This source code is licensed under Apache 2.0 License
  *  (found in the LICENSE.Apache file in the root directory)
  */
-#ifndef PARSER_VGRAPHSCANNER_H_
-#define PARSER_VGRAPHSCANNER_H_
+#ifndef PARSER_GRAPHSCANNER_H_
+#define PARSER_GRAPHSCANNER_H_
 
 #include "base/Base.h"
 
@@ -15,16 +15,16 @@
 
 // Override the interface for yylex since we namespaced it
 #undef YY_DECL
-#define YY_DECL int vesoft::VGraphScanner::yylex()
+#define YY_DECL int nebula::GraphScanner::yylex()
 
-#include "VGraphParser.hpp"
+#include "GraphParser.hpp"
 
-namespace vesoft {
+namespace nebula {
 
-class VGraphScanner : public yyFlexLexer {
+class GraphScanner : public yyFlexLexer {
 public:
-    int yylex(vesoft::VGraphParser::semantic_type * lval,
-              vesoft::VGraphParser::location_type *loc) {
+    int yylex(nebula::GraphParser::semantic_type * lval,
+              nebula::GraphParser::location_type *loc) {
         yylval = lval;
         yylloc = loc;
         return yylex();
@@ -35,10 +35,10 @@ private:
     friend class Scanner_Basic_Test;
     int yylex();
 
-    vesoft::VGraphParser::semantic_type * yylval{nullptr};
-    vesoft::VGraphParser::location_type * yylloc{nullptr};
+    nebula::GraphParser::semantic_type * yylval{nullptr};
+    nebula::GraphParser::location_type * yylloc{nullptr};
 };
 
-}   // namespace vesoft
+}   // namespace nebula
 
-#endif  // PARSER_VGRAPHSCANNER_H_
+#endif  // PARSER_GRAPHSCANNER_H_
diff --git a/src/parser/MaintainSentences.cpp b/src/parser/MaintainSentences.cpp
index 8f287410..ad26a639 100644
--- a/src/parser/MaintainSentences.cpp
+++ b/src/parser/MaintainSentences.cpp
@@ -7,7 +7,7 @@
 #include "base/Base.h"
 #include "parser/MaintainSentences.h"
 
-namespace vesoft {
+namespace nebula {
 
 std::string DefineTagSentence::toString() const {
     std::string buf;
@@ -110,4 +110,4 @@ std::string DescribeEdgeSentence::toString() const {
     return buf;
 }
 
-}   // namespace vesoft
+}   // namespace nebula
diff --git a/src/parser/MaintainSentences.h b/src/parser/MaintainSentences.h
index eae4aaa5..cf4c5e29 100644
--- a/src/parser/MaintainSentences.h
+++ b/src/parser/MaintainSentences.h
@@ -10,7 +10,7 @@
 #include "parser/Clauses.h"
 #include "parser/Sentence.h"
 
-namespace vesoft {
+namespace nebula {
 
 class ColumnSpecification final {
 public:
@@ -216,6 +216,6 @@ private:
     std::unique_ptr<std::string>                name_;
 };
 
-}   // namespace vesoft
+}   // namespace nebula
 
 #endif  // PARSER_MAINTAINSENTENCES_H_
diff --git a/src/parser/MutateSentences.cpp b/src/parser/MutateSentences.cpp
index 8914310a..1bd3a55c 100644
--- a/src/parser/MutateSentences.cpp
+++ b/src/parser/MutateSentences.cpp
@@ -7,7 +7,7 @@
 #include "base/Base.h"
 #include "parser/MutateSentences.h"
 
-namespace vesoft {
+namespace nebula {
 
 std::string PropertyList::toString() const {
     std::string buf;
@@ -139,4 +139,4 @@ std::string UpdateEdgeSentence::toString() const {
     return buf;
 }
 
-}   // namespace vesoft
+}   // namespace nebula
diff --git a/src/parser/MutateSentences.h b/src/parser/MutateSentences.h
index 95c5dc70..c92dfa14 100644
--- a/src/parser/MutateSentences.h
+++ b/src/parser/MutateSentences.h
@@ -10,7 +10,7 @@
 #include "parser/Clauses.h"
 #include "parser/Sentence.h"
 
-namespace vesoft {
+namespace nebula {
 
 class PropertyList final {
 public:
@@ -267,6 +267,6 @@ private:
     std::unique_ptr<YieldClause>                yieldClause_;
 };
 
-}   // namespace vesoft
+}   // namespace nebula
 
 #endif  // PARSER_MUTATESENTENCES_H_
diff --git a/src/parser/README.md b/src/parser/README.md
new file mode 100644
index 00000000..07dd0c5c
--- /dev/null
+++ b/src/parser/README.md
@@ -0,0 +1 @@
+# Overview
diff --git a/src/parser/Sentence.h b/src/parser/Sentence.h
index 06a838d5..50a38ab2 100644
--- a/src/parser/Sentence.h
+++ b/src/parser/Sentence.h
@@ -9,7 +9,7 @@
 #include "base/Base.h"
 #include "parser/Expressions.h"
 
-namespace vesoft {
+namespace nebula {
 
 class Sentence {
 public:
@@ -46,6 +46,6 @@ inline std::ostream& operator<<(std::ostream &os, Sentence::Kind kind) {
     return os << static_cast<uint32_t>(kind);
 }
 
-}   // namespace vesoft
+}   // namespace nebula
 
 #endif  // PARSER_SENTENCE_H_
diff --git a/src/parser/TraverseSentences.cpp b/src/parser/TraverseSentences.cpp
index 0c6e7e44..671a29e8 100644
--- a/src/parser/TraverseSentences.cpp
+++ b/src/parser/TraverseSentences.cpp
@@ -7,7 +7,7 @@
 #include "base/Base.h"
 #include "parser/TraverseSentences.h"
 
-namespace vesoft {
+namespace nebula {
 
 std::string GoSentence::toString() const {
     std::string buf;
@@ -84,4 +84,4 @@ std::string AssignmentSentence::toString() const {
     return buf;
 }
 
-}   // namespace vesoft
+}   // namespace nebula
diff --git a/src/parser/TraverseSentences.h b/src/parser/TraverseSentences.h
index c86f4aec..772fb353 100644
--- a/src/parser/TraverseSentences.h
+++ b/src/parser/TraverseSentences.h
@@ -10,7 +10,7 @@
 #include "parser/Sentence.h"
 #include "parser/Clauses.h"
 
-namespace vesoft {
+namespace nebula {
 
 class GoSentence final : public Sentence {
 public:
@@ -159,6 +159,6 @@ private:
 };
 
 
-}   // namespace vesoft
+}   // namespace nebula
 
 #endif  // PARSER_TRAVERSESENTENCES_H_
diff --git a/src/parser/parser.yy b/src/parser/parser.yy
index ecad4072..ef61efb1 100644
--- a/src/parser/parser.yy
+++ b/src/parser/parser.yy
@@ -2,12 +2,12 @@
 %skeleton "lalr1.cc"
 %no-lines
 %locations
-%define api.namespace { vesoft }
-%define parser_class_name { VGraphParser }
-%lex-param { vesoft::VGraphScanner& scanner }
-%parse-param { vesoft::VGraphScanner& scanner }
+%define api.namespace { nebula }
+%define parser_class_name { GraphParser }
+%lex-param { nebula::GraphScanner& scanner }
+%parse-param { nebula::GraphScanner& scanner }
 %parse-param { std::string &errmsg }
-%parse-param { vesoft::CompoundSentence** compound }
+%parse-param { nebula::CompoundSentence** compound }
 
 %code requires {
 #include <iostream>
@@ -15,18 +15,18 @@
 #include <string>
 #include "parser/CompoundSentence.h"
 
-namespace vesoft {
+namespace nebula {
 
-class VGraphScanner;
+class GraphScanner;
 
 }
 
 }
 
 %code {
-    static int yylex(vesoft::VGraphParser::semantic_type* yylval,
-            vesoft::VGraphParser::location_type *yylloc,
-            vesoft::VGraphScanner& scanner);
+    static int yylex(nebula::GraphParser::semantic_type* yylval,
+            nebula::GraphParser::location_type *yylloc,
+            nebula::GraphScanner& scanner);
 }
 
 %union {
@@ -34,26 +34,26 @@ class VGraphScanner;
     uint64_t                                intval;
     double                                  doubleval;
     std::string                            *strval;
-    vesoft::Expression                     *expr;
-    vesoft::Sentence                       *sentence;
-    vesoft::CompoundSentence               *compound;
-    vesoft::ColumnSpecification            *colspec;
-    vesoft::ColumnSpecificationList        *colspeclist;
-    vesoft::ColumnType                      type;
-    vesoft::StepClause                     *step_clause;
-    vesoft::FromClause                     *from_clause;
-    vesoft::SourceNodeList                 *src_node_list;
-    vesoft::OverClause                     *over_clause;
-    vesoft::EdgeList                       *edge_list;
-    vesoft::EdgeItem                       *edge_item;
-    vesoft::WhereClause                    *where_clause;
-    vesoft::YieldClause                    *yield_clause;
-    vesoft::YieldColumns                   *yield_columns;
-    vesoft::YieldColumn                    *yield_column;
-    vesoft::PropertyList                   *prop_list;
-    vesoft::ValueList                      *value_list;
-    vesoft::UpdateList                     *update_list;
-    vesoft::UpdateItem                     *update_item;
+    nebula::Expression                     *expr;
+    nebula::Sentence                       *sentence;
+    nebula::CompoundSentence               *compound;
+    nebula::ColumnSpecification            *colspec;
+    nebula::ColumnSpecificationList        *colspeclist;
+    nebula::ColumnType                      type;
+    nebula::StepClause                     *step_clause;
+    nebula::FromClause                     *from_clause;
+    nebula::SourceNodeList                 *src_node_list;
+    nebula::OverClause                     *over_clause;
+    nebula::EdgeList                       *edge_list;
+    nebula::EdgeItem                       *edge_item;
+    nebula::WhereClause                    *where_clause;
+    nebula::YieldClause                    *yield_clause;
+    nebula::YieldColumns                   *yield_columns;
+    nebula::YieldColumn                    *yield_column;
+    nebula::PropertyList                   *prop_list;
+    nebula::ValueList                      *value_list;
+    nebula::UpdateList                     *update_list;
+    nebula::UpdateItem                     *update_item;
 }
 /* keywords */
 %token KW_GO KW_AS KW_TO KW_OR KW_USE KW_SET KW_FROM KW_WHERE KW_ALTER
@@ -770,17 +770,17 @@ compound
 
 %%
 
-void vesoft::VGraphParser::error(const vesoft::VGraphParser::location_type& loc,
-                                     const std::string &msg) {
+void nebula::GraphParser::error(const nebula::GraphParser::location_type& loc,
+                                const std::string &msg) {
     std::ostringstream os;
     os << msg << " at " << loc;
     errmsg = os.str();
 }
 
 
-#include "VGraphScanner.h"
-static int yylex(vesoft::VGraphParser::semantic_type* yylval,
-        vesoft::VGraphParser::location_type *yylloc,
-        vesoft::VGraphScanner& scanner) {
+#include "GraphScanner.h"
+static int yylex(nebula::GraphParser::semantic_type* yylval,
+                 nebula::GraphParser::location_type *yylloc,
+                 nebula::GraphScanner& scanner) {
     return scanner.yylex(yylval, yylloc);
 }
diff --git a/src/parser/scanner.lex b/src/parser/scanner.lex
index 97c21826..d7c00001 100644
--- a/src/parser/scanner.lex
+++ b/src/parser/scanner.lex
@@ -1,17 +1,17 @@
 %option c++
-%option yyclass="VGraphScanner"
+%option yyclass="GraphScanner"
 %option nodefault noyywrap
 %option never-interactive
 %option yylineno
 
 %{
 #include "parser/GQLParser.h"
-#include "parser/VGraphScanner.h"
-#include "VGraphParser.hpp"
+#include "parser/GraphScanner.h"
+#include "GraphParser.hpp"
 
 #define YY_USER_ACTION  yylloc->columns(yyleng);
 
-using TokenType = vesoft::VGraphParser::token;
+using TokenType = nebula::GraphParser::token;
 
 static constexpr size_t MAX_STRING = 4096;
 
diff --git a/src/parser/test/ParserTest.cpp b/src/parser/test/ParserTest.cpp
index 548a8b20..ccb77b4a 100644
--- a/src/parser/test/ParserTest.cpp
+++ b/src/parser/test/ParserTest.cpp
@@ -10,7 +10,7 @@
 
 // TODO(dutor) Inspect the internal structures to check on the syntax and semantics
 
-namespace vesoft {
+namespace nebula {
 
 TEST(Parser, Go) {
     {
@@ -272,4 +272,4 @@ TEST(Parser, UpdateEdge) {
     }
 }
 
-}   // namespace vesoft
+}   // namespace nebula
diff --git a/src/parser/test/ScannerTest.cpp b/src/parser/test/ScannerTest.cpp
index 3b4f2b99..9ff9fa0b 100644
--- a/src/parser/test/ScannerTest.cpp
+++ b/src/parser/test/ScannerTest.cpp
@@ -9,15 +9,15 @@
 #include <sstream>
 #include <vector>
 #include <utility>
-#include "parser/VGraphParser.hpp"
-#include "parser/VGraphScanner.h"
+#include "parser/GraphParser.hpp"
+#include "parser/GraphScanner.h"
 
 using namespace ::testing;
 // TODO(dutor) Check on the sematic value of tokens
 
-namespace vesoft {
+namespace nebula {
 
-using semantic_type = vesoft::VGraphParser::semantic_type;
+using semantic_type = nebula::GraphParser::semantic_type;
 static auto checkSemanticValue(const char *expected, semantic_type *sv) {
     auto &actual = *sv->strval;
     if (expected != actual) {
@@ -67,11 +67,11 @@ checkSemanticValue(T expected, semantic_type *sv) {
 
 
 TEST(Scanner, Basic) {
-    using TokenType = vesoft::VGraphParser::token_type;
+    using TokenType = nebula::GraphParser::token_type;
     using Validator = std::function<::testing::AssertionResult()>;
-    vesoft::VGraphParser::semantic_type yylval;
-    vesoft::VGraphParser::location_type yyloc;
-    VGraphScanner scanner;
+    nebula::GraphParser::semantic_type yylval;
+    nebula::GraphParser::location_type yyloc;
+    GraphScanner scanner;
     std::string stream;
 
 #define CHECK_SEMANTIC_TYPE(STR, TYPE)                                      \
@@ -239,4 +239,4 @@ TEST(Scanner, Basic) {
     }
 }
 
-}   // namespace vesoft
+}   // namespace nebula
-- 
GitLab