diff --git a/ast.rkt b/ast.rkt index 6681a56..c3d8c28 100644 --- a/ast.rkt +++ b/ast.rkt @@ -1,121 +1,118 @@ #lang racket -(require racket/class) -(require struct-update) -(require racket/generic) -(require (except-in racket/serialize - serialize - deserialize - serializable?)) -(require threading) +(provide + check-local-constraints + (struct+updaters-out table) + fields-size + (struct+updaters-out procedure) + (struct+updaters-out field) + (struct+updaters-out integer32) + (struct+updaters-out type) + stringl) -(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) -(require (only-in RacketowerDB/util define-serializable entity-structs)) -(require (submod RacketowerDB/util interfaces)) -(require (submod RacketowerDB/util hashable)) +(require + struct-update + racket/generic + threading + (only-in RacketowerDB/util define-serializable entity-structs) + (submod RacketowerDB/util interfaces) + (submod RacketowerDB/util hashable)) -(define-serializable type - (name byte-size) #:transparent +(define-serializable type [name byte-size] #:transparent #:methods gen:byteable - [(define (from-bytes self byte-stream) - (let ((received-bytes-size (bytes-length byte-stream))) - (if (equal? received-bytes-size (type-byte-size self)) - (case (list 'quote (string->symbol (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)))) - (define (to-byte-size self) - (type-byte-size self))] + [(define (from-bytes self byte-stream) + (let [(received-bytes-size (bytes-length byte-stream))] + (if (equal? received-bytes-size (type-byte-size self)) + (case (list 'quote (string->symbol (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)))) + (define (to-byte-size self) + (type-byte-size self))] #:methods gen:serializable - [(define (serialize self #:size [_size #f]) - (let* ((name-bytes (string->bytes/utf-8 (symbol->string (type-name self)))) - (name-length (integer->integer-bytes (bytes-length name-bytes) 1 #t)) - (byte-size-bytes (integer->integer-bytes (type-byte-size self) 4 #t))) - (bytes-append name-length name-bytes byte-size-bytes))) - (define (deserialize _self byte-stream) - (let* ((name-length (integer-bytes->integer (make-bytes 1 (bytes-ref byte-stream 0)) #t)) - (name-value (bytes->string/utf-8 (subbytes byte-stream 1 (+ 1 name-length)))) - (byte-size-value (integer-bytes->integer (subbytes byte-stream (+ 1 name-length) (+ 3 name-length)) #t))) - (values (type name-value byte-size-value) (+ 5 name-length))))]) + [(define (serialize self #:size [_size #f]) + (let* [(name-bytes (string->bytes/utf-8 (symbol->string (type-name self)))) + (name-length (integer->integer-bytes (bytes-length name-bytes) 1 #t)) + (byte-size-bytes (integer->integer-bytes (type-byte-size self) 4 #t))] + (bytes-append name-length name-bytes byte-size-bytes))) + (define (deserialize _self byte-stream) + (let* [(name-length (integer-bytes->integer (make-bytes 1 (bytes-ref byte-stream 0)) #t)) + (name-value (bytes->string/utf-8 (subbytes byte-stream 1 (+ 1 name-length)))) + (byte-size-value (integer-bytes->integer (subbytes byte-stream (+ 1 name-length) (+ 3 name-length)) #t))] + (values (type name-value byte-size-value) (+ 5 name-length))))]) -(define-serializable stringl - (value) #:transparent +(define-serializable stringl [value] #:transparent #:methods gen:serializable [(define (serialize self #:size [size #f]) - (unless size (error "size is required")) - (let* ((value (stringl-value self)) - (size-of-string (string-length value))) - (if (< size size-of-string) - (string->bytes/utf-8 (substring value 0 size)) ;; Truncate - (let ((dest-bytes (make-bytes size 0)) - (serialyzed-string (string->bytes/utf-8 value))) - (bytes-copy! dest-bytes 0 serialyzed-string) - dest-bytes)))) + (unless size + (error "size is required")) + (let* [(value (stringl-value self)) + (size-of-string (string-length value))] + (if (< size size-of-string) + (string->bytes/utf-8 (substring value 0 size)) ;; Truncate + (let [(dest-bytes (make-bytes size 0)) + (serialyzed-string (string->bytes/utf-8 value))] + (bytes-copy! dest-bytes 0 serialyzed-string) + dest-bytes)))) (define (deserialize _self byte-stream) (values (stringl (string-trim (bytes->string/utf-8 byte-stream)) (bytes-length byte-stream))))]) -(define-serializable integer32 - (value) #:transparent +(define-serializable integer32 [value] #:transparent #:methods gen:serializable - [(define (serialize self #:size [_size #f]) - (integer->integer-bytes (integer32-value self) 4 #t)) - (define (deserialize _self byte-stream) - (values (integer32 (integer-bytes->integer (subbytes byte-stream 0 4) #t)) 4))]) + [(define (serialize self #:size [_size #f]) + (integer->integer-bytes (integer32-value self) 4 #t)) + (define (deserialize _self byte-stream) + (values (integer32 (integer-bytes->integer (subbytes byte-stream 0 4) #t)) 4))]) -(define-serializable fyeld - (position type) #:transparent +(define-serializable field [position type] #:transparent #:methods gen:serializable [(define/generic super-serialize serialize) (define (serialize self #:size [_size #f]) - (let* ((position (fyeld-position self)) + (let* [(position (field-position self)) (position-bytes (integer->integer-bytes position 1 #t)) - (type (fyeld-type self)) - (type-bytes (super-serialize type #:size (type-byte-size type)))) + (type (field-type self)) + (type-bytes (super-serialize type #:size (type-byte-size type)))] (bytes-append position-bytes type-bytes))) (define/generic super-deserialize deserialize) (define (deserialize self byte-stream) - (let* ((position-value (integer-bytes->integer (make-bytes 1 (bytes-ref byte-stream 0)) #t)) - (type-bytes (subbytes byte-stream 1))) - (define-values (new-type type-consumed) (super-deserialize struct:type type-bytes)) - (values (fyeld position-value new-type) (+ 1 type-consumed))))]) + (let* [(position-value (integer-bytes->integer (make-bytes 1 (bytes-ref byte-stream 0)) #t)) + (type-bytes (subbytes byte-stream 1))] + (define-values [new-type type-consumed] (super-deserialize struct:type type-bytes)) + (values (field position-value new-type) (+ 1 type-consumed))))]) (define (fields-size fields) - (let* ((fields-values (hash-values fields))) - (foldl (lambda (elem acc) - (let ((size (type-byte-size (fyeld-type elem)))) + (let* [(fields-values (hash-values fields))] + (foldl (lambda [elem acc] + (let [(size (type-byte-size (field-type elem)))] (+ acc size))) - 0 fields-values))) + 0 fields-values))) (define (check-local-constraints table rows) - (let ((constraints (table-local-constraints table))) - (andmap (lambda (constraint) ((eval-syntax constraint) rows)) constraints))) + (let [(constraints (table-local-constraints table))] + (andmap (lambda [constraint] + ((eval-syntax constraint) rows)) + constraints))) (define-serializable table - (identifier row-id fields local-constraints) #:transparent + [identifier row-id fields local-constraints] #:transparent #:methods gen:identifiable [(define (give-identifier self) (table-identifier self))] #:methods gen:serializable [(define (serialize self #:size [_size #f]) - (let* ((row-id (table-row-id self)) + (let* [(row-id (table-row-id self)) (row-id-bytes (integer->integer-bytes row-id 4 #t)) - (fields-list (hash->list (table-fields self)))) + (fields-list (hash->list (table-fields self)))] (bytes-append row-id-bytes (serialize-hash-list fields-list #:entity? #f)))) (define (deserialize self byte-stream) - (let* ((row-id-value (integer-bytes->integer (subbytes byte-stream 0 4) #t)) - (fields-value (make-hash (deserialize-hash-list struct:fyeld (subbytes byte-stream 4) '())))) - (values (table "table" row-id-value fields-value) (bytes-length byte-stream))))]) + (let* [(row-id-value (integer-bytes->integer (subbytes byte-stream 0 4) #t)) + (fields-value (make-hash (deserialize-hash-list struct:field (subbytes byte-stream 4) '())))] + (values + (table "table" row-id-value fields-value (list)) ;; TODO: constraints + (bytes-length byte-stream))))]) -(define-serializable procedure - (identifier) #:transparent +(define-serializable procedure [identifier] #:transparent #:methods gen:identifiable [(define (give-identifier self) (procedure-identifier self))] diff --git a/backend.rkt b/backend.rkt index e18355f..f78524c 100644 --- a/backend.rkt +++ b/backend.rkt @@ -2,24 +2,25 @@ (require racket/tcp) -(module+ server +(module+ server + (provide + server-socket + default-port) + (define default-port 8891) - + (define (server) (tcp-listen default-port)) (define (server-socket) (define listener (server)) - (define (loop) - (define-values (in out) (tcp-accept listener)) - (thread (lambda () - (let ((file-out (open-output-file "backend.log" #:exists 'can-update))) + (let loop [] + (define-values (in out) (tcp-accept listener)) + (thread + (lambda [] + (let [(file-out (open-output-file "backend.log" #:exists 'can-update))] (write (read in) file-out) (close-output-port file-out) (write "I saved your amazing message!" out) (close-output-port out)))) - (loop)) - (loop)) - - (provide server-socket) - (provide default-port)) + (loop)))) diff --git a/info.rkt b/info.rkt index f326ea8..188e722 100644 --- a/info.rkt +++ b/info.rkt @@ -3,22 +3,22 @@ (define pkg-desc "A simple database") (define version "1.0") -(define pkg-authors '(lemos magueta)) -(define license '(MIT)) +(define pkg-authors '[lemos magueta]) +(define license '[MIT]) (define deps - '("racket" + '["racket" "threading-lib" "beautiful-racket" - "struct-update-lib")) + "struct-update-lib"]) (define build-deps - '("scribble-lib" + '["scribble-lib" "racket-doc" - "rackunit-lib")) + "rackunit-lib"]) (define compile-omit-files - '("guix.scm")) + '["guix.scm"]) (define scribblings - '(("scribblings/RacketowerDB.scrbl" ()))) + '[("scribblings/RacketowerDB.scrbl" ())]) diff --git a/io.rkt b/io.rkt index 2839d15..0200b51 100644 --- a/io.rkt +++ b/io.rkt @@ -1,169 +1,170 @@ #lang racket -(require racket/base) -(require threading) -(require racket/serialize) -(require (rename-in RacketowerDB/ast (procedure? procedura?))) +(require + threading + RacketowerDB/util + (rename-in RacketowerDB/ast (procedure? procedura?)) + (submod RacketowerDB/util interfaces) + (submod RacketowerDB/util hashable)) (module+ writer - (require RacketowerDB/util) - (require (submod RacketowerDB/util interfaces)) - (require (submod RacketowerDB/util hashable)) - (require struct-update) - (provide write-rows-to-disk) - (provide write-table-to-disk) - (provide write-schema-to-disk) - + (provide + write-rows-to-disk + write-table-to-disk + write-schema-to-disk) + (define (convert-literal table attribute-name literal) - (let* ((attribute (hash-ref (table-fields table) + (let* [(attribute (hash-ref (table-fields table) attribute-name)) - (type (fyeld-type attribute)) + (type (field-type attribute)) (type-size (type-byte-size type)) - (position (fyeld-position attribute))) + (position (field-position attribute))] (cons position (serialize literal #:size type-size)))) - + (define (convert-row table row) (~> - (foldl (lambda (elem acc) + (foldl (lambda [elem acc] (cons (convert-literal table (car elem) (cdr elem)) - acc)) (list) row) - (sort _ (lambda (a b) (< (car a) (car b)))) + acc)) + (list) row) + (sort _ (lambda [a b] (< (car a) (car b)))) (map cdr _) (bytes-join _ #""))) (define (write-row-to-disk schema table-name row) - (let ((entity (hash-ref schema table-name))) + (let [(entity (hash-ref schema table-name))] (cond [(table? entity) - (let* ((converted-row (convert-row entity row)) + (let* [(converted-row (convert-row entity row)) (row-id (table-row-id entity)) (total-size (fields-size (table-fields entity))) (off-set (* row-id total-size)) - (file-name (build-ndf-filename table-name #:data? 'data))) + (file-name (build-ndf-filename table-name #:data? 'data))] (call-with-output-file file-name #:exists 'can-update - (lambda (out) + (lambda [out] (file-position out off-set) (write-bytes converted-row out))) (set! schema (update-row-id-table schema table-name (+ row-id 1))))] [(procedura? entity) (println "Don't write procedures yet")]) schema)) - + (define (write-rows-to-disk schema table-name rows) (if (empty? rows) - schema - (let* ((first-row (first rows)) - (new-schema (write-row-to-disk schema table-name first-row))) - (write-rows-to-disk new-schema table-name (rest rows))))) + schema + (let* [(first-row (first rows)) + (new-schema (write-row-to-disk schema table-name first-row))] + (write-rows-to-disk new-schema table-name (rest rows))))) (define (update-row-id-table schema table-name id) - (let ((entity (hash-ref schema table-name))) + (let [(entity (hash-ref schema table-name))] (cond [(table? entity) - (begin - (hash-set! schema table-name (table-row-id-set entity id)) - schema)] + (hash-set! schema table-name (table-row-id-set entity id)) + schema] [(procedura? entity) (raise 'tried-update-row-id-with-procedure)]))) (define (write-table-to-disk table table-name) - (let* ((serialized-table (serialize table)) - (file-name (build-ndf-filename table-name))) + (let* [(serialized-table (serialize table)) + (file-name (build-ndf-filename table-name))] (call-with-output-file file-name #:exists 'truncate - (curry write-bytes serialized-table)))) - + (curry write-bytes serialized-table)) + (void))) + (define (write-schema-to-disk schema) (define (write-entity-to-disk file-out entities-list) - (let* ((entity-name (give-identifier (cdr (car entities-list))))) + (let* [(entity-name (give-identifier (cdr (car entities-list))))] (write-string entity-name file-out) (newline file-out) (write-bytes (serialize-hash-list entities-list #:entity? #t) file-out) (newline file-out))) - (let* ((schema-list (hash->list schema)) - (file-name (build-ndf-filename "schema" #:data? 'schema))) + (let* [(schema-list (hash->list schema)) + (file-name (build-ndf-filename "schema" #:data? 'schema))] (call-with-output-file file-name #:exists 'truncate - (lambda (out) + (lambda [out] (~>> (group-by (compose give-identifier cdr) schema-list) - (map (curry write-entity-to-disk out)))))))) + (map (curry write-entity-to-disk out))) + (void)))))) (module+ reader - (require RacketowerDB/util) - (require (submod RacketowerDB/util interfaces)) - (require (submod RacketowerDB/util hashable)) - (require RacketowerDB/ast) - (require racket/hash) - (provide read-schema-from-disk) - (provide read-table-from-disk) - (provide read-table-values-from-disk) + (provide + read-schema-from-disk + read-table-from-disk + read-table-values-from-disk) + + (require + RacketowerDB/ast + racket/hash) (define (read-schema-from-disk schema-name) (define (build-hash-from-line struct-instance line-in-bytes) (make-immutable-hash - (deserialize-hash-list - struct-instance - line-in-bytes - '()))) + (deserialize-hash-list + struct-instance + line-in-bytes + '()))) (define (proceed-reading struct-name current-schema line-in-bytes) - (let ((line (bytes->string/utf-8 line-in-bytes))) + (let [(line (bytes->string/utf-8 line-in-bytes))] (if (hash-has-key? entity-structs line) - (cons line current-schema) - (cons struct-name (hash-union current-schema (build-hash-from-line (hash-ref entity-structs struct-name) line-in-bytes)))))) - (let* ((file-name (build-ndf-filename schema-name #:data? 'schema)) + (cons line current-schema) + (cons struct-name (hash-union current-schema (build-hash-from-line (hash-ref entity-structs struct-name) line-in-bytes)))))) + (let* [(file-name (build-ndf-filename schema-name #:data? 'schema)) (in (open-input-file file-name #:mode 'binary)) (schema (make-immutable-hash (list))) (real-lines (port->bytes-lines in #:close? #t)) - (read-lines (fix-empty-read-bytes-lines real-lines))) + (read-lines (fix-empty-read-bytes-lines real-lines))] (~> (foldl - (lambda (line-in-bytes acc) - (let ((builder-struct (car acc)) - (current-schema (cdr acc))) - (proceed-reading builder-struct current-schema line-in-bytes))) - (cons null schema) read-lines) - cdr - hash->list - make-hash))) + (lambda [line-in-bytes acc] + (let [(builder-struct (car acc)) + (current-schema (cdr acc))] + (proceed-reading builder-struct current-schema line-in-bytes))) + (cons null schema) read-lines) + cdr + hash->list + make-hash))) (define (read-table-from-disk table-name) - (let* ((file-name (build-ndf-filename #:data? 'entity table-name)) - (in (open-input-file file-name #:mode 'binary))) + (let* [(file-name (build-ndf-filename #:data? 'entity table-name)) + (in (open-input-file file-name #:mode 'binary))] (define-values (table table-consumed) (deserialize struct:table (port->bytes in #:close? #t))) table)) (define (read-table-values-from-disk schema table-name) - (let* ((file-name (build-ndf-filename #:data? 'data table-name)) + (let* [(file-name (build-ndf-filename #:data? 'data table-name)) (in (open-input-file file-name #:mode 'binary)) (byte-stream (port->bytes in #:close? #t)) - (entity (hash-ref schema table-name))) + (entity (hash-ref schema table-name))] (cond [(table? entity) - (define (create-pair key-field) (cons (car key-field) (fyeld-type (cdr key-field)))) + (define (create-pair key-field) (cons (car key-field) (field-type (cdr key-field)))) (define (sort-by-position key-field1 key-field2) - (let ((p1 (fyeld-position (cdr key-field1))) - (p2 (fyeld-position (cdr key-field2)))) + (let [(p1 (field-position (cdr key-field1))) + (p2 (field-position (cdr key-field2)))] (< p1 p2))) (define (reconstruct-literal-data accumulator fields sub-byte-stream) - (let* ((first-elem (first fields)) + (let* [(first-elem (first fields)) (name (car first-elem)) (type (cdr first-elem)) (size (type-byte-size type)) (new-literal (from-bytes type (subbytes sub-byte-stream 0 size))) (return (append (list (cons name new-literal)) accumulator)) (rest-fields (rest fields)) - (remaining-bytes (subbytes sub-byte-stream size (bytes-length sub-byte-stream)))) + (remaining-bytes (subbytes sub-byte-stream size (bytes-length sub-byte-stream)))] (if (empty? rest-fields) - (cons return remaining-bytes) - (reconstruct-literal-data return rest-fields remaining-bytes)))) - (define (reconstruct-all-literals accumulator fields inner-byte-stream) - (let* ((one-line (reconstruct-literal-data (list) fields inner-byte-stream)) + (cons return remaining-bytes) + (reconstruct-literal-data return rest-fields remaining-bytes)))) + (define (reconstruct-all-literals accumulator fields inner-byte-stream) + (let* [(one-line (reconstruct-literal-data (list) fields inner-byte-stream)) (computed-line (list (car one-line))) (remaining-bytes (cdr one-line)) - (return (append accumulator computed-line))) + (return (append accumulator computed-line))] (if (bytes=? #"" remaining-bytes) - return - (reconstruct-all-literals return fields remaining-bytes)))) + return + (reconstruct-all-literals return fields remaining-bytes)))) (~> - (hash->list (table-fields entity)) - (sort _ sort-by-position) - (map create-pair _) - (reconstruct-all-literals (list) _ byte-stream))] + (hash->list (table-fields entity)) + (sort _ sort-by-position) + (map create-pair _) + (reconstruct-all-literals (list) _ byte-stream))] [(procedura? entity) (raise 'tried-deserialize-procedure-in-table-function)])))) diff --git a/main.rkt b/main.rkt index f2f6bd6..e7ae3ed 100644 --- a/main.rkt +++ b/main.rkt @@ -1,4 +1,15 @@ #lang racket +(require + racket/serialize + (rename-in RacketowerDB/ast (procedure? procedura?)) + (submod RacketowerDB/io writer) + (submod RacketowerDB/io reader) + ;(submod RacketowerDB/language parser) + (submod RacketowerDB/backend server) + RacketowerDB/util) + +;; review if this is needed for eval-syntax +(dynamic-require 'RacketowerDB/ast 0) (module+ test (require rackunit) @@ -10,76 +21,84 @@ ;; http://docs.racket-lang.org/guide/Module_Syntax.html#%28part._main-and-test%29 (module+ main - (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) - - (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))) - (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")) - ("AGE" . ,(integer32 123)))) - (row2 `(("NAME" . ,(stringl "Lemos")) - ("EDITOR" . ,(stringl "Emacs")) - ("AGE" . ,(integer32 100)))) - (row3 `(("MODEL" . ,(stringl "Ford")) - ("YEAR" . ,(integer32 1999)))) - (row4 `(("MODEL" . ,(stringl "Abc")) - ("YEAR" . ,(integer32 2013))))) - (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) - - ;; (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 field-name (field 0 (type 'VARCHAR 7))) + (define field-editor (field 1 (type 'VARCHAR 5))) + (define field-year (field 1 (type 'INTEGER 4))) + (define field-age (field 2 (type 'INTEGER 4))) + + + (define 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))) + + (define programmer-table + (table "table" 0 + (make-hash `(("NAME" . ,field-name) + ("AGE" . ,field-age) + ("EDITOR" . ,field-editor))) + (list constraint-1))) + + (define car-table + (table "table" 0 + (make-hash `(("MODEL" . ,field-name) + ("YEAR" . ,field-year))) + (list))) + + (define procedure-test (procedure "procedure")) + (define schema (make-hash (list))) + + (define row1 + `(("NAME" . ,(stringl "Nathan")) + ("EDITOR" . ,(stringl "Visual Studio Code")) + ("AGE" . ,(integer32 123)))) + + (define row2 + `(("NAME" . ,(stringl "Lemos")) + ("EDITOR" . ,(stringl "Emacs")) + ("AGE" . ,(integer32 100)))) + + (define row3 + `(("MODEL" . ,(stringl "Ford")) + ("YEAR" . ,(integer32 1999)))) + + (define row4 + `(("MODEL" . ,(stringl "Abc")) + ("YEAR" . ,(integer32 2013)))) + + (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) + + ;;(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)))) diff --git a/ndf/data/PROGRAMMER.ndf b/ndf/data/PROGRAMMER.ndf index 3c3a039..1bd73f3 100644 Binary files a/ndf/data/PROGRAMMER.ndf and b/ndf/data/PROGRAMMER.ndf differ diff --git a/ndf/entities/PROGRAMMER.ndf b/ndf/entities/PROGRAMMER.ndf index bfaa93e..cce277c 100644 Binary files a/ndf/entities/PROGRAMMER.ndf and b/ndf/entities/PROGRAMMER.ndf differ diff --git a/ndf/schemas/schema.ndf b/ndf/schemas/schema.ndf index a1dda58..b960152 100644 Binary files a/ndf/schemas/schema.ndf and b/ndf/schemas/schema.ndf differ diff --git a/util.rkt b/util.rkt index 3fab3bd..b3e7439 100644 --- a/util.rkt +++ b/util.rkt @@ -1,45 +1,47 @@ #lang racket -(require struct-update) -(require threading) -(require br/cond) +(provide + build-ndf-filename + entity-structs + define-serializable + fix-empty-read-bytes-lines) -(provide build-ndf-filename) -(provide entity-structs) -(provide define-serializable) -(provide fix-empty-read-bytes-lines) - -(require syntax/parse/define - (for-syntax racket/syntax)) +(require + struct-update + threading + br/cond) (define (fix-empty-read-bytes-lines lines) (define (fix-one-turn inner-lines) - (let ((newline-flag #f)) - (foldl (lambda (line new-lines) - (if newline-flag - (begin - (begin - (set! newline-flag #f) - new-lines) - (append new-lines (list (bytes-append #"\n" line)))) - (if (bytes=? #"" line) - (begin - (set! newline-flag #t) - new-lines) - (append new-lines (list line))))) (list) inner-lines))) - (define (stop-condition lines-to-check) (empty? (filter (curry bytes=? #"") lines-to-check))) + (let [(newline-flag #f)] + (foldl (lambda [line new-lines] + (cond + [newline-flag + (set! newline-flag #f) + (append new-lines (list (bytes-append #"\n" line)))] + + [(bytes=? #"" line) + (set! newline-flag #t) + new-lines] + + [else (append new-lines (list line))])) + (list) inner-lines))) + + (define (stop-condition lines-to-check) + (empty? (filter (curry bytes=? #"") lines-to-check))) + (while (not (stop-condition lines)) (set! lines (fix-one-turn lines))) + lines) -(define build-ndf-filename - (lambda (#:data? [data? 'entity] name) - (let ((path (case (list 'quote data?) - [('entity) "ndf/entities/"] - [('schema) "ndf/schemas/"] - [('data) "ndf/data/"] - [else (raise 'error-not-specified-datatype)]))) - (string-append path (string-append name ".ndf"))))) +(define (build-ndf-filename #:data? [data? 'entity] name) + (let [(path (case (list 'quote data?) + [('entity) "ndf/entities/"] + [('schema) "ndf/schemas/"] + [('data) "ndf/data/"] + [else (raise 'error-not-specified-datatype)]))] + (string-append path (string-append name ".ndf")))) (define entity-structs (make-hash (list))) @@ -49,33 +51,31 @@ #`(begin (struct name body ...) (define-struct-updaters name) - (hash-set! - entity-structs - (symbol->string 'name) - #,(datum->syntax #'name (let ((datum-name (syntax->datum #'name))) - (string->symbol (string-append "struct:" (symbol->string datum-name)))))))])) + (hash-set! entity-structs (symbol->string 'name) + #,(datum->syntax #'name + (let [(datum-name (syntax->datum #'name))] + (string->symbol (string-append "struct:" (symbol->string datum-name)))))))])) (module interfaces racket (provide - (contract-out - [give-identifier (-> identifiable? string?)] - [serialize (->* (serializable?) (#:size integer?) bytes?)] - [deserialize (-> serializable? bytes? (values serializable? natural?))] - [from-bytes (-> byteable? bytes? serializable?)] - [to-byte-size (-> byteable? natural?)]) - serializable? - byteable? - identifiable? - gen:serializable - gen:byteable - gen:identifiable) - - (require racket/generic) - (require racket/contract) + serializable? + byteable? + identifiable? + gen:serializable + gen:byteable + gen:identifiable + (contract-out + [give-identifier (-> identifiable? string?)] + [serialize (->* (serializable?) (#:size integer?) bytes?)] + [deserialize (-> serializable? bytes? (values serializable? natural?))] + [from-bytes (-> byteable? bytes? serializable?)] + [to-byte-size (-> byteable? natural?)])) + + (require racket/generic racket/contract) (define-generics identifiable #:requires [give-identifier] (give-identifier identifiable)) - + (define-generics serializable #:requires [serialize deserialize] (serialize serializable #:size (size)) (deserialize serializable byte-stream)) @@ -85,41 +85,42 @@ (to-byte-size byteable))) (module+ hashable - (require (submod ".." interfaces)) - (provide (contract-out [deserialize-hash-list (-> serializable? bytes? list? list?)] [serialize-hash-list (-> (listof (cons/c string? serializable?)) #:entity? boolean? bytes?)])) + (require (submod ".." interfaces)) + (define (deserialize-hash-list entity byte-stream accumulator) (define (deserialize-name more-bytes) - (let* ((name-size (integer-bytes->integer (subbytes more-bytes 0 4) #t)) - (name (bytes->string/utf-8 (subbytes more-bytes 4 (+ 4 name-size))))) + (let* [(name-size (integer-bytes->integer (subbytes more-bytes 0 4) #t)) + (name (bytes->string/utf-8 (subbytes more-bytes 4 (+ 4 name-size))))] (cons name (+ 4 name-size)))) (if (equal? byte-stream #"") - accumulator - (let* ((name-consumption (deserialize-name byte-stream)) - (name-consumed (cdr name-consumption)) - (name (car name-consumption))) - (define-values (thing thing-consumed) (deserialize entity (subbytes byte-stream name-consumed))) - (deserialize-hash-list - entity - (subbytes byte-stream (+ name-consumed thing-consumed) (bytes-length byte-stream)) - (append accumulator (list (cons name thing))))))) + accumulator + (let* [(name-consumption (deserialize-name byte-stream)) + (name-consumed (cdr name-consumption)) + (name (car name-consumption))] + (define-values [thing thing-consumed] (deserialize entity (subbytes byte-stream name-consumed))) + (deserialize-hash-list + entity + (subbytes byte-stream (+ name-consumed thing-consumed) (bytes-length byte-stream)) + (append accumulator (list (cons name thing))))))) (define (serialize-hash-list named-values-list #:entity? entity?) - (define (serialize-name name) - (let* ((name-bytes (string->bytes/utf-8 name)) - (name-size (integer->integer-bytes (bytes-length name-bytes) 4 #t))) - (bytes-append name-size name-bytes))) - (~> - (map (lambda (named-value) - (let ((name (car named-value)) - (value (cdr named-value))) - (bytes-append - (serialize-name name) - (serialize value)))) - named-values-list) - (bytes-join _ (if entity? #"\n" #""))))) + (define (serialize-name name) + (let* [(name-bytes (string->bytes/utf-8 name)) + (name-size (integer->integer-bytes (bytes-length name-bytes) 4 #t))] + (bytes-append name-size name-bytes))) + + (~> + (map (lambda [named-value] + (let [(name (car named-value)) + (value (cdr named-value))] + (bytes-append + (serialize-name name) + (serialize value)))) + named-values-list) + (bytes-join _ (if entity? #"\n" #"")))))