aboutsummaryrefslogtreecommitdiffstats
path: root/proof/drl_verified.ml
blob: f4c282a96752cbfe799f6214afee14fd34daa298 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
(** val negb : bool -> bool **)

let negb = function
| true -> false
| false -> true

(** val fst : ('a1 * 'a2) -> 'a1 **)

let fst = function
| (x, _) -> x

(** val snd : ('a1 * 'a2) -> 'a2 **)

let snd = function
| (_, y) -> y

(** val app : 'a1 list -> 'a1 list -> 'a1 list **)

let rec app l m =
  match l with
  | [] -> m
  | a :: l1 -> a :: (app l1 m)

(** val map : ('a1 -> 'a2) -> 'a1 list -> 'a2 list **)

let rec map f = function
| [] -> []
| a :: l0 -> (f a) :: (map f l0)

(** val firstn : int -> 'a1 list -> 'a1 list **)

let rec firstn n l =
  (fun fO fS n -> if n=0 then fO () else fS (n-1))
    (fun _ -> [])
    (fun n0 -> match l with
               | [] -> []
               | a :: l0 -> a :: (firstn n0 l0))
    n

(** val flat_map : ('a1 -> 'a2 list) -> 'a1 list -> 'a2 list **)

let rec flat_map f = function
| [] -> []
| x :: l0 -> app (f x) (flat_map f l0)

(** val existsb : ('a1 -> bool) -> 'a1 list -> bool **)

let rec existsb f = function
| [] -> false
| a :: l0 -> (||) (f a) (existsb f l0)

(** val forallb : ('a1 -> bool) -> 'a1 list -> bool **)

let rec forallb f = function
| [] -> true
| a :: l0 -> (&&) (f a) (forallb f l0)

(** val filter : ('a1 -> bool) -> 'a1 list -> 'a1 list **)

let rec filter f = function
| [] -> []
| x :: l0 -> if f x then x :: (filter f l0) else filter f l0

(** val find : ('a1 -> bool) -> 'a1 list -> 'a1 option **)

let rec find f = function
| [] -> None
| x :: tl -> if f x then Some x else find f tl

(** val eqb : char list -> char list -> bool **)

let rec eqb s1 s2 =
  match s1 with
  | [] -> (match s2 with
           | [] -> true
           | _::_ -> false)
  | c1::s1' ->
    (match s2 with
     | [] -> false
     | c2::s2' -> if (=) c1 c2 then eqb s1' s2' else false)

(** val append : char list -> char list -> char list **)

let rec append s1 s2 =
  match s1 with
  | [] -> s2
  | c::s1' -> c::(append s1' s2)

type attr_name = char list

type domain_name = char list

type schema = (attr_name * domain_name) list

(** val has_attr : attr_name -> schema -> bool **)

let has_attr a s =
  existsb (fun p -> eqb a (fst p)) s

(** val attr_names : schema -> attr_name list **)

let attr_names s =
  map fst s

(** val filter_schema : attr_name list -> schema -> schema **)

let filter_schema attrs s =
  filter (fun p -> existsb (eqb (fst p)) attrs) s

(** val merge_schema : schema -> schema -> schema **)

let merge_schema s1 s2 =
  app s1 (filter (fun p -> negb (has_attr (fst p) s1)) s2)

(** val remove_attrs : attr_name list -> schema -> schema **)

let remove_attrs attrs s =
  filter (fun p -> negb (existsb (eqb (fst p)) attrs)) s

(** val rename_in_schema :
    (attr_name * attr_name) list -> schema -> schema **)

let rename_in_schema renames s =
  map (fun p ->
    let a = fst p in
    let d = snd p in
    (match find (fun r -> eqb a (fst r)) renames with
     | Some p0 -> let (_, a') = p0 in (a', d)
     | None -> (a, d)))
    s

type value (* AXIOM TO BE REALIZED *)

(** val value_eqb : value -> value -> bool **)

let value_eqb =
  failwith "AXIOM TO BE REALIZED (Sakura.Relation.value_eqb)"

type tuple = (attr_name * value) list

(** val tuple_lookup : attr_name -> tuple -> value option **)

let rec tuple_lookup a = function
| [] -> None
| p :: rest ->
  let (a', v) = p in if eqb a a' then Some v else tuple_lookup a rest

(** val project_tuple : attr_name list -> tuple -> tuple **)

let project_tuple attrs t =
  filter (fun p -> existsb (eqb (fst p)) attrs) t

(** val rename_tuple : (attr_name * attr_name) list -> tuple -> tuple **)

let rename_tuple renames t =
  map (fun p ->
    let a = fst p in
    let v = snd p in
    (match find (fun r -> eqb a (fst r)) renames with
     | Some p0 -> let (_, a') = p0 in (a', v)
     | None -> (a, v)))
    t

(** val merge_tuples : tuple -> tuple -> tuple **)

let merge_tuples t1 t2 =
  app t1 (filter (fun p -> negb (existsb (eqb (fst p)) (map fst t1))) t2)

(** val tuples_agree_on : attr_name list -> tuple -> tuple -> bool **)

let tuples_agree_on attrs t1 t2 =
  forallb (fun a ->
    match tuple_lookup a t1 with
    | Some v1 ->
      (match tuple_lookup a t2 with
       | Some v2 -> value_eqb v1 v2
       | None -> false)
    | None -> (match tuple_lookup a t2 with
               | Some _ -> false
               | None -> true))
    attrs

type relation = { rel_name : char list; rel_schema : schema;
                  rel_tuples : tuple list }

type database = (char list * relation) list

(** val db_lookup : char list -> database -> relation option **)

let rec db_lookup name = function
| [] -> None
| p :: rest ->
  let (n, r) = p in if eqb name n then Some r else db_lookup name rest

type literal =
| LitInt of int
| LitStr of char list
| LitBool of bool

type query =
| Base of char list
| Const of (attr_name * literal) list
| Select of query * query
| Join of attr_name list * query * query
| Cartesian of query * query
| Project of attr_name list * query
| Rename of (attr_name * attr_name) list * query
| Union of query * query
| Diff of query * query
| Take of int * query

(** val predicted_schema : database -> query -> schema option **)

let rec predicted_schema db = function
| Base name ->
  (match db_lookup name db with
   | Some r -> Some r.rel_schema
   | None -> None)
| Const pairs ->
  Some
    (map (fun p -> ((fst p),
      ('a'::('b'::('s'::('t'::('r'::('a'::('c'::('t'::[])))))))))) pairs)
| Select (_, source) -> predicted_schema db source
| Join (attrs, q1, q2) ->
  (match predicted_schema db q1 with
   | Some s1 ->
     (match predicted_schema db q2 with
      | Some s2 ->
        Some
          (merge_schema s1
            (remove_attrs (attr_names s1) (remove_attrs attrs s2)))
      | None -> None)
   | None -> None)
| Cartesian (q1, q2) ->
  (match predicted_schema db q1 with
   | Some s1 ->
     (match predicted_schema db q2 with
      | Some s2 -> Some (merge_schema s1 s2)
      | None -> None)
   | None -> None)
| Project (attrs, q') ->
  (match predicted_schema db q' with
   | Some s -> Some (filter_schema attrs s)
   | None -> None)
| Rename (renames, q') ->
  (match predicted_schema db q' with
   | Some s -> Some (rename_in_schema renames s)
   | None -> None)
| Union (q1, _) -> predicted_schema db q1
| Diff (q1, _) -> predicted_schema db q1
| Take (_, q') -> predicted_schema db q'

(** val literal_to_value : literal -> value **)

let literal_to_value =
  failwith "AXIOM TO BE REALIZED (Sakura.Drl.literal_to_value)"

(** val eval_const : (attr_name * literal) list -> relation **)

let eval_const pairs =
  let tuple0 = map (fun p -> ((fst p), (literal_to_value (snd p)))) pairs in
  let sch =
    map (fun p -> ((fst p),
      ('a'::('b'::('s'::('t'::('r'::('a'::('c'::('t'::[])))))))))) pairs
  in
  { rel_name = ('c'::('o'::('n'::('s'::('t'::[]))))); rel_schema = sch;
  rel_tuples = (tuple0 :: []) }

(** val semijoin : relation -> relation -> relation **)

let semijoin filter_rel source =
  let common =
    filter (fun a -> has_attr a filter_rel.rel_schema)
      (attr_names source.rel_schema)
  in
  let matches = fun t ->
    existsb (fun ft -> tuples_agree_on common t ft) filter_rel.rel_tuples
  in
  { rel_name = source.rel_name; rel_schema = source.rel_schema; rel_tuples =
  (filter matches source.rel_tuples) }

(** val equijoin : attr_name list -> relation -> relation -> relation **)

let equijoin attrs left right =
  let joined =
    flat_map (fun lt ->
      flat_map (fun rt ->
        if tuples_agree_on attrs lt rt then (merge_tuples lt rt) :: [] else [])
        right.rel_tuples)
      left.rel_tuples
  in
  let new_schema =
    merge_schema left.rel_schema
      (remove_attrs (attr_names left.rel_schema)
        (remove_attrs attrs right.rel_schema))
  in
  { rel_name =
  (append ('j'::('o'::('i'::('n'::('_'::[])))))
    (append left.rel_name (append ('_'::[]) right.rel_name)));
  rel_schema = new_schema; rel_tuples = joined }

(** val cartesian : relation -> relation -> relation **)

let cartesian left right =
  let joined =
    flat_map (fun lt -> map (fun rt -> merge_tuples lt rt) right.rel_tuples)
      left.rel_tuples
  in
  { rel_name =
  (append ('c'::('a'::('r'::('t'::('_'::[])))))
    (append left.rel_name (append ('_'::[]) right.rel_name)));
  rel_schema = (merge_schema left.rel_schema right.rel_schema); rel_tuples =
  joined }

(** val project : attr_name list -> relation -> relation **)

let project attrs r =
  { rel_name = (append ('p'::('r'::('o'::('j'::('_'::[]))))) r.rel_name);
    rel_schema = (filter_schema attrs r.rel_schema); rel_tuples =
    (map (project_tuple attrs) r.rel_tuples) }

(** val rename : (attr_name * attr_name) list -> relation -> relation **)

let rename renames r =
  { rel_name =
    (append ('r'::('e'::('n'::('a'::('m'::('e'::('_'::[]))))))) r.rel_name);
    rel_schema = (rename_in_schema renames r.rel_schema); rel_tuples =
    (map (rename_tuple renames) r.rel_tuples) }

(** val rel_union : relation -> relation -> relation **)

let rel_union r1 r2 =
  { rel_name =
    (append ('u'::('n'::('i'::('o'::('n'::('_'::[]))))))
      (append r1.rel_name (append ('_'::[]) r2.rel_name)));
    rel_schema = r1.rel_schema; rel_tuples =
    (app r1.rel_tuples r2.rel_tuples) }

(** val rel_diff : relation -> relation -> relation **)

let rel_diff r1 r2 =
  let in_r2 = fun t ->
    existsb (fun t2 -> tuples_agree_on (attr_names r1.rel_schema) t t2)
      r2.rel_tuples
  in
  { rel_name =
  (append ('d'::('i'::('f'::('f'::('_'::[])))))
    (append r1.rel_name (append ('_'::[]) r2.rel_name)));
  rel_schema = r1.rel_schema; rel_tuples =
  (filter (fun t -> negb (in_r2 t)) r1.rel_tuples) }

(** val take : int -> relation -> relation **)

let take n r =
  { rel_name = (append ('t'::('a'::('k'::('e'::('_'::[]))))) r.rel_name);
    rel_schema = r.rel_schema; rel_tuples = (firstn n r.rel_tuples) }

(** val eval : database -> query -> relation option **)

let rec eval db = function
| Base name -> db_lookup name db
| Const pairs -> Some (eval_const pairs)
| Select (filter_q, source_q) ->
  (match eval db filter_q with
   | Some filter_rel ->
     (match eval db source_q with
      | Some source_rel -> Some (semijoin filter_rel source_rel)
      | None -> None)
   | None -> None)
| Join (attrs, q1, q2) ->
  (match eval db q1 with
   | Some r1 ->
     (match eval db q2 with
      | Some r2 -> Some (equijoin attrs r1 r2)
      | None -> None)
   | None -> None)
| Cartesian (q1, q2) ->
  (match eval db q1 with
   | Some r1 ->
     (match eval db q2 with
      | Some r2 -> Some (cartesian r1 r2)
      | None -> None)
   | None -> None)
| Project (attrs, q') ->
  (match eval db q' with
   | Some r -> Some (project attrs r)
   | None -> None)
| Rename (renames, q') ->
  (match eval db q' with
   | Some r -> Some (rename renames r)
   | None -> None)
| Union (q1, q2) ->
  (match eval db q1 with
   | Some r1 ->
     (match eval db q2 with
      | Some r2 -> Some (rel_union r1 r2)
      | None -> None)
   | None -> None)
| Diff (q1, q2) ->
  (match eval db q1 with
   | Some r1 ->
     (match eval db q2 with
      | Some r2 -> Some (rel_diff r1 r2)
      | None -> None)
   | None -> None)
| Take (n, q') ->
  (match eval db q' with
   | Some r -> Some (take n r)
   | None -> None)