Skip to content

Commit b66adbd

Browse files
authored
fix: update level on object update (#768)
1 parent 84dfe26 commit b66adbd

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
CREATE OR REPLACE FUNCTION "storage"."objects_update_level_trigger"()
2+
RETURNS trigger
3+
AS $func$
4+
BEGIN
5+
-- Ensure this is an update operation and the name has changed
6+
IF TG_OP = 'UPDATE' AND (NEW."name" <> OLD."name" OR NEW."bucket_id" <> OLD."bucket_id") THEN
7+
-- Set the new level
8+
NEW."level" := "storage"."get_level"(NEW."name");
9+
END IF;
10+
RETURN NEW;
11+
END;
12+
$func$ LANGUAGE plpgsql VOLATILE;
13+
14+
CREATE OR REPLACE TRIGGER "objects_update_level_trigger"
15+
BEFORE UPDATE ON "storage"."objects"
16+
FOR EACH ROW
17+
WHEN (NEW.name != OLD.name OR NEW.bucket_id != OLD.bucket_id)
18+
EXECUTE FUNCTION "storage"."objects_update_level_trigger"();
19+
20+
21+
CREATE OR REPLACE FUNCTION storage.delete_leaf_prefixes(bucket_ids text[], names text[])
22+
RETURNS void
23+
LANGUAGE plpgsql
24+
SECURITY DEFINER
25+
AS $$
26+
DECLARE
27+
v_rows_deleted integer;
28+
BEGIN
29+
LOOP
30+
WITH candidates AS (
31+
SELECT DISTINCT
32+
t.bucket_id,
33+
unnest(storage.get_prefixes(t.name)) AS name
34+
FROM unnest(bucket_ids, names) AS t(bucket_id, name)
35+
),
36+
uniq AS (
37+
SELECT
38+
bucket_id,
39+
name,
40+
storage.get_level(name) AS level
41+
FROM candidates
42+
WHERE name <> ''
43+
GROUP BY bucket_id, name
44+
),
45+
leaf AS (
46+
SELECT
47+
p.bucket_id,
48+
p.name,
49+
p.level
50+
FROM storage.prefixes AS p
51+
JOIN uniq AS u
52+
ON u.bucket_id = p.bucket_id
53+
AND u.name = p.name
54+
AND u.level = p.level
55+
WHERE NOT EXISTS (
56+
SELECT 1
57+
FROM storage.objects AS o
58+
WHERE o.bucket_id = p.bucket_id
59+
AND o.level = p.level + 1
60+
AND o.name COLLATE "C" LIKE p.name || '/%'
61+
)
62+
AND NOT EXISTS (
63+
SELECT 1
64+
FROM storage.prefixes AS c
65+
WHERE c.bucket_id = p.bucket_id
66+
AND c.level = p.level + 1
67+
AND c.name COLLATE "C" LIKE p.name || '/%'
68+
)
69+
)
70+
DELETE
71+
FROM storage.prefixes AS p
72+
USING leaf AS l
73+
WHERE p.bucket_id = l.bucket_id
74+
AND p.name = l.name
75+
AND p.level = l.level;
76+
77+
GET DIAGNOSTICS v_rows_deleted = ROW_COUNT;
78+
EXIT WHEN v_rows_deleted = 0;
79+
END LOOP;
80+
END;
81+
$$;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
DO $$
2+
BEGIN
3+
IF EXISTS(
4+
SELECT id FROM storage.migrations
5+
WHERE name = 'fix-prefix-race-conditions-optimized'
6+
AND executed_at >= now() - interval '1 minutes'
7+
) THEN
8+
RETURN;
9+
END IF;
10+
11+
-- Update all object levels based on their names that are incorrect
12+
UPDATE storage.objects SET level = storage.get_level(name)
13+
WHERE level != storage.get_level(name);
14+
END$$;

src/internal/database/migrations/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,6 @@ export const DBMigration = {
3939
'iceberg-catalog-flag-on-buckets': 38,
4040
'add-search-v2-sort-support': 39,
4141
'fix-prefix-race-conditions-optimized': 40,
42+
'add-object-level-update-trigger': 41,
43+
'fix-object-level': 42,
4244
}

0 commit comments

Comments
 (0)