TigerGraph文档
2.3
2.3
  • TigerGraph 2.3 技术文档目录
  • TigerGraph 版本比较
  • GSQL 图数据库算法库
  • 版本发布, 功能变更
    • 版本发布 - TigerGraph 2.3
      • 版本发布 - TigerGraph 2.2
    • 变更日志
  • INTRODUCTION AND OVERVIEW
    • TigerGraph 入门指南
    • GSQL 101
      • 环境准备
      • 定义一个Schema
      • 加载数据
      • 使用内置的SELECT进行查询
      • 使用参数化GSQL查询进行查询
      • 总结:你学到的东西
    • TigerGraph平台概览
    • Knowledge Base and FAQs
      • TigerGraph 常见问题
      • GSQL 常见问题
    • Kafka Loader用户手册
  • 系统管理指南
    • TigerGraph 管理员指南
      • 硬件及软件配置
      • 安装和配置
        • 安装指南
        • 高可用(HA)集群配置
        • 集群的扩容
        • 软件许可激活
      • 系统权限管理
        • 用户权限及验证
        • LDAP
        • 单点登录(SSO)
      • 数据加密
        • 链接的加密
        • 非活跃数据(Data At Rest)的加密
      • 系统管理
        • 基于Web的管理工具:Admin Portal
        • 使用gadmin工具管理
        • 数据的备份与恢复
        • 系统维护中的常见问题
  • 开发者指南
    • GSQL 语言开发指南
      • 第一部分 数据定义及加载
        • 简介
        • 系统和语言基础
        • 定义一个图模型(Graph Schema)
        • 修改图模型
        • 创建数据加载任务
        • 执行加载作业
        • 附录
          • 关键词和系统预留词
          • GSQL 从开始到结束的整个过程和数据流向
      • 第二部分 查询
        • 简介
        • 创建、安装、执行查询
        • 数据类型
        • 累加器(Accumulators)
        • 运算符,函数和表达式
        • 声明和赋值
        • SELECT语句
        • 控制流语句
        • 数据修改语句
        • 输出语句以及文件对象
        • 异常处理语句
        • 注释
        • 附录
          • 附录A: 一般错误和问题
          • 附录B:查询语言的完整正式语法
          • 附录C. 图查询语言的预留词列表
          • 附录D. 示例
    • RESTPP API 开发指南
      • 简介
      • RESTPP请求
      • 系统预制函数(Endpoints)
      • 系统预制函数请求格式(JSON)
    • 事务处理及ACID支持
  • 图形界面 可视化
    • GraphStudio 用户指南
      • GraphStudio 概述
      • GraphStudio许可证
      • 用户权限管理
      • 设计图模型(Schema)
      • 将数据映射到图
      • 加载数据
      • 探索图数据
      • 编写查询
      • 导入和导出解决方案
      • 已知问题
      • GraphStudio中的专利及第三方软件版权说明
Powered by GitBook
On this page
  • 异常响应的默认方式
  • 自定义异常的响应方式
  • EXCEPTION 的声明
  • RAISE 语句
  • 用TRY...EXCEPTION 语句自定义异常处理动作
  • 异常处理的流程图

Was this helpful?

  1. 开发者指南
  2. GSQL 语言开发指南
  3. 第二部分 查询

异常处理语句

本章介绍GSQL语言如何对程序异常进行响应,以及如何让用户自定义异常处理的方式。异常是指运行时错误。 GSQL语言同时支持内置系统异常和用户自定义异常。 内置异常包括GSQL语言异常(例如超出范围的值,错误的数据类型和非法操作),以及其他TigerGraph组件或操作系统中出现的错误。

GSQL 还支持用户自定义异常响应,也称为异常处理。 本节介绍用户自定义异常的方法:

#########################################################
## Exception Statements ##
 
declExceptStmt := EXCEPTION exceptVarName "(" errorCode ")"
exceptVarName  := name
errorCode      := integer
 
