Changes between Version 4 and Version 5 of appdevelopment


Ignore:
Timestamp:
09/30/25 18:44:37 (2 weeks ago)
Author:
155036
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • appdevelopment

    v4 v5  
    123123        out = event_create(payload)  # повик на p_event_create
    124124        return Response(out, status=201)
     125}}}
     126
     127=== p_event_create_bulk ===
     128{{{
     129CREATE OR REPLACE PROCEDURE p_event_bulk_create(
     130  IN  _items jsonb,
     131  INOUT cur refcursor
     132)
     133LANGUAGE plpgsql
     134AS $$
     135BEGIN
     136  -- Validate top-level shape
     137  IF jsonb_typeof(_items) <> 'array' THEN
     138    RAISE EXCEPTION 'payload must be a JSON array';
     139  END IF;
     140
     141  OPEN cur FOR
     142  WITH ins AS (
     143      INSERT INTO events (
     144        sql_date, is_root_event, event_code, goldstein_scale,
     145        num_mentions, num_sources, num_articles, avg_tone,
     146        month_year, year, fraction_date
     147      )
     148      SELECT
     149        (x->>'sql_date')::date,
     150        COALESCE((x->>'is_root_event')::boolean, TRUE),
     151        (x->>'event_code')::text,
     152        NULLIF(x->>'goldstein_scale','')::numeric,
     153        NULLIF(x->>'num_mentions','')::int,
     154        NULLIF(x->>'num_sources','')::int,
     155        NULLIF(x->>'num_articles','')::int,
     156        NULLIF(x->>'avg_tone','')::numeric,
     157        to_char((x->>'sql_date')::date, 'MMYYYY'),
     158        EXTRACT(YEAR FROM (x->>'sql_date')::date)::int,
     159        EXTRACT(DOY FROM (x->>'sql_date')::date) / 365.0
     160      FROM jsonb_array_elements(_items) AS x
     161      RETURNING global_event_id, sql_date, event_code
     162  )
     163  SELECT jsonb_build_object(
     164    'ok', true,
     165    'inserted_count', (SELECT count(*) FROM ins),
     166    'inserted_ids', (SELECT jsonb_agg(global_event_id) FROM ins)
     167  ) AS j;
     168
     169EXCEPTION
     170  WHEN OTHERS THEN
     171    -- Any error will abort the outer transaction unless handled
     172    RAISE;
     173END;
     174$$;
     175}}}
     176
     177=== p_event_create_update_delete_bulk ===
     178{{{
     179
     180-- Multiple operations in one go: INSERT + UPDATE + DELETE
     181-- Payload shape:
     182-- {
     183--   "insert": [
     184--     {
     185--       "sql_date": "2025-09-01",
     186--       "is_root_event": true,
     187--       "event_code": "E123",
     188--       "goldstein_scale": 1.5,
     189--       "num_mentions": 5,
     190--       "num_sources": 2,
     191--       "num_articles": 3,
     192--       "avg_tone": 0.75
     193--     }, ...
     194--   ],
     195--   "update": [
     196--     {
     197--       "global_event_id": 42,
     198--       "sql_date": "2025-09-02",         
     199--       "num_mentions": 7,
     200--       "avg_tone": 0.1
     201--     }, ...
     202--   ],
     203--   "delete": [ 10, 11, 12 ]     
     204-- }
     205
     206CREATE OR REPLACE PROCEDURE p_event_bulk_apply(
     207  IN  _payload jsonb,
     208  INOUT cur refcursor DEFAULT NULL
     209)
     210LANGUAGE plpgsql
     211AS $$
     212DECLARE
     213  v_has_insert boolean := (_payload ? 'insert');
     214  v_has_update boolean := (_payload ? 'update');
     215  v_has_delete boolean := (_payload ? 'delete');
     216BEGIN
     217  -- Basic validation
     218  IF _payload IS NULL OR jsonb_typeof(_payload) <> 'object' THEN
     219    RAISE EXCEPTION 'payload must be a JSON object with optional keys: insert, update, delete';
     220  END IF;
     221  IF v_has_insert AND jsonb_typeof(_payload->'insert') <> 'array' THEN
     222    RAISE EXCEPTION '"insert" must be an array';
     223  END IF;
     224  IF v_has_update AND jsonb_typeof(_payload->'update') <> 'array' THEN
     225    RAISE EXCEPTION '"update" must be an array';
     226  END IF;
     227  IF v_has_delete AND jsonb_typeof(_payload->'delete') <> 'array' THEN
     228    RAISE EXCEPTION '"delete" must be an array of IDs';
     229  END IF;
     230
     231  -- Perform all operations in a single statement block using CTEs
     232  IF cur IS NULL THEN cur := 'cur_event_bulk_apply'; END IF;
     233  OPEN cur FOR
     234  WITH
     235  -- 1) INSERT many (optional)
     236  ins AS (
     237    SELECT * FROM (
     238      INSERT INTO events (
     239        sql_date, is_root_event, event_code, goldstein_scale,
     240        num_mentions, num_sources, num_articles, avg_tone,
     241        month_year, year, fraction_date
     242      )
     243      SELECT
     244        (x->>'sql_date')::date,
     245        COALESCE((x->>'is_root_event')::boolean, TRUE),
     246        UPPER((x->>'event_code')::text),
     247        NULLIF(x->>'goldstein_scale','')::numeric,
     248        NULLIF(x->>'num_mentions','')::int,
     249        NULLIF(x->>'num_sources','')::int,
     250        NULLIF(x->>'num_articles','')::int,
     251        NULLIF(x->>'avg_tone','')::numeric,
     252        TO_CHAR((x->>'sql_date')::date, 'MMYYYY'),
     253        EXTRACT(YEAR FROM (x->>'sql_date')::date)::int,
     254        EXTRACT(DOY FROM (x->>'sql_date')::date)::numeric / 365.0
     255      FROM jsonb_array_elements(COALESCE(_payload->'insert', '[]'::jsonb)) AS x
     256      RETURNING global_event_id
     257    ) t
     258  ),
     259  upd_src AS (
     260    SELECT *
     261    FROM jsonb_to_recordset(COALESCE(_payload->'update','[]'::jsonb)) AS r(
     262      global_event_id int,
     263      sql_date date,
     264      is_root_event boolean,
     265      event_code text,
     266      goldstein_scale numeric(5,2),
     267      num_mentions int,
     268      num_sources int,
     269      num_articles int,
     270      avg_tone numeric(5,2)
     271    )
     272  ),
     273  upd AS (
     274    UPDATE events e
     275    SET
     276      sql_date       = COALESCE(u.sql_date, e.sql_date),
     277      is_root_event  = COALESCE(u.is_root_event, e.is_root_event),
     278      event_code     = COALESCE(UPPER(u.event_code), e.event_code),
     279      goldstein_scale= COALESCE(u.goldstein_scale, e.goldstein_scale),
     280      num_mentions   = COALESCE(u.num_mentions, e.num_mentions),
     281      num_sources    = COALESCE(u.num_sources,  e.num_sources),
     282      num_articles   = COALESCE(u.num_articles, e.num_articles),
     283      avg_tone       = COALESCE(u.avg_tone,     e.avg_tone),
     284      month_year     = CASE WHEN u.sql_date IS NULL THEN e.month_year ELSE TO_CHAR(u.sql_date,'MMYYYY') END,
     285      year           = CASE WHEN u.sql_date IS NULL THEN e.year ELSE EXTRACT(YEAR FROM u.sql_date)::int END,
     286      fraction_date  = CASE WHEN u.sql_date IS NULL THEN e.fraction_date ELSE (EXTRACT(DOY FROM u.sql_date)::numeric / 365.0) END
     287    FROM upd_src u
     288    WHERE e.global_event_id = u.global_event_id
     289    RETURNING e.global_event_id
     290  ),
     291  -- 3) DELETE many (optional)
     292  del_ids AS (
     293    SELECT (x)::int AS id
     294    FROM jsonb_array_elements_text(COALESCE(_payload->'delete','[]'::jsonb)) AS x
     295  ),
     296  del AS (
     297    DELETE FROM events e
     298    USING del_ids d
     299    WHERE e.global_event_id = d.id
     300    RETURNING e.global_event_id
     301  )
     302  SELECT jsonb_build_object(
     303    'ok', true,
     304    'inserted_count', (SELECT COUNT(*) FROM ins),
     305    'inserted_ids',   COALESCE((SELECT jsonb_agg(global_event_id) FROM ins), '[]'::jsonb),
     306    'updated_count',  (SELECT COUNT(*) FROM upd),
     307    'updated_ids',    COALESCE((SELECT jsonb_agg(global_event_id) FROM upd), '[]'::jsonb),
     308    'deleted_count',  (SELECT COUNT(*) FROM del),
     309    'deleted_ids',    COALESCE((SELECT jsonb_agg(global_event_id) FROM del), '[]'::jsonb)
     310  ) AS j;
     311
     312
     313EXCEPTION
     314  WHEN OTHERS THEN
     315    RAISE;
     316END;
     317$$;
    125318}}}
    126319
     
    183376$$;
    184377}}}
     378
    185379
    186380=== p_event_get ===