;; The first three lines of this file were inserted by DrRacket. They record metadata
;; about the language level of this file in a form that our tools can easily process.
#reader(lib "htdp-intermediate-lambda-reader.ss" "lang")((modname database) (read-case-sensitive #t) (teachpacks ((lib "image.rkt" "teachpack" "2htdp") (lib "universe.rkt" "teachpack" "2htdp") (lib "batch-io.rkt" "teachpack" "2htdp") (lib "web-io.rkt" "teachpack" "2htdp") (lib "dir.rkt" "teachpack" "htdp"))) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ((lib "image.rkt" "teachpack" "2htdp") (lib "universe.rkt" "teachpack" "2htdp") (lib "batch-io.rkt" "teachpack" "2htdp") (lib "web-io.rkt" "teachpack" "2htdp") (lib "dir.rkt" "teachpack" "htdp")) #f)))
(define-struct db [schema content])
; A DB is a structure: (make-db Schema Content)
; A Schema is a [List-of Spec]
; A Spec is a [List Label Predicate]
; A Label is a String
; A Predicate is a [Any -> Boolean]
; A (piece of) Content is a [List-of Row]
; A Row is a [List-of Cell]
; A Cell is Any
; constraint cells do not contain functions
; integrity constraint In (make-db sch con),
; for every row in con,
; (I1) its length is the same as sch's, and
; (I2) its ith Cell satisfies the ith Predicate in sch
(define-struct spec [label predicate])
; Spec is a structure: (make-spec Label Predicate)
(define db1 (make-db (list (list "Name" string?)
(list "Age" integer?)
(list "Present" boolean?))
'(("Alice" 35 #true) ("Bob" 25 #false))))
(make-db '((make-spec "Name" String?)
(make-spec "Age" Integer)
(make-spec "Present" Boolean))
'(("Alice" 35 #true) ("Bob" 25 #false)))
; Exercise 404
; f [List-of N][List-of N] -> Boolean
; comparision two values from two list
(check-expect (andmap2 (lambda(s c) [(second s) c])
(list (list "name" string?) (list "age" number?)) '("a" 1))
#true)
(define (andmap2 f l1 l2)
(cond
[(empty? l1) #true]
[(cons? l1) (and (f (first l1) (first l2))
(andmap2 f (rest l1) (rest l2)))]))
; DB -> Boolean
; do all rows in db satisfy (I1) and (I2)
(check-expect (integrity-check db1) #true)
(define (integrity-check db)
(local (; Row -> Boolean
; does row satisfy (I1) and (I2)
(define (row-integrity-check row)
(and (= (length row)
(length (db-schema db)))
(andmap (lambda (s c) [(second s) c])
(db-schema db)
row))))
(andmap row-integrity-check (db-content db))))
(define labels '("Name" "Present"))
; Spec -> Boolean
; does this spec belong to the new schema
(define (keep? c)
(member? (first c) labels))
; Row [List-of Label] -> Row
; retains those cells whose corresponding element
; in names is also in labels
(check-expect (row-filter '("Alice" 35 #true) '("Name" "Age" "Present"))
'("Alice" #true))
(define (row-filter row names)
(cond
[(empty? row) '()]
[else (if (member? (first names) labels)
(cons (first row) (row-filter (rest row) (rest names)))
(row-filter (rest row) (rest names)))]))
; Exercise 406
(define school-schema
`(("Name" ,string?)
("Age" ,integer?)
("Present" ,boolean?)))
(define school-content
`(("Alice" 35 #true)
("Bob" 25 #false)
("Carol" 30 #true)
("Dave" 32 #false)))
(define school-db
(make-db school-schema
school-content))
; DB [List-of Label] -> DB
; retains a column from db if its label is in labels
(define projected-content
`(("Alice" #true)
("Bob" #false)
("Carol" #true)
("Dave" #false)))
(define projected-schema
`(("Name" ,string?) ("Present" ,boolean?)))
(define projected-db
(make-db projected-schema projected-content))
; Stop! Read this test carefully. What's wrong?
(check-expect (db-content (project.v1 school-db '("Name" "Present")))
projected-content)
(define (project.v1 db labels)
(local ((define schema (db-schema db))
(define content (db-content db))
(define (member*? i) (member? i labels))
; Spec -> Boolean
; does this column belong to the new schema
(define (keep? c)
(member*? (first c)))
; Row -> Row
; retains those columns whose name is in labels
(define (row-project row)
(row-filter row (map first schema)))
; Row [List-of Label] -> Row
; retains those cells whose name is in labels
(define (row-filter row names)
(cond
[(empty? names) '()]
[else
(if (member*? (first names))
(cons (first row)
(row-filter (rest row) (rest names)))
(row-filter (rest row) (rest names)))])))
(make-db (filter keep? schema)
(map row-project content))))