ITADN

schema-sync creates indexes against unqualified table names for entities in non-default PostgreSQL schemas

#3084Openouywm 创建于 2026-06-13
O
ouywmcommented
<!-- Welcome! Thank you for reporting bugs! First of all, please star our repo. Your support is vital to the continued maintenance of SeaORM. Want to ask a question? You can reach us via: - Discord: https://discord.com/invite/uCPdDXzbdv - GitHub Discussions: https://github.com/SeaQL/sea-orm/discussions/new Please make sure that you are not asking for a missing feature; a bug is incorrect behavior - either in the feature specification or implementation. Feature requests should be first raised in discussions. Please also make sure your description is clear and precise - maintainers don't have access to your code and can't see what you have seen. Please avoid vague descriptions like "they are different" or "the program crashes" - in either case, provide exact information. If you are certain there is a bug, please provide a reproducible example, which helps the investigator to pin-point the bug and the implementor to verify that a solution is satisfactory. Bug reports without reproducible example may be closed or dangle forever. Finally, please search for existing issues and discussions before submission. Feel free to revive old threads if you have new information to add, but please don't ask for ETA or "+1". --> ## Description I think I ran into a follow-up case to #2952 / #3016. `schema-sync` now discovers tables in non-default PostgreSQL schemas correctly, but indexes generated from entity attributes still seem to use the table name without the schema qualifier. For an entity like this: ```rust #[sea_orm(schema_name = "sys", table_name = "app_user")] ``` the table itself is created in the expected schema: ```sql CREATE TABLE "sys"."app_user" ... ``` But indexes generated from `#[sea_orm(indexed)]` or `#[sea_orm(unique_key = "...")]` appear to target: ```sql CREATE INDEX ... ON "app_user" (...); CREATE UNIQUE INDEX ... ON "app_user" (...); ``` instead of: ```sql CREATE INDEX ... ON "sys"."app_user" (...); CREATE UNIQUE INDEX ... ON "sys"."app_user" (...); ``` When the connection is still using the default `search_path` / current schema, PostgreSQL resolves `"app_user"` in `public`, not in `sys`. On a fresh database this can fail with `relation "app_user" does not exist`. If another schema has a table with the same name, it could also target the wrong table. This seems different from #3016: that PR fixed schema-aware table discovery and lookup during sync. This report is about the index DDL generated after the table has been found or created. ## Steps to Reproduce 1. Create a non-default PostgreSQL schema: ```sql CREATE SCHEMA IF NOT EXISTS sys; ``` 2. Define an entity in that schema with an indexed column and a multi-column unique key: ```rust use sea_orm::entity::prelude::*; #[sea_orm::model] #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] #[sea_orm(schema_name = "sys", table_name = "app_user")] pub struct Model { #[sea_orm(primary_key)] pub id: i32, #[sea_orm(indexed)] pub email: String, #[sea_orm(unique_key = "tenant_name")] pub tenant_id: i32, #[sea_orm(unique_key = "tenant_name")] pub name: String, } impl ActiveModelBehavior for ActiveModel {} ``` 3. Run schema sync while the connection's current schema is still `public`: ```rust db.get_schema_builder() .register(app_user::Entity) .sync(&db) .await?; ``` ### Expected Behavior The table and generated indexes should all use the entity's `schema_name`. For example: ```sql CREATE TABLE "sys"."app_user" (...); CREATE INDEX IF NOT EXISTS "idx-app_user-email" ON "sys"."app_user" ("email"); CREATE UNIQUE INDEX IF NOT EXISTS "idx-app_user-tenant_name" ON "sys"."app_user" ("tenant_id", "name"); ``` ### Actual Behavior The table is created in the correct schema, but the generated index statements target the unqualified table name: ```sql CREATE INDEX IF NOT EXISTS "idx-app_user-email" ON "app_user" ("email"); CREATE UNIQUE INDEX IF NOT EXISTS "idx-app_user-tenant_name" ON "app_user" ("tenant_id", "name"); ``` With the default `search_path`, PostgreSQL resolves `"app_user"` in `public`, not in `sys`, so sync fails or targets the wrong table. From a quick look at current `master`, table creation already uses: ```rust stmt.table(entity.table_ref()).take() ``` but `create_index_from_entity` still seems to use `entity` as the target table for generated indexes. I may be missing a layer here, but the generated SQL appears to line up with that. ### Reproduces How Often Always, when: - the entity uses `#[sea_orm(schema_name = "...")]` - the schema is not the current/default PostgreSQL schema - the entity has an index generated from `#[sea_orm(indexed)]` or `#[sea_orm(unique_key = "...")]` ### Workarounds Setting the connection `search_path` to the target schema can work if all synced entities live in a single schema. For multi-schema projects, that workaround is fragile because unqualified table names depend on whichever schema happens to be first in `search_path`. ## Versions ```text sea-orm v2.0.0-rc.40 PostgreSQL 16 macOS ```
0 条评论