diff --git a/README.org b/README.org index d09855e..a100a08 100644 --- a/README.org +++ b/README.org @@ -11,6 +11,12 @@ 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 - [ ] Query Language - [ ] Server - [ ] Keys (logical and indexing) diff --git a/ast.rkt b/ast.rkt index e80e974..6681a56 100644 --- a/ast.rkt +++ b/ast.rkt @@ -9,13 +9,14 @@ serializable?)) (require threading) +(provide check-local-constraints) (provide (struct+updaters-out table)) (provide fields-size) (provide (struct+updaters-out procedure)) (provide (struct+updaters-out fyeld)) +(provide (struct+updaters-out integer32)) (provide (struct+updaters-out type)) (provide stringl) -(provide integer32) (require (only-in RacketowerDB/util define-serializable entity-structs)) (require (submod RacketowerDB/util interfaces)) (require (submod RacketowerDB/util hashable)) @@ -93,8 +94,12 @@ (+ acc size))) 0 fields-values))) +(define (check-local-constraints table rows) + (let ((constraints (table-local-constraints table))) + (andmap (lambda (constraint) ((eval-syntax constraint) rows)) constraints))) + (define-serializable table - (identifier row-id fields) #:transparent + (identifier row-id fields local-constraints) #:transparent #:methods gen:identifiable [(define (give-identifier self) (table-identifier self))] diff --git a/main.rkt b/main.rkt index 27ec988..f2f6bd6 100644 --- a/main.rkt +++ b/main.rkt @@ -13,44 +13,64 @@ (require racket/base) (require racket/serialize) (require racket/class) + (require (rename-in RacketowerDB/ast (procedure? procedura?))) (require (submod RacketowerDB/io writer)) (require (submod RacketowerDB/io reader)) ;; (require (submod RacketowerDB/language parser)) (require (submod RacketowerDB/backend server)) (require RacketowerDB/util) - (require (except-in RacketowerDB/ast procedure?)) - + (dynamic-require 'RacketowerDB/ast 0) + (let* ((field-name (fyeld 0 (type 'VARCHAR 7))) (field-editor (fyeld 1 (type 'VARCHAR 5))) (field-year (fyeld 1 (type 'INTEGER 4))) - (programmer-table (table "table" 0 (make-hash `(("NAME" . ,field-name) - ("EDITOR" . ,field-editor))))) - (car-table (table "table" 0 (make-hash `(("MODEL" . ,field-name) - ("YEAR" . ,field-year))))) + (field-age (fyeld 2 (type 'INTEGER 4))) + (constraint-1 + #`(lambda (rows) + (andmap (lambda (row) + (andmap (lambda (raw-field) + (let ((raw-name (car raw-field)) + (raw-value (cdr raw-field))) + (if (equal? raw-name "AGE") + (>= (integer32-value raw-value) 50) + #t))) row)) rows))) + (programmer-table (table + "table" + 0 + (make-hash `(("NAME" . ,field-name) + ("AGE" . ,field-age) + ("EDITOR" . ,field-editor))) + (list constraint-1))) + ; (car-table (table "table" 0 (make-hash `(("MODEL" . ,field-name) + ; ("YEAR" . ,field-year))))) (procedure-test (procedure "procedure")) (schema (make-hash (list))) (row1 `(("NAME" . ,(stringl "Nathan")) - ("EDITOR" . ,(stringl "Visual Studio Code")))) + ("EDITOR" . ,(stringl "Visual Studio Code")) + ("AGE" . ,(integer32 123)))) (row2 `(("NAME" . ,(stringl "Lemos")) - ("EDITOR" . ,(stringl "Emacs")))) + ("EDITOR" . ,(stringl "Emacs")) + ("AGE" . ,(integer32 100)))) (row3 `(("MODEL" . ,(stringl "Ford")) ("YEAR" . ,(integer32 1999)))) (row4 `(("MODEL" . ,(stringl "Abc")) ("YEAR" . ,(integer32 2013))))) - (hash-set! schema "CAR" car-table) - (hash-set! schema "TEST" procedure-test) - (hash-set! schema "PROGRAMMER" programmer-table) - (write-schema-to-disk schema) - (set! schema (read-schema-from-disk "schema")) - (println schema) - (set! schema (write-rows-to-disk schema "PROGRAMMER" (list row1 row2))) - (println (read-table-values-from-disk schema "PROGRAMMER")) - (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)))) + (check-local-constraints programmer-table (list row1 row2)) +; (hash-set! schema "CAR" car-table) +; (hash-set! schema "TEST" procedure-test) +; (hash-set! schema "PROGRAMMER" programmer-table) +; (write-schema-to-disk schema) +; (set! schema (read-schema-from-disk "schema")) +; (println schema) +; (set! schema (write-rows-to-disk schema "PROGRAMMER" (list row1 row2))) +; (println (read-table-values-from-disk schema "PROGRAMMER")) +; (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)) + )) ;; (exit-handler) ;; (server-entrypoint) diff --git a/samples/constraints.sql b/samples/constraints.sql new file mode 100644 index 0000000..38674ae --- /dev/null +++ b/samples/constraints.sql @@ -0,0 +1,16 @@ +CREATE RELATION Person( + age INTEGER CHECK age >= 0 && age != 5, + name VARCHAR(64), + document_number DOCUMENT_NUMBER document_number = (name + (DATE_NOW() - age)), + KEY(document_number), + UNIQUE (age, name, document_number), + CHECK function_check_if_no_person_with_age_5() +); + +KEY -> HASH document_number -> rowId +UNIQUE -> HASH (age, name, document_number) -> rowId + +RowId = 1 (1,"Lemos","Lemos-2022") +RowId = 2 (1,"Marinho","Marinho-2022") +RowId = 3 (1,"Magueta","Magueta-2022") +