From 4217362f37f8c8129264a71ceafd221c96a7f814 Mon Sep 17 00:00:00 2001 From: CIOI Date: Tue, 21 Apr 2026 15:57:21 +0900 Subject: [PATCH 1/4] docs(api-server): document SeaORM vs supabase/migrations roles Made-with: Cursor --- AGENT.md | 3 ++- packages/api-server/AGENT.md | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/AGENT.md b/AGENT.md index 97f969e3..457b4293 100644 --- a/AGENT.md +++ b/AGENT.md @@ -21,6 +21,7 @@ | 디자인 시스템 import·컴포넌트 목록 | [docs/agent/design-system-llm.md](docs/agent/design-system-llm.md) | | Warehouse 스키마 (ETL·Seed) | [docs/agent/warehouse-schema.md](docs/agent/warehouse-schema.md) | | Rust API 서버 (`api-server`) | [packages/api-server/AGENT.md](packages/api-server/AGENT.md) | +| DB 마이그레이션 역할(SeaORM vs `supabase/migrations`) | [packages/api-server/AGENT.md — §2.4](packages/api-server/AGENT.md) | ## 반드시 지킬 것 @@ -34,4 +35,4 @@ - 디자인 시스템 토큰·UI 가이드: [docs/design-system/README.md](docs/design-system/README.md) - 문서 인덱스: [docs/README.md](docs/README.md) -**마지막 업데이트**: 2026-04-02 +**마지막 업데이트**: 2026-04-21 diff --git a/packages/api-server/AGENT.md b/packages/api-server/AGENT.md index 78020857..1516b925 100644 --- a/packages/api-server/AGENT.md +++ b/packages/api-server/AGENT.md @@ -1,7 +1,7 @@ # DECODED - Coding Agent 행동 규칙 -**Version:** 3.1.0 -**Last Updated:** 2026.01.12 +**Version:** 3.2.0 +**Last Updated:** 2026.04.21 **Purpose:** Coding Agent가 개발 시 반드시 준수해야 하는 실행 가능한 규칙 --- @@ -43,6 +43,21 @@ Axum v0.7에서는 경로 파라미터를 `{param}` 형식으로 사용해야 **에러 메시지**: `Path segments must not start with ':'. For capture groups, use {capture}.` +### 2.4 마이그레이션 트랙 역할 분리 (SeaORM vs Supabase SQL) + +앱 스키마는 **`public`** 과 **`warehouse`** 를 사용한다. 변경을 넣을 때 **아래 구분**을 따른다. + +| 담당 | 도구 | 넣는 것 | +|------|------|---------| +| DDL·구조 | SeaORM (`packages/api-server/migration/`) | `CREATE EXTENSION`, 테이블·컬럼·인덱스·**외래키(FK)** 등 ORM이 소유하는 스키마 | +| Supabase 플랫폼 | Supabase CLI 마이그레이션 (`supabase/migrations/*.sql`) | **RLS** 정책, `SECURITY DEFINER` 함수, `auth.uid()` 등과 맞물리는 트리거·RPC 등 | + +**Greenfield 권장 적용 순서**: (1) 확장 및 SeaORM 마이그레이션 적용 → (2) `supabase/migrations` SQL을 파일명(타임스탬프) 순으로 적용. + +SeaORM 마이그레이션 안에서 raw SQL로 RLS를 넣는 것은 가능하지만, **RLS·함수는 Supabase 트랙에 모아** 링크된 프로젝트에서 `supabase db push` 로 같이 올리기 쉽게 유지하는 것을 권장한다. 뷰 등 그 밖의 객체는 팀이 한쪽 트랙으로만 모은다. + +상세: [`migration/README.md`](migration/README.md), [루트 `supabase/migrations/README.md`](../../supabase/migrations/README.md). + --- ## 3. 비동기 프로그래밍 규칙 ⚠️ @@ -194,6 +209,7 @@ some_async_fn().await; | 버전 | 날짜 | 변경 내용 | |------|------|----------| +| 3.2.0 | 2026.04.21 | 마이그레이션 트랙 역할 분리(SeaORM vs `supabase/migrations`) 추가 | | 3.1.0 | 2026.01.12 | 비동기 프로그래밍 규칙(Send 트레이트) 추가 | | 3.0.0 | 2026.01.08 | 코드 예제 제거, 텍스트 설명 중심으로 재구성 (510줄 → 250줄) | | 2.0.0 | 2026.01.08 | 문서 대폭 축소 및 구조 개편 (2,338줄 → ~510줄) | From 5c0ea97ba3a108468c8b423270e28ede1a6a8835 Mon Sep 17 00:00:00 2001 From: CIOI Date: Tue, 21 Apr 2026 16:07:35 +0900 Subject: [PATCH 2/4] refactor(db): archive migrations to legacy, scaffold fresh migration + supabase dirs - Move packages/api-server/migration -> legacy (crate migration_legacy); api-server still depends on migration crate with empty Migrator for supabase-dev baseline work - Move supabase/migrations SQL -> supabase/legacy; active supabase/migrations is README-only until new SQL is added - Document paths in AGENT.md, database-summary, supabase CLI guide Made-with: Cursor --- docs/agent/database-summary.md | 3 +- docs/database/04-supabase-cli-setup.md | 6 +- packages/api-server/AGENT.md | 10 +- packages/api-server/Cargo.toml | 2 +- packages/api-server/legacy/Cargo.toml | 18 +++ packages/api-server/legacy/README.md | 71 +++++++++ packages/api-server/legacy/clippy.toml | 10 ++ .../sql/01_auth_trigger_handle_new_user.sql | 0 .../sql/02_rls_policy_users.sql | 0 .../sql/03_rls_policy_posts.sql | 0 packages/api-server/legacy/src/lib.rs | 145 ++++++++++++++++++ .../src/m20230101_000000_local_auth_stub.rs | 0 .../src/m20240101_000001_create_users.rs | 0 .../src/m20240101_000002_create_categories.rs | 0 .../src/m20240101_000003_create_posts.rs | 0 .../src/m20240101_000004_create_spots.rs | 0 .../src/m20240101_000005_create_solutions.rs | 0 .../src/m20240101_000006_create_votes.rs | 0 .../src/m20240101_000007_create_comments.rs | 0 .../src/m20240101_000008_create_synonyms.rs | 0 .../m20240101_000009_create_search_logs.rs | 0 .../src/m20240101_000010_create_curations.rs | 0 .../m20240101_000011_create_curation_posts.rs | 0 .../src/m20240101_000013_create_badges.rs | 0 .../m20240101_000014_create_user_badges.rs | 0 .../src/m20240101_000015_create_click_logs.rs | 0 .../src/m20240101_000016_create_earnings.rs | 0 .../m20240101_000017_create_settlements.rs | 0 .../src/m20240101_000018_create_view_logs.rs | 0 .../src/m20240101_000019_seed_badges.rs | 0 ...0101_000020_add_trending_score_to_posts.rs | 0 .../src/m20260108_005000_create_point_logs.rs | 0 .../m20260110_000001_create_subcategories.rs | 0 ...pdate_categories_and_seed_subcategories.rs | 0 ...60110_000003_alter_spots_subcategory_id.rs | 0 ...111_000001_add_ai_metadata_to_solutions.rs | 0 ...0260112_000001_add_comment_to_solutions.rs | 0 .../m20260126_000001_add_qna_to_solutions.rs | 0 ...20260127_000001_update_solutions_schema.rs | 0 ...01_remove_product_fields_from_solutions.rs | 0 ...2_rename_solution_product_name_to_title.rs | 0 ...60130_000001_add_link_type_to_solutions.rs | 0 ...0260205_000001_create_processed_batches.rs | 0 ...260205_000002_create_failed_batch_items.rs | 0 ...260205_000003_make_subcategory_nullable.rs | 0 ...260205_000004_make_media_title_nullable.rs | 0 ...0205_000005_rename_media_title_to_title.rs | 0 ...001_add_created_with_solutions_to_posts.rs | 0 .../m20260316_000001_create_post_magazines.rs | 0 ...16_000002_add_post_magazine_id_to_posts.rs | 0 ...20260317_000001_add_ai_summary_to_posts.rs | 0 .../src/m20260318_000001_create_post_likes.rs | 0 .../m20260318_000002_create_saved_posts.rs | 0 ...01_add_system_uncategorized_subcategory.rs | 0 ...20260402_000001_add_try_fields_to_posts.rs | 0 ...000001_add_warehouse_fk_posts_solutions.rs | 0 .../m20260402_000002_create_try_spot_tags.rs | 0 ..._000001_backfill_created_with_solutions.rs | 0 ...06_000001_drop_post_magazines_thread_id.rs | 0 ...20260406_000002_add_style_tags_to_posts.rs | 0 ...01_create_post_magazine_news_references.rs | 0 .../src/m20260409_add_image_dimensions.rs | 0 ...12_000001_add_posts_performance_indexes.rs | 0 ...20260419_000001_create_raw_posts_tables.rs | 2 +- ..._initial_scraped_at_to_raw_post_sources.rs | 0 ...m20260501_000001_decouple_auth_users_fk.rs | 10 +- .../src/m20260501_000002_auth_uid_stub.rs | 0 .../src/m20260502_000001_enable_extensions.rs | 0 ..._000002_warehouse_schema_tables_and_rls.rs | 2 +- ...02_000003_public_missing_tables_and_rls.rs | 2 +- ...02_000004_embeddings_and_search_similar.rs | 0 ...60502_000005_magazine_approval_and_rpcs.rs | 0 ...20260502_000006_backfill_public_columns.rs | 0 packages/api-server/legacy/src/main.rs | 6 + packages/api-server/migration/README.md | 60 ++------ packages/api-server/migration/src/lib.rs | 139 +---------------- .../20260409075040_remote_schema.sql | 0 ...20260419120000_create_raw_posts_tables.sql | 0 supabase/legacy/README.md | 5 + supabase/migrations/README.md | 14 ++ 80 files changed, 302 insertions(+), 203 deletions(-) create mode 100644 packages/api-server/legacy/Cargo.toml create mode 100644 packages/api-server/legacy/README.md create mode 100644 packages/api-server/legacy/clippy.toml rename packages/api-server/{migration => legacy}/sql/01_auth_trigger_handle_new_user.sql (100%) rename packages/api-server/{migration => legacy}/sql/02_rls_policy_users.sql (100%) rename packages/api-server/{migration => legacy}/sql/03_rls_policy_posts.sql (100%) create mode 100644 packages/api-server/legacy/src/lib.rs rename packages/api-server/{migration => legacy}/src/m20230101_000000_local_auth_stub.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000001_create_users.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000002_create_categories.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000003_create_posts.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000004_create_spots.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000005_create_solutions.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000006_create_votes.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000007_create_comments.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000008_create_synonyms.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000009_create_search_logs.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000010_create_curations.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000011_create_curation_posts.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000013_create_badges.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000014_create_user_badges.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000015_create_click_logs.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000016_create_earnings.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000017_create_settlements.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000018_create_view_logs.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000019_seed_badges.rs (100%) rename packages/api-server/{migration => legacy}/src/m20240101_000020_add_trending_score_to_posts.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260108_005000_create_point_logs.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260110_000001_create_subcategories.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260110_000002_update_categories_and_seed_subcategories.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260110_000003_alter_spots_subcategory_id.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260111_000001_add_ai_metadata_to_solutions.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260112_000001_add_comment_to_solutions.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260126_000001_add_qna_to_solutions.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260127_000001_update_solutions_schema.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260129_000001_remove_product_fields_from_solutions.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260129_000002_rename_solution_product_name_to_title.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260130_000001_add_link_type_to_solutions.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260205_000001_create_processed_batches.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260205_000002_create_failed_batch_items.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260205_000003_make_subcategory_nullable.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260205_000004_make_media_title_nullable.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260205_000005_rename_media_title_to_title.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260215_000001_add_created_with_solutions_to_posts.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260316_000001_create_post_magazines.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260316_000002_add_post_magazine_id_to_posts.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260317_000001_add_ai_summary_to_posts.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260318_000001_create_post_likes.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260318_000002_create_saved_posts.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260320_000001_add_system_uncategorized_subcategory.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260402_000001_add_try_fields_to_posts.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260402_000001_add_warehouse_fk_posts_solutions.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260402_000002_create_try_spot_tags.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260403_000001_backfill_created_with_solutions.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260406_000001_drop_post_magazines_thread_id.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260406_000002_add_style_tags_to_posts.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260407_000001_create_post_magazine_news_references.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260409_add_image_dimensions.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260412_000001_add_posts_performance_indexes.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260419_000001_create_raw_posts_tables.rs (98%) rename packages/api-server/{migration => legacy}/src/m20260420_000001_add_initial_scraped_at_to_raw_post_sources.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260501_000001_decouple_auth_users_fk.rs (95%) rename packages/api-server/{migration => legacy}/src/m20260501_000002_auth_uid_stub.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260502_000001_enable_extensions.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260502_000002_warehouse_schema_tables_and_rls.rs (99%) rename packages/api-server/{migration => legacy}/src/m20260502_000003_public_missing_tables_and_rls.rs (98%) rename packages/api-server/{migration => legacy}/src/m20260502_000004_embeddings_and_search_similar.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260502_000005_magazine_approval_and_rpcs.rs (100%) rename packages/api-server/{migration => legacy}/src/m20260502_000006_backfill_public_columns.rs (100%) create mode 100644 packages/api-server/legacy/src/main.rs rename supabase/{migrations => legacy}/20260409075040_remote_schema.sql (100%) rename supabase/{migrations => legacy}/20260419120000_create_raw_posts_tables.sql (100%) create mode 100644 supabase/legacy/README.md create mode 100644 supabase/migrations/README.md diff --git a/docs/agent/database-summary.md b/docs/agent/database-summary.md index 87697736..e030d2aa 100644 --- a/docs/agent/database-summary.md +++ b/docs/agent/database-summary.md @@ -23,12 +23,13 @@ Supabase 기반 이중 스키마 (public / warehouse) 구조의 진입점. 앱 - 업데이트 체크리스트: [`docs/database/02-update-checklist.md`](../database/02-update-checklist.md) - Warehouse 스키마 인벤토리: [`docs/agent/warehouse-schema.md`](warehouse-schema.md) - Supabase CLI setup: [`docs/database/04-supabase-cli-setup.md`](../database/04-supabase-cli-setup.md) +- 마이그레이션 레이아웃 (SeaORM vs `supabase/migrations`, 보관 `legacy/`): [`packages/api-server/migration/README.md`](../../packages/api-server/migration/README.md), [`supabase/migrations/README.md`](../../supabase/migrations/README.md) ## Key files / concepts - **Public schema**: 앱 데이터 (posts, items, users, solutions, social 등) - **Warehouse schema**: ETL·Seed 파이프라인 (seed_candidates, review_queue, seed_images 등) -- Migration 전략: SeaORM (테이블·컬럼) + Supabase CLI (RLS·함수·warehouse) +- Migration 전략: 활성 SeaORM은 `packages/api-server/migration/`; Supabase CLI는 `supabase/migrations/`; 이전 전체는 `packages/api-server/legacy/`, `supabase/legacy/` 보관. 수동 SQL은 `legacy/sql/` 등 참고 (원격 덤프와 중복 주의) - Types: `packages/shared/supabase/types.ts` (typegen 재생성으로 drift 감지) ## Gotchas diff --git a/docs/database/04-supabase-cli-setup.md b/docs/database/04-supabase-cli-setup.md index 0171741e..c69bd676 100644 --- a/docs/database/04-supabase-cli-setup.md +++ b/docs/database/04-supabase-cli-setup.md @@ -23,9 +23,9 @@ supabase link --project-ref fvxchskblyhuswzlcmql | 변경 유형 | 관리 도구 | 위치 | |---------|----------|------| -| 테이블/컬럼 (API 서버 관련) | SeaORM | `packages/api-server/migration/` | -| RLS, 함수, 트리거, 뷰 | Supabase CLI | `supabase/migrations/` | -| warehouse 스키마 | Supabase CLI | `supabase/migrations/` | +| 테이블/컬럼 (API 서버 관련) | SeaORM | `packages/api-server/migration/` (활성), 보관 `packages/api-server/legacy/` | +| RLS, 함수, 트리거, 뷰 | Supabase CLI | `supabase/migrations/` (활성), 보관 `supabase/legacy/` | +| warehouse 스키마 | SeaORM 또는 Supabase CLI (팀 합의) | 위 경로 중 하나 | ## Common Commands diff --git a/packages/api-server/AGENT.md b/packages/api-server/AGENT.md index 1516b925..94d8a7d5 100644 --- a/packages/api-server/AGENT.md +++ b/packages/api-server/AGENT.md @@ -1,6 +1,6 @@ # DECODED - Coding Agent 행동 규칙 -**Version:** 3.2.0 +**Version:** 3.3.0 **Last Updated:** 2026.04.21 **Purpose:** Coding Agent가 개발 시 반드시 준수해야 하는 실행 가능한 규칙 @@ -49,14 +49,15 @@ Axum v0.7에서는 경로 파라미터를 `{param}` 형식으로 사용해야 | 담당 | 도구 | 넣는 것 | |------|------|---------| -| DDL·구조 | SeaORM (`packages/api-server/migration/`) | `CREATE EXTENSION`, 테이블·컬럼·인덱스·**외래키(FK)** 등 ORM이 소유하는 스키마 | -| Supabase 플랫폼 | Supabase CLI 마이그레이션 (`supabase/migrations/*.sql`) | **RLS** 정책, `SECURITY DEFINER` 함수, `auth.uid()` 등과 맞물리는 트리거·RPC 등 | +| DDL·구조 | SeaORM (`packages/api-server/migration/`, 활성) | `CREATE EXTENSION`, 테이블·컬럼·인덱스·**외래키(FK)** 등 ORM이 소유하는 스키마 | +| Supabase 플랫폼 | Supabase CLI (`supabase/migrations/*.sql`, 활성) | **RLS** 정책, `SECURITY DEFINER` 함수, `auth.uid()` 등과 맞물리는 트리거·RPC 등 | +| (보관) | `packages/api-server/legacy/`, `supabase/legacy/` | 이전 마이그레이션 전체 — 크레이트 `migration_legacy`, 자동 적용 대상 아님 | **Greenfield 권장 적용 순서**: (1) 확장 및 SeaORM 마이그레이션 적용 → (2) `supabase/migrations` SQL을 파일명(타임스탬프) 순으로 적용. SeaORM 마이그레이션 안에서 raw SQL로 RLS를 넣는 것은 가능하지만, **RLS·함수는 Supabase 트랙에 모아** 링크된 프로젝트에서 `supabase db push` 로 같이 올리기 쉽게 유지하는 것을 권장한다. 뷰 등 그 밖의 객체는 팀이 한쪽 트랙으로만 모은다. -상세: [`migration/README.md`](migration/README.md), [루트 `supabase/migrations/README.md`](../../supabase/migrations/README.md). +상세: [`migration/README.md`](migration/README.md), [`supabase/migrations/README.md`](../../supabase/migrations/README.md). 보관: [`legacy/README.md`](legacy/README.md), [`supabase/legacy/README.md`](../../supabase/legacy/README.md). --- @@ -209,6 +210,7 @@ some_async_fn().await; | 버전 | 날짜 | 변경 내용 | |------|------|----------| +| 3.3.0 | 2026.04.21 | 활성 `migration/`·`supabase/migrations/` vs 보관 `legacy/` 디렉터리 구조 반영 | | 3.2.0 | 2026.04.21 | 마이그레이션 트랙 역할 분리(SeaORM vs `supabase/migrations`) 추가 | | 3.1.0 | 2026.01.12 | 비동기 프로그래밍 규칙(Send 트레이트) 추가 | | 3.0.0 | 2026.01.08 | 코드 예제 제거, 텍스트 설명 중심으로 재구성 (510줄 → 250줄) | diff --git a/packages/api-server/Cargo.toml b/packages/api-server/Cargo.toml index 4dab87b1..ee10293f 100644 --- a/packages/api-server/Cargo.toml +++ b/packages/api-server/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "2" -members = ["migration", "entity"] +members = ["migration", "legacy", "entity"] [workspace.dependencies] # Web Framework diff --git a/packages/api-server/legacy/Cargo.toml b/packages/api-server/legacy/Cargo.toml new file mode 100644 index 00000000..bd1b269b --- /dev/null +++ b/packages/api-server/legacy/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "migration_legacy" +version = "0.5.1" +edition = "2021" +license = "MIT" +publish = false + +[lib] +name = "migration_legacy" +path = "src/lib.rs" + +[dependencies] +sea-orm-migration = { workspace = true } +tokio = { workspace = true } +dotenvy = { workspace = true } + +[lints.rust] +unused_imports = "deny" diff --git a/packages/api-server/legacy/README.md b/packages/api-server/legacy/README.md new file mode 100644 index 00000000..97d63006 --- /dev/null +++ b/packages/api-server/legacy/README.md @@ -0,0 +1,71 @@ +# Database Migrations — **legacy (archived)** + +> 이 디렉터리는 **보관**용이다. 크레이트 이름은 `migration_legacy`이며 `cargo run -p migration_legacy`로 실행한다. +> **활성** SeaORM 마이그레이션은 [`../migration/`](../migration/) 을 사용한다. + +SeaORM 마이그레이션 및 Supabase 설정 가이드 (과거 본문) + +## 마이그레이션 실행 + +### 1. Rust 마이그레이션 실행 + +```bash +# 마이그레이션 디렉토리로 이동 (legacy 크레이트) +cd legacy + +# 마이그레이션 적용 +cargo run -- up + +# 마이그레이션 롤백 +cargo run -- down + +# 마이그레이션 상태 확인 +cargo run -- status + +# 마이그레이션 새로고침 (down → up) +cargo run -- refresh +``` + +### 2. Supabase SQL 스크립트 실행 + +Rust 마이그레이션 후, Supabase Dashboard의 SQL Editor에서 다음 파일들을 순서대로 실행하세요: + +1. **Auth 트리거**: `sql/01_auth_trigger_handle_new_user.sql` + - Supabase Auth에서 새 사용자 생성 시 자동으로 users 테이블에 레코드 생성 + +2. **RLS 정책**: `sql/02_rls_policy_users.sql` + - users 테이블에 Row Level Security 정책 적용 + - 모든 사용자가 프로필 조회 가능 + - 사용자는 자신의 프로필만 수정/삭제 가능 + +## 마이그레이션 목록 + +### m20240101_000001_create_users + +- users 테이블 생성 +- auth.users 외래키 참조 (CASCADE DELETE) +- updated_at 자동 업데이트 트리거 +- 인덱스: email, username, rank + +## Entity 생성 + +마이그레이션 실행 후 SeaORM Entity를 생성합니다: + +```bash +# 프로젝트 루트로 이동 +cd .. + +# entity 디렉토리 생성 (없는 경우) +mkdir -p src/entities + +# Entity 생성 +sea-orm-cli generate entity \ + --database-url "$DATABASE_URL" \ + --output-dir src/entities \ + --with-serde both +``` + +## 참고 + +- [SeaORM Migration 문서](https://www.sea-ql.org/SeaORM/docs/migration/writing-migration/) +- [Supabase RLS 문서](https://supabase.com/docs/guides/auth/row-level-security) diff --git a/packages/api-server/legacy/clippy.toml b/packages/api-server/legacy/clippy.toml new file mode 100644 index 00000000..335d543a --- /dev/null +++ b/packages/api-server/legacy/clippy.toml @@ -0,0 +1,10 @@ +# 마이그레이션 크레이트 — SeaORM 매크로/생성 코드의 unwrap 은 허용 +# (부모 디렉터리 clippy.toml 대신 이 파일이 적용됨) + +disallowed-methods = [] + +disallowed-macros = [ + { path = "std::println", reason = "tracing::info! / tracing::debug! 를 사용하세요" }, + { path = "std::dbg", reason = "tracing::debug! 를 사용하세요" }, + { path = "std::eprintln", reason = "tracing::warn! 또는 tracing::error! 를 사용하세요" }, +] diff --git a/packages/api-server/migration/sql/01_auth_trigger_handle_new_user.sql b/packages/api-server/legacy/sql/01_auth_trigger_handle_new_user.sql similarity index 100% rename from packages/api-server/migration/sql/01_auth_trigger_handle_new_user.sql rename to packages/api-server/legacy/sql/01_auth_trigger_handle_new_user.sql diff --git a/packages/api-server/migration/sql/02_rls_policy_users.sql b/packages/api-server/legacy/sql/02_rls_policy_users.sql similarity index 100% rename from packages/api-server/migration/sql/02_rls_policy_users.sql rename to packages/api-server/legacy/sql/02_rls_policy_users.sql diff --git a/packages/api-server/migration/sql/03_rls_policy_posts.sql b/packages/api-server/legacy/sql/03_rls_policy_posts.sql similarity index 100% rename from packages/api-server/migration/sql/03_rls_policy_posts.sql rename to packages/api-server/legacy/sql/03_rls_policy_posts.sql diff --git a/packages/api-server/legacy/src/lib.rs b/packages/api-server/legacy/src/lib.rs new file mode 100644 index 00000000..ef2b800a --- /dev/null +++ b/packages/api-server/legacy/src/lib.rs @@ -0,0 +1,145 @@ +pub use sea_orm_migration::prelude::*; + +mod m20230101_000000_local_auth_stub; +mod m20240101_000001_create_users; +mod m20240101_000002_create_categories; +mod m20240101_000003_create_posts; +mod m20240101_000004_create_spots; +mod m20240101_000005_create_solutions; +mod m20240101_000006_create_votes; +mod m20240101_000007_create_comments; +mod m20240101_000008_create_synonyms; +mod m20240101_000009_create_search_logs; +mod m20240101_000010_create_curations; +mod m20240101_000011_create_curation_posts; +mod m20240101_000013_create_badges; +mod m20240101_000014_create_user_badges; +mod m20240101_000015_create_click_logs; +mod m20240101_000016_create_earnings; +mod m20240101_000017_create_settlements; +mod m20240101_000018_create_view_logs; +mod m20240101_000019_seed_badges; +mod m20240101_000020_add_trending_score_to_posts; +mod m20260108_005000_create_point_logs; +mod m20260110_000001_create_subcategories; +mod m20260110_000002_update_categories_and_seed_subcategories; +mod m20260110_000003_alter_spots_subcategory_id; +mod m20260111_000001_add_ai_metadata_to_solutions; +mod m20260112_000001_add_comment_to_solutions; +mod m20260126_000001_add_qna_to_solutions; +mod m20260127_000001_update_solutions_schema; +mod m20260129_000001_remove_product_fields_from_solutions; +mod m20260129_000002_rename_solution_product_name_to_title; +mod m20260130_000001_add_link_type_to_solutions; +mod m20260205_000001_create_processed_batches; +mod m20260205_000002_create_failed_batch_items; +mod m20260205_000003_make_subcategory_nullable; +mod m20260205_000004_make_media_title_nullable; +mod m20260205_000005_rename_media_title_to_title; +mod m20260215_000001_add_created_with_solutions_to_posts; +mod m20260316_000001_create_post_magazines; +mod m20260316_000002_add_post_magazine_id_to_posts; +mod m20260317_000001_add_ai_summary_to_posts; +mod m20260318_000001_create_post_likes; +mod m20260318_000002_create_saved_posts; +mod m20260320_000001_add_system_uncategorized_subcategory; +mod m20260402_000001_add_try_fields_to_posts; +mod m20260402_000001_add_warehouse_fk_posts_solutions; +mod m20260402_000002_create_try_spot_tags; +mod m20260403_000001_backfill_created_with_solutions; +mod m20260406_000001_drop_post_magazines_thread_id; +mod m20260406_000002_add_style_tags_to_posts; +mod m20260407_000001_create_post_magazine_news_references; +mod m20260409_add_image_dimensions; +mod m20260412_000001_add_posts_performance_indexes; +mod m20260419_000001_create_raw_posts_tables; +mod m20260420_000001_add_initial_scraped_at_to_raw_post_sources; +mod m20260501_000001_decouple_auth_users_fk; +mod m20260501_000002_auth_uid_stub; +mod m20260502_000001_enable_extensions; +mod m20260502_000002_warehouse_schema_tables_and_rls; +mod m20260502_000003_public_missing_tables_and_rls; +mod m20260502_000004_embeddings_and_search_similar; +mod m20260502_000005_magazine_approval_and_rpcs; +mod m20260502_000006_backfill_public_columns; + +pub struct Migrator; + +#[async_trait::async_trait] +impl MigratorTrait for Migrator { + fn migrations() -> Vec> { + vec![ + // Ensure auth.users stub exists before any FK references it (#267). + Box::new(m20230101_000000_local_auth_stub::Migration), + Box::new(m20240101_000001_create_users::Migration), + Box::new(m20240101_000002_create_categories::Migration), + Box::new(m20240101_000003_create_posts::Migration), + Box::new(m20240101_000004_create_spots::Migration), + Box::new(m20240101_000005_create_solutions::Migration), + Box::new(m20240101_000006_create_votes::Migration), + Box::new(m20240101_000007_create_comments::Migration), + Box::new(m20240101_000008_create_synonyms::Migration), + Box::new(m20240101_000009_create_search_logs::Migration), + Box::new(m20240101_000010_create_curations::Migration), + Box::new(m20240101_000011_create_curation_posts::Migration), + Box::new(m20260108_005000_create_point_logs::Migration), + Box::new(m20240101_000013_create_badges::Migration), + Box::new(m20240101_000014_create_user_badges::Migration), + Box::new(m20240101_000015_create_click_logs::Migration), + Box::new(m20240101_000016_create_earnings::Migration), + Box::new(m20240101_000017_create_settlements::Migration), + Box::new(m20240101_000018_create_view_logs::Migration), + Box::new(m20240101_000019_seed_badges::Migration), + Box::new(m20240101_000020_add_trending_score_to_posts::Migration), + Box::new(m20260110_000001_create_subcategories::Migration), + Box::new(m20260110_000002_update_categories_and_seed_subcategories::Migration), + Box::new(m20260110_000003_alter_spots_subcategory_id::Migration), + Box::new(m20260111_000001_add_ai_metadata_to_solutions::Migration), + Box::new(m20260112_000001_add_comment_to_solutions::Migration), + Box::new(m20260126_000001_add_qna_to_solutions::Migration), + Box::new(m20260127_000001_update_solutions_schema::Migration), + Box::new(m20260129_000001_remove_product_fields_from_solutions::Migration), + Box::new(m20260129_000002_rename_solution_product_name_to_title::Migration), + Box::new(m20260130_000001_add_link_type_to_solutions::Migration), + Box::new(m20260205_000001_create_processed_batches::Migration), + Box::new(m20260205_000002_create_failed_batch_items::Migration), + Box::new(m20260205_000003_make_subcategory_nullable::Migration), + Box::new(m20260205_000004_make_media_title_nullable::Migration), + Box::new(m20260205_000005_rename_media_title_to_title::Migration), + Box::new(m20260215_000001_add_created_with_solutions_to_posts::Migration), + Box::new(m20260316_000001_create_post_magazines::Migration), + Box::new(m20260316_000002_add_post_magazine_id_to_posts::Migration), + Box::new(m20260317_000001_add_ai_summary_to_posts::Migration), + Box::new(m20260318_000001_create_post_likes::Migration), + Box::new(m20260318_000002_create_saved_posts::Migration), + Box::new(m20260320_000001_add_system_uncategorized_subcategory::Migration), + Box::new(m20260402_000001_add_try_fields_to_posts::Migration), + Box::new(m20260402_000002_create_try_spot_tags::Migration), + // Warehouse schema must exist before the FK migration references it. + // On prod the schema already exists (Supabase CLI ran earlier); these new + // SeaORM migrations are idempotent no-ops there. On fresh local, these run + // first and create the schema so the FK migration below can succeed. + Box::new(m20260502_000001_enable_extensions::Migration), + Box::new(m20260502_000002_warehouse_schema_tables_and_rls::Migration), + Box::new(m20260402_000001_add_warehouse_fk_posts_solutions::Migration), + Box::new(m20260403_000001_backfill_created_with_solutions::Migration), + Box::new(m20260406_000001_drop_post_magazines_thread_id::Migration), + Box::new(m20260406_000002_add_style_tags_to_posts::Migration), + Box::new(m20260407_000001_create_post_magazine_news_references::Migration), + Box::new(m20260409_add_image_dimensions::Migration), + Box::new(m20260412_000001_add_posts_performance_indexes::Migration), + // #258 raw_posts pipeline tables + Box::new(m20260419_000001_create_raw_posts_tables::Migration), + // #214 Pinterest adapter — initial vs incremental scrape tracking + Box::new(m20260420_000001_add_initial_scraped_at_to_raw_post_sources::Migration), + // PR #273 — auth.uid() stub must run before RLS migrations that use it. + Box::new(m20260501_000002_auth_uid_stub::Migration), + Box::new(m20260501_000001_decouple_auth_users_fk::Migration), + // #202 remaining migrations (warehouse schema already registered above) + Box::new(m20260502_000003_public_missing_tables_and_rls::Migration), + Box::new(m20260502_000004_embeddings_and_search_similar::Migration), + Box::new(m20260502_000005_magazine_approval_and_rpcs::Migration), + Box::new(m20260502_000006_backfill_public_columns::Migration), + ] + } +} diff --git a/packages/api-server/migration/src/m20230101_000000_local_auth_stub.rs b/packages/api-server/legacy/src/m20230101_000000_local_auth_stub.rs similarity index 100% rename from packages/api-server/migration/src/m20230101_000000_local_auth_stub.rs rename to packages/api-server/legacy/src/m20230101_000000_local_auth_stub.rs diff --git a/packages/api-server/migration/src/m20240101_000001_create_users.rs b/packages/api-server/legacy/src/m20240101_000001_create_users.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000001_create_users.rs rename to packages/api-server/legacy/src/m20240101_000001_create_users.rs diff --git a/packages/api-server/migration/src/m20240101_000002_create_categories.rs b/packages/api-server/legacy/src/m20240101_000002_create_categories.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000002_create_categories.rs rename to packages/api-server/legacy/src/m20240101_000002_create_categories.rs diff --git a/packages/api-server/migration/src/m20240101_000003_create_posts.rs b/packages/api-server/legacy/src/m20240101_000003_create_posts.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000003_create_posts.rs rename to packages/api-server/legacy/src/m20240101_000003_create_posts.rs diff --git a/packages/api-server/migration/src/m20240101_000004_create_spots.rs b/packages/api-server/legacy/src/m20240101_000004_create_spots.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000004_create_spots.rs rename to packages/api-server/legacy/src/m20240101_000004_create_spots.rs diff --git a/packages/api-server/migration/src/m20240101_000005_create_solutions.rs b/packages/api-server/legacy/src/m20240101_000005_create_solutions.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000005_create_solutions.rs rename to packages/api-server/legacy/src/m20240101_000005_create_solutions.rs diff --git a/packages/api-server/migration/src/m20240101_000006_create_votes.rs b/packages/api-server/legacy/src/m20240101_000006_create_votes.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000006_create_votes.rs rename to packages/api-server/legacy/src/m20240101_000006_create_votes.rs diff --git a/packages/api-server/migration/src/m20240101_000007_create_comments.rs b/packages/api-server/legacy/src/m20240101_000007_create_comments.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000007_create_comments.rs rename to packages/api-server/legacy/src/m20240101_000007_create_comments.rs diff --git a/packages/api-server/migration/src/m20240101_000008_create_synonyms.rs b/packages/api-server/legacy/src/m20240101_000008_create_synonyms.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000008_create_synonyms.rs rename to packages/api-server/legacy/src/m20240101_000008_create_synonyms.rs diff --git a/packages/api-server/migration/src/m20240101_000009_create_search_logs.rs b/packages/api-server/legacy/src/m20240101_000009_create_search_logs.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000009_create_search_logs.rs rename to packages/api-server/legacy/src/m20240101_000009_create_search_logs.rs diff --git a/packages/api-server/migration/src/m20240101_000010_create_curations.rs b/packages/api-server/legacy/src/m20240101_000010_create_curations.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000010_create_curations.rs rename to packages/api-server/legacy/src/m20240101_000010_create_curations.rs diff --git a/packages/api-server/migration/src/m20240101_000011_create_curation_posts.rs b/packages/api-server/legacy/src/m20240101_000011_create_curation_posts.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000011_create_curation_posts.rs rename to packages/api-server/legacy/src/m20240101_000011_create_curation_posts.rs diff --git a/packages/api-server/migration/src/m20240101_000013_create_badges.rs b/packages/api-server/legacy/src/m20240101_000013_create_badges.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000013_create_badges.rs rename to packages/api-server/legacy/src/m20240101_000013_create_badges.rs diff --git a/packages/api-server/migration/src/m20240101_000014_create_user_badges.rs b/packages/api-server/legacy/src/m20240101_000014_create_user_badges.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000014_create_user_badges.rs rename to packages/api-server/legacy/src/m20240101_000014_create_user_badges.rs diff --git a/packages/api-server/migration/src/m20240101_000015_create_click_logs.rs b/packages/api-server/legacy/src/m20240101_000015_create_click_logs.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000015_create_click_logs.rs rename to packages/api-server/legacy/src/m20240101_000015_create_click_logs.rs diff --git a/packages/api-server/migration/src/m20240101_000016_create_earnings.rs b/packages/api-server/legacy/src/m20240101_000016_create_earnings.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000016_create_earnings.rs rename to packages/api-server/legacy/src/m20240101_000016_create_earnings.rs diff --git a/packages/api-server/migration/src/m20240101_000017_create_settlements.rs b/packages/api-server/legacy/src/m20240101_000017_create_settlements.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000017_create_settlements.rs rename to packages/api-server/legacy/src/m20240101_000017_create_settlements.rs diff --git a/packages/api-server/migration/src/m20240101_000018_create_view_logs.rs b/packages/api-server/legacy/src/m20240101_000018_create_view_logs.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000018_create_view_logs.rs rename to packages/api-server/legacy/src/m20240101_000018_create_view_logs.rs diff --git a/packages/api-server/migration/src/m20240101_000019_seed_badges.rs b/packages/api-server/legacy/src/m20240101_000019_seed_badges.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000019_seed_badges.rs rename to packages/api-server/legacy/src/m20240101_000019_seed_badges.rs diff --git a/packages/api-server/migration/src/m20240101_000020_add_trending_score_to_posts.rs b/packages/api-server/legacy/src/m20240101_000020_add_trending_score_to_posts.rs similarity index 100% rename from packages/api-server/migration/src/m20240101_000020_add_trending_score_to_posts.rs rename to packages/api-server/legacy/src/m20240101_000020_add_trending_score_to_posts.rs diff --git a/packages/api-server/migration/src/m20260108_005000_create_point_logs.rs b/packages/api-server/legacy/src/m20260108_005000_create_point_logs.rs similarity index 100% rename from packages/api-server/migration/src/m20260108_005000_create_point_logs.rs rename to packages/api-server/legacy/src/m20260108_005000_create_point_logs.rs diff --git a/packages/api-server/migration/src/m20260110_000001_create_subcategories.rs b/packages/api-server/legacy/src/m20260110_000001_create_subcategories.rs similarity index 100% rename from packages/api-server/migration/src/m20260110_000001_create_subcategories.rs rename to packages/api-server/legacy/src/m20260110_000001_create_subcategories.rs diff --git a/packages/api-server/migration/src/m20260110_000002_update_categories_and_seed_subcategories.rs b/packages/api-server/legacy/src/m20260110_000002_update_categories_and_seed_subcategories.rs similarity index 100% rename from packages/api-server/migration/src/m20260110_000002_update_categories_and_seed_subcategories.rs rename to packages/api-server/legacy/src/m20260110_000002_update_categories_and_seed_subcategories.rs diff --git a/packages/api-server/migration/src/m20260110_000003_alter_spots_subcategory_id.rs b/packages/api-server/legacy/src/m20260110_000003_alter_spots_subcategory_id.rs similarity index 100% rename from packages/api-server/migration/src/m20260110_000003_alter_spots_subcategory_id.rs rename to packages/api-server/legacy/src/m20260110_000003_alter_spots_subcategory_id.rs diff --git a/packages/api-server/migration/src/m20260111_000001_add_ai_metadata_to_solutions.rs b/packages/api-server/legacy/src/m20260111_000001_add_ai_metadata_to_solutions.rs similarity index 100% rename from packages/api-server/migration/src/m20260111_000001_add_ai_metadata_to_solutions.rs rename to packages/api-server/legacy/src/m20260111_000001_add_ai_metadata_to_solutions.rs diff --git a/packages/api-server/migration/src/m20260112_000001_add_comment_to_solutions.rs b/packages/api-server/legacy/src/m20260112_000001_add_comment_to_solutions.rs similarity index 100% rename from packages/api-server/migration/src/m20260112_000001_add_comment_to_solutions.rs rename to packages/api-server/legacy/src/m20260112_000001_add_comment_to_solutions.rs diff --git a/packages/api-server/migration/src/m20260126_000001_add_qna_to_solutions.rs b/packages/api-server/legacy/src/m20260126_000001_add_qna_to_solutions.rs similarity index 100% rename from packages/api-server/migration/src/m20260126_000001_add_qna_to_solutions.rs rename to packages/api-server/legacy/src/m20260126_000001_add_qna_to_solutions.rs diff --git a/packages/api-server/migration/src/m20260127_000001_update_solutions_schema.rs b/packages/api-server/legacy/src/m20260127_000001_update_solutions_schema.rs similarity index 100% rename from packages/api-server/migration/src/m20260127_000001_update_solutions_schema.rs rename to packages/api-server/legacy/src/m20260127_000001_update_solutions_schema.rs diff --git a/packages/api-server/migration/src/m20260129_000001_remove_product_fields_from_solutions.rs b/packages/api-server/legacy/src/m20260129_000001_remove_product_fields_from_solutions.rs similarity index 100% rename from packages/api-server/migration/src/m20260129_000001_remove_product_fields_from_solutions.rs rename to packages/api-server/legacy/src/m20260129_000001_remove_product_fields_from_solutions.rs diff --git a/packages/api-server/migration/src/m20260129_000002_rename_solution_product_name_to_title.rs b/packages/api-server/legacy/src/m20260129_000002_rename_solution_product_name_to_title.rs similarity index 100% rename from packages/api-server/migration/src/m20260129_000002_rename_solution_product_name_to_title.rs rename to packages/api-server/legacy/src/m20260129_000002_rename_solution_product_name_to_title.rs diff --git a/packages/api-server/migration/src/m20260130_000001_add_link_type_to_solutions.rs b/packages/api-server/legacy/src/m20260130_000001_add_link_type_to_solutions.rs similarity index 100% rename from packages/api-server/migration/src/m20260130_000001_add_link_type_to_solutions.rs rename to packages/api-server/legacy/src/m20260130_000001_add_link_type_to_solutions.rs diff --git a/packages/api-server/migration/src/m20260205_000001_create_processed_batches.rs b/packages/api-server/legacy/src/m20260205_000001_create_processed_batches.rs similarity index 100% rename from packages/api-server/migration/src/m20260205_000001_create_processed_batches.rs rename to packages/api-server/legacy/src/m20260205_000001_create_processed_batches.rs diff --git a/packages/api-server/migration/src/m20260205_000002_create_failed_batch_items.rs b/packages/api-server/legacy/src/m20260205_000002_create_failed_batch_items.rs similarity index 100% rename from packages/api-server/migration/src/m20260205_000002_create_failed_batch_items.rs rename to packages/api-server/legacy/src/m20260205_000002_create_failed_batch_items.rs diff --git a/packages/api-server/migration/src/m20260205_000003_make_subcategory_nullable.rs b/packages/api-server/legacy/src/m20260205_000003_make_subcategory_nullable.rs similarity index 100% rename from packages/api-server/migration/src/m20260205_000003_make_subcategory_nullable.rs rename to packages/api-server/legacy/src/m20260205_000003_make_subcategory_nullable.rs diff --git a/packages/api-server/migration/src/m20260205_000004_make_media_title_nullable.rs b/packages/api-server/legacy/src/m20260205_000004_make_media_title_nullable.rs similarity index 100% rename from packages/api-server/migration/src/m20260205_000004_make_media_title_nullable.rs rename to packages/api-server/legacy/src/m20260205_000004_make_media_title_nullable.rs diff --git a/packages/api-server/migration/src/m20260205_000005_rename_media_title_to_title.rs b/packages/api-server/legacy/src/m20260205_000005_rename_media_title_to_title.rs similarity index 100% rename from packages/api-server/migration/src/m20260205_000005_rename_media_title_to_title.rs rename to packages/api-server/legacy/src/m20260205_000005_rename_media_title_to_title.rs diff --git a/packages/api-server/migration/src/m20260215_000001_add_created_with_solutions_to_posts.rs b/packages/api-server/legacy/src/m20260215_000001_add_created_with_solutions_to_posts.rs similarity index 100% rename from packages/api-server/migration/src/m20260215_000001_add_created_with_solutions_to_posts.rs rename to packages/api-server/legacy/src/m20260215_000001_add_created_with_solutions_to_posts.rs diff --git a/packages/api-server/migration/src/m20260316_000001_create_post_magazines.rs b/packages/api-server/legacy/src/m20260316_000001_create_post_magazines.rs similarity index 100% rename from packages/api-server/migration/src/m20260316_000001_create_post_magazines.rs rename to packages/api-server/legacy/src/m20260316_000001_create_post_magazines.rs diff --git a/packages/api-server/migration/src/m20260316_000002_add_post_magazine_id_to_posts.rs b/packages/api-server/legacy/src/m20260316_000002_add_post_magazine_id_to_posts.rs similarity index 100% rename from packages/api-server/migration/src/m20260316_000002_add_post_magazine_id_to_posts.rs rename to packages/api-server/legacy/src/m20260316_000002_add_post_magazine_id_to_posts.rs diff --git a/packages/api-server/migration/src/m20260317_000001_add_ai_summary_to_posts.rs b/packages/api-server/legacy/src/m20260317_000001_add_ai_summary_to_posts.rs similarity index 100% rename from packages/api-server/migration/src/m20260317_000001_add_ai_summary_to_posts.rs rename to packages/api-server/legacy/src/m20260317_000001_add_ai_summary_to_posts.rs diff --git a/packages/api-server/migration/src/m20260318_000001_create_post_likes.rs b/packages/api-server/legacy/src/m20260318_000001_create_post_likes.rs similarity index 100% rename from packages/api-server/migration/src/m20260318_000001_create_post_likes.rs rename to packages/api-server/legacy/src/m20260318_000001_create_post_likes.rs diff --git a/packages/api-server/migration/src/m20260318_000002_create_saved_posts.rs b/packages/api-server/legacy/src/m20260318_000002_create_saved_posts.rs similarity index 100% rename from packages/api-server/migration/src/m20260318_000002_create_saved_posts.rs rename to packages/api-server/legacy/src/m20260318_000002_create_saved_posts.rs diff --git a/packages/api-server/migration/src/m20260320_000001_add_system_uncategorized_subcategory.rs b/packages/api-server/legacy/src/m20260320_000001_add_system_uncategorized_subcategory.rs similarity index 100% rename from packages/api-server/migration/src/m20260320_000001_add_system_uncategorized_subcategory.rs rename to packages/api-server/legacy/src/m20260320_000001_add_system_uncategorized_subcategory.rs diff --git a/packages/api-server/migration/src/m20260402_000001_add_try_fields_to_posts.rs b/packages/api-server/legacy/src/m20260402_000001_add_try_fields_to_posts.rs similarity index 100% rename from packages/api-server/migration/src/m20260402_000001_add_try_fields_to_posts.rs rename to packages/api-server/legacy/src/m20260402_000001_add_try_fields_to_posts.rs diff --git a/packages/api-server/migration/src/m20260402_000001_add_warehouse_fk_posts_solutions.rs b/packages/api-server/legacy/src/m20260402_000001_add_warehouse_fk_posts_solutions.rs similarity index 100% rename from packages/api-server/migration/src/m20260402_000001_add_warehouse_fk_posts_solutions.rs rename to packages/api-server/legacy/src/m20260402_000001_add_warehouse_fk_posts_solutions.rs diff --git a/packages/api-server/migration/src/m20260402_000002_create_try_spot_tags.rs b/packages/api-server/legacy/src/m20260402_000002_create_try_spot_tags.rs similarity index 100% rename from packages/api-server/migration/src/m20260402_000002_create_try_spot_tags.rs rename to packages/api-server/legacy/src/m20260402_000002_create_try_spot_tags.rs diff --git a/packages/api-server/migration/src/m20260403_000001_backfill_created_with_solutions.rs b/packages/api-server/legacy/src/m20260403_000001_backfill_created_with_solutions.rs similarity index 100% rename from packages/api-server/migration/src/m20260403_000001_backfill_created_with_solutions.rs rename to packages/api-server/legacy/src/m20260403_000001_backfill_created_with_solutions.rs diff --git a/packages/api-server/migration/src/m20260406_000001_drop_post_magazines_thread_id.rs b/packages/api-server/legacy/src/m20260406_000001_drop_post_magazines_thread_id.rs similarity index 100% rename from packages/api-server/migration/src/m20260406_000001_drop_post_magazines_thread_id.rs rename to packages/api-server/legacy/src/m20260406_000001_drop_post_magazines_thread_id.rs diff --git a/packages/api-server/migration/src/m20260406_000002_add_style_tags_to_posts.rs b/packages/api-server/legacy/src/m20260406_000002_add_style_tags_to_posts.rs similarity index 100% rename from packages/api-server/migration/src/m20260406_000002_add_style_tags_to_posts.rs rename to packages/api-server/legacy/src/m20260406_000002_add_style_tags_to_posts.rs diff --git a/packages/api-server/migration/src/m20260407_000001_create_post_magazine_news_references.rs b/packages/api-server/legacy/src/m20260407_000001_create_post_magazine_news_references.rs similarity index 100% rename from packages/api-server/migration/src/m20260407_000001_create_post_magazine_news_references.rs rename to packages/api-server/legacy/src/m20260407_000001_create_post_magazine_news_references.rs diff --git a/packages/api-server/migration/src/m20260409_add_image_dimensions.rs b/packages/api-server/legacy/src/m20260409_add_image_dimensions.rs similarity index 100% rename from packages/api-server/migration/src/m20260409_add_image_dimensions.rs rename to packages/api-server/legacy/src/m20260409_add_image_dimensions.rs diff --git a/packages/api-server/migration/src/m20260412_000001_add_posts_performance_indexes.rs b/packages/api-server/legacy/src/m20260412_000001_add_posts_performance_indexes.rs similarity index 100% rename from packages/api-server/migration/src/m20260412_000001_add_posts_performance_indexes.rs rename to packages/api-server/legacy/src/m20260412_000001_add_posts_performance_indexes.rs diff --git a/packages/api-server/migration/src/m20260419_000001_create_raw_posts_tables.rs b/packages/api-server/legacy/src/m20260419_000001_create_raw_posts_tables.rs similarity index 98% rename from packages/api-server/migration/src/m20260419_000001_create_raw_posts_tables.rs rename to packages/api-server/legacy/src/m20260419_000001_create_raw_posts_tables.rs index 95026749..3b6090d7 100644 --- a/packages/api-server/migration/src/m20260419_000001_create_raw_posts_tables.rs +++ b/packages/api-server/legacy/src/m20260419_000001_create_raw_posts_tables.rs @@ -2,7 +2,7 @@ use sea_orm_migration::prelude::*; /// #258 — create warehouse.raw_post_sources + warehouse.raw_posts. /// -/// This migration mirrors `supabase/migrations/20260419120000_create_raw_posts_tables.sql` +/// This migration mirrors `supabase/legacy/20260419120000_create_raw_posts_tables.sql` /// so local dev environments using the SeaORM runner stay in sync with /// Supabase-managed ones. #[derive(DeriveMigrationName)] diff --git a/packages/api-server/migration/src/m20260420_000001_add_initial_scraped_at_to_raw_post_sources.rs b/packages/api-server/legacy/src/m20260420_000001_add_initial_scraped_at_to_raw_post_sources.rs similarity index 100% rename from packages/api-server/migration/src/m20260420_000001_add_initial_scraped_at_to_raw_post_sources.rs rename to packages/api-server/legacy/src/m20260420_000001_add_initial_scraped_at_to_raw_post_sources.rs diff --git a/packages/api-server/migration/src/m20260501_000001_decouple_auth_users_fk.rs b/packages/api-server/legacy/src/m20260501_000001_decouple_auth_users_fk.rs similarity index 95% rename from packages/api-server/migration/src/m20260501_000001_decouple_auth_users_fk.rs rename to packages/api-server/legacy/src/m20260501_000001_decouple_auth_users_fk.rs index 5a443eca..44c2262b 100644 --- a/packages/api-server/migration/src/m20260501_000001_decouple_auth_users_fk.rs +++ b/packages/api-server/legacy/src/m20260501_000001_decouple_auth_users_fk.rs @@ -5,13 +5,13 @@ use sea_orm_migration::prelude::*; /// Why: Path X-1 (#267) requires public schema to stand alone on plain Postgres. /// `auth.users` only exists when Supabase GoTrue is running; local dev doesn't have it. /// `public.users` is already kept in sync with `auth.users` via the handle_new_user trigger -/// (see migration/sql/01_auth_trigger_handle_new_user.sql), so `public.users.id` is the +/// (see legacy/sql/01_auth_trigger_handle_new_user.sql), so `public.users.id` is the /// authoritative application-side identity. /// /// Idempotent: every step uses `DROP CONSTRAINT IF EXISTS` + `ADD CONSTRAINT` wrapped in /// `IF EXISTS` table checks. Prod (where old constraints exist) and fresh local (where /// some tables — content_reports, user_follows, user_tryon_history — haven't been created -/// yet because they still live in migration/sql/*) both converge safely. +/// yet because they still live in legacy/sql/*) both converge safely. #[derive(DeriveMigrationName)] pub struct Migration; @@ -57,7 +57,7 @@ impl MigrationTrait for Migration { .await?; // 3) public.user_follows: follower_id + following_id → public.users(id) CASCADE - // (table comes from migration/sql/04_user_follows.sql — may be absent locally) + // (table comes from legacy/sql/04_user_follows.sql — may be absent locally) conn.execute_unprepared( r#" DO $$ @@ -81,7 +81,7 @@ impl MigrationTrait for Migration { .await?; // 4) public.user_tryon_history.user_id → public.users(id) CASCADE - // (table comes from migration/sql/05_user_tryon_history.sql) + // (table comes from legacy/sql/05_user_tryon_history.sql) conn.execute_unprepared( r#" DO $$ @@ -99,7 +99,7 @@ impl MigrationTrait for Migration { .await?; // 5) public.content_reports.{reporter_id,reviewed_by} → public.users(id) - // (table comes from migration/sql/06_content_reports.sql) + // (table comes from legacy/sql/06_content_reports.sql) conn.execute_unprepared( r#" DO $$ diff --git a/packages/api-server/migration/src/m20260501_000002_auth_uid_stub.rs b/packages/api-server/legacy/src/m20260501_000002_auth_uid_stub.rs similarity index 100% rename from packages/api-server/migration/src/m20260501_000002_auth_uid_stub.rs rename to packages/api-server/legacy/src/m20260501_000002_auth_uid_stub.rs diff --git a/packages/api-server/migration/src/m20260502_000001_enable_extensions.rs b/packages/api-server/legacy/src/m20260502_000001_enable_extensions.rs similarity index 100% rename from packages/api-server/migration/src/m20260502_000001_enable_extensions.rs rename to packages/api-server/legacy/src/m20260502_000001_enable_extensions.rs diff --git a/packages/api-server/migration/src/m20260502_000002_warehouse_schema_tables_and_rls.rs b/packages/api-server/legacy/src/m20260502_000002_warehouse_schema_tables_and_rls.rs similarity index 99% rename from packages/api-server/migration/src/m20260502_000002_warehouse_schema_tables_and_rls.rs rename to packages/api-server/legacy/src/m20260502_000002_warehouse_schema_tables_and_rls.rs index f797f855..6eebfce4 100644 --- a/packages/api-server/migration/src/m20260502_000002_warehouse_schema_tables_and_rls.rs +++ b/packages/api-server/legacy/src/m20260502_000002_warehouse_schema_tables_and_rls.rs @@ -3,7 +3,7 @@ use sea_orm_migration::prelude::*; /// Bootstrap the entire `warehouse` schema: 12 tables + ENUMs + indexes + RLS + trigger. /// /// Why: `warehouse.*` was previously created only by -/// `supabase/migrations/20260409075040_remote_schema.sql` (Supabase CLI). After #202 the +/// `supabase/legacy/20260409075040_remote_schema.sql` (Supabase CLI). After #202 the /// SeaORM migrator is the single source of truth, so local plain Postgres needs to build /// the whole schema too. Prod already has everything — all statements are idempotent, so /// re-running against prod is a no-op. diff --git a/packages/api-server/migration/src/m20260502_000003_public_missing_tables_and_rls.rs b/packages/api-server/legacy/src/m20260502_000003_public_missing_tables_and_rls.rs similarity index 98% rename from packages/api-server/migration/src/m20260502_000003_public_missing_tables_and_rls.rs rename to packages/api-server/legacy/src/m20260502_000003_public_missing_tables_and_rls.rs index 6088b1d1..92dcd2c3 100644 --- a/packages/api-server/migration/src/m20260502_000003_public_missing_tables_and_rls.rs +++ b/packages/api-server/legacy/src/m20260502_000003_public_missing_tables_and_rls.rs @@ -1,7 +1,7 @@ use sea_orm_migration::prelude::*; /// Create `user_follows`, `user_tryon_history`, `content_reports` — tables that were -/// previously only in `packages/api-server/migration/sql/` (manual Supabase Dashboard runs). +/// previously only in `packages/api-server/legacy/sql/` (manual Supabase Dashboard runs). /// /// FK direction: these tables reference `public.users(id)` instead of `auth.users(id)` — /// matches the decoupling done by PR #267 (`m20260501_000001_decouple_auth_users_fk`). diff --git a/packages/api-server/migration/src/m20260502_000004_embeddings_and_search_similar.rs b/packages/api-server/legacy/src/m20260502_000004_embeddings_and_search_similar.rs similarity index 100% rename from packages/api-server/migration/src/m20260502_000004_embeddings_and_search_similar.rs rename to packages/api-server/legacy/src/m20260502_000004_embeddings_and_search_similar.rs diff --git a/packages/api-server/migration/src/m20260502_000005_magazine_approval_and_rpcs.rs b/packages/api-server/legacy/src/m20260502_000005_magazine_approval_and_rpcs.rs similarity index 100% rename from packages/api-server/migration/src/m20260502_000005_magazine_approval_and_rpcs.rs rename to packages/api-server/legacy/src/m20260502_000005_magazine_approval_and_rpcs.rs diff --git a/packages/api-server/migration/src/m20260502_000006_backfill_public_columns.rs b/packages/api-server/legacy/src/m20260502_000006_backfill_public_columns.rs similarity index 100% rename from packages/api-server/migration/src/m20260502_000006_backfill_public_columns.rs rename to packages/api-server/legacy/src/m20260502_000006_backfill_public_columns.rs diff --git a/packages/api-server/legacy/src/main.rs b/packages/api-server/legacy/src/main.rs new file mode 100644 index 00000000..391012ef --- /dev/null +++ b/packages/api-server/legacy/src/main.rs @@ -0,0 +1,6 @@ +use sea_orm_migration::prelude::*; + +#[tokio::main] +async fn main() { + cli::run_cli(migration_legacy::Migrator).await; +} diff --git a/packages/api-server/migration/README.md b/packages/api-server/migration/README.md index 2ae7e92a..71752b3f 100644 --- a/packages/api-server/migration/README.md +++ b/packages/api-server/migration/README.md @@ -1,68 +1,28 @@ -# Database Migrations +# Database Migrations (active) -SeaORM 마이그레이션 및 Supabase 설정 가이드 +**supabase-dev** 스키마에 맞춰 새로 추가하는 SeaORM 마이그레이션만 둔다. -## 마이그레이션 실행 +**주의**: 이미 `seaql_migrations`가 채워진 기존 DB에 연결할 때는, 첫 마이그레이션부터 스키마와 충돌하지 않게 작성해야 한다. 완전히 빈 DB(greenfield)에 맞추는 것이 목표다. -### 1. Rust 마이그레이션 실행 +- 과거 전체 마이그레이션 소스: [`../legacy/`](../legacy/) (보관, 크레이트 이름 `migration_legacy`) +- Supabase CLI SQL: [`../../supabase/migrations/`](../../supabase/migrations/) +- 에이전트 규칙: [`../AGENT.md`](../AGENT.md) §2.4 -```bash -# 마이그레이션 디렉토리로 이동 -cd migration +## 실행 -# 마이그레이션 적용 +```bash +cd packages/api-server/migration cargo run -- up - -# 마이그레이션 롤백 -cargo run -- down - -# 마이그레이션 상태 확인 -cargo run -- status - -# 마이그레이션 새로고침 (down → up) -cargo run -- refresh ``` -### 2. Supabase SQL 스크립트 실행 - -Rust 마이그레이션 후, Supabase Dashboard의 SQL Editor에서 다음 파일들을 순서대로 실행하세요: - -1. **Auth 트리거**: `sql/01_auth_trigger_handle_new_user.sql` - - Supabase Auth에서 새 사용자 생성 시 자동으로 users 테이블에 레코드 생성 - -2. **RLS 정책**: `sql/02_rls_policy_users.sql` - - users 테이블에 Row Level Security 정책 적용 - - 모든 사용자가 프로필 조회 가능 - - 사용자는 자신의 프로필만 수정/삭제 가능 - -## 마이그레이션 목록 - -### m20240101_000001_create_users - -- users 테이블 생성 -- auth.users 외래키 참조 (CASCADE DELETE) -- updated_at 자동 업데이트 트리거 -- 인덱스: email, username, rank - ## Entity 생성 -마이그레이션 실행 후 SeaORM Entity를 생성합니다: +스키마 반영 후 (기존과 동일): ```bash -# 프로젝트 루트로 이동 cd .. - -# entity 디렉토리 생성 (없는 경우) -mkdir -p src/entities - -# Entity 생성 sea-orm-cli generate entity \ --database-url "$DATABASE_URL" \ --output-dir src/entities \ --with-serde both ``` - -## 참고 - -- [SeaORM Migration 문서](https://www.sea-ql.org/SeaORM/docs/migration/writing-migration/) -- [Supabase RLS 문서](https://supabase.com/docs/guides/auth/row-level-security) diff --git a/packages/api-server/migration/src/lib.rs b/packages/api-server/migration/src/lib.rs index ef2b800a..c585e86a 100644 --- a/packages/api-server/migration/src/lib.rs +++ b/packages/api-server/migration/src/lib.rs @@ -1,145 +1,12 @@ +//! SeaORM 마이그레이션 — **supabase-dev 기준**으로 새로 쌓는 트랙. +//! 이전 전체 이력은 [`../legacy/`](../legacy/)를 참고한다. pub use sea_orm_migration::prelude::*; -mod m20230101_000000_local_auth_stub; -mod m20240101_000001_create_users; -mod m20240101_000002_create_categories; -mod m20240101_000003_create_posts; -mod m20240101_000004_create_spots; -mod m20240101_000005_create_solutions; -mod m20240101_000006_create_votes; -mod m20240101_000007_create_comments; -mod m20240101_000008_create_synonyms; -mod m20240101_000009_create_search_logs; -mod m20240101_000010_create_curations; -mod m20240101_000011_create_curation_posts; -mod m20240101_000013_create_badges; -mod m20240101_000014_create_user_badges; -mod m20240101_000015_create_click_logs; -mod m20240101_000016_create_earnings; -mod m20240101_000017_create_settlements; -mod m20240101_000018_create_view_logs; -mod m20240101_000019_seed_badges; -mod m20240101_000020_add_trending_score_to_posts; -mod m20260108_005000_create_point_logs; -mod m20260110_000001_create_subcategories; -mod m20260110_000002_update_categories_and_seed_subcategories; -mod m20260110_000003_alter_spots_subcategory_id; -mod m20260111_000001_add_ai_metadata_to_solutions; -mod m20260112_000001_add_comment_to_solutions; -mod m20260126_000001_add_qna_to_solutions; -mod m20260127_000001_update_solutions_schema; -mod m20260129_000001_remove_product_fields_from_solutions; -mod m20260129_000002_rename_solution_product_name_to_title; -mod m20260130_000001_add_link_type_to_solutions; -mod m20260205_000001_create_processed_batches; -mod m20260205_000002_create_failed_batch_items; -mod m20260205_000003_make_subcategory_nullable; -mod m20260205_000004_make_media_title_nullable; -mod m20260205_000005_rename_media_title_to_title; -mod m20260215_000001_add_created_with_solutions_to_posts; -mod m20260316_000001_create_post_magazines; -mod m20260316_000002_add_post_magazine_id_to_posts; -mod m20260317_000001_add_ai_summary_to_posts; -mod m20260318_000001_create_post_likes; -mod m20260318_000002_create_saved_posts; -mod m20260320_000001_add_system_uncategorized_subcategory; -mod m20260402_000001_add_try_fields_to_posts; -mod m20260402_000001_add_warehouse_fk_posts_solutions; -mod m20260402_000002_create_try_spot_tags; -mod m20260403_000001_backfill_created_with_solutions; -mod m20260406_000001_drop_post_magazines_thread_id; -mod m20260406_000002_add_style_tags_to_posts; -mod m20260407_000001_create_post_magazine_news_references; -mod m20260409_add_image_dimensions; -mod m20260412_000001_add_posts_performance_indexes; -mod m20260419_000001_create_raw_posts_tables; -mod m20260420_000001_add_initial_scraped_at_to_raw_post_sources; -mod m20260501_000001_decouple_auth_users_fk; -mod m20260501_000002_auth_uid_stub; -mod m20260502_000001_enable_extensions; -mod m20260502_000002_warehouse_schema_tables_and_rls; -mod m20260502_000003_public_missing_tables_and_rls; -mod m20260502_000004_embeddings_and_search_similar; -mod m20260502_000005_magazine_approval_and_rpcs; -mod m20260502_000006_backfill_public_columns; - pub struct Migrator; #[async_trait::async_trait] impl MigratorTrait for Migrator { fn migrations() -> Vec> { - vec![ - // Ensure auth.users stub exists before any FK references it (#267). - Box::new(m20230101_000000_local_auth_stub::Migration), - Box::new(m20240101_000001_create_users::Migration), - Box::new(m20240101_000002_create_categories::Migration), - Box::new(m20240101_000003_create_posts::Migration), - Box::new(m20240101_000004_create_spots::Migration), - Box::new(m20240101_000005_create_solutions::Migration), - Box::new(m20240101_000006_create_votes::Migration), - Box::new(m20240101_000007_create_comments::Migration), - Box::new(m20240101_000008_create_synonyms::Migration), - Box::new(m20240101_000009_create_search_logs::Migration), - Box::new(m20240101_000010_create_curations::Migration), - Box::new(m20240101_000011_create_curation_posts::Migration), - Box::new(m20260108_005000_create_point_logs::Migration), - Box::new(m20240101_000013_create_badges::Migration), - Box::new(m20240101_000014_create_user_badges::Migration), - Box::new(m20240101_000015_create_click_logs::Migration), - Box::new(m20240101_000016_create_earnings::Migration), - Box::new(m20240101_000017_create_settlements::Migration), - Box::new(m20240101_000018_create_view_logs::Migration), - Box::new(m20240101_000019_seed_badges::Migration), - Box::new(m20240101_000020_add_trending_score_to_posts::Migration), - Box::new(m20260110_000001_create_subcategories::Migration), - Box::new(m20260110_000002_update_categories_and_seed_subcategories::Migration), - Box::new(m20260110_000003_alter_spots_subcategory_id::Migration), - Box::new(m20260111_000001_add_ai_metadata_to_solutions::Migration), - Box::new(m20260112_000001_add_comment_to_solutions::Migration), - Box::new(m20260126_000001_add_qna_to_solutions::Migration), - Box::new(m20260127_000001_update_solutions_schema::Migration), - Box::new(m20260129_000001_remove_product_fields_from_solutions::Migration), - Box::new(m20260129_000002_rename_solution_product_name_to_title::Migration), - Box::new(m20260130_000001_add_link_type_to_solutions::Migration), - Box::new(m20260205_000001_create_processed_batches::Migration), - Box::new(m20260205_000002_create_failed_batch_items::Migration), - Box::new(m20260205_000003_make_subcategory_nullable::Migration), - Box::new(m20260205_000004_make_media_title_nullable::Migration), - Box::new(m20260205_000005_rename_media_title_to_title::Migration), - Box::new(m20260215_000001_add_created_with_solutions_to_posts::Migration), - Box::new(m20260316_000001_create_post_magazines::Migration), - Box::new(m20260316_000002_add_post_magazine_id_to_posts::Migration), - Box::new(m20260317_000001_add_ai_summary_to_posts::Migration), - Box::new(m20260318_000001_create_post_likes::Migration), - Box::new(m20260318_000002_create_saved_posts::Migration), - Box::new(m20260320_000001_add_system_uncategorized_subcategory::Migration), - Box::new(m20260402_000001_add_try_fields_to_posts::Migration), - Box::new(m20260402_000002_create_try_spot_tags::Migration), - // Warehouse schema must exist before the FK migration references it. - // On prod the schema already exists (Supabase CLI ran earlier); these new - // SeaORM migrations are idempotent no-ops there. On fresh local, these run - // first and create the schema so the FK migration below can succeed. - Box::new(m20260502_000001_enable_extensions::Migration), - Box::new(m20260502_000002_warehouse_schema_tables_and_rls::Migration), - Box::new(m20260402_000001_add_warehouse_fk_posts_solutions::Migration), - Box::new(m20260403_000001_backfill_created_with_solutions::Migration), - Box::new(m20260406_000001_drop_post_magazines_thread_id::Migration), - Box::new(m20260406_000002_add_style_tags_to_posts::Migration), - Box::new(m20260407_000001_create_post_magazine_news_references::Migration), - Box::new(m20260409_add_image_dimensions::Migration), - Box::new(m20260412_000001_add_posts_performance_indexes::Migration), - // #258 raw_posts pipeline tables - Box::new(m20260419_000001_create_raw_posts_tables::Migration), - // #214 Pinterest adapter — initial vs incremental scrape tracking - Box::new(m20260420_000001_add_initial_scraped_at_to_raw_post_sources::Migration), - // PR #273 — auth.uid() stub must run before RLS migrations that use it. - Box::new(m20260501_000002_auth_uid_stub::Migration), - Box::new(m20260501_000001_decouple_auth_users_fk::Migration), - // #202 remaining migrations (warehouse schema already registered above) - Box::new(m20260502_000003_public_missing_tables_and_rls::Migration), - Box::new(m20260502_000004_embeddings_and_search_similar::Migration), - Box::new(m20260502_000005_magazine_approval_and_rpcs::Migration), - Box::new(m20260502_000006_backfill_public_columns::Migration), - ] + vec![] } } diff --git a/supabase/migrations/20260409075040_remote_schema.sql b/supabase/legacy/20260409075040_remote_schema.sql similarity index 100% rename from supabase/migrations/20260409075040_remote_schema.sql rename to supabase/legacy/20260409075040_remote_schema.sql diff --git a/supabase/migrations/20260419120000_create_raw_posts_tables.sql b/supabase/legacy/20260419120000_create_raw_posts_tables.sql similarity index 100% rename from supabase/migrations/20260419120000_create_raw_posts_tables.sql rename to supabase/legacy/20260419120000_create_raw_posts_tables.sql diff --git a/supabase/legacy/README.md b/supabase/legacy/README.md new file mode 100644 index 00000000..33a113e5 --- /dev/null +++ b/supabase/legacy/README.md @@ -0,0 +1,5 @@ +# Supabase migrations — **legacy (archived)** + +이전에 사용하던 `supabase/migrations/` 내용이며, CLI 이력·원격 스키마 정렬용으로 보관한다. + +**활성 트랙**은 상위 [`../migrations/`](../migrations/) 이다. diff --git a/supabase/migrations/README.md b/supabase/migrations/README.md new file mode 100644 index 00000000..0c3979d5 --- /dev/null +++ b/supabase/migrations/README.md @@ -0,0 +1,14 @@ +# Supabase CLI migrations (active) + +**supabase-dev** 기준으로 새로 추가하는 SQL만 둔다. + +- 과거 스냅샷·incremental 전체: [`../legacy/`](../legacy/) +- SeaORM 활성 트랙: [`../../packages/api-server/migration/`](../../packages/api-server/migration/) +- 에이전트 역할 구분: [`../../packages/api-server/AGENT.md`](../../packages/api-server/AGENT.md) §2.4 + +## 적용 + +```bash +# 프로젝트 링크 후 +supabase db push +``` From 8ca1845b3a2c44aecfb18d37ec81514ee8ba8d9b Mon Sep 17 00:00:00 2001 From: CIOI Date: Wed, 22 Apr 2026 02:29:56 +0900 Subject: [PATCH 3/4] feat(migration): baseline SeaORM migrations and Supabase SQL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Split dev schema into m20260421_000001–000007 SeaORM steps with inline SQL bundles\n- Add split_dev_schema.py helper for regenerating step files from dumps\n- Add Supabase migrations: functions (20260421100000), triggers/auth (20260421110000), RLS (20260421120000)\n- Document apply order in api-server and supabase migration READMEs Made-with: Cursor --- packages/api-server/migration/README.md | 2 + .../migration/scripts/split_dev_schema.py | 255 ++ .../migration/sql/001_enable_extensions.sql | 4 + .../migration/sql/002_warehouse_types.sql | 39 + .../migration/sql/003_public_tables.sql | 833 ++++++ .../migration/sql/004_warehouse_tables.sql | 267 ++ .../api-server/migration/sql/005_views.sql | 32 + .../sql/006_indexes_and_constraints.sql | 2439 +++++++++++++++++ .../migration/sql/007_triggers_ddl.sql | 216 ++ packages/api-server/migration/src/lib.rs | 20 +- .../src/m20260421_000001_enable_extensions.rs | 20 + .../src/m20260421_000002_warehouse_types.rs | 20 + .../src/m20260421_000003_public_tables.rs | 20 + .../src/m20260421_000004_warehouse_tables.rs | 20 + .../migration/src/m20260421_000005_views.rs | 20 + ...20260421_000006_indexes_and_constraints.rs | 20 + .../src/m20260421_000007_triggers_ddl.rs | 20 + .../20260421100000_baseline_functions.sql | 251 ++ .../20260421110000_baseline_triggers_auth.sql | 6 + .../20260421120000_baseline_rls.sql | 831 ++++++ supabase/migrations/README.md | 1 + 21 files changed, 5335 insertions(+), 1 deletion(-) create mode 100644 packages/api-server/migration/scripts/split_dev_schema.py create mode 100644 packages/api-server/migration/sql/001_enable_extensions.sql create mode 100644 packages/api-server/migration/sql/002_warehouse_types.sql create mode 100644 packages/api-server/migration/sql/003_public_tables.sql create mode 100644 packages/api-server/migration/sql/004_warehouse_tables.sql create mode 100644 packages/api-server/migration/sql/005_views.sql create mode 100644 packages/api-server/migration/sql/006_indexes_and_constraints.sql create mode 100644 packages/api-server/migration/sql/007_triggers_ddl.sql create mode 100644 packages/api-server/migration/src/m20260421_000001_enable_extensions.rs create mode 100644 packages/api-server/migration/src/m20260421_000002_warehouse_types.rs create mode 100644 packages/api-server/migration/src/m20260421_000003_public_tables.rs create mode 100644 packages/api-server/migration/src/m20260421_000004_warehouse_tables.rs create mode 100644 packages/api-server/migration/src/m20260421_000005_views.rs create mode 100644 packages/api-server/migration/src/m20260421_000006_indexes_and_constraints.rs create mode 100644 packages/api-server/migration/src/m20260421_000007_triggers_ddl.rs create mode 100644 supabase/migrations/20260421100000_baseline_functions.sql create mode 100644 supabase/migrations/20260421110000_baseline_triggers_auth.sql create mode 100644 supabase/migrations/20260421120000_baseline_rls.sql diff --git a/packages/api-server/migration/README.md b/packages/api-server/migration/README.md index 71752b3f..d47724dd 100644 --- a/packages/api-server/migration/README.md +++ b/packages/api-server/migration/README.md @@ -2,6 +2,8 @@ **supabase-dev** 스키마에 맞춰 새로 추가하는 SeaORM 마이그레이션만 둔다. +- Baseline DDL은 `sql/*.sql`(Rust에서는 `include_str!`)로 두고, 갱신 절차는 저장소 루트 [`plan.md`](../../../plan.md)와 [`scripts/split_dev_schema.py`](scripts/split_dev_schema.py)를 본다. + **주의**: 이미 `seaql_migrations`가 채워진 기존 DB에 연결할 때는, 첫 마이그레이션부터 스키마와 충돌하지 않게 작성해야 한다. 완전히 빈 DB(greenfield)에 맞추는 것이 목표다. - 과거 전체 마이그레이션 소스: [`../legacy/`](../legacy/) (보관, 크레이트 이름 `migration_legacy`) diff --git a/packages/api-server/migration/scripts/split_dev_schema.py b/packages/api-server/migration/scripts/split_dev_schema.py new file mode 100644 index 00000000..5eae53a4 --- /dev/null +++ b/packages/api-server/migration/scripts/split_dev_schema.py @@ -0,0 +1,255 @@ +#!/usr/bin/env python3 +""" +Split repo-root dev-schema-*.sql into SeaORM sql/*.sql and supabase/migrations/20260421*.sql. +Run from repo root: python3 packages/api-server/migration/scripts/split_dev_schema.py +""" +from __future__ import annotations + +import re +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parents[4] +DUMP = REPO_ROOT / "dev-schema-20260421.sql" +MIG_SQL = REPO_ROOT / "packages/api-server/migration/sql" +SUPABASE_MIG = REPO_ROOT / "supabase/migrations" + +TRIGGER_FN_NAMES = frozenset( + { + "update_updated_at_column", + "set_updated_at", + "touch_updated_at", + } +) + + +def strip_restrict(lines: list[str]) -> list[str]: + out: list[str] = [] + for line in lines: + s = line.strip() + if s.startswith("\\restrict") or s.startswith("\\unrestrict"): + continue + out.append(line) + return out + + +def parse_header(first_line: str) -> tuple[str, str, str]: + """Return (name_field, type_field, schema_field).""" + m = re.match( + r"-- Name: (?P.+?); Type: (?P[^;]+); Schema: (?P[^;]+);", + first_line.strip(), + ) + if not m: + return ("", "", "") + return (m.group("name"), m.group("type").strip(), m.group("schema").strip()) + + +def is_trigger_helper_function(block_text: str, name_field: str) -> bool: + if not name_field: + return False + base = name_field.split("(")[0].strip() + if base in TRIGGER_FN_NAMES: + return True + if "CREATE FUNCTION public.update_updated_at_column" in block_text: + return True + if "CREATE FUNCTION warehouse.set_updated_at" in block_text: + return True + if "CREATE FUNCTION warehouse.touch_updated_at" in block_text: + return True + return False + + +def main() -> None: + if not DUMP.is_file(): + raise SystemExit(f"missing dump: {DUMP}") + + lines = strip_restrict(DUMP.read_text(encoding="utf-8").splitlines(keepends=True)) + + starts: list[int] = [] + for i, line in enumerate(lines): + if line.startswith("-- Name: "): + starts.append(i) + + blocks: list[str] = [] + for j, start in enumerate(starts): + end = starts[j + 1] if j + 1 < len(starts) else len(lines) + blocks.append("".join(lines[start:end])) + + buckets: dict[str, list[str]] = { + "002_warehouse_types": [], + "003_public_tables": [], + "004_warehouse_tables": [], + "005_views": [], + "006_indexes_and_constraints": [], + "007_triggers_ddl": [], + "supabase_functions": [], + "supabase_rls": [], + } + + # Preamble SETs before first table (after functions in dump): lines between first TABLE and previous + # Lines after search_similar function, before first public TABLE (SET default_tablespace / heap). + preamble_table_setup = "".join(lines[234:238]) + + for b in blocks: + first = b.splitlines()[0] if b else "" + name_f, typ, schema_f = parse_header(first) + + if typ == "SCHEMA" and "warehouse" in first and "public" not in first.split("Type:")[0]: + buckets["002_warehouse_types"].append(b) + continue + if typ == "TYPE": + buckets["002_warehouse_types"].append(b) + continue + + if typ == "TABLE": + if "seaql_migrations" in first and "Type: TABLE" in first: + continue + if schema_f == "public": + buckets["003_public_tables"].append(b) + elif schema_f == "warehouse": + buckets["004_warehouse_tables"].append(b) + continue + + if typ == "VIEW": + buckets["005_views"].append(b) + continue + + if typ == "INDEX": + buckets["006_indexes_and_constraints"].append(b) + continue + + if typ == "CONSTRAINT" or typ == "FK CONSTRAINT": + if "seaql_migrations" in first: + continue + buckets["006_indexes_and_constraints"].append(b) + continue + + if typ == "TRIGGER": + buckets["007_triggers_ddl"].append(b) + continue + + if typ == "FUNCTION": + if is_trigger_helper_function(b, name_f): + buckets["007_triggers_ddl"].append(b) + else: + buckets["supabase_functions"].append(b) + continue + + if typ == "COMMENT": + if "FUNCTION" in first and "handle_new_user" in first: + buckets["supabase_functions"].append(b) + continue + if "COLUMN" in first or "TABLE" in first: + if schema_f == "public": + buckets["003_public_tables"].append(b) + elif schema_f == "warehouse": + buckets["004_warehouse_tables"].append(b) + continue + if "SCHEMA" in first: + continue + continue + + if typ == "POLICY": + if "seaql_migrations" in first: + continue + buckets["supabase_rls"].append(b) + continue + + if typ == "ROW SECURITY": + if "seaql_migrations" in first: + continue + buckets["supabase_rls"].append(b) + continue + + # ignore SCHEMA public, COMMENT ON SCHEMA, etc. + + MIG_SQL.mkdir(parents=True, exist_ok=True) + SUPABASE_MIG.mkdir(parents=True, exist_ok=True) + + ext = """-- Baseline: extensions required by dev schema (not in pg_dump --schema-only). +CREATE SCHEMA IF NOT EXISTS extensions; +CREATE EXTENSION IF NOT EXISTS vector WITH SCHEMA extensions; +CREATE EXTENSION IF NOT EXISTS pg_trgm WITH SCHEMA extensions; +""" + (MIG_SQL / "001_enable_extensions.sql").write_text(ext, encoding="utf-8") + + def write_bucket(rel: str, parts: list[str], prefix: str = "") -> None: + body = prefix + "\n".join(parts) + (MIG_SQL / rel).write_text(body, encoding="utf-8") + + write_bucket( + "002_warehouse_types.sql", + buckets["002_warehouse_types"], + "-- warehouse schema + enum types\n\n", + ) + + write_bucket( + "003_public_tables.sql", + buckets["003_public_tables"], + "CREATE SCHEMA IF NOT EXISTS public;\n" + + "COMMENT ON SCHEMA public IS 'standard public schema';\n\n" + + preamble_table_setup + + "\n", + ) + + write_bucket( + "004_warehouse_tables.sql", + buckets["004_warehouse_tables"], + "-- warehouse tables\n\n", + ) + + write_bucket("005_views.sql", buckets["005_views"], "-- views\n\n") + + write_bucket( + "006_indexes_and_constraints.sql", + buckets["006_indexes_and_constraints"], + "-- PK, UNIQUE, indexes, FKs (reordered: indexes+FK after tables; triggers excluded)\n\n", + ) + + trig = buckets["007_triggers_ddl"] + # Ensure trigger functions appear before CREATE TRIGGER lines + trig_sorted = sorted( + trig, + key=lambda s: ( + 0 if "CREATE FUNCTION" in s else 1, + s, + ), + ) + write_bucket( + "007_triggers_ddl.sql", + trig_sorted, + "SET check_function_bodies = false;\n\n", + ) + + supa_fn = ( + "SET check_function_bodies = false;\n" + "SET client_min_messages = warning;\n\n" + + "".join(buckets["supabase_functions"]) + ) + (SUPABASE_MIG / "20260421100000_baseline_functions.sql").write_text( + supa_fn, encoding="utf-8" + ) + + auth_trig = """-- Auth trigger (not present in schema-only dump; pairs with public.handle_new_user) +DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users; +CREATE TRIGGER on_auth_user_created + AFTER INSERT ON auth.users + FOR EACH ROW + EXECUTE FUNCTION public.handle_new_user(); +""" + (SUPABASE_MIG / "20260421110000_baseline_triggers_auth.sql").write_text( + auth_trig, encoding="utf-8" + ) + + (SUPABASE_MIG / "20260421120000_baseline_rls.sql").write_text( + "".join(buckets["supabase_rls"]), + encoding="utf-8", + ) + + print("Wrote:", MIG_SQL / "001_enable_extensions.sql", "… 007_triggers_ddl.sql") + print("Wrote:", SUPABASE_MIG / "20260421100000_baseline_functions.sql") + print("Wrote:", SUPABASE_MIG / "20260421110000_baseline_triggers_auth.sql") + print("Wrote:", SUPABASE_MIG / "20260421120000_baseline_rls.sql") + + +if __name__ == "__main__": + main() diff --git a/packages/api-server/migration/sql/001_enable_extensions.sql b/packages/api-server/migration/sql/001_enable_extensions.sql new file mode 100644 index 00000000..152dfa19 --- /dev/null +++ b/packages/api-server/migration/sql/001_enable_extensions.sql @@ -0,0 +1,4 @@ +-- Baseline: extensions required by dev schema (not in pg_dump --schema-only). +CREATE SCHEMA IF NOT EXISTS extensions; +CREATE EXTENSION IF NOT EXISTS vector WITH SCHEMA extensions; +CREATE EXTENSION IF NOT EXISTS pg_trgm WITH SCHEMA extensions; diff --git a/packages/api-server/migration/sql/002_warehouse_types.sql b/packages/api-server/migration/sql/002_warehouse_types.sql new file mode 100644 index 00000000..c31ffdcc --- /dev/null +++ b/packages/api-server/migration/sql/002_warehouse_types.sql @@ -0,0 +1,39 @@ +-- warehouse schema + enum types + +-- Name: warehouse; Type: SCHEMA; Schema: -; Owner: - +-- + +CREATE SCHEMA IF NOT EXISTS warehouse; + + +-- + +-- Name: account_type; Type: TYPE; Schema: warehouse; Owner: - +-- + +CREATE TYPE warehouse.account_type AS ENUM ( + 'artist', + 'group', + 'brand', + 'source', + 'influencer', + 'place', + 'other', + 'company', + 'designer' +); + + +-- + +-- Name: entity_ig_role; Type: TYPE; Schema: warehouse; Owner: - +-- + +CREATE TYPE warehouse.entity_ig_role AS ENUM ( + 'primary', + 'regional', + 'secondary' +); + + +-- diff --git a/packages/api-server/migration/sql/003_public_tables.sql b/packages/api-server/migration/sql/003_public_tables.sql new file mode 100644 index 00000000..554ef8ca --- /dev/null +++ b/packages/api-server/migration/sql/003_public_tables.sql @@ -0,0 +1,833 @@ +CREATE SCHEMA IF NOT EXISTS public; +COMMENT ON SCHEMA public IS 'standard public schema'; + +SET default_tablespace = ''; + +SET default_table_access_method = heap; + +-- + +-- Name: post_magazines; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.post_magazines ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + title character varying DEFAULT 'Untitled'::character varying NOT NULL, + subtitle text, + keyword character varying, + layout_json jsonb, + status character varying DEFAULT 'draft'::character varying NOT NULL, + review_summary text, + error_log jsonb DEFAULT '[]'::jsonb, + created_at timestamp with time zone DEFAULT now() NOT NULL, + updated_at timestamp with time zone DEFAULT now() NOT NULL, + published_at timestamp with time zone, + approved_by uuid, + rejection_reason text, + CONSTRAINT post_magazines_status_check CHECK (((status)::text = ANY ((ARRAY['draft'::character varying, 'pending'::character varying, 'published'::character varying, 'rejected'::character varying])::text[]))) +); + + +-- + +-- Name: agent_sessions; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.agent_sessions ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + thread_id character varying(100) NOT NULL, + magazine_id uuid, + user_id uuid NOT NULL, + status character varying(20) DEFAULT 'active'::character varying NOT NULL, + keywords jsonb DEFAULT '[]'::jsonb, + message_count integer DEFAULT 0, + last_message_at timestamp with time zone, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + metadata jsonb DEFAULT '{}'::jsonb +); + + +-- + +-- Name: badges; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.badges ( + id uuid NOT NULL, + type character varying(50) NOT NULL, + name character varying(255) NOT NULL, + description text, + icon_url text, + criteria jsonb NOT NULL, + rarity character varying(20) DEFAULT 'common'::character varying NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: categories; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.categories ( + id uuid NOT NULL, + code character varying(50) NOT NULL, + name json NOT NULL, + icon_url text, + color_hex character varying(7), + description json, + display_order integer DEFAULT 0 NOT NULL, + is_active boolean DEFAULT true NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: checkpoint_blobs; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.checkpoint_blobs ( + thread_id text NOT NULL, + checkpoint_ns text DEFAULT ''::text NOT NULL, + channel text NOT NULL, + version text NOT NULL, + type text NOT NULL, + blob bytea +); + + +-- + +-- Name: checkpoint_migrations; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.checkpoint_migrations ( + v integer NOT NULL +); + + +-- + +-- Name: checkpoint_writes; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.checkpoint_writes ( + thread_id text NOT NULL, + checkpoint_ns text DEFAULT ''::text NOT NULL, + checkpoint_id text NOT NULL, + task_id text NOT NULL, + idx integer NOT NULL, + channel text NOT NULL, + type text, + blob bytea NOT NULL, + task_path text DEFAULT ''::text NOT NULL +); + + +-- + +-- Name: checkpoints; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.checkpoints ( + thread_id text NOT NULL, + checkpoint_ns text DEFAULT ''::text NOT NULL, + checkpoint_id text NOT NULL, + parent_checkpoint_id text, + type text, + checkpoint jsonb NOT NULL, + metadata jsonb DEFAULT '{}'::jsonb NOT NULL +); + + +-- + +-- Name: click_logs; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.click_logs ( + id uuid NOT NULL, + user_id uuid, + solution_id uuid NOT NULL, + ip_address character varying(45) NOT NULL, + user_agent text, + referrer text, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: comments; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.comments ( + id uuid NOT NULL, + post_id uuid NOT NULL, + user_id uuid NOT NULL, + parent_id uuid, + content text NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: content_reports; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.content_reports ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + target_type character varying(32) DEFAULT 'post'::character varying NOT NULL, + target_id uuid NOT NULL, + reporter_id uuid NOT NULL, + reason character varying(64) NOT NULL, + details text, + status character varying(32) DEFAULT 'pending'::character varying NOT NULL, + resolution text, + reviewed_by uuid, + created_at timestamp with time zone DEFAULT now() NOT NULL, + updated_at timestamp with time zone DEFAULT now() NOT NULL +); + + +-- + +-- Name: credit_transactions; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.credit_transactions ( + id uuid NOT NULL, + user_id uuid NOT NULL, + amount integer NOT NULL, + action_type character varying(50) NOT NULL, + status character varying(20) DEFAULT 'completed'::character varying NOT NULL, + reference_id uuid, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: curation_posts; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.curation_posts ( + curation_id uuid NOT NULL, + post_id uuid NOT NULL, + display_order integer DEFAULT 0 NOT NULL +); + + +-- + +-- Name: curations; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.curations ( + id uuid NOT NULL, + title character varying(255) NOT NULL, + description text, + cover_image_url text, + display_order integer DEFAULT 0 NOT NULL, + is_active boolean DEFAULT true NOT NULL, + created_at timestamp without time zone NOT NULL, + updated_at timestamp without time zone NOT NULL +); + + +-- + +-- Name: decoded_picks; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.decoded_picks ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + post_id uuid NOT NULL, + pick_date date DEFAULT CURRENT_DATE NOT NULL, + note text, + curated_by character varying DEFAULT 'system'::character varying NOT NULL, + is_active boolean DEFAULT true NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: earnings; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.earnings ( + id uuid NOT NULL, + user_id uuid NOT NULL, + solution_id uuid NOT NULL, + amount numeric(12,2) NOT NULL, + currency character varying(10) DEFAULT 'KRW'::character varying NOT NULL, + status character varying(20) DEFAULT 'pending'::character varying NOT NULL, + affiliate_platform character varying(50), + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: embeddings; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.embeddings ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + entity_type character varying(20) NOT NULL, + entity_id uuid NOT NULL, + content_text text NOT NULL, + embedding extensions.vector(256) NOT NULL, + created_at timestamp with time zone DEFAULT now() +); + + +-- + +-- Name: posts; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.posts ( + id uuid NOT NULL, + user_id uuid NOT NULL, + image_url text NOT NULL, + media_type character varying(50) NOT NULL, + title character varying(255), + media_metadata json, + group_name character varying(100), + artist_name character varying(100), + context character varying(50), + view_count integer DEFAULT 0 NOT NULL, + status character varying(20) DEFAULT 'active'::character varying NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + trending_score double precision, + created_with_solutions boolean, + post_magazine_id uuid, + ai_summary text, + artist_id uuid, + group_id uuid, + style_tags jsonb, + image_width integer, + image_height integer, + parent_post_id uuid, + post_type character varying(20) +); + + +-- + +-- Name: COLUMN posts.artist_id; Type: COMMENT; Schema: public; Owner: - +-- + +COMMENT ON COLUMN public.posts.artist_id IS 'FK to warehouse.artists.id (backfilled from legacy artist_name)'; + + +-- + +-- Name: COLUMN posts.group_id; Type: COMMENT; Schema: public; Owner: - +-- + +COMMENT ON COLUMN public.posts.group_id IS 'FK to warehouse.groups.id (backfilled from legacy group_name)'; + + +-- + +-- Name: COLUMN posts.image_width; Type: COMMENT; Schema: public; Owner: - +-- + +COMMENT ON COLUMN public.posts.image_width IS 'Original image width in pixels'; + + +-- + +-- Name: COLUMN posts.image_height; Type: COMMENT; Schema: public; Owner: - +-- + +COMMENT ON COLUMN public.posts.image_height IS 'Original image height in pixels'; + + +-- + +-- Name: failed_batch_items; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.failed_batch_items ( + id uuid NOT NULL, + item_id character varying(255) NOT NULL, + batch_id character varying(255) NOT NULL, + url text NOT NULL, + status character varying(50) NOT NULL, + error_message text, + retry_count integer DEFAULT 0 NOT NULL, + next_retry_at timestamp with time zone NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: magazine_posts; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.magazine_posts ( + magazine_id uuid NOT NULL, + post_id uuid NOT NULL, + section_index integer DEFAULT 0 NOT NULL +); + + +-- + +-- Name: magazines; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.magazines ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + title character varying(255) NOT NULL, + subtitle text, + keywords jsonb DEFAULT '[]'::jsonb NOT NULL, + spec jsonb DEFAULT '{}'::jsonb NOT NULL, + cover_image_url text, + theme character varying(50), + artists jsonb DEFAULT '[]'::jsonb, + status character varying(20) DEFAULT 'draft'::character varying NOT NULL, + review_notes text, + reviewed_at timestamp with time zone, + reviewed_by uuid, + published_at timestamp with time zone, + published_by uuid, + agent_version character varying(20), + generation_log jsonb DEFAULT '{}'::jsonb, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: point_logs; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.point_logs ( + id uuid NOT NULL, + user_id uuid NOT NULL, + activity_type character varying NOT NULL, + points integer NOT NULL, + ref_id uuid, + ref_type character varying, + description character varying, + created_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: post_likes; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.post_likes ( + id uuid NOT NULL, + post_id uuid NOT NULL, + user_id uuid NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: post_magazine_news_references; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.post_magazine_news_references ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + post_magazine_id uuid NOT NULL, + title character varying NOT NULL, + url character varying NOT NULL, + source character varying NOT NULL, + summary text, + og_title character varying, + og_description text, + og_image character varying, + og_site_name character varying, + relevance_score double precision DEFAULT 0 NOT NULL, + credibility_score double precision DEFAULT 0 NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + matched_item character varying +); + + +-- + +-- Name: processed_batches; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.processed_batches ( + batch_id character varying(255) NOT NULL, + processing_timestamp timestamp with time zone NOT NULL, + total_count integer NOT NULL, + success_count integer NOT NULL, + partial_count integer NOT NULL, + failed_count integer NOT NULL, + processing_time_ms integer NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: saved_posts; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.saved_posts ( + id uuid NOT NULL, + post_id uuid NOT NULL, + user_id uuid NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: search_logs; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.search_logs ( + id uuid NOT NULL, + user_id uuid, + query character varying(255) NOT NULL, + filters json, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: settlements; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.settlements ( + id uuid NOT NULL, + user_id uuid NOT NULL, + amount numeric(12,2) NOT NULL, + currency character varying(10) DEFAULT 'KRW'::character varying NOT NULL, + status character varying(20) DEFAULT 'pending'::character varying NOT NULL, + bank_info jsonb, + processed_at timestamp with time zone, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: solutions; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.solutions ( + id uuid NOT NULL, + spot_id uuid NOT NULL, + user_id uuid NOT NULL, + match_type character varying(20), + title character varying(255) NOT NULL, + original_url text, + affiliate_url text, + thumbnail_url text, + description text, + accurate_count integer DEFAULT 0 NOT NULL, + different_count integer DEFAULT 0 NOT NULL, + is_verified boolean DEFAULT false NOT NULL, + is_adopted boolean DEFAULT false NOT NULL, + adopted_at timestamp with time zone, + click_count integer DEFAULT 0 NOT NULL, + purchase_count integer DEFAULT 0 NOT NULL, + status character varying(20) DEFAULT 'active'::character varying NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + metadata jsonb, + comment text, + qna jsonb, + keywords jsonb, + link_type character varying(20) DEFAULT 'other'::character varying, + brand_id uuid, + price_amount numeric(12,2), + price_currency character varying(10) DEFAULT 'KRW'::character varying +); + + +-- + +-- Name: COLUMN solutions.metadata; Type: COMMENT; Schema: public; Owner: - +-- + +COMMENT ON COLUMN public.solutions.metadata IS 'Product metadata (price, brand, etc.)'; + + +-- + +-- Name: COLUMN solutions.comment; Type: COMMENT; Schema: public; Owner: - +-- + +COMMENT ON COLUMN public.solutions.comment IS 'Solver 코멘트 (상품 설명과 구분)'; + + +-- + +-- Name: COLUMN solutions.qna; Type: COMMENT; Schema: public; Owner: - +-- + +COMMENT ON COLUMN public.solutions.qna IS 'Question and Answer pairs from Gemini analysis'; + + +-- + +-- Name: COLUMN solutions.link_type; Type: COMMENT; Schema: public; Owner: - +-- + +COMMENT ON COLUMN public.solutions.link_type IS 'Link type: product | article | video | other'; + + +-- + +-- Name: COLUMN solutions.brand_id; Type: COMMENT; Schema: public; Owner: - +-- + +COMMENT ON COLUMN public.solutions.brand_id IS 'FK to warehouse.brands.id (backfilled from metadata.brand)'; + + +-- + +-- Name: spots; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.spots ( + id uuid NOT NULL, + post_id uuid NOT NULL, + user_id uuid NOT NULL, + position_left text NOT NULL, + position_top text NOT NULL, + subcategory_id uuid, + status character varying(20) DEFAULT 'open'::character varying NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: subcategories; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.subcategories ( + id uuid NOT NULL, + category_id uuid NOT NULL, + code character varying(50) NOT NULL, + name json NOT NULL, + description json, + display_order integer DEFAULT 0 NOT NULL, + is_active boolean DEFAULT true NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: synonyms; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.synonyms ( + id uuid NOT NULL, + type character varying(50) NOT NULL, + canonical character varying(255) NOT NULL, + synonyms text[] NOT NULL, + is_active boolean DEFAULT true NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: try_spot_tags; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.try_spot_tags ( + id uuid NOT NULL, + try_post_id uuid NOT NULL, + spot_id uuid NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: user_badges; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.user_badges ( + user_id uuid NOT NULL, + badge_id uuid NOT NULL, + earned_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: user_collections; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.user_collections ( + id uuid NOT NULL, + user_id uuid NOT NULL, + magazine_id uuid NOT NULL, + is_pinned boolean DEFAULT false NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: user_events; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.user_events ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + user_id uuid NOT NULL, + event_type character varying NOT NULL, + entity_id uuid, + session_id character varying NOT NULL, + page_path character varying NOT NULL, + metadata jsonb, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: user_follows; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.user_follows ( + follower_id uuid NOT NULL, + following_id uuid NOT NULL, + created_at timestamp with time zone DEFAULT now() NOT NULL +); + + +-- + +-- Name: user_magazines; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.user_magazines ( + id uuid NOT NULL, + created_by uuid NOT NULL, + magazine_type character varying(20) NOT NULL, + title text NOT NULL, + theme_palette jsonb, + layout_json jsonb, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: user_social_accounts; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.user_social_accounts ( + id uuid NOT NULL, + user_id uuid NOT NULL, + provider character varying(20) NOT NULL, + provider_user_id text NOT NULL, + access_token text NOT NULL, + refresh_token text, + last_synced_at timestamp with time zone, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: user_tryon_history; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.user_tryon_history ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + user_id uuid NOT NULL, + image_url text NOT NULL, + style_combination jsonb, + created_at timestamp with time zone DEFAULT now() NOT NULL +); + + +-- + +-- Name: TABLE user_tryon_history; Type: COMMENT; Schema: public; Owner: - +-- + +COMMENT ON TABLE public.user_tryon_history IS 'Virtual try-on (VTON) history for archive stats'; + + +-- + +-- Name: users; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.users ( + id uuid NOT NULL, + email character varying(255) NOT NULL, + username character varying(50) NOT NULL, + display_name character varying(100), + avatar_url text, + bio text, + rank character varying(20) DEFAULT 'Member'::character varying NOT NULL, + total_points integer DEFAULT 0 NOT NULL, + is_admin boolean DEFAULT false NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + style_dna jsonb, + ink_credits integer DEFAULT 5 NOT NULL, + studio_config jsonb +); + + +-- + +-- Name: view_logs; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.view_logs ( + id uuid NOT NULL, + user_id uuid, + reference_type character varying(20) NOT NULL, + reference_id uuid NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- + +-- Name: votes; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.votes ( + id uuid NOT NULL, + solution_id uuid NOT NULL, + user_id uuid NOT NULL, + vote_type character varying(20) NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); + + +-- diff --git a/packages/api-server/migration/sql/004_warehouse_tables.sql b/packages/api-server/migration/sql/004_warehouse_tables.sql new file mode 100644 index 00000000..505c0d30 --- /dev/null +++ b/packages/api-server/migration/sql/004_warehouse_tables.sql @@ -0,0 +1,267 @@ +-- warehouse tables + +-- Name: admin_audit_log; Type: TABLE; Schema: warehouse; Owner: - +-- + +CREATE TABLE warehouse.admin_audit_log ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + admin_user_id uuid NOT NULL, + action text NOT NULL, + target_table text NOT NULL, + target_id uuid, + before_state jsonb, + after_state jsonb, + metadata jsonb, + created_at timestamp with time zone DEFAULT now() NOT NULL +); + + +-- + +-- Name: TABLE admin_audit_log; Type: COMMENT; Schema: warehouse; Owner: - +-- + +COMMENT ON TABLE warehouse.admin_audit_log IS 'Admin action audit trail for all seed-ops and entity management operations'; + + +-- + +-- Name: artists; Type: TABLE; Schema: warehouse; Owner: - +-- + +CREATE TABLE warehouse.artists ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + name_ko text, + name_en text, + profile_image_url text, + primary_instagram_account_id uuid, + metadata jsonb, + created_at timestamp with time zone DEFAULT now() NOT NULL, + updated_at timestamp with time zone DEFAULT now() NOT NULL +); + + +-- + +-- Name: brands; Type: TABLE; Schema: warehouse; Owner: - +-- + +CREATE TABLE warehouse.brands ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + name_ko text, + name_en text, + logo_image_url text, + primary_instagram_account_id uuid, + metadata jsonb, + created_at timestamp with time zone DEFAULT now() NOT NULL, + updated_at timestamp with time zone DEFAULT now() NOT NULL +); + + +-- + +-- Name: group_members; Type: TABLE; Schema: warehouse; Owner: - +-- + +CREATE TABLE warehouse.group_members ( + group_id uuid NOT NULL, + artist_id uuid NOT NULL, + is_active boolean DEFAULT true NOT NULL, + metadata jsonb, + created_at timestamp with time zone DEFAULT now() NOT NULL, + updated_at timestamp with time zone DEFAULT now() NOT NULL +); + + +-- + +-- Name: groups; Type: TABLE; Schema: warehouse; Owner: - +-- + +CREATE TABLE warehouse.groups ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + name_ko text, + name_en text, + profile_image_url text, + primary_instagram_account_id uuid, + metadata jsonb, + created_at timestamp with time zone DEFAULT now() NOT NULL, + updated_at timestamp with time zone DEFAULT now() NOT NULL +); + + +-- + +-- Name: images; Type: TABLE; Schema: warehouse; Owner: - +-- + +CREATE TABLE warehouse.images ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + post_id uuid NOT NULL, + image_hash text NOT NULL, + image_url text NOT NULL, + with_items boolean DEFAULT false NOT NULL, + status text DEFAULT 'pending'::text NOT NULL, + created_at timestamp with time zone DEFAULT now() NOT NULL +); + + +-- + +-- Name: instagram_accounts; Type: TABLE; Schema: warehouse; Owner: - +-- + +CREATE TABLE warehouse.instagram_accounts ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + username text NOT NULL, + account_type warehouse.account_type NOT NULL, + name_ko text, + name_en text, + display_name text, + bio text, + profile_image_url text, + is_active boolean DEFAULT true NOT NULL, + metadata jsonb, + wikidata_status text, + wikidata_id text, + needs_review boolean, + created_at timestamp with time zone DEFAULT now() NOT NULL, + updated_at timestamp with time zone DEFAULT now() NOT NULL, + brand_id uuid, + artist_id uuid, + entity_ig_role warehouse.entity_ig_role, + entity_region_code text, + group_id uuid, + CONSTRAINT warehouse_instagram_accounts_brand_xor_artist CHECK ((NOT ((brand_id IS NOT NULL) AND (artist_id IS NOT NULL)))), + CONSTRAINT warehouse_instagram_accounts_entity_role_when_linked CHECK ((((brand_id IS NULL) AND (artist_id IS NULL)) OR (entity_ig_role IS NOT NULL))), + CONSTRAINT warehouse_instagram_accounts_wikidata_status_check CHECK (((wikidata_status IS NULL) OR (wikidata_status = ANY (ARRAY['matched'::text, 'not_found'::text, 'ambiguous'::text, 'error'::text])))) +); + + +-- + +-- Name: posts; Type: TABLE; Schema: warehouse; Owner: - +-- + +CREATE TABLE warehouse.posts ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + account_id uuid NOT NULL, + posted_at timestamp with time zone NOT NULL, + caption_text text, + tagged_account_ids uuid[], + created_at timestamp with time zone DEFAULT now() NOT NULL +); + + +-- + +-- Name: raw_post_sources; Type: TABLE; Schema: warehouse; Owner: - +-- + +CREATE TABLE warehouse.raw_post_sources ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + platform text NOT NULL, + source_type text NOT NULL, + source_identifier text NOT NULL, + label text, + is_active boolean DEFAULT true NOT NULL, + fetch_interval_seconds integer DEFAULT 3600 NOT NULL, + last_enqueued_at timestamp with time zone, + last_scraped_at timestamp with time zone, + metadata jsonb, + created_at timestamp with time zone DEFAULT now() NOT NULL, + updated_at timestamp with time zone DEFAULT now() NOT NULL +); + + +-- + +-- Name: raw_posts; Type: TABLE; Schema: warehouse; Owner: - +-- + +CREATE TABLE warehouse.raw_posts ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + source_id uuid NOT NULL, + platform text NOT NULL, + external_id text NOT NULL, + external_url text NOT NULL, + image_url text NOT NULL, + r2_key text, + r2_url text, + image_hash text, + caption text, + author_name text, + parse_status text DEFAULT 'pending'::text NOT NULL, + parse_result jsonb, + parse_error text, + parse_attempts integer DEFAULT 0 NOT NULL, + seed_post_id uuid, + platform_metadata jsonb, + dispatch_id text, + created_at timestamp with time zone DEFAULT now() NOT NULL, + updated_at timestamp with time zone DEFAULT now() NOT NULL, + CONSTRAINT raw_posts_parse_status_check CHECK ((parse_status = ANY (ARRAY['pending'::text, 'parsing'::text, 'parsed'::text, 'failed'::text, 'skipped'::text]))) +); + + +-- + +-- Name: seed_asset; Type: TABLE; Schema: warehouse; Owner: - +-- + +CREATE TABLE warehouse.seed_asset ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + seed_post_id uuid NOT NULL, + source_url text, + source_domain text, + archived_url text, + image_hash text NOT NULL, + metadata jsonb, + created_at timestamp with time zone DEFAULT now() NOT NULL, + updated_at timestamp with time zone DEFAULT now() NOT NULL +); + + +-- + +-- Name: seed_posts; Type: TABLE; Schema: warehouse; Owner: - +-- + +CREATE TABLE warehouse.seed_posts ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + source_post_id uuid, + source_image_id uuid, + image_url text NOT NULL, + media_source jsonb, + group_id uuid, + artist_id uuid, + metadata jsonb, + status text DEFAULT 'draft'::text NOT NULL, + publish_error text, + created_at timestamp with time zone DEFAULT now() NOT NULL, + updated_at timestamp with time zone DEFAULT now() NOT NULL, + backend_post_id uuid +); + + +-- + +-- Name: seed_spots; Type: TABLE; Schema: warehouse; Owner: - +-- + +CREATE TABLE warehouse.seed_spots ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + seed_post_id uuid NOT NULL, + request_order integer NOT NULL, + position_left text NOT NULL, + position_top text NOT NULL, + status text DEFAULT 'draft'::text NOT NULL, + publish_error text, + created_at timestamp with time zone DEFAULT now() NOT NULL, + updated_at timestamp with time zone DEFAULT now() NOT NULL, + solutions jsonb DEFAULT '[]'::jsonb NOT NULL, + subcategory_id uuid +); + + +-- diff --git a/packages/api-server/migration/sql/005_views.sql b/packages/api-server/migration/sql/005_views.sql new file mode 100644 index 00000000..e70665cf --- /dev/null +++ b/packages/api-server/migration/sql/005_views.sql @@ -0,0 +1,32 @@ +-- views + +-- Name: explore_posts; Type: VIEW; Schema: public; Owner: - +-- + +CREATE VIEW public.explore_posts WITH (security_invoker='true') AS + SELECT p.id, + p.user_id, + p.image_url, + p.media_type, + p.title, + p.media_metadata, + p.group_name, + p.artist_name, + p.context, + p.view_count, + p.status, + p.created_at, + p.updated_at, + p.trending_score, + p.created_with_solutions, + p.post_magazine_id, + p.ai_summary, + p.artist_id, + p.group_id, + pm.title AS post_magazine_title + FROM (public.posts p + JOIN public.post_magazines pm ON ((pm.id = p.post_magazine_id))) + WHERE (((p.status)::text = 'active'::text) AND (p.image_url IS NOT NULL) AND (p.created_with_solutions = true) AND ((pm.status)::text = 'published'::text)); + + +-- diff --git a/packages/api-server/migration/sql/006_indexes_and_constraints.sql b/packages/api-server/migration/sql/006_indexes_and_constraints.sql new file mode 100644 index 00000000..977585b9 --- /dev/null +++ b/packages/api-server/migration/sql/006_indexes_and_constraints.sql @@ -0,0 +1,2439 @@ +-- PK, UNIQUE, indexes, FKs (reordered: indexes+FK after tables; triggers excluded) + +-- Name: agent_sessions agent_sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.agent_sessions + ADD CONSTRAINT agent_sessions_pkey PRIMARY KEY (id); + + +-- + +-- Name: agent_sessions agent_sessions_thread_id_key; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.agent_sessions + ADD CONSTRAINT agent_sessions_thread_id_key UNIQUE (thread_id); + + +-- + +-- Name: badges badges_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.badges + ADD CONSTRAINT badges_pkey PRIMARY KEY (id); + + +-- + +-- Name: categories categories_code_key; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.categories + ADD CONSTRAINT categories_code_key UNIQUE (code); + + +-- + +-- Name: categories categories_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.categories + ADD CONSTRAINT categories_pkey PRIMARY KEY (id); + + +-- + +-- Name: checkpoint_blobs checkpoint_blobs_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.checkpoint_blobs + ADD CONSTRAINT checkpoint_blobs_pkey PRIMARY KEY (thread_id, checkpoint_ns, channel, version); + + +-- + +-- Name: checkpoint_migrations checkpoint_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.checkpoint_migrations + ADD CONSTRAINT checkpoint_migrations_pkey PRIMARY KEY (v); + + +-- + +-- Name: checkpoint_writes checkpoint_writes_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.checkpoint_writes + ADD CONSTRAINT checkpoint_writes_pkey PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id, task_id, idx); + + +-- + +-- Name: checkpoints checkpoints_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.checkpoints + ADD CONSTRAINT checkpoints_pkey PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id); + + +-- + +-- Name: click_logs click_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.click_logs + ADD CONSTRAINT click_logs_pkey PRIMARY KEY (id); + + +-- + +-- Name: comments comments_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.comments + ADD CONSTRAINT comments_pkey PRIMARY KEY (id); + + +-- + +-- Name: content_reports content_reports_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.content_reports + ADD CONSTRAINT content_reports_pkey PRIMARY KEY (id); + + +-- + +-- Name: credit_transactions credit_transactions_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.credit_transactions + ADD CONSTRAINT credit_transactions_pkey PRIMARY KEY (id); + + +-- + +-- Name: curation_posts curation_posts_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.curation_posts + ADD CONSTRAINT curation_posts_pkey PRIMARY KEY (curation_id, post_id); + + +-- + +-- Name: curations curations_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.curations + ADD CONSTRAINT curations_pkey PRIMARY KEY (id); + + +-- + +-- Name: decoded_picks decoded_picks_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.decoded_picks + ADD CONSTRAINT decoded_picks_pkey PRIMARY KEY (id); + + +-- + +-- Name: earnings earnings_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.earnings + ADD CONSTRAINT earnings_pkey PRIMARY KEY (id); + + +-- + +-- Name: embeddings embeddings_entity_type_entity_id_key; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.embeddings + ADD CONSTRAINT embeddings_entity_type_entity_id_key UNIQUE (entity_type, entity_id); + + +-- + +-- Name: embeddings embeddings_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.embeddings + ADD CONSTRAINT embeddings_pkey PRIMARY KEY (id); + + +-- + +-- Name: failed_batch_items failed_batch_items_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.failed_batch_items + ADD CONSTRAINT failed_batch_items_pkey PRIMARY KEY (id); + + +-- + +-- Name: magazine_posts magazine_posts_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.magazine_posts + ADD CONSTRAINT magazine_posts_pkey PRIMARY KEY (magazine_id, post_id); + + +-- + +-- Name: magazines magazines_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.magazines + ADD CONSTRAINT magazines_pkey PRIMARY KEY (id); + + +-- + +-- Name: user_badges pk_user_badges; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_badges + ADD CONSTRAINT pk_user_badges PRIMARY KEY (user_id, badge_id); + + +-- + +-- Name: point_logs point_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.point_logs + ADD CONSTRAINT point_logs_pkey PRIMARY KEY (id); + + +-- + +-- Name: post_likes post_likes_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.post_likes + ADD CONSTRAINT post_likes_pkey PRIMARY KEY (id); + + +-- + +-- Name: post_magazine_news_references post_magazine_news_references_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.post_magazine_news_references + ADD CONSTRAINT post_magazine_news_references_pkey PRIMARY KEY (id); + + +-- + +-- Name: post_magazines post_magazines_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.post_magazines + ADD CONSTRAINT post_magazines_pkey PRIMARY KEY (id); + + +-- + +-- Name: posts posts_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.posts + ADD CONSTRAINT posts_pkey PRIMARY KEY (id); + + +-- + +-- Name: processed_batches processed_batches_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.processed_batches + ADD CONSTRAINT processed_batches_pkey PRIMARY KEY (batch_id); + + +-- + +-- Name: saved_posts saved_posts_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.saved_posts + ADD CONSTRAINT saved_posts_pkey PRIMARY KEY (id); + + +-- + +-- Name: search_logs search_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.search_logs + ADD CONSTRAINT search_logs_pkey PRIMARY KEY (id); + + +-- + +-- Name: settlements settlements_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.settlements + ADD CONSTRAINT settlements_pkey PRIMARY KEY (id); + + +-- + +-- Name: solutions solutions_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.solutions + ADD CONSTRAINT solutions_pkey PRIMARY KEY (id); + + +-- + +-- Name: spots spots_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.spots + ADD CONSTRAINT spots_pkey PRIMARY KEY (id); + + +-- + +-- Name: subcategories subcategories_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.subcategories + ADD CONSTRAINT subcategories_pkey PRIMARY KEY (id); + + +-- + +-- Name: synonyms synonyms_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.synonyms + ADD CONSTRAINT synonyms_pkey PRIMARY KEY (id); + + +-- + +-- Name: try_spot_tags try_spot_tags_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.try_spot_tags + ADD CONSTRAINT try_spot_tags_pkey PRIMARY KEY (id); + + +-- + +-- Name: user_collections user_collections_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_collections + ADD CONSTRAINT user_collections_pkey PRIMARY KEY (id); + + +-- + +-- Name: user_events user_events_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_events + ADD CONSTRAINT user_events_pkey PRIMARY KEY (id); + + +-- + +-- Name: user_follows user_follows_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_follows + ADD CONSTRAINT user_follows_pkey PRIMARY KEY (follower_id, following_id); + + +-- + +-- Name: user_magazines user_magazines_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_magazines + ADD CONSTRAINT user_magazines_pkey PRIMARY KEY (id); + + +-- + +-- Name: user_social_accounts user_social_accounts_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_social_accounts + ADD CONSTRAINT user_social_accounts_pkey PRIMARY KEY (id); + + +-- + +-- Name: user_tryon_history user_tryon_history_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_tryon_history + ADD CONSTRAINT user_tryon_history_pkey PRIMARY KEY (id); + + +-- + +-- Name: users users_email_key; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.users + ADD CONSTRAINT users_email_key UNIQUE (email); + + +-- + +-- Name: users users_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.users + ADD CONSTRAINT users_pkey PRIMARY KEY (id); + + +-- + +-- Name: users users_username_key; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.users + ADD CONSTRAINT users_username_key UNIQUE (username); + + +-- + +-- Name: view_logs view_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.view_logs + ADD CONSTRAINT view_logs_pkey PRIMARY KEY (id); + + +-- + +-- Name: votes votes_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.votes + ADD CONSTRAINT votes_pkey PRIMARY KEY (id); + + +-- + +-- Name: admin_audit_log admin_audit_log_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.admin_audit_log + ADD CONSTRAINT admin_audit_log_pkey PRIMARY KEY (id); + + +-- + +-- Name: artists artists_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.artists + ADD CONSTRAINT artists_pkey PRIMARY KEY (id); + + +-- + +-- Name: brands brands_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.brands + ADD CONSTRAINT brands_pkey PRIMARY KEY (id); + + +-- + +-- Name: group_members group_members_pkey1; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.group_members + ADD CONSTRAINT group_members_pkey1 PRIMARY KEY (group_id, artist_id); + + +-- + +-- Name: groups groups_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.groups + ADD CONSTRAINT groups_pkey PRIMARY KEY (id); + + +-- + +-- Name: images images_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.images + ADD CONSTRAINT images_pkey PRIMARY KEY (id); + + +-- + +-- Name: instagram_accounts instagram_accounts_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.instagram_accounts + ADD CONSTRAINT instagram_accounts_pkey PRIMARY KEY (id); + + +-- + +-- Name: posts posts_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.posts + ADD CONSTRAINT posts_pkey PRIMARY KEY (id); + + +-- + +-- Name: raw_post_sources raw_post_sources_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.raw_post_sources + ADD CONSTRAINT raw_post_sources_pkey PRIMARY KEY (id); + + +-- + +-- Name: raw_post_sources raw_post_sources_unique_target; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.raw_post_sources + ADD CONSTRAINT raw_post_sources_unique_target UNIQUE (platform, source_type, source_identifier); + + +-- + +-- Name: raw_posts raw_posts_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.raw_posts + ADD CONSTRAINT raw_posts_pkey PRIMARY KEY (id); + + +-- + +-- Name: raw_posts raw_posts_unique_external; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.raw_posts + ADD CONSTRAINT raw_posts_unique_external UNIQUE (platform, external_id); + + +-- + +-- Name: seed_asset seed_asset_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.seed_asset + ADD CONSTRAINT seed_asset_pkey PRIMARY KEY (id); + + +-- + +-- Name: seed_posts seed_posts_backend_post_id_key; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.seed_posts + ADD CONSTRAINT seed_posts_backend_post_id_key UNIQUE (backend_post_id); + + +-- + +-- Name: seed_posts seed_posts_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.seed_posts + ADD CONSTRAINT seed_posts_pkey PRIMARY KEY (id); + + +-- + +-- Name: seed_spots seed_spots_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.seed_spots + ADD CONSTRAINT seed_spots_pkey PRIMARY KEY (id); + + +-- + +-- Name: images warehouse_images_post_id_image_hash_key; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.images + ADD CONSTRAINT warehouse_images_post_id_image_hash_key UNIQUE (post_id, image_hash); + + +-- + +-- Name: instagram_accounts warehouse_instagram_accounts_username_key; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.instagram_accounts + ADD CONSTRAINT warehouse_instagram_accounts_username_key UNIQUE (username); + + +-- + +-- Name: posts warehouse_posts_account_id_posted_at_key; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.posts + ADD CONSTRAINT warehouse_posts_account_id_posted_at_key UNIQUE (account_id, posted_at); + + +-- + +-- Name: seed_asset warehouse_seed_asset_image_hash_key; Type: CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.seed_asset + ADD CONSTRAINT warehouse_seed_asset_image_hash_key UNIQUE (image_hash); + + +-- + +-- Name: checkpoint_blobs_thread_id_idx; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX checkpoint_blobs_thread_id_idx ON public.checkpoint_blobs USING btree (thread_id); + + +-- + +-- Name: checkpoint_writes_thread_id_idx; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX checkpoint_writes_thread_id_idx ON public.checkpoint_writes USING btree (thread_id); + + +-- + +-- Name: checkpoints_thread_id_idx; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX checkpoints_thread_id_idx ON public.checkpoints USING btree (thread_id); + + +-- + +-- Name: idx_badges_rarity; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_badges_rarity ON public.badges USING btree (rarity); + + +-- + +-- Name: idx_badges_type; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_badges_type ON public.badges USING btree (type); + + +-- + +-- Name: idx_categories_code; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_categories_code ON public.categories USING btree (code); + + +-- + +-- Name: idx_categories_display_order; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_categories_display_order ON public.categories USING btree (display_order); + + +-- + +-- Name: idx_categories_is_active; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_categories_is_active ON public.categories USING btree (is_active); + + +-- + +-- Name: idx_click_logs_created_at; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_click_logs_created_at ON public.click_logs USING btree (created_at); + + +-- + +-- Name: idx_click_logs_ip_created; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_click_logs_ip_created ON public.click_logs USING btree (ip_address, created_at); + + +-- + +-- Name: idx_click_logs_solution_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_click_logs_solution_id ON public.click_logs USING btree (solution_id); + + +-- + +-- Name: idx_click_logs_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_click_logs_user_id ON public.click_logs USING btree (user_id); + + +-- + +-- Name: idx_click_logs_user_solution_created; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_click_logs_user_solution_created ON public.click_logs USING btree (user_id, solution_id, created_at); + + +-- + +-- Name: idx_comments_parent_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_comments_parent_id ON public.comments USING btree (parent_id); + + +-- + +-- Name: idx_comments_post_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_comments_post_id ON public.comments USING btree (post_id); + + +-- + +-- Name: idx_comments_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_comments_user_id ON public.comments USING btree (user_id); + + +-- + +-- Name: idx_content_reports_reporter; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_content_reports_reporter ON public.content_reports USING btree (reporter_id); + + +-- + +-- Name: idx_content_reports_status; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_content_reports_status ON public.content_reports USING btree (status); + + +-- + +-- Name: idx_content_reports_target; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_content_reports_target ON public.content_reports USING btree (target_type, target_id); + + +-- + +-- Name: idx_content_reports_unique_per_user; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX idx_content_reports_unique_per_user ON public.content_reports USING btree (target_type, target_id, reporter_id); + + +-- + +-- Name: idx_credit_transactions_action_type; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_credit_transactions_action_type ON public.credit_transactions USING btree (action_type); + + +-- + +-- Name: idx_credit_transactions_status; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_credit_transactions_status ON public.credit_transactions USING btree (status); + + +-- + +-- Name: idx_credit_transactions_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_credit_transactions_user_id ON public.credit_transactions USING btree (user_id); + + +-- + +-- Name: idx_curation_posts_curation_id_display_order; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_curation_posts_curation_id_display_order ON public.curation_posts USING btree (curation_id, display_order); + + +-- + +-- Name: idx_curation_posts_post_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_curation_posts_post_id ON public.curation_posts USING btree (post_id); + + +-- + +-- Name: idx_curations_is_active_display_order; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_curations_is_active_display_order ON public.curations USING btree (is_active, display_order); + + +-- + +-- Name: idx_decoded_picks_pick_date; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_decoded_picks_pick_date ON public.decoded_picks USING btree (pick_date DESC); + + +-- + +-- Name: idx_decoded_picks_post_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_decoded_picks_post_id ON public.decoded_picks USING btree (post_id); + + +-- + +-- Name: idx_earnings_created_at; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_earnings_created_at ON public.earnings USING btree (created_at); + + +-- + +-- Name: idx_earnings_solution_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_earnings_solution_id ON public.earnings USING btree (solution_id); + + +-- + +-- Name: idx_earnings_status; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_earnings_status ON public.earnings USING btree (status); + + +-- + +-- Name: idx_earnings_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_earnings_user_id ON public.earnings USING btree (user_id); + + +-- + +-- Name: idx_embeddings_entity_type; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_embeddings_entity_type ON public.embeddings USING btree (entity_type); + + +-- + +-- Name: idx_embeddings_hnsw; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_embeddings_hnsw ON public.embeddings USING hnsw (embedding extensions.vector_cosine_ops); + + +-- + +-- Name: idx_failed_items_item_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_failed_items_item_id ON public.failed_batch_items USING btree (item_id); + + +-- + +-- Name: idx_failed_items_retry; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_failed_items_retry ON public.failed_batch_items USING btree (next_retry_at); + + +-- + +-- Name: idx_news_refs_magazine; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_news_refs_magazine ON public.post_magazine_news_references USING btree (post_magazine_id); + + +-- + +-- Name: idx_point_logs_created_at; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_point_logs_created_at ON public.point_logs USING btree (created_at); + + +-- + +-- Name: idx_point_logs_user_created; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_point_logs_user_created ON public.point_logs USING btree (user_id, created_at); + + +-- + +-- Name: idx_point_logs_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_point_logs_user_id ON public.point_logs USING btree (user_id); + + +-- + +-- Name: idx_post_likes_post_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_post_likes_post_id ON public.post_likes USING btree (post_id); + + +-- + +-- Name: idx_post_likes_post_user_unique; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX idx_post_likes_post_user_unique ON public.post_likes USING btree (post_id, user_id); + + +-- + +-- Name: idx_post_likes_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_post_likes_user_id ON public.post_likes USING btree (user_id); + + +-- + +-- Name: idx_post_magazines_status; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_post_magazines_status ON public.post_magazines USING btree (status); + + +-- + +-- Name: idx_posts_artist_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_posts_artist_id ON public.posts USING btree (artist_id); + + +-- + +-- Name: idx_posts_artist_name; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_posts_artist_name ON public.posts USING btree (artist_name); + + +-- + +-- Name: idx_posts_artist_name_trgm; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_posts_artist_name_trgm ON public.posts USING gin (artist_name extensions.gin_trgm_ops); + + +-- + +-- Name: idx_posts_context; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_posts_context ON public.posts USING btree (context); + + +-- + +-- Name: idx_posts_created_at; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_posts_created_at ON public.posts USING btree (created_at); + + +-- + +-- Name: idx_posts_group_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_posts_group_id ON public.posts USING btree (group_id); + + +-- + +-- Name: idx_posts_group_name; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_posts_group_name ON public.posts USING btree (group_name); + + +-- + +-- Name: idx_posts_group_name_trgm; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_posts_group_name_trgm ON public.posts USING gin (group_name extensions.gin_trgm_ops); + + +-- + +-- Name: idx_posts_parent_post_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_posts_parent_post_id ON public.posts USING btree (parent_post_id); + + +-- + +-- Name: idx_posts_post_type; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_posts_post_type ON public.posts USING btree (post_type); + + +-- + +-- Name: idx_posts_status; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_posts_status ON public.posts USING btree (status); + + +-- + +-- Name: idx_posts_trending_active; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_posts_trending_active ON public.posts USING btree (trending_score DESC NULLS LAST, created_at DESC) WHERE (((status)::text = 'active'::text) AND ((post_type IS NULL) OR ((post_type)::text <> 'try'::text))); + + +-- + +-- Name: idx_posts_trending_score; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_posts_trending_score ON public.posts USING btree (trending_score); + + +-- + +-- Name: idx_posts_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_posts_user_id ON public.posts USING btree (user_id); + + +-- + +-- Name: idx_processed_batches_created_at; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_processed_batches_created_at ON public.processed_batches USING btree (created_at); + + +-- + +-- Name: idx_saved_posts_post_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_saved_posts_post_id ON public.saved_posts USING btree (post_id); + + +-- + +-- Name: idx_saved_posts_post_user_unique; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX idx_saved_posts_post_user_unique ON public.saved_posts USING btree (post_id, user_id); + + +-- + +-- Name: idx_saved_posts_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_saved_posts_user_id ON public.saved_posts USING btree (user_id); + + +-- + +-- Name: idx_search_logs_created_at; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_search_logs_created_at ON public.search_logs USING btree (created_at); + + +-- + +-- Name: idx_search_logs_query; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_search_logs_query ON public.search_logs USING btree (query); + + +-- + +-- Name: idx_search_logs_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_search_logs_user_id ON public.search_logs USING btree (user_id); + + +-- + +-- Name: idx_settlements_created_at; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_settlements_created_at ON public.settlements USING btree (created_at); + + +-- + +-- Name: idx_settlements_status; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_settlements_status ON public.settlements USING btree (status); + + +-- + +-- Name: idx_settlements_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_settlements_user_id ON public.settlements USING btree (user_id); + + +-- + +-- Name: idx_solutions_active_spot_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_solutions_active_spot_id ON public.solutions USING btree (spot_id) WHERE ((status)::text = 'active'::text); + + +-- + +-- Name: idx_solutions_brand_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_solutions_brand_id ON public.solutions USING btree (brand_id); + + +-- + +-- Name: idx_solutions_is_adopted; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_solutions_is_adopted ON public.solutions USING btree (is_adopted); + + +-- + +-- Name: idx_solutions_is_verified; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_solutions_is_verified ON public.solutions USING btree (is_verified); + + +-- + +-- Name: idx_solutions_match_type; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_solutions_match_type ON public.solutions USING btree (match_type); + + +-- + +-- Name: idx_solutions_spot_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_solutions_spot_id ON public.solutions USING btree (spot_id); + + +-- + +-- Name: idx_solutions_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_solutions_user_id ON public.solutions USING btree (user_id); + + +-- + +-- Name: idx_spots_post_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_spots_post_id ON public.spots USING btree (post_id); + + +-- + +-- Name: idx_spots_status; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_spots_status ON public.spots USING btree (status); + + +-- + +-- Name: idx_spots_subcategory_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_spots_subcategory_id ON public.spots USING btree (subcategory_id); + + +-- + +-- Name: idx_subcategories_category_code_unique; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX idx_subcategories_category_code_unique ON public.subcategories USING btree (category_id, code); + + +-- + +-- Name: idx_subcategories_category_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_subcategories_category_id ON public.subcategories USING btree (category_id); + + +-- + +-- Name: idx_subcategories_display_order; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_subcategories_display_order ON public.subcategories USING btree (display_order); + + +-- + +-- Name: idx_subcategories_is_active; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_subcategories_is_active ON public.subcategories USING btree (is_active); + + +-- + +-- Name: idx_synonyms_canonical; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_synonyms_canonical ON public.synonyms USING btree (canonical); + + +-- + +-- Name: idx_synonyms_is_active; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_synonyms_is_active ON public.synonyms USING btree (is_active); + + +-- + +-- Name: idx_synonyms_type; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_synonyms_type ON public.synonyms USING btree (type); + + +-- + +-- Name: idx_try_spot_tags_spot_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_try_spot_tags_spot_id ON public.try_spot_tags USING btree (spot_id); + + +-- + +-- Name: idx_try_spot_tags_try_post_spot_unique; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX idx_try_spot_tags_try_post_spot_unique ON public.try_spot_tags USING btree (try_post_id, spot_id); + + +-- + +-- Name: idx_user_badges_badge_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_user_badges_badge_id ON public.user_badges USING btree (badge_id); + + +-- + +-- Name: idx_user_badges_earned_at; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_user_badges_earned_at ON public.user_badges USING btree (earned_at); + + +-- + +-- Name: idx_user_badges_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_user_badges_user_id ON public.user_badges USING btree (user_id); + + +-- + +-- Name: idx_user_collections_user_magazine; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX idx_user_collections_user_magazine ON public.user_collections USING btree (user_id, magazine_id); + + +-- + +-- Name: idx_user_events_created_at; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_user_events_created_at ON public.user_events USING btree (created_at DESC); + + +-- + +-- Name: idx_user_events_event_type; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_user_events_event_type ON public.user_events USING btree (event_type); + + +-- + +-- Name: idx_user_events_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_user_events_user_id ON public.user_events USING btree (user_id); + + +-- + +-- Name: idx_user_follows_follower_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_user_follows_follower_id ON public.user_follows USING btree (follower_id); + + +-- + +-- Name: idx_user_follows_following_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_user_follows_following_id ON public.user_follows USING btree (following_id); + + +-- + +-- Name: idx_user_magazines_created_by; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_user_magazines_created_by ON public.user_magazines USING btree (created_by); + + +-- + +-- Name: idx_user_magazines_type; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_user_magazines_type ON public.user_magazines USING btree (magazine_type); + + +-- + +-- Name: idx_user_social_accounts_user_provider; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX idx_user_social_accounts_user_provider ON public.user_social_accounts USING btree (user_id, provider); + + +-- + +-- Name: idx_user_tryon_history_created_at; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_user_tryon_history_created_at ON public.user_tryon_history USING btree (user_id, created_at DESC); + + +-- + +-- Name: idx_user_tryon_history_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_user_tryon_history_user_id ON public.user_tryon_history USING btree (user_id); + + +-- + +-- Name: idx_users_email; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_users_email ON public.users USING btree (email); + + +-- + +-- Name: idx_users_rank; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_users_rank ON public.users USING btree (rank); + + +-- + +-- Name: idx_users_username; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_users_username ON public.users USING btree (username); + + +-- + +-- Name: idx_view_logs_created_at; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_view_logs_created_at ON public.view_logs USING btree (created_at); + + +-- + +-- Name: idx_view_logs_reference; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_view_logs_reference ON public.view_logs USING btree (reference_type, reference_id); + + +-- + +-- Name: idx_view_logs_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_view_logs_user_id ON public.view_logs USING btree (user_id); + + +-- + +-- Name: idx_view_logs_user_reference_created; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_view_logs_user_reference_created ON public.view_logs USING btree (user_id, reference_type, reference_id, created_at); + + +-- + +-- Name: idx_votes_solution_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_votes_solution_id ON public.votes USING btree (solution_id); + + +-- + +-- Name: idx_votes_solution_user_unique; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX idx_votes_solution_user_unique ON public.votes USING btree (solution_id, user_id); + + +-- + +-- Name: idx_votes_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_votes_user_id ON public.votes USING btree (user_id); + + +-- + +-- Name: post_magazines_status_idx; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX post_magazines_status_idx ON public.post_magazines USING btree (status) WHERE ((status)::text = ANY ((ARRAY['pending'::character varying, 'draft'::character varying])::text[])); + + +-- + +-- Name: idx_audit_log_admin; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_audit_log_admin ON warehouse.admin_audit_log USING btree (admin_user_id); + + +-- + +-- Name: idx_audit_log_created; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_audit_log_created ON warehouse.admin_audit_log USING btree (created_at DESC); + + +-- + +-- Name: idx_audit_log_target; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_audit_log_target ON warehouse.admin_audit_log USING btree (target_table, target_id); + + +-- + +-- Name: idx_warehouse_group_members_artist_id; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_group_members_artist_id ON warehouse.group_members USING btree (artist_id); + + +-- + +-- Name: idx_warehouse_group_members_is_active; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_group_members_is_active ON warehouse.group_members USING btree (is_active); + + +-- + +-- Name: idx_warehouse_images_post_id; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_images_post_id ON warehouse.images USING btree (post_id); + + +-- + +-- Name: idx_warehouse_images_with_items; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_images_with_items ON warehouse.images USING btree (with_items); + + +-- + +-- Name: idx_warehouse_instagram_accounts_active; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_instagram_accounts_active ON warehouse.instagram_accounts USING btree (is_active); + + +-- + +-- Name: idx_warehouse_instagram_accounts_artist_id; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_instagram_accounts_artist_id ON warehouse.instagram_accounts USING btree (artist_id) WHERE (artist_id IS NOT NULL); + + +-- + +-- Name: idx_warehouse_instagram_accounts_brand_id; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_instagram_accounts_brand_id ON warehouse.instagram_accounts USING btree (brand_id) WHERE (brand_id IS NOT NULL); + + +-- + +-- Name: idx_warehouse_instagram_accounts_group_id; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_instagram_accounts_group_id ON warehouse.instagram_accounts USING btree (group_id); + + +-- + +-- Name: idx_warehouse_instagram_accounts_type; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_instagram_accounts_type ON warehouse.instagram_accounts USING btree (account_type); + + +-- + +-- Name: idx_warehouse_posts_account_id; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_posts_account_id ON warehouse.posts USING btree (account_id); + + +-- + +-- Name: idx_warehouse_posts_posted_at; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_posts_posted_at ON warehouse.posts USING btree (posted_at); + + +-- + +-- Name: idx_warehouse_posts_tagged_account_ids; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_posts_tagged_account_ids ON warehouse.posts USING gin (tagged_account_ids); + + +-- + +-- Name: idx_warehouse_seed_asset_seed_post_id; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_seed_asset_seed_post_id ON warehouse.seed_asset USING btree (seed_post_id); + + +-- + +-- Name: idx_warehouse_seed_posts_source_image_id; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_seed_posts_source_image_id ON warehouse.seed_posts USING btree (source_image_id); + + +-- + +-- Name: idx_warehouse_seed_posts_source_post_id; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_seed_posts_source_post_id ON warehouse.seed_posts USING btree (source_post_id); + + +-- + +-- Name: idx_warehouse_seed_posts_status; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_seed_posts_status ON warehouse.seed_posts USING btree (status); + + +-- + +-- Name: idx_warehouse_seed_spots_request_order; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_seed_spots_request_order ON warehouse.seed_spots USING btree (request_order); + + +-- + +-- Name: idx_warehouse_seed_spots_seed_post_id; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_seed_spots_seed_post_id ON warehouse.seed_spots USING btree (seed_post_id); + + +-- + +-- Name: idx_warehouse_seed_spots_status; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX idx_warehouse_seed_spots_status ON warehouse.seed_spots USING btree (status); + + +-- + +-- Name: raw_post_sources_active_platform_idx; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX raw_post_sources_active_platform_idx ON warehouse.raw_post_sources USING btree (is_active, platform); + + +-- + +-- Name: raw_post_sources_due_idx; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX raw_post_sources_due_idx ON warehouse.raw_post_sources USING btree (last_enqueued_at) WHERE (is_active = true); + + +-- + +-- Name: raw_posts_parse_status_idx; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX raw_posts_parse_status_idx ON warehouse.raw_posts USING btree (parse_status, created_at); + + +-- + +-- Name: raw_posts_platform_idx; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX raw_posts_platform_idx ON warehouse.raw_posts USING btree (platform); + + +-- + +-- Name: raw_posts_source_idx; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE INDEX raw_posts_source_idx ON warehouse.raw_posts USING btree (source_id); + + +-- + +-- Name: uq_warehouse_seed_posts_source_post_image; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE UNIQUE INDEX uq_warehouse_seed_posts_source_post_image ON warehouse.seed_posts USING btree (source_post_id, source_image_id) WHERE ((source_post_id IS NOT NULL) AND (source_image_id IS NOT NULL)); + + +-- + +-- Name: warehouse_artists_primary_ig_unique; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE UNIQUE INDEX warehouse_artists_primary_ig_unique ON warehouse.artists USING btree (primary_instagram_account_id) WHERE (primary_instagram_account_id IS NOT NULL); + + +-- + +-- Name: warehouse_brands_primary_ig_unique; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE UNIQUE INDEX warehouse_brands_primary_ig_unique ON warehouse.brands USING btree (primary_instagram_account_id) WHERE (primary_instagram_account_id IS NOT NULL); + + +-- + +-- Name: warehouse_groups_primary_ig_unique; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE UNIQUE INDEX warehouse_groups_primary_ig_unique ON warehouse.groups USING btree (primary_instagram_account_id) WHERE (primary_instagram_account_id IS NOT NULL); + + +-- + +-- Name: warehouse_ig_one_primary_per_artist; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE UNIQUE INDEX warehouse_ig_one_primary_per_artist ON warehouse.instagram_accounts USING btree (artist_id) WHERE ((artist_id IS NOT NULL) AND (entity_ig_role = 'primary'::warehouse.entity_ig_role)); + + +-- + +-- Name: warehouse_ig_one_primary_per_brand; Type: INDEX; Schema: warehouse; Owner: - +-- + +CREATE UNIQUE INDEX warehouse_ig_one_primary_per_brand ON warehouse.instagram_accounts USING btree (brand_id) WHERE ((brand_id IS NOT NULL) AND (entity_ig_role = 'primary'::warehouse.entity_ig_role)); + + +-- + +-- Name: agent_sessions agent_sessions_magazine_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.agent_sessions + ADD CONSTRAINT agent_sessions_magazine_id_fkey FOREIGN KEY (magazine_id) REFERENCES public.magazines(id); + + +-- + +-- Name: agent_sessions agent_sessions_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.agent_sessions + ADD CONSTRAINT agent_sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id); + + +-- + +-- Name: content_reports content_reports_reporter_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.content_reports + ADD CONSTRAINT content_reports_reporter_id_fkey FOREIGN KEY (reporter_id) REFERENCES auth.users(id) ON DELETE CASCADE; + + +-- + +-- Name: content_reports content_reports_reviewed_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.content_reports + ADD CONSTRAINT content_reports_reviewed_by_fkey FOREIGN KEY (reviewed_by) REFERENCES auth.users(id); + + +-- + +-- Name: credit_transactions credit_transactions_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.credit_transactions + ADD CONSTRAINT credit_transactions_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: decoded_picks decoded_picks_post_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.decoded_picks + ADD CONSTRAINT decoded_picks_post_id_fkey FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; + + +-- + +-- Name: click_logs fk_click_logs_solution_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.click_logs + ADD CONSTRAINT fk_click_logs_solution_id FOREIGN KEY (solution_id) REFERENCES public.solutions(id) ON DELETE CASCADE; + + +-- + +-- Name: click_logs fk_click_logs_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.click_logs + ADD CONSTRAINT fk_click_logs_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL; + + +-- + +-- Name: comments fk_comments_parent_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.comments + ADD CONSTRAINT fk_comments_parent_id FOREIGN KEY (parent_id) REFERENCES public.comments(id) ON DELETE CASCADE; + + +-- + +-- Name: comments fk_comments_post_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.comments + ADD CONSTRAINT fk_comments_post_id FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; + + +-- + +-- Name: comments fk_comments_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.comments + ADD CONSTRAINT fk_comments_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: curation_posts fk_curation_posts_curation_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.curation_posts + ADD CONSTRAINT fk_curation_posts_curation_id FOREIGN KEY (curation_id) REFERENCES public.curations(id) ON DELETE CASCADE; + + +-- + +-- Name: curation_posts fk_curation_posts_post_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.curation_posts + ADD CONSTRAINT fk_curation_posts_post_id FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; + + +-- + +-- Name: earnings fk_earnings_solution_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.earnings + ADD CONSTRAINT fk_earnings_solution_id FOREIGN KEY (solution_id) REFERENCES public.solutions(id) ON DELETE CASCADE; + + +-- + +-- Name: earnings fk_earnings_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.earnings + ADD CONSTRAINT fk_earnings_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: point_logs fk_point_logs_user; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.point_logs + ADD CONSTRAINT fk_point_logs_user FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: post_likes fk_post_likes_post_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.post_likes + ADD CONSTRAINT fk_post_likes_post_id FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; + + +-- + +-- Name: post_likes fk_post_likes_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.post_likes + ADD CONSTRAINT fk_post_likes_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: posts fk_posts_artist_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.posts + ADD CONSTRAINT fk_posts_artist_id FOREIGN KEY (artist_id) REFERENCES warehouse.artists(id) ON DELETE SET NULL; + + +-- + +-- Name: posts fk_posts_group_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.posts + ADD CONSTRAINT fk_posts_group_id FOREIGN KEY (group_id) REFERENCES warehouse.groups(id) ON DELETE SET NULL; + + +-- + +-- Name: posts fk_posts_parent_post_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.posts + ADD CONSTRAINT fk_posts_parent_post_id FOREIGN KEY (parent_post_id) REFERENCES public.posts(id) ON DELETE SET NULL; + + +-- + +-- Name: posts fk_posts_post_magazine_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.posts + ADD CONSTRAINT fk_posts_post_magazine_id FOREIGN KEY (post_magazine_id) REFERENCES public.post_magazines(id) ON DELETE SET NULL; + + +-- + +-- Name: posts fk_posts_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.posts + ADD CONSTRAINT fk_posts_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: saved_posts fk_saved_posts_post_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.saved_posts + ADD CONSTRAINT fk_saved_posts_post_id FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; + + +-- + +-- Name: saved_posts fk_saved_posts_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.saved_posts + ADD CONSTRAINT fk_saved_posts_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: search_logs fk_search_logs_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.search_logs + ADD CONSTRAINT fk_search_logs_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON UPDATE CASCADE ON DELETE SET NULL; + + +-- + +-- Name: settlements fk_settlements_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.settlements + ADD CONSTRAINT fk_settlements_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: solutions fk_solutions_brand_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.solutions + ADD CONSTRAINT fk_solutions_brand_id FOREIGN KEY (brand_id) REFERENCES warehouse.brands(id) ON DELETE SET NULL; + + +-- + +-- Name: solutions fk_solutions_spot_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.solutions + ADD CONSTRAINT fk_solutions_spot_id FOREIGN KEY (spot_id) REFERENCES public.spots(id) ON DELETE CASCADE; + + +-- + +-- Name: solutions fk_solutions_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.solutions + ADD CONSTRAINT fk_solutions_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: spots fk_spots_post_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.spots + ADD CONSTRAINT fk_spots_post_id FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; + + +-- + +-- Name: spots fk_spots_subcategory_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.spots + ADD CONSTRAINT fk_spots_subcategory_id FOREIGN KEY (subcategory_id) REFERENCES public.subcategories(id); + + +-- + +-- Name: spots fk_spots_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.spots + ADD CONSTRAINT fk_spots_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: subcategories fk_subcategories_category_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.subcategories + ADD CONSTRAINT fk_subcategories_category_id FOREIGN KEY (category_id) REFERENCES public.categories(id) ON DELETE CASCADE; + + +-- + +-- Name: try_spot_tags fk_try_spot_tags_spot_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.try_spot_tags + ADD CONSTRAINT fk_try_spot_tags_spot_id FOREIGN KEY (spot_id) REFERENCES public.spots(id) ON DELETE CASCADE; + + +-- + +-- Name: try_spot_tags fk_try_spot_tags_try_post_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.try_spot_tags + ADD CONSTRAINT fk_try_spot_tags_try_post_id FOREIGN KEY (try_post_id) REFERENCES public.posts(id) ON DELETE CASCADE; + + +-- + +-- Name: user_badges fk_user_badges_badge_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_badges + ADD CONSTRAINT fk_user_badges_badge_id FOREIGN KEY (badge_id) REFERENCES public.badges(id) ON DELETE CASCADE; + + +-- + +-- Name: user_badges fk_user_badges_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_badges + ADD CONSTRAINT fk_user_badges_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: users fk_users_auth_users; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.users + ADD CONSTRAINT fk_users_auth_users FOREIGN KEY (id) REFERENCES auth.users(id) ON DELETE CASCADE; + + +-- + +-- Name: view_logs fk_view_logs_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.view_logs + ADD CONSTRAINT fk_view_logs_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL; + + +-- + +-- Name: votes fk_votes_solution_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.votes + ADD CONSTRAINT fk_votes_solution_id FOREIGN KEY (solution_id) REFERENCES public.solutions(id) ON DELETE CASCADE; + + +-- + +-- Name: votes fk_votes_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.votes + ADD CONSTRAINT fk_votes_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: magazine_posts magazine_posts_magazine_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.magazine_posts + ADD CONSTRAINT magazine_posts_magazine_id_fkey FOREIGN KEY (magazine_id) REFERENCES public.magazines(id) ON DELETE CASCADE; + + +-- + +-- Name: magazine_posts magazine_posts_post_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.magazine_posts + ADD CONSTRAINT magazine_posts_post_id_fkey FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; + + +-- + +-- Name: magazines magazines_published_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.magazines + ADD CONSTRAINT magazines_published_by_fkey FOREIGN KEY (published_by) REFERENCES public.users(id); + + +-- + +-- Name: magazines magazines_reviewed_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.magazines + ADD CONSTRAINT magazines_reviewed_by_fkey FOREIGN KEY (reviewed_by) REFERENCES public.users(id); + + +-- + +-- Name: post_magazine_news_references post_magazine_news_references_post_magazine_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.post_magazine_news_references + ADD CONSTRAINT post_magazine_news_references_post_magazine_id_fkey FOREIGN KEY (post_magazine_id) REFERENCES public.post_magazines(id) ON DELETE CASCADE; + + +-- + +-- Name: post_magazines post_magazines_approved_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.post_magazines + ADD CONSTRAINT post_magazines_approved_by_fkey FOREIGN KEY (approved_by) REFERENCES auth.users(id) ON DELETE SET NULL; + + +-- + +-- Name: user_collections user_collections_magazine_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_collections + ADD CONSTRAINT user_collections_magazine_id_fkey FOREIGN KEY (magazine_id) REFERENCES public.user_magazines(id) ON DELETE CASCADE; + + +-- + +-- Name: user_collections user_collections_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_collections + ADD CONSTRAINT user_collections_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: user_events user_events_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_events + ADD CONSTRAINT user_events_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: user_follows user_follows_follower_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_follows + ADD CONSTRAINT user_follows_follower_id_fkey FOREIGN KEY (follower_id) REFERENCES auth.users(id) ON DELETE CASCADE; + + +-- + +-- Name: user_follows user_follows_following_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_follows + ADD CONSTRAINT user_follows_following_id_fkey FOREIGN KEY (following_id) REFERENCES auth.users(id) ON DELETE CASCADE; + + +-- + +-- Name: user_magazines user_magazines_created_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_magazines + ADD CONSTRAINT user_magazines_created_by_fkey FOREIGN KEY (created_by) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: user_social_accounts user_social_accounts_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_social_accounts + ADD CONSTRAINT user_social_accounts_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: user_tryon_history user_tryon_history_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_tryon_history + ADD CONSTRAINT user_tryon_history_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + + +-- + +-- Name: artists artists_primary_instagram_account_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.artists + ADD CONSTRAINT artists_primary_instagram_account_id_fkey FOREIGN KEY (primary_instagram_account_id) REFERENCES warehouse.instagram_accounts(id) ON DELETE SET NULL; + + +-- + +-- Name: brands brands_primary_instagram_account_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.brands + ADD CONSTRAINT brands_primary_instagram_account_id_fkey FOREIGN KEY (primary_instagram_account_id) REFERENCES warehouse.instagram_accounts(id) ON DELETE SET NULL; + + +-- + +-- Name: group_members group_members_artist_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.group_members + ADD CONSTRAINT group_members_artist_id_fkey FOREIGN KEY (artist_id) REFERENCES warehouse.artists(id) ON DELETE CASCADE; + + +-- + +-- Name: group_members group_members_group_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.group_members + ADD CONSTRAINT group_members_group_id_fkey FOREIGN KEY (group_id) REFERENCES warehouse.groups(id) ON DELETE CASCADE; + + +-- + +-- Name: groups groups_primary_instagram_account_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.groups + ADD CONSTRAINT groups_primary_instagram_account_id_fkey FOREIGN KEY (primary_instagram_account_id) REFERENCES warehouse.instagram_accounts(id) ON DELETE SET NULL; + + +-- + +-- Name: instagram_accounts instagram_accounts_artist_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.instagram_accounts + ADD CONSTRAINT instagram_accounts_artist_id_fkey FOREIGN KEY (artist_id) REFERENCES warehouse.artists(id) ON DELETE SET NULL; + + +-- + +-- Name: instagram_accounts instagram_accounts_brand_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.instagram_accounts + ADD CONSTRAINT instagram_accounts_brand_id_fkey FOREIGN KEY (brand_id) REFERENCES warehouse.brands(id) ON DELETE SET NULL; + + +-- + +-- Name: raw_posts raw_posts_seed_post_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.raw_posts + ADD CONSTRAINT raw_posts_seed_post_id_fkey FOREIGN KEY (seed_post_id) REFERENCES warehouse.seed_posts(id) ON DELETE SET NULL; + + +-- + +-- Name: raw_posts raw_posts_source_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.raw_posts + ADD CONSTRAINT raw_posts_source_id_fkey FOREIGN KEY (source_id) REFERENCES warehouse.raw_post_sources(id) ON DELETE CASCADE; + + +-- + +-- Name: images warehouse_images_post_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.images + ADD CONSTRAINT warehouse_images_post_id_fkey FOREIGN KEY (post_id) REFERENCES warehouse.posts(id) ON DELETE CASCADE; + + +-- + +-- Name: instagram_accounts warehouse_instagram_accounts_group_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.instagram_accounts + ADD CONSTRAINT warehouse_instagram_accounts_group_id_fkey FOREIGN KEY (group_id) REFERENCES warehouse.groups(id) ON DELETE SET NULL; + + +-- + +-- Name: posts warehouse_posts_account_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.posts + ADD CONSTRAINT warehouse_posts_account_id_fkey FOREIGN KEY (account_id) REFERENCES warehouse.instagram_accounts(id) ON DELETE RESTRICT; + + +-- + +-- Name: seed_asset warehouse_seed_asset_seed_post_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.seed_asset + ADD CONSTRAINT warehouse_seed_asset_seed_post_id_fkey FOREIGN KEY (seed_post_id) REFERENCES warehouse.seed_posts(id) ON DELETE CASCADE; + + +-- + +-- Name: seed_posts warehouse_seed_posts_artist_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.seed_posts + ADD CONSTRAINT warehouse_seed_posts_artist_id_fkey FOREIGN KEY (artist_id) REFERENCES warehouse.artists(id) ON DELETE SET NULL; + + +-- + +-- Name: seed_posts warehouse_seed_posts_group_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.seed_posts + ADD CONSTRAINT warehouse_seed_posts_group_id_fkey FOREIGN KEY (group_id) REFERENCES warehouse.groups(id) ON DELETE SET NULL; + + +-- + +-- Name: seed_posts warehouse_seed_posts_source_image_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.seed_posts + ADD CONSTRAINT warehouse_seed_posts_source_image_id_fkey FOREIGN KEY (source_image_id) REFERENCES warehouse.images(id) ON DELETE SET NULL; + + +-- + +-- Name: seed_posts warehouse_seed_posts_source_post_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.seed_posts + ADD CONSTRAINT warehouse_seed_posts_source_post_id_fkey FOREIGN KEY (source_post_id) REFERENCES warehouse.posts(id) ON DELETE SET NULL; + + +-- + +-- Name: seed_spots warehouse_seed_spots_seed_post_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - +-- + +ALTER TABLE ONLY warehouse.seed_spots + ADD CONSTRAINT warehouse_seed_spots_seed_post_id_fkey FOREIGN KEY (seed_post_id) REFERENCES warehouse.seed_posts(id) ON DELETE CASCADE; + + +-- diff --git a/packages/api-server/migration/sql/007_triggers_ddl.sql b/packages/api-server/migration/sql/007_triggers_ddl.sql new file mode 100644 index 00000000..e2e5b839 --- /dev/null +++ b/packages/api-server/migration/sql/007_triggers_ddl.sql @@ -0,0 +1,216 @@ +SET check_function_bodies = false; + +-- Name: set_updated_at(); Type: FUNCTION; Schema: warehouse; Owner: - +-- + +CREATE FUNCTION warehouse.set_updated_at() RETURNS trigger + LANGUAGE plpgsql + AS $$ + BEGIN + NEW.updated_at = now(); + RETURN NEW; + END; + $$; + + +-- + +-- Name: touch_updated_at(); Type: FUNCTION; Schema: warehouse; Owner: - +-- + +CREATE FUNCTION warehouse.touch_updated_at() RETURNS trigger + LANGUAGE plpgsql + SET search_path TO '' + AS $$ +begin + new.updated_at = now(); + return new; +end; +$$; + + +-- + +-- Name: update_updated_at_column(); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION public.update_updated_at_column() RETURNS trigger + LANGUAGE plpgsql + SET search_path TO '' + AS $$ + BEGIN + NEW.updated_at = NOW(); + RETURN NEW; + END; + $$; + + +-- + +-- Name: artists trg_artists_touch_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - +-- + +CREATE TRIGGER trg_artists_touch_updated_at BEFORE UPDATE ON warehouse.artists FOR EACH ROW EXECUTE FUNCTION warehouse.touch_updated_at(); + + +-- + +-- Name: badges update_badges_updated_at; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER update_badges_updated_at BEFORE UPDATE ON public.badges FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); + + +-- + +-- Name: brands trg_brands_touch_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - +-- + +CREATE TRIGGER trg_brands_touch_updated_at BEFORE UPDATE ON warehouse.brands FOR EACH ROW EXECUTE FUNCTION warehouse.touch_updated_at(); + + +-- + +-- Name: categories update_categories_updated_at; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER update_categories_updated_at BEFORE UPDATE ON public.categories FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); + + +-- + +-- Name: comments update_comments_updated_at; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER update_comments_updated_at BEFORE UPDATE ON public.comments FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); + + +-- + +-- Name: group_members trg_group_members_touch_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - +-- + +CREATE TRIGGER trg_group_members_touch_updated_at BEFORE UPDATE ON warehouse.group_members FOR EACH ROW EXECUTE FUNCTION warehouse.touch_updated_at(); + + +-- + +-- Name: groups trg_groups_touch_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - +-- + +CREATE TRIGGER trg_groups_touch_updated_at BEFORE UPDATE ON warehouse.groups FOR EACH ROW EXECUTE FUNCTION warehouse.touch_updated_at(); + + +-- + +-- Name: instagram_accounts trg_instagram_accounts_touch_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - +-- + +CREATE TRIGGER trg_instagram_accounts_touch_updated_at BEFORE UPDATE ON warehouse.instagram_accounts FOR EACH ROW EXECUTE FUNCTION warehouse.touch_updated_at(); + + +-- + +-- Name: posts update_posts_updated_at; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER update_posts_updated_at BEFORE UPDATE ON public.posts FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); + + +-- + +-- Name: raw_post_sources raw_post_sources_set_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - +-- + +CREATE TRIGGER raw_post_sources_set_updated_at BEFORE UPDATE ON warehouse.raw_post_sources FOR EACH ROW EXECUTE FUNCTION warehouse.set_updated_at(); + + +-- + +-- Name: raw_posts raw_posts_set_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - +-- + +CREATE TRIGGER raw_posts_set_updated_at BEFORE UPDATE ON warehouse.raw_posts FOR EACH ROW EXECUTE FUNCTION warehouse.set_updated_at(); + + +-- + +-- Name: seed_asset trg_seed_asset_touch_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - +-- + +CREATE TRIGGER trg_seed_asset_touch_updated_at BEFORE UPDATE ON warehouse.seed_asset FOR EACH ROW EXECUTE FUNCTION warehouse.touch_updated_at(); + + +-- + +-- Name: seed_posts trg_seed_posts_touch_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - +-- + +CREATE TRIGGER trg_seed_posts_touch_updated_at BEFORE UPDATE ON warehouse.seed_posts FOR EACH ROW EXECUTE FUNCTION warehouse.touch_updated_at(); + + +-- + +-- Name: seed_spots trg_seed_spots_touch_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - +-- + +CREATE TRIGGER trg_seed_spots_touch_updated_at BEFORE UPDATE ON warehouse.seed_spots FOR EACH ROW EXECUTE FUNCTION warehouse.touch_updated_at(); + + +-- + +-- Name: solutions update_solutions_updated_at; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER update_solutions_updated_at BEFORE UPDATE ON public.solutions FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); + + +-- + +-- Name: spots update_spots_updated_at; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER update_spots_updated_at BEFORE UPDATE ON public.spots FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); + + +-- + +-- Name: subcategories update_subcategories_updated_at; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER update_subcategories_updated_at BEFORE UPDATE ON public.subcategories FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); + + +-- + +-- Name: synonyms update_synonyms_updated_at; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER update_synonyms_updated_at BEFORE UPDATE ON public.synonyms FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); + + +-- + +-- Name: user_magazines update_user_magazines_updated_at; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER update_user_magazines_updated_at BEFORE UPDATE ON public.user_magazines FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); + + +-- + +-- Name: user_social_accounts update_user_social_accounts_updated_at; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER update_user_social_accounts_updated_at BEFORE UPDATE ON public.user_social_accounts FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); + + +-- + +-- Name: users update_users_updated_at; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON public.users FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); + + +-- diff --git a/packages/api-server/migration/src/lib.rs b/packages/api-server/migration/src/lib.rs index c585e86a..d5d78b01 100644 --- a/packages/api-server/migration/src/lib.rs +++ b/packages/api-server/migration/src/lib.rs @@ -1,12 +1,30 @@ //! SeaORM 마이그레이션 — **supabase-dev 기준**으로 새로 쌓는 트랙. //! 이전 전체 이력은 [`../legacy/`](../legacy/)를 참고한다. +//! +//! Baseline 절차·파일 목록: 저장소 루트 [`../../../../plan.md`](../../../../plan.md). pub use sea_orm_migration::prelude::*; +mod m20260421_000001_enable_extensions; +mod m20260421_000002_warehouse_types; +mod m20260421_000003_public_tables; +mod m20260421_000004_warehouse_tables; +mod m20260421_000005_views; +mod m20260421_000006_indexes_and_constraints; +mod m20260421_000007_triggers_ddl; + pub struct Migrator; #[async_trait::async_trait] impl MigratorTrait for Migrator { fn migrations() -> Vec> { - vec![] + vec![ + Box::new(m20260421_000001_enable_extensions::Migration), + Box::new(m20260421_000002_warehouse_types::Migration), + Box::new(m20260421_000003_public_tables::Migration), + Box::new(m20260421_000004_warehouse_tables::Migration), + Box::new(m20260421_000005_views::Migration), + Box::new(m20260421_000006_indexes_and_constraints::Migration), + Box::new(m20260421_000007_triggers_ddl::Migration), + ] } } diff --git a/packages/api-server/migration/src/m20260421_000001_enable_extensions.rs b/packages/api-server/migration/src/m20260421_000001_enable_extensions.rs new file mode 100644 index 00000000..eef276ea --- /dev/null +++ b/packages/api-server/migration/src/m20260421_000001_enable_extensions.rs @@ -0,0 +1,20 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .get_connection() + .execute_unprepared(include_str!("../sql/001_enable_extensions.sql")) + .await?; + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + let _ = manager; + Ok(()) + } +} diff --git a/packages/api-server/migration/src/m20260421_000002_warehouse_types.rs b/packages/api-server/migration/src/m20260421_000002_warehouse_types.rs new file mode 100644 index 00000000..3486764f --- /dev/null +++ b/packages/api-server/migration/src/m20260421_000002_warehouse_types.rs @@ -0,0 +1,20 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .get_connection() + .execute_unprepared(include_str!("../sql/002_warehouse_types.sql")) + .await?; + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + let _ = manager; + Ok(()) + } +} diff --git a/packages/api-server/migration/src/m20260421_000003_public_tables.rs b/packages/api-server/migration/src/m20260421_000003_public_tables.rs new file mode 100644 index 00000000..ccfb92ef --- /dev/null +++ b/packages/api-server/migration/src/m20260421_000003_public_tables.rs @@ -0,0 +1,20 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .get_connection() + .execute_unprepared(include_str!("../sql/003_public_tables.sql")) + .await?; + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + let _ = manager; + Ok(()) + } +} diff --git a/packages/api-server/migration/src/m20260421_000004_warehouse_tables.rs b/packages/api-server/migration/src/m20260421_000004_warehouse_tables.rs new file mode 100644 index 00000000..bcfd1712 --- /dev/null +++ b/packages/api-server/migration/src/m20260421_000004_warehouse_tables.rs @@ -0,0 +1,20 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .get_connection() + .execute_unprepared(include_str!("../sql/004_warehouse_tables.sql")) + .await?; + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + let _ = manager; + Ok(()) + } +} diff --git a/packages/api-server/migration/src/m20260421_000005_views.rs b/packages/api-server/migration/src/m20260421_000005_views.rs new file mode 100644 index 00000000..97ddd765 --- /dev/null +++ b/packages/api-server/migration/src/m20260421_000005_views.rs @@ -0,0 +1,20 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .get_connection() + .execute_unprepared(include_str!("../sql/005_views.sql")) + .await?; + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + let _ = manager; + Ok(()) + } +} diff --git a/packages/api-server/migration/src/m20260421_000006_indexes_and_constraints.rs b/packages/api-server/migration/src/m20260421_000006_indexes_and_constraints.rs new file mode 100644 index 00000000..c4fcddc0 --- /dev/null +++ b/packages/api-server/migration/src/m20260421_000006_indexes_and_constraints.rs @@ -0,0 +1,20 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .get_connection() + .execute_unprepared(include_str!("../sql/006_indexes_and_constraints.sql")) + .await?; + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + let _ = manager; + Ok(()) + } +} diff --git a/packages/api-server/migration/src/m20260421_000007_triggers_ddl.rs b/packages/api-server/migration/src/m20260421_000007_triggers_ddl.rs new file mode 100644 index 00000000..f0904813 --- /dev/null +++ b/packages/api-server/migration/src/m20260421_000007_triggers_ddl.rs @@ -0,0 +1,20 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .get_connection() + .execute_unprepared(include_str!("../sql/007_triggers_ddl.sql")) + .await?; + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + let _ = manager; + Ok(()) + } +} diff --git a/supabase/migrations/20260421100000_baseline_functions.sql b/supabase/migrations/20260421100000_baseline_functions.sql new file mode 100644 index 00000000..55ef07b6 --- /dev/null +++ b/supabase/migrations/20260421100000_baseline_functions.sql @@ -0,0 +1,251 @@ +SET check_function_bodies = false; +SET client_min_messages = warning; + +-- Name: admin_daily_metrics(timestamp with time zone, timestamp with time zone); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION public.admin_daily_metrics(p_from_ts timestamp with time zone, p_to_ts timestamp with time zone) RETURNS TABLE(day date, clicks integer, searches integer, dau integer) + LANGUAGE plpgsql SECURITY DEFINER + SET search_path TO 'public', 'pg_temp' + AS $$ +BEGIN + IF auth.uid() IS NULL OR NOT public.is_admin(auth.uid()) THEN + RAISE EXCEPTION 'forbidden' USING ERRCODE = '42501'; + END IF; + + IF p_from_ts IS NULL OR p_to_ts IS NULL + OR NOT isfinite(p_from_ts) OR NOT isfinite(p_to_ts) + OR p_to_ts <= p_from_ts THEN + RAISE EXCEPTION 'invalid_range' USING ERRCODE = 'P0001'; + END IF; + + IF (p_to_ts - p_from_ts) > INTERVAL '366 days' THEN + RAISE EXCEPTION 'range_too_large' USING ERRCODE = 'P0001'; + END IF; + + RETURN QUERY + WITH + c AS ( + SELECT date_trunc('day', created_at)::date AS d, COUNT(*)::int AS n + FROM public.click_logs + WHERE created_at >= p_from_ts AND created_at < p_to_ts + GROUP BY 1 + ), + s AS ( + SELECT date_trunc('day', created_at)::date AS d, COUNT(*)::int AS n + FROM public.search_logs + WHERE created_at >= p_from_ts AND created_at < p_to_ts + GROUP BY 1 + ), + e AS ( + SELECT date_trunc('day', created_at)::date AS d, + COUNT(DISTINCT user_id)::int AS n + FROM public.user_events + WHERE created_at >= p_from_ts AND created_at < p_to_ts + GROUP BY 1 + ), + days AS ( + SELECT generate_series( + date_trunc('day', p_from_ts)::date, + date_trunc('day', p_to_ts - INTERVAL '1 microsecond')::date, + INTERVAL '1 day' + )::date AS d + ) + SELECT + days.d, + COALESCE(c.n, 0), + COALESCE(s.n, 0), + COALESCE(e.n, 0) + FROM days + LEFT JOIN c USING (d) + LEFT JOIN s USING (d) + LEFT JOIN e USING (d) + ORDER BY days.d; +END; +$$; + + +-- +-- Name: admin_distinct_user_count(timestamp with time zone, timestamp with time zone); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION public.admin_distinct_user_count(p_from_ts timestamp with time zone, p_to_ts timestamp with time zone) RETURNS integer + LANGUAGE plpgsql SECURITY DEFINER + SET search_path TO 'public', 'pg_temp' + AS $$ +DECLARE + v_count INTEGER; +BEGIN + IF auth.uid() IS NULL OR NOT public.is_admin(auth.uid()) THEN + RAISE EXCEPTION 'forbidden' USING ERRCODE = '42501'; + END IF; + + IF p_from_ts IS NULL OR p_to_ts IS NULL + OR NOT isfinite(p_from_ts) OR NOT isfinite(p_to_ts) + OR p_to_ts <= p_from_ts THEN + RAISE EXCEPTION 'invalid_range' USING ERRCODE = 'P0001'; + END IF; + + IF (p_to_ts - p_from_ts) > INTERVAL '366 days' THEN + RAISE EXCEPTION 'range_too_large' USING ERRCODE = 'P0001'; + END IF; + + SELECT COUNT(DISTINCT user_id)::INTEGER + INTO v_count + FROM public.user_events + WHERE created_at >= p_from_ts + AND created_at < p_to_ts; + + RETURN COALESCE(v_count, 0); +END; +$$; + + +-- +-- Name: handle_new_user(); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION public.handle_new_user() RETURNS trigger + LANGUAGE plpgsql SECURITY DEFINER + SET search_path TO '' + AS $$ +BEGIN + INSERT INTO public.users (id, email, username, display_name) + VALUES ( + NEW.id, + NEW.email, + COALESCE(NEW.raw_user_meta_data->>'username', SPLIT_PART(NEW.email, '@', 1)), + COALESCE(NEW.raw_user_meta_data->>'display_name', SPLIT_PART(NEW.email, '@', 1)) + ); + RETURN NEW; +END; +$$; + + +-- +-- Name: FUNCTION handle_new_user(); Type: COMMENT; Schema: public; Owner: - +-- + +COMMENT ON FUNCTION public.handle_new_user() IS 'Supabase Auth에서 새 사용자 생성 시 public.users 테이블에 자동으로 레코드 생성'; + + +-- +-- Name: is_admin(uuid); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION public.is_admin(user_id uuid) RETURNS boolean + LANGUAGE sql STABLE SECURITY DEFINER + SET search_path TO 'public', 'pg_temp' + AS $$ + SELECT COALESCE( + (SELECT is_admin FROM public.users WHERE id = user_id), + false + ); +$$; + + +-- +-- Name: search_similar(extensions.vector, integer, character varying); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION public.search_similar(query_embedding extensions.vector, match_count integer DEFAULT 10, filter_type character varying DEFAULT NULL::character varying) RETURNS TABLE(entity_type character varying, entity_id uuid, content_text text, similarity double precision) + LANGUAGE plpgsql + SET search_path TO '' + AS $$ +BEGIN + RETURN QUERY + SELECT e.entity_type, e.entity_id, e.content_text, + 1 - (e.embedding <=> query_embedding) AS similarity + FROM public.embeddings e + WHERE (filter_type IS NULL OR e.entity_type = filter_type) + ORDER BY e.embedding <=> query_embedding + LIMIT match_count; +END; +$$; + + +SET default_tablespace = ''; + +SET default_table_access_method = heap; + +-- +-- Name: update_magazine_status(uuid, character varying, uuid, text); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION public.update_magazine_status(p_magazine_id uuid, p_new_status character varying, p_admin_user_id uuid, p_rejection_reason text DEFAULT NULL::text) RETURNS SETOF public.post_magazines + LANGUAGE plpgsql SECURITY DEFINER + SET search_path TO 'public', 'warehouse', 'pg_temp' + AS $$ +DECLARE + v_before public.post_magazines; + v_after public.post_magazines; + v_action TEXT; + v_caller UUID := auth.uid(); +BEGIN + IF v_caller IS NOT NULL AND v_caller <> p_admin_user_id THEN + RAISE EXCEPTION 'caller_mismatch' USING ERRCODE = 'P0003'; + END IF; + + IF NOT public.is_admin(p_admin_user_id) THEN + RAISE EXCEPTION 'caller_not_admin' USING ERRCODE = 'P0003'; + END IF; + + IF p_rejection_reason IS NOT NULL AND length(p_rejection_reason) > 2000 THEN + RAISE EXCEPTION 'rejection_reason_too_long' USING ERRCODE = 'P0001'; + END IF; + + SELECT * INTO v_before FROM public.post_magazines + WHERE id = p_magazine_id FOR UPDATE; + + IF NOT FOUND THEN + RAISE EXCEPTION 'magazine_not_found' USING ERRCODE = 'P0002'; + END IF; + + IF NOT ( + (v_before.status = 'draft' AND p_new_status = 'pending') OR + (v_before.status = 'pending' AND p_new_status = 'published') OR + (v_before.status = 'pending' AND p_new_status = 'rejected') OR + (v_before.status = 'rejected' AND p_new_status = 'pending') OR + (v_before.status = 'published' AND p_new_status = 'draft') + ) THEN + RAISE EXCEPTION 'invalid_transition: % -> %', v_before.status, p_new_status + USING ERRCODE = 'P0001'; + END IF; + + IF p_new_status = 'rejected' AND (p_rejection_reason IS NULL OR length(trim(p_rejection_reason)) = 0) THEN + RAISE EXCEPTION 'rejection_reason_required' USING ERRCODE = 'P0001'; + END IF; + + UPDATE public.post_magazines + SET status = p_new_status, + approved_by = CASE WHEN p_new_status = 'published' THEN p_admin_user_id ELSE approved_by END, + published_at = CASE WHEN p_new_status = 'published' THEN now() ELSE published_at END, + rejection_reason = CASE WHEN p_new_status = 'rejected' THEN p_rejection_reason ELSE NULL END, + updated_at = now() + WHERE id = p_magazine_id + RETURNING * INTO v_after; + + v_action := CASE p_new_status + WHEN 'published' THEN 'magazine_approve' + WHEN 'rejected' THEN 'magazine_reject' + WHEN 'pending' THEN 'magazine_submit' + WHEN 'draft' THEN 'magazine_unpublish' + ELSE 'magazine_status_change' + END; + + INSERT INTO warehouse.admin_audit_log ( + admin_user_id, action, target_table, target_id, + before_state, after_state, metadata + ) VALUES ( + p_admin_user_id, v_action, 'post_magazines', p_magazine_id, + row_to_json(v_before)::jsonb, + row_to_json(v_after)::jsonb, + jsonb_build_object('rejection_reason', p_rejection_reason) + ); + + RETURN NEXT v_after; +END; +$$; + + +-- diff --git a/supabase/migrations/20260421110000_baseline_triggers_auth.sql b/supabase/migrations/20260421110000_baseline_triggers_auth.sql new file mode 100644 index 00000000..8c125767 --- /dev/null +++ b/supabase/migrations/20260421110000_baseline_triggers_auth.sql @@ -0,0 +1,6 @@ +-- Auth trigger (not present in schema-only dump; pairs with public.handle_new_user) +DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users; +CREATE TRIGGER on_auth_user_created + AFTER INSERT ON auth.users + FOR EACH ROW + EXECUTE FUNCTION public.handle_new_user(); diff --git a/supabase/migrations/20260421120000_baseline_rls.sql b/supabase/migrations/20260421120000_baseline_rls.sql new file mode 100644 index 00000000..94f59080 --- /dev/null +++ b/supabase/migrations/20260421120000_baseline_rls.sql @@ -0,0 +1,831 @@ +-- Name: badges Allow public read; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read" ON public.badges FOR SELECT USING (true); + + +-- +-- Name: categories Allow public read; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read" ON public.categories FOR SELECT USING (true); + + +-- +-- Name: comments Allow public read; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read" ON public.comments FOR SELECT USING (true); + + +-- +-- Name: curation_posts Allow public read; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read" ON public.curation_posts FOR SELECT USING (true); + + +-- +-- Name: curations Allow public read; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read" ON public.curations FOR SELECT USING (true); + + +-- +-- Name: embeddings Allow public read; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read" ON public.embeddings FOR SELECT USING (true); + + +-- +-- Name: magazine_posts Allow public read; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read" ON public.magazine_posts FOR SELECT USING (true); + + +-- +-- Name: magazines Allow public read; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read" ON public.magazines FOR SELECT USING (true); + + +-- +-- Name: post_magazines Allow public read; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read" ON public.post_magazines FOR SELECT USING (true); + + +-- +-- Name: posts Allow public read; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read" ON public.posts FOR SELECT USING (true); + + +-- +-- Name: solutions Allow public read; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read" ON public.solutions FOR SELECT USING (true); + + +-- +-- Name: spots Allow public read; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read" ON public.spots FOR SELECT USING (true); + + +-- +-- Name: subcategories Allow public read; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read" ON public.subcategories FOR SELECT USING (true); + + +-- +-- Name: synonyms Allow public read; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read" ON public.synonyms FOR SELECT USING (true); + + +-- +-- Name: user_badges Allow public read; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read" ON public.user_badges FOR SELECT USING (true); + + +-- +-- Name: votes Allow public read; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read" ON public.votes FOR SELECT USING (true); + + +-- +-- Name: decoded_picks Allow public read decoded_picks; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Allow public read decoded_picks" ON public.decoded_picks FOR SELECT USING (true); + + +-- +-- Name: comments Auth insert comments; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Auth insert comments" ON public.comments FOR INSERT WITH CHECK ((auth.uid() = user_id)); + + +-- +-- Name: user_follows Auth insert follows; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Auth insert follows" ON public.user_follows FOR INSERT WITH CHECK ((auth.uid() = follower_id)); + + +-- +-- Name: votes Auth insert votes; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Auth insert votes" ON public.votes FOR INSERT WITH CHECK ((auth.uid() = user_id)); + + +-- +-- Name: post_likes Owner delete; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner delete" ON public.post_likes FOR DELETE USING ((auth.uid() = user_id)); + + +-- +-- Name: saved_posts Owner delete; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner delete" ON public.saved_posts FOR DELETE USING ((auth.uid() = user_id)); + + +-- +-- Name: user_collections Owner delete; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner delete" ON public.user_collections FOR DELETE USING ((auth.uid() = user_id)); + + +-- +-- Name: user_magazines Owner delete; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner delete" ON public.user_magazines FOR DELETE USING ((auth.uid() = created_by)); + + +-- +-- Name: user_social_accounts Owner delete; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner delete" ON public.user_social_accounts FOR DELETE USING ((auth.uid() = user_id)); + + +-- +-- Name: comments Owner delete comments; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner delete comments" ON public.comments FOR DELETE USING ((auth.uid() = user_id)); + + +-- +-- Name: user_follows Owner delete follows; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner delete follows" ON public.user_follows FOR DELETE USING ((auth.uid() = follower_id)); + + +-- +-- Name: posts Owner delete posts; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner delete posts" ON public.posts FOR DELETE USING ((auth.uid() = user_id)); + + +-- +-- Name: votes Owner delete votes; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner delete votes" ON public.votes FOR DELETE USING ((auth.uid() = user_id)); + + +-- +-- Name: click_logs Owner insert; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner insert" ON public.click_logs FOR INSERT WITH CHECK ((auth.uid() = user_id)); + + +-- +-- Name: credit_transactions Owner insert; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner insert" ON public.credit_transactions FOR INSERT WITH CHECK ((auth.uid() = user_id)); + + +-- +-- Name: post_likes Owner insert; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner insert" ON public.post_likes FOR INSERT WITH CHECK ((auth.uid() = user_id)); + + +-- +-- Name: saved_posts Owner insert; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner insert" ON public.saved_posts FOR INSERT WITH CHECK ((auth.uid() = user_id)); + + +-- +-- Name: user_collections Owner insert; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner insert" ON public.user_collections FOR INSERT WITH CHECK ((auth.uid() = user_id)); + + +-- +-- Name: user_magazines Owner insert; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner insert" ON public.user_magazines FOR INSERT WITH CHECK ((auth.uid() = created_by)); + + +-- +-- Name: user_social_accounts Owner insert; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner insert" ON public.user_social_accounts FOR INSERT WITH CHECK ((auth.uid() = user_id)); + + +-- +-- Name: view_logs Owner insert; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner insert" ON public.view_logs FOR INSERT WITH CHECK ((auth.uid() = user_id)); + + +-- +-- Name: posts Owner insert posts; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner insert posts" ON public.posts FOR INSERT WITH CHECK ((auth.uid() = user_id)); + + +-- +-- Name: click_logs Owner select; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner select" ON public.click_logs FOR SELECT USING ((auth.uid() = user_id)); + + +-- +-- Name: credit_transactions Owner select; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner select" ON public.credit_transactions FOR SELECT USING ((auth.uid() = user_id)); + + +-- +-- Name: post_likes Owner select; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner select" ON public.post_likes FOR SELECT USING ((auth.uid() = user_id)); + + +-- +-- Name: saved_posts Owner select; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner select" ON public.saved_posts FOR SELECT USING ((auth.uid() = user_id)); + + +-- +-- Name: user_collections Owner select; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner select" ON public.user_collections FOR SELECT USING ((auth.uid() = user_id)); + + +-- +-- Name: user_magazines Owner select; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner select" ON public.user_magazines FOR SELECT USING ((auth.uid() = created_by)); + + +-- +-- Name: user_social_accounts Owner select; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner select" ON public.user_social_accounts FOR SELECT USING ((auth.uid() = user_id)); + + +-- +-- Name: view_logs Owner select; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner select" ON public.view_logs FOR SELECT USING ((auth.uid() = user_id)); + + +-- +-- Name: user_social_accounts Owner update; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner update" ON public.user_social_accounts FOR UPDATE USING ((auth.uid() = user_id)); + + +-- +-- Name: posts Owner update posts; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner update posts" ON public.posts FOR UPDATE USING ((auth.uid() = user_id)); + + +-- +-- Name: users Owner update profile; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Owner update profile" ON public.users FOR UPDATE USING ((auth.uid() = id)); + + +-- +-- Name: users Public read profiles; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Public read profiles" ON public.users FOR SELECT USING (true); + + +-- +-- Name: user_tryon_history Users can insert own tryon history; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Users can insert own tryon history" ON public.user_tryon_history FOR INSERT WITH CHECK ((auth.uid() = user_id)); + + +-- +-- Name: user_tryon_history Users can view own tryon history; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Users can view own tryon history" ON public.user_tryon_history FOR SELECT USING ((auth.uid() = user_id)); + + +-- +-- Name: user_events Users insert own events; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Users insert own events" ON public.user_events FOR INSERT WITH CHECK ((auth.uid() = user_id)); + + +-- +-- Name: user_events Users read own events; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY "Users read own events" ON public.user_events FOR SELECT USING ((auth.uid() = user_id)); + + +-- +-- Name: post_magazines admin_can_update_magazines; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY admin_can_update_magazines ON public.post_magazines FOR UPDATE USING (public.is_admin(auth.uid())) WITH CHECK (public.is_admin(auth.uid())); + + +-- +-- Name: agent_sessions; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.agent_sessions ENABLE ROW LEVEL SECURITY; + +-- +-- Name: badges; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.badges ENABLE ROW LEVEL SECURITY; + +-- +-- Name: categories; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.categories ENABLE ROW LEVEL SECURITY; + +-- +-- Name: checkpoint_blobs; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.checkpoint_blobs ENABLE ROW LEVEL SECURITY; + +-- +-- Name: checkpoint_migrations; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.checkpoint_migrations ENABLE ROW LEVEL SECURITY; + +-- +-- Name: checkpoint_writes; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.checkpoint_writes ENABLE ROW LEVEL SECURITY; + +-- +-- Name: checkpoints; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.checkpoints ENABLE ROW LEVEL SECURITY; + +-- +-- Name: click_logs; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.click_logs ENABLE ROW LEVEL SECURITY; + +-- +-- Name: comments; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.comments ENABLE ROW LEVEL SECURITY; + +-- +-- Name: content_reports; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.content_reports ENABLE ROW LEVEL SECURITY; + +-- +-- Name: content_reports content_reports_insert_own; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY content_reports_insert_own ON public.content_reports FOR INSERT WITH CHECK ((auth.uid() = reporter_id)); + + +-- +-- Name: content_reports content_reports_select_own; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY content_reports_select_own ON public.content_reports FOR SELECT USING ((auth.uid() = reporter_id)); + + +-- +-- Name: credit_transactions; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.credit_transactions ENABLE ROW LEVEL SECURITY; + +-- +-- Name: curation_posts; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.curation_posts ENABLE ROW LEVEL SECURITY; + +-- +-- Name: curations; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.curations ENABLE ROW LEVEL SECURITY; + +-- +-- Name: decoded_picks; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.decoded_picks ENABLE ROW LEVEL SECURITY; + +-- +-- Name: earnings; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.earnings ENABLE ROW LEVEL SECURITY; + +-- +-- Name: embeddings; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.embeddings ENABLE ROW LEVEL SECURITY; + +-- +-- Name: failed_batch_items; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.failed_batch_items ENABLE ROW LEVEL SECURITY; + +-- +-- Name: magazine_posts; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.magazine_posts ENABLE ROW LEVEL SECURITY; + +-- +-- Name: magazines; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.magazines ENABLE ROW LEVEL SECURITY; + +-- +-- Name: point_logs; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.point_logs ENABLE ROW LEVEL SECURITY; + +-- +-- Name: post_likes; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.post_likes ENABLE ROW LEVEL SECURITY; + +-- +-- Name: post_magazine_news_references; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.post_magazine_news_references ENABLE ROW LEVEL SECURITY; + +-- +-- Name: post_magazines; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.post_magazines ENABLE ROW LEVEL SECURITY; + +-- +-- Name: posts; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.posts ENABLE ROW LEVEL SECURITY; + +-- +-- Name: processed_batches; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.processed_batches ENABLE ROW LEVEL SECURITY; + +-- +-- Name: saved_posts; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.saved_posts ENABLE ROW LEVEL SECURITY; + +-- +-- Name: search_logs; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.search_logs ENABLE ROW LEVEL SECURITY; + +-- +-- Name: settlements; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.settlements ENABLE ROW LEVEL SECURITY; + +-- +-- Name: solutions; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.solutions ENABLE ROW LEVEL SECURITY; + +-- +-- Name: spots; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.spots ENABLE ROW LEVEL SECURITY; + +-- +-- Name: subcategories; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.subcategories ENABLE ROW LEVEL SECURITY; + +-- +-- Name: synonyms; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.synonyms ENABLE ROW LEVEL SECURITY; + +-- +-- Name: try_spot_tags; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.try_spot_tags ENABLE ROW LEVEL SECURITY; + +-- +-- Name: user_badges; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.user_badges ENABLE ROW LEVEL SECURITY; + +-- +-- Name: user_collections; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.user_collections ENABLE ROW LEVEL SECURITY; + +-- +-- Name: user_events; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.user_events ENABLE ROW LEVEL SECURITY; + +-- +-- Name: user_follows; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.user_follows ENABLE ROW LEVEL SECURITY; + +-- +-- Name: user_follows user_follows_select_public; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY user_follows_select_public ON public.user_follows FOR SELECT USING (true); + + +-- +-- Name: user_magazines; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.user_magazines ENABLE ROW LEVEL SECURITY; + +-- +-- Name: user_social_accounts; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.user_social_accounts ENABLE ROW LEVEL SECURITY; + +-- +-- Name: user_tryon_history; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.user_tryon_history ENABLE ROW LEVEL SECURITY; + +-- +-- Name: user_tryon_history user_tryon_history_select_own; Type: POLICY; Schema: public; Owner: - +-- + +CREATE POLICY user_tryon_history_select_own ON public.user_tryon_history FOR SELECT USING ((auth.uid() = user_id)); + + +-- +-- Name: users; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.users ENABLE ROW LEVEL SECURITY; + +-- +-- Name: view_logs; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.view_logs ENABLE ROW LEVEL SECURITY; + +-- +-- Name: votes; Type: ROW SECURITY; Schema: public; Owner: - +-- + +ALTER TABLE public.votes ENABLE ROW LEVEL SECURITY; + +-- +-- Name: artists Allow public read; Type: POLICY; Schema: warehouse; Owner: - +-- + +CREATE POLICY "Allow public read" ON warehouse.artists FOR SELECT USING (true); + + +-- +-- Name: brands Allow public read; Type: POLICY; Schema: warehouse; Owner: - +-- + +CREATE POLICY "Allow public read" ON warehouse.brands FOR SELECT USING (true); + + +-- +-- Name: group_members Allow public read; Type: POLICY; Schema: warehouse; Owner: - +-- + +CREATE POLICY "Allow public read" ON warehouse.group_members FOR SELECT USING (true); + + +-- +-- Name: groups Allow public read; Type: POLICY; Schema: warehouse; Owner: - +-- + +CREATE POLICY "Allow public read" ON warehouse.groups FOR SELECT USING (true); + + +-- +-- Name: images Allow public read; Type: POLICY; Schema: warehouse; Owner: - +-- + +CREATE POLICY "Allow public read" ON warehouse.images FOR SELECT USING (true); + + +-- +-- Name: instagram_accounts Allow public read; Type: POLICY; Schema: warehouse; Owner: - +-- + +CREATE POLICY "Allow public read" ON warehouse.instagram_accounts FOR SELECT USING (true); + + +-- +-- Name: posts Allow public read; Type: POLICY; Schema: warehouse; Owner: - +-- + +CREATE POLICY "Allow public read" ON warehouse.posts FOR SELECT USING (true); + + +-- +-- Name: seed_asset Allow public read; Type: POLICY; Schema: warehouse; Owner: - +-- + +CREATE POLICY "Allow public read" ON warehouse.seed_asset FOR SELECT USING (true); + + +-- +-- Name: seed_posts Allow public read; Type: POLICY; Schema: warehouse; Owner: - +-- + +CREATE POLICY "Allow public read" ON warehouse.seed_posts FOR SELECT USING (true); + + +-- +-- Name: seed_spots Allow public read; Type: POLICY; Schema: warehouse; Owner: - +-- + +CREATE POLICY "Allow public read" ON warehouse.seed_spots FOR SELECT USING (true); + + +-- +-- Name: artists; Type: ROW SECURITY; Schema: warehouse; Owner: - +-- + +ALTER TABLE warehouse.artists ENABLE ROW LEVEL SECURITY; + +-- +-- Name: brands; Type: ROW SECURITY; Schema: warehouse; Owner: - +-- + +ALTER TABLE warehouse.brands ENABLE ROW LEVEL SECURITY; + +-- +-- Name: group_members; Type: ROW SECURITY; Schema: warehouse; Owner: - +-- + +ALTER TABLE warehouse.group_members ENABLE ROW LEVEL SECURITY; + +-- +-- Name: groups; Type: ROW SECURITY; Schema: warehouse; Owner: - +-- + +ALTER TABLE warehouse.groups ENABLE ROW LEVEL SECURITY; + +-- +-- Name: images; Type: ROW SECURITY; Schema: warehouse; Owner: - +-- + +ALTER TABLE warehouse.images ENABLE ROW LEVEL SECURITY; + +-- +-- Name: instagram_accounts; Type: ROW SECURITY; Schema: warehouse; Owner: - +-- + +ALTER TABLE warehouse.instagram_accounts ENABLE ROW LEVEL SECURITY; + +-- +-- Name: posts; Type: ROW SECURITY; Schema: warehouse; Owner: - +-- + +ALTER TABLE warehouse.posts ENABLE ROW LEVEL SECURITY; + +-- +-- Name: raw_post_sources; Type: ROW SECURITY; Schema: warehouse; Owner: - +-- + +ALTER TABLE warehouse.raw_post_sources ENABLE ROW LEVEL SECURITY; + +-- +-- Name: raw_post_sources raw_post_sources_select_public; Type: POLICY; Schema: warehouse; Owner: - +-- + +CREATE POLICY raw_post_sources_select_public ON warehouse.raw_post_sources FOR SELECT USING (true); + + +-- +-- Name: raw_posts; Type: ROW SECURITY; Schema: warehouse; Owner: - +-- + +ALTER TABLE warehouse.raw_posts ENABLE ROW LEVEL SECURITY; + +-- +-- Name: raw_posts raw_posts_select_public; Type: POLICY; Schema: warehouse; Owner: - +-- + +CREATE POLICY raw_posts_select_public ON warehouse.raw_posts FOR SELECT USING (true); + + +-- +-- Name: seed_asset; Type: ROW SECURITY; Schema: warehouse; Owner: - +-- + +ALTER TABLE warehouse.seed_asset ENABLE ROW LEVEL SECURITY; + +-- +-- Name: seed_posts; Type: ROW SECURITY; Schema: warehouse; Owner: - +-- + +ALTER TABLE warehouse.seed_posts ENABLE ROW LEVEL SECURITY; + +-- +-- Name: seed_spots; Type: ROW SECURITY; Schema: warehouse; Owner: - +-- + +ALTER TABLE warehouse.seed_spots ENABLE ROW LEVEL SECURITY; + +-- +-- PostgreSQL database dump complete +-- + + diff --git a/supabase/migrations/README.md b/supabase/migrations/README.md index 0c3979d5..e050ea09 100644 --- a/supabase/migrations/README.md +++ b/supabase/migrations/README.md @@ -2,6 +2,7 @@ **supabase-dev** 기준으로 새로 추가하는 SQL만 둔다. +- Baseline(함수·auth 트리거·RLS): `20260421100000_baseline_functions.sql`, `20260421110000_baseline_triggers_auth.sql`, `20260421120000_baseline_rls.sql` — 생성 절차는 저장소 루트 [`plan.md`](../../plan.md), [`packages/api-server/migration/scripts/split_dev_schema.py`](../../packages/api-server/migration/scripts/split_dev_schema.py). - 과거 스냅샷·incremental 전체: [`../legacy/`](../legacy/) - SeaORM 활성 트랙: [`../../packages/api-server/migration/`](../../packages/api-server/migration/) - 에이전트 역할 구분: [`../../packages/api-server/AGENT.md`](../../packages/api-server/AGENT.md) §2.4 From 6351e7c31721e7b16047e5453adbdda6e7457466 Mon Sep 17 00:00:00 2001 From: CIOI Date: Wed, 22 Apr 2026 03:18:05 +0900 Subject: [PATCH 4/4] feat(migration): idempotent baseline SQL + post_magazines failed status - Wrap warehouse ENUMs and constraint/index DDL for safe re-run on brownfield DBs\n- post_magazines CHECK includes failed; legacy migration aligned\n- CREATE TABLE IF NOT EXISTS, OR REPLACE views, index IF NOT EXISTS, DO blocks for constraints Made-with: Cursor --- ...60502_000005_magazine_approval_and_rpcs.rs | 2 +- .../migration/sql/002_warehouse_types.sql | 45 +- .../migration/sql/003_public_tables.sql | 88 +- .../migration/sql/004_warehouse_tables.sql | 26 +- .../api-server/migration/sql/005_views.sql | 2 +- .../sql/006_indexes_and_constraints.sql | 1852 +++++++++++++---- .../migration/sql/007_triggers_ddl.sql | 48 +- 7 files changed, 1556 insertions(+), 507 deletions(-) diff --git a/packages/api-server/legacy/src/m20260502_000005_magazine_approval_and_rpcs.rs b/packages/api-server/legacy/src/m20260502_000005_magazine_approval_and_rpcs.rs index 0244f684..ac6a3c04 100644 --- a/packages/api-server/legacy/src/m20260502_000005_magazine_approval_and_rpcs.rs +++ b/packages/api-server/legacy/src/m20260502_000005_magazine_approval_and_rpcs.rs @@ -68,7 +68,7 @@ impl MigrationTrait for Migration { DROP CONSTRAINT IF EXISTS post_magazines_status_check; ALTER TABLE public.post_magazines ADD CONSTRAINT post_magazines_status_check - CHECK (status IN ('draft', 'pending', 'published', 'rejected')); + CHECK (status IN ('draft', 'pending', 'published', 'rejected', 'failed')); CREATE INDEX IF NOT EXISTS post_magazines_status_idx ON public.post_magazines(status) diff --git a/packages/api-server/migration/sql/002_warehouse_types.sql b/packages/api-server/migration/sql/002_warehouse_types.sql index c31ffdcc..251f2c19 100644 --- a/packages/api-server/migration/sql/002_warehouse_types.sql +++ b/packages/api-server/migration/sql/002_warehouse_types.sql @@ -9,19 +9,26 @@ CREATE SCHEMA IF NOT EXISTS warehouse; -- -- Name: account_type; Type: TYPE; Schema: warehouse; Owner: - +-- Idempotent: brownfield DB에 타입이 이미 있으면 건너뜀 -- -CREATE TYPE warehouse.account_type AS ENUM ( - 'artist', - 'group', - 'brand', - 'source', - 'influencer', - 'place', - 'other', - 'company', - 'designer' -); +DO $t$ +BEGIN + CREATE TYPE warehouse.account_type AS ENUM ( + 'artist', + 'group', + 'brand', + 'source', + 'influencer', + 'place', + 'other', + 'company', + 'designer' + ); +EXCEPTION + WHEN duplicate_object THEN NULL; +END +$t$; -- @@ -29,11 +36,17 @@ CREATE TYPE warehouse.account_type AS ENUM ( -- Name: entity_ig_role; Type: TYPE; Schema: warehouse; Owner: - -- -CREATE TYPE warehouse.entity_ig_role AS ENUM ( - 'primary', - 'regional', - 'secondary' -); +DO $t$ +BEGIN + CREATE TYPE warehouse.entity_ig_role AS ENUM ( + 'primary', + 'regional', + 'secondary' + ); +EXCEPTION + WHEN duplicate_object THEN NULL; +END +$t$; -- diff --git a/packages/api-server/migration/sql/003_public_tables.sql b/packages/api-server/migration/sql/003_public_tables.sql index 554ef8ca..90567198 100644 --- a/packages/api-server/migration/sql/003_public_tables.sql +++ b/packages/api-server/migration/sql/003_public_tables.sql @@ -10,7 +10,7 @@ SET default_table_access_method = heap; -- Name: post_magazines; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.post_magazines ( +CREATE TABLE IF NOT EXISTS public.post_magazines ( id uuid DEFAULT gen_random_uuid() NOT NULL, title character varying DEFAULT 'Untitled'::character varying NOT NULL, subtitle text, @@ -24,7 +24,7 @@ CREATE TABLE public.post_magazines ( published_at timestamp with time zone, approved_by uuid, rejection_reason text, - CONSTRAINT post_magazines_status_check CHECK (((status)::text = ANY ((ARRAY['draft'::character varying, 'pending'::character varying, 'published'::character varying, 'rejected'::character varying])::text[]))) + CONSTRAINT post_magazines_status_check CHECK (((status)::text = ANY ((ARRAY['draft'::character varying, 'pending'::character varying, 'published'::character varying, 'rejected'::character varying, 'failed'::character varying])::text[]))) ); @@ -33,7 +33,7 @@ CREATE TABLE public.post_magazines ( -- Name: agent_sessions; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.agent_sessions ( +CREATE TABLE IF NOT EXISTS public.agent_sessions ( id uuid DEFAULT gen_random_uuid() NOT NULL, thread_id character varying(100) NOT NULL, magazine_id uuid, @@ -53,7 +53,7 @@ CREATE TABLE public.agent_sessions ( -- Name: badges; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.badges ( +CREATE TABLE IF NOT EXISTS public.badges ( id uuid NOT NULL, type character varying(50) NOT NULL, name character varying(255) NOT NULL, @@ -71,7 +71,7 @@ CREATE TABLE public.badges ( -- Name: categories; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.categories ( +CREATE TABLE IF NOT EXISTS public.categories ( id uuid NOT NULL, code character varying(50) NOT NULL, name json NOT NULL, @@ -90,7 +90,7 @@ CREATE TABLE public.categories ( -- Name: checkpoint_blobs; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.checkpoint_blobs ( +CREATE TABLE IF NOT EXISTS public.checkpoint_blobs ( thread_id text NOT NULL, checkpoint_ns text DEFAULT ''::text NOT NULL, channel text NOT NULL, @@ -105,7 +105,7 @@ CREATE TABLE public.checkpoint_blobs ( -- Name: checkpoint_migrations; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.checkpoint_migrations ( +CREATE TABLE IF NOT EXISTS public.checkpoint_migrations ( v integer NOT NULL ); @@ -115,7 +115,7 @@ CREATE TABLE public.checkpoint_migrations ( -- Name: checkpoint_writes; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.checkpoint_writes ( +CREATE TABLE IF NOT EXISTS public.checkpoint_writes ( thread_id text NOT NULL, checkpoint_ns text DEFAULT ''::text NOT NULL, checkpoint_id text NOT NULL, @@ -133,7 +133,7 @@ CREATE TABLE public.checkpoint_writes ( -- Name: checkpoints; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.checkpoints ( +CREATE TABLE IF NOT EXISTS public.checkpoints ( thread_id text NOT NULL, checkpoint_ns text DEFAULT ''::text NOT NULL, checkpoint_id text NOT NULL, @@ -149,7 +149,7 @@ CREATE TABLE public.checkpoints ( -- Name: click_logs; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.click_logs ( +CREATE TABLE IF NOT EXISTS public.click_logs ( id uuid NOT NULL, user_id uuid, solution_id uuid NOT NULL, @@ -165,7 +165,7 @@ CREATE TABLE public.click_logs ( -- Name: comments; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.comments ( +CREATE TABLE IF NOT EXISTS public.comments ( id uuid NOT NULL, post_id uuid NOT NULL, user_id uuid NOT NULL, @@ -181,7 +181,7 @@ CREATE TABLE public.comments ( -- Name: content_reports; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.content_reports ( +CREATE TABLE IF NOT EXISTS public.content_reports ( id uuid DEFAULT gen_random_uuid() NOT NULL, target_type character varying(32) DEFAULT 'post'::character varying NOT NULL, target_id uuid NOT NULL, @@ -201,7 +201,7 @@ CREATE TABLE public.content_reports ( -- Name: credit_transactions; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.credit_transactions ( +CREATE TABLE IF NOT EXISTS public.credit_transactions ( id uuid NOT NULL, user_id uuid NOT NULL, amount integer NOT NULL, @@ -217,7 +217,7 @@ CREATE TABLE public.credit_transactions ( -- Name: curation_posts; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.curation_posts ( +CREATE TABLE IF NOT EXISTS public.curation_posts ( curation_id uuid NOT NULL, post_id uuid NOT NULL, display_order integer DEFAULT 0 NOT NULL @@ -229,7 +229,7 @@ CREATE TABLE public.curation_posts ( -- Name: curations; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.curations ( +CREATE TABLE IF NOT EXISTS public.curations ( id uuid NOT NULL, title character varying(255) NOT NULL, description text, @@ -246,7 +246,7 @@ CREATE TABLE public.curations ( -- Name: decoded_picks; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.decoded_picks ( +CREATE TABLE IF NOT EXISTS public.decoded_picks ( id uuid DEFAULT gen_random_uuid() NOT NULL, post_id uuid NOT NULL, pick_date date DEFAULT CURRENT_DATE NOT NULL, @@ -262,7 +262,7 @@ CREATE TABLE public.decoded_picks ( -- Name: earnings; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.earnings ( +CREATE TABLE IF NOT EXISTS public.earnings ( id uuid NOT NULL, user_id uuid NOT NULL, solution_id uuid NOT NULL, @@ -279,7 +279,7 @@ CREATE TABLE public.earnings ( -- Name: embeddings; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.embeddings ( +CREATE TABLE IF NOT EXISTS public.embeddings ( id uuid DEFAULT gen_random_uuid() NOT NULL, entity_type character varying(20) NOT NULL, entity_id uuid NOT NULL, @@ -294,7 +294,7 @@ CREATE TABLE public.embeddings ( -- Name: posts; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.posts ( +CREATE TABLE IF NOT EXISTS public.posts ( id uuid NOT NULL, user_id uuid NOT NULL, image_url text NOT NULL, @@ -359,7 +359,7 @@ COMMENT ON COLUMN public.posts.image_height IS 'Original image height in pixels' -- Name: failed_batch_items; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.failed_batch_items ( +CREATE TABLE IF NOT EXISTS public.failed_batch_items ( id uuid NOT NULL, item_id character varying(255) NOT NULL, batch_id character varying(255) NOT NULL, @@ -378,7 +378,7 @@ CREATE TABLE public.failed_batch_items ( -- Name: magazine_posts; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.magazine_posts ( +CREATE TABLE IF NOT EXISTS public.magazine_posts ( magazine_id uuid NOT NULL, post_id uuid NOT NULL, section_index integer DEFAULT 0 NOT NULL @@ -390,7 +390,7 @@ CREATE TABLE public.magazine_posts ( -- Name: magazines; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.magazines ( +CREATE TABLE IF NOT EXISTS public.magazines ( id uuid DEFAULT gen_random_uuid() NOT NULL, title character varying(255) NOT NULL, subtitle text, @@ -417,7 +417,7 @@ CREATE TABLE public.magazines ( -- Name: point_logs; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.point_logs ( +CREATE TABLE IF NOT EXISTS public.point_logs ( id uuid NOT NULL, user_id uuid NOT NULL, activity_type character varying NOT NULL, @@ -434,7 +434,7 @@ CREATE TABLE public.point_logs ( -- Name: post_likes; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.post_likes ( +CREATE TABLE IF NOT EXISTS public.post_likes ( id uuid NOT NULL, post_id uuid NOT NULL, user_id uuid NOT NULL, @@ -447,7 +447,7 @@ CREATE TABLE public.post_likes ( -- Name: post_magazine_news_references; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.post_magazine_news_references ( +CREATE TABLE IF NOT EXISTS public.post_magazine_news_references ( id uuid DEFAULT gen_random_uuid() NOT NULL, post_magazine_id uuid NOT NULL, title character varying NOT NULL, @@ -470,7 +470,7 @@ CREATE TABLE public.post_magazine_news_references ( -- Name: processed_batches; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.processed_batches ( +CREATE TABLE IF NOT EXISTS public.processed_batches ( batch_id character varying(255) NOT NULL, processing_timestamp timestamp with time zone NOT NULL, total_count integer NOT NULL, @@ -487,7 +487,7 @@ CREATE TABLE public.processed_batches ( -- Name: saved_posts; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.saved_posts ( +CREATE TABLE IF NOT EXISTS public.saved_posts ( id uuid NOT NULL, post_id uuid NOT NULL, user_id uuid NOT NULL, @@ -500,7 +500,7 @@ CREATE TABLE public.saved_posts ( -- Name: search_logs; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.search_logs ( +CREATE TABLE IF NOT EXISTS public.search_logs ( id uuid NOT NULL, user_id uuid, query character varying(255) NOT NULL, @@ -514,7 +514,7 @@ CREATE TABLE public.search_logs ( -- Name: settlements; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.settlements ( +CREATE TABLE IF NOT EXISTS public.settlements ( id uuid NOT NULL, user_id uuid NOT NULL, amount numeric(12,2) NOT NULL, @@ -531,7 +531,7 @@ CREATE TABLE public.settlements ( -- Name: solutions; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.solutions ( +CREATE TABLE IF NOT EXISTS public.solutions ( id uuid NOT NULL, spot_id uuid NOT NULL, user_id uuid NOT NULL, @@ -607,7 +607,7 @@ COMMENT ON COLUMN public.solutions.brand_id IS 'FK to warehouse.brands.id (backf -- Name: spots; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.spots ( +CREATE TABLE IF NOT EXISTS public.spots ( id uuid NOT NULL, post_id uuid NOT NULL, user_id uuid NOT NULL, @@ -625,7 +625,7 @@ CREATE TABLE public.spots ( -- Name: subcategories; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.subcategories ( +CREATE TABLE IF NOT EXISTS public.subcategories ( id uuid NOT NULL, category_id uuid NOT NULL, code character varying(50) NOT NULL, @@ -643,7 +643,7 @@ CREATE TABLE public.subcategories ( -- Name: synonyms; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.synonyms ( +CREATE TABLE IF NOT EXISTS public.synonyms ( id uuid NOT NULL, type character varying(50) NOT NULL, canonical character varying(255) NOT NULL, @@ -659,7 +659,7 @@ CREATE TABLE public.synonyms ( -- Name: try_spot_tags; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.try_spot_tags ( +CREATE TABLE IF NOT EXISTS public.try_spot_tags ( id uuid NOT NULL, try_post_id uuid NOT NULL, spot_id uuid NOT NULL, @@ -672,7 +672,7 @@ CREATE TABLE public.try_spot_tags ( -- Name: user_badges; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.user_badges ( +CREATE TABLE IF NOT EXISTS public.user_badges ( user_id uuid NOT NULL, badge_id uuid NOT NULL, earned_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL @@ -684,7 +684,7 @@ CREATE TABLE public.user_badges ( -- Name: user_collections; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.user_collections ( +CREATE TABLE IF NOT EXISTS public.user_collections ( id uuid NOT NULL, user_id uuid NOT NULL, magazine_id uuid NOT NULL, @@ -698,7 +698,7 @@ CREATE TABLE public.user_collections ( -- Name: user_events; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.user_events ( +CREATE TABLE IF NOT EXISTS public.user_events ( id uuid DEFAULT gen_random_uuid() NOT NULL, user_id uuid NOT NULL, event_type character varying NOT NULL, @@ -715,7 +715,7 @@ CREATE TABLE public.user_events ( -- Name: user_follows; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.user_follows ( +CREATE TABLE IF NOT EXISTS public.user_follows ( follower_id uuid NOT NULL, following_id uuid NOT NULL, created_at timestamp with time zone DEFAULT now() NOT NULL @@ -727,7 +727,7 @@ CREATE TABLE public.user_follows ( -- Name: user_magazines; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.user_magazines ( +CREATE TABLE IF NOT EXISTS public.user_magazines ( id uuid NOT NULL, created_by uuid NOT NULL, magazine_type character varying(20) NOT NULL, @@ -744,7 +744,7 @@ CREATE TABLE public.user_magazines ( -- Name: user_social_accounts; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.user_social_accounts ( +CREATE TABLE IF NOT EXISTS public.user_social_accounts ( id uuid NOT NULL, user_id uuid NOT NULL, provider character varying(20) NOT NULL, @@ -762,7 +762,7 @@ CREATE TABLE public.user_social_accounts ( -- Name: user_tryon_history; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.user_tryon_history ( +CREATE TABLE IF NOT EXISTS public.user_tryon_history ( id uuid DEFAULT gen_random_uuid() NOT NULL, user_id uuid NOT NULL, image_url text NOT NULL, @@ -784,7 +784,7 @@ COMMENT ON TABLE public.user_tryon_history IS 'Virtual try-on (VTON) history for -- Name: users; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.users ( +CREATE TABLE IF NOT EXISTS public.users ( id uuid NOT NULL, email character varying(255) NOT NULL, username character varying(50) NOT NULL, @@ -807,7 +807,7 @@ CREATE TABLE public.users ( -- Name: view_logs; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.view_logs ( +CREATE TABLE IF NOT EXISTS public.view_logs ( id uuid NOT NULL, user_id uuid, reference_type character varying(20) NOT NULL, @@ -821,7 +821,7 @@ CREATE TABLE public.view_logs ( -- Name: votes; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.votes ( +CREATE TABLE IF NOT EXISTS public.votes ( id uuid NOT NULL, solution_id uuid NOT NULL, user_id uuid NOT NULL, diff --git a/packages/api-server/migration/sql/004_warehouse_tables.sql b/packages/api-server/migration/sql/004_warehouse_tables.sql index 505c0d30..c906a47e 100644 --- a/packages/api-server/migration/sql/004_warehouse_tables.sql +++ b/packages/api-server/migration/sql/004_warehouse_tables.sql @@ -3,7 +3,7 @@ -- Name: admin_audit_log; Type: TABLE; Schema: warehouse; Owner: - -- -CREATE TABLE warehouse.admin_audit_log ( +CREATE TABLE IF NOT EXISTS warehouse.admin_audit_log ( id uuid DEFAULT gen_random_uuid() NOT NULL, admin_user_id uuid NOT NULL, action text NOT NULL, @@ -29,7 +29,7 @@ COMMENT ON TABLE warehouse.admin_audit_log IS 'Admin action audit trail for all -- Name: artists; Type: TABLE; Schema: warehouse; Owner: - -- -CREATE TABLE warehouse.artists ( +CREATE TABLE IF NOT EXISTS warehouse.artists ( id uuid DEFAULT gen_random_uuid() NOT NULL, name_ko text, name_en text, @@ -46,7 +46,7 @@ CREATE TABLE warehouse.artists ( -- Name: brands; Type: TABLE; Schema: warehouse; Owner: - -- -CREATE TABLE warehouse.brands ( +CREATE TABLE IF NOT EXISTS warehouse.brands ( id uuid DEFAULT gen_random_uuid() NOT NULL, name_ko text, name_en text, @@ -63,7 +63,7 @@ CREATE TABLE warehouse.brands ( -- Name: group_members; Type: TABLE; Schema: warehouse; Owner: - -- -CREATE TABLE warehouse.group_members ( +CREATE TABLE IF NOT EXISTS warehouse.group_members ( group_id uuid NOT NULL, artist_id uuid NOT NULL, is_active boolean DEFAULT true NOT NULL, @@ -78,7 +78,7 @@ CREATE TABLE warehouse.group_members ( -- Name: groups; Type: TABLE; Schema: warehouse; Owner: - -- -CREATE TABLE warehouse.groups ( +CREATE TABLE IF NOT EXISTS warehouse.groups ( id uuid DEFAULT gen_random_uuid() NOT NULL, name_ko text, name_en text, @@ -95,7 +95,7 @@ CREATE TABLE warehouse.groups ( -- Name: images; Type: TABLE; Schema: warehouse; Owner: - -- -CREATE TABLE warehouse.images ( +CREATE TABLE IF NOT EXISTS warehouse.images ( id uuid DEFAULT gen_random_uuid() NOT NULL, post_id uuid NOT NULL, image_hash text NOT NULL, @@ -111,7 +111,7 @@ CREATE TABLE warehouse.images ( -- Name: instagram_accounts; Type: TABLE; Schema: warehouse; Owner: - -- -CREATE TABLE warehouse.instagram_accounts ( +CREATE TABLE IF NOT EXISTS warehouse.instagram_accounts ( id uuid DEFAULT gen_random_uuid() NOT NULL, username text NOT NULL, account_type warehouse.account_type NOT NULL, @@ -143,7 +143,7 @@ CREATE TABLE warehouse.instagram_accounts ( -- Name: posts; Type: TABLE; Schema: warehouse; Owner: - -- -CREATE TABLE warehouse.posts ( +CREATE TABLE IF NOT EXISTS warehouse.posts ( id uuid DEFAULT gen_random_uuid() NOT NULL, account_id uuid NOT NULL, posted_at timestamp with time zone NOT NULL, @@ -158,7 +158,7 @@ CREATE TABLE warehouse.posts ( -- Name: raw_post_sources; Type: TABLE; Schema: warehouse; Owner: - -- -CREATE TABLE warehouse.raw_post_sources ( +CREATE TABLE IF NOT EXISTS warehouse.raw_post_sources ( id uuid DEFAULT gen_random_uuid() NOT NULL, platform text NOT NULL, source_type text NOT NULL, @@ -179,7 +179,7 @@ CREATE TABLE warehouse.raw_post_sources ( -- Name: raw_posts; Type: TABLE; Schema: warehouse; Owner: - -- -CREATE TABLE warehouse.raw_posts ( +CREATE TABLE IF NOT EXISTS warehouse.raw_posts ( id uuid DEFAULT gen_random_uuid() NOT NULL, source_id uuid NOT NULL, platform text NOT NULL, @@ -209,7 +209,7 @@ CREATE TABLE warehouse.raw_posts ( -- Name: seed_asset; Type: TABLE; Schema: warehouse; Owner: - -- -CREATE TABLE warehouse.seed_asset ( +CREATE TABLE IF NOT EXISTS warehouse.seed_asset ( id uuid DEFAULT gen_random_uuid() NOT NULL, seed_post_id uuid NOT NULL, source_url text, @@ -227,7 +227,7 @@ CREATE TABLE warehouse.seed_asset ( -- Name: seed_posts; Type: TABLE; Schema: warehouse; Owner: - -- -CREATE TABLE warehouse.seed_posts ( +CREATE TABLE IF NOT EXISTS warehouse.seed_posts ( id uuid DEFAULT gen_random_uuid() NOT NULL, source_post_id uuid, source_image_id uuid, @@ -249,7 +249,7 @@ CREATE TABLE warehouse.seed_posts ( -- Name: seed_spots; Type: TABLE; Schema: warehouse; Owner: - -- -CREATE TABLE warehouse.seed_spots ( +CREATE TABLE IF NOT EXISTS warehouse.seed_spots ( id uuid DEFAULT gen_random_uuid() NOT NULL, seed_post_id uuid NOT NULL, request_order integer NOT NULL, diff --git a/packages/api-server/migration/sql/005_views.sql b/packages/api-server/migration/sql/005_views.sql index e70665cf..49178f6c 100644 --- a/packages/api-server/migration/sql/005_views.sql +++ b/packages/api-server/migration/sql/005_views.sql @@ -3,7 +3,7 @@ -- Name: explore_posts; Type: VIEW; Schema: public; Owner: - -- -CREATE VIEW public.explore_posts WITH (security_invoker='true') AS +CREATE OR REPLACE VIEW public.explore_posts WITH (security_invoker='true') AS SELECT p.id, p.user_id, p.image_url, diff --git a/packages/api-server/migration/sql/006_indexes_and_constraints.sql b/packages/api-server/migration/sql/006_indexes_and_constraints.sql index 977585b9..3f5fd341 100644 --- a/packages/api-server/migration/sql/006_indexes_and_constraints.sql +++ b/packages/api-server/migration/sql/006_indexes_and_constraints.sql @@ -3,8 +3,15 @@ -- Name: agent_sessions agent_sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.agent_sessions - ADD CONSTRAINT agent_sessions_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.agent_sessions + ADD CONSTRAINT agent_sessions_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -12,8 +19,15 @@ ALTER TABLE ONLY public.agent_sessions -- Name: agent_sessions agent_sessions_thread_id_key; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.agent_sessions - ADD CONSTRAINT agent_sessions_thread_id_key UNIQUE (thread_id); +DO $$ +BEGIN + ALTER TABLE ONLY public.agent_sessions + ADD CONSTRAINT agent_sessions_thread_id_key UNIQUE (thread_id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -21,8 +35,15 @@ ALTER TABLE ONLY public.agent_sessions -- Name: badges badges_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.badges - ADD CONSTRAINT badges_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.badges + ADD CONSTRAINT badges_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -30,8 +51,15 @@ ALTER TABLE ONLY public.badges -- Name: categories categories_code_key; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.categories - ADD CONSTRAINT categories_code_key UNIQUE (code); +DO $$ +BEGIN + ALTER TABLE ONLY public.categories + ADD CONSTRAINT categories_code_key UNIQUE (code); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -39,8 +67,15 @@ ALTER TABLE ONLY public.categories -- Name: categories categories_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.categories - ADD CONSTRAINT categories_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.categories + ADD CONSTRAINT categories_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -48,8 +83,15 @@ ALTER TABLE ONLY public.categories -- Name: checkpoint_blobs checkpoint_blobs_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.checkpoint_blobs - ADD CONSTRAINT checkpoint_blobs_pkey PRIMARY KEY (thread_id, checkpoint_ns, channel, version); +DO $$ +BEGIN + ALTER TABLE ONLY public.checkpoint_blobs + ADD CONSTRAINT checkpoint_blobs_pkey PRIMARY KEY (thread_id, checkpoint_ns, channel, version); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -57,8 +99,15 @@ ALTER TABLE ONLY public.checkpoint_blobs -- Name: checkpoint_migrations checkpoint_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.checkpoint_migrations - ADD CONSTRAINT checkpoint_migrations_pkey PRIMARY KEY (v); +DO $$ +BEGIN + ALTER TABLE ONLY public.checkpoint_migrations + ADD CONSTRAINT checkpoint_migrations_pkey PRIMARY KEY (v); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -66,8 +115,15 @@ ALTER TABLE ONLY public.checkpoint_migrations -- Name: checkpoint_writes checkpoint_writes_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.checkpoint_writes - ADD CONSTRAINT checkpoint_writes_pkey PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id, task_id, idx); +DO $$ +BEGIN + ALTER TABLE ONLY public.checkpoint_writes + ADD CONSTRAINT checkpoint_writes_pkey PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id, task_id, idx); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -75,8 +131,15 @@ ALTER TABLE ONLY public.checkpoint_writes -- Name: checkpoints checkpoints_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.checkpoints - ADD CONSTRAINT checkpoints_pkey PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id); +DO $$ +BEGIN + ALTER TABLE ONLY public.checkpoints + ADD CONSTRAINT checkpoints_pkey PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -84,8 +147,15 @@ ALTER TABLE ONLY public.checkpoints -- Name: click_logs click_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.click_logs - ADD CONSTRAINT click_logs_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.click_logs + ADD CONSTRAINT click_logs_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -93,8 +163,15 @@ ALTER TABLE ONLY public.click_logs -- Name: comments comments_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.comments - ADD CONSTRAINT comments_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.comments + ADD CONSTRAINT comments_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -102,8 +179,15 @@ ALTER TABLE ONLY public.comments -- Name: content_reports content_reports_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.content_reports - ADD CONSTRAINT content_reports_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.content_reports + ADD CONSTRAINT content_reports_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -111,8 +195,15 @@ ALTER TABLE ONLY public.content_reports -- Name: credit_transactions credit_transactions_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.credit_transactions - ADD CONSTRAINT credit_transactions_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.credit_transactions + ADD CONSTRAINT credit_transactions_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -120,8 +211,15 @@ ALTER TABLE ONLY public.credit_transactions -- Name: curation_posts curation_posts_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.curation_posts - ADD CONSTRAINT curation_posts_pkey PRIMARY KEY (curation_id, post_id); +DO $$ +BEGIN + ALTER TABLE ONLY public.curation_posts + ADD CONSTRAINT curation_posts_pkey PRIMARY KEY (curation_id, post_id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -129,8 +227,15 @@ ALTER TABLE ONLY public.curation_posts -- Name: curations curations_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.curations - ADD CONSTRAINT curations_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.curations + ADD CONSTRAINT curations_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -138,8 +243,15 @@ ALTER TABLE ONLY public.curations -- Name: decoded_picks decoded_picks_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.decoded_picks - ADD CONSTRAINT decoded_picks_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.decoded_picks + ADD CONSTRAINT decoded_picks_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -147,8 +259,15 @@ ALTER TABLE ONLY public.decoded_picks -- Name: earnings earnings_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.earnings - ADD CONSTRAINT earnings_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.earnings + ADD CONSTRAINT earnings_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -156,8 +275,15 @@ ALTER TABLE ONLY public.earnings -- Name: embeddings embeddings_entity_type_entity_id_key; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.embeddings - ADD CONSTRAINT embeddings_entity_type_entity_id_key UNIQUE (entity_type, entity_id); +DO $$ +BEGIN + ALTER TABLE ONLY public.embeddings + ADD CONSTRAINT embeddings_entity_type_entity_id_key UNIQUE (entity_type, entity_id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -165,8 +291,15 @@ ALTER TABLE ONLY public.embeddings -- Name: embeddings embeddings_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.embeddings - ADD CONSTRAINT embeddings_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.embeddings + ADD CONSTRAINT embeddings_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -174,8 +307,15 @@ ALTER TABLE ONLY public.embeddings -- Name: failed_batch_items failed_batch_items_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.failed_batch_items - ADD CONSTRAINT failed_batch_items_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.failed_batch_items + ADD CONSTRAINT failed_batch_items_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -183,8 +323,15 @@ ALTER TABLE ONLY public.failed_batch_items -- Name: magazine_posts magazine_posts_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.magazine_posts - ADD CONSTRAINT magazine_posts_pkey PRIMARY KEY (magazine_id, post_id); +DO $$ +BEGIN + ALTER TABLE ONLY public.magazine_posts + ADD CONSTRAINT magazine_posts_pkey PRIMARY KEY (magazine_id, post_id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -192,8 +339,15 @@ ALTER TABLE ONLY public.magazine_posts -- Name: magazines magazines_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.magazines - ADD CONSTRAINT magazines_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.magazines + ADD CONSTRAINT magazines_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -201,8 +355,15 @@ ALTER TABLE ONLY public.magazines -- Name: user_badges pk_user_badges; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_badges - ADD CONSTRAINT pk_user_badges PRIMARY KEY (user_id, badge_id); +DO $$ +BEGIN + ALTER TABLE ONLY public.user_badges + ADD CONSTRAINT pk_user_badges PRIMARY KEY (user_id, badge_id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -210,8 +371,15 @@ ALTER TABLE ONLY public.user_badges -- Name: point_logs point_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.point_logs - ADD CONSTRAINT point_logs_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.point_logs + ADD CONSTRAINT point_logs_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -219,8 +387,15 @@ ALTER TABLE ONLY public.point_logs -- Name: post_likes post_likes_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.post_likes - ADD CONSTRAINT post_likes_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.post_likes + ADD CONSTRAINT post_likes_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -228,8 +403,15 @@ ALTER TABLE ONLY public.post_likes -- Name: post_magazine_news_references post_magazine_news_references_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.post_magazine_news_references - ADD CONSTRAINT post_magazine_news_references_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.post_magazine_news_references + ADD CONSTRAINT post_magazine_news_references_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -237,8 +419,15 @@ ALTER TABLE ONLY public.post_magazine_news_references -- Name: post_magazines post_magazines_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.post_magazines - ADD CONSTRAINT post_magazines_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.post_magazines + ADD CONSTRAINT post_magazines_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -246,8 +435,15 @@ ALTER TABLE ONLY public.post_magazines -- Name: posts posts_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.posts - ADD CONSTRAINT posts_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.posts + ADD CONSTRAINT posts_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -255,8 +451,15 @@ ALTER TABLE ONLY public.posts -- Name: processed_batches processed_batches_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.processed_batches - ADD CONSTRAINT processed_batches_pkey PRIMARY KEY (batch_id); +DO $$ +BEGIN + ALTER TABLE ONLY public.processed_batches + ADD CONSTRAINT processed_batches_pkey PRIMARY KEY (batch_id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -264,8 +467,15 @@ ALTER TABLE ONLY public.processed_batches -- Name: saved_posts saved_posts_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.saved_posts - ADD CONSTRAINT saved_posts_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.saved_posts + ADD CONSTRAINT saved_posts_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -273,8 +483,15 @@ ALTER TABLE ONLY public.saved_posts -- Name: search_logs search_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.search_logs - ADD CONSTRAINT search_logs_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.search_logs + ADD CONSTRAINT search_logs_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -282,8 +499,15 @@ ALTER TABLE ONLY public.search_logs -- Name: settlements settlements_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.settlements - ADD CONSTRAINT settlements_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.settlements + ADD CONSTRAINT settlements_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -291,8 +515,15 @@ ALTER TABLE ONLY public.settlements -- Name: solutions solutions_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.solutions - ADD CONSTRAINT solutions_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.solutions + ADD CONSTRAINT solutions_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -300,8 +531,15 @@ ALTER TABLE ONLY public.solutions -- Name: spots spots_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.spots - ADD CONSTRAINT spots_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.spots + ADD CONSTRAINT spots_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -309,8 +547,15 @@ ALTER TABLE ONLY public.spots -- Name: subcategories subcategories_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.subcategories - ADD CONSTRAINT subcategories_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.subcategories + ADD CONSTRAINT subcategories_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -318,8 +563,15 @@ ALTER TABLE ONLY public.subcategories -- Name: synonyms synonyms_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.synonyms - ADD CONSTRAINT synonyms_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.synonyms + ADD CONSTRAINT synonyms_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -327,8 +579,15 @@ ALTER TABLE ONLY public.synonyms -- Name: try_spot_tags try_spot_tags_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.try_spot_tags - ADD CONSTRAINT try_spot_tags_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.try_spot_tags + ADD CONSTRAINT try_spot_tags_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -336,8 +595,15 @@ ALTER TABLE ONLY public.try_spot_tags -- Name: user_collections user_collections_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_collections - ADD CONSTRAINT user_collections_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.user_collections + ADD CONSTRAINT user_collections_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -345,8 +611,15 @@ ALTER TABLE ONLY public.user_collections -- Name: user_events user_events_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_events - ADD CONSTRAINT user_events_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.user_events + ADD CONSTRAINT user_events_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -354,8 +627,15 @@ ALTER TABLE ONLY public.user_events -- Name: user_follows user_follows_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_follows - ADD CONSTRAINT user_follows_pkey PRIMARY KEY (follower_id, following_id); +DO $$ +BEGIN + ALTER TABLE ONLY public.user_follows + ADD CONSTRAINT user_follows_pkey PRIMARY KEY (follower_id, following_id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -363,8 +643,15 @@ ALTER TABLE ONLY public.user_follows -- Name: user_magazines user_magazines_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_magazines - ADD CONSTRAINT user_magazines_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.user_magazines + ADD CONSTRAINT user_magazines_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -372,8 +659,15 @@ ALTER TABLE ONLY public.user_magazines -- Name: user_social_accounts user_social_accounts_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_social_accounts - ADD CONSTRAINT user_social_accounts_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.user_social_accounts + ADD CONSTRAINT user_social_accounts_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -381,8 +675,15 @@ ALTER TABLE ONLY public.user_social_accounts -- Name: user_tryon_history user_tryon_history_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_tryon_history - ADD CONSTRAINT user_tryon_history_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.user_tryon_history + ADD CONSTRAINT user_tryon_history_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -390,8 +691,15 @@ ALTER TABLE ONLY public.user_tryon_history -- Name: users users_email_key; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.users - ADD CONSTRAINT users_email_key UNIQUE (email); +DO $$ +BEGIN + ALTER TABLE ONLY public.users + ADD CONSTRAINT users_email_key UNIQUE (email); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -399,8 +707,15 @@ ALTER TABLE ONLY public.users -- Name: users users_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.users - ADD CONSTRAINT users_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.users + ADD CONSTRAINT users_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -408,8 +723,15 @@ ALTER TABLE ONLY public.users -- Name: users users_username_key; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.users - ADD CONSTRAINT users_username_key UNIQUE (username); +DO $$ +BEGIN + ALTER TABLE ONLY public.users + ADD CONSTRAINT users_username_key UNIQUE (username); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -417,8 +739,15 @@ ALTER TABLE ONLY public.users -- Name: view_logs view_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.view_logs - ADD CONSTRAINT view_logs_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.view_logs + ADD CONSTRAINT view_logs_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -426,8 +755,15 @@ ALTER TABLE ONLY public.view_logs -- Name: votes votes_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.votes - ADD CONSTRAINT votes_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY public.votes + ADD CONSTRAINT votes_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -435,8 +771,15 @@ ALTER TABLE ONLY public.votes -- Name: admin_audit_log admin_audit_log_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.admin_audit_log - ADD CONSTRAINT admin_audit_log_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.admin_audit_log + ADD CONSTRAINT admin_audit_log_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -444,8 +787,15 @@ ALTER TABLE ONLY warehouse.admin_audit_log -- Name: artists artists_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.artists - ADD CONSTRAINT artists_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.artists + ADD CONSTRAINT artists_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -453,8 +803,15 @@ ALTER TABLE ONLY warehouse.artists -- Name: brands brands_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.brands - ADD CONSTRAINT brands_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.brands + ADD CONSTRAINT brands_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -462,8 +819,15 @@ ALTER TABLE ONLY warehouse.brands -- Name: group_members group_members_pkey1; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.group_members - ADD CONSTRAINT group_members_pkey1 PRIMARY KEY (group_id, artist_id); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.group_members + ADD CONSTRAINT group_members_pkey1 PRIMARY KEY (group_id, artist_id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -471,8 +835,15 @@ ALTER TABLE ONLY warehouse.group_members -- Name: groups groups_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.groups - ADD CONSTRAINT groups_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.groups + ADD CONSTRAINT groups_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -480,8 +851,15 @@ ALTER TABLE ONLY warehouse.groups -- Name: images images_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.images - ADD CONSTRAINT images_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.images + ADD CONSTRAINT images_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -489,8 +867,15 @@ ALTER TABLE ONLY warehouse.images -- Name: instagram_accounts instagram_accounts_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.instagram_accounts - ADD CONSTRAINT instagram_accounts_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.instagram_accounts + ADD CONSTRAINT instagram_accounts_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -498,8 +883,15 @@ ALTER TABLE ONLY warehouse.instagram_accounts -- Name: posts posts_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.posts - ADD CONSTRAINT posts_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.posts + ADD CONSTRAINT posts_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -507,8 +899,15 @@ ALTER TABLE ONLY warehouse.posts -- Name: raw_post_sources raw_post_sources_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.raw_post_sources - ADD CONSTRAINT raw_post_sources_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.raw_post_sources + ADD CONSTRAINT raw_post_sources_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -516,8 +915,15 @@ ALTER TABLE ONLY warehouse.raw_post_sources -- Name: raw_post_sources raw_post_sources_unique_target; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.raw_post_sources - ADD CONSTRAINT raw_post_sources_unique_target UNIQUE (platform, source_type, source_identifier); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.raw_post_sources + ADD CONSTRAINT raw_post_sources_unique_target UNIQUE (platform, source_type, source_identifier); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -525,8 +931,15 @@ ALTER TABLE ONLY warehouse.raw_post_sources -- Name: raw_posts raw_posts_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.raw_posts - ADD CONSTRAINT raw_posts_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.raw_posts + ADD CONSTRAINT raw_posts_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -534,8 +947,15 @@ ALTER TABLE ONLY warehouse.raw_posts -- Name: raw_posts raw_posts_unique_external; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.raw_posts - ADD CONSTRAINT raw_posts_unique_external UNIQUE (platform, external_id); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.raw_posts + ADD CONSTRAINT raw_posts_unique_external UNIQUE (platform, external_id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -543,8 +963,15 @@ ALTER TABLE ONLY warehouse.raw_posts -- Name: seed_asset seed_asset_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.seed_asset - ADD CONSTRAINT seed_asset_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.seed_asset + ADD CONSTRAINT seed_asset_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -552,8 +979,15 @@ ALTER TABLE ONLY warehouse.seed_asset -- Name: seed_posts seed_posts_backend_post_id_key; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.seed_posts - ADD CONSTRAINT seed_posts_backend_post_id_key UNIQUE (backend_post_id); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.seed_posts + ADD CONSTRAINT seed_posts_backend_post_id_key UNIQUE (backend_post_id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -561,8 +995,15 @@ ALTER TABLE ONLY warehouse.seed_posts -- Name: seed_posts seed_posts_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.seed_posts - ADD CONSTRAINT seed_posts_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.seed_posts + ADD CONSTRAINT seed_posts_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -570,8 +1011,15 @@ ALTER TABLE ONLY warehouse.seed_posts -- Name: seed_spots seed_spots_pkey; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.seed_spots - ADD CONSTRAINT seed_spots_pkey PRIMARY KEY (id); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.seed_spots + ADD CONSTRAINT seed_spots_pkey PRIMARY KEY (id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -579,8 +1027,15 @@ ALTER TABLE ONLY warehouse.seed_spots -- Name: images warehouse_images_post_id_image_hash_key; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.images - ADD CONSTRAINT warehouse_images_post_id_image_hash_key UNIQUE (post_id, image_hash); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.images + ADD CONSTRAINT warehouse_images_post_id_image_hash_key UNIQUE (post_id, image_hash); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -588,8 +1043,15 @@ ALTER TABLE ONLY warehouse.images -- Name: instagram_accounts warehouse_instagram_accounts_username_key; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.instagram_accounts - ADD CONSTRAINT warehouse_instagram_accounts_username_key UNIQUE (username); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.instagram_accounts + ADD CONSTRAINT warehouse_instagram_accounts_username_key UNIQUE (username); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -597,8 +1059,15 @@ ALTER TABLE ONLY warehouse.instagram_accounts -- Name: posts warehouse_posts_account_id_posted_at_key; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.posts - ADD CONSTRAINT warehouse_posts_account_id_posted_at_key UNIQUE (account_id, posted_at); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.posts + ADD CONSTRAINT warehouse_posts_account_id_posted_at_key UNIQUE (account_id, posted_at); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -606,8 +1075,15 @@ ALTER TABLE ONLY warehouse.posts -- Name: seed_asset warehouse_seed_asset_image_hash_key; Type: CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.seed_asset - ADD CONSTRAINT warehouse_seed_asset_image_hash_key UNIQUE (image_hash); +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.seed_asset + ADD CONSTRAINT warehouse_seed_asset_image_hash_key UNIQUE (image_hash); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -615,7 +1091,7 @@ ALTER TABLE ONLY warehouse.seed_asset -- Name: checkpoint_blobs_thread_id_idx; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX checkpoint_blobs_thread_id_idx ON public.checkpoint_blobs USING btree (thread_id); +CREATE INDEX IF NOT EXISTS checkpoint_blobs_thread_id_idx ON public.checkpoint_blobs USING btree (thread_id); -- @@ -623,7 +1099,7 @@ CREATE INDEX checkpoint_blobs_thread_id_idx ON public.checkpoint_blobs USING btr -- Name: checkpoint_writes_thread_id_idx; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX checkpoint_writes_thread_id_idx ON public.checkpoint_writes USING btree (thread_id); +CREATE INDEX IF NOT EXISTS checkpoint_writes_thread_id_idx ON public.checkpoint_writes USING btree (thread_id); -- @@ -631,7 +1107,7 @@ CREATE INDEX checkpoint_writes_thread_id_idx ON public.checkpoint_writes USING b -- Name: checkpoints_thread_id_idx; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX checkpoints_thread_id_idx ON public.checkpoints USING btree (thread_id); +CREATE INDEX IF NOT EXISTS checkpoints_thread_id_idx ON public.checkpoints USING btree (thread_id); -- @@ -639,7 +1115,7 @@ CREATE INDEX checkpoints_thread_id_idx ON public.checkpoints USING btree (thread -- Name: idx_badges_rarity; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_badges_rarity ON public.badges USING btree (rarity); +CREATE INDEX IF NOT EXISTS idx_badges_rarity ON public.badges USING btree (rarity); -- @@ -647,7 +1123,7 @@ CREATE INDEX idx_badges_rarity ON public.badges USING btree (rarity); -- Name: idx_badges_type; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_badges_type ON public.badges USING btree (type); +CREATE INDEX IF NOT EXISTS idx_badges_type ON public.badges USING btree (type); -- @@ -655,7 +1131,7 @@ CREATE INDEX idx_badges_type ON public.badges USING btree (type); -- Name: idx_categories_code; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_categories_code ON public.categories USING btree (code); +CREATE INDEX IF NOT EXISTS idx_categories_code ON public.categories USING btree (code); -- @@ -663,7 +1139,7 @@ CREATE INDEX idx_categories_code ON public.categories USING btree (code); -- Name: idx_categories_display_order; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_categories_display_order ON public.categories USING btree (display_order); +CREATE INDEX IF NOT EXISTS idx_categories_display_order ON public.categories USING btree (display_order); -- @@ -671,7 +1147,7 @@ CREATE INDEX idx_categories_display_order ON public.categories USING btree (disp -- Name: idx_categories_is_active; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_categories_is_active ON public.categories USING btree (is_active); +CREATE INDEX IF NOT EXISTS idx_categories_is_active ON public.categories USING btree (is_active); -- @@ -679,7 +1155,7 @@ CREATE INDEX idx_categories_is_active ON public.categories USING btree (is_activ -- Name: idx_click_logs_created_at; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_click_logs_created_at ON public.click_logs USING btree (created_at); +CREATE INDEX IF NOT EXISTS idx_click_logs_created_at ON public.click_logs USING btree (created_at); -- @@ -687,7 +1163,7 @@ CREATE INDEX idx_click_logs_created_at ON public.click_logs USING btree (created -- Name: idx_click_logs_ip_created; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_click_logs_ip_created ON public.click_logs USING btree (ip_address, created_at); +CREATE INDEX IF NOT EXISTS idx_click_logs_ip_created ON public.click_logs USING btree (ip_address, created_at); -- @@ -695,7 +1171,7 @@ CREATE INDEX idx_click_logs_ip_created ON public.click_logs USING btree (ip_addr -- Name: idx_click_logs_solution_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_click_logs_solution_id ON public.click_logs USING btree (solution_id); +CREATE INDEX IF NOT EXISTS idx_click_logs_solution_id ON public.click_logs USING btree (solution_id); -- @@ -703,7 +1179,7 @@ CREATE INDEX idx_click_logs_solution_id ON public.click_logs USING btree (soluti -- Name: idx_click_logs_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_click_logs_user_id ON public.click_logs USING btree (user_id); +CREATE INDEX IF NOT EXISTS idx_click_logs_user_id ON public.click_logs USING btree (user_id); -- @@ -711,7 +1187,7 @@ CREATE INDEX idx_click_logs_user_id ON public.click_logs USING btree (user_id); -- Name: idx_click_logs_user_solution_created; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_click_logs_user_solution_created ON public.click_logs USING btree (user_id, solution_id, created_at); +CREATE INDEX IF NOT EXISTS idx_click_logs_user_solution_created ON public.click_logs USING btree (user_id, solution_id, created_at); -- @@ -719,7 +1195,7 @@ CREATE INDEX idx_click_logs_user_solution_created ON public.click_logs USING btr -- Name: idx_comments_parent_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_comments_parent_id ON public.comments USING btree (parent_id); +CREATE INDEX IF NOT EXISTS idx_comments_parent_id ON public.comments USING btree (parent_id); -- @@ -727,7 +1203,7 @@ CREATE INDEX idx_comments_parent_id ON public.comments USING btree (parent_id); -- Name: idx_comments_post_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_comments_post_id ON public.comments USING btree (post_id); +CREATE INDEX IF NOT EXISTS idx_comments_post_id ON public.comments USING btree (post_id); -- @@ -735,7 +1211,7 @@ CREATE INDEX idx_comments_post_id ON public.comments USING btree (post_id); -- Name: idx_comments_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_comments_user_id ON public.comments USING btree (user_id); +CREATE INDEX IF NOT EXISTS idx_comments_user_id ON public.comments USING btree (user_id); -- @@ -743,7 +1219,7 @@ CREATE INDEX idx_comments_user_id ON public.comments USING btree (user_id); -- Name: idx_content_reports_reporter; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_content_reports_reporter ON public.content_reports USING btree (reporter_id); +CREATE INDEX IF NOT EXISTS idx_content_reports_reporter ON public.content_reports USING btree (reporter_id); -- @@ -751,7 +1227,7 @@ CREATE INDEX idx_content_reports_reporter ON public.content_reports USING btree -- Name: idx_content_reports_status; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_content_reports_status ON public.content_reports USING btree (status); +CREATE INDEX IF NOT EXISTS idx_content_reports_status ON public.content_reports USING btree (status); -- @@ -759,7 +1235,7 @@ CREATE INDEX idx_content_reports_status ON public.content_reports USING btree (s -- Name: idx_content_reports_target; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_content_reports_target ON public.content_reports USING btree (target_type, target_id); +CREATE INDEX IF NOT EXISTS idx_content_reports_target ON public.content_reports USING btree (target_type, target_id); -- @@ -767,7 +1243,7 @@ CREATE INDEX idx_content_reports_target ON public.content_reports USING btree (t -- Name: idx_content_reports_unique_per_user; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX idx_content_reports_unique_per_user ON public.content_reports USING btree (target_type, target_id, reporter_id); +CREATE UNIQUE INDEX IF NOT EXISTS idx_content_reports_unique_per_user ON public.content_reports USING btree (target_type, target_id, reporter_id); -- @@ -775,7 +1251,7 @@ CREATE UNIQUE INDEX idx_content_reports_unique_per_user ON public.content_report -- Name: idx_credit_transactions_action_type; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_credit_transactions_action_type ON public.credit_transactions USING btree (action_type); +CREATE INDEX IF NOT EXISTS idx_credit_transactions_action_type ON public.credit_transactions USING btree (action_type); -- @@ -783,7 +1259,7 @@ CREATE INDEX idx_credit_transactions_action_type ON public.credit_transactions U -- Name: idx_credit_transactions_status; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_credit_transactions_status ON public.credit_transactions USING btree (status); +CREATE INDEX IF NOT EXISTS idx_credit_transactions_status ON public.credit_transactions USING btree (status); -- @@ -791,7 +1267,7 @@ CREATE INDEX idx_credit_transactions_status ON public.credit_transactions USING -- Name: idx_credit_transactions_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_credit_transactions_user_id ON public.credit_transactions USING btree (user_id); +CREATE INDEX IF NOT EXISTS idx_credit_transactions_user_id ON public.credit_transactions USING btree (user_id); -- @@ -799,7 +1275,7 @@ CREATE INDEX idx_credit_transactions_user_id ON public.credit_transactions USING -- Name: idx_curation_posts_curation_id_display_order; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_curation_posts_curation_id_display_order ON public.curation_posts USING btree (curation_id, display_order); +CREATE INDEX IF NOT EXISTS idx_curation_posts_curation_id_display_order ON public.curation_posts USING btree (curation_id, display_order); -- @@ -807,7 +1283,7 @@ CREATE INDEX idx_curation_posts_curation_id_display_order ON public.curation_pos -- Name: idx_curation_posts_post_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_curation_posts_post_id ON public.curation_posts USING btree (post_id); +CREATE INDEX IF NOT EXISTS idx_curation_posts_post_id ON public.curation_posts USING btree (post_id); -- @@ -815,7 +1291,7 @@ CREATE INDEX idx_curation_posts_post_id ON public.curation_posts USING btree (po -- Name: idx_curations_is_active_display_order; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_curations_is_active_display_order ON public.curations USING btree (is_active, display_order); +CREATE INDEX IF NOT EXISTS idx_curations_is_active_display_order ON public.curations USING btree (is_active, display_order); -- @@ -823,7 +1299,7 @@ CREATE INDEX idx_curations_is_active_display_order ON public.curations USING btr -- Name: idx_decoded_picks_pick_date; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_decoded_picks_pick_date ON public.decoded_picks USING btree (pick_date DESC); +CREATE INDEX IF NOT EXISTS idx_decoded_picks_pick_date ON public.decoded_picks USING btree (pick_date DESC); -- @@ -831,7 +1307,7 @@ CREATE INDEX idx_decoded_picks_pick_date ON public.decoded_picks USING btree (pi -- Name: idx_decoded_picks_post_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_decoded_picks_post_id ON public.decoded_picks USING btree (post_id); +CREATE INDEX IF NOT EXISTS idx_decoded_picks_post_id ON public.decoded_picks USING btree (post_id); -- @@ -839,7 +1315,7 @@ CREATE INDEX idx_decoded_picks_post_id ON public.decoded_picks USING btree (post -- Name: idx_earnings_created_at; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_earnings_created_at ON public.earnings USING btree (created_at); +CREATE INDEX IF NOT EXISTS idx_earnings_created_at ON public.earnings USING btree (created_at); -- @@ -847,7 +1323,7 @@ CREATE INDEX idx_earnings_created_at ON public.earnings USING btree (created_at) -- Name: idx_earnings_solution_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_earnings_solution_id ON public.earnings USING btree (solution_id); +CREATE INDEX IF NOT EXISTS idx_earnings_solution_id ON public.earnings USING btree (solution_id); -- @@ -855,7 +1331,7 @@ CREATE INDEX idx_earnings_solution_id ON public.earnings USING btree (solution_i -- Name: idx_earnings_status; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_earnings_status ON public.earnings USING btree (status); +CREATE INDEX IF NOT EXISTS idx_earnings_status ON public.earnings USING btree (status); -- @@ -863,7 +1339,7 @@ CREATE INDEX idx_earnings_status ON public.earnings USING btree (status); -- Name: idx_earnings_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_earnings_user_id ON public.earnings USING btree (user_id); +CREATE INDEX IF NOT EXISTS idx_earnings_user_id ON public.earnings USING btree (user_id); -- @@ -871,7 +1347,7 @@ CREATE INDEX idx_earnings_user_id ON public.earnings USING btree (user_id); -- Name: idx_embeddings_entity_type; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_embeddings_entity_type ON public.embeddings USING btree (entity_type); +CREATE INDEX IF NOT EXISTS idx_embeddings_entity_type ON public.embeddings USING btree (entity_type); -- @@ -879,7 +1355,7 @@ CREATE INDEX idx_embeddings_entity_type ON public.embeddings USING btree (entity -- Name: idx_embeddings_hnsw; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_embeddings_hnsw ON public.embeddings USING hnsw (embedding extensions.vector_cosine_ops); +CREATE INDEX IF NOT EXISTS idx_embeddings_hnsw ON public.embeddings USING hnsw (embedding extensions.vector_cosine_ops); -- @@ -887,7 +1363,7 @@ CREATE INDEX idx_embeddings_hnsw ON public.embeddings USING hnsw (embedding exte -- Name: idx_failed_items_item_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_failed_items_item_id ON public.failed_batch_items USING btree (item_id); +CREATE INDEX IF NOT EXISTS idx_failed_items_item_id ON public.failed_batch_items USING btree (item_id); -- @@ -895,7 +1371,7 @@ CREATE INDEX idx_failed_items_item_id ON public.failed_batch_items USING btree ( -- Name: idx_failed_items_retry; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_failed_items_retry ON public.failed_batch_items USING btree (next_retry_at); +CREATE INDEX IF NOT EXISTS idx_failed_items_retry ON public.failed_batch_items USING btree (next_retry_at); -- @@ -903,7 +1379,7 @@ CREATE INDEX idx_failed_items_retry ON public.failed_batch_items USING btree (ne -- Name: idx_news_refs_magazine; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_news_refs_magazine ON public.post_magazine_news_references USING btree (post_magazine_id); +CREATE INDEX IF NOT EXISTS idx_news_refs_magazine ON public.post_magazine_news_references USING btree (post_magazine_id); -- @@ -911,7 +1387,7 @@ CREATE INDEX idx_news_refs_magazine ON public.post_magazine_news_references USIN -- Name: idx_point_logs_created_at; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_point_logs_created_at ON public.point_logs USING btree (created_at); +CREATE INDEX IF NOT EXISTS idx_point_logs_created_at ON public.point_logs USING btree (created_at); -- @@ -919,7 +1395,7 @@ CREATE INDEX idx_point_logs_created_at ON public.point_logs USING btree (created -- Name: idx_point_logs_user_created; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_point_logs_user_created ON public.point_logs USING btree (user_id, created_at); +CREATE INDEX IF NOT EXISTS idx_point_logs_user_created ON public.point_logs USING btree (user_id, created_at); -- @@ -927,7 +1403,7 @@ CREATE INDEX idx_point_logs_user_created ON public.point_logs USING btree (user_ -- Name: idx_point_logs_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_point_logs_user_id ON public.point_logs USING btree (user_id); +CREATE INDEX IF NOT EXISTS idx_point_logs_user_id ON public.point_logs USING btree (user_id); -- @@ -935,7 +1411,7 @@ CREATE INDEX idx_point_logs_user_id ON public.point_logs USING btree (user_id); -- Name: idx_post_likes_post_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_post_likes_post_id ON public.post_likes USING btree (post_id); +CREATE INDEX IF NOT EXISTS idx_post_likes_post_id ON public.post_likes USING btree (post_id); -- @@ -943,7 +1419,7 @@ CREATE INDEX idx_post_likes_post_id ON public.post_likes USING btree (post_id); -- Name: idx_post_likes_post_user_unique; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX idx_post_likes_post_user_unique ON public.post_likes USING btree (post_id, user_id); +CREATE UNIQUE INDEX IF NOT EXISTS idx_post_likes_post_user_unique ON public.post_likes USING btree (post_id, user_id); -- @@ -951,7 +1427,7 @@ CREATE UNIQUE INDEX idx_post_likes_post_user_unique ON public.post_likes USING b -- Name: idx_post_likes_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_post_likes_user_id ON public.post_likes USING btree (user_id); +CREATE INDEX IF NOT EXISTS idx_post_likes_user_id ON public.post_likes USING btree (user_id); -- @@ -959,7 +1435,7 @@ CREATE INDEX idx_post_likes_user_id ON public.post_likes USING btree (user_id); -- Name: idx_post_magazines_status; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_post_magazines_status ON public.post_magazines USING btree (status); +CREATE INDEX IF NOT EXISTS idx_post_magazines_status ON public.post_magazines USING btree (status); -- @@ -967,7 +1443,7 @@ CREATE INDEX idx_post_magazines_status ON public.post_magazines USING btree (sta -- Name: idx_posts_artist_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_posts_artist_id ON public.posts USING btree (artist_id); +CREATE INDEX IF NOT EXISTS idx_posts_artist_id ON public.posts USING btree (artist_id); -- @@ -975,7 +1451,7 @@ CREATE INDEX idx_posts_artist_id ON public.posts USING btree (artist_id); -- Name: idx_posts_artist_name; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_posts_artist_name ON public.posts USING btree (artist_name); +CREATE INDEX IF NOT EXISTS idx_posts_artist_name ON public.posts USING btree (artist_name); -- @@ -983,7 +1459,7 @@ CREATE INDEX idx_posts_artist_name ON public.posts USING btree (artist_name); -- Name: idx_posts_artist_name_trgm; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_posts_artist_name_trgm ON public.posts USING gin (artist_name extensions.gin_trgm_ops); +CREATE INDEX IF NOT EXISTS idx_posts_artist_name_trgm ON public.posts USING gin (artist_name extensions.gin_trgm_ops); -- @@ -991,7 +1467,7 @@ CREATE INDEX idx_posts_artist_name_trgm ON public.posts USING gin (artist_name e -- Name: idx_posts_context; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_posts_context ON public.posts USING btree (context); +CREATE INDEX IF NOT EXISTS idx_posts_context ON public.posts USING btree (context); -- @@ -999,7 +1475,7 @@ CREATE INDEX idx_posts_context ON public.posts USING btree (context); -- Name: idx_posts_created_at; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_posts_created_at ON public.posts USING btree (created_at); +CREATE INDEX IF NOT EXISTS idx_posts_created_at ON public.posts USING btree (created_at); -- @@ -1007,7 +1483,7 @@ CREATE INDEX idx_posts_created_at ON public.posts USING btree (created_at); -- Name: idx_posts_group_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_posts_group_id ON public.posts USING btree (group_id); +CREATE INDEX IF NOT EXISTS idx_posts_group_id ON public.posts USING btree (group_id); -- @@ -1015,7 +1491,7 @@ CREATE INDEX idx_posts_group_id ON public.posts USING btree (group_id); -- Name: idx_posts_group_name; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_posts_group_name ON public.posts USING btree (group_name); +CREATE INDEX IF NOT EXISTS idx_posts_group_name ON public.posts USING btree (group_name); -- @@ -1023,7 +1499,7 @@ CREATE INDEX idx_posts_group_name ON public.posts USING btree (group_name); -- Name: idx_posts_group_name_trgm; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_posts_group_name_trgm ON public.posts USING gin (group_name extensions.gin_trgm_ops); +CREATE INDEX IF NOT EXISTS idx_posts_group_name_trgm ON public.posts USING gin (group_name extensions.gin_trgm_ops); -- @@ -1031,7 +1507,7 @@ CREATE INDEX idx_posts_group_name_trgm ON public.posts USING gin (group_name ext -- Name: idx_posts_parent_post_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_posts_parent_post_id ON public.posts USING btree (parent_post_id); +CREATE INDEX IF NOT EXISTS idx_posts_parent_post_id ON public.posts USING btree (parent_post_id); -- @@ -1039,7 +1515,7 @@ CREATE INDEX idx_posts_parent_post_id ON public.posts USING btree (parent_post_i -- Name: idx_posts_post_type; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_posts_post_type ON public.posts USING btree (post_type); +CREATE INDEX IF NOT EXISTS idx_posts_post_type ON public.posts USING btree (post_type); -- @@ -1047,7 +1523,7 @@ CREATE INDEX idx_posts_post_type ON public.posts USING btree (post_type); -- Name: idx_posts_status; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_posts_status ON public.posts USING btree (status); +CREATE INDEX IF NOT EXISTS idx_posts_status ON public.posts USING btree (status); -- @@ -1055,7 +1531,7 @@ CREATE INDEX idx_posts_status ON public.posts USING btree (status); -- Name: idx_posts_trending_active; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_posts_trending_active ON public.posts USING btree (trending_score DESC NULLS LAST, created_at DESC) WHERE (((status)::text = 'active'::text) AND ((post_type IS NULL) OR ((post_type)::text <> 'try'::text))); +CREATE INDEX IF NOT EXISTS idx_posts_trending_active ON public.posts USING btree (trending_score DESC NULLS LAST, created_at DESC) WHERE (((status)::text = 'active'::text) AND ((post_type IS NULL) OR ((post_type)::text <> 'try'::text))); -- @@ -1063,7 +1539,7 @@ CREATE INDEX idx_posts_trending_active ON public.posts USING btree (trending_sco -- Name: idx_posts_trending_score; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_posts_trending_score ON public.posts USING btree (trending_score); +CREATE INDEX IF NOT EXISTS idx_posts_trending_score ON public.posts USING btree (trending_score); -- @@ -1071,7 +1547,7 @@ CREATE INDEX idx_posts_trending_score ON public.posts USING btree (trending_scor -- Name: idx_posts_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_posts_user_id ON public.posts USING btree (user_id); +CREATE INDEX IF NOT EXISTS idx_posts_user_id ON public.posts USING btree (user_id); -- @@ -1079,7 +1555,7 @@ CREATE INDEX idx_posts_user_id ON public.posts USING btree (user_id); -- Name: idx_processed_batches_created_at; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_processed_batches_created_at ON public.processed_batches USING btree (created_at); +CREATE INDEX IF NOT EXISTS idx_processed_batches_created_at ON public.processed_batches USING btree (created_at); -- @@ -1087,7 +1563,7 @@ CREATE INDEX idx_processed_batches_created_at ON public.processed_batches USING -- Name: idx_saved_posts_post_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_saved_posts_post_id ON public.saved_posts USING btree (post_id); +CREATE INDEX IF NOT EXISTS idx_saved_posts_post_id ON public.saved_posts USING btree (post_id); -- @@ -1095,7 +1571,7 @@ CREATE INDEX idx_saved_posts_post_id ON public.saved_posts USING btree (post_id) -- Name: idx_saved_posts_post_user_unique; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX idx_saved_posts_post_user_unique ON public.saved_posts USING btree (post_id, user_id); +CREATE UNIQUE INDEX IF NOT EXISTS idx_saved_posts_post_user_unique ON public.saved_posts USING btree (post_id, user_id); -- @@ -1103,7 +1579,7 @@ CREATE UNIQUE INDEX idx_saved_posts_post_user_unique ON public.saved_posts USING -- Name: idx_saved_posts_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_saved_posts_user_id ON public.saved_posts USING btree (user_id); +CREATE INDEX IF NOT EXISTS idx_saved_posts_user_id ON public.saved_posts USING btree (user_id); -- @@ -1111,7 +1587,7 @@ CREATE INDEX idx_saved_posts_user_id ON public.saved_posts USING btree (user_id) -- Name: idx_search_logs_created_at; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_search_logs_created_at ON public.search_logs USING btree (created_at); +CREATE INDEX IF NOT EXISTS idx_search_logs_created_at ON public.search_logs USING btree (created_at); -- @@ -1119,7 +1595,7 @@ CREATE INDEX idx_search_logs_created_at ON public.search_logs USING btree (creat -- Name: idx_search_logs_query; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_search_logs_query ON public.search_logs USING btree (query); +CREATE INDEX IF NOT EXISTS idx_search_logs_query ON public.search_logs USING btree (query); -- @@ -1127,7 +1603,7 @@ CREATE INDEX idx_search_logs_query ON public.search_logs USING btree (query); -- Name: idx_search_logs_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_search_logs_user_id ON public.search_logs USING btree (user_id); +CREATE INDEX IF NOT EXISTS idx_search_logs_user_id ON public.search_logs USING btree (user_id); -- @@ -1135,7 +1611,7 @@ CREATE INDEX idx_search_logs_user_id ON public.search_logs USING btree (user_id) -- Name: idx_settlements_created_at; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_settlements_created_at ON public.settlements USING btree (created_at); +CREATE INDEX IF NOT EXISTS idx_settlements_created_at ON public.settlements USING btree (created_at); -- @@ -1143,7 +1619,7 @@ CREATE INDEX idx_settlements_created_at ON public.settlements USING btree (creat -- Name: idx_settlements_status; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_settlements_status ON public.settlements USING btree (status); +CREATE INDEX IF NOT EXISTS idx_settlements_status ON public.settlements USING btree (status); -- @@ -1151,7 +1627,7 @@ CREATE INDEX idx_settlements_status ON public.settlements USING btree (status); -- Name: idx_settlements_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_settlements_user_id ON public.settlements USING btree (user_id); +CREATE INDEX IF NOT EXISTS idx_settlements_user_id ON public.settlements USING btree (user_id); -- @@ -1159,7 +1635,7 @@ CREATE INDEX idx_settlements_user_id ON public.settlements USING btree (user_id) -- Name: idx_solutions_active_spot_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_solutions_active_spot_id ON public.solutions USING btree (spot_id) WHERE ((status)::text = 'active'::text); +CREATE INDEX IF NOT EXISTS idx_solutions_active_spot_id ON public.solutions USING btree (spot_id) WHERE ((status)::text = 'active'::text); -- @@ -1167,7 +1643,7 @@ CREATE INDEX idx_solutions_active_spot_id ON public.solutions USING btree (spot_ -- Name: idx_solutions_brand_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_solutions_brand_id ON public.solutions USING btree (brand_id); +CREATE INDEX IF NOT EXISTS idx_solutions_brand_id ON public.solutions USING btree (brand_id); -- @@ -1175,7 +1651,7 @@ CREATE INDEX idx_solutions_brand_id ON public.solutions USING btree (brand_id); -- Name: idx_solutions_is_adopted; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_solutions_is_adopted ON public.solutions USING btree (is_adopted); +CREATE INDEX IF NOT EXISTS idx_solutions_is_adopted ON public.solutions USING btree (is_adopted); -- @@ -1183,7 +1659,7 @@ CREATE INDEX idx_solutions_is_adopted ON public.solutions USING btree (is_adopte -- Name: idx_solutions_is_verified; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_solutions_is_verified ON public.solutions USING btree (is_verified); +CREATE INDEX IF NOT EXISTS idx_solutions_is_verified ON public.solutions USING btree (is_verified); -- @@ -1191,7 +1667,7 @@ CREATE INDEX idx_solutions_is_verified ON public.solutions USING btree (is_verif -- Name: idx_solutions_match_type; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_solutions_match_type ON public.solutions USING btree (match_type); +CREATE INDEX IF NOT EXISTS idx_solutions_match_type ON public.solutions USING btree (match_type); -- @@ -1199,7 +1675,7 @@ CREATE INDEX idx_solutions_match_type ON public.solutions USING btree (match_typ -- Name: idx_solutions_spot_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_solutions_spot_id ON public.solutions USING btree (spot_id); +CREATE INDEX IF NOT EXISTS idx_solutions_spot_id ON public.solutions USING btree (spot_id); -- @@ -1207,7 +1683,7 @@ CREATE INDEX idx_solutions_spot_id ON public.solutions USING btree (spot_id); -- Name: idx_solutions_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_solutions_user_id ON public.solutions USING btree (user_id); +CREATE INDEX IF NOT EXISTS idx_solutions_user_id ON public.solutions USING btree (user_id); -- @@ -1215,7 +1691,7 @@ CREATE INDEX idx_solutions_user_id ON public.solutions USING btree (user_id); -- Name: idx_spots_post_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_spots_post_id ON public.spots USING btree (post_id); +CREATE INDEX IF NOT EXISTS idx_spots_post_id ON public.spots USING btree (post_id); -- @@ -1223,7 +1699,7 @@ CREATE INDEX idx_spots_post_id ON public.spots USING btree (post_id); -- Name: idx_spots_status; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_spots_status ON public.spots USING btree (status); +CREATE INDEX IF NOT EXISTS idx_spots_status ON public.spots USING btree (status); -- @@ -1231,7 +1707,7 @@ CREATE INDEX idx_spots_status ON public.spots USING btree (status); -- Name: idx_spots_subcategory_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_spots_subcategory_id ON public.spots USING btree (subcategory_id); +CREATE INDEX IF NOT EXISTS idx_spots_subcategory_id ON public.spots USING btree (subcategory_id); -- @@ -1239,7 +1715,7 @@ CREATE INDEX idx_spots_subcategory_id ON public.spots USING btree (subcategory_i -- Name: idx_subcategories_category_code_unique; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX idx_subcategories_category_code_unique ON public.subcategories USING btree (category_id, code); +CREATE UNIQUE INDEX IF NOT EXISTS idx_subcategories_category_code_unique ON public.subcategories USING btree (category_id, code); -- @@ -1247,7 +1723,7 @@ CREATE UNIQUE INDEX idx_subcategories_category_code_unique ON public.subcategori -- Name: idx_subcategories_category_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_subcategories_category_id ON public.subcategories USING btree (category_id); +CREATE INDEX IF NOT EXISTS idx_subcategories_category_id ON public.subcategories USING btree (category_id); -- @@ -1255,7 +1731,7 @@ CREATE INDEX idx_subcategories_category_id ON public.subcategories USING btree ( -- Name: idx_subcategories_display_order; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_subcategories_display_order ON public.subcategories USING btree (display_order); +CREATE INDEX IF NOT EXISTS idx_subcategories_display_order ON public.subcategories USING btree (display_order); -- @@ -1263,7 +1739,7 @@ CREATE INDEX idx_subcategories_display_order ON public.subcategories USING btree -- Name: idx_subcategories_is_active; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_subcategories_is_active ON public.subcategories USING btree (is_active); +CREATE INDEX IF NOT EXISTS idx_subcategories_is_active ON public.subcategories USING btree (is_active); -- @@ -1271,7 +1747,7 @@ CREATE INDEX idx_subcategories_is_active ON public.subcategories USING btree (is -- Name: idx_synonyms_canonical; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_synonyms_canonical ON public.synonyms USING btree (canonical); +CREATE INDEX IF NOT EXISTS idx_synonyms_canonical ON public.synonyms USING btree (canonical); -- @@ -1279,7 +1755,7 @@ CREATE INDEX idx_synonyms_canonical ON public.synonyms USING btree (canonical); -- Name: idx_synonyms_is_active; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_synonyms_is_active ON public.synonyms USING btree (is_active); +CREATE INDEX IF NOT EXISTS idx_synonyms_is_active ON public.synonyms USING btree (is_active); -- @@ -1287,7 +1763,7 @@ CREATE INDEX idx_synonyms_is_active ON public.synonyms USING btree (is_active); -- Name: idx_synonyms_type; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_synonyms_type ON public.synonyms USING btree (type); +CREATE INDEX IF NOT EXISTS idx_synonyms_type ON public.synonyms USING btree (type); -- @@ -1295,7 +1771,7 @@ CREATE INDEX idx_synonyms_type ON public.synonyms USING btree (type); -- Name: idx_try_spot_tags_spot_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_try_spot_tags_spot_id ON public.try_spot_tags USING btree (spot_id); +CREATE INDEX IF NOT EXISTS idx_try_spot_tags_spot_id ON public.try_spot_tags USING btree (spot_id); -- @@ -1303,7 +1779,7 @@ CREATE INDEX idx_try_spot_tags_spot_id ON public.try_spot_tags USING btree (spot -- Name: idx_try_spot_tags_try_post_spot_unique; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX idx_try_spot_tags_try_post_spot_unique ON public.try_spot_tags USING btree (try_post_id, spot_id); +CREATE UNIQUE INDEX IF NOT EXISTS idx_try_spot_tags_try_post_spot_unique ON public.try_spot_tags USING btree (try_post_id, spot_id); -- @@ -1311,7 +1787,7 @@ CREATE UNIQUE INDEX idx_try_spot_tags_try_post_spot_unique ON public.try_spot_ta -- Name: idx_user_badges_badge_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_user_badges_badge_id ON public.user_badges USING btree (badge_id); +CREATE INDEX IF NOT EXISTS idx_user_badges_badge_id ON public.user_badges USING btree (badge_id); -- @@ -1319,7 +1795,7 @@ CREATE INDEX idx_user_badges_badge_id ON public.user_badges USING btree (badge_i -- Name: idx_user_badges_earned_at; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_user_badges_earned_at ON public.user_badges USING btree (earned_at); +CREATE INDEX IF NOT EXISTS idx_user_badges_earned_at ON public.user_badges USING btree (earned_at); -- @@ -1327,7 +1803,7 @@ CREATE INDEX idx_user_badges_earned_at ON public.user_badges USING btree (earned -- Name: idx_user_badges_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_user_badges_user_id ON public.user_badges USING btree (user_id); +CREATE INDEX IF NOT EXISTS idx_user_badges_user_id ON public.user_badges USING btree (user_id); -- @@ -1335,7 +1811,7 @@ CREATE INDEX idx_user_badges_user_id ON public.user_badges USING btree (user_id) -- Name: idx_user_collections_user_magazine; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX idx_user_collections_user_magazine ON public.user_collections USING btree (user_id, magazine_id); +CREATE UNIQUE INDEX IF NOT EXISTS idx_user_collections_user_magazine ON public.user_collections USING btree (user_id, magazine_id); -- @@ -1343,7 +1819,7 @@ CREATE UNIQUE INDEX idx_user_collections_user_magazine ON public.user_collection -- Name: idx_user_events_created_at; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_user_events_created_at ON public.user_events USING btree (created_at DESC); +CREATE INDEX IF NOT EXISTS idx_user_events_created_at ON public.user_events USING btree (created_at DESC); -- @@ -1351,7 +1827,7 @@ CREATE INDEX idx_user_events_created_at ON public.user_events USING btree (creat -- Name: idx_user_events_event_type; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_user_events_event_type ON public.user_events USING btree (event_type); +CREATE INDEX IF NOT EXISTS idx_user_events_event_type ON public.user_events USING btree (event_type); -- @@ -1359,7 +1835,7 @@ CREATE INDEX idx_user_events_event_type ON public.user_events USING btree (event -- Name: idx_user_events_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_user_events_user_id ON public.user_events USING btree (user_id); +CREATE INDEX IF NOT EXISTS idx_user_events_user_id ON public.user_events USING btree (user_id); -- @@ -1367,7 +1843,7 @@ CREATE INDEX idx_user_events_user_id ON public.user_events USING btree (user_id) -- Name: idx_user_follows_follower_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_user_follows_follower_id ON public.user_follows USING btree (follower_id); +CREATE INDEX IF NOT EXISTS idx_user_follows_follower_id ON public.user_follows USING btree (follower_id); -- @@ -1375,7 +1851,7 @@ CREATE INDEX idx_user_follows_follower_id ON public.user_follows USING btree (fo -- Name: idx_user_follows_following_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_user_follows_following_id ON public.user_follows USING btree (following_id); +CREATE INDEX IF NOT EXISTS idx_user_follows_following_id ON public.user_follows USING btree (following_id); -- @@ -1383,7 +1859,7 @@ CREATE INDEX idx_user_follows_following_id ON public.user_follows USING btree (f -- Name: idx_user_magazines_created_by; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_user_magazines_created_by ON public.user_magazines USING btree (created_by); +CREATE INDEX IF NOT EXISTS idx_user_magazines_created_by ON public.user_magazines USING btree (created_by); -- @@ -1391,7 +1867,7 @@ CREATE INDEX idx_user_magazines_created_by ON public.user_magazines USING btree -- Name: idx_user_magazines_type; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_user_magazines_type ON public.user_magazines USING btree (magazine_type); +CREATE INDEX IF NOT EXISTS idx_user_magazines_type ON public.user_magazines USING btree (magazine_type); -- @@ -1399,7 +1875,7 @@ CREATE INDEX idx_user_magazines_type ON public.user_magazines USING btree (magaz -- Name: idx_user_social_accounts_user_provider; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX idx_user_social_accounts_user_provider ON public.user_social_accounts USING btree (user_id, provider); +CREATE UNIQUE INDEX IF NOT EXISTS idx_user_social_accounts_user_provider ON public.user_social_accounts USING btree (user_id, provider); -- @@ -1407,7 +1883,7 @@ CREATE UNIQUE INDEX idx_user_social_accounts_user_provider ON public.user_social -- Name: idx_user_tryon_history_created_at; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_user_tryon_history_created_at ON public.user_tryon_history USING btree (user_id, created_at DESC); +CREATE INDEX IF NOT EXISTS idx_user_tryon_history_created_at ON public.user_tryon_history USING btree (user_id, created_at DESC); -- @@ -1415,7 +1891,7 @@ CREATE INDEX idx_user_tryon_history_created_at ON public.user_tryon_history USIN -- Name: idx_user_tryon_history_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_user_tryon_history_user_id ON public.user_tryon_history USING btree (user_id); +CREATE INDEX IF NOT EXISTS idx_user_tryon_history_user_id ON public.user_tryon_history USING btree (user_id); -- @@ -1423,7 +1899,7 @@ CREATE INDEX idx_user_tryon_history_user_id ON public.user_tryon_history USING b -- Name: idx_users_email; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_users_email ON public.users USING btree (email); +CREATE INDEX IF NOT EXISTS idx_users_email ON public.users USING btree (email); -- @@ -1431,7 +1907,7 @@ CREATE INDEX idx_users_email ON public.users USING btree (email); -- Name: idx_users_rank; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_users_rank ON public.users USING btree (rank); +CREATE INDEX IF NOT EXISTS idx_users_rank ON public.users USING btree (rank); -- @@ -1439,7 +1915,7 @@ CREATE INDEX idx_users_rank ON public.users USING btree (rank); -- Name: idx_users_username; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_users_username ON public.users USING btree (username); +CREATE INDEX IF NOT EXISTS idx_users_username ON public.users USING btree (username); -- @@ -1447,7 +1923,7 @@ CREATE INDEX idx_users_username ON public.users USING btree (username); -- Name: idx_view_logs_created_at; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_view_logs_created_at ON public.view_logs USING btree (created_at); +CREATE INDEX IF NOT EXISTS idx_view_logs_created_at ON public.view_logs USING btree (created_at); -- @@ -1455,7 +1931,7 @@ CREATE INDEX idx_view_logs_created_at ON public.view_logs USING btree (created_a -- Name: idx_view_logs_reference; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_view_logs_reference ON public.view_logs USING btree (reference_type, reference_id); +CREATE INDEX IF NOT EXISTS idx_view_logs_reference ON public.view_logs USING btree (reference_type, reference_id); -- @@ -1463,7 +1939,7 @@ CREATE INDEX idx_view_logs_reference ON public.view_logs USING btree (reference_ -- Name: idx_view_logs_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_view_logs_user_id ON public.view_logs USING btree (user_id); +CREATE INDEX IF NOT EXISTS idx_view_logs_user_id ON public.view_logs USING btree (user_id); -- @@ -1471,7 +1947,7 @@ CREATE INDEX idx_view_logs_user_id ON public.view_logs USING btree (user_id); -- Name: idx_view_logs_user_reference_created; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_view_logs_user_reference_created ON public.view_logs USING btree (user_id, reference_type, reference_id, created_at); +CREATE INDEX IF NOT EXISTS idx_view_logs_user_reference_created ON public.view_logs USING btree (user_id, reference_type, reference_id, created_at); -- @@ -1479,7 +1955,7 @@ CREATE INDEX idx_view_logs_user_reference_created ON public.view_logs USING btre -- Name: idx_votes_solution_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_votes_solution_id ON public.votes USING btree (solution_id); +CREATE INDEX IF NOT EXISTS idx_votes_solution_id ON public.votes USING btree (solution_id); -- @@ -1487,7 +1963,7 @@ CREATE INDEX idx_votes_solution_id ON public.votes USING btree (solution_id); -- Name: idx_votes_solution_user_unique; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX idx_votes_solution_user_unique ON public.votes USING btree (solution_id, user_id); +CREATE UNIQUE INDEX IF NOT EXISTS idx_votes_solution_user_unique ON public.votes USING btree (solution_id, user_id); -- @@ -1495,7 +1971,7 @@ CREATE UNIQUE INDEX idx_votes_solution_user_unique ON public.votes USING btree ( -- Name: idx_votes_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX idx_votes_user_id ON public.votes USING btree (user_id); +CREATE INDEX IF NOT EXISTS idx_votes_user_id ON public.votes USING btree (user_id); -- @@ -1503,7 +1979,7 @@ CREATE INDEX idx_votes_user_id ON public.votes USING btree (user_id); -- Name: post_magazines_status_idx; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX post_magazines_status_idx ON public.post_magazines USING btree (status) WHERE ((status)::text = ANY ((ARRAY['pending'::character varying, 'draft'::character varying])::text[])); +CREATE INDEX IF NOT EXISTS post_magazines_status_idx ON public.post_magazines USING btree (status) WHERE ((status)::text = ANY ((ARRAY['pending'::character varying, 'draft'::character varying])::text[])); -- @@ -1511,7 +1987,7 @@ CREATE INDEX post_magazines_status_idx ON public.post_magazines USING btree (sta -- Name: idx_audit_log_admin; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_audit_log_admin ON warehouse.admin_audit_log USING btree (admin_user_id); +CREATE INDEX IF NOT EXISTS idx_audit_log_admin ON warehouse.admin_audit_log USING btree (admin_user_id); -- @@ -1519,7 +1995,7 @@ CREATE INDEX idx_audit_log_admin ON warehouse.admin_audit_log USING btree (admin -- Name: idx_audit_log_created; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_audit_log_created ON warehouse.admin_audit_log USING btree (created_at DESC); +CREATE INDEX IF NOT EXISTS idx_audit_log_created ON warehouse.admin_audit_log USING btree (created_at DESC); -- @@ -1527,7 +2003,7 @@ CREATE INDEX idx_audit_log_created ON warehouse.admin_audit_log USING btree (cre -- Name: idx_audit_log_target; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_audit_log_target ON warehouse.admin_audit_log USING btree (target_table, target_id); +CREATE INDEX IF NOT EXISTS idx_audit_log_target ON warehouse.admin_audit_log USING btree (target_table, target_id); -- @@ -1535,7 +2011,7 @@ CREATE INDEX idx_audit_log_target ON warehouse.admin_audit_log USING btree (targ -- Name: idx_warehouse_group_members_artist_id; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_group_members_artist_id ON warehouse.group_members USING btree (artist_id); +CREATE INDEX IF NOT EXISTS idx_warehouse_group_members_artist_id ON warehouse.group_members USING btree (artist_id); -- @@ -1543,7 +2019,7 @@ CREATE INDEX idx_warehouse_group_members_artist_id ON warehouse.group_members US -- Name: idx_warehouse_group_members_is_active; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_group_members_is_active ON warehouse.group_members USING btree (is_active); +CREATE INDEX IF NOT EXISTS idx_warehouse_group_members_is_active ON warehouse.group_members USING btree (is_active); -- @@ -1551,7 +2027,7 @@ CREATE INDEX idx_warehouse_group_members_is_active ON warehouse.group_members US -- Name: idx_warehouse_images_post_id; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_images_post_id ON warehouse.images USING btree (post_id); +CREATE INDEX IF NOT EXISTS idx_warehouse_images_post_id ON warehouse.images USING btree (post_id); -- @@ -1559,7 +2035,7 @@ CREATE INDEX idx_warehouse_images_post_id ON warehouse.images USING btree (post_ -- Name: idx_warehouse_images_with_items; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_images_with_items ON warehouse.images USING btree (with_items); +CREATE INDEX IF NOT EXISTS idx_warehouse_images_with_items ON warehouse.images USING btree (with_items); -- @@ -1567,7 +2043,7 @@ CREATE INDEX idx_warehouse_images_with_items ON warehouse.images USING btree (wi -- Name: idx_warehouse_instagram_accounts_active; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_instagram_accounts_active ON warehouse.instagram_accounts USING btree (is_active); +CREATE INDEX IF NOT EXISTS idx_warehouse_instagram_accounts_active ON warehouse.instagram_accounts USING btree (is_active); -- @@ -1575,7 +2051,7 @@ CREATE INDEX idx_warehouse_instagram_accounts_active ON warehouse.instagram_acco -- Name: idx_warehouse_instagram_accounts_artist_id; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_instagram_accounts_artist_id ON warehouse.instagram_accounts USING btree (artist_id) WHERE (artist_id IS NOT NULL); +CREATE INDEX IF NOT EXISTS idx_warehouse_instagram_accounts_artist_id ON warehouse.instagram_accounts USING btree (artist_id) WHERE (artist_id IS NOT NULL); -- @@ -1583,7 +2059,7 @@ CREATE INDEX idx_warehouse_instagram_accounts_artist_id ON warehouse.instagram_a -- Name: idx_warehouse_instagram_accounts_brand_id; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_instagram_accounts_brand_id ON warehouse.instagram_accounts USING btree (brand_id) WHERE (brand_id IS NOT NULL); +CREATE INDEX IF NOT EXISTS idx_warehouse_instagram_accounts_brand_id ON warehouse.instagram_accounts USING btree (brand_id) WHERE (brand_id IS NOT NULL); -- @@ -1591,7 +2067,7 @@ CREATE INDEX idx_warehouse_instagram_accounts_brand_id ON warehouse.instagram_ac -- Name: idx_warehouse_instagram_accounts_group_id; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_instagram_accounts_group_id ON warehouse.instagram_accounts USING btree (group_id); +CREATE INDEX IF NOT EXISTS idx_warehouse_instagram_accounts_group_id ON warehouse.instagram_accounts USING btree (group_id); -- @@ -1599,7 +2075,7 @@ CREATE INDEX idx_warehouse_instagram_accounts_group_id ON warehouse.instagram_ac -- Name: idx_warehouse_instagram_accounts_type; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_instagram_accounts_type ON warehouse.instagram_accounts USING btree (account_type); +CREATE INDEX IF NOT EXISTS idx_warehouse_instagram_accounts_type ON warehouse.instagram_accounts USING btree (account_type); -- @@ -1607,7 +2083,7 @@ CREATE INDEX idx_warehouse_instagram_accounts_type ON warehouse.instagram_accoun -- Name: idx_warehouse_posts_account_id; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_posts_account_id ON warehouse.posts USING btree (account_id); +CREATE INDEX IF NOT EXISTS idx_warehouse_posts_account_id ON warehouse.posts USING btree (account_id); -- @@ -1615,7 +2091,7 @@ CREATE INDEX idx_warehouse_posts_account_id ON warehouse.posts USING btree (acco -- Name: idx_warehouse_posts_posted_at; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_posts_posted_at ON warehouse.posts USING btree (posted_at); +CREATE INDEX IF NOT EXISTS idx_warehouse_posts_posted_at ON warehouse.posts USING btree (posted_at); -- @@ -1623,7 +2099,7 @@ CREATE INDEX idx_warehouse_posts_posted_at ON warehouse.posts USING btree (poste -- Name: idx_warehouse_posts_tagged_account_ids; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_posts_tagged_account_ids ON warehouse.posts USING gin (tagged_account_ids); +CREATE INDEX IF NOT EXISTS idx_warehouse_posts_tagged_account_ids ON warehouse.posts USING gin (tagged_account_ids); -- @@ -1631,7 +2107,7 @@ CREATE INDEX idx_warehouse_posts_tagged_account_ids ON warehouse.posts USING gin -- Name: idx_warehouse_seed_asset_seed_post_id; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_seed_asset_seed_post_id ON warehouse.seed_asset USING btree (seed_post_id); +CREATE INDEX IF NOT EXISTS idx_warehouse_seed_asset_seed_post_id ON warehouse.seed_asset USING btree (seed_post_id); -- @@ -1639,7 +2115,7 @@ CREATE INDEX idx_warehouse_seed_asset_seed_post_id ON warehouse.seed_asset USING -- Name: idx_warehouse_seed_posts_source_image_id; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_seed_posts_source_image_id ON warehouse.seed_posts USING btree (source_image_id); +CREATE INDEX IF NOT EXISTS idx_warehouse_seed_posts_source_image_id ON warehouse.seed_posts USING btree (source_image_id); -- @@ -1647,7 +2123,7 @@ CREATE INDEX idx_warehouse_seed_posts_source_image_id ON warehouse.seed_posts US -- Name: idx_warehouse_seed_posts_source_post_id; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_seed_posts_source_post_id ON warehouse.seed_posts USING btree (source_post_id); +CREATE INDEX IF NOT EXISTS idx_warehouse_seed_posts_source_post_id ON warehouse.seed_posts USING btree (source_post_id); -- @@ -1655,7 +2131,7 @@ CREATE INDEX idx_warehouse_seed_posts_source_post_id ON warehouse.seed_posts USI -- Name: idx_warehouse_seed_posts_status; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_seed_posts_status ON warehouse.seed_posts USING btree (status); +CREATE INDEX IF NOT EXISTS idx_warehouse_seed_posts_status ON warehouse.seed_posts USING btree (status); -- @@ -1663,7 +2139,7 @@ CREATE INDEX idx_warehouse_seed_posts_status ON warehouse.seed_posts USING btree -- Name: idx_warehouse_seed_spots_request_order; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_seed_spots_request_order ON warehouse.seed_spots USING btree (request_order); +CREATE INDEX IF NOT EXISTS idx_warehouse_seed_spots_request_order ON warehouse.seed_spots USING btree (request_order); -- @@ -1671,7 +2147,7 @@ CREATE INDEX idx_warehouse_seed_spots_request_order ON warehouse.seed_spots USIN -- Name: idx_warehouse_seed_spots_seed_post_id; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_seed_spots_seed_post_id ON warehouse.seed_spots USING btree (seed_post_id); +CREATE INDEX IF NOT EXISTS idx_warehouse_seed_spots_seed_post_id ON warehouse.seed_spots USING btree (seed_post_id); -- @@ -1679,7 +2155,7 @@ CREATE INDEX idx_warehouse_seed_spots_seed_post_id ON warehouse.seed_spots USING -- Name: idx_warehouse_seed_spots_status; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX idx_warehouse_seed_spots_status ON warehouse.seed_spots USING btree (status); +CREATE INDEX IF NOT EXISTS idx_warehouse_seed_spots_status ON warehouse.seed_spots USING btree (status); -- @@ -1687,7 +2163,7 @@ CREATE INDEX idx_warehouse_seed_spots_status ON warehouse.seed_spots USING btree -- Name: raw_post_sources_active_platform_idx; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX raw_post_sources_active_platform_idx ON warehouse.raw_post_sources USING btree (is_active, platform); +CREATE INDEX IF NOT EXISTS raw_post_sources_active_platform_idx ON warehouse.raw_post_sources USING btree (is_active, platform); -- @@ -1695,7 +2171,7 @@ CREATE INDEX raw_post_sources_active_platform_idx ON warehouse.raw_post_sources -- Name: raw_post_sources_due_idx; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX raw_post_sources_due_idx ON warehouse.raw_post_sources USING btree (last_enqueued_at) WHERE (is_active = true); +CREATE INDEX IF NOT EXISTS raw_post_sources_due_idx ON warehouse.raw_post_sources USING btree (last_enqueued_at) WHERE (is_active = true); -- @@ -1703,7 +2179,7 @@ CREATE INDEX raw_post_sources_due_idx ON warehouse.raw_post_sources USING btree -- Name: raw_posts_parse_status_idx; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX raw_posts_parse_status_idx ON warehouse.raw_posts USING btree (parse_status, created_at); +CREATE INDEX IF NOT EXISTS raw_posts_parse_status_idx ON warehouse.raw_posts USING btree (parse_status, created_at); -- @@ -1711,7 +2187,7 @@ CREATE INDEX raw_posts_parse_status_idx ON warehouse.raw_posts USING btree (pars -- Name: raw_posts_platform_idx; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX raw_posts_platform_idx ON warehouse.raw_posts USING btree (platform); +CREATE INDEX IF NOT EXISTS raw_posts_platform_idx ON warehouse.raw_posts USING btree (platform); -- @@ -1719,7 +2195,7 @@ CREATE INDEX raw_posts_platform_idx ON warehouse.raw_posts USING btree (platform -- Name: raw_posts_source_idx; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE INDEX raw_posts_source_idx ON warehouse.raw_posts USING btree (source_id); +CREATE INDEX IF NOT EXISTS raw_posts_source_idx ON warehouse.raw_posts USING btree (source_id); -- @@ -1727,7 +2203,7 @@ CREATE INDEX raw_posts_source_idx ON warehouse.raw_posts USING btree (source_id) -- Name: uq_warehouse_seed_posts_source_post_image; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE UNIQUE INDEX uq_warehouse_seed_posts_source_post_image ON warehouse.seed_posts USING btree (source_post_id, source_image_id) WHERE ((source_post_id IS NOT NULL) AND (source_image_id IS NOT NULL)); +CREATE UNIQUE INDEX IF NOT EXISTS uq_warehouse_seed_posts_source_post_image ON warehouse.seed_posts USING btree (source_post_id, source_image_id) WHERE ((source_post_id IS NOT NULL) AND (source_image_id IS NOT NULL)); -- @@ -1735,7 +2211,7 @@ CREATE UNIQUE INDEX uq_warehouse_seed_posts_source_post_image ON warehouse.seed_ -- Name: warehouse_artists_primary_ig_unique; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE UNIQUE INDEX warehouse_artists_primary_ig_unique ON warehouse.artists USING btree (primary_instagram_account_id) WHERE (primary_instagram_account_id IS NOT NULL); +CREATE UNIQUE INDEX IF NOT EXISTS warehouse_artists_primary_ig_unique ON warehouse.artists USING btree (primary_instagram_account_id) WHERE (primary_instagram_account_id IS NOT NULL); -- @@ -1743,7 +2219,7 @@ CREATE UNIQUE INDEX warehouse_artists_primary_ig_unique ON warehouse.artists USI -- Name: warehouse_brands_primary_ig_unique; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE UNIQUE INDEX warehouse_brands_primary_ig_unique ON warehouse.brands USING btree (primary_instagram_account_id) WHERE (primary_instagram_account_id IS NOT NULL); +CREATE UNIQUE INDEX IF NOT EXISTS warehouse_brands_primary_ig_unique ON warehouse.brands USING btree (primary_instagram_account_id) WHERE (primary_instagram_account_id IS NOT NULL); -- @@ -1751,7 +2227,7 @@ CREATE UNIQUE INDEX warehouse_brands_primary_ig_unique ON warehouse.brands USING -- Name: warehouse_groups_primary_ig_unique; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE UNIQUE INDEX warehouse_groups_primary_ig_unique ON warehouse.groups USING btree (primary_instagram_account_id) WHERE (primary_instagram_account_id IS NOT NULL); +CREATE UNIQUE INDEX IF NOT EXISTS warehouse_groups_primary_ig_unique ON warehouse.groups USING btree (primary_instagram_account_id) WHERE (primary_instagram_account_id IS NOT NULL); -- @@ -1759,7 +2235,7 @@ CREATE UNIQUE INDEX warehouse_groups_primary_ig_unique ON warehouse.groups USING -- Name: warehouse_ig_one_primary_per_artist; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE UNIQUE INDEX warehouse_ig_one_primary_per_artist ON warehouse.instagram_accounts USING btree (artist_id) WHERE ((artist_id IS NOT NULL) AND (entity_ig_role = 'primary'::warehouse.entity_ig_role)); +CREATE UNIQUE INDEX IF NOT EXISTS warehouse_ig_one_primary_per_artist ON warehouse.instagram_accounts USING btree (artist_id) WHERE ((artist_id IS NOT NULL) AND (entity_ig_role = 'primary'::warehouse.entity_ig_role)); -- @@ -1767,7 +2243,7 @@ CREATE UNIQUE INDEX warehouse_ig_one_primary_per_artist ON warehouse.instagram_a -- Name: warehouse_ig_one_primary_per_brand; Type: INDEX; Schema: warehouse; Owner: - -- -CREATE UNIQUE INDEX warehouse_ig_one_primary_per_brand ON warehouse.instagram_accounts USING btree (brand_id) WHERE ((brand_id IS NOT NULL) AND (entity_ig_role = 'primary'::warehouse.entity_ig_role)); +CREATE UNIQUE INDEX IF NOT EXISTS warehouse_ig_one_primary_per_brand ON warehouse.instagram_accounts USING btree (brand_id) WHERE ((brand_id IS NOT NULL) AND (entity_ig_role = 'primary'::warehouse.entity_ig_role)); -- @@ -1775,8 +2251,15 @@ CREATE UNIQUE INDEX warehouse_ig_one_primary_per_brand ON warehouse.instagram_ac -- Name: agent_sessions agent_sessions_magazine_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.agent_sessions - ADD CONSTRAINT agent_sessions_magazine_id_fkey FOREIGN KEY (magazine_id) REFERENCES public.magazines(id); +DO $$ +BEGIN + ALTER TABLE ONLY public.agent_sessions + ADD CONSTRAINT agent_sessions_magazine_id_fkey FOREIGN KEY (magazine_id) REFERENCES public.magazines(id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1784,8 +2267,15 @@ ALTER TABLE ONLY public.agent_sessions -- Name: agent_sessions agent_sessions_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.agent_sessions - ADD CONSTRAINT agent_sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id); +DO $$ +BEGIN + ALTER TABLE ONLY public.agent_sessions + ADD CONSTRAINT agent_sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1793,8 +2283,15 @@ ALTER TABLE ONLY public.agent_sessions -- Name: content_reports content_reports_reporter_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.content_reports - ADD CONSTRAINT content_reports_reporter_id_fkey FOREIGN KEY (reporter_id) REFERENCES auth.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.content_reports + ADD CONSTRAINT content_reports_reporter_id_fkey FOREIGN KEY (reporter_id) REFERENCES auth.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1802,8 +2299,15 @@ ALTER TABLE ONLY public.content_reports -- Name: content_reports content_reports_reviewed_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.content_reports - ADD CONSTRAINT content_reports_reviewed_by_fkey FOREIGN KEY (reviewed_by) REFERENCES auth.users(id); +DO $$ +BEGIN + ALTER TABLE ONLY public.content_reports + ADD CONSTRAINT content_reports_reviewed_by_fkey FOREIGN KEY (reviewed_by) REFERENCES auth.users(id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1811,8 +2315,15 @@ ALTER TABLE ONLY public.content_reports -- Name: credit_transactions credit_transactions_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.credit_transactions - ADD CONSTRAINT credit_transactions_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.credit_transactions + ADD CONSTRAINT credit_transactions_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1820,8 +2331,15 @@ ALTER TABLE ONLY public.credit_transactions -- Name: decoded_picks decoded_picks_post_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.decoded_picks - ADD CONSTRAINT decoded_picks_post_id_fkey FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.decoded_picks + ADD CONSTRAINT decoded_picks_post_id_fkey FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1829,8 +2347,15 @@ ALTER TABLE ONLY public.decoded_picks -- Name: click_logs fk_click_logs_solution_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.click_logs - ADD CONSTRAINT fk_click_logs_solution_id FOREIGN KEY (solution_id) REFERENCES public.solutions(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.click_logs + ADD CONSTRAINT fk_click_logs_solution_id FOREIGN KEY (solution_id) REFERENCES public.solutions(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1838,8 +2363,15 @@ ALTER TABLE ONLY public.click_logs -- Name: click_logs fk_click_logs_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.click_logs - ADD CONSTRAINT fk_click_logs_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY public.click_logs + ADD CONSTRAINT fk_click_logs_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1847,8 +2379,15 @@ ALTER TABLE ONLY public.click_logs -- Name: comments fk_comments_parent_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.comments - ADD CONSTRAINT fk_comments_parent_id FOREIGN KEY (parent_id) REFERENCES public.comments(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.comments + ADD CONSTRAINT fk_comments_parent_id FOREIGN KEY (parent_id) REFERENCES public.comments(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1856,8 +2395,15 @@ ALTER TABLE ONLY public.comments -- Name: comments fk_comments_post_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.comments - ADD CONSTRAINT fk_comments_post_id FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.comments + ADD CONSTRAINT fk_comments_post_id FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1865,8 +2411,15 @@ ALTER TABLE ONLY public.comments -- Name: comments fk_comments_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.comments - ADD CONSTRAINT fk_comments_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.comments + ADD CONSTRAINT fk_comments_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1874,8 +2427,15 @@ ALTER TABLE ONLY public.comments -- Name: curation_posts fk_curation_posts_curation_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.curation_posts - ADD CONSTRAINT fk_curation_posts_curation_id FOREIGN KEY (curation_id) REFERENCES public.curations(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.curation_posts + ADD CONSTRAINT fk_curation_posts_curation_id FOREIGN KEY (curation_id) REFERENCES public.curations(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1883,8 +2443,15 @@ ALTER TABLE ONLY public.curation_posts -- Name: curation_posts fk_curation_posts_post_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.curation_posts - ADD CONSTRAINT fk_curation_posts_post_id FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.curation_posts + ADD CONSTRAINT fk_curation_posts_post_id FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1892,8 +2459,15 @@ ALTER TABLE ONLY public.curation_posts -- Name: earnings fk_earnings_solution_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.earnings - ADD CONSTRAINT fk_earnings_solution_id FOREIGN KEY (solution_id) REFERENCES public.solutions(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.earnings + ADD CONSTRAINT fk_earnings_solution_id FOREIGN KEY (solution_id) REFERENCES public.solutions(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1901,8 +2475,15 @@ ALTER TABLE ONLY public.earnings -- Name: earnings fk_earnings_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.earnings - ADD CONSTRAINT fk_earnings_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.earnings + ADD CONSTRAINT fk_earnings_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1910,8 +2491,15 @@ ALTER TABLE ONLY public.earnings -- Name: point_logs fk_point_logs_user; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.point_logs - ADD CONSTRAINT fk_point_logs_user FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.point_logs + ADD CONSTRAINT fk_point_logs_user FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1919,8 +2507,15 @@ ALTER TABLE ONLY public.point_logs -- Name: post_likes fk_post_likes_post_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.post_likes - ADD CONSTRAINT fk_post_likes_post_id FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.post_likes + ADD CONSTRAINT fk_post_likes_post_id FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1928,8 +2523,15 @@ ALTER TABLE ONLY public.post_likes -- Name: post_likes fk_post_likes_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.post_likes - ADD CONSTRAINT fk_post_likes_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.post_likes + ADD CONSTRAINT fk_post_likes_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1937,8 +2539,15 @@ ALTER TABLE ONLY public.post_likes -- Name: posts fk_posts_artist_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.posts - ADD CONSTRAINT fk_posts_artist_id FOREIGN KEY (artist_id) REFERENCES warehouse.artists(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY public.posts + ADD CONSTRAINT fk_posts_artist_id FOREIGN KEY (artist_id) REFERENCES warehouse.artists(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1946,8 +2555,15 @@ ALTER TABLE ONLY public.posts -- Name: posts fk_posts_group_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.posts - ADD CONSTRAINT fk_posts_group_id FOREIGN KEY (group_id) REFERENCES warehouse.groups(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY public.posts + ADD CONSTRAINT fk_posts_group_id FOREIGN KEY (group_id) REFERENCES warehouse.groups(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1955,8 +2571,15 @@ ALTER TABLE ONLY public.posts -- Name: posts fk_posts_parent_post_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.posts - ADD CONSTRAINT fk_posts_parent_post_id FOREIGN KEY (parent_post_id) REFERENCES public.posts(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY public.posts + ADD CONSTRAINT fk_posts_parent_post_id FOREIGN KEY (parent_post_id) REFERENCES public.posts(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1964,8 +2587,15 @@ ALTER TABLE ONLY public.posts -- Name: posts fk_posts_post_magazine_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.posts - ADD CONSTRAINT fk_posts_post_magazine_id FOREIGN KEY (post_magazine_id) REFERENCES public.post_magazines(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY public.posts + ADD CONSTRAINT fk_posts_post_magazine_id FOREIGN KEY (post_magazine_id) REFERENCES public.post_magazines(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1973,8 +2603,15 @@ ALTER TABLE ONLY public.posts -- Name: posts fk_posts_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.posts - ADD CONSTRAINT fk_posts_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.posts + ADD CONSTRAINT fk_posts_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1982,8 +2619,15 @@ ALTER TABLE ONLY public.posts -- Name: saved_posts fk_saved_posts_post_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.saved_posts - ADD CONSTRAINT fk_saved_posts_post_id FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.saved_posts + ADD CONSTRAINT fk_saved_posts_post_id FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -1991,8 +2635,15 @@ ALTER TABLE ONLY public.saved_posts -- Name: saved_posts fk_saved_posts_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.saved_posts - ADD CONSTRAINT fk_saved_posts_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.saved_posts + ADD CONSTRAINT fk_saved_posts_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2000,8 +2651,15 @@ ALTER TABLE ONLY public.saved_posts -- Name: search_logs fk_search_logs_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.search_logs - ADD CONSTRAINT fk_search_logs_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON UPDATE CASCADE ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY public.search_logs + ADD CONSTRAINT fk_search_logs_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON UPDATE CASCADE ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2009,8 +2667,15 @@ ALTER TABLE ONLY public.search_logs -- Name: settlements fk_settlements_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.settlements - ADD CONSTRAINT fk_settlements_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.settlements + ADD CONSTRAINT fk_settlements_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2018,8 +2683,15 @@ ALTER TABLE ONLY public.settlements -- Name: solutions fk_solutions_brand_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.solutions - ADD CONSTRAINT fk_solutions_brand_id FOREIGN KEY (brand_id) REFERENCES warehouse.brands(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY public.solutions + ADD CONSTRAINT fk_solutions_brand_id FOREIGN KEY (brand_id) REFERENCES warehouse.brands(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2027,8 +2699,15 @@ ALTER TABLE ONLY public.solutions -- Name: solutions fk_solutions_spot_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.solutions - ADD CONSTRAINT fk_solutions_spot_id FOREIGN KEY (spot_id) REFERENCES public.spots(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.solutions + ADD CONSTRAINT fk_solutions_spot_id FOREIGN KEY (spot_id) REFERENCES public.spots(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2036,8 +2715,15 @@ ALTER TABLE ONLY public.solutions -- Name: solutions fk_solutions_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.solutions - ADD CONSTRAINT fk_solutions_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.solutions + ADD CONSTRAINT fk_solutions_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2045,8 +2731,15 @@ ALTER TABLE ONLY public.solutions -- Name: spots fk_spots_post_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.spots - ADD CONSTRAINT fk_spots_post_id FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.spots + ADD CONSTRAINT fk_spots_post_id FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2054,8 +2747,15 @@ ALTER TABLE ONLY public.spots -- Name: spots fk_spots_subcategory_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.spots - ADD CONSTRAINT fk_spots_subcategory_id FOREIGN KEY (subcategory_id) REFERENCES public.subcategories(id); +DO $$ +BEGIN + ALTER TABLE ONLY public.spots + ADD CONSTRAINT fk_spots_subcategory_id FOREIGN KEY (subcategory_id) REFERENCES public.subcategories(id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2063,8 +2763,15 @@ ALTER TABLE ONLY public.spots -- Name: spots fk_spots_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.spots - ADD CONSTRAINT fk_spots_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.spots + ADD CONSTRAINT fk_spots_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2072,8 +2779,15 @@ ALTER TABLE ONLY public.spots -- Name: subcategories fk_subcategories_category_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.subcategories - ADD CONSTRAINT fk_subcategories_category_id FOREIGN KEY (category_id) REFERENCES public.categories(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.subcategories + ADD CONSTRAINT fk_subcategories_category_id FOREIGN KEY (category_id) REFERENCES public.categories(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2081,8 +2795,15 @@ ALTER TABLE ONLY public.subcategories -- Name: try_spot_tags fk_try_spot_tags_spot_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.try_spot_tags - ADD CONSTRAINT fk_try_spot_tags_spot_id FOREIGN KEY (spot_id) REFERENCES public.spots(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.try_spot_tags + ADD CONSTRAINT fk_try_spot_tags_spot_id FOREIGN KEY (spot_id) REFERENCES public.spots(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2090,8 +2811,15 @@ ALTER TABLE ONLY public.try_spot_tags -- Name: try_spot_tags fk_try_spot_tags_try_post_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.try_spot_tags - ADD CONSTRAINT fk_try_spot_tags_try_post_id FOREIGN KEY (try_post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.try_spot_tags + ADD CONSTRAINT fk_try_spot_tags_try_post_id FOREIGN KEY (try_post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2099,8 +2827,15 @@ ALTER TABLE ONLY public.try_spot_tags -- Name: user_badges fk_user_badges_badge_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_badges - ADD CONSTRAINT fk_user_badges_badge_id FOREIGN KEY (badge_id) REFERENCES public.badges(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.user_badges + ADD CONSTRAINT fk_user_badges_badge_id FOREIGN KEY (badge_id) REFERENCES public.badges(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2108,8 +2843,15 @@ ALTER TABLE ONLY public.user_badges -- Name: user_badges fk_user_badges_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_badges - ADD CONSTRAINT fk_user_badges_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.user_badges + ADD CONSTRAINT fk_user_badges_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2117,8 +2859,15 @@ ALTER TABLE ONLY public.user_badges -- Name: users fk_users_auth_users; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.users - ADD CONSTRAINT fk_users_auth_users FOREIGN KEY (id) REFERENCES auth.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.users + ADD CONSTRAINT fk_users_auth_users FOREIGN KEY (id) REFERENCES auth.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2126,8 +2875,15 @@ ALTER TABLE ONLY public.users -- Name: view_logs fk_view_logs_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.view_logs - ADD CONSTRAINT fk_view_logs_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY public.view_logs + ADD CONSTRAINT fk_view_logs_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2135,8 +2891,15 @@ ALTER TABLE ONLY public.view_logs -- Name: votes fk_votes_solution_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.votes - ADD CONSTRAINT fk_votes_solution_id FOREIGN KEY (solution_id) REFERENCES public.solutions(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.votes + ADD CONSTRAINT fk_votes_solution_id FOREIGN KEY (solution_id) REFERENCES public.solutions(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2144,8 +2907,15 @@ ALTER TABLE ONLY public.votes -- Name: votes fk_votes_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.votes - ADD CONSTRAINT fk_votes_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.votes + ADD CONSTRAINT fk_votes_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2153,8 +2923,15 @@ ALTER TABLE ONLY public.votes -- Name: magazine_posts magazine_posts_magazine_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.magazine_posts - ADD CONSTRAINT magazine_posts_magazine_id_fkey FOREIGN KEY (magazine_id) REFERENCES public.magazines(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.magazine_posts + ADD CONSTRAINT magazine_posts_magazine_id_fkey FOREIGN KEY (magazine_id) REFERENCES public.magazines(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2162,8 +2939,15 @@ ALTER TABLE ONLY public.magazine_posts -- Name: magazine_posts magazine_posts_post_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.magazine_posts - ADD CONSTRAINT magazine_posts_post_id_fkey FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.magazine_posts + ADD CONSTRAINT magazine_posts_post_id_fkey FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2171,8 +2955,15 @@ ALTER TABLE ONLY public.magazine_posts -- Name: magazines magazines_published_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.magazines - ADD CONSTRAINT magazines_published_by_fkey FOREIGN KEY (published_by) REFERENCES public.users(id); +DO $$ +BEGIN + ALTER TABLE ONLY public.magazines + ADD CONSTRAINT magazines_published_by_fkey FOREIGN KEY (published_by) REFERENCES public.users(id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2180,8 +2971,15 @@ ALTER TABLE ONLY public.magazines -- Name: magazines magazines_reviewed_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.magazines - ADD CONSTRAINT magazines_reviewed_by_fkey FOREIGN KEY (reviewed_by) REFERENCES public.users(id); +DO $$ +BEGIN + ALTER TABLE ONLY public.magazines + ADD CONSTRAINT magazines_reviewed_by_fkey FOREIGN KEY (reviewed_by) REFERENCES public.users(id); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2189,8 +2987,15 @@ ALTER TABLE ONLY public.magazines -- Name: post_magazine_news_references post_magazine_news_references_post_magazine_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.post_magazine_news_references - ADD CONSTRAINT post_magazine_news_references_post_magazine_id_fkey FOREIGN KEY (post_magazine_id) REFERENCES public.post_magazines(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.post_magazine_news_references + ADD CONSTRAINT post_magazine_news_references_post_magazine_id_fkey FOREIGN KEY (post_magazine_id) REFERENCES public.post_magazines(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2198,8 +3003,15 @@ ALTER TABLE ONLY public.post_magazine_news_references -- Name: post_magazines post_magazines_approved_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.post_magazines - ADD CONSTRAINT post_magazines_approved_by_fkey FOREIGN KEY (approved_by) REFERENCES auth.users(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY public.post_magazines + ADD CONSTRAINT post_magazines_approved_by_fkey FOREIGN KEY (approved_by) REFERENCES auth.users(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2207,8 +3019,15 @@ ALTER TABLE ONLY public.post_magazines -- Name: user_collections user_collections_magazine_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_collections - ADD CONSTRAINT user_collections_magazine_id_fkey FOREIGN KEY (magazine_id) REFERENCES public.user_magazines(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.user_collections + ADD CONSTRAINT user_collections_magazine_id_fkey FOREIGN KEY (magazine_id) REFERENCES public.user_magazines(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2216,8 +3035,15 @@ ALTER TABLE ONLY public.user_collections -- Name: user_collections user_collections_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_collections - ADD CONSTRAINT user_collections_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.user_collections + ADD CONSTRAINT user_collections_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2225,8 +3051,15 @@ ALTER TABLE ONLY public.user_collections -- Name: user_events user_events_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_events - ADD CONSTRAINT user_events_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.user_events + ADD CONSTRAINT user_events_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2234,8 +3067,15 @@ ALTER TABLE ONLY public.user_events -- Name: user_follows user_follows_follower_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_follows - ADD CONSTRAINT user_follows_follower_id_fkey FOREIGN KEY (follower_id) REFERENCES auth.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.user_follows + ADD CONSTRAINT user_follows_follower_id_fkey FOREIGN KEY (follower_id) REFERENCES auth.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2243,8 +3083,15 @@ ALTER TABLE ONLY public.user_follows -- Name: user_follows user_follows_following_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_follows - ADD CONSTRAINT user_follows_following_id_fkey FOREIGN KEY (following_id) REFERENCES auth.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.user_follows + ADD CONSTRAINT user_follows_following_id_fkey FOREIGN KEY (following_id) REFERENCES auth.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2252,8 +3099,15 @@ ALTER TABLE ONLY public.user_follows -- Name: user_magazines user_magazines_created_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_magazines - ADD CONSTRAINT user_magazines_created_by_fkey FOREIGN KEY (created_by) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.user_magazines + ADD CONSTRAINT user_magazines_created_by_fkey FOREIGN KEY (created_by) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2261,8 +3115,15 @@ ALTER TABLE ONLY public.user_magazines -- Name: user_social_accounts user_social_accounts_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_social_accounts - ADD CONSTRAINT user_social_accounts_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.user_social_accounts + ADD CONSTRAINT user_social_accounts_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2270,8 +3131,15 @@ ALTER TABLE ONLY public.user_social_accounts -- Name: user_tryon_history user_tryon_history_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY public.user_tryon_history - ADD CONSTRAINT user_tryon_history_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY public.user_tryon_history + ADD CONSTRAINT user_tryon_history_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2279,8 +3147,15 @@ ALTER TABLE ONLY public.user_tryon_history -- Name: artists artists_primary_instagram_account_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.artists - ADD CONSTRAINT artists_primary_instagram_account_id_fkey FOREIGN KEY (primary_instagram_account_id) REFERENCES warehouse.instagram_accounts(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.artists + ADD CONSTRAINT artists_primary_instagram_account_id_fkey FOREIGN KEY (primary_instagram_account_id) REFERENCES warehouse.instagram_accounts(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2288,8 +3163,15 @@ ALTER TABLE ONLY warehouse.artists -- Name: brands brands_primary_instagram_account_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.brands - ADD CONSTRAINT brands_primary_instagram_account_id_fkey FOREIGN KEY (primary_instagram_account_id) REFERENCES warehouse.instagram_accounts(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.brands + ADD CONSTRAINT brands_primary_instagram_account_id_fkey FOREIGN KEY (primary_instagram_account_id) REFERENCES warehouse.instagram_accounts(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2297,8 +3179,15 @@ ALTER TABLE ONLY warehouse.brands -- Name: group_members group_members_artist_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.group_members - ADD CONSTRAINT group_members_artist_id_fkey FOREIGN KEY (artist_id) REFERENCES warehouse.artists(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.group_members + ADD CONSTRAINT group_members_artist_id_fkey FOREIGN KEY (artist_id) REFERENCES warehouse.artists(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2306,8 +3195,15 @@ ALTER TABLE ONLY warehouse.group_members -- Name: group_members group_members_group_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.group_members - ADD CONSTRAINT group_members_group_id_fkey FOREIGN KEY (group_id) REFERENCES warehouse.groups(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.group_members + ADD CONSTRAINT group_members_group_id_fkey FOREIGN KEY (group_id) REFERENCES warehouse.groups(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2315,8 +3211,15 @@ ALTER TABLE ONLY warehouse.group_members -- Name: groups groups_primary_instagram_account_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.groups - ADD CONSTRAINT groups_primary_instagram_account_id_fkey FOREIGN KEY (primary_instagram_account_id) REFERENCES warehouse.instagram_accounts(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.groups + ADD CONSTRAINT groups_primary_instagram_account_id_fkey FOREIGN KEY (primary_instagram_account_id) REFERENCES warehouse.instagram_accounts(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2324,8 +3227,15 @@ ALTER TABLE ONLY warehouse.groups -- Name: instagram_accounts instagram_accounts_artist_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.instagram_accounts - ADD CONSTRAINT instagram_accounts_artist_id_fkey FOREIGN KEY (artist_id) REFERENCES warehouse.artists(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.instagram_accounts + ADD CONSTRAINT instagram_accounts_artist_id_fkey FOREIGN KEY (artist_id) REFERENCES warehouse.artists(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2333,8 +3243,15 @@ ALTER TABLE ONLY warehouse.instagram_accounts -- Name: instagram_accounts instagram_accounts_brand_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.instagram_accounts - ADD CONSTRAINT instagram_accounts_brand_id_fkey FOREIGN KEY (brand_id) REFERENCES warehouse.brands(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.instagram_accounts + ADD CONSTRAINT instagram_accounts_brand_id_fkey FOREIGN KEY (brand_id) REFERENCES warehouse.brands(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2342,8 +3259,15 @@ ALTER TABLE ONLY warehouse.instagram_accounts -- Name: raw_posts raw_posts_seed_post_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.raw_posts - ADD CONSTRAINT raw_posts_seed_post_id_fkey FOREIGN KEY (seed_post_id) REFERENCES warehouse.seed_posts(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.raw_posts + ADD CONSTRAINT raw_posts_seed_post_id_fkey FOREIGN KEY (seed_post_id) REFERENCES warehouse.seed_posts(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2351,8 +3275,15 @@ ALTER TABLE ONLY warehouse.raw_posts -- Name: raw_posts raw_posts_source_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.raw_posts - ADD CONSTRAINT raw_posts_source_id_fkey FOREIGN KEY (source_id) REFERENCES warehouse.raw_post_sources(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.raw_posts + ADD CONSTRAINT raw_posts_source_id_fkey FOREIGN KEY (source_id) REFERENCES warehouse.raw_post_sources(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2360,8 +3291,15 @@ ALTER TABLE ONLY warehouse.raw_posts -- Name: images warehouse_images_post_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.images - ADD CONSTRAINT warehouse_images_post_id_fkey FOREIGN KEY (post_id) REFERENCES warehouse.posts(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.images + ADD CONSTRAINT warehouse_images_post_id_fkey FOREIGN KEY (post_id) REFERENCES warehouse.posts(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2369,8 +3307,15 @@ ALTER TABLE ONLY warehouse.images -- Name: instagram_accounts warehouse_instagram_accounts_group_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.instagram_accounts - ADD CONSTRAINT warehouse_instagram_accounts_group_id_fkey FOREIGN KEY (group_id) REFERENCES warehouse.groups(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.instagram_accounts + ADD CONSTRAINT warehouse_instagram_accounts_group_id_fkey FOREIGN KEY (group_id) REFERENCES warehouse.groups(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2378,8 +3323,15 @@ ALTER TABLE ONLY warehouse.instagram_accounts -- Name: posts warehouse_posts_account_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.posts - ADD CONSTRAINT warehouse_posts_account_id_fkey FOREIGN KEY (account_id) REFERENCES warehouse.instagram_accounts(id) ON DELETE RESTRICT; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.posts + ADD CONSTRAINT warehouse_posts_account_id_fkey FOREIGN KEY (account_id) REFERENCES warehouse.instagram_accounts(id) ON DELETE RESTRICT; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2387,8 +3339,15 @@ ALTER TABLE ONLY warehouse.posts -- Name: seed_asset warehouse_seed_asset_seed_post_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.seed_asset - ADD CONSTRAINT warehouse_seed_asset_seed_post_id_fkey FOREIGN KEY (seed_post_id) REFERENCES warehouse.seed_posts(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.seed_asset + ADD CONSTRAINT warehouse_seed_asset_seed_post_id_fkey FOREIGN KEY (seed_post_id) REFERENCES warehouse.seed_posts(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2396,8 +3355,15 @@ ALTER TABLE ONLY warehouse.seed_asset -- Name: seed_posts warehouse_seed_posts_artist_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.seed_posts - ADD CONSTRAINT warehouse_seed_posts_artist_id_fkey FOREIGN KEY (artist_id) REFERENCES warehouse.artists(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.seed_posts + ADD CONSTRAINT warehouse_seed_posts_artist_id_fkey FOREIGN KEY (artist_id) REFERENCES warehouse.artists(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2405,8 +3371,15 @@ ALTER TABLE ONLY warehouse.seed_posts -- Name: seed_posts warehouse_seed_posts_group_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.seed_posts - ADD CONSTRAINT warehouse_seed_posts_group_id_fkey FOREIGN KEY (group_id) REFERENCES warehouse.groups(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.seed_posts + ADD CONSTRAINT warehouse_seed_posts_group_id_fkey FOREIGN KEY (group_id) REFERENCES warehouse.groups(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2414,8 +3387,15 @@ ALTER TABLE ONLY warehouse.seed_posts -- Name: seed_posts warehouse_seed_posts_source_image_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.seed_posts - ADD CONSTRAINT warehouse_seed_posts_source_image_id_fkey FOREIGN KEY (source_image_id) REFERENCES warehouse.images(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.seed_posts + ADD CONSTRAINT warehouse_seed_posts_source_image_id_fkey FOREIGN KEY (source_image_id) REFERENCES warehouse.images(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2423,8 +3403,15 @@ ALTER TABLE ONLY warehouse.seed_posts -- Name: seed_posts warehouse_seed_posts_source_post_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.seed_posts - ADD CONSTRAINT warehouse_seed_posts_source_post_id_fkey FOREIGN KEY (source_post_id) REFERENCES warehouse.posts(id) ON DELETE SET NULL; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.seed_posts + ADD CONSTRAINT warehouse_seed_posts_source_post_id_fkey FOREIGN KEY (source_post_id) REFERENCES warehouse.posts(id) ON DELETE SET NULL; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- @@ -2432,8 +3419,15 @@ ALTER TABLE ONLY warehouse.seed_posts -- Name: seed_spots warehouse_seed_spots_seed_post_id_fkey; Type: FK CONSTRAINT; Schema: warehouse; Owner: - -- -ALTER TABLE ONLY warehouse.seed_spots - ADD CONSTRAINT warehouse_seed_spots_seed_post_id_fkey FOREIGN KEY (seed_post_id) REFERENCES warehouse.seed_posts(id) ON DELETE CASCADE; +DO $$ +BEGIN + ALTER TABLE ONLY warehouse.seed_spots + ADD CONSTRAINT warehouse_seed_spots_seed_post_id_fkey FOREIGN KEY (seed_post_id) REFERENCES warehouse.seed_posts(id) ON DELETE CASCADE; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN duplicate_table THEN NULL; + WHEN invalid_table_definition THEN NULL; +END $$; -- diff --git a/packages/api-server/migration/sql/007_triggers_ddl.sql b/packages/api-server/migration/sql/007_triggers_ddl.sql index e2e5b839..2ec4a952 100644 --- a/packages/api-server/migration/sql/007_triggers_ddl.sql +++ b/packages/api-server/migration/sql/007_triggers_ddl.sql @@ -3,7 +3,7 @@ SET check_function_bodies = false; -- Name: set_updated_at(); Type: FUNCTION; Schema: warehouse; Owner: - -- -CREATE FUNCTION warehouse.set_updated_at() RETURNS trigger +CREATE OR REPLACE FUNCTION warehouse.set_updated_at() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN @@ -18,7 +18,7 @@ CREATE FUNCTION warehouse.set_updated_at() RETURNS trigger -- Name: touch_updated_at(); Type: FUNCTION; Schema: warehouse; Owner: - -- -CREATE FUNCTION warehouse.touch_updated_at() RETURNS trigger +CREATE OR REPLACE FUNCTION warehouse.touch_updated_at() RETURNS trigger LANGUAGE plpgsql SET search_path TO '' AS $$ @@ -34,7 +34,7 @@ $$; -- Name: update_updated_at_column(); Type: FUNCTION; Schema: public; Owner: - -- -CREATE FUNCTION public.update_updated_at_column() RETURNS trigger +CREATE OR REPLACE FUNCTION public.update_updated_at_column() RETURNS trigger LANGUAGE plpgsql SET search_path TO '' AS $$ @@ -50,6 +50,8 @@ CREATE FUNCTION public.update_updated_at_column() RETURNS trigger -- Name: artists trg_artists_touch_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - -- +DROP TRIGGER IF EXISTS trg_artists_touch_updated_at ON warehouse.artists; + CREATE TRIGGER trg_artists_touch_updated_at BEFORE UPDATE ON warehouse.artists FOR EACH ROW EXECUTE FUNCTION warehouse.touch_updated_at(); @@ -58,6 +60,8 @@ CREATE TRIGGER trg_artists_touch_updated_at BEFORE UPDATE ON warehouse.artists F -- Name: badges update_badges_updated_at; Type: TRIGGER; Schema: public; Owner: - -- +DROP TRIGGER IF EXISTS update_badges_updated_at ON public.badges; + CREATE TRIGGER update_badges_updated_at BEFORE UPDATE ON public.badges FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); @@ -66,6 +70,8 @@ CREATE TRIGGER update_badges_updated_at BEFORE UPDATE ON public.badges FOR EACH -- Name: brands trg_brands_touch_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - -- +DROP TRIGGER IF EXISTS trg_brands_touch_updated_at ON warehouse.brands; + CREATE TRIGGER trg_brands_touch_updated_at BEFORE UPDATE ON warehouse.brands FOR EACH ROW EXECUTE FUNCTION warehouse.touch_updated_at(); @@ -74,6 +80,8 @@ CREATE TRIGGER trg_brands_touch_updated_at BEFORE UPDATE ON warehouse.brands FOR -- Name: categories update_categories_updated_at; Type: TRIGGER; Schema: public; Owner: - -- +DROP TRIGGER IF EXISTS update_categories_updated_at ON public.categories; + CREATE TRIGGER update_categories_updated_at BEFORE UPDATE ON public.categories FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); @@ -82,6 +90,8 @@ CREATE TRIGGER update_categories_updated_at BEFORE UPDATE ON public.categories F -- Name: comments update_comments_updated_at; Type: TRIGGER; Schema: public; Owner: - -- +DROP TRIGGER IF EXISTS update_comments_updated_at ON public.comments; + CREATE TRIGGER update_comments_updated_at BEFORE UPDATE ON public.comments FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); @@ -90,6 +100,8 @@ CREATE TRIGGER update_comments_updated_at BEFORE UPDATE ON public.comments FOR E -- Name: group_members trg_group_members_touch_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - -- +DROP TRIGGER IF EXISTS trg_group_members_touch_updated_at ON warehouse.group_members; + CREATE TRIGGER trg_group_members_touch_updated_at BEFORE UPDATE ON warehouse.group_members FOR EACH ROW EXECUTE FUNCTION warehouse.touch_updated_at(); @@ -98,6 +110,8 @@ CREATE TRIGGER trg_group_members_touch_updated_at BEFORE UPDATE ON warehouse.gro -- Name: groups trg_groups_touch_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - -- +DROP TRIGGER IF EXISTS trg_groups_touch_updated_at ON warehouse.groups; + CREATE TRIGGER trg_groups_touch_updated_at BEFORE UPDATE ON warehouse.groups FOR EACH ROW EXECUTE FUNCTION warehouse.touch_updated_at(); @@ -106,6 +120,8 @@ CREATE TRIGGER trg_groups_touch_updated_at BEFORE UPDATE ON warehouse.groups FOR -- Name: instagram_accounts trg_instagram_accounts_touch_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - -- +DROP TRIGGER IF EXISTS trg_instagram_accounts_touch_updated_at ON warehouse.instagram_accounts; + CREATE TRIGGER trg_instagram_accounts_touch_updated_at BEFORE UPDATE ON warehouse.instagram_accounts FOR EACH ROW EXECUTE FUNCTION warehouse.touch_updated_at(); @@ -114,6 +130,8 @@ CREATE TRIGGER trg_instagram_accounts_touch_updated_at BEFORE UPDATE ON warehous -- Name: posts update_posts_updated_at; Type: TRIGGER; Schema: public; Owner: - -- +DROP TRIGGER IF EXISTS update_posts_updated_at ON public.posts; + CREATE TRIGGER update_posts_updated_at BEFORE UPDATE ON public.posts FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); @@ -122,6 +140,8 @@ CREATE TRIGGER update_posts_updated_at BEFORE UPDATE ON public.posts FOR EACH RO -- Name: raw_post_sources raw_post_sources_set_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - -- +DROP TRIGGER IF EXISTS raw_post_sources_set_updated_at ON warehouse.raw_post_sources; + CREATE TRIGGER raw_post_sources_set_updated_at BEFORE UPDATE ON warehouse.raw_post_sources FOR EACH ROW EXECUTE FUNCTION warehouse.set_updated_at(); @@ -130,6 +150,8 @@ CREATE TRIGGER raw_post_sources_set_updated_at BEFORE UPDATE ON warehouse.raw_po -- Name: raw_posts raw_posts_set_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - -- +DROP TRIGGER IF EXISTS raw_posts_set_updated_at ON warehouse.raw_posts; + CREATE TRIGGER raw_posts_set_updated_at BEFORE UPDATE ON warehouse.raw_posts FOR EACH ROW EXECUTE FUNCTION warehouse.set_updated_at(); @@ -138,6 +160,8 @@ CREATE TRIGGER raw_posts_set_updated_at BEFORE UPDATE ON warehouse.raw_posts FOR -- Name: seed_asset trg_seed_asset_touch_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - -- +DROP TRIGGER IF EXISTS trg_seed_asset_touch_updated_at ON warehouse.seed_asset; + CREATE TRIGGER trg_seed_asset_touch_updated_at BEFORE UPDATE ON warehouse.seed_asset FOR EACH ROW EXECUTE FUNCTION warehouse.touch_updated_at(); @@ -146,6 +170,8 @@ CREATE TRIGGER trg_seed_asset_touch_updated_at BEFORE UPDATE ON warehouse.seed_a -- Name: seed_posts trg_seed_posts_touch_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - -- +DROP TRIGGER IF EXISTS trg_seed_posts_touch_updated_at ON warehouse.seed_posts; + CREATE TRIGGER trg_seed_posts_touch_updated_at BEFORE UPDATE ON warehouse.seed_posts FOR EACH ROW EXECUTE FUNCTION warehouse.touch_updated_at(); @@ -154,6 +180,8 @@ CREATE TRIGGER trg_seed_posts_touch_updated_at BEFORE UPDATE ON warehouse.seed_p -- Name: seed_spots trg_seed_spots_touch_updated_at; Type: TRIGGER; Schema: warehouse; Owner: - -- +DROP TRIGGER IF EXISTS trg_seed_spots_touch_updated_at ON warehouse.seed_spots; + CREATE TRIGGER trg_seed_spots_touch_updated_at BEFORE UPDATE ON warehouse.seed_spots FOR EACH ROW EXECUTE FUNCTION warehouse.touch_updated_at(); @@ -162,6 +190,8 @@ CREATE TRIGGER trg_seed_spots_touch_updated_at BEFORE UPDATE ON warehouse.seed_s -- Name: solutions update_solutions_updated_at; Type: TRIGGER; Schema: public; Owner: - -- +DROP TRIGGER IF EXISTS update_solutions_updated_at ON public.solutions; + CREATE TRIGGER update_solutions_updated_at BEFORE UPDATE ON public.solutions FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); @@ -170,6 +200,8 @@ CREATE TRIGGER update_solutions_updated_at BEFORE UPDATE ON public.solutions FOR -- Name: spots update_spots_updated_at; Type: TRIGGER; Schema: public; Owner: - -- +DROP TRIGGER IF EXISTS update_spots_updated_at ON public.spots; + CREATE TRIGGER update_spots_updated_at BEFORE UPDATE ON public.spots FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); @@ -178,6 +210,8 @@ CREATE TRIGGER update_spots_updated_at BEFORE UPDATE ON public.spots FOR EACH RO -- Name: subcategories update_subcategories_updated_at; Type: TRIGGER; Schema: public; Owner: - -- +DROP TRIGGER IF EXISTS update_subcategories_updated_at ON public.subcategories; + CREATE TRIGGER update_subcategories_updated_at BEFORE UPDATE ON public.subcategories FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); @@ -186,6 +220,8 @@ CREATE TRIGGER update_subcategories_updated_at BEFORE UPDATE ON public.subcatego -- Name: synonyms update_synonyms_updated_at; Type: TRIGGER; Schema: public; Owner: - -- +DROP TRIGGER IF EXISTS update_synonyms_updated_at ON public.synonyms; + CREATE TRIGGER update_synonyms_updated_at BEFORE UPDATE ON public.synonyms FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); @@ -194,6 +230,8 @@ CREATE TRIGGER update_synonyms_updated_at BEFORE UPDATE ON public.synonyms FOR E -- Name: user_magazines update_user_magazines_updated_at; Type: TRIGGER; Schema: public; Owner: - -- +DROP TRIGGER IF EXISTS update_user_magazines_updated_at ON public.user_magazines; + CREATE TRIGGER update_user_magazines_updated_at BEFORE UPDATE ON public.user_magazines FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); @@ -202,6 +240,8 @@ CREATE TRIGGER update_user_magazines_updated_at BEFORE UPDATE ON public.user_mag -- Name: user_social_accounts update_user_social_accounts_updated_at; Type: TRIGGER; Schema: public; Owner: - -- +DROP TRIGGER IF EXISTS update_user_social_accounts_updated_at ON public.user_social_accounts; + CREATE TRIGGER update_user_social_accounts_updated_at BEFORE UPDATE ON public.user_social_accounts FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); @@ -210,6 +250,8 @@ CREATE TRIGGER update_user_social_accounts_updated_at BEFORE UPDATE ON public.us -- Name: users update_users_updated_at; Type: TRIGGER; Schema: public; Owner: - -- +DROP TRIGGER IF EXISTS update_users_updated_at ON public.users; + CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON public.users FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column();