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
Abstraction is leacking from data access layer to api-controller #1393
Comments
P.S. it also has hardcoded number 200, it could be made into regex, to be future schema-change proof. |
We will never allow a different DB other than postgres. Could you do a PR for this? |
Anyway, it's a broken abstraction, and hardcoded length.
I'm not sure. I haven't written in Rust anything serious. |
Perhaps I should try making PR. Would get to it on next week. But I find getting started documentation lacking. I have no idea how to set-up admin user, for example. |
@Mart-Bogdan It depends how you start Lemmy. If you use the |
@Nutomic I'm back. Was hoping to make use of DatabaseErrorInformation::column_name but it seems now that Postgres don't provide column name. It's a type error that happens on type biding level or something(which is irrelevant why it don't show column name). I would like to change the column type to ALTER TABLE post ALTER COLUMN name type text;
ALTER TABLE post ADD CONSTRAINT post_title_too_long CHECK ( char_length(name) <= 200 ) ; It's actually not recommended to use legacy SQL string types in postgres (unless compatibility with other DBMS is required, which you state is not needed). From docs:
P.S. I've read a long time ago this SO answer about domains. Dpmains would definitely be overkill, but we could use simple check constraints. That way we can change constraints without locking the whole table in the future. So how do you think @Nutomic, would it be ok to add CHECK CONSTRAINT in migration instead of VARCHAR(200)? P.P.S. In my most Postgres development I use just text type and check length inside application code. And I had a lot of problems with fixed limited length columns in MS SQL Server. |
I do most of the DB work.
I def prefer varchar fixed limit lengths over extra unnecessary constraints. They work fine in postgres. |
I think then it's not many that could be done. I hoped something useful could be xtracted from diesel Error::DatabaseError. My initial assumption was to create custom struct/enum like LemmyDbError, and wrap it around diesel's error, but that won'd to mutch at this point, what do you think? P.S. What do you think about Keats/validator for proactive validation instead of DB type constraints? Because currently I've noticed a lot of columns with limited length in DB, but it's not possible to detect from code -- which one failed. But using validator has two drawbacks:
|
I think we will have to move the length checks to Rust anyway, because of #1447. Otherwise they need to be defined in 2 different places (Postgres and Rust). |
I'm good with adding different constraint checks to rust, but I don't want to ever remove them from the DB. But also I don't see what's wrong with checking error messages coming back from diesel like we do now. |
Hm, we are checking for exact message with a specified length
and then inferring field name. But my initial objection was about that code is tightly coupled to diesel error, code inside "controllers". Perhaps I'll look at it again later. But for now I would like to focus on auth improvements. P.S. In my C# project, we are using following error handling in Data Access Layer catch (DbUpdateException dbException)
{
if (dbException.InnerException != null)
{
//Postgres generated error
//Sql State 23505 a unique value constraint is violated
if ((string)dbException.InnerException.Data["SqlState"] == "23505")
{
throw new $MyCompany$UniquenessErrorException(dbException);
}
}
throw;
} So in this particular case upper lying code don't bother to know that under the hood we are using Entity Framework or even SQL. It only needs to care about our domain Exception. But in case if we don't detect SqlState -- we are using catch-all that rethrows the original error with |
We're in a sense doing a similar thing here, checking to see if its a specific type of diesel error, then returning our own let err_type = if e.to_string()
== "duplicate key value violates unique constraint \"user__email_key\""
{
"email_already_exists"
} else {
"user_already_exists"
};
return Err(ApiError::err(err_type).into()); I think we've tried before, but have been unable to get cleaner errors out of that diesel error type, but you could try to see if you could get anything more concrete than the string checking we have. |
Unfortunately, diesel do not export SQLState, I was asking if SQLState could also be included, but it didn't get into PR. @dessalines I've just run a search for How do you think it's only places with similar checks? |
Could you clarify, I don't understand. |
I mean co you know of other similar cases in codebase? I could wrap these cases into an enum enum LemmyDataAccessError{ or plain diesel::Error in the last case. |
I mean apply some regex and create helper function that would be called inside db_queries crate |
Could you open an issue about this in the Diesel repo and link it here? I think this should be handled in the library, and not by us. |
He-he. Nice fix. Indeed this can be done by validation. 🎉 |
In the pointed line of code
lemmy/crates/api/src/post.rs
Line 107 in 3a05817
logic in controller is checking error string specific to concrete RDBMS implementation.
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.
The text was updated successfully, but these errors were encountered: