| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
There was a problem hiding this comment.
🤩 Let me know at whatever point you need my input on this. Looking good!
Sorry, something went wrong.
|
Hi @tomchristie, I was finally able to finish the first turn around and there're some issues appeared.
Also there might be some confusion as asyncpg is implicit choice for Postgres (even though I believe a good one :)). Update: All in all, we just need to distinguish asyncpg and aiopg at the database class and supply a url sqlalchemy can recognise (for alembic or some other things).
In overall, it's pretty close to mysql backend, but there're some differences in details. Yeah, it would great to have any feedback, recommendations, complains. |
Sorry, something went wrong.
|
I suppose sqlalchemy should only see it as postgresql. We're not using their drivers, so that's the best information we can give it. |
Sorry, something went wrong.
|
Yes, I see, it clarifies and makes it easier. |
Sorry, something went wrong.
|
@tomchristie, @gvbgduh when do you plan to merge this PR? |
Sorry, something went wrong.
|
Yup, it'd be great to get this in! |
Sorry, something went wrong.
|
|
||
|
|
||
| def test_aiopg_ssl(): | ||
| backend = AiopgBackend("postgres+aiopg://localhost/database?ssl=true") |
There was a problem hiding this comment.
Looks like we're expecting postgres+aiopg in some places and postgresql+aiopg in others.
I'd be okay with us accepting either or both.
Sorry, something went wrong.
There was a problem hiding this comment.
Right, yeah, it's a typo, but we only expect postgresql+aiopg as of now, at least there's only this mapping. it's not triggered in these tests as don't make any use of it. I'll update urls to avoid confusion.
Sorry, something went wrong.
| # Apparently for `aiopg` it's OID that will always 0 in this case | ||
| # As it's only one action within this cursor life cycle | ||
| # It's recommended to use the `RETURNING` clause | ||
| # For obtaining the record id |
There was a problem hiding this comment.
This is a good example of where we ought to be returning a more structured type from .execute - that way we could have different drivers either support or not support result.row_id.
Sorry, something went wrong.
There was a problem hiding this comment.
Can we change our query here to make it consistently return the pk across all our implementations maybe?
Sorry, something went wrong.
There was a problem hiding this comment.
Yes, sounds reasonable indeed.
There're two ways though as I can see:
Sorry, something went wrong.
There was a problem hiding this comment.
Oh, just 25 secs later, ok, let's follow the second path, all in all, there's always a way to jump to the raw driver and get the full manual control over it.
Sorry, something went wrong.
There was a problem hiding this comment.
@tomchristie I'm thinking quite hard about it. There's a function in postgres - lastval() that can be executed to retrieve the value, but it's not reliable as there're circumstances where it can return the wrong value. The returning clause is the best way to do it, but we can't assume how the PK column is called and returning * won't be consistent with other back-ends.
Sorry, something went wrong.
| values = {"data": data} | ||
|
|
||
| if database.url.scheme == "postgresql+aiopg": | ||
| await database.execute(query, {"data": json.dumps(data)}) |
There was a problem hiding this comment.
Can we handle this automatically for our users?
Would that be a sensible thing to do here?
Sorry, something went wrong.
There was a problem hiding this comment.
Not sure it's possible in all cases, as I would need to know that the column of a type json, so it'll require either a lookup to the sqlalchemy's metadata or to the DB schema. But I'll have a look at how easy it can be.
Sorry, something went wrong.
There was a problem hiding this comment.
it'll require either a lookup to the sqlalchemy's metadata or to the DB schema
If it means a lookup then let's not do it. I'm just not clear why JSONField isn't already handling the serialization for us in this case. Might need some more looking into?
Sorry, something went wrong.
There was a problem hiding this comment.
yeah, I'm dealing with it now, there're several facets to approach it.
it can work canonically, but the field has to be sqlalchemy.dialects.postgresql.JSON, but aiopg returns back (over select) the decoded value and it breaks the RowProxy as it expects string.
so, i'm looking for compromise/settings to get the balance
Sorry, something went wrong.
There was a problem hiding this comment.
ok, it was the matter of the dialect class, I reused the one that's in use for the integration with sa part of aoipg it got back to normal.
Sorry, something went wrong.
| await cursor.executemany(insert_query, values) | ||
| elif database.url.scheme == "postgresql+aiopg": | ||
| cursor = await raw_connection.cursor() | ||
| # No async support for `executemany` |
There was a problem hiding this comment.
Okay, in these kinds of cases we should still support the .executemany API, even if all it actually does is for value in values: ...execute... under the hood.
(We can document limitations of particular drivers, but it'd def. be a benefit if we can keep the API the same, even if there's different performance characteristics in some cases.)
Sorry, something went wrong.
There was a problem hiding this comment.
Yeah, I see and agree, will try my best.
Sorry, something went wrong.
There was a problem hiding this comment.
Ok, it's the test for the raw driver across different backends, but aiopg has the implementation for execute_many and yeah it's with the for loop.
Sorry, something went wrong.
There was a problem hiding this comment.
Grand, let's just hook our backend implementation up to that then, right?
Sorry, something went wrong.
There was a problem hiding this comment.
All should be in place! I have a unittest to test it for database.execute_many.
Sorry, something went wrong.
There was a problem hiding this comment.
this case is the battle test of the raw driver, so it replicates backend implementations in some places.
Sorry, something went wrong.
| database_url = DatabaseURL(url) | ||
| if database_url.dialect == "mysql": | ||
| url = str(database_url.replace(driver="pymysql")) | ||
| elif database_url.driver == "aiopg": |
There was a problem hiding this comment.
Let's check the .scheme here instead in these conditionals.
Sorry, something went wrong.
There was a problem hiding this comment.
fixed
Sorry, something went wrong.
|
Yes yes yes! Let's make this a priority. 🚀 |
Sorry, something went wrong.
|
Awesome, thanks @tomchristie! |
Sorry, something went wrong.
|
@tomchristie I think it's in good shape now. There's only one open question - lastrowid, but I'm not sure about the universal, consistent and reliable solution for that. Happy to follow up on it in the next PR if it's more reasonable. |
Sorry, something went wrong.
|
hi @tomchristie! A gentle nudge here, I think it's mergeable. Happy to follow up on any appeared issues anyway. |
Sorry, something went wrong.
|
What would be the point of this if databases already works with asyncpg? |
Sorry, something went wrong.
|
@StephenCarboni There's a bunch of different reasons, but the main point is asyncpg and aiopg are totally different, including underlying lower-level drivers, internal and external APIs, and even query syntax details. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
No description provided.