-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow state skipping for dependent encoding profiles #217
base: master
Are you sure you want to change the base?
Changes from 4 commits
c8e7926
7b8e63c
8e729ac
8401633
bd6278e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -2,7 +2,7 @@ BEGIN; | |||
|
||||
SET ROLE TO postgres; | ||||
|
||||
CREATE OR REPLACE FUNCTION ticket_state_next(param_project_id bigint, param_ticket_type enum_ticket_type, param_ticket_state enum_ticket_state) | ||||
CREATE OR REPLACE FUNCTION ticket_state_next(param_ticket_id bigint, param_ticket_state enum_ticket_state DEFAULT NULL) | ||||
RETURNS TABLE(ticket_state enum_ticket_state, service_executable boolean) AS | ||||
$$ | ||||
DECLARE | ||||
|
@@ -11,26 +11,35 @@ BEGIN | |||
SELECT | ||||
pts.ticket_state, pts.service_executable | ||||
FROM | ||||
tbl_ticket_state ts1 | ||||
tbl_ticket t | ||||
JOIN | ||||
tbl_project_ticket_state pts ON pts.ticket_type = ts1.ticket_type AND pts.ticket_state = ts1.ticket_state | ||||
tbl_ticket_state ts_this ON ts_this.ticket_type = t.ticket_type AND ts_this.ticket_state = COALESCE(param_ticket_state, t.ticket_state) | ||||
JOIN | ||||
tbl_ticket_state ts2 ON ts1.ticket_type = ts2.ticket_type AND ts1.sort > ts2.sort | ||||
tbl_project_ticket_state pts ON pts.project_id = t.project_id AND pts.ticket_type = t.ticket_type | ||||
JOIN | ||||
tbl_ticket_state ts_other ON ts_other.ticket_type = pts.ticket_type AND ts_other.ticket_state = pts.ticket_state | ||||
WHERE | ||||
pts.project_id = param_project_id AND | ||||
ts2.ticket_type = param_ticket_type AND | ||||
ts2.ticket_state = param_ticket_state | ||||
ORDER BY | ||||
ts1.sort ASC | ||||
t.id = param_ticket_id AND | ||||
ts_other.sort > ts_this.sort AND | ||||
(pts.skip_on_dependent = FALSE OR | ||||
( /* is master encoding ticket */ | ||||
SELECT ep.depends_on | ||||
FROM tbl_ticket t | ||||
INNER JOIN tbl_encoding_profile_version epv ON epv.id = t.encoding_profile_version_id | ||||
INNER JOIN tbl_encoding_profile ep ON ep.id = epv.encoding_profile_id | ||||
WHERE t.id = param_ticket_id | ||||
) IS NULL ) | ||||
ORDER BY ts_other.sort ASC | ||||
LIMIT 1; | ||||
IF NOT FOUND THEN | ||||
RETURN QUERY SELECT NULL::enum_ticket_state, false; | ||||
END IF; | ||||
|
||||
IF NOT FOUND THEN | ||||
RETURN QUERY SELECT NULL::enum_ticket_state, false; | ||||
END IF; | ||||
END | ||||
$$ | ||||
LANGUAGE plpgsql; | ||||
|
||||
CREATE OR REPLACE FUNCTION ticket_state_previous(param_project_id bigint, param_ticket_type enum_ticket_type, param_ticket_state enum_ticket_state) | ||||
CREATE OR REPLACE FUNCTION ticket_state_previous(param_ticket_id bigint, param_ticket_state enum_ticket_state DEFAULT NULL) | ||||
RETURNS TABLE(ticket_state enum_ticket_state, service_executable boolean) AS | ||||
$$ | ||||
DECLARE | ||||
|
@@ -39,21 +48,30 @@ BEGIN | |||
SELECT | ||||
pts.ticket_state, pts.service_executable | ||||
FROM | ||||
tbl_ticket_state ts1 | ||||
tbl_ticket t | ||||
JOIN | ||||
tbl_ticket_state ts_this ON ts_this.ticket_type = t.ticket_type AND ts_this.ticket_state = COALESCE(param_ticket_state, t.ticket_state) | ||||
JOIN | ||||
tbl_project_ticket_state pts ON pts.ticket_type = ts1.ticket_type AND pts.ticket_state = ts1.ticket_state | ||||
tbl_project_ticket_state pts ON pts.project_id = t.project_id AND pts.ticket_type = t.ticket_type | ||||
JOIN | ||||
tbl_ticket_state ts2 ON ts1.ticket_type = ts2.ticket_type AND ts1.sort < ts2.sort | ||||
tbl_ticket_state ts_other ON ts_other.ticket_type = pts.ticket_type AND ts_other.ticket_state = pts.ticket_state | ||||
WHERE | ||||
pts.project_id = param_project_id AND | ||||
ts2.ticket_type = param_ticket_type AND | ||||
ts2.ticket_state = param_ticket_state | ||||
ORDER BY | ||||
ts1.sort DESC | ||||
t.id = param_ticket_id AND | ||||
ts_other.sort < ts_this.sort AND | ||||
(pts.skip_on_dependent = FALSE OR | ||||
( /* is master encoding ticket */ | ||||
SELECT ep.depends_on | ||||
FROM tbl_ticket t | ||||
JOIN tbl_encoding_profile_version epv ON epv.id = t.encoding_profile_version_id | ||||
JOIN tbl_encoding_profile ep ON ep.id = epv.encoding_profile_id | ||||
WHERE t.id = param_ticket_id | ||||
) IS NULL ) | ||||
ORDER BY ts_other.sort DESC | ||||
LIMIT 1; | ||||
IF NOT FOUND THEN | ||||
RETURN QUERY SELECT NULL::enum_ticket_state, false; | ||||
END IF; | ||||
|
||||
IF NOT FOUND THEN | ||||
RETURN QUERY SELECT NULL::enum_ticket_state, false; | ||||
END IF; | ||||
END | ||||
$$ | ||||
LANGUAGE plpgsql; | ||||
|
@@ -96,22 +114,31 @@ END | |||
$$ | ||||
LANGUAGE plpgsql; | ||||
|
||||
CREATE OR REPLACE FUNCTION ticket_state_commence(param_project_id bigint, param_ticket_type enum_ticket_type) | ||||
CREATE OR REPLACE FUNCTION ticket_state_commence(param_ticket_id bigint) | ||||
RETURNS enum_ticket_state AS | ||||
$$ | ||||
DECLARE | ||||
var_project_id bigint; | ||||
var_ticket_type enum_ticket_type; | ||||
ret enum_ticket_state; | ||||
next_state record; | ||||
BEGIN | ||||
SELECT | ||||
project_id, ticket_type INTO var_project_id, var_ticket_type | ||||
FROM | ||||
tbl_ticket t | ||||
WHERE | ||||
t.id = param_ticket_id; | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens if that ticket_id is not found? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then ticket_state_initial(NULL, NULL) is called which results in
which returns NULL, so the while loop is not entered and function returns NULL. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, nothing breaks but the warning message is misleading. Mh. |
||||
|
||||
-- special case: meta ticket, since it has no serviceable states | ||||
IF param_ticket_type = 'meta' THEN | ||||
IF var_ticket_type = 'meta' THEN | ||||
RETURN 'staged'::enum_ticket_state; | ||||
END IF; | ||||
|
||||
ret := (SELECT ticket_state_initial(param_project_id, param_ticket_type)); | ||||
ret := (SELECT ticket_state_initial(var_project_id, var_ticket_type)); | ||||
|
||||
WHILE ret IS NOT NULL LOOP | ||||
SELECT * INTO next_state FROM ticket_state_next(param_project_id, param_ticket_type, ret); | ||||
SELECT * INTO next_state FROM ticket_state_next(param_ticket_id, ret); | ||||
IF NOT FOUND THEN | ||||
ret := NULL; | ||||
EXIT; | ||||
|
@@ -215,4 +242,4 @@ END | |||
$$ | ||||
LANGUAGE plpgsql; | ||||
|
||||
COMMIT; | ||||
COMMIT; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
BEGIN; | ||
|
||
SET ROLE TO postgres; | ||
|
||
ALTER TABLE tbl_project_ticket_state | ||
ADD COLUMN skip_on_dependent boolean NOT NULL DEFAULT false; | ||
|
||
ALTER TABLE tbl_ticket_state | ||
ADD COLUMN skippable_on_dependent boolean NOT NULL DEFAULT false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That column only exists in the migration patch?! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And it only seems to be used when displaying the states, but a database user would be allowed to set that flag on states not marked as skippable? or did I miss something There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It belongs to the state, so it's stored together with states. I'm not sure we need additional validation if the state marked to skip in a project is skippable? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Fixed, thanks. |
||
|
||
|
||
UPDATE tbl_ticket_state | ||
SET skippable_on_dependent = true | ||
WHERE ticket_type = 'encoding' | ||
AND ticket_state IN ('checking', 'checked', 'postprocessing', 'postprocessed', 'ready to release'); | ||
|
||
DROP FUNCTION IF EXISTS ticket_state_next(bigint); | ||
DROP FUNCTION IF EXISTS ticket_state_next(bigint, enum_ticket_type); | ||
DROP FUNCTION IF EXISTS ticket_state_next(bigint, enum_ticket_type, enum_ticket_state); | ||
|
||
DROP FUNCTION IF EXISTS ticket_state_previous(bigint); | ||
DROP FUNCTION IF EXISTS ticket_state_previous(bigint, enum_ticket_type); | ||
DROP FUNCTION IF EXISTS ticket_state_previous(bigint, enum_ticket_type, enum_ticket_state); | ||
|
||
DROP FUNCTION IF EXISTS ticket_state_commence(bigint, enum_ticket_type); | ||
DROP FUNCTION IF EXISTS ticket_state_commence(bigint); | ||
|
||
|
||
CREATE OR REPLACE FUNCTION update_ticket_next_state() | ||
RETURNS trigger AS | ||
$BODY$ | ||
DECLARE | ||
next_state record; | ||
BEGIN | ||
next_state := ticket_state_next(NEW.id, NEW.ticket_state); | ||
|
||
NEW.ticket_state_next := next_state.ticket_state; | ||
NEW.service_executable := next_state.service_executable; | ||
|
||
RETURN NEW; | ||
END | ||
$BODY$ | ||
LANGUAGE plpgsql VOLATILE; | ||
|
||
|
||
CREATE OR REPLACE FUNCTION update_all_tickets_progress_and_next_state(param_project_id bigint) | ||
RETURNS VOID AS | ||
$BODY$ | ||
BEGIN | ||
|
||
UPDATE tbl_ticket t SET | ||
(progress, ticket_state_next, service_executable) | ||
= (tp, (n).ticket_state, (n).service_executable) | ||
FROM ( | ||
SELECT id, ticket_state_next(t2.id) AS n, ticket_progress(t2.id) as tp | ||
FROM tbl_ticket t2 | ||
WHERE t2.project_id = param_project_id AND param_project_id IS NOT NULL | ||
) AS x | ||
WHERE t.id = x.id; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure why that needs a subquery?! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The function "ticket_state_next" shall not be called twice per row. No idea how to use the result of a function call in a SET block of an UPDATE statement, since you need the state and its executable flag separately. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see |
||
|
||
END; | ||
$BODY$ | ||
LANGUAGE plpgsql VOLATILE; | ||
|
||
|
||
CREATE OR REPLACE FUNCTION ticket_state_next(param_ticket_id bigint, param_ticket_state enum_ticket_state DEFAULT NULL) | ||
RETURNS TABLE(ticket_state enum_ticket_state, service_executable boolean) AS | ||
$$ | ||
DECLARE | ||
BEGIN | ||
RETURN QUERY | ||
SELECT | ||
pts.ticket_state, pts.service_executable | ||
FROM | ||
tbl_ticket t | ||
JOIN | ||
tbl_ticket_state ts_this ON ts_this.ticket_type = t.ticket_type AND ts_this.ticket_state = COALESCE(param_ticket_state, t.ticket_state) | ||
JOIN | ||
tbl_project_ticket_state pts ON pts.project_id = t.project_id AND pts.ticket_type = t.ticket_type | ||
JOIN | ||
tbl_ticket_state ts_other ON ts_other.ticket_type = pts.ticket_type AND ts_other.ticket_state = pts.ticket_state | ||
WHERE | ||
t.id = param_ticket_id AND | ||
ts_other.sort > ts_this.sort AND | ||
(pts.skip_on_dependent = FALSE OR | ||
( /* is master encoding ticket */ | ||
SELECT ep.depends_on | ||
FROM tbl_ticket t | ||
INNER JOIN tbl_encoding_profile_version epv ON epv.id = t.encoding_profile_version_id | ||
INNER JOIN tbl_encoding_profile ep ON ep.id = epv.encoding_profile_id | ||
WHERE t.id = param_ticket_id | ||
) IS NULL ) | ||
ORDER BY ts_other.sort ASC | ||
LIMIT 1; | ||
|
||
IF NOT FOUND THEN | ||
RETURN QUERY SELECT NULL::enum_ticket_state, false; | ||
END IF; | ||
END | ||
$$ | ||
LANGUAGE plpgsql; | ||
|
||
CREATE OR REPLACE FUNCTION ticket_state_previous(param_ticket_id bigint, param_ticket_state enum_ticket_state DEFAULT NULL) | ||
RETURNS TABLE(ticket_state enum_ticket_state, service_executable boolean) AS | ||
$$ | ||
DECLARE | ||
BEGIN | ||
RETURN QUERY | ||
SELECT | ||
pts.ticket_state, pts.service_executable | ||
FROM | ||
tbl_ticket t | ||
JOIN | ||
tbl_ticket_state ts_this ON ts_this.ticket_type = t.ticket_type AND ts_this.ticket_state = COALESCE(param_ticket_state, t.ticket_state) | ||
JOIN | ||
tbl_project_ticket_state pts ON pts.project_id = t.project_id AND pts.ticket_type = t.ticket_type | ||
JOIN | ||
tbl_ticket_state ts_other ON ts_other.ticket_type = pts.ticket_type AND ts_other.ticket_state = pts.ticket_state | ||
WHERE | ||
t.id = param_ticket_id AND | ||
ts_other.sort < ts_this.sort AND | ||
(pts.skip_on_dependent = FALSE OR | ||
( /* is master encoding ticket */ | ||
SELECT ep.depends_on | ||
FROM tbl_ticket t | ||
JOIN tbl_encoding_profile_version epv ON epv.id = t.encoding_profile_version_id | ||
JOIN tbl_encoding_profile ep ON ep.id = epv.encoding_profile_id | ||
WHERE t.id = param_ticket_id | ||
) IS NULL ) | ||
ORDER BY ts_other.sort DESC | ||
LIMIT 1; | ||
|
||
IF NOT FOUND THEN | ||
RETURN QUERY SELECT NULL::enum_ticket_state, false; | ||
END IF; | ||
END | ||
$$ | ||
LANGUAGE plpgsql; | ||
|
||
|
||
CREATE OR REPLACE FUNCTION ticket_state_commence(param_ticket_id bigint) | ||
RETURNS enum_ticket_state AS | ||
$$ | ||
DECLARE | ||
var_project_id bigint; | ||
var_ticket_type enum_ticket_type; | ||
ret enum_ticket_state; | ||
next_state record; | ||
BEGIN | ||
SELECT | ||
project_id, ticket_type INTO var_project_id, var_ticket_type | ||
FROM | ||
tbl_ticket t | ||
WHERE | ||
t.id = param_ticket_id; | ||
|
||
-- special case: meta ticket, since it has no serviceable states | ||
IF var_ticket_type = 'meta' THEN | ||
RETURN 'staged'::enum_ticket_state; | ||
END IF; | ||
|
||
ret := (SELECT ticket_state_initial(var_project_id, var_ticket_type)); | ||
|
||
WHILE ret IS NOT NULL LOOP | ||
SELECT * INTO next_state FROM ticket_state_next(param_ticket_id, ret); | ||
IF NOT FOUND THEN | ||
ret := NULL; | ||
EXIT; | ||
END IF; | ||
|
||
-- exit, if serviceable state is found | ||
EXIT WHEN next_state.service_executable IS TRUE; | ||
|
||
-- otherwise set current state as possible commence state | ||
ret := next_state.ticket_state; | ||
END LOOP; | ||
|
||
RETURN ret; | ||
END | ||
$$ | ||
LANGUAGE plpgsql; | ||
|
||
|
||
COMMIT; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Second time the exact same subquery is used. Would it be worth it to have is
is_master_ticket(ticket_id)
?