Skip to content

Commit f0ae728

Browse files
committed
fix: make storage migrations idempotent
1 parent 4f66e94 commit f0ae728

File tree

7 files changed

+32
-13
lines changed

7 files changed

+32
-13
lines changed

.github/workflows/ci.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,17 @@ jobs:
9595
with:
9696
github-token: ${{ secrets.GITHUB_TOKEN }}
9797

98+
- name: Verify migration idempotency
99+
run: |
100+
psql "${{ env.DATABASE_URL }}" -c "DROP TABLE IF EXISTS storage.migrations;"
101+
npm run migration:run
102+
env:
103+
DATABASE_URL: postgresql://postgres:[email protected]/postgres
104+
DB_INSTALL_ROLES: true
105+
ENABLE_DEFAULT_METRICS: false
106+
PG_QUEUE_ENABLE: false
107+
MULTI_TENANT: false
108+
98109
- name: Ensure OrioleDB migration compatibility
99110
run: |
100111
npm run infra:restart:oriole

migrations/tenant/00010-search-files-search-function.sql

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
drop function storage.search;
21

32
create or replace function storage.search (
43
prefix text,

migrations/tenant/0002-storage-schema.sql

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,23 @@ BEGIN
1818
END IF;
1919

2020
-- Install ROLES
21-
EXECUTE 'CREATE ROLE ' || anon_role || ' NOLOGIN NOINHERIT';
22-
EXECUTE 'CREATE ROLE ' || authenticated_role || ' NOLOGIN NOINHERIT';
23-
EXECUTE 'CREATE ROLE ' || service_role || ' NOLOGIN NOINHERIT bypassrls';
21+
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = anon_role) THEN
22+
EXECUTE 'CREATE ROLE ' || anon_role || ' NOLOGIN NOINHERIT';
23+
END IF;
24+
25+
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = authenticated_role ) THEN
26+
EXECUTE 'CREATE ROLE ' || authenticated_role || ' NOLOGIN NOINHERIT';
27+
END IF;
28+
29+
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = service_role) THEN
30+
EXECUTE 'CREATE ROLE ' || service_role || ' NOLOGIN NOINHERIT bypassrls';
31+
END IF;
32+
33+
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'authenticator') THEN
34+
EXECUTE 'CREATE USER authenticator NOINHERIT';
35+
END IF;
36+
2437

25-
create user authenticator noinherit;
2638
EXECUTE 'grant ' || anon_role || ' to authenticator';
2739
EXECUTE 'grant ' || authenticated_role || ' to authenticator';
2840
EXECUTE 'grant ' || service_role || ' to authenticator';
@@ -70,7 +82,6 @@ CREATE INDEX IF NOT EXISTS name_prefix_search ON storage.objects(name text_patte
7082

7183
ALTER TABLE storage.objects ENABLE ROW LEVEL SECURITY;
7284

73-
drop function if exists storage.foldername;
7485
CREATE OR REPLACE FUNCTION storage.foldername(name text)
7586
RETURNS text[]
7687
LANGUAGE plpgsql
@@ -83,7 +94,6 @@ BEGIN
8394
END
8495
$function$;
8596

86-
drop function if exists storage.filename;
8797
CREATE OR REPLACE FUNCTION storage.filename(name text)
8898
RETURNS text
8999
LANGUAGE plpgsql
@@ -96,7 +106,6 @@ BEGIN
96106
END
97107
$function$;
98108

99-
drop function if exists storage.extension;
100109
CREATE OR REPLACE FUNCTION storage.extension(name text)
101110
RETURNS text
102111
LANGUAGE plpgsql
@@ -113,7 +122,6 @@ END
113122
$function$;
114123

115124
-- @todo can this query be optimised further?
116-
drop function if exists storage.search;
117125
CREATE OR REPLACE FUNCTION storage.search(prefix text, bucketname text, limits int DEFAULT 100, levels int DEFAULT 1, offsets int DEFAULT 0)
118126
RETURNS TABLE (
119127
name text,

migrations/tenant/0006-change-column-name-in-get-size.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
DROP FUNCTION storage.get_size_by_bucket();
1+
DROP FUNCTION IF EXISTS storage.get_size_by_bucket();
22
CREATE OR REPLACE FUNCTION storage.get_size_by_bucket()
33
RETURNS TABLE (
44
size BIGINT,

migrations/tenant/0009-fix-search-function.sql

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
drop function if exists storage.search;
21
CREATE OR REPLACE FUNCTION storage.search(prefix text, bucketname text, limits int DEFAULT 100, levels int DEFAULT 1, offsets int DEFAULT 0)
32
RETURNS TABLE (
43
name text,

migrations/tenant/0038-iceberg-catalog-flag-on-buckets.sql

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ DO $$
4040
updated_at timestamptz NOT NULL default now()
4141
);
4242

43-
CREATE UNIQUE INDEX IF NOT EXISTS idx_iceberg_namespaces_bucket_id ON storage.iceberg_namespaces (bucket_id, name);
43+
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'iceberg_namespaces' AND column_name = 'bucket_id') THEN
44+
CREATE UNIQUE INDEX IF NOT EXISTS idx_iceberg_namespaces_bucket_id ON storage.iceberg_namespaces (bucket_id, name);
45+
END IF;
4446

4547
CREATE TABLE IF NOT EXISTS storage.iceberg_tables (
4648
id uuid primary key default gen_random_uuid(),
@@ -52,6 +54,7 @@ DO $$
5254
updated_at timestamptz NOT NULL default now()
5355
);
5456

57+
DROP INDEX IF EXISTS idx_iceberg_tables_namespace_id;
5558
CREATE UNIQUE INDEX idx_iceberg_tables_namespace_id ON storage.iceberg_tables (namespace_id, name);
5659

5760
ALTER TABLE storage.iceberg_namespaces ENABLE ROW LEVEL SECURITY;

migrations/tenant/0039-add-search-v2-sort-support.sql

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
DROP FUNCTION IF EXISTS storage.search_v2;
21
CREATE OR REPLACE FUNCTION storage.search_v2 (
32
prefix text,
43
bucket_name text,

0 commit comments

Comments
 (0)