schema-sync creates indexes against unqualified table names for entities in non-default PostgreSQL schemas
<!--
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 条评论