Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Test Suite #22

Merged
merged 9 commits into from
Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ jobs:
run: raco pkg install --auto --batch
- name: Check compilation
run: raco exe --gui main.rkt
- name: Create C lib for FFI
run: gcc -c -fPIC utilities/bplustree.c -o utilities/bplustree.o && gcc utilities/bplustree.o -shared -o libbplustree.so
- name: Check test
run: raco test main.rkt
48 changes: 37 additions & 11 deletions README.org
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#+TITLE: Racket Tower DB 🎾 🏰

* About
This is a toy database :)
This is a toy relational database using unclustered indexing for queries.

It is written in Racket for us to be able to practice Scheme lisp and also leverage the
ecosystem.

Do not use it professionally (it's always good to warn).

Expand All @@ -11,18 +13,42 @@ Do not use it professionally (it's always good to warn).
- [X] Write the logical schema onto disk
- [X] Reads of tables and schemas
- [X] Persistent storage
- [ ] Constraints
+ [ ] Add row-id to row reading from the disk
+ [ ] Add local constraints to table struct
+ [ ] Do a proof of concept using the backticked lambdas for local constraints
+ [ ] Do a proof of concept using the hashed values for set constraints
+ [ ] Add a serialization for constraints
- [X] Constraints
+ [X] Add row-id to row reading from the disk
+ [X] Add local constraints to table struct
+ [X] Do a proof of concept using the backticked lambdas for local constraints
+ [X] Do a proof of concept using the hashed values for set constraints
+ [X] Add a serialization for constraints
- [X] Keys (logical and indexing)
- [X] Internal tooling for searches
** RacketowerDB 2.0 [0/3]
- [ ] Query Language
- [ ] Improve searching with different types
- [ ] Server
- [ ] Keys (logical and indexing)
- [ ] Internal tooling for searches
** RacketowerDB 2.0 [0/3]
- [ ] Procedures
- [ ] Transactions
- [ ] Cascading

* How to use RacketowerDB

** Nix

#+begin_src shell
> nix develop
> just run
> just test
#+end_src

** Guix

TODO

** Developers

- EduardoLR10
- MMagueta
- z-silver

* Dr.Nekoma

Built live on [[https://www.twitch.tv/drnekoma][Twitch]] and archived on [[https://youtube.com/playlist?list=PLafNlGaxdt65iwFNDtAG-WXsoRoi-ZJmx&si=he3YkzRNaUHYsyOr][Youtube]].
19 changes: 15 additions & 4 deletions ast.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
(case (type-name self)
[[INTEGER] (integer32 (integer-bytes->integer byte-stream #t))]
[[VARCHAR] (stringl (bytes->string/utf-8 byte-stream))]
[else (raise 'error-with-unknown-type-from-bytes)])
(raise 'error-with-from-bytes-size-check))))
[else (error "Unknown type. Supported types: INTEGER and VARCHAR")])
(error "Unmatch between type byte size and bytes from byte stream"))))
(define (to-byte-size self)
(type-byte-size self))]
#:methods gen:serializable
Expand All @@ -56,11 +56,22 @@
(byte-size-value (integer-bytes->integer (subbytes byte-stream (+ 1 name-length)) #t))]
(type name-value byte-size-value)))])

(define (stringl-trim string-1)
(string-trim (stringl-value string-1) "\u0000" #:left? false #:repeat? #t))

(define (stringl-equal string-1 string-2 recur-equal)
(recur-equal (stringl-trim string-1)
(stringl-trim string-2)))

(define-serializable stringl [value] #:transparent
#:guard
(checked-guard
[(value . string?)]
value)
#:methods gen:equal+hash
[(define equal-proc stringl-equal)
(define hash-proc (lambda (stringl rec-hash) (rec-hash (stringl-trim stringl))))
(define hash2-proc (lambda (stringl rec-hash) (rec-hash (stringl-trim stringl))))]
#:methods gen:serializable
[(define (serialize self #:size [size #f])
(unless size
Expand Down Expand Up @@ -136,7 +147,7 @@
(cond
[(table? entity) entity]
[(procedure? entity)
(error "Don't write procedures yet")])))
(error (format "Found procedure ~s instead of a table" table-name))])))

(define (table-column-value table table-name column-name)
(define (column-name-message column-name)
Expand Down Expand Up @@ -179,7 +190,7 @@
(bytes-append constraint-size serialized-constraint)))
(define constraints-count (length constraint-list))
(unless (<= constraints-count #xff)
(raise 'using-more-constraints-than-supported))
(error "Using more than supported constraints (max 255"))
EduardoLR10 marked this conversation as resolved.
Show resolved Hide resolved
(let [(serialized-count (integer->integer-bytes constraints-count 1 #f))
(serialized-constraints (bytes-join (map serialize-constraint constraint-list) #""))]
(bytes-append serialized-count serialized-constraints)))
Expand Down
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ docs NAME:
raco docs {{ NAME }}

test:
EduardoLR10 marked this conversation as resolved.
Show resolved Hide resolved
raco test
raco test main.rkt
138 changes: 71 additions & 67 deletions main.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,12 @@

(module+ test
(require rackunit)
;; Any code in this `test` submodule runs when this file is run using DrRacket
;; or with `raco test`. The code here does not run when this file is
;; required by another module.

(check-equal? (+ 2 2) 4))

;; http://docs.racket-lang.org/guide/Module_Syntax.html#%28part._main-and-test%29
(module+ main


(define field-name (field 0 (type 'VARCHAR 7)))
(define field-editor (field 1 (type 'VARCHAR 10)))
(define field-year (field 1 (type 'INTEGER 4)))
(define field-age (field 2 (type 'INTEGER 4)))


(define constraint-1
#`(lambda [rows]
(andmap
Expand All @@ -39,7 +30,7 @@
(let [(raw-name (car raw-field))
(raw-value (cdr raw-field))]
(if (equal? raw-name "AGE")
(>= (integer32-value raw-value) 50)
(<= (integer32-value raw-value) 50)
#t)))
row))
rows)))
Expand Down Expand Up @@ -74,81 +65,94 @@
(define procedure-test (procedure "procedure"))
(define schema (make-hash (list)))

(define row0
`(("NAME" . ,(stringl "Marinho"))
("EDITOR" . ,(stringl "Kakoune"))
("AGE" . ,(integer32 29))))

(define row1
`(("NAME" . ,(stringl "Nathan"))
("EDITOR" . ,(stringl "Visual Studio Code"))
("AGE" . ,(integer32 100))))
("AGE" . ,(integer32 23))))

(define row2
`(("NAME" . ,(stringl "Lemos"))
("EDITOR" . ,(stringl "Emacs"))
("AGE" . ,(integer32 100))))
("AGE" . ,(integer32 24))))

(define row3
`(("MODEL" . ,(stringl "Ford"))
("YEAR" . ,(integer32 1996))))
`(("NAME" . ,(stringl "Magueta"))
("EDITOR" . ,(stringl "Emacs"))
("AGE" . ,(integer32 24))))

(define row4
`(("MODEL" . ,(stringl "Abcd"))
("YEAR" . ,(integer32 1999))))
`(("MODEL" . ,(stringl "Model X"))
("YEAR" . ,(integer32 2015))))

(define row5
`(("MODEL" . ,(stringl "asdf"))
("YEAR" . ,(integer32 1996))))
`(("MODEL" . ,(stringl "Model S"))
("YEAR" . ,(integer32 2012))))

(define row6
`(("MODEL" . ,(stringl "jkl;"))
("YEAR" . ,(integer32 1997))))
`(("MODEL" . ,(stringl "R1S"))
("YEAR" . ,(integer32 2021))))

(define row7
`(("MODEL" . ,(stringl "Mach 6"))
("YEAR" . ,(integer32 1997))))

(define row8
`(("MODEL" . ,(stringl "qwer"))
("YEAR" . ,(integer32 1997))))
`(("MODEL" . ,(stringl "Beetle"))
("YEAR" . ,(integer32 1938))))

(define row9
(define row8
`(("MODEL" . ,(stringl "Mach 5"))
("YEAR" . ,(integer32 1997))))

(define row10
`(("MODEL" . ,(stringl "Tesla"))
("YEAR" . ,(integer32 2020))))
("YEAR" . ,(integer32 1967))))

(define row11
`(("MODEL" . ,(stringl "Honda"))
("YEAR" . ,(integer32 1996))))

(define row9
`(("MODEL" . ,(stringl "Mach 6"))
("YEAR" . ,(integer32 1967))))
(hash-set! schema "PROGRAMMER" programmer-table)
(hash-set! schema "CAR" car-table)
(set! schema (write-rows-to-disk schema "CAR" (list row3 row4 row5 row6 row7 row8 row9 row10 row11)))
(set! schema (write-rows-to-disk schema "PROGRAMMER" (list row1 row2)))
;; (println (read-table-values-from-disk schema "PROGRAMMER"))
;; (define-values (pages amount-already-read) (build-pages 0 1 1 (+ 7 10 4) 0 "AGE" schema "PROGRAMMER"))
(println (search schema (query "PROGRAMMER" "AGE" 100)))
;; (check-local-constraints programmer-table (list row1 row2))
;; (hash-set! schema "TEST" procedure-test)
;; (write-schema-to-disk schema)
;; (set! schema (read-schema-from-disk "schema"))
;; (check-local-constraints (hash-ref schema "PROGRAMMER") (list row1 row2))
;; (println schema)
;; (write-table-to-disk programmer-table "PROGRAMMER")
;; (let ((read-table (read-table-from-disk "PROGRAMMER")))
;; (hash-set! schema "PROGRAMMER" read-table)
;; (set! schema (write-rows-to-disk schema "PROGRAMMER" (list row1 row2)))
;; (println schema))
;; (tree-test)
)

;;(exit-handler)
;;(server-entrypoint)

;;(require racket/cmdline)
;;(define who (box "world"))
;;(command-line
;; #:program "my-program"
;; #:once-each
;; [("-n" "--name") name "Who to say hello to" (set-box! who name)]
;; #:args ()
;; (printf "hello ~a~n" (unbox who))))
(define programmer-list (list row0 row1 row2 row3))
(define car-list (list row4 row5 row6 row7 row8 row9))

(test-case
"Write mocked data into disk with PROGRAMMER table"
(set! schema (write-rows-to-disk schema "PROGRAMMER" programmer-list))
(check-equal? (table-row-id (hash-ref schema "PROGRAMMER")) 4))

(test-case
"Write mocked data into disk with CAR table"
(set! schema (write-rows-to-disk schema "CAR" car-list))
(check-equal? (table-row-id (hash-ref schema "CAR")) 6))

(test-case
"Read written data from disk with CAR table"
(check-equal? (read-table-values-from-disk schema "CAR") (map make-hash car-list)))

(test-case
"Check for constraints in the PROGRAMMER table"
(check-true (check-local-constraints (hash-ref schema "PROGRAMMER") programmer-list)))

(test-case
"Check writing schema into disk"
(write-schema-to-disk schema)
(check-match (read-schema-from-disk "schema") schema))

(test-case
"Check writing table PROGRAMMER into disk"
(write-table-to-disk programmer-table "PROGRAMMER")
(check-match (read-table-from-disk "PROGRAMMER") programmer-table))
(test-case
"Check writing table CAR into disk"
(write-table-to-disk car-table "CAR")
(check-match (read-table-from-disk "CAR") car-table))

(test-case
"Query integer values from persisted PROGRAMMER table"
(check-equal? (search schema (query "PROGRAMMER" "AGE" 24)) (map make-hash (list row2 row3))))
(test-case
"Query integer values from persisted CAR table"
(check-equal? (search schema (query "CAR" "YEAR" 1967)) (map make-hash (list row8 row9)))))

(module+ main
(println "Welcome to RacketowerDB!")
(println "TODO: Server yet to be implemented xD"))
Binary file modified ndf/data/CAR.ndf
Binary file not shown.
Binary file modified ndf/data/PROGRAMMER.ndf
Binary file not shown.
Binary file modified ndf/entities/CAR.ndf
Binary file not shown.
Binary file modified ndf/entities/PROGRAMMER.ndf
Binary file not shown.
Binary file modified ndf/schemas/schema.ndf
Binary file not shown.
2 changes: 1 addition & 1 deletion util.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
[('entity) "ndf/entities/"]
[('schema) "ndf/schemas/"]
[('data) "ndf/data/"]
[else (raise 'error-not-specified-datatype)]))]
[else (error (format "Unknown data type for filename creation: ~a" data?))]))]
(string-append path (string-append name ".ndf"))))

(define (chunk-by-size chunk-size elements)
Expand Down
Loading