database.lisp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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)))