Datalog是什么

Datalog是一种数据查询语言,专门设计与大型关系数据库交互,语法与Prolog相似。Datalog的语法是Prolog的子集,但是Datalog的语义与Prolog不同。Datalog是一种声明式的语言,Declarative(声明式)语言主要有SQL等,其屏蔽细节,因此代码量更小,可读性更强。 ​

Datalog=Data+Logic(and,or,not) 其特性为:

  • 没有副作用(不会更改已有数据)
  • 没有控制流
  • 没有函数
  • 不是图灵完备的

Datalog语法

Data部分

Predicates(谓词)

谓词(Predicates)是datalog中的一个主要组成部分,可以看作是数据所组成的一个表(table of data),每一行都代表一个事实(fact)。

image.png

在上述表中,Age就是个谓词,在Age中(‘xiaoming’, 18)就是个事实,而(‘xiaohong’, 18)不存在,就不是个事实。

Atoms

atoms分为两种:关系型原子(relational atom)和算术型原子(arithmetic atoms)。 算数型原子由算数表达式组成,例如age >= 18

关系型原子由谓词名称(name of predicates)和参数(arguments/terms)组成,例如P(X1,X2…Xn),P表示谓词名称,(X1,X2,…Xn)表示参数。参数可以有两种形式:变量和常量。例如Age(person, age)列出Age中所有的事实,Age(‘xiaoming’, 18)列出小明18岁这个事实。

Logic部分

Rules

Datalog使用规则来进行推导,H <- B1, B2, … ,Bn就是一个rules,其中H是一个atom,B1,B2…Bn表示前提条件,Bi表示子目标,逗号表示逻辑与。这个rules表示当B1、B2一直到Bn这些子目标都成立,H才能成立,本质上是霍恩子句。

image.png

求解过程(Interpretation of Datalog Rules)——枚举Body中所有关系表达式的可能取值组合,进而得到新的predicate/table。例如:

image.png

枚举Age中的事实,找到满足age >= 18的事实,组成新的谓词Adult。

image.png

对于谓词,分为两类EDB和IDB:

  • EDB(extensional database):在程序运行前,这些数据已经给定。例如上述的Age。
  • IDB(intensional database):由规则推导而来。例如上述的Adult。

Logic

And

上面也提到过,逗号表示逻辑与。

Or

逻辑或则有两种实现方式:

  1. 编写多条推到规则,但是Head要相同。例如:

    1
    2
    
    SportFan(person) <- Hobby(person, "jogging").
    SortFan(person) <- Hobby(person, "swimming").
  2. 使用 ; 分隔

    1
    
    SportFan(person) <- Hobby(person, "jogging");Hobby(person, "swimming").

or的优先级低于and,组合运用时要注意优先级,必要时要使用括号。

Not/Negation

! 表示非,例如找出不喜欢慢跑的人:

1
SportFan(person) <- !Hobby(person, "jogging").
Recursion
1
2
Reach(from, to) <- Edge(from, to).
Reach(from, to) <- Reach(from, node),Edge(node, to).

Datalog支持递归调用,例如可达性分析,如果from跟to之间有边连接,则from可达to。如果from跟to没有直接的边进行连接,就可以枚举from可达的node,再判断node到to之前是否存在边。

Rule Safely

现有两条有问题的rules:

1
2
A(x) <- B(y), x > y.
A(x) <- B(y), !C(x,y).

由于x有无限的取值能满足规则,所以生成的A是一个无限大的关系。因此上述两条规则是不安全的。在Datalog中,只接受安全的规则。

如果规则中的每个变量至少在一个non-nageted relational atom中出现一次,那么这个规则是安全的。 因为已有的谓词中的事实是有限,通过这个性质来限制变量的取值范围。

1
A(x) <- B(x), !A(x)

假设B(x)为真,如果Head中的A(x)为真,那么body中的A(x)就要为假;如果Head中的A(x)为假,那么Body中的A(x)就要为真。互相矛盾了,所以不要把recursion和negation写在同一条规则里。

执行

Datalog输入EDB和Rules,经过Datalog engine不断推导,最终产生IDB。

image.png

Datalog engine有不同语言的实现,例如LogicBox, soufflé等。 所以Datalog有两大重要特性:

  • 单调性。因为事实(facts)不会被删除的。
  • 必然终止。
    • 事实的数量是单调的。
    • 由Rule Safety,所能得到的IDB的大小也是有限的。

应用

Pointer Analysis via Datalog

EDB

根据指针分析的几种行为(先排除call,在call graph中进行分析):

image.png

定义变量集合为 V,域为 F,对象为 O。

所以就有:

1
2
3
4
New(x : V, o: O) // 存在x变量与o对象这一对事实
Assign(x : V, y : V) // x变量与y变量这一对事实
Store(x : V, f : F, y : V)
Load(y : V, x : V, f : F)

IDB

1
2
VarPointsTo(v: V, o: O) // o 属于 pt(v)
FieldPointsTo(oi: O, f: V, oj: O) // oj 属于 pt(oi.f)

rules

根据先前指针分析部分中定义的规则:

image.png

组合上述IDB与EDB,就能得出Datalog的rules:

image.png

纸上运行

根据例子,将EDB中的事实填充好:

image _2_.png

处理New语句,得到部分VarPointsTo:

image _3_.png

因为VarPointsTo中存在事实了,就可以进行递归了,下一步处理Assign:

image _4_.png

处理Store:

image _5_.png

处理Load:

image _6_.png

如果不能产生新的事实,就退出程序。实际情况下,Datalog engine不一定是这样按顺序推导,只要能够产生新的事实的rules,就能进行推导。

其他应用

例如call graph分析,请参考:

https://spa-book.pblo.gq/ch4/04-02-datalog-based-pa

摘自

  1. https://pascal-group.bitbucket.io/lectures/2020f-static-program-analysis-14.pdf
  2. https://spa-book.pblo.gq/ch4/04-02-datalog-based-pa
  3. https://anemone.top/pl-%E9%9D%99%E6%80%81%E7%A8%8B%E5%BA%8F%E5%88%86%E6%9E%90%E8%AF%BE%E7%A8%8B%E7%AC%94%E8%AE%B0%EF%BC%88Datalog%EF%BC%89/