You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ha...@apache.org on 2021/03/01 10:03:23 UTC

[iotdb] branch master updated: [IOTDB-1177] Trigger module: ANTLR, logical operators, physical plans and authorization (#2738)

This is an automated email from the ASF dual-hosted git repository.

haonan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 9c4dbd6  [IOTDB-1177] Trigger module: ANTLR, logical operators, physical plans and authorization  (#2738)
9c4dbd6 is described below

commit 9c4dbd6ed01ac60e5120b2301a0fe27537177015
Author: Steve Yurong Su <st...@outlook.com>
AuthorDate: Mon Mar 1 18:02:59 2021 +0800

    [IOTDB-1177] Trigger module: ANTLR, logical operators, physical plans and authorization  (#2738)
---
 .../antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4   |  42 +++++++++
 docs/UserGuide/Operation Manual/Administration.md  |   4 +
 docs/UserGuide/Operation Manual/Triggers.md        | 100 +++++++++++++++++++++
 .../UserGuide/Operation Manual/Administration.md   |   4 +
 docs/zh/UserGuide/Operation Manual/Triggers.md     | 100 +++++++++++++++++++++
 .../org/apache/iotdb/db/auth/AuthorityChecker.java |   8 ++
 .../apache/iotdb/db/auth/entity/PrivilegeType.java |   4 +
 .../org/apache/iotdb/db/conf/IoTDBConstant.java    |   7 ++
 .../iotdb/db/engine/trigger/api/TriggerEvent.java  |  35 ++++++++
 .../main/java/org/apache/iotdb/db/qp/Planner.java  |   4 +
 .../apache/iotdb/db/qp/constant/SQLConstant.java   |  12 +++
 .../apache/iotdb/db/qp/executor/PlanExecutor.java  |  55 ++++++++++++
 .../org/apache/iotdb/db/qp/logical/Operator.java   |   8 +-
 .../db/qp/logical/sys/CreateTriggerOperator.java   |  82 +++++++++++++++++
 .../db/qp/logical/sys/DropTriggerOperator.java     |  40 +++++++++
 .../db/qp/logical/sys/ShowTriggersOperator.java    |  39 ++++++++
 .../db/qp/logical/sys/StartTriggerOperator.java    |  40 +++++++++
 .../db/qp/logical/sys/StopTriggerOperator.java     |  40 +++++++++
 .../db/qp/physical/sys/CreateTriggerPlan.java      |  77 ++++++++++++++++
 .../iotdb/db/qp/physical/sys/DropTriggerPlan.java  |  46 ++++++++++
 .../apache/iotdb/db/qp/physical/sys/ShowPlan.java  |   3 +-
 .../iotdb/db/qp/physical/sys/ShowTriggersPlan.java |  35 ++++++++
 .../iotdb/db/qp/physical/sys/StartTriggerPlan.java |  46 ++++++++++
 .../iotdb/db/qp/physical/sys/StopTriggerPlan.java  |  46 ++++++++++
 .../apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java    |  66 ++++++++++++++
 .../iotdb/db/qp/strategy/PhysicalGenerator.java    |  26 ++++++
 .../iotdb/db/qp/physical/PhysicalPlanTest.java     |  75 ++++++++++++++++
 site/src/main/.vuepress/config.js                  |  34 ++++---
 28 files changed, 1061 insertions(+), 17 deletions(-)

diff --git a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4 b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4
index 0d065b4..37d9056 100644
--- a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4
+++ b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4
@@ -97,6 +97,12 @@ statement
     | CREATE TEMPORARY? FUNCTION udfName=ID AS className=stringLiteral #createFunction
     | DROP FUNCTION udfName=ID #dropFunction
     | SHOW TEMPORARY? FUNCTIONS #showFunctions
+    | CREATE TRIGGER triggerName=ID triggerEventClause ON fullPath
+      AS className=stringLiteral triggerAttributeClause? #createTrigger
+    | DROP TRIGGER triggerName=ID #dropTrigger
+    | START TRIGGER triggerName=ID #startTrigger
+    | STOP TRIGGER triggerName=ID #stopTrigger
+    | SHOW TRIGGERS (ON fullPath)? #showTriggers
     | SELECT topClause? selectElements
     fromClause
     whereClause?
@@ -688,6 +694,18 @@ autoCreateSchema
     | booleanClause INT
     ;
 
+triggerEventClause
+    : (BEFORE | AFTER) INSERT
+    ;
+
+triggerAttributeClause
+    : WITH LR_BRACKET triggerAttribute (COMMA triggerAttribute)* RR_BRACKET
+    ;
+
+triggerAttribute
+    : key=stringLiteral OPERATOR_EQ value=stringLiteral
+    ;
+
 //============================
 // Start of the keywords list
 //============================
@@ -1217,6 +1235,30 @@ AS
     : A S
     ;
 
+TRIGGER
+    : T R I G G E R
+    ;
+
+TRIGGERS
+    : T R I G G E R S
+    ;
+
+BEFORE
+    : B E F O R E
+    ;
+
+AFTER
+    : A F T E R
+    ;
+
+START
+    : S T A R T
+    ;
+
+STOP
+    : S T O P
+    ;
+
 DESC
     : D E S C
     ;
diff --git a/docs/UserGuide/Operation Manual/Administration.md b/docs/UserGuide/Operation Manual/Administration.md
index 266d757..97660ca 100644
--- a/docs/UserGuide/Operation Manual/Administration.md	
+++ b/docs/UserGuide/Operation Manual/Administration.md	
@@ -143,6 +143,10 @@ At the same time, changes to roles are immediately reflected on all users who ow
 |REVOKE\_ROLE\_PRIVILEGE|revoke role privileges; path independent|
 |CREATE_FUNCTION|register UDFs; path independent|
 |DROP_FUNCTION|deregister UDFs; path independent|
+|CREATE_TRIGGER|create triggers; path independent|
+|DROP_TRIGGER|drop triggers; path independent|
+|START_TRIGGER|start triggers; path independent|
+|STOP_TRIGGER|stop triggers; path independent|
 </center>
 
 ### Username Restrictions
diff --git a/docs/UserGuide/Operation Manual/Triggers.md b/docs/UserGuide/Operation Manual/Triggers.md
new file mode 100644
index 0000000..d8b0d1b
--- /dev/null
+++ b/docs/UserGuide/Operation Manual/Triggers.md	
@@ -0,0 +1,100 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+    
+        http://www.apache.org/licenses/LICENSE-2.0
+    
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+
+
+# Triggers
+
+
+
+## Triggers Management
+
+You can register, deregister, start or stop a trigger instance through SQL statements, and you can also query all registered triggers through SQL statements.
+
+Triggers have two states: `STARTED` and `STOPPED`. You can start or stop a trigger by executing `START TRIGGER` or `STOP TRIGGER`. Note that the triggers registered by the `CREATE TRIGGER` statement are `STARTED` by default.
+
+
+
+### Create Triggers
+
+The following shows the SQL syntax of how to register a trigger.
+
+```sql
+CREATE TRIGGER <TRIGGER-NAME>
+(BEFORE | AFTER) INSERT
+ON <FULL-PATH>
+AS <CLASSNAME>
+```
+
+You can also set any number of key-value pair attributes for the trigger through the `WITH` clause:
+
+```sql
+CREATE TRIGGER <TRIGGER-NAME>
+(BEFORE | AFTER) INSERT
+ON <FULL-PATH>
+AS <CLASSNAME>
+WITH (
+  <KEY-1>=<VALUE-1>, 
+  <KEY-2>=<VALUE-2>, 
+  ...
+)
+```
+
+Note that `CLASSNAME`, `KEY` and `VALUE` in key-value pair attributes need to be quoted in single or double quotes.
+
+
+
+### Drop Triggers
+
+The following shows the SQL syntax of how to deregister a trigger.
+
+```sql
+DROP TRIGGER <TRIGGER-NAME>
+```
+
+
+
+### Start Triggers
+
+The following shows the SQL syntax of how to start a trigger.
+
+```sql
+START TRIGGER <TRIGGER-NAME>
+```
+
+
+
+### Stop Triggers
+
+The following shows the SQL syntax of how to stop a trigger.
+
+```sql
+STOP TRIGGER <TRIGGER-NAME>
+```
+
+
+
+### Show All Registered Triggers
+
+``` sql
+SHOW TRIGGERS
+```
+
diff --git a/docs/zh/UserGuide/Operation Manual/Administration.md b/docs/zh/UserGuide/Operation Manual/Administration.md
index 10747a5..6585167 100644
--- a/docs/zh/UserGuide/Operation Manual/Administration.md	
+++ b/docs/zh/UserGuide/Operation Manual/Administration.md	
@@ -120,6 +120,10 @@ INSERT INTO root.ln.wf01.wt01(timestamp, status) values(1509465600000, true)
 |REVOKE\_ROLE\_PRIVILEGE|撤销角色权限。路径无关|
 |CREATE_FUNCTION|注册UDF。路径无关|
 |DROP_FUNCTION|卸载UDF。路径无关|
+|CREATE_TRIGGER|创建触发器。路径无关|
+|DROP_TRIGGER|卸载触发器。路径无关|
+|START_TRIGGER|启动触发器。路径无关|
+|STOP_TRIGGER|停止触发器。路径无关|
 </center>
 
 ### 用户名限制
diff --git a/docs/zh/UserGuide/Operation Manual/Triggers.md b/docs/zh/UserGuide/Operation Manual/Triggers.md
new file mode 100644
index 0000000..9890ecf
--- /dev/null
+++ b/docs/zh/UserGuide/Operation Manual/Triggers.md	
@@ -0,0 +1,100 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+    
+        http://www.apache.org/licenses/LICENSE-2.0
+    
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+
+
+# 触发器
+
+
+
+## SQL管理语句
+
+您可以通过SQL语句注册、卸载、启动或停止一个触发器实例,您也可以通过SQL语句查询到所有已经注册的触发器。
+
+触发器有两种运行状态:`STARTED`和`STOPPED`,您可以通过执行`START TRIGGER`或者`STOP TRIGGER`启动或者停止一个触发器。注意,通过`CREATE TRIGGER`语句注册的触发器默认是`STARTED`的。
+
+
+
+### 注册触发器
+
+注册触发器的SQL语法如下:
+
+```sql
+CREATE TRIGGER <TRIGGER-NAME>
+(BEFORE | AFTER) INSERT
+ON <FULL-PATH>
+AS <CLASSNAME>
+```
+
+同时,您还可以通过`WITH`子句传入任意数量的自定义属性值:
+
+```sql
+CREATE TRIGGER <TRIGGER-NAME>
+(BEFORE | AFTER) INSERT
+ON <FULL-PATH>
+AS <CLASSNAME>
+WITH (
+  <KEY-1>=<VALUE-1>, 
+  <KEY-2>=<VALUE-2>, 
+  ...
+)
+```
+
+注意,`CLASSNAME`以及属性值中的`KEY`和`VALUE`都需要被单引号或者双引号引用起来。
+
+
+
+### 卸载触发器
+
+卸载触发器的SQL语法如下:
+
+```sql
+DROP TRIGGER <TRIGGER-NAME>
+```
+
+
+
+### 启动触发器
+
+启动触发器的SQL语法如下:
+
+```sql
+START TRIGGER <TRIGGER-NAME>
+```
+
+
+
+### 停止触发器
+
+停止触发器的SQL语法如下:
+
+```sql
+STOP TRIGGER <TRIGGER-NAME>
+```
+
+
+
+### 查询所有注册的触发器
+
+``` sql
+SHOW TRIGGERS
+```
+
diff --git a/server/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java b/server/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
index 89a74e5..fc5c680 100644
--- a/server/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
+++ b/server/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
@@ -149,6 +149,14 @@ public class AuthorityChecker {
         return PrivilegeType.CREATE_FUNCTION.ordinal();
       case DROP_FUNCTION:
         return PrivilegeType.DROP_FUNCTION.ordinal();
+      case CREATE_TRIGGER:
+        return PrivilegeType.CREATE_TRIGGER.ordinal();
+      case DROP_TRIGGER:
+        return PrivilegeType.DROP_TRIGGER.ordinal();
+      case START_TRIGGER:
+        return PrivilegeType.START_TRIGGER.ordinal();
+      case STOP_TRIGGER:
+        return PrivilegeType.STOP_TRIGGER.ordinal();
       case AUTHOR:
       case METADATA:
       case BASIC_FUNC:
diff --git a/server/src/main/java/org/apache/iotdb/db/auth/entity/PrivilegeType.java b/server/src/main/java/org/apache/iotdb/db/auth/entity/PrivilegeType.java
index 740e3fd..efde036 100644
--- a/server/src/main/java/org/apache/iotdb/db/auth/entity/PrivilegeType.java
+++ b/server/src/main/java/org/apache/iotdb/db/auth/entity/PrivilegeType.java
@@ -41,6 +41,10 @@ public enum PrivilegeType {
   REVOKE_ROLE_PRIVILEGE,
   CREATE_FUNCTION,
   DROP_FUNCTION,
+  CREATE_TRIGGER,
+  DROP_TRIGGER,
+  START_TRIGGER,
+  STOP_TRIGGER,
   ALL;
 
   /**
diff --git a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConstant.java b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConstant.java
index cb1027b..692a700 100644
--- a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConstant.java
+++ b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConstant.java
@@ -101,6 +101,13 @@ public class IoTDBConstant {
   public static final String FUNCTION_TYPE_EXTERNAL_UDAF = "external UDAF";
   public static final String FUNCTION_TYPE_EXTERNAL_UDTF = "external UDTF";
 
+  public static final String COLUMN_TRIGGER_NAME = "trigger name";
+  public static final String COLUMN_TRIGGER_STATUS = "status";
+  public static final String COLUMN_TRIGGER_EVENT = "event";
+  public static final String COLUMN_TRIGGER_PATH = "path";
+  public static final String COLUMN_TRIGGER_CLASS = "class name";
+  public static final String COLUMN_TRIGGER_ATTRIBUTES = "attributes";
+
   public static final String PATH_WILDCARD = "*";
   public static final String TIME = "time";
 
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/trigger/api/TriggerEvent.java b/server/src/main/java/org/apache/iotdb/db/engine/trigger/api/TriggerEvent.java
new file mode 100644
index 0000000..6ab33e1
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/engine/trigger/api/TriggerEvent.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.engine.trigger.api;
+
+public enum TriggerEvent {
+  BEFORE_INSERT((byte) 0),
+  AFTER_INSERT((byte) 1);
+
+  private final byte id;
+
+  TriggerEvent(byte id) {
+    this.id = id;
+  }
+
+  public byte getId() {
+    return id;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/Planner.java b/server/src/main/java/org/apache/iotdb/db/qp/Planner.java
index 802984a..355b7ef 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/Planner.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/Planner.java
@@ -177,6 +177,10 @@ public class Planner {
       case KILL:
       case CREATE_FUNCTION:
       case DROP_FUNCTION:
+      case CREATE_TRIGGER:
+      case DROP_TRIGGER:
+      case START_TRIGGER:
+      case STOP_TRIGGER:
         return operator;
       case QUERY:
       case DELETE:
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/constant/SQLConstant.java b/server/src/main/java/org/apache/iotdb/db/qp/constant/SQLConstant.java
index c13f7fb..35dcdec 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/constant/SQLConstant.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/constant/SQLConstant.java
@@ -172,6 +172,12 @@ public class SQLConstant {
 
   public static final int TOK_CHILD_NODES = 99;
 
+  public static final int TOK_TRIGGER_CREATE = 100;
+  public static final int TOK_TRIGGER_DROP = 101;
+  public static final int TOK_TRIGGER_START = 102;
+  public static final int TOK_TRIGGER_STOP = 103;
+  public static final int TOK_SHOW_TRIGGERS = 104;
+
   public static final Map<Integer, String> tokenSymbol = new HashMap<>();
   public static final Map<Integer, String> tokenNames = new HashMap<>();
   public static final Map<Integer, Integer> reverseWords = new HashMap<>();
@@ -259,6 +265,12 @@ public class SQLConstant {
     tokenNames.put(TOK_CREATE_INDEX, "TOK_CREATE_INDEX");
     tokenNames.put(TOK_DROP_INDEX, "TOK_DROP_INDEX");
     tokenNames.put(TOK_QUERY_INDEX, "TOK_QUERY_INDEX");
+
+    tokenNames.put(TOK_TRIGGER_CREATE, "TOK_TRIGGER_CREATE");
+    tokenNames.put(TOK_TRIGGER_DROP, "TOK_TRIGGER_DROP");
+    tokenNames.put(TOK_TRIGGER_START, "TOK_TRIGGER_START");
+    tokenNames.put(TOK_TRIGGER_STOP, "TOK_TRIGGER_STOP");
+    tokenNames.put(TOK_SHOW_TRIGGERS, "TOK_SHOW_TRIGGERS");
   }
 
   static {
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java b/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
index b7a1abf..89f77cf 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
@@ -79,10 +79,12 @@ import org.apache.iotdb.db.qp.physical.sys.CountPlan;
 import org.apache.iotdb.db.qp.physical.sys.CreateFunctionPlan;
 import org.apache.iotdb.db.qp.physical.sys.CreateMultiTimeSeriesPlan;
 import org.apache.iotdb.db.qp.physical.sys.CreateTimeSeriesPlan;
+import org.apache.iotdb.db.qp.physical.sys.CreateTriggerPlan;
 import org.apache.iotdb.db.qp.physical.sys.DataAuthPlan;
 import org.apache.iotdb.db.qp.physical.sys.DeleteStorageGroupPlan;
 import org.apache.iotdb.db.qp.physical.sys.DeleteTimeSeriesPlan;
 import org.apache.iotdb.db.qp.physical.sys.DropFunctionPlan;
+import org.apache.iotdb.db.qp.physical.sys.DropTriggerPlan;
 import org.apache.iotdb.db.qp.physical.sys.FlushPlan;
 import org.apache.iotdb.db.qp.physical.sys.KillQueryPlan;
 import org.apache.iotdb.db.qp.physical.sys.LoadConfigurationPlan;
@@ -98,6 +100,9 @@ import org.apache.iotdb.db.qp.physical.sys.ShowPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowStorageGroupPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowTTLPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowTimeSeriesPlan;
+import org.apache.iotdb.db.qp.physical.sys.ShowTriggersPlan;
+import org.apache.iotdb.db.qp.physical.sys.StartTriggerPlan;
+import org.apache.iotdb.db.qp.physical.sys.StopTriggerPlan;
 import org.apache.iotdb.db.qp.physical.sys.TracingPlan;
 import org.apache.iotdb.db.query.context.QueryContext;
 import org.apache.iotdb.db.query.control.QueryTimeManager;
@@ -165,6 +170,12 @@ import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_PROGRESS;
 import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_ROLE;
 import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_STORAGE_GROUP;
 import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_TASK_NAME;
+import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_TRIGGER_ATTRIBUTES;
+import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_TRIGGER_CLASS;
+import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_TRIGGER_EVENT;
+import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_TRIGGER_NAME;
+import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_TRIGGER_PATH;
+import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_TRIGGER_STATUS;
 import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_TTL;
 import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_USER;
 import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_VALUE;
@@ -307,6 +318,14 @@ public class PlanExecutor implements IPlanExecutor {
         return operateCreateFunction((CreateFunctionPlan) plan);
       case DROP_FUNCTION:
         return operateDropFunction((DropFunctionPlan) plan);
+      case CREATE_TRIGGER:
+        return operateCreateTrigger((CreateTriggerPlan) plan);
+      case DROP_TRIGGER:
+        return operateDropTrigger((DropTriggerPlan) plan);
+      case START_TRIGGER:
+        return operateStartTrigger((StartTriggerPlan) plan);
+      case STOP_TRIGGER:
+        return operateStopTrigger((StopTriggerPlan) plan);
       case CREATE_INDEX:
         throw new QueryProcessException("Create index hasn't been supported yet");
       case DROP_INDEX:
@@ -335,6 +354,22 @@ public class PlanExecutor implements IPlanExecutor {
     return true;
   }
 
+  private boolean operateCreateTrigger(CreateTriggerPlan plan) {
+    return false;
+  }
+
+  private boolean operateDropTrigger(DropTriggerPlan plan) {
+    return false;
+  }
+
+  private boolean operateStartTrigger(StartTriggerPlan plan) {
+    return false;
+  }
+
+  private boolean operateStopTrigger(StopTriggerPlan plan) {
+    return false;
+  }
+
   private void operateMerge(MergePlan plan) throws StorageEngineException {
     if (plan.getOperatorType() == OperatorType.FULL_MERGE) {
       StorageEngine.getInstance().mergeAll(true);
@@ -505,6 +540,8 @@ public class PlanExecutor implements IPlanExecutor {
         return processShowQueryProcesslist();
       case FUNCTIONS:
         return processShowFunctions((ShowFunctionsPlan) showPlan);
+      case TRIGGERS:
+        return processShowTriggers((ShowTriggersPlan) showPlan);
       default:
         throw new QueryProcessException(String.format("Unrecognized show plan %s", showPlan));
     }
@@ -841,6 +878,24 @@ public class PlanExecutor implements IPlanExecutor {
     }
   }
 
+  private QueryDataSet processShowTriggers(ShowTriggersPlan showPlan) {
+    return new ListDataSet(
+        Arrays.asList(
+            new PartialPath(COLUMN_TRIGGER_NAME, false),
+            new PartialPath(COLUMN_TRIGGER_STATUS, false),
+            new PartialPath(COLUMN_TRIGGER_EVENT, false),
+            new PartialPath(COLUMN_TRIGGER_PATH, false),
+            new PartialPath(COLUMN_TRIGGER_CLASS, false),
+            new PartialPath(COLUMN_TRIGGER_ATTRIBUTES, false)),
+        Arrays.asList(
+            TSDataType.TEXT,
+            TSDataType.TEXT,
+            TSDataType.TEXT,
+            TSDataType.TEXT,
+            TSDataType.TEXT,
+            TSDataType.TEXT));
+  }
+
   private void addRowRecordForShowQuery(
       ListDataSet listDataSet, int timestamp, String item, String value) {
     RowRecord rowRecord = new RowRecord(timestamp);
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/Operator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/Operator.java
index d1e9971..c7ec520 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/logical/Operator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/Operator.java
@@ -30,7 +30,7 @@ public abstract class Operator {
 
   protected OperatorType operatorType = OperatorType.NULL;
 
-  public Operator(int tokenIntType) {
+  protected Operator(int tokenIntType) {
     this.tokenIntType = tokenIntType;
     this.tokenName = SQLConstant.tokenNames.get(tokenIntType);
   }
@@ -146,6 +146,10 @@ public abstract class Operator {
     STORAGE_GROUP_MNODE,
     BATCH_INSERT_ONE_DEVICE,
     MULTI_BATCH_INSERT,
-    BATCH_INSERT_ROWS
+    BATCH_INSERT_ROWS,
+    CREATE_TRIGGER,
+    DROP_TRIGGER,
+    START_TRIGGER,
+    STOP_TRIGGER
   }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/CreateTriggerOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/CreateTriggerOperator.java
new file mode 100644
index 0000000..a3459af
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/CreateTriggerOperator.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.qp.logical.sys;
+
+import org.apache.iotdb.db.engine.trigger.api.TriggerEvent;
+import org.apache.iotdb.db.metadata.PartialPath;
+import org.apache.iotdb.db.qp.logical.RootOperator;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class CreateTriggerOperator extends RootOperator {
+
+  private String triggerName;
+  private TriggerEvent event;
+  private PartialPath fullPath;
+  private String className;
+  private final Map<String, String> attributes;
+
+  public CreateTriggerOperator(int tokenIntType) {
+    super(tokenIntType);
+    operatorType = OperatorType.CREATE_TRIGGER;
+    attributes = new HashMap<>();
+  }
+
+  public void setTriggerName(String triggerName) {
+    this.triggerName = triggerName;
+  }
+
+  public void setEvent(TriggerEvent event) {
+    this.event = event;
+  }
+
+  public void setClassName(String className) {
+    this.className = className;
+  }
+
+  public void setFullPath(PartialPath fullPath) {
+    this.fullPath = fullPath;
+  }
+
+  public void addAttribute(String key, String value) {
+    attributes.put(key, value);
+  }
+
+  public String getTriggerName() {
+    return triggerName;
+  }
+
+  public TriggerEvent getEvent() {
+    return event;
+  }
+
+  public String getClassName() {
+    return className;
+  }
+
+  public PartialPath getFullPath() {
+    return fullPath;
+  }
+
+  public Map<String, String> getAttributes() {
+    return attributes;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/DropTriggerOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/DropTriggerOperator.java
new file mode 100644
index 0000000..ba52205
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/DropTriggerOperator.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.qp.logical.sys;
+
+import org.apache.iotdb.db.qp.logical.RootOperator;
+
+public class DropTriggerOperator extends RootOperator {
+
+  private String triggerName;
+
+  public DropTriggerOperator(int tokenIntType) {
+    super(tokenIntType);
+    operatorType = OperatorType.DROP_TRIGGER;
+  }
+
+  public void setTriggerName(String triggerName) {
+    this.triggerName = triggerName;
+  }
+
+  public String getTriggerName() {
+    return triggerName;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/ShowTriggersOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/ShowTriggersOperator.java
new file mode 100644
index 0000000..ef41513
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/ShowTriggersOperator.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.qp.logical.sys;
+
+import org.apache.iotdb.db.metadata.PartialPath;
+
+public class ShowTriggersOperator extends ShowOperator {
+
+  private PartialPath path;
+
+  public ShowTriggersOperator(int tokenIntType) {
+    super(tokenIntType);
+  }
+
+  public void setPath(PartialPath path) {
+    this.path = path;
+  }
+
+  public PartialPath getPath() {
+    return path;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/StartTriggerOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/StartTriggerOperator.java
new file mode 100644
index 0000000..8cc4ff7
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/StartTriggerOperator.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.qp.logical.sys;
+
+import org.apache.iotdb.db.qp.logical.RootOperator;
+
+public class StartTriggerOperator extends RootOperator {
+
+  private String triggerName;
+
+  public StartTriggerOperator(int tokenIntType) {
+    super(tokenIntType);
+    operatorType = OperatorType.START_TRIGGER;
+  }
+
+  public void setTriggerName(String triggerName) {
+    this.triggerName = triggerName;
+  }
+
+  public String getTriggerName() {
+    return triggerName;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/StopTriggerOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/StopTriggerOperator.java
new file mode 100644
index 0000000..f07ae8f
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/StopTriggerOperator.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.qp.logical.sys;
+
+import org.apache.iotdb.db.qp.logical.RootOperator;
+
+public class StopTriggerOperator extends RootOperator {
+
+  private String triggerName;
+
+  public StopTriggerOperator(int tokenIntType) {
+    super(tokenIntType);
+    operatorType = OperatorType.STOP_TRIGGER;
+  }
+
+  public void setTriggerName(String triggerName) {
+    this.triggerName = triggerName;
+  }
+
+  public String getTriggerName() {
+    return triggerName;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/CreateTriggerPlan.java b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/CreateTriggerPlan.java
new file mode 100644
index 0000000..6d01f55
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/CreateTriggerPlan.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.qp.physical.sys;
+
+import org.apache.iotdb.db.engine.trigger.api.TriggerEvent;
+import org.apache.iotdb.db.metadata.PartialPath;
+import org.apache.iotdb.db.qp.logical.Operator.OperatorType;
+import org.apache.iotdb.db.qp.physical.PhysicalPlan;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+public class CreateTriggerPlan extends PhysicalPlan {
+
+  private final String triggerName;
+  private final TriggerEvent event;
+  private final PartialPath fullPath;
+  private final String className;
+  private final Map<String, String> attributes;
+
+  public CreateTriggerPlan(
+      String triggerName,
+      TriggerEvent event,
+      PartialPath fullPath,
+      String className,
+      Map<String, String> attributes) {
+    super(false, OperatorType.CREATE_TRIGGER);
+    this.triggerName = triggerName;
+    this.event = event;
+    this.fullPath = fullPath;
+    this.className = className;
+    this.attributes = attributes;
+  }
+
+  public String getTriggerName() {
+    return triggerName;
+  }
+
+  public TriggerEvent getEvent() {
+    return event;
+  }
+
+  public PartialPath getFullPath() {
+    return fullPath;
+  }
+
+  public String getClassName() {
+    return className;
+  }
+
+  public Map<String, String> getAttributes() {
+    return attributes;
+  }
+
+  @Override
+  public List<PartialPath> getPaths() {
+    return Collections.emptyList();
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/DropTriggerPlan.java b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/DropTriggerPlan.java
new file mode 100644
index 0000000..76a0799
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/DropTriggerPlan.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.qp.physical.sys;
+
+import org.apache.iotdb.db.metadata.PartialPath;
+import org.apache.iotdb.db.qp.logical.Operator.OperatorType;
+import org.apache.iotdb.db.qp.physical.PhysicalPlan;
+
+import java.util.Collections;
+import java.util.List;
+
+public class DropTriggerPlan extends PhysicalPlan {
+
+  private final String triggerName;
+
+  public DropTriggerPlan(String triggerName) {
+    super(false, OperatorType.DROP_TRIGGER);
+    this.triggerName = triggerName;
+  }
+
+  public String getTriggerName() {
+    return triggerName;
+  }
+
+  @Override
+  public List<PartialPath> getPaths() {
+    return Collections.emptyList();
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowPlan.java b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowPlan.java
index 1a9e906..a77917a 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowPlan.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowPlan.java
@@ -116,6 +116,7 @@ public class ShowPlan extends PhysicalPlan {
     FUNCTIONS,
     COUNT_DEVICES,
     COUNT_STORAGE_GROUP,
-    QUERY_PROCESSLIST
+    QUERY_PROCESSLIST,
+    TRIGGERS
   }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowTriggersPlan.java b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowTriggersPlan.java
new file mode 100644
index 0000000..989e99d
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowTriggersPlan.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.qp.physical.sys;
+
+import org.apache.iotdb.db.metadata.PartialPath;
+
+public class ShowTriggersPlan extends ShowPlan {
+
+  public ShowTriggersPlan(PartialPath path) {
+    super(ShowContentType.TRIGGERS);
+    this.path = path;
+  }
+
+  @Override
+  public PartialPath getPath() {
+    return path;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/StartTriggerPlan.java b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/StartTriggerPlan.java
new file mode 100644
index 0000000..02af2dc
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/StartTriggerPlan.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.qp.physical.sys;
+
+import org.apache.iotdb.db.metadata.PartialPath;
+import org.apache.iotdb.db.qp.logical.Operator.OperatorType;
+import org.apache.iotdb.db.qp.physical.PhysicalPlan;
+
+import java.util.Collections;
+import java.util.List;
+
+public class StartTriggerPlan extends PhysicalPlan {
+
+  private final String triggerName;
+
+  public StartTriggerPlan(String triggerName) {
+    super(false, OperatorType.START_TRIGGER);
+    this.triggerName = triggerName;
+  }
+
+  public String getTriggerName() {
+    return triggerName;
+  }
+
+  @Override
+  public List<PartialPath> getPaths() {
+    return Collections.emptyList();
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/StopTriggerPlan.java b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/StopTriggerPlan.java
new file mode 100644
index 0000000..233ef87
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/StopTriggerPlan.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.qp.physical.sys;
+
+import org.apache.iotdb.db.metadata.PartialPath;
+import org.apache.iotdb.db.qp.logical.Operator.OperatorType;
+import org.apache.iotdb.db.qp.physical.PhysicalPlan;
+
+import java.util.Collections;
+import java.util.List;
+
+public class StopTriggerPlan extends PhysicalPlan {
+
+  private final String triggerName;
+
+  public StopTriggerPlan(String triggerName) {
+    super(false, OperatorType.STOP_TRIGGER);
+    this.triggerName = triggerName;
+  }
+
+  public String getTriggerName() {
+    return triggerName;
+  }
+
+  @Override
+  public List<PartialPath> getPaths() {
+    return Collections.emptyList();
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
index 9c622f8..1fd4522 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
@@ -19,6 +19,7 @@
 package org.apache.iotdb.db.qp.sql;
 
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.db.engine.trigger.api.TriggerEvent;
 import org.apache.iotdb.db.exception.index.UnsupportedIndexTypeException;
 import org.apache.iotdb.db.exception.runtime.SQLParserException;
 import org.apache.iotdb.db.index.common.IndexType;
@@ -44,12 +45,14 @@ import org.apache.iotdb.db.qp.logical.sys.CreateFunctionOperator;
 import org.apache.iotdb.db.qp.logical.sys.CreateIndexOperator;
 import org.apache.iotdb.db.qp.logical.sys.CreateSnapshotOperator;
 import org.apache.iotdb.db.qp.logical.sys.CreateTimeSeriesOperator;
+import org.apache.iotdb.db.qp.logical.sys.CreateTriggerOperator;
 import org.apache.iotdb.db.qp.logical.sys.DataAuthOperator;
 import org.apache.iotdb.db.qp.logical.sys.DeletePartitionOperator;
 import org.apache.iotdb.db.qp.logical.sys.DeleteStorageGroupOperator;
 import org.apache.iotdb.db.qp.logical.sys.DeleteTimeSeriesOperator;
 import org.apache.iotdb.db.qp.logical.sys.DropFunctionOperator;
 import org.apache.iotdb.db.qp.logical.sys.DropIndexOperator;
+import org.apache.iotdb.db.qp.logical.sys.DropTriggerOperator;
 import org.apache.iotdb.db.qp.logical.sys.FlushOperator;
 import org.apache.iotdb.db.qp.logical.sys.KillQueryOperator;
 import org.apache.iotdb.db.qp.logical.sys.LoadConfigurationOperator;
@@ -70,6 +73,9 @@ import org.apache.iotdb.db.qp.logical.sys.ShowOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowStorageGroupOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowTTLOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowTimeSeriesOperator;
+import org.apache.iotdb.db.qp.logical.sys.ShowTriggersOperator;
+import org.apache.iotdb.db.qp.logical.sys.StartTriggerOperator;
+import org.apache.iotdb.db.qp.logical.sys.StopTriggerOperator;
 import org.apache.iotdb.db.qp.logical.sys.TracingOperator;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.AggregationCallContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.AggregationElementContext;
@@ -96,6 +102,7 @@ import org.apache.iotdb.db.qp.sql.SqlBaseParser.CreateIndexContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.CreateRoleContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.CreateSnapshotContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.CreateTimeseriesContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.CreateTriggerContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.CreateUserContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.DateExpressionContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.DeletePartitionContext;
@@ -105,6 +112,7 @@ import org.apache.iotdb.db.qp.sql.SqlBaseParser.DeleteTimeseriesContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.DropFunctionContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.DropIndexContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.DropRoleContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.DropTriggerContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.DropUserContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.FillClauseContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.FillStatementContext;
@@ -180,6 +188,7 @@ import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowQueryProcesslistContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowStorageGroupContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowTTLStatementContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowTimeseriesContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowTriggersContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowVersionContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowWhereClauseContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.SingleStatementContext;
@@ -187,6 +196,8 @@ import org.apache.iotdb.db.qp.sql.SqlBaseParser.SlimitClauseContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.SlimitStatementContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.SoffsetClauseContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.SpecialLimitStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.StartTriggerContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.StopTriggerContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.StringLiteralContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.SuffixPathContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.TableCallContext;
@@ -195,6 +206,7 @@ import org.apache.iotdb.db.qp.sql.SqlBaseParser.TagClauseContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.TimeIntervalContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.TracingOffContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.TracingOnContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.TriggerAttributeContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.TypeClauseContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.UdfAttributeContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.UdfCallContext;
@@ -450,6 +462,60 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> {
   }
 
   @Override
+  public Operator visitCreateTrigger(CreateTriggerContext ctx) {
+    CreateTriggerOperator createTriggerOperator =
+        new CreateTriggerOperator(SQLConstant.TOK_TRIGGER_CREATE);
+    createTriggerOperator.setTriggerName(ctx.triggerName.getText());
+    createTriggerOperator.setEvent(
+        ctx.triggerEventClause().BEFORE() != null
+            ? TriggerEvent.BEFORE_INSERT
+            : TriggerEvent.AFTER_INSERT);
+    createTriggerOperator.setFullPath(parseFullPath(ctx.fullPath()));
+    createTriggerOperator.setClassName(removeStringQuote(ctx.className.getText()));
+    if (ctx.triggerAttributeClause() != null) {
+      for (TriggerAttributeContext triggerAttributeContext :
+          ctx.triggerAttributeClause().triggerAttribute()) {
+        createTriggerOperator.addAttribute(
+            removeStringQuote(triggerAttributeContext.key.getText()),
+            removeStringQuote(triggerAttributeContext.value.getText()));
+      }
+    }
+    return createTriggerOperator;
+  }
+
+  @Override
+  public Operator visitDropTrigger(DropTriggerContext ctx) {
+    DropTriggerOperator dropTriggerOperator = new DropTriggerOperator(SQLConstant.TOK_TRIGGER_DROP);
+    dropTriggerOperator.setTriggerName(ctx.triggerName.getText());
+    return dropTriggerOperator;
+  }
+
+  @Override
+  public Operator visitStartTrigger(StartTriggerContext ctx) {
+    StartTriggerOperator startTriggerOperator =
+        new StartTriggerOperator(SQLConstant.TOK_TRIGGER_START);
+    startTriggerOperator.setTriggerName(ctx.triggerName.getText());
+    return startTriggerOperator;
+  }
+
+  @Override
+  public Operator visitStopTrigger(StopTriggerContext ctx) {
+    StopTriggerOperator stopTriggerOperator = new StopTriggerOperator(SQLConstant.TOK_TRIGGER_STOP);
+    stopTriggerOperator.setTriggerName(ctx.triggerName.getText());
+    return stopTriggerOperator;
+  }
+
+  @Override
+  public Operator visitShowTriggers(ShowTriggersContext ctx) {
+    ShowTriggersOperator showTriggersOperator =
+        new ShowTriggersOperator(SQLConstant.TOK_SHOW_TRIGGERS);
+    if (ctx.fullPath() != null) {
+      showTriggersOperator.setPath(parseFullPath(ctx.fullPath()));
+    }
+    return showTriggersOperator;
+  }
+
+  @Override
   public Operator visitMerge(MergeContext ctx) {
     return new MergeOperator(SQLConstant.TOK_MERGE);
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
index f40c94a..4fddd2d 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
@@ -40,12 +40,14 @@ import org.apache.iotdb.db.qp.logical.sys.CountOperator;
 import org.apache.iotdb.db.qp.logical.sys.CreateFunctionOperator;
 import org.apache.iotdb.db.qp.logical.sys.CreateIndexOperator;
 import org.apache.iotdb.db.qp.logical.sys.CreateTimeSeriesOperator;
+import org.apache.iotdb.db.qp.logical.sys.CreateTriggerOperator;
 import org.apache.iotdb.db.qp.logical.sys.DataAuthOperator;
 import org.apache.iotdb.db.qp.logical.sys.DeletePartitionOperator;
 import org.apache.iotdb.db.qp.logical.sys.DeleteStorageGroupOperator;
 import org.apache.iotdb.db.qp.logical.sys.DeleteTimeSeriesOperator;
 import org.apache.iotdb.db.qp.logical.sys.DropFunctionOperator;
 import org.apache.iotdb.db.qp.logical.sys.DropIndexOperator;
+import org.apache.iotdb.db.qp.logical.sys.DropTriggerOperator;
 import org.apache.iotdb.db.qp.logical.sys.FlushOperator;
 import org.apache.iotdb.db.qp.logical.sys.KillQueryOperator;
 import org.apache.iotdb.db.qp.logical.sys.LoadConfigurationOperator;
@@ -63,6 +65,9 @@ import org.apache.iotdb.db.qp.logical.sys.ShowFunctionsOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowStorageGroupOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowTTLOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowTimeSeriesOperator;
+import org.apache.iotdb.db.qp.logical.sys.ShowTriggersOperator;
+import org.apache.iotdb.db.qp.logical.sys.StartTriggerOperator;
+import org.apache.iotdb.db.qp.logical.sys.StopTriggerOperator;
 import org.apache.iotdb.db.qp.logical.sys.TracingOperator;
 import org.apache.iotdb.db.qp.physical.PhysicalPlan;
 import org.apache.iotdb.db.qp.physical.crud.AggregationPlan;
@@ -87,11 +92,13 @@ import org.apache.iotdb.db.qp.physical.sys.CreateFunctionPlan;
 import org.apache.iotdb.db.qp.physical.sys.CreateIndexPlan;
 import org.apache.iotdb.db.qp.physical.sys.CreateSnapshotPlan;
 import org.apache.iotdb.db.qp.physical.sys.CreateTimeSeriesPlan;
+import org.apache.iotdb.db.qp.physical.sys.CreateTriggerPlan;
 import org.apache.iotdb.db.qp.physical.sys.DataAuthPlan;
 import org.apache.iotdb.db.qp.physical.sys.DeleteStorageGroupPlan;
 import org.apache.iotdb.db.qp.physical.sys.DeleteTimeSeriesPlan;
 import org.apache.iotdb.db.qp.physical.sys.DropFunctionPlan;
 import org.apache.iotdb.db.qp.physical.sys.DropIndexPlan;
+import org.apache.iotdb.db.qp.physical.sys.DropTriggerPlan;
 import org.apache.iotdb.db.qp.physical.sys.FlushPlan;
 import org.apache.iotdb.db.qp.physical.sys.KillQueryPlan;
 import org.apache.iotdb.db.qp.physical.sys.LoadConfigurationPlan;
@@ -112,6 +119,9 @@ import org.apache.iotdb.db.qp.physical.sys.ShowQueryProcesslistPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowStorageGroupPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowTTLPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowTimeSeriesPlan;
+import org.apache.iotdb.db.qp.physical.sys.ShowTriggersPlan;
+import org.apache.iotdb.db.qp.physical.sys.StartTriggerPlan;
+import org.apache.iotdb.db.qp.physical.sys.StopTriggerPlan;
 import org.apache.iotdb.db.qp.physical.sys.TracingPlan;
 import org.apache.iotdb.db.query.control.QueryResourceManager;
 import org.apache.iotdb.db.query.udf.core.context.UDFContext;
@@ -322,6 +332,8 @@ public class PhysicalGenerator {
             return new ShowQueryProcesslistPlan(ShowContentType.QUERY_PROCESSLIST);
           case SQLConstant.TOK_SHOW_FUNCTIONS:
             return new ShowFunctionsPlan(((ShowFunctionsOperator) operator).showTemporary());
+          case SQLConstant.TOK_SHOW_TRIGGERS:
+            return new ShowTriggersPlan(((ShowTriggersOperator) operator).getPath());
           default:
             throw new LogicalOperatorException(
                 String.format(
@@ -361,6 +373,20 @@ public class PhysicalGenerator {
       case DROP_FUNCTION:
         DropFunctionOperator dropFunctionOperator = (DropFunctionOperator) operator;
         return new DropFunctionPlan(dropFunctionOperator.getUdfName());
+      case CREATE_TRIGGER:
+        CreateTriggerOperator createTriggerOperator = (CreateTriggerOperator) operator;
+        return new CreateTriggerPlan(
+            createTriggerOperator.getTriggerName(),
+            createTriggerOperator.getEvent(),
+            createTriggerOperator.getFullPath(),
+            createTriggerOperator.getClassName(),
+            createTriggerOperator.getAttributes());
+      case DROP_TRIGGER:
+        return new DropTriggerPlan(((DropTriggerOperator) operator).getTriggerName());
+      case START_TRIGGER:
+        return new StartTriggerPlan(((StartTriggerOperator) operator).getTriggerName());
+      case STOP_TRIGGER:
+        return new StopTriggerPlan(((StopTriggerOperator) operator).getTriggerName());
       default:
         throw new LogicalOperatorException(operator.getType().toString(), "");
     }
diff --git a/server/src/test/java/org/apache/iotdb/db/qp/physical/PhysicalPlanTest.java b/server/src/test/java/org/apache/iotdb/db/qp/physical/PhysicalPlanTest.java
index da1f821..e6aaa95 100644
--- a/server/src/test/java/org/apache/iotdb/db/qp/physical/PhysicalPlanTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/qp/physical/PhysicalPlanTest.java
@@ -19,6 +19,7 @@
 package org.apache.iotdb.db.qp.physical;
 
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.db.engine.trigger.api.TriggerEvent;
 import org.apache.iotdb.db.exception.StorageEngineException;
 import org.apache.iotdb.db.exception.metadata.IllegalPathException;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
@@ -39,11 +40,16 @@ import org.apache.iotdb.db.qp.physical.crud.UDTFPlan;
 import org.apache.iotdb.db.qp.physical.sys.AuthorPlan;
 import org.apache.iotdb.db.qp.physical.sys.CreateFunctionPlan;
 import org.apache.iotdb.db.qp.physical.sys.CreateTimeSeriesPlan;
+import org.apache.iotdb.db.qp.physical.sys.CreateTriggerPlan;
 import org.apache.iotdb.db.qp.physical.sys.DataAuthPlan;
 import org.apache.iotdb.db.qp.physical.sys.DropFunctionPlan;
+import org.apache.iotdb.db.qp.physical.sys.DropTriggerPlan;
 import org.apache.iotdb.db.qp.physical.sys.LoadConfigurationPlan;
 import org.apache.iotdb.db.qp.physical.sys.OperateFilePlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowPlan;
+import org.apache.iotdb.db.qp.physical.sys.ShowTriggersPlan;
+import org.apache.iotdb.db.qp.physical.sys.StartTriggerPlan;
+import org.apache.iotdb.db.qp.physical.sys.StopTriggerPlan;
 import org.apache.iotdb.db.query.executor.fill.LinearFill;
 import org.apache.iotdb.db.query.executor.fill.PreviousFill;
 import org.apache.iotdb.db.query.udf.service.UDFRegistrationService;
@@ -72,8 +78,10 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import static org.junit.Assert.assertEquals;
@@ -1140,4 +1148,71 @@ public class PhysicalPlanTest {
     Assert.assertEquals(1, ((DeletePlan) plan).getDeleteStartTime());
     Assert.assertEquals(2, ((DeletePlan) plan).getDeleteEndTime());
   }
+
+  @Test
+  public void testCreateTrigger1() throws QueryProcessException {
+    String sql =
+        "CREATE TRIGGER trigger1 BEFORE INSERT ON root.sg1.d1.s1 AS 'org.apache.iotdb.engine.trigger.Example'";
+
+    CreateTriggerPlan plan = (CreateTriggerPlan) processor.parseSQLToPhysicalPlan(sql);
+    Assert.assertFalse(plan.isQuery());
+    Assert.assertEquals("trigger1", plan.getTriggerName());
+    Assert.assertEquals(TriggerEvent.BEFORE_INSERT, plan.getEvent());
+    Assert.assertEquals("root.sg1.d1.s1", plan.getFullPath().getFullPath());
+    Assert.assertEquals("org.apache.iotdb.engine.trigger.Example", plan.getClassName());
+  }
+
+  @Test
+  public void testCreateTrigger2() throws QueryProcessException {
+    String sql =
+        "CREATE TRIGGER trigger2 AFTER INSERT ON root.sg1.d1.s2 AS 'org.apache.iotdb.engine.trigger.Example'"
+            + "WITH ('key1'='value1', 'key2'='value2')";
+
+    CreateTriggerPlan plan = (CreateTriggerPlan) processor.parseSQLToPhysicalPlan(sql);
+    Assert.assertFalse(plan.isQuery());
+    Assert.assertEquals("trigger2", plan.getTriggerName());
+    Assert.assertEquals(TriggerEvent.AFTER_INSERT, plan.getEvent());
+    Assert.assertEquals("root.sg1.d1.s2", plan.getFullPath().getFullPath());
+    Assert.assertEquals("org.apache.iotdb.engine.trigger.Example", plan.getClassName());
+    Map<String, String> expectedAttributes = new HashMap<>();
+    expectedAttributes.put("key1", "value1");
+    expectedAttributes.put("key2", "value2");
+    Assert.assertEquals(expectedAttributes, plan.getAttributes());
+  }
+
+  @Test
+  public void testDropTrigger() throws QueryProcessException {
+    String sql = "DROP TRIGGER trigger1";
+
+    DropTriggerPlan plan = (DropTriggerPlan) processor.parseSQLToPhysicalPlan(sql);
+    Assert.assertFalse(plan.isQuery());
+    Assert.assertEquals("trigger1", plan.getTriggerName());
+  }
+
+  @Test
+  public void testStartTrigger() throws QueryProcessException {
+    String sql = "START TRIGGER my-trigger";
+
+    StartTriggerPlan plan = (StartTriggerPlan) processor.parseSQLToPhysicalPlan(sql);
+    Assert.assertFalse(plan.isQuery());
+    Assert.assertEquals("my-trigger", plan.getTriggerName());
+  }
+
+  @Test
+  public void testStopTrigger() throws QueryProcessException {
+    String sql = "STOP TRIGGER my-trigger";
+
+    StopTriggerPlan plan = (StopTriggerPlan) processor.parseSQLToPhysicalPlan(sql);
+    Assert.assertFalse(plan.isQuery());
+    Assert.assertEquals("my-trigger", plan.getTriggerName());
+  }
+
+  @Test
+  public void testShowTriggers() throws QueryProcessException {
+    String sql = "SHOW TRIGGERS ON root.sg1.d1.s1";
+
+    ShowTriggersPlan plan = (ShowTriggersPlan) processor.parseSQLToPhysicalPlan(sql);
+    Assert.assertTrue(plan.isQuery());
+    Assert.assertEquals("root.sg1.d1.s1", plan.getPath().getFullPath());
+  }
 }
diff --git a/site/src/main/.vuepress/config.js b/site/src/main/.vuepress/config.js
index 2d37ca0..8f8358d 100644
--- a/site/src/main/.vuepress/config.js
+++ b/site/src/main/.vuepress/config.js
@@ -27,15 +27,15 @@ var config = {
 
     // 静态网站部署的目录
     base: '',
-  
+
     // 网站标题
     title: 'IoTDB Website',
-  
+
     // <meta name="description" content="...">
-    description: 'Apache IoTDB', 
-  
+    description: 'Apache IoTDB',
+
     markdown: {
-      
+
       // 显示代码行号
       lineNumbers: true
     },
@@ -43,18 +43,18 @@ var config = {
 
         // 项目的 github 地址
         repo: 'https://github.com/apache/iotdb.git',
-    
+
         // github 地址的链接名
         repoLabel: 'gitHub',
-		
+
 		logo: '/img/logo.png',
-		
+
 		searchMaxSuggestions:10,
 
 		displayAllHeaders: true,
-		
+
 		sidebarDepth: 0,
-    
+
 		locales: {
 		  '/': {
 			selectText: 'Languages',
@@ -554,6 +554,9 @@ var config = {
 							['Operation Manual/DDL Data Definition Language','DDL (Data Definition Language)'],
 							['Operation Manual/DML Data Manipulation Language','DML (Data Manipulation Language)'],
 							['Operation Manual/UDF User Defined Function','UDF (User Defined Function)'],
+							// The trigger module has not been implemented yet,
+							// so the website should not show users how to use it to avoid misleading.
+              // ['Operation Manual/Triggers','Triggers'],
 							['Operation Manual/Kill Query','Kill Query'],
 							['Operation Manual/Administration','Administration'],
 							['Operation Manual/SQL Reference','SQL Reference']
@@ -836,7 +839,7 @@ var config = {
 							['8-System Tools/1-Sync','同步工具'],
 							['8-System Tools/2-Memory Estimation Tool','内存预估工具']
 						]
-					},		   
+					},
 				],
 				'/zh/UserGuide/V0.9.x/': [
 					{
@@ -1175,7 +1178,10 @@ var config = {
 						children: [
 							['Operation Manual/DDL Data Definition Language','DDL (数据定义语言)'],
 							['Operation Manual/DML Data Manipulation Language','DML (数据操作语言)'],
-							['Operation Manual/UDF User Defined Function','UDF(用户自定义函数)'],
+              ['Operation Manual/UDF User Defined Function','UDF(用户自定义函数)'],
+							// The trigger module has not been implemented yet,
+							// so the website should not show users how to use it to avoid misleading.
+              // ['Operation Manual/Triggers','触发器'],
 							['Operation Manual/Kill Query','中止查询'],
 							['Operation Manual/Administration','权限管理语句'],
 							['Operation Manual/SQL Reference','SQL 参考文档']
@@ -1308,7 +1314,7 @@ var config = {
       },
 	locales: {
 		'/': {
-		  lang: 'en-US', 
+		  lang: 'en-US',
 		  title: ' ',
 		  description: ' '
 		},
@@ -1319,6 +1325,6 @@ var config = {
 		}
 	  },
   }
-  
+
   module.exports = config