2.2. RQL语法

2.2.1. 保留关键字

AND, ASC, BEING, DELETE, DESC, DISTINCT, EXISTS, FALSE, GROUPBY,
HAVING, ILIKE, INSERT, LIKE, LIMIT, NOT, NOW, NULL, OFFSET,
OR, ORDERBY, SET, TODAY, TRUE, UNION, WHERE, WITH

关键字不区分大小写。在定义模式或作为RQL变量名时,不应该使用它们。

2.2.2. 案例

  • 变量应该全部大写。

  • 关系应该都是小写的,并且与模式中定义的关系的名称完全匹配。

  • 实体类型应该以大写字母开头,后面至少跟一个小写字母。

2.2.3. 变量和类型

要浏览和/或选择的实体和值在查询中表示为 变量 那必须用大写字母写。

使用RQL,我们不区分实体和属性。属性值被视为特定类型的实体(见下文),通过称为属性名称的关系链接到一个(真实)实体,其中实体是主题,属性是对象。

每个变量的可能类型是根据上面表达的约束和每个变量之间的关系从模式派生的。

我们可以使用特殊关系来限制变量的可能类型 is 在限制中。

2.2.4. 虚拟关系

这些关系只能在RQL查询中使用,但不是实体的实际属性。

  • has_text :用于查询全文索引的关系(仅适用于具有全文索引属性的实体)。

  • identity :当您需要使用两个不同的变量进行查询时,用于告诉RQL变量与另一个变量相同的关系。相反,它与 NOT 告诉两个变量不应标识同一实体的运算符

2.2.5. 文字表达式

RQL支持的基类型是那些由YAMS模式支持的基类型。文字值表示如下:

  • 字符串应在双引号或单引号之间。如果该值包含一个引号,则应在其前面加上一个反斜杠“\”

  • 浮点数分隔符是点“.”

  • 布尔值为 TRUEFALSE 关键词

  • 日期和时间应表示为带ISO符号的字符串:YYYY/MM/DD [HH:毫米] ,或使用关键字 TODAYNOW

您也可以使用 NULL 关键字,表示“未指定”。

2.2.6. 算子

2.2.6.1. 逻辑运算符

AND, OR, NOT, ','

“,”等价于“and”,但逻辑运算符的优先级最小(请参见 操作员优先级

2.2.6.2. 数学运算符

算符

描述

例子

结果

+

附加

2+3

5

-

减法

2-3个

-1

*

乘法

2*3个

6

/

分开

4月2日

2

%

模(余数)

5%4

1

^

求幂

2.0^3.0

8

&

按位与

91和15

11

|

按位或

32 3

35

γ

位异或

17 5

20

~

按位不

~1个

-2

<<

位左移

1<<4

16

>>

按位右移

8>>2

2

注意整数除法根据后端行为截断结果。例如,PostgreSQL就是这样。

2.2.6.3. 比较运算符

=, !=, <, <=, >=, >, IN

使用比较运算符的语法是:

VARIABLE attribute <operator> VALUE

这个 = operator是默认的运算符,可以省略,即:

VARIABLE attribute = VALUE

等于

VARIABLE attribute VALUE

操作员 IN 提供可能值的列表:

Any X WHERE X name IN ('chauvat', 'fayolle', 'di mascio', 'thenault')

2.2.6.4. 字符串运算符

LIKE, ILIKE, ~=, REGEXP

这个 LIKE 字符串运算符可以与特殊字符一起使用 % 在字符串中作为通配符:

-- match every entity whose name starts with 'Th'
Any X WHERE X name ~= 'Th%'
-- match every entity whose name endswith 'lt'
Any X WHERE X name LIKE '%lt'
-- match every entity whose name contains a 'l' and a 't'
Any X WHERE X name LIKE '%l%t%'

ILIKE 是的不区分大小写版本 LIKE .它在所有后端上都不可用(例如,sqlite不支持它)。如果后端不可用, ILIKE 会表现得像 LIKE .

~= 是的快捷方式版本 ILIKE ,或 LIKE 当后端没有前者时。

这个 REGEXP 是替代 LIKE 它支持POSIX正则表达式:

-- match entities whose title starts with a digit
Any X WHERE X title REGEXP "^[0-9].*"

使用的底层SQL运算符依赖于后端:

  • 这个 ~ 运算符用于PostgreSQL,

  • 这个 REGEXP mysql和sqlite的运算符。

其他后端尚不受支持。

2.2.6.5. 操作员优先级

  1. (, )

  2. ^, <<, >>

  3. *, /, %, &

  4. +, -, |, #

  5. NOT

  6. AND

  7. OR

  8. ,

2.2.7. 搜索查询

搜索查询的简化语法:::

[ `DISTINCT`] `Any` V1 (, V2) \*
[ `GROUPBY` V1 (, V2) \*] [ `ORDERBY` <orderterms>]
[ `LIMIT` <value>] [ `OFFSET` <value>]
[ `WHERE` <triplet restrictions>]
[ `WITH` V1 (, V2)\* BEING (<query>)]
[ `HAVING` <other restrictions>]
[ `UNION` <query>]

2.2.7.1. 选择

第一个occuring子句是应在结果集中选择的术语。术语可以是变量、文本、函数调用、算术等,并且每个术语由逗号分隔。

结果集中的列与本条款中的术语相同,与顺序有关。

函数调用的语法有些直观,例如:

Any UPPER(N) WHERE P firstname N

2.2.7.2. 分组和聚合

这个 GROUPBY 关键字后面是一个术语列表,应根据该列表对结果进行分组。它们通常与聚合函数一起使用,负责聚合每个组的值(请参见 聚合函数

对于分组查询,所有选定的变量必须进行聚合(即由聚合函数使用)或分组(即列出在 GROUPBY 条款)。

2.2.7.3. 分选

这个 ORDERBY 关键字if后接选择顺序的定义:变量或列号后接排序方法 (ASCDESCASC 作为默认值。如果未指定排序方法,则排序是升序的。 (ASC

2.2.7.4. 分页

这个 LIMITOFFSET 关键字可以分别用于限制结果的数量和判断从哪个结果行开始(例如,使用 LIMIT 20 为了得到前20个结果,然后 LIMIT 20 OFFSET 20 得到下20个。

2.2.7.5. 限制

这个 WHERE 关键字引入查询的“主要”部分之一,在这里您可以“定义”变量,并添加一些限制来说明您感兴趣的内容。

它是一个三元组的列表“主题关系对象”,例如 V1 relation (V2 | <static value>) .三胞胎是用 逻辑运算符 .

注解

关于否定运算符 (NOT ):

  • NOT X relation Y is equivalent to NOT EXISTS(X relation Y)

  • Any X WHERE NOT X owned_by U 指“没有关系的实体” owned_by “。

  • Any X WHERE NOT X owned_by U, U login "syt" 表示“实体没有关系” owned_by 使用用户syt”。他们可能与另一个用户有“所有者”关系。

在这个子句中,您还可以使用 EXISTS 当您想知道某个表达式是否为真,并且不需要使其成为真的完整元素集时。对存在性的测试比获取完整的结果集要快得多,尤其是当您考虑使用 OR 反对几种表达。例如,如果要检索状态为“就绪”或标记为“优先级”的版本,则应编写:

Any X ORDERBY PN,N
WHERE X num N, X version_of P, P name PN,
      EXISTS(X in_state S, S name "ready")
      OR EXISTS(T tags X, T name "priority")

Any X ORDERBY PN,N
WHERE X num N, X version_of P, P name PN,
      (X in_state S, S name "ready")
      OR (T tags X, T name "priority")

这两个查询根本不等价:

  • 前者将检索所有版本,然后检查处于匹配状态或由预期标签标记的每个版本,

  • 后者将检索所有版本、状态和标记(笛卡尔产品!),计算联接,然后排除处于匹配状态或由预期标记标记的每一行。这意味着,如果in-u状态或标记表为空(即应用程序中没有这样的关系),则不会得到任何结果。这通常不是你想要的。

另一个你可能想使用的常见情况 EXISTS 当你发现自己在使用 DISTINCT 在查询开始时删除重复的结果。典型的情况是,当您具有多值关系(如Project的versionu),并且希望检索具有版本的项目时:

Any P WHERE V version_of P

将返回每个项目的版本数次。因此,您可能会尝试使用:

DISTINCT Any P WHERE V version_of P

这将起作用,但不是有效的,因为它将使用 SELECT DISTINCT SQL谓词,它需要检索所有项目,然后对它们进行排序并丢弃重复项,这对于大型结果集来说成本非常高。所以写这个的最好方法是:

Any P WHERE EXISTS(V version_of P)

你也可以用问号 (?) to mark optional relations. This allows you to select entities related or not to another. It is a similar concept to Left outer join

表A和B的左外部联接(或简单的左联接)的结果始终包含“左”表(A)的所有记录,即使联接条件在“右”表(B)中找不到任何匹配的记录。

你必须使用 ? 在变量后面指定与该变量的关系是可选的。例如:

  • 附加或不附加到版本的项目的错误

    Any X, V WHERE X concerns P, P eid 42, X corrected_in V?
    

    您将得到一个结果集,其中包含所有项目的通知单,其中要么是修复的版本,要么是与某个版本无关的通知单没有。

  • 所有卡片和他们记录的项目(如果有的话)

    Any C, P WHERE C is Card, P? documented_by C
    

请注意,您也可以使用外部联接:

  • 在属性关系的rhs上,例如

    Any X WHERE X ref XR, Y name XR?
    

    使y在x上通过ref/name属性进行外部连接比较

  • HAVING 表达式,例如

    Any X WHERE X creation_date XC, Y creation_date YC
    HAVING YEAR(XC)=YEAR(YC)?
    

    因此,通过比较从其创建日期提取的年份,y在x上是外部连接的。

    Any X WHERE X creation_date XC, Y creation_date YC
    HAVING YEAR(XC)?=YEAR(YC)
    

    将外部连接X而不是Y。

2.2.7.6. 有限制的

这个 HAVING 子句(如SQL)可用于根据聚合函数返回的值限制查询,例如

Any X GROUPBY X WHERE X relation Y HAVING COUNT(Y) > 10

但是,它可能用于其他用途:在 WHERE 从句,我们只限于三元组表达式,所以有些东西可能不在这里表达。让我们举一个例子:如果你想让某人的大写名等于另一个人的大写名。没有合适的方法可以用三联体来表达这一点,因此您应该使用如下内容:

Any X WHERE X firstname XFN, Y firstname YFN, NOT X identity Y HAVING UPPER(XFN) = UPPER(YFN)

另一个例子:假设你想要一个2000年出生的人:

Any X WHERE X birthday XB HAVING YEAR(XB) = 2000

请注意,虽然我们希望在不使用HAVING子句的情况下进行此操作,但目前无法进行此操作,因为它在RQL语法中引入了一个无法处理的歧义。 Yapps, 我们使用的解析器生成器。

2.2.7.7. 子查询

这个 WITH 关键字引入子查询子句。每个子查询的形式如下:

v1(,v2)是(rql查询)

左边的变量 BEING 关键字定义将子查询结果映射到外部查询的变量。子查询之间使用逗号分隔。

假设我们要检索每个项目的版本数和票据数。由于场景背后的关系代数的性质,这无法使用单个查询实现。你必须写些东西:

Any X, VC, TC WHERE X identity XX
WITH X, VC BEING (Any X, COUNT(V) GROUPBY X WHERE V version_of X),
     XX, TC BEING (Any X, COUNT(T) GROUPBY X WHERE T ticket_of X)

注意,对于两个不同的子查询,我们不能将同一个变量名用作别名,因此在本例中使用“x”和“xx”,然后使用特殊的 identity 关系(参见 虚拟关系

警告

子查询定义了一个新的变量范围,因此即使在外部查询和子查询中变量具有相同的名称,它们在技术上也是如此 不是 相同的变量。所以:

Any W, REF WITH W, REF BEING
    (Any W, REF WHERE W is Workcase, W ref REF,
                      W concerned_by D, D name "Logilab")

可以写:

Any W, REF WITH W, REF BEING
   (Any W1, REF1 WHERE W1 is Workcase, W1 ref REF1,
                       W1 concerned_by D, D name "Logilab")

此外,当变量来自子查询时,当前不能在外部查询中引用其属性或内联关系,必须在子查询中获取它们。例如,假设我们希望在第一个示例中按项目名称排序,我们必须编写:

Any X, VC, TC ORDERBY XN WHERE X identity XX
WITH X, XN, VC BEING (Any X, COUNT(V) GROUPBY X,XN WHERE V version_of X, X name XN),
     XX, TC BEING (Any X, COUNT(T) GROUPBY X WHERE T ticket_of X)

而不是:

Any X, VC, TC ORDERBY XN WHERE X identity XX, X name XN,
WITH X, XN, VC BEING (Any X, COUNT(V) GROUPBY X WHERE V version_of X),
     XX, TC BEING (Any X, COUNT(T) GROUPBY X WHERE T ticket_of X)

这将导致SQL执行错误。

2.2.7.8. 联合

您可以使用 UNION .每个查询的所选内容应具有相同的列数。

(Any X, XN WHERE X is Person, X surname XN) UNION (Any X,XN WHERE X is Company, X name XN)

2.2.8. 可用功能

下面是框架本机支持的聚合和转换函数列表。注意,多维数据集可以定义其他函数。

2.2.8.1. 聚合函数

COUNT(Any)

返回行数

MIN(Any)

返回最小值

MAX(Any)

返回最大值

AVG(Any)

返回平均值

SUM(Any)

返回值之和

COMMA_JOIN(String)

返回用逗号分隔的每个值(仅限字符串)

上面的所有聚合函数都采用一个参数。注意一些聚合函数(例如 MAXMIN )可能会回来 None 如果没有结果行。

2.2.8.2. 字符串转换函数

UPPER(String)

大写字符串

LOWER(String)

小写字符串

LENGTH(String)

返回字符串的长度

SUBSTRING(String, start, length)

从字符串中提取从给定索引开始并具有给定长度的字符串

LIMIT_SIZE(String, max size)

如果字符串的长度大于给定的最大大小,则去掉它并添加省略号(“…”)。因此,结果字符串的最大大小为+3个字符

TEXT_LIMIT_SIZE(String, format, max size)

与上面类似,但允许指定字符串所包含文本的mime类型。支持的格式有text/html、text/xhtml和text/xml。所有其他内容将被视为纯文本。对于非纯文本格式,在限制字符串之前,将首先删除SGML标记。

2.2.8.3. 日期提取函数

YEAR(Date)

返回日期或日期时间的年份

MONTH(Date)

返回日期或日期时间的月份

DAY(Date)

返回日期或日期时间的日期

HOUR(Datetime)

返回日期时间的小时数

MINUTE(Datetime)

返回日期时间的分钟数

SECOND(Datetime)

返回日期时间的秒数

WEEKDAY(Date)

返回日期或日期时间的星期几。星期日==1,星期六==7。

2.2.8.4. 其他功能

ABS(num)

返回数字的绝对值

RANDOM()

返回从0.0到1.0的伪随机值

FSPATH(X)

期望x是其值存储在 BFSStorage 并返回文件系统上的路径

FTIRANK(X)

期望x是has-text关系中使用的实体,并返回与每个结果实体的排名顺序相对应的数字

CAST(Type, X)

期望x是一个属性,并返回它强制转换为给定的最终类型

2.2.9. 实例

  • 搜索标识符53的对象

    Any X WHERE X eid 53
    
  • 搜索材料,如漫画,由Syt所有,可用

    Any X WHERE X is Document,
                X occurence_of F, F class C, C name 'Comics',
                X owned_by U, U login 'syt',
                X available TRUE
    
  • 寻找对培训感兴趣的欧洲直升机工作人员

    Any P WHERE P is Person, P work_for S, S name 'Eurocopter',
                P interested_by T, T name 'training'
    
  • jphc或cyc编写的10天以内的搜索注释

    Any N WHERE N is Note, N written_on D, D day> (today -10),
                N written_by P, P name 'jphc' or P name 'ocy'
    
  • 寻找对巴黎培训或生活感兴趣的人

    Any P WHERE P is Person, EXISTS(P interested_by T, T name 'training') OR
                (P city 'Paris')
    
  • 所有人的姓和名

    Any N, P WHERE X is Person, X name N, X firstname P
    

    注意,选择多个实体通常强制使用“any”,因为类型规范以其他方式应用于所有选定的变量。我们可以在这里写

    String N, P WHERE X is Person, X name N, X first_name P
    

    注意:不能使用 ……其中x是第一种类型或x是第二种类型 .要显式指定多个类型,必须执行以下操作

    Any X WHERE X is IN (FirstType, SecondType)
    

2.2.10. 插入查询

INSERT <entity type>v1(,<entity type>v2)* : <assignments> [ WHERE <restriction>]

作业

表单中要分配的关系列表 V1 relationship V2 | <static value>

限制可以定义分配中使用的变量。

小心,如果指定了限制,则插入操作将针对 限制返回的每个行结果 .

  • 插入名为“foo”的新人员

    INSERT Person X: X name 'foo'
    
  • 插入一个名为“foo”的新成员,另一个名为“nice”,以及他们之间的“friend”关系

    INSERT Person X, Person Y: X name 'foo', Y name 'nice', X friend Y
    
  • 插入一个名为“foo”的新用户和一个名为“nice”的现有用户的“friend”关系

    INSERT Person X: X name 'foo', X friend  Y WHERE Y name 'nice'
    

2.2.11. 更新和关系创建查询

SET <assignments> [ WHERE <restriction>]

警告:如果指定了限制,则完成更新 对于由限制返回的每个结果行 .

  • 将名为“foo”的人重命名为“bar”,名字已更改

    SET X name 'bar', X firstname 'original' WHERE X is Person, X name 'foo'
    
  • 在“friend”类型的关系所链接的对象之间插入“know”类型的关系

    SET X know Y  WHERE X friend Y
    

2.2.12. 删除查询

DELETE (<实体类型>v)(v1关系v2),… [ WHERE <restriction>]

警告:如果指定了限制,则删除 对于限制返回的每个行结果 .

  • 删除名为“foo”的人

    DELETE Person X WHERE X name 'foo'
    
  • 从名为“foo”的人中删除“friend”类型的所有关系

    DELETE X friend Y WHERE X is Person, X name 'foo'