Changes between Initial Version and Version 1 of AditionalApplicationDevelopment


Ignore:
Timestamp:
09/15/25 13:20:45 (8 hours ago)
Author:
221028
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • AditionalApplicationDevelopment

    v1 v1  
     1
     2== Напредни PostgreSQL компоненти
     3
     4** 1) Интегритетни ограничувања (CHECK/UNIQUE)**
     5**1.1 Реакција: различни елементи**
     6
     7{{{
     8ALTER TABLE reaction
     9  ADD CONSTRAINT reaction_distinct_elements
     10  CHECK (element1_id <> element2_id);
     11}}}
     12
     13
     14**1.2 Елементи: валидни физички вредности**
     15
     16{{{
     17ALTER TABLE elements
     18  ADD CONSTRAINT elements_atomic_number_positive CHECK (atomic_number > 0);
     19
     20ALTER TABLE elements
     21  ADD CONSTRAINT elements_mass_positive CHECK (atomic_weight > 0);
     22
     23ALTER TABLE elements
     24  ADD CONSTRAINT elements_melting_before_boiling CHECK (
     25    boiling_point IS NULL OR melting_point IS NULL OR melting_point < boiling_point
     26  );
     27
     28}}}
     29
     30**1.3 Партиципација: без дупликати**
     31
     32{{{
     33ALTER TABLE userparticipatesinexperiment
     34  ADD CONSTRAINT uq_user_experiment UNIQUE (user_id, experiment_id);
     35}}}
     36
     37
     38**2) Временско печатење на учество**
     39
     40{{{
     41ALTER TABLE userparticipatesinexperiment
     42  ADD COLUMN IF NOT EXISTS participation_timestamp TIMESTAMPTZ;
     43
     44UPDATE userparticipatesinexperiment
     45   SET participation_timestamp = COALESCE(participation_timestamp, NOW());
     46
     47ALTER TABLE userparticipatesinexperiment
     48  ALTER COLUMN participation_timestamp SET NOT NULL,
     49  ALTER COLUMN participation_timestamp SET DEFAULT NOW();
     50}}}
     51 
     52
     53**3) Тригер: set_default_safety (на experiment)
     54**
     55
     56{{{
     57CREATE OR REPLACE FUNCTION trg_experiment_default_safety()
     58RETURNS TRIGGER AS $$
     59BEGIN
     60  IF NEW.safety_warning IS NULL OR NEW.safety_warning = '' THEN
     61    NEW.safety_warning := 'Стандардни безбедносни мерки';
     62  END IF;
     63  RETURN NEW;
     64END;
     65$$ LANGUAGE plpgsql;
     66
     67DROP TRIGGER IF EXISTS set_default_safety ON experiment;
     68CREATE TRIGGER set_default_safety
     69BEFORE INSERT ON experiment
     70FOR EACH ROW
     71EXECUTE FUNCTION trg_experiment_default_safety();
     72
     73}}}
     74
     75
     76**4) Погледи (Views)**
     77**4.1 vw_students_experiments_detailed**
     78
     79
     80{{{
     81CREATE OR REPLACE VIEW vw_students_experiments_detailed AS
     82SELECT
     83  s.student_id,
     84  (u.user_name || ' ' || u.user_surname) AS full_name,
     85  e.experiment_id,
     86  e.result,
     87  e.time_stamp AS participation_time
     88FROM student s
     89JOIN "User" u ON s.student_id = u.user_id
     90JOIN userparticipatesinexperiment up ON s.student_id = up.user_id
     91JOIN experiment e ON up.experiment_id = e.experiment_id
     92ORDER BY u.user_name, e.time_stamp DESC;
     93
     94}}}
     95
     96**4.2 vw_user_activity_summary**
     97
     98
     99{{{
     100CREATE OR REPLACE VIEW vw_user_activity_summary AS
     101SELECT
     102  u.user_id,
     103  (u.user_name || ' ' || u.user_surname) AS full_name,
     104  u.role,
     105  COUNT(DISTINCT uve.element_id)    AS elements_viewed,
     106  COUNT(DISTINCT uvl.equipment_id)  AS equipment_viewed,
     107  COUNT(DISTINCT upe.experiment_id) AS experiments_participated
     108FROM "User" u
     109LEFT JOIN userviewselement           uve ON u.user_id = uve.user_id
     110LEFT JOIN userviewslabequipment      uvl ON u.user_id = uvl.user_id
     111LEFT JOIN userparticipatesinexperiment upe ON u.user_id = upe.user_id
     112GROUP BY u.user_id, full_name, u.role
     113ORDER BY full_name;
     114
     115}}}
     116
     117**4.3 vw_students_experiments_for_teacher**
     118
     119
     120{{{
     121CREATE OR REPLACE VIEW vw_students_experiments_for_teacher AS
     122SELECT
     123  (u.user_name || ' ' || u.user_surname) AS student_name,
     124  s.student_id,
     125  e.experiment_id,
     126  e.result,
     127  e.time_stamp,
     128  r.product,
     129  el1.symbol AS element1_symbol,
     130  el2.symbol AS element2_symbol,
     131  up.participation_timestamp AS participation_date,
     132  s.teacher_id
     133FROM student s
     134JOIN "User" u ON s.student_id = u.user_id
     135JOIN userparticipatesinexperiment up ON s.student_id = up.user_id
     136JOIN experiment e ON up.experiment_id = e.experiment_id
     137JOIN reaction  r ON e.reaction_id   = r.reaction_id
     138JOIN elements el1 ON r.element1_id = el1.element_id
     139JOIN elements el2 ON r.element2_id = el2.element_id
     140ORDER BY up.participation_timestamp DESC, student_name;
     141}}}
     142
     143
     144**5) Stored function: create_reaction_and_experiment_fn(...)**
     145
     146
     147{{{
     148create_reaction_and_experiment_fn(
     149  p_teacher_id    INT,
     150  p_element1_id   INT,
     151  p_element2_id   INT,
     152  p_product       TEXT,
     153  p_conditions    TEXT,
     154  p_exp_result    TEXT,
     155  p_safety        TEXT,
     156  p_equipment_ids INT[]
     157) RETURNS TABLE(reaction_id INT, experiment_id INT)
     158
     159}}}
     160
     161
     162Логика (атомично во една функција):
     163
     164INSERT во reaction → reaction_id.
     165
     166Ако p_exp_result е празен → авто-генерира текст „Експеримент со X + Y…“.
     167
     168INSERT во experiment (time_stamp = CURRENT_TIMESTAMP, safety_warning = p_safety).
     169
     170Ако има p_equipment_ids → INSERT во experimentlabequipment со unnest(p_equipment_ids).
     171
     172Враќа {reaction_id, experiment_id}.
     173
     174Во апликацијата, оваа функција се повикува ако е достапна; ако не, има Python fallback со транскација (исто поведение).
     175
     176**6) Индекси (перформанси)**
     177
     178{{{
     179CREATE INDEX IF NOT EXISTS idx_reaction_elements ON reaction (element1_id, element2_id);
     180CREATE INDEX IF NOT EXISTS idx_exp_reaction      ON experiment (reaction_id);
     181CREATE INDEX IF NOT EXISTS idx_up_user           ON userparticipatesinexperiment (user_id);
     182CREATE INDEX IF NOT EXISTS idx_up_experiment     ON userparticipatesinexperiment (experiment_id);
     183}}}
     184
     185