mirror of
https://github.com/launchbadge/sqlx.git
synced 2026-03-19 08:39:44 +00:00
feat: better database errors (#2109)
* feat(core): create error kind enum * feat(core): add error kind for postgres * feat(core): add error kind for sqlite * feat(core): add error kind for mysql * test(postgres): add error tests * test(sqlite): add error tests * test(mysql): add error tests * fix(tests): fix tests rebasing * refac(errors): add `ErrorKind::Other` variant
This commit is contained in:
committed by
Austin Bonander
parent
771ab80a62
commit
c09532864d
72
tests/sqlite/error.rs
Normal file
72
tests/sqlite/error.rs
Normal file
@@ -0,0 +1,72 @@
|
||||
use sqlx::{error::ErrorKind, query, sqlite::Sqlite, Connection, Executor, Transaction};
|
||||
use sqlx_test::new;
|
||||
|
||||
#[sqlx_macros::test]
|
||||
async fn it_fails_with_unique_violation() -> anyhow::Result<()> {
|
||||
let mut conn = new::<Sqlite>().await?;
|
||||
let mut tx = conn.begin().await?;
|
||||
|
||||
let res: Result<_, sqlx::Error> = sqlx::query("INSERT INTO tweet VALUES (1, 'Foo', true, 1);")
|
||||
.execute(&mut *tx)
|
||||
.await;
|
||||
let err = res.unwrap_err();
|
||||
|
||||
let err = err.into_database_error().unwrap();
|
||||
|
||||
assert_eq!(err.kind(), ErrorKind::UniqueViolation);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[sqlx_macros::test]
|
||||
async fn it_fails_with_foreign_key_violation() -> anyhow::Result<()> {
|
||||
let mut conn = new::<Sqlite>().await?;
|
||||
let mut tx = conn.begin().await?;
|
||||
|
||||
let res: Result<_, sqlx::Error> =
|
||||
sqlx::query("INSERT INTO tweet_reply (id, tweet_id, text) VALUES (2, 2, 'Reply!');")
|
||||
.execute(&mut *tx)
|
||||
.await;
|
||||
let err = res.unwrap_err();
|
||||
|
||||
let err = err.into_database_error().unwrap();
|
||||
|
||||
assert_eq!(err.kind(), ErrorKind::ForeignKeyViolation);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[sqlx_macros::test]
|
||||
async fn it_fails_with_not_null_violation() -> anyhow::Result<()> {
|
||||
let mut conn = new::<Sqlite>().await?;
|
||||
let mut tx = conn.begin().await?;
|
||||
|
||||
let res: Result<_, sqlx::Error> = sqlx::query("INSERT INTO tweet (text) VALUES (null);")
|
||||
.execute(&mut *tx)
|
||||
.await;
|
||||
let err = res.unwrap_err();
|
||||
|
||||
let err = err.into_database_error().unwrap();
|
||||
|
||||
assert_eq!(err.kind(), ErrorKind::NotNullViolation);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[sqlx_macros::test]
|
||||
async fn it_fails_with_check_violation() -> anyhow::Result<()> {
|
||||
let mut conn = new::<Sqlite>().await?;
|
||||
let mut tx = conn.begin().await?;
|
||||
|
||||
let res: Result<_, sqlx::Error> =
|
||||
sqlx::query("INSERT INTO products VALUES (1, 'Product 1', 0);")
|
||||
.execute(&mut *tx)
|
||||
.await;
|
||||
let err = res.unwrap_err();
|
||||
|
||||
let err = err.into_database_error().unwrap();
|
||||
|
||||
assert_eq!(err.kind(), ErrorKind::CheckViolation);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -8,6 +8,16 @@ CREATE TABLE tweet (
|
||||
INSERT INTO tweet(id, text, owner_id)
|
||||
VALUES (1, '#sqlx is pretty cool!', 1);
|
||||
--
|
||||
CREATE TABLE tweet_reply (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
tweet_id BIGINT NOT NULL,
|
||||
text TEXT NOT NULL,
|
||||
owner_id BIGINT,
|
||||
CONSTRAINT tweet_id_fk FOREIGN KEY (tweet_id) REFERENCES tweet(id)
|
||||
);
|
||||
INSERT INTO tweet_reply(id, tweet_id, text, owner_id)
|
||||
VALUES (1, 1, 'Yeah! #sqlx is indeed pretty cool!', 1);
|
||||
--
|
||||
CREATE TABLE accounts (
|
||||
id INTEGER NOT NULL PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
@@ -18,3 +28,10 @@ VALUES (1, 'Herp Derpinson', 1);
|
||||
CREATE VIEW accounts_view as
|
||||
SELECT *
|
||||
FROM accounts;
|
||||
--
|
||||
CREATE TABLE products (
|
||||
product_no INTEGER,
|
||||
name TEXT,
|
||||
price NUMERIC,
|
||||
CONSTRAINT price_greater_than_zero CHECK (price > 0)
|
||||
);
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user