From 3008eb25f79ef1ed54fcc2b3f5b6635b34394680 Mon Sep 17 00:00:00 2001 From: Marius Peter Date: Sun, 19 Oct 2025 21:15:18 +0200 Subject: Absorb existing domain data. --- db/migrations.rkt | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 db/migrations.rkt (limited to 'db/migrations.rkt') diff --git a/db/migrations.rkt b/db/migrations.rkt new file mode 100644 index 0000000..95164e4 --- /dev/null +++ b/db/migrations.rkt @@ -0,0 +1,167 @@ +#lang racket + +(provide migrate-all!) + +(require db + sql + "conn.rkt") + +(define migrations-box (box '())) + +(define (migrate-all!) + (printf "Applying migrations on connection ~a...\n" + (dbsystem-name (connection-dbsystem (current-conn)))) + (for ([pair (in-list (unbox migrations-box))]) + (match pair + [(cons migration-name stmts) + (with-tx + (for ([stmt (in-list stmts)]) + (query-exec (current-conn) stmt))) + (printf "Applied migration: ~a\n" migration-name)]))) + +(define-syntax-rule (define-migration migration-name sql) + (let ((migrations (unbox migrations-box)) + (name-symbol (string->symbol migration-name))) + (if (assoc name-symbol migrations) + (error 'define-migration "migration '~a' declared more than once" migration-name) + (set-box! migrations-box (append migrations (list (cons name-symbol sql))))))) + + +;;;;;;;;;;;; +;; NUTRIENTS +;;;;;;;;;;;; + +(define-migration "create table nutrients" + (list + (create-table #:if-not-exists + nutrients + #:columns + [id integer #:not-null] + [canonical_name text #:not-null] + [formula text #:not-null] + #:constraints + (primary-key id) + (unique canonical_name) + (unique formula)))) + +(define-migration "create table nutrient_value_sets" + (list + (create-table #:if-not-exists + nutrient_value_sets + #:columns + [id integer #:not-null] + [nutrient_measurement_id integer] + [nutrient_target_id integer] + [crop_requirement_id integer] + [fertilizer_product_id integer] + #:constraints + (primary-key id) + (foreign-key nutrient_measurement_id + #:references (nutrient_measurement id) + #:on-delete #:cascade) + (foreign-key nutrient_target_id + #:references (nutrient_target id) + #:on-delete #:cascade) + (foreign-key crop_requirement_id + #:references (crop_requirements id) + #:on-delete #:cascade) + (foreign-key fertilizer_product_id + #:references (fertilizer_products id) + #:on-delete #:cascade)) + "CREATE INDEX IF NOT EXISTS idx_nvs_meas ON nutrient_value_sets(nutrient_measurement_id)" + "CREATE INDEX IF NOT EXISTS idx_nvs_targ ON nutrient_value_sets(nutrient_target_id)" + "CREATE INDEX IF NOT EXISTS idx_nvs_crop ON nutrient_value_sets(crop_requirement_id)" + "CREATE INDEX IF NOT EXISTS idx_nvs_prod ON nutrient_value_sets(fertilizer_product_id)")) + +(define-migration "create table nutrient_values" + (list + (create-table #:if-not-exists + nutrient_values + #:columns + [value_set_id integer #:not-null] + [nutrient_id integer #:not-null] + [value_ppm real #:not-null] + #:constraints + (primary-key value_set_id nutrient_id) + (foreign-key value_set_id + #:references (nutrient_value_sets id) + #:on-delete #:cascade) + (foreign-key nutrient_id + #:references (nutrients id) + #:on-delete #:cascade)) + "CREATE INDEX IF NOT EXISTS idx_nv_set_nutrient ON nutrient_values(value_set_id, nutrient_id)")) + +(define-migration "create table nutrient_measurements" + (list + (create-table #:if-not-exists + nutrient_measurements + #:columns + [id integer #:not-null] + ;; ISO8601 date + [measured_on text #:not-null] + #:constraints + (primary-key id) + (unique measured_on)))) + +(define-migration "create table nutrient_targets" + (list + (create-table #:if-not-exists + nutrient_targets + #:columns + [id integer #:not-null] + ;; ISO8601 date + [effective_on text #:not-null] + #:constraints + (primary-key id) + (unique effective_on)))) + + +;;;;;;;; +;; CROPS +;;;;;;;; + +(define-migration "create table crops" + (list + (create-table #:if-not-exists + crops + #:columns + [id integer #:not-null] + [canonical_name integer #:not-null] + #:constraints + (primary-key id) + (unique canonical_name)))) + +(define-migration "create table crop_requirements" + (list + (create-table #:if-not-exists + crop_requirements + #:columns + [id integer #:not-null] + [crop_id integer] + [profile text #:not-null] + #:constraints + (primary-key id) + (foreign-key crop_id + #:references (crops id) + #:on-delete #:cascade)))) + + +;;;;;;;;;;;;;; +;; FERTILIZERS +;;;;;;;;;;;;;; + +(define-migration "create table fertilizer_products" + (list + (create-table #:if-not-exists + fertilizer_products + #:columns + [id integer #:not-null] + [canonical_name text #:not-null] + [brand_name text] + #:constraints + (primary-key id) + (unique canonical_name)))) + +(module+ test + (connect!) + (migrate-all!)) -- cgit v1.2.3