raiseStmt       := RAISE exceptVarName [errorMsg]
errorMsg        := "(" expr ")"
 
tryStmt         := TRY queryBodyStmts EXCEPTION caseExceptBlock+
                  [elseExceptBlock] END ";"
caseExceptBlock := WHEN exceptVarName THEN queryBodyStmts
elseExceptBlock := ELSE queryBodyStmts

异常响应的默认方式

在执行查询期间发生异常时,默认响应如下:

  • 查询不再执行任何语句; 它会退出。

  • 如果使用的是RUN QUERY命令执行查询,则将显示错误消息。

  • 如果是通过调用GET /query REST++ 接口的方式运行查询,则输出将是一个简单的JSON对象。 一些错误拥有错误代码(code)字段,另一些错误则没有改字段:

Unhandled Exception的输出结果(以REST 接口方式执行)
{
 "error": true,
 "message": "<errorMsg>"
 "code": "<errType><errorCode>"
}

下面的示例演示了两个常见的错误:数据类型错误和分母为零错误。 首先我们定义一个简单的查询,然后用查询的输入的参数除以100.0。

例: query excpBuiltin
CREATE QUERY excpBuiltin(INT n1) FOR GRAPH minimalNet {
 PRINT 100.0/n1;
}

然后我们测试三个运算:

  1. 一个有效的输入 (例如 n1 = 7)

  2. 输入错误的数据类型 (例如n1 = "A")

  3. 除以零 (例如n1 = 0)

首先,我们使用GSQL接口进行测试。 当查询运行且没有错误时,则输出一个JSON格式的值。 但如果存在异常,则仅显示错误消息。

RUN QUERY的异常响应
GSQL > RUN QUERY excpBuiltin(7)
{
 "error": false,
 "message": "",
 "version": {
   "schema": 0,
   "api": "v2"
 },
 "results": [{"100.0/n1": 14.28571}]
}

GSQL > RUN QUERY excpBuiltin("a")
Values of parameter n1 must be INT64 type, invalid value [a] provided.
 
GSQL > RUN QUERY excpBuiltin(0)
Runtime Error: divider is zero.

将查询作为REST ++接口运行时情况略有不同。 输出的结果始终为JSON格式。

从TigerGraph v1.2开始,GET /query端点的格式发生了变化。 现在必须在/query之后指定图形名称:

/query/{graph_name}/{query_name}

GET /query请求时的异常响应
$curl -X GET "http://localhost:9000/query/minimalNet/excpBuiltin?n1=7"
{
   "error": false,
   "message": "",
   "results": [
       {
           "100.0/n1": 14.28571
       }
   ],
   "version": {
       "api": "v2",
       "schema": 0
   }
}
 
$curl -X GET "http://localhost:9000/query/minimalNet/excpBuiltin?n1=a"
{
   "code": "REST-30000",
   "error": true,
   "message": "Values of parameter n1 must be INT64 type, invalid value [a] provided.",
   "version": {
       "api": "v2",
       "schema": 0
   }
}
 
$curl -X GET "http://localhost:9000/query/minimalNet/excpBuiltin?n1=0"
{
   "error": true,
   "message": "Runtime Error: divider is zero.",
   "version": {
       "api": "v2",
       "schema": 0
   }
}

自定义异常的响应方式

如果某种异常常发生在特定的语句块中,则查询的编写人员可以指定该响应的具体内容。

以下语句类型可用于指定用户自定义异常的条件或响应。

  • 用EXCEPTION声明语句给用户自定义异常命名。

  • 用RAISE语句来表示一个用户自定义异常的发生。

  • 用TRY ... EXCEPTION语句在查询主体层语句中定义和应用一个用户自定义异常处理动作。无论在先前有或没有EXCEPTION和RAISE语句,该语句都能使用。

系统内置异常始终优先于用户自定义异常。因此,用户自定义异常只能用于捕获系统内置异常无法捕获的异常情况。这意味着系统内置异常最好用于检验GSQL图形查询语言的语法和语义是否合规,但对于某些特定用户的应用来说,这并不是一定满足需求。

EXCEPTION 的声明

EXCEPTION 的声明
declExceptStmt := EXCEPTION exceptVarName "(" errorCode ")"
exceptVarName := name
errorCode     := integer

要使用用户自定义的异常,我们必须首先声明它。 异常声明语句声明用户自定义异常的类型,名称和id。 自定义异常的id号的errorCode必须大于40,000。 小于40,000的数字预留给系统内置异常。异常语句必须放在累加器声明语句之后,任何查询主体层语句之前。 一个查询中,用户可以声明多个异常类型。

RAISE 语句

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

RAISE语句用于判断用户自定义异常的发生。 示例中的exceptVarName必须是之前已经声明过的异常之一。 我们也可以选择是否需要自定义异常发生时报告的错误消息。 执行RAISE语句后,查询动作的工作流会发生变化。 如果RAISE语句不在TRY子句中,则查询以默认的响应结束,返回由该异常类型和该RAISE语句所定义的错误代码和错误消息。 如果RAISE语句在TRY子句中,则查询动作会跳转到TRY子句的EXCEPTION部分。

RAISE语句本身不包括定义异常的发生条件。 通常,用户会使用IF ... THEN语句实现该逻辑,并将RAISE语句放在THEN子句中。

在当前版本中,RAISE语句只能用作查询主体层的语句中,而不能用在DML子句中。 特别的,不能在SELECT语句中使用RAISE语句判断一个异常。

下面的示例定义并检查了两种类型的异常:空输入集(40001)和无匹配边(40002)。 请记住,系统允许的最小代码是40001。

例: 未处理的用户自定义异常
CREATE QUERY excpCountActivity(SET<VERTEX<person>> vSet, STRING eType) FOR GRAPH socialNet {
 # Count how many edges there are from each member of the input person set to posts,
 # along the specified edge type.
 
 MapAccum<STRING,INT> @@allCount;
 EXCEPTION emptyList (40001);
 EXCEPTION noEdges   (40002);
 
 IF ISEMPTY(vSet) THEN ## Raise 40001
   RAISE emptyList ("Error: Input parameter 'vSet' (type SET<VERTEX<person>>) is empty");
 END;
 
 Start = vSet;
 Results = SELECT s
   FROM Start:s -(:e)-> post:t
   WHERE e.type == eType
   ACCUM @@allCount += (t.subject -> 1);
   
 IF Results.size() == 0 THEN ## Raise 40002
   RAISE noEdges ("Error: No '" + eType + "' edges from the vertex set");
 END;
 PRINT @@allCount;
}
结果
// Valid input: no exceptions
$curl -X GET "http://localhost:9000/query/socialNet/excpCountActivity?vSet=person2&vSet=person6&eType=posted"
{
 "error": false,
 "message": "",
 "version": {
   "schema": 0,
   "api": "v2"
 },
 "results": [{
   "@@allCount": {
     "cats": 1,
     "tigergraph": 2
   }
 }]
}
 
// empty input set (due to spelling error in parameter name)
$curl -X GET "http://localhost:9000/query/socialNet/excpCountActivity?vset=person2&vset=person6&eType=posted"
{
 "code": "40001",
 "error": true,
 "version": {
   "schema": 0,
   "api": "v2"
 },
 "message": "Error: Input parameter 'vSet' (type SET<VERTEX<person>>) is empty"
}
 
 
// no edges (due to unknown edge type)
$curl -X GET "http://localhost:9000/query/socialNet/excpCountActivity?vSet=person2&vSet=person6&eType=commented"
{
 "code": "40002",
 "error": true,
 "version": {
   "schema": 0,
   "api": "v2"
 },
 "message": "Error: No 'commented' edges from the vertex set"
}

用TRY...EXCEPTION 语句自定义异常处理动作

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

TRY ... EXCEPTION语句允许用户自行定义异常处理动作,并将其添加到一个查询主体层语句中的某个语句块中。 TRY ...EXCEPTION语句可以嵌套在TRY语句块或EXCEPTION语句块中。

当前版本的GSQL不支持自定义处理系统内置的异常。 因此,如果发生系统内置的异常,它会忽略TRY..EXCEPTION语句而直接采取默认的处理方式,并将中止该查询。 在将来的更新中,我们有计划使得TRY ... EXCEPTION可以既支持自定义异常(RAISE)的处理,也支持内置异常的处理。

TRY ... EXCEPTION是一个嵌套两个语句块的复合句。第一个语句块(TRY)定义了自定义的错误处理动作,是一个查询主体层语句。第二个 (EXCEPTION)语句块包含了一系列的WHEN ... THEN子句。每个子句都指定一个异常类型,并表明了在发生该异常时需要采取的动作。用户还可以选择添加ELSE子句,用于处理所有其他的异常。下面的文字和流程图详细说明了TRY ...EXCEPTION的详细工作机制。

当TRY语句块中发生异常时,执行流程会跳过TRY的剩余部分并直接跳转到EXCEPTION语句块。这表明 GSQL正在寻求与该异常类型匹配的处理程序。在THEN或ELSE子句中执行完对应的处理后,执行过程将跳过EXCEPTION语句块的其余部分并继续执行END后面的语句。但是,如果没有匹配到合适的WHEN或ELSE处理程序,则向用户通告该异常,即在退出EXCEPTION之后,该查询仍然保持在RAISE的状态。如果该TRY ... EXCEPTION语句块是嵌套在另一个TRY语句块之内的,则该异常处理过程会在上层语句中重复执行,直到该异常最终被处理,或是所有的TRY ... EXCEPTION语句块都处理结束。

最后,如果未处理的异常不包含在一个TRY语句块内,则该查询将中止,输出该异常的默认处理响应。

情况 1: 如果在外层TRY语句中的条件1(cond1)为真,

  • 激活A选项(即RAISE A),并直接跳转到外层EXCEPTION 语句块.

由ELSE HandStmtsZ 语句处理.

情况2: 如果在内层TRY语句中的条件2(cond2)为真,

  • 激活A选项(即RAISE A),并直接跳转到内层的EXCEPTION 语句块.

由handStmtsX语句处理;

情况3: 如果在内层TRY语句中的条件3(cond3)为真,

  • 激活B选项(即RAISE B),并跳转到内部的EXCEPTION语句块。由于此时没有找到合适的处理方法,所以该异常被传播,并同时跳转到外层的EXCEPTION语句块,并在此处被handStmtsY语句处理。

自定义处理的示例:

以下示例是改进过的的最短路径查询。它用于查找计算机网络中从源到目标的所有路径。它使用广度优先算法,当在深度N处找到至少一条路径时,它便停在N处,否则就遍历整个图形。下列三个条件会引发它的异常并使搜索中止:

  1. 发现某条边的连接速度为负(由已损坏的数据导致)。

  2. 发现某条边的连接速度极慢(同样的,由已损坏的数据导致)。

  3. 图形中未找到符合要求的路径(搜索已经结束,但我们不打印结果)。

注意,情况1和2并不代表负速度或慢速度的边存在于最短路径上,它只是表示该查询在搜索期间发现了损坏的边。另外,因为我们不能在SELECT语句中执行RAISE动作,所以我们采取了一个变通的办法:设置一个带有错误代码的整数变量,并在SELECT过程中实时将该整数变量与需要检测的RAISE异常进行比较。

例:带有异常处理的路径搜索
CREATE QUERY compPathValid (vertex<computer> src, vertex<computer> tgt, BOOL enExcp)
FOR GRAPH computerNet {
# Find valid paths in a computer network from a source to a target.
# Stop search once you have found some paths.
# 3 Exceptions: (1) Negative connection speed, (2) Slow connection speed, (3) No path.
# Set enExcp=true to raise exceptions. enExcp=false will find paths, good or bad.
 
​OrAccum @@reached, @visited;
​ListAccum<STRING> @paths;
​DOUBLE minSpeed = 0.4;
​INT err;
 
​EXCEPTION negSpeed (40001);
​EXCEPTION slowSpeed (40002);
​EXCEPTION notReached (40003);
 
​TRY
​​Start = {src};
​​# Initialize: path to src is itself.
​​Start = SELECT s
​​​FROM Start:s
​​​ACCUM s.@paths = s.id;
 
​​WHILE Start.size() != 0 AND NOT @@reached DO
​​​Start = SELECT t
​​​​FROM Start:s -(:e)-> :t
​​​​WHERE t.@visited == false
​​​​ACCUM CASE
​​​​​WHEN e.connectionSpeed < 0 THEN err = 1
​​​​​WHEN e.connectionSpeed < minSpeed THEN err = 2
​​​​​WHEN t == tgt THEN @@reached += true
​​​​​END,
​​​# List1 * List2 -> List(each elem of List1 concat w/each elem of List2)
​​​​​t.@paths += (s.@paths * ["~"]) * [t.id]
​​​​POST-ACCUM t.@visited = true;
​​​IF err == 1 AND enExcp THEN
​​​​RAISE negSpeed ("Negative Speed");
​​​ELSE IF err == 2 AND enExcp THEN
​​​​RAISE slowSpeed ("Slow Speed");
​​​END;
​​END; # WHILE
 
​​IF NOT @@reached AND enExcp THEN
​​​RAISE notReached ("No path to target");
​​ELSE
​​​Result = {tgt};
​​​PRINT Result[Result.@paths]; // api v2
​​END;
​EXCEPTION
​​WHEN negSpeed THEN PRINT "bad path: negative speed";
​​WHEN slowSpeed THEN PRINT "bad path: slow speed";
​​WHEN notReached THEN PRINT "no path from source to target";
​END;
}

如附录D中的数据所示:

  • 任何通过了c1的搜索都将看到负边。

  • 任何通过了c12的搜索都会看到负边和慢边。

  • 任何通过了c14的搜索都会看到负边。

下面所示的5种情况的结果中:包含1个有效搜索和3种异常情况各一个。第5种与第4种情况相同,只不过第5种未启用异常处理。

compPathValid结果
GSQL > RUN QUERY compPathValid("c10","c12",true)
{
 "error": false,
 "message": "",
 "version": {
   "schema": 0,
   "api": "v2"
 },
 "results": [{"Result": [{
   "v_id": "c12",
   "attributes": {"Result.@paths": ["c10~c11~c12"]},
   "v_type": "computer"
 }]}]
}
GSQL > RUN QUERY compPathValid("c1","c12",true)
{
 "error": false,
 "message": "",
 "version": {
   "schema": 0,
   "api": "v2"
 },
 "results": [{"bad path: negative speed": "bad path: negative speed"}]
}
GSQL > RUN QUERY compPathValid("c10","c13",true)
{
 "error": false,
 "message": "",
 "version": {
   "schema": 0,
   "api": "v2"
 },
 "results": [{"bad path: slow speed": "bad path: slow speed"}]
}
GSQL > RUN QUERY compPathValid("c24","c25",true)
{
 "error": false,
 "message": "",
 "version": {
   "schema": 0,
   "api": "v2"
 },
 "results": [{"no path from source to target": "no path from source to target"}]
}
GSQL > RUN QUERY compPathValid("c24","c25",false)
{
 "error": false,
 "message": "",
 "version": {
   "schema": 0,
   "api": "v2"
 },
 "results": [{"Result": [{
   "v_id": "c25",
   "attributes": {"Result.@paths": []},
   "v_type": "computer"
 }]}]
}

异常处理的流程图

以下的流程图详述了触发和处理异常的所有情况,同时包含了用户自定义异常和系统内置异常:

Previous输出语句以及文件对象Next注释

Last updated 6 years ago

Was this helpful?