Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Escaping causes check statement to fail #686

Closed
kikijiki opened this issue Aug 29, 2023 · 5 comments
Closed

Escaping causes check statement to fail #686

kikijiki opened this issue Aug 29, 2023 · 5 comments

Comments

@kikijiki
Copy link

Description

In a migration for PostgreSQL I have some code like this:

    manager
        .create_table(
            Table::create()
                .table(User::Table)
                .col(
                    ColumnDef::new(User::Id)
                        .big_integer()
                        .not_null()
                        .auto_increment()
                        .primary_key(),
                )
                .col(
                    ColumnDef::new(User::Email)
                        .string_len(320)
                        .check("email ~* '^[^@]+@[^@]+\\.[^@]+$'")
                        .unique_key()
                        .not_null(),
                )
                .to_owned(),
        )
        .await?;

This is the SQL that gets produced:

CREATE TABLE "user" (
  "id" bigserial NOT NULL PRIMARY KEY,
  "email" varchar(320) CHECK (E'email ~* ''^[^@]+@[^@]+\.[^@]+$''') UNIQUE NOT NULL,
);

The error is:

Execution Error: error returned from database: invalid input syntax for type boolean: "email ~* '^[^@]+@[^@]+\.[^@]+$'"

I tried changing the way I express the check but I could not find a way to make it work, there is always some escaping problem.

This is what would work instead:

CREATE TABLE "user" (
  "id" bigserial NOT NULL PRIMARY KEY,
  -- Either this
  "email" varchar(320) CHECK (email ~* '^[^@]+@[^@]+\.[^@]+$') UNIQUE NOT NULL
  -- Or this?
  "email" varchar(320) CHECK (email ~* E'^[^@]+@[^@]+\\.[^@]+$') UNIQUE NOT NULL
);

Workarounds

Current workaround is to add the check as a separate sql statement bypassing seaorm.

Versions

sea-orm: 0.12.2
sea-orm-migration: 0.12.2
db: postgres
OS: Win11

@tyt2y3
Copy link
Member

tyt2y3 commented Aug 29, 2023

I think you have to use extra()
It won't be quoted by any means

@kikijiki
Copy link
Author

@tyt2y3 Thank you for the quick response, I didn't know about extra().
That seems to do the trick too.

Not sure if this is a bug or not, feel free to close this if it is intended to behave like this.

@tyt2y3 tyt2y3 transferred this issue from SeaQL/sea-orm Aug 29, 2023
@tyt2y3
Copy link
Member

tyt2y3 commented Aug 29, 2023

Okay I found the context

fn alter_with_check_constraint() {
assert_eq!(
Table::alter()
.table(Glyph::Table)
.add_column(
ColumnDef::new(Glyph::Aspect)
.integer()
.not_null()
.default(101)
.check(Expr::col(Glyph::Aspect).gt(100))
)
.to_string(MysqlQueryBuilder),
r#"ALTER TABLE `glyph` ADD COLUMN `aspect` int NOT NULL DEFAULT 101 CHECK (`aspect` > 100)"#,
);

@tyt2y3
Copy link
Member

tyt2y3 commented Aug 29, 2023

So you can actually

.check(Expr::col(User::Email).binary(PgBinOper::RegexCaseInsensitive, Expr::value("^[^@]+@[^@]+\\.[^@]+$"))

@tyt2y3 tyt2y3 closed this as completed Aug 29, 2023
@tyt2y3
Copy link
Member

tyt2y3 commented Aug 29, 2023

We should add an example though.

tyt2y3 added a commit that referenced this issue Aug 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants