gdritter repos datalog / master
Summary of Datalog language deviations Getty Ritter 6 years ago
1 changed file(s) with 57 addition(s) and 16 deletion(s). Collapse all Expand all
33 standard Datalog is the existence of a simple type system for rows as
44 well as a choice of tuple- or record-structured data.
55
6 Typical datalog facts are tuple-structured:
6 # Deviation 1: Record-Structured Data
7
8 Any place where Datalog uses tuple-structured data (i.e. where you
9 have comma-separated expressions in between parentheses) you can also
10 use record-structured data, which allow fields to appear in any
11 order. So the classic example
712
813 ```
9 table parent(atom, atom).
14 - parent ( terry, austin ).
1015 ```
1116
12 Facts are inserted into the database by stating them.
17 can be expressed nearly equivalently using record-structured data as
1318
1419 ```
15 parent(terry, austin).
20 - parent { parent: terry, child: austin }.
1621 ```
1722
18 Queries against this are done in the typical Datalog way:
23 Similarly, a query to find all the children of `terry` could be
24 written as
1925
2026 ```
21 ancestor(X, Y) :- parent(X, Y).
22 ancestor(X, Y) :- ancestor(X, Z), parent(Z, Y).
27 - parent { parent: terry, child: X }?
2328 ```
2429
25 However, for utility, you can also express this in a record-structured
26 way with field names. Predicates/queries can also use record
27 structures, which act as keyword arguments.
30 # Deviation 2: Static Types
31
32 Datalog facts are usually dynamically typed, but this implementation
33 requires (in part to support the syntax above) that facts and
34 predicates have a consistent statically known type. For facts, this
35 often involves a "table declaration" which dictates the structure of
36 all future facts in that table. Some table declarations might look
37 like
2838
2939 ```
30 table parent { parent : atom, child : atom }.
31 parent { parent: terry, child: austin }.
32 ancestor { parent: X, child: Y }
33 :- parent { parent: X, child: Y }.
34 ancestor { parent: X, child: Y }
35 :- ancestor { parent: X, child: Z }, parent { parent: X, child: Y }.
40 - @table edge ( integer, integer ).
41 - @table parent { parent: atom, child: atom }.
3642 ```
43
44 Queries also have static types, but these can _generally_ be inferred
45 from context in Datalog, and so do not need to be defined. If
46 necessary, though, a `query` definition can be used.
47
48 ```
49 - @query ancestor { parent: atom, child: atom }.
50 - ancestor { parent: X, child: Y}
51 :- parent { parent: X, child: Y }.
52 - ancestor { parent: X, child: Y}
53 :- parent { parent: X, child: Z},
54 ancestor { parent: X, child: Y }.
55 ```
56
57 # Deviation 3: Implicit Variables
58
59 When defining a table's type signature, we can also include a few
60 extra annotations about the meaning of that variable. For example, we
61 might want a particular field of a table to be an auto-incrementing
62 integer, so that every row would include a fresh value without us
63 having to discover it first. If we define a table with the
64 `@autoincrement` keyword, like so
65
66 ```
67 - @table person { id: integer @autoincrement, name: string }.
68 ```
69
70 then we can use the placeholder `@auto` value, which mean Datalog will
71 examine the table to find the necessary "next" value.
72
73 ```
74 - person { id: @auto, name: "alice" }.
75 - person { id: @auto, name: "bob" }.
76 - person { id: @auto, name: "carol" }.
77 ```