fix: use two-phase bump when shifting sort_order on content insert
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
a704c3b29f
commit
a4792206f7
|
|
@ -9,61 +9,83 @@ import (
|
|||
// Sequential siblings (programs global, courses per program, modules per course, lessons per module) use unique sort_order.
|
||||
// These helpers move id from oldPos to newPos without collisions by temporarily assigning sort_order = -id then shifting intermediates.
|
||||
|
||||
// shift*SortOrderForInsert makes room at fromPos by incrementing existing rows at/after that position.
|
||||
// Rows are updated highest-first so the unique (parent, sort_order) index is never violated mid-shift.
|
||||
// sortOrderInsertShiftBump moves affected rows into a high temporary range, then back to
|
||||
// (old + 1). A single UPDATE ... SET sort_order = sort_order + 1 can violate unique
|
||||
// (parent, sort_order) indexes because PostgreSQL does not apply row updates in sort order.
|
||||
const sortOrderInsertShiftBump = int32(1_000_000)
|
||||
|
||||
func shiftProgramsSortOrderForInsert(ctx context.Context, tx pgx.Tx, fromPos int32) error {
|
||||
bump := sortOrderInsertShiftBump
|
||||
if _, err := tx.Exec(ctx, `
|
||||
UPDATE programs
|
||||
SET sort_order = sort_order + $2
|
||||
WHERE sort_order >= $1`, fromPos, bump); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := tx.Exec(ctx, `
|
||||
UPDATE programs AS t
|
||||
SET sort_order = t.sort_order + 1
|
||||
FROM (
|
||||
SELECT id FROM programs WHERE sort_order >= $1 ORDER BY sort_order DESC
|
||||
) AS s
|
||||
WHERE t.id = s.id`, fromPos)
|
||||
UPDATE programs
|
||||
SET sort_order = sort_order - $2
|
||||
WHERE sort_order >= $1`, bump, bump-1)
|
||||
return err
|
||||
}
|
||||
|
||||
func shiftCoursesSortOrderForInsert(ctx context.Context, tx pgx.Tx, programID int64, fromPos int32) error {
|
||||
bump := sortOrderInsertShiftBump
|
||||
if _, err := tx.Exec(ctx, `
|
||||
UPDATE courses
|
||||
SET sort_order = sort_order + $3
|
||||
WHERE program_id = $1 AND sort_order >= $2`, programID, fromPos, bump); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := tx.Exec(ctx, `
|
||||
UPDATE courses AS t
|
||||
SET sort_order = t.sort_order + 1
|
||||
FROM (
|
||||
SELECT id FROM courses WHERE program_id = $1 AND sort_order >= $2 ORDER BY sort_order DESC
|
||||
) AS s
|
||||
WHERE t.id = s.id`, programID, fromPos)
|
||||
UPDATE courses
|
||||
SET sort_order = sort_order - $3
|
||||
WHERE program_id = $1 AND sort_order >= $2`, programID, bump, bump-1)
|
||||
return err
|
||||
}
|
||||
|
||||
func shiftModulesSortOrderForInsert(ctx context.Context, tx pgx.Tx, courseID int64, fromPos int32) error {
|
||||
bump := sortOrderInsertShiftBump
|
||||
if _, err := tx.Exec(ctx, `
|
||||
UPDATE modules
|
||||
SET sort_order = sort_order + $3
|
||||
WHERE course_id = $1 AND sort_order >= $2`, courseID, fromPos, bump); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := tx.Exec(ctx, `
|
||||
UPDATE modules AS t
|
||||
SET sort_order = t.sort_order + 1
|
||||
FROM (
|
||||
SELECT id FROM modules WHERE course_id = $1 AND sort_order >= $2 ORDER BY sort_order DESC
|
||||
) AS s
|
||||
WHERE t.id = s.id`, courseID, fromPos)
|
||||
UPDATE modules
|
||||
SET sort_order = sort_order - $3
|
||||
WHERE course_id = $1 AND sort_order >= $2`, courseID, bump, bump-1)
|
||||
return err
|
||||
}
|
||||
|
||||
func shiftLessonsSortOrderForInsert(ctx context.Context, tx pgx.Tx, moduleID int64, fromPos int32) error {
|
||||
bump := sortOrderInsertShiftBump
|
||||
if _, err := tx.Exec(ctx, `
|
||||
UPDATE lessons
|
||||
SET sort_order = sort_order + $3
|
||||
WHERE module_id = $1 AND sort_order >= $2`, moduleID, fromPos, bump); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := tx.Exec(ctx, `
|
||||
UPDATE lessons AS t
|
||||
SET sort_order = t.sort_order + 1
|
||||
FROM (
|
||||
SELECT id FROM lessons WHERE module_id = $1 AND sort_order >= $2 ORDER BY sort_order DESC
|
||||
) AS s
|
||||
WHERE t.id = s.id`, moduleID, fromPos)
|
||||
UPDATE lessons
|
||||
SET sort_order = sort_order - $3
|
||||
WHERE module_id = $1 AND sort_order >= $2`, moduleID, bump, bump-1)
|
||||
return err
|
||||
}
|
||||
|
||||
func shiftExamPrepUnitsSortOrderForInsert(ctx context.Context, tx pgx.Tx, catalogCourseID int64, fromPos int32) error {
|
||||
bump := sortOrderInsertShiftBump
|
||||
if _, err := tx.Exec(ctx, `
|
||||
UPDATE exam_prep.units
|
||||
SET sort_order = sort_order + $3
|
||||
WHERE catalog_course_id = $1 AND sort_order >= $2`, catalogCourseID, fromPos, bump); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := tx.Exec(ctx, `
|
||||
UPDATE exam_prep.units AS t
|
||||
SET sort_order = t.sort_order + 1
|
||||
FROM (
|
||||
SELECT id FROM exam_prep.units WHERE catalog_course_id = $1 AND sort_order >= $2 ORDER BY sort_order DESC
|
||||
) AS s
|
||||
WHERE t.id = s.id`, catalogCourseID, fromPos)
|
||||
UPDATE exam_prep.units
|
||||
SET sort_order = sort_order - $3
|
||||
WHERE catalog_course_id = $1 AND sort_order >= $2`, catalogCourseID, bump, bump-1)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user