Skip to content

Commit

Permalink
fix reportportal#194: Incorrect deep merge of suites with has_childre…
Browse files Browse the repository at this point in the history
…n = false
  • Loading branch information
mrbinwin committed Aug 16, 2021
1 parent 15cbb71 commit 1bdd537
Show file tree
Hide file tree
Showing 2 changed files with 503 additions and 0 deletions.
251 changes: 251 additions & 0 deletions migrations/49_merge_suit_with_no_children_fix.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
CREATE OR REPLACE FUNCTION merge_launch(launchid BIGINT)
RETURNS INTEGER
AS
$$
DECLARE
target_item_cursor CURSOR (id BIGINT, lvl INT) FOR
SELECT DISTINCT ON (unique_id) unique_id, item_id, path AS path_value, has_children
FROM test_item parent
WHERE parent.launch_id = id
AND nlevel(parent.path) = lvl
AND has_stats
AND (parent.type = 'SUITE' OR (SELECT EXISTS(SELECT 1 FROM test_item t WHERE t.parent_id = parent.item_id LIMIT 1)));
DECLARE
merging_item_cursor CURSOR (uniqueid VARCHAR, lvl INT, launchid BIGINT) FOR
SELECT item_id, path AS path_value, has_retries
FROM test_item
WHERE test_item.unique_id = uniqueid
AND has_stats
AND nlevel(test_item.path) = lvl
AND test_item.launch_id = launchid;
DECLARE
target_item_field RECORD;
DECLARE
merging_item_field RECORD;
DECLARE
max_level BIGINT;
DECLARE
first_item_unique_id VARCHAR;
DECLARE
item_has_children BOOLEAN;
DECLARE
parent_item_id BIGINT;
DECLARE
parent_item_path LTREE;
DECLARE
nested_step_path LTREE;
DECLARE
previous_parent_path LTREE;
DECLARE
concatenated_descr TEXT;
DECLARE
nested_step_nlevel INTEGER;
BEGIN
max_level := (SELECT MAX(nlevel(path))
FROM test_item
WHERE launch_id = launchid
AND has_stats);
IF (max_level ISNULL)
THEN
RETURN 0;
END IF;

FOR i IN 1..max_level
LOOP

OPEN target_item_cursor(launchid, i);

LOOP
FETCH target_item_cursor INTO target_item_field;

EXIT WHEN NOT found;

first_item_unique_id := target_item_field.unique_id;
parent_item_id := target_item_field.item_id;
parent_item_path := target_item_field.path_value;
item_has_children := target_item_field.has_children;

EXIT WHEN first_item_unique_id ISNULL;

IF item_has_children
THEN
SELECT string_agg(description, chr(10))
INTO concatenated_descr
FROM test_item
WHERE test_item.unique_id = first_item_unique_id
AND has_stats
AND has_children
AND nlevel(test_item.path) = i
AND test_item.launch_id = launchid;

UPDATE test_item SET description = concatenated_descr WHERE test_item.item_id = parent_item_id;

UPDATE test_item
SET start_time = (SELECT min(start_time)
FROM test_item
WHERE test_item.unique_id = first_item_unique_id
AND has_stats
AND has_children
AND nlevel(test_item.path) = i
AND test_item.launch_id = launchid)
WHERE test_item.item_id = parent_item_id;

UPDATE test_item_results
SET end_time = (SELECT max(end_time)
FROM test_item
JOIN test_item_results result ON test_item.item_id = result.result_id
WHERE test_item.unique_id = first_item_unique_id
AND has_stats
AND has_children
AND nlevel(test_item.path) = i
AND test_item.launch_id = launchid)
WHERE test_item_results.result_id = parent_item_id;

INSERT INTO statistics (statistics_field_id, item_id, launch_id, s_counter)
SELECT statistics_field_id, parent_item_id, NULL, sum(s_counter)
FROM statistics
JOIN test_item ti ON statistics.item_id = ti.item_id
WHERE ti.unique_id = first_item_unique_id
AND ti.launch_id = launchid
AND nlevel(ti.path) = i
AND ti.has_stats
AND ti.has_children
GROUP BY statistics_field_id
ON CONFLICT ON CONSTRAINT unique_stats_item DO UPDATE
SET s_counter = excluded.s_counter;

IF exists(SELECT 1
FROM test_item_results
JOIN test_item t ON test_item_results.result_id = t.item_id
WHERE (test_item_results.status != 'PASSED' AND test_item_results.status != 'SKIPPED')
AND t.unique_id = first_item_unique_id
AND nlevel(t.path) = i
AND t.has_stats
AND t.has_children
AND t.launch_id = launchid)
THEN
UPDATE test_item_results SET status = 'FAILED' WHERE test_item_results.result_id = parent_item_id;
ELSEIF exists(SELECT 1
FROM test_item_results
JOIN test_item t ON test_item_results.result_id = t.item_id
WHERE test_item_results.status != 'PASSED'
AND t.unique_id = first_item_unique_id
AND nlevel(t.path) = i
AND t.has_stats
AND t.has_children
AND t.launch_id = launchid)
THEN
UPDATE test_item_results SET status = 'SKIPPED' WHERE test_item_results.result_id = parent_item_id;
ELSE
UPDATE test_item_results SET status = 'PASSED' WHERE test_item_results.result_id = parent_item_id;
END IF;
END IF;


OPEN merging_item_cursor(target_item_field.unique_id, i, launchid);

LOOP

FETCH merging_item_cursor INTO merging_item_field;

EXIT WHEN NOT found;

IF (SELECT EXISTS(SELECT 1
FROM test_item t
WHERE (t.parent_id = merging_item_field.item_id
OR (t.item_id = merging_item_field.item_id AND t.type = 'SUITE'))
AND t.has_stats))
THEN
UPDATE test_item
SET parent_id = parent_item_id,
path = text2ltree(concat(parent_item_path :: TEXT, '.', test_item.item_id :: TEXT))
WHERE test_item.parent_id = merging_item_field.item_id
AND nlevel(test_item.path) = i + 1
AND has_stats
AND test_item.retry_of IS NULL;

UPDATE test_item
SET parent_id = parent_item_id,
path = text2ltree(
concat(parent_item_path :: TEXT, '.', test_item.retry_of ::TEXT, '.', test_item.item_id :: TEXT))
WHERE test_item.parent_id = merging_item_field.item_id
AND test_item.retry_of IS NOT NULL;

IF parent_item_id != merging_item_field.item_id
THEN
UPDATE attachment
SET item_id = parent_item_id
WHERE attachment.item_id = merging_item_field.item_id;

UPDATE log
SET item_id = parent_item_id
WHERE log.item_id = merging_item_field.item_id;

DELETE
FROM test_item
WHERE test_item.item_id = merging_item_field.item_id
AND test_item.has_stats;
END IF;

ELSE
IF
merging_item_field.has_retries
THEN
UPDATE test_item
SET path = text2ltree(concat(merging_item_field.path_value :: TEXT, '.', test_item.item_id :: TEXT))
WHERE test_item.retry_of = merging_item_field.item_id;
END IF;

nested_step_path :=
(SELECT path FROM test_item WHERE parent_id = merging_item_field.item_id AND NOT has_stats LIMIT 1);
IF
nested_step_path IS NOT NULL
THEN

nested_step_nlevel = nlevel(nested_step_path) - 2;
IF nested_step_nlevel < 0
THEN
nested_step_nlevel = 0;
END IF;

previous_parent_path := text2ltree(
concat(subpath(nested_step_path, 0, nested_step_nlevel) :: TEXT, '.', merging_item_field.item_id :: TEXT));

UPDATE test_item
SET path = text2ltree(concat(merging_item_field.path_value :: TEXT, '.',
subpath(path, nlevel(merging_item_field.path_value)) :: TEXT))
WHERE path <@ previous_parent_path
AND item_id != merging_item_field.item_id
AND NOT has_stats;
END IF;


END IF;


END LOOP;

CLOSE merging_item_cursor;

END LOOP;

CLOSE target_item_cursor;

END LOOP;


INSERT INTO statistics (statistics_field_id, launch_id, s_counter)
SELECT statistics_field_id, launchid, sum(s_counter)
FROM statistics
JOIN test_item ti ON statistics.item_id = ti.item_id
WHERE ti.launch_id = launchid
AND ti.has_stats
AND ti.parent_id IS NULL
GROUP BY statistics_field_id
ON CONFLICT ON CONSTRAINT unique_stats_launch DO UPDATE
SET s_counter = excluded.s_counter;

RETURN 0;
END;
$$
LANGUAGE plpgsql;
Loading

0 comments on commit 1bdd537

Please sign in to comment.