From e9bd3de661a7713c53d6ed9c79b871bedef4fc4f Mon Sep 17 00:00:00 2001 From: "Karl O. Pinc kop@karlpinc.com" Date: Thu, 14 May 2026 20:04:00 +0000 Subject: [PATCH] Create, document, index, and trigger FOOD_EVENTS --- db/schemas/lib/triggers/Makefile | 3 +- db/schemas/lib/triggers/create/food_events.m4 | 358 ++++++++++++++++++ db/schemas/lib/triggers/drop/food_events.m4 | 25 ++ db/schemas/sokwedb/indexes/Makefile | 2 +- .../sokwedb/indexes/create/food_events.m4 | 31 ++ .../sokwedb/indexes/drop/food_events.m4 | 27 ++ db/schemas/sokwedb/tables/Makefile | 3 +- .../sokwedb/tables/create/food_events.m4 | 44 +++ doc/src/epilog.inc.m4 | 16 + doc/src/tables.m4 | 1 + doc/src/tables/events.m4 | 21 +- doc/src/tables/food_events.m4 | 172 +++++++++ 12 files changed, 699 insertions(+), 4 deletions(-) create mode 100644 db/schemas/lib/triggers/create/food_events.m4 create mode 100644 db/schemas/lib/triggers/drop/food_events.m4 create mode 100644 db/schemas/sokwedb/indexes/create/food_events.m4 create mode 100644 db/schemas/sokwedb/indexes/drop/food_events.m4 create mode 100644 db/schemas/sokwedb/tables/create/food_events.m4 create mode 100644 doc/src/tables/food_events.m4 diff --git a/db/schemas/lib/triggers/Makefile b/db/schemas/lib/triggers/Makefile index 414c54a..fe1433f 100644 --- a/db/schemas/lib/triggers/Makefile +++ b/db/schemas/lib/triggers/Makefile @@ -34,7 +34,8 @@ ORDER := comm_ids \ roles \ arrivals \ aggressions \ - sightings + sightings \ + food_events DROP_EXISTING := true diff --git a/db/schemas/lib/triggers/create/food_events.m4 b/db/schemas/lib/triggers/create/food_events.m4 new file mode 100644 index 0000000..918842e --- /dev/null +++ b/db/schemas/lib/triggers/create/food_events.m4 @@ -0,0 +1,358 @@ +dnl Copyright (C) 2026 The Meme Factory, Inc. http://www.karlpinc.com/ +dnl +dnl This program is free software: you can redistribute it and/or modify it +dnl under the terms of the GNU Affero General Public License as published by +dnl the Free Software Foundation, either version 3 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU Affero General Public License for more details. +dnl +dnl You should have received a copy of the GNU Affero General Public License +dnl along with this program. If not, see . +dnl +dnl Triggers for the food_events table +dnl +dnl Karl O. Pinc + +dnl m4 includes +include(`copyright.m4')dnl +include(`constants.m4')dnl +include(`macros.m4')dnl + + +RAISE INFO 'food_events_func'; +CREATE OR REPLACE FUNCTION food_events_func () + RETURNS trigger + LANGUAGE plpgsql + sdb_function_set_search_path + AS $$ + BEGIN + -- Function for food_events insert and update triggers + -- + -- AGPL_notice(` --', `2026', + `The Meme Factory, Inc., www.karlpinc.com') + + IF TG_OP = 'UPDATE' THEN + cannot_change(`FOOD_EVENTS', `FEID') + END IF; + + -- The EVENTS.Behavior must be sdb_food + IF TG_OP = 'INSERT' + OR NEW.EID <> OLD.EID THEN + DECLARE + -- EVENTS + a_behavior events.behavior%TYPE; + a_start events.start%TYPE; + a_stop events.stop%TYPE; + -- FOLLOWS + a_fid follows.fid%TYPE; + a_focal follows.focal%TYPE; + a_date follows.date%TYPE; + -- ROLES + a_pid roles.pid%TYPE; + a_role roles.role%TYPE; + a_participant roles.participant%TYPE; + + BEGIN + SELECT events.behavior, events.start, events.stop + , follows.fid, follows.focal, follows.date + , roles.pid, roles.role, roles.participant + INTO a_behavior , a_start , a_stop + , a_fid , a_focal , a_date + , a_pid , a_role , a_participant + FROM events + JOIN follows ON (follows.fid = events.fid) + LEFT OUTER JOIN roles ON (roles.eid = events.eid) + WHERE events.eid = NEW.eid + AND events.behavior <> 'sdb_food'; + IF FOUND THEN + RAISE EXCEPTION integrity_constraint_violation USING + MESSAGE = 'Error on ' || TG_OP || ' of FOOD_EVENTS' + , DETAIL = 'Food events can only be related to an event with an' + || ' EVENTS.Behavior value of (sdb_food)' + || ': Key (FEID = (' + || NEW.feid + || '): Value (FoodPart) = (' + || NEW.foodpart + || '): Value (FoodName) = (' + || NEW.foodname + || '): Value (FoodPartWritten) = (' + || NEW.foodpartwritten + || '): Value (FoodNameWritten) = (' + || NEW.foodnamewritten + || '): Value (Seq) = (' + || NEW.Seq + || '): Key (ROLES.PID) = (' + || textualize(`a_pid') + || '), Value (ROLES.Role) = (' + || textualize(`a_role') + || '), Value (ROLES.Participant) = (' + || textualize(`a_participant') + || '): Key (EVENTS.EID) = (' + || NEW.eid + || '): Value (EVENTS.Behavior) = (' + || a_behavior + || '), Value (EVENTS.Start) = (' + || a_start + || '), Value (EVENTS.Stop) = (' + || a_stop + || '): Key (FOLLOWS.FID) = (' + || a_fid + || '), Value (FOLLOWS.Focal) = (' + || a_focal + || '), Value (FOLLOWS.Date) = (' + || a_date + || ')'; + END IF; + END; + END IF; + + RETURN NULL; + END; +$$; + + +RAISE INFO 'food_events_commit_func'; +CREATE OR REPLACE FUNCTION food_events_commit_func () + RETURNS trigger + LANGUAGE plpgsql + sdb_function_set_search_path + AS $$ + DECLARE + a_feid food_events.feid%TYPE; + a_foodpart food_events.foodpart%TYPE; + a_foodname food_events.foodname%TYPE; + a_seq food_events.seq%TYPE; + + BEGIN + -- Function for food_events on-commit insert and update triggers + -- + -- AGPL_notice(` --', `2026', + `The Meme Factory, Inc., www.karlpinc.com') + + -- The Seq must start with 1 and can't have gaps + IF TG_OP = 'INSERT' + OR NEW.seq <> OLD.seq THEN + + SELECT food_events.feid, food_events.foodpart, food_events.foodname + , food_events.seq + INTO a_feid , a_foodpart , a_foodname + , a_seq + FROM food_events + WHERE food_events.eid = NEW.eid + AND food_events.seq > 1 + AND NOT EXISTS + (SELECT 1 + FROM food_events AS previous + WHERE previous.eid = NEW.eid + AND previous.seq = food_events.seq - 1) + -- Produce a consistent error message + ORDER BY food_events.seq, food_events.feid; + + IF FOUND THEN + DECLARE + -- EVENTS + a_behavior events.behavior%TYPE; + a_start events.start%TYPE; + a_stop events.stop%TYPE; + -- FOLLOWS + a_fid follows.fid%TYPE; + a_focal follows.focal%TYPE; + a_date follows.date%TYPE; + -- ROLES + a_pid roles.pid%TYPE; + a_role roles.role%TYPE; + a_participant roles.participant%TYPE; + + BEGIN + SELECT events.behavior, events.start, events.stop + , follows.fid, follows.focal, follows.date + , roles.pid, roles.role, roles.participant + INTO a_behavior , a_start , a_stop + , a_fid , a_focal , a_date + , a_pid , a_role , a_participant + FROM events + JOIN follows ON (follows.fid = events.fid) + -- It would be nice to also check, and know, that + -- a ROLES row exists, but we leave this to the warnings. + LEFT OUTER JOIN roles ON (roles.eid = events.eid) + WHERE events.eid = NEW.eid; + + RAISE EXCEPTION integrity_constraint_violation USING + MESSAGE = 'Error on ' || TG_OP || ' of FOOD_EVENTS' + , DETAIL = 'Food events must have Seq values that increase' + || ' without gaps, with respect to their related' + || ' EVENTS row; but there is no such FOOD_EVENTS row' + || ' with a Seq of (' + || a_seq - 1 + || ') to pair with the following FOOD_EVENTS row:' + || ' Key (FEID = (' + || a_feid + || '): Value (FoodPart) = (' + || a_foodpart + || '): Value (FoodName) = (' + || a_foodname + || '): Value (Seq) = (' + || a_seq + || '): Key (ROLES.PID) = (' + || textualize(`a_pid') + || '), Value (ROLES.Role) = (' + || textualize(`a_role') + || '), Value (ROLES.Participant) = (' + || textualize(`a_participant') + || '): Key (EVENTS.EID) = (' + || NEW.eid + || '): Value (EVENTS.Behavior) = (' + || a_behavior + || '), Value (EVENTS.Start) = (' + || a_start + || '), Value (EVENTS.Stop) = (' + || a_stop + || '): Key (FOLLOWS.FID) = (' + || a_fid + || '), Value (FOLLOWS.Focal) = (' + || a_focal + || '), Value (FOLLOWS.Date) = (' + || a_date + || ')'; + END; + END IF; + END IF; + + RETURN NULL; + END; +$$; + + +RAISE INFO 'food_events_delete_commit_func'; +CREATE OR REPLACE FUNCTION food_events_delete_commit_func () + RETURNS trigger + LANGUAGE plpgsql + sdb_function_set_search_path + AS $$ + DECLARE + a_feid food_events.feid%TYPE; + a_foodpart food_events.foodpart%TYPE; + a_foodname food_events.foodname%TYPE; + a_seq food_events.seq%TYPE; + + BEGIN + -- Function for food_events on-commit delete trigger + -- + -- AGPL_notice(` --', `2026', + `The Meme Factory, Inc., www.karlpinc.com') + + -- The Seq can't have gaps + SELECT food_events.feid, food_events.foodpart, food_events.foodname + , food_events.seq + INTO a_feid , a_foodpart , a_foodname + , a_seq + FROM food_events + WHERE food_events.eid = OLD.eid + AND food_events.seq = OLD.seq + 1 + AND NOT EXISTS + (SELECT 1 + FROM food_events AS this_slot + WHERE this_slot.eid = OLD.eid + AND this_slot.seq = OLD.seq) + -- Produce a consistent error message + ORDER BY food_events.feid; + + IF FOUND THEN + DECLARE + -- EVENTS + a_behavior events.behavior%TYPE; + a_start events.start%TYPE; + a_stop events.stop%TYPE; + -- FOLLOWS + a_fid follows.fid%TYPE; + a_focal follows.focal%TYPE; + a_date follows.date%TYPE; + -- ROLES + a_pid roles.pid%TYPE; + a_role roles.role%TYPE; + a_participant roles.participant%TYPE; + + BEGIN + SELECT events.behavior, events.start, events.stop + , follows.fid, follows.focal, follows.date + , roles.pid, roles.role, roles.participant + INTO a_behavior , a_start , a_stop + , a_fid , a_focal , a_date + , a_pid , a_role , a_participant + FROM events + JOIN follows ON (follows.fid = events.fid) + -- It would be nice to also check, and know, that + -- a ROLES row exists, but we leave this to the warnings. + LEFT OUTER JOIN roles ON (roles.eid = events.eid) + WHERE events.eid = OLD.eid; + + RAISE EXCEPTION integrity_constraint_violation USING + MESSAGE = 'Error on DELETE of FOOD_EVENTS' + , DETAIL = 'Food events must have Seq values that increase' + || ' without gaps, with respect to their related' + || ' EVENTS row; but there is no such FOOD_EVENTS row' + || ' with a Seq of (' + || a_seq - 1 + || ') to pair with the following FOOD_EVENTS row:' + || ' Key (FEID = (' + || a_feid + || '): Value (FoodPart) = (' + || a_foodpart + || '): Value (FoodName) = (' + || a_foodname + || '): Value (Seq) = (' + || a_seq + || '): Key (ROLES.PID) = (' + || textualize(`a_pid') + || '), Value (ROLES.Role) = (' + || textualize(`a_role') + || '), Value (ROLES.Participant) = (' + || textualize(`a_participant') + || '): Key (EVENTS.EID) = (' + || OLD.eid + || '): Value (EVENTS.Behavior) = (' + || a_behavior + || '), Value (EVENTS.Start) = (' + || a_start + || '), Value (EVENTS.Stop) = (' + || a_stop + || '): Key (FOLLOWS.FID) = (' + || a_fid + || '), Value (FOLLOWS.Focal) = (' + || a_focal + || '), Value (FOLLOWS.Date) = (' + || a_date + || ')'; + END; + END IF; + + RETURN NULL; + END; +$$; + + +RAISE INFO 'food_events_trigger'; +CREATE TRIGGER food_events_trigger + AFTER INSERT OR UPDATE + ON food_events FOR EACH ROW + EXECUTE PROCEDURE food_events_func(); + +RAISE INFO 'food_events_commit_trigger'; +CREATE CONSTRAINT TRIGGER food_events_commit_trigger + AFTER INSERT OR UPDATE + ON food_events + DEFERRABLE INITIALLY DEFERRED + FOR EACH ROW + EXECUTE PROCEDURE food_events_commit_func(); + +RAISE INFO 'food_events_delete_commit_trigger'; +CREATE CONSTRAINT TRIGGER food_events_delete_commit_trigger + AFTER DELETE + ON food_events + DEFERRABLE INITIALLY DEFERRED + FOR EACH ROW + Execute PROCEDURE food_events_delete_commit_func(); diff --git a/db/schemas/lib/triggers/drop/food_events.m4 b/db/schemas/lib/triggers/drop/food_events.m4 new file mode 100644 index 0000000..fe5c344 --- /dev/null +++ b/db/schemas/lib/triggers/drop/food_events.m4 @@ -0,0 +1,25 @@ +dnl Copyright (C) 2026 The Meme Factory, Inc. http://www.karlpinc.com/ +dnl +dnl This program is free software: you can redistribute it and/or modify +dnl it under the terms of the GNU Affero General Public License as published by +dnl the Free Software Foundation, either version 3 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU Affero General Public License for more details. +dnl +dnl You should have received a copy of the GNU Affero General Public License +dnl along with this program. If not, see . +dnl +dnl Drop triggers for aggressions table +dnl +dnl Karl O. Pinc + +dnl m4 includes +include(`copyright.m4')dnl + +DROP FUNCTION IF EXISTS food_events_func() CASCADE; +DROP FUNCTION IF EXISTS food_events_commit_func() CASCADE; +DROP FUNCTION IF EXISTS food_events_delete_commit_func() CASCADE; diff --git a/db/schemas/sokwedb/indexes/Makefile b/db/schemas/sokwedb/indexes/Makefile index 7ef5dd1..50a3a4d 100644 --- a/db/schemas/sokwedb/indexes/Makefile +++ b/db/schemas/sokwedb/indexes/Makefile @@ -22,7 +22,7 @@ ORDER := biography_data biography_log comm_membs comm_memb_log \ follows follow_observers follow_studies events roles arrivals \ estrus_sources estrus_states aggression_event_log sightings \ - aggressions + aggressions food_events ## ## CAUTION: This Makefile is not designed to be run directly. It is normally diff --git a/db/schemas/sokwedb/indexes/create/food_events.m4 b/db/schemas/sokwedb/indexes/create/food_events.m4 new file mode 100644 index 0000000..57bb7a2 --- /dev/null +++ b/db/schemas/sokwedb/indexes/create/food_events.m4 @@ -0,0 +1,31 @@ +dnl Copyright (C) 2026 The Meme Factory, Inc., http://www.karlpinc.com/ +dnl +dnl This program is free software: you can redistribute it and/or modify +dnl it under the terms of the GNU Affero General Public License as published +dnl by the Free Software Foundation, either version 3 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU Affero General Public License for more details. +dnl +dnl You should have received a copy of the GNU Affero General Public License +dnl along with this program. If not, see . +dnl +dnl Karl O. Pinc +dnl +dnl +dnl m4 includes +include(`copyright.m4')dnl +include(`constants.m4')dnl +include(`indexmacros.m4')dnl + +CREATE UNIQUE INDEX IF NOT EXISTS food_events_eid_seq ON food_events + (eid, seq); + +CREATE INDEX IF NOT EXISTS food_events_foodpart ON food_events + (foodpart); +CREATE INDEX IF NOT EXISTS food_events_foodname ON food_events + (foodname); + diff --git a/db/schemas/sokwedb/indexes/drop/food_events.m4 b/db/schemas/sokwedb/indexes/drop/food_events.m4 new file mode 100644 index 0000000..dccf236 --- /dev/null +++ b/db/schemas/sokwedb/indexes/drop/food_events.m4 @@ -0,0 +1,27 @@ +dnl Copyright (C) 2026 The Meme Factory, Inc., http://www.karlpinc.com/ +dnl +dnl This program is free software: you can redistribute it and/or modify +dnl it under the terms of the GNU Affero General Public License as published +dnl by the Free Software Foundation, either version 3 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU Affero General Public License for more details. +dnl +dnl You should have received a copy of the GNU Affero General Public License +dnl along with this program. If not, see . +dnl +dnl Karl O. Pinc +dnl +dnl +dnl m4 includes +include(`copyright.m4')dnl +include(`constants.m4')dnl +include(`indexmacros.m4')dnl + +DROP INDEX IF EXISTS food_events_eid_seq; + +DROP INDEX IF EXISTS food_events_foodpart; +DROP INDEX IF EXISTS food_events_foodname; diff --git a/db/schemas/sokwedb/tables/Makefile b/db/schemas/sokwedb/tables/Makefile index a0e05c0..63e089c 100644 --- a/db/schemas/sokwedb/tables/Makefile +++ b/db/schemas/sokwedb/tables/Makefile @@ -37,7 +37,8 @@ ORDER := biography_data \ arrivals \ aggressions \ aggression_event_log \ - non_brec_sighting_sources + non_brec_sighting_sources \ + food_events ## ## CAUTION: This Makefile is not designed to be run directly. It is normally ## invoked by another Makefile. diff --git a/db/schemas/sokwedb/tables/create/food_events.m4 b/db/schemas/sokwedb/tables/create/food_events.m4 new file mode 100644 index 0000000..76a56ba --- /dev/null +++ b/db/schemas/sokwedb/tables/create/food_events.m4 @@ -0,0 +1,44 @@ +dnl Copyright (C) 2026 The Meme Factory, Inc., http://www.karlpinc.com/ +dnl +dnl This program is free software: you can redistribute it and/or modify +dnl it under the terms of the GNU Affero General Public License as published +dnl by the Free Software Foundation, either version 3 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU Affero General Public License for more details. +dnl +dnl You should have received a copy of the GNU Affero General Public License +dnl along with this program. If not, see . +dnl +dnl Karl O. Pinc +dnl +dnl +dnl m4 includes +include(`copyright.m4')dnl +include(`constants.m4')dnl +include(`tablemacros.m4')dnl +include(`grants.m4')dnl +dnl + +CREATE TABLE food_events ( + key_column(`FOOD_EVENTS', `FEID', INTEGER) + ,eid INTEGER NOT NULL + REFERENCES events + ,foodpart TEXT NOT NULL + CONSTRAINT "FoodPart must be a FOOD_PARTS.Part" + REFERENCES food_parts (part) + ,foodname TEXT NOT NULL + CONSTRAINT "FoodName must be a FOODS.Food" + REFERENCES food_names (name) + ,foodpartwritten TEXT NOT NULL + notonlyspaces_check(`FoodPartWritten') + ,foodnamewritten TEXT NOT NULL + notonlyspaces_check(`FoodNameWritten') + ,seq INTEGER NOT NULL + positive_check(`Seq') +); + +grant_priv(`FOOD_EVENTS') diff --git a/doc/src/epilog.inc.m4 b/doc/src/epilog.inc.m4 index 8235e9c..3c5c8c1 100644 --- a/doc/src/epilog.inc.m4 +++ b/doc/src/epilog.inc.m4 @@ -338,6 +338,22 @@ sdb_generated_rst()dnl .. |EVENTS.Notes| replace:: :ref:`Notes ` +.. |FOOD_EVENTS| replace:: :ref:`FOOD_EVENTS ` +.. |FOOD_EVENTS.FEID| replace:: + :ref:`FEID ` +.. |FOOD_EVENTS.EID| replace:: + :ref:`EID ` +.. |FOOD_EVENTS.FoodPart| replace:: + :ref:`FoodPart ` +.. |FOOD_EVENTS.FoodName| replace:: + :ref:`FoodName ` +.. |FOOD_EVENTS.FoodPartWritten| replace:: + :ref:`FoodPartWritten ` +.. |FOOD_EVENTS.FoodNameWritten| replace:: + :ref:`FoodNameWritten ` +.. |FOOD_EVENTS.Seq| replace:: + :ref:`Seq ` + .. |FOOD_NAMES| replace:: :ref:`FOOD_NAMES ` .. |FOOD_NAMES.Name| replace:: :ref:`Food ` diff --git a/doc/src/tables.m4 b/doc/src/tables.m4 index ba19d30..0199956 100644 --- a/doc/src/tables.m4 +++ b/doc/src/tables.m4 @@ -44,6 +44,7 @@ and are therefore the result of at least a rudimentary analytical process. tables/follows.rst tables/follow_observers.rst tables/follow_studies.rst + tables/food_events.rst tables/humans.rst tables/roles.rst tables/non_brec_sighting_sources.rst diff --git a/doc/src/tables/events.m4 b/doc/src/tables/events.m4 index eea26f5..327750c 100644 --- a/doc/src/tables/events.m4 +++ b/doc/src/tables/events.m4 @@ -113,7 +113,26 @@ The following table lists these rules and implications: .. _EVENTS_food_code: ``sdb_food`` (Food) - A row must exist on FOOD_EVENTS. + A related row should exist on |FOOD_EVENTS|; there should be a row + on |FOOD_EVENTS| with an |FOOD_EVENTS.EID| value of the event's + |EVENTS.EID|. + The system will generate a warning when there is no |FOOD_EVENTS| + row related to the food event. + There may be more than one of these related |FOOD_EVENTS| rows, + one for every food category/food part pairing observed. + + The |ROLES| row related to the event, the row with a |ROLES.EID| + value equal to the |EVENTS.EID| value, designates the + individual that consumed the food. + There may be at most one |ROLES| row related to the food event. + The system will generate a warning when there is no |ROLES| row + related to the food event. + + The EVENTS.\ |EVENTS.Start| column contains the time the food bout + began. + + The |EVENTS|.\ |EVENTS.Stop| column contains the time the food bout + finished. .. _EVENTS_grooming_code: diff --git a/doc/src/tables/food_events.m4 b/doc/src/tables/food_events.m4 new file mode 100644 index 0000000..a7a1028 --- /dev/null +++ b/doc/src/tables/food_events.m4 @@ -0,0 +1,172 @@ +.. Copyright (C) 2026 The Meme Factory, Inc. www.karlpinc.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +.. M4 setup +include(constants.m4)dnl +include(macros.m4)dnl +sdb_rst_quotes(`on')dnl +sdb_generated_rst()dnl + +.. _FOOD_EVENTS: + +FOOD_EVENTS +----------- + +.. |FOOD_EVENTS_summary| replace:: + + Each row represents a food eaten during a food bout recorded during + a follow. + When more than one food was eaten during a bout, this table + contains one row for each food eaten. + + +|FOOD_EVENTS_summary| + +.. sidebar:: The conversion of transcribed food-related text + + The MS Access database recorded |FOOD_EVENTS.FoodPartWritten| and + |FOOD_EVENTS.FoodNameWritten| in separate columns, but contained + only one value for each no matter how many food items were + consumed. + Consequently, the conversion of the MS Access data into SokweDB + placed each of these values into a single FOOD_EVENTS row, no + matter how many foods were consumed during the related food bout -- + no matter how many FOOD_EVENTS rows are related to the |EVENTS| row + representing the food bout. + + The data in these columns was placed in the first FOOD_EVENTS row + of the food bout, the row with a |FOOD_EVENTS.Seq| value of ``1``. + The |FOOD_EVENTS.FoodPartWritten| and |FOOD_EVENTS.FoodNameWritten| + columns of converted rows with |FOOD_EVENTS.Seq| values of ``2`` + contain the empty string, even when there was transcribed text. + + Note that there may be post-conversion data alterations and the + situation described above may not persist. + +The related |EVENTS| row must be a food event; it must have an +|EVENTS|.\ |EVENTS.Behavior| value of ``sdb_food``. +This related |EVENTS| row supplies the start and ending times of the +food bout, relates to the follow, and relates to the |ROLES| row that +identifies the individual who consumed the food. + +The value of the |FOOD_EVENTS.Seq| column must begin with ``1`` and +increase, without gaps or duplication, with every additional +FOOD_EVENTS row related to a given |EVENTS| row. +|transaction commit| + +For further information, including additional data integrity rules, +see the documentation of the :ref:`EVENTS ` +table. + + +.. contents:: + :depth: 2 + + +.. _FOOD_EVENTS.FEID: + +FEID (Food Event IDentifier) +```````````````````````````` + +.. |FOOD_EVENTS.FEID_summary| replace:: |idcol| + +|FOOD_EVENTS.FEID_summary| |notnull| + + +.. _FOOD_EVENTS.EID: + +EID (Event ID) +`````````````` + +.. |FOOD_EVENTS.EID_summary| replace:: + The |EVENTS|.\ |EVENTS.EID| identifying the food bout event. + +|FOOD_EVENTS.EID_summary| +The related event contains information on the start and stop times of +the food bout and is related to the participant, the individual +consuming the food. + +|notnull| + + +.. _FOOD_EVENTS.FoodPart: + +FoodPart +```````` + +.. |FOOD_EVENTS.FoodPart_summary| replace:: + A code indicating the part of the food source consumed. + +|FOOD_EVENTS.FoodPart_summary| +A |FOOD_PARTS|.\ |FOOD_PARTS.Part| value. +|notnull| + + +.. _FOOD_EVENTS.FoodName: + +FoodName +```````` + +.. |FOOD_EVENTS.FoodName_summary| replace:: + A code indicating the food source consumed. + +|FOOD_EVENTS.FoodName_summary| +A |FOOD_Names|.\ |FOOD_NAMES.Name| value. +|notnull| + + +.. _FOOD_EVENTS.FoodPartWritten: + +FoodPartWritten +``````````````` + +.. |FOOD_EVENTS.FoodPartWritten_summary| replace:: + A transcription of the text written in the field that describes the + food part. + +|FOOD_EVENTS.FoodPartWritten_summary| |notnull| + + +.. _FOOD_EVENTS.FoodNameWritten: + +FoodNameWritten +``````````````` + +.. |FOOD_EVENTS.FoodNameWritten_summary| replace:: + A transcription of the text written in the field that describes the + food part. + +|FOOD_EVENTS.FoodNameWritten_summary| |notnull| + + +.. _FOOD_EVENTS.Seq: + +Seq (written Sequencing) +```````````````````````` + +.. |FOOD_EVENTS.Seq_summary| replace:: + A positive integer indicating the sequence in which the food + consumed was recorded, when more than one food is consumed during + a food bout. + +|FOOD_EVENTS.Seq_summary| + +The value of this column may not be useful, or have any real +significance. +This column exists so that information (the order in which the food +consumed was written) is not lost in the conversion from written +records to digitized records. + +|notnull| -- 2.34.1