database.lisp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. ;;;; database.lisp
  2. (in-package #:genie)
  3. ;;; "database" goes here. Hacks and glory await!
  4. (defmacro constrain-values (&rest values)
  5. `(lambda (object)
  6. (the boolean
  7. (member object (list ,@values)))))
  8. (defmacro in-table-column (table column)
  9. `(lambda (object)
  10. (let ((possible-values (iter
  11. (for row in (select ,table))
  12. (collect (,column row)))))
  13. (the boolean (member object possible-values)))))
  14. (defmacro unique-in-column (table column type)
  15. `(lambda (object)
  16. (if (typep object ',type)
  17. (let ((possible-values (iter
  18. (for row in (select ,table))
  19. (collect (,column row)))))
  20. (not (the boolean (member object possible-values)))))))
  21. (defun generate-table-id (table)
  22. (declare (keyword table))
  23. (1+ (length (select table))))
  24. ;;; The Person table
  25. (defattributes
  26. :/person-id (unique-in-column :people :/person-id integer)
  27. :/person-name #'stringp
  28. :/gender (constrain-values "M" "F"))
  29. ;;; The Births table
  30. (defattributes
  31. :/birth-id (unique-in-column :births :/birth-id integer)
  32. :/birth-person (in-table-column :people :/person-id)
  33. :/birth-date #'stringp
  34. :/father (lambda (object)
  35. (or (= 0 object)
  36. (funcall (in-table-column :people :/person-id) object)))
  37. :/mother (lambda (object)
  38. (or (= 0 object)
  39. (funcall (in-table-column :people :/person-id) object))))
  40. ;;; The Deaths table
  41. (defattributes
  42. :/death-id (unique-in-column :deaths :/death-id integer)
  43. :/death-person (in-table-column :people :/person-id)
  44. :/death-date #'stringp)
  45. ;;; The Marriages table
  46. (defattributes
  47. :/marriage-id (unique-in-column :marriages :/marriage-id integer)
  48. :/husband (in-table-column :people :/person-id)
  49. :/wife (in-table-column :people :/person-id)
  50. :/wedding-date #'stringp
  51. :/end-date #'stringp)
  52. ;;; The Divorces table
  53. (defattributes
  54. :/divorce-id (unique-in-column :divorces :/divorce-id integer)
  55. :/marriage (in-table-column :marriages :/marriage-id)
  56. :/divorce-date #'stringp)
  57. ;;; insert person
  58. (defun new-person (name gender birth-date mother father)
  59. (declare (string name)
  60. (integer mother
  61. father))
  62. (with-tx
  63. (let ((person-id (generate-table-id :people))
  64. (birth-id (generate-table-id :births)))
  65. (insert :people
  66. (list :/person-id person-id
  67. :/person-name name
  68. :/gender gender))
  69. (insert :births
  70. (list :/birth-id birth-id
  71. :/birth-person person-id
  72. :/birth-date birth-date
  73. :/mother mother
  74. :/father father))
  75. (values person-id birth-id))))
  76. ;;; insert death
  77. (defun new-death (person death-date)
  78. (with-tx
  79. (let ((death-id (generate-table-id :deaths)))
  80. (insert :deaths
  81. (list :/death-id death-id
  82. :/death-person person
  83. :/death-date death-date))
  84. death-id)))
  85. ;;; insert marriage
  86. (defun new-marriage (husband wife date end-date)
  87. (with-tx
  88. (let ((marriage-id (generate-table-id :marriages)))
  89. (insert :marriages
  90. (list :/marriage-id marriage-id
  91. :/husband husband
  92. :/wife wife
  93. :/wedding-date date
  94. :/end-date date))
  95. marriage-id)))
  96. ;;; insert divorce
  97. (defun new-divorce (marriage-id date)
  98. (with-tx
  99. (let ((divorce-id (generate-table-id :divorces)))
  100. (insert :divorces
  101. (list :/divorce-id divorce-id
  102. :/marriage marriage-id
  103. :/divorce-date date))
  104. divorce-id)))
  105. ;;; Query records
  106. ;;; Get Person
  107. (defun get-person (id)
  108. (with-tx
  109. (first
  110. (select :people
  111. (where (equal :/person-id id))))))
  112. ;;; Get Birth record (by person)
  113. (defun get-birth (id)
  114. (with-tx
  115. (first
  116. (select :births
  117. (where (equal :/birth-person id))))))
  118. ;;; Get Death Record
  119. (defun get-death (id)
  120. (with-tx
  121. (first
  122. (select :deaths
  123. (where (equal :/death-person id))))))
  124. ;;; get marriage (by husband/wife)
  125. (defun get-marriage (husband wife)
  126. (with-tx
  127. (first
  128. (select :marriages
  129. (where (and (equal :/wife wife)
  130. (equal :/husband husband)))))))
  131. ;;; get divorce (by marriage)
  132. (defun get-divorce (id)
  133. (with-tx
  134. (first
  135. (select :divorces
  136. (where (equal :/marriage id))))))