Skip to content

Commit e2dfd4e

Browse files
committed
update sqlalchemy doc
1 parent 80aa389 commit e2dfd4e

1 file changed

Lines changed: 95 additions & 44 deletions

File tree

docs/posts/2025/2025-12-30-sqlalchemy-cheetsheet.md

Lines changed: 95 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,112 @@ date:
1010
published: false
1111
---
1212

13-
# SQLAlchemy cheatsheet
13+
# SQLAlchemy cheat-sheet
1414

1515
## Architecture
1616

1717
https://aosabook.org/en/v2/sqlalchemy.html
1818

19+
## Online tutorials
20+
21+
* https://leapcell.medium.com/leapcell-the-next-gen-serverless-platform-for-python-app-hosting-0722d1b32047
22+
23+
<!-- more -->
24+
1925
## Engine, Connection, and Session
2026

2127
https://stackoverflow.com/questions/34322471/sqlalchemy-engine-connection-and-session-difference
2228

23-
## Renew connection/session credentials
29+
### Session-level vs. Engine level transaction control
30+
31+
Just copied from the [official documentation](https://docs.sqlalchemy.org/en/20/orm/session_transaction.html#session-level-vs-engine-level-transaction-control):
32+
33+
| ORM | Core |
34+
| ------------------------------------------ | ------------------------------------------ |
35+
| sessionmaker | Engine |
36+
| Session | Connection |
37+
| sessionmaker.begin() | Engine.begin() |
38+
| some_session.commit() | some_connection.commit() |
39+
| with some_sessionmaker() as session: | with some_engine.connect() as conn: |
40+
| with some_sessionmaker.begin() as session: | with some_engine.begin() as conn: |
41+
| with some_session.begin_nested() as sp: | with some_connection.begin_nested() as sp: |
42+
43+
### with Session() as session vs with Session.begin() as session
44+
45+
ref: https://docs.sqlalchemy.org/en/20/orm/session_api.html#session-and-sessionmaker
46+
47+
```python hl_lines="11"
48+
from sqlalchemy import create_engine
49+
from sqlalchemy.orm import sessionmaker
50+
51+
# an Engine, which the Session will use for connection resources
52+
engine = create_engine("postgresql+psycopg2://scott:tiger@localhost/")
53+
54+
Session = sessionmaker(engine)
55+
with Session() as session:
56+
session.add(some_object)
57+
session.add(some_other_object)
58+
# need manual commit
59+
session.commit()
60+
```
61+
62+
```python
63+
with Session.begin() as session:
64+
# auto commits on context exit
65+
session.add(some_object)
66+
session.add(some_other_object)
67+
```
68+
69+
| Aspect | with Session() as session | with Session.begin() as session |
70+
| ----------------------------- | ---------------------------------------- | ------------------------------------- |
71+
| Transaction Start immediately | same | same |
72+
| Session is closed on complete | same | same |
73+
| Rollback on Exception | same | same |
74+
| (different) Commit Behavior | Requires explicit commit to save changes | Automatically commits on context exit |
75+
76+
### Using event lister to refresh volatile authentication credentials
77+
78+
* https://github.com/sqlalchemy/sqlalchemy/discussions/7148
79+
* https://github.com/sqlalchemy/sqlalchemy/discussions/12133
80+
* https://github.com/sqlalchemy/sqlalchemy/discussions/8349
81+
* https://github.com/sqlalchemy/sqlalchemy/discussions/11806
82+
* https://docs.sqlalchemy.org/en/20/dialects/mssql.html#mssql-pyodbc-access-tokens
83+
* https://community.snowflake.com/s/article/Snowflake-OAuth-Support-Guide
84+
* https://community.snowflake.com/s/article/Create-External-OAuth-Token-Using-Azure-AD-For-The-OAuth-Client-Itself
85+
86+
Use the [event lister to refresh volatile authentication credentials](https://docs.sqlalchemy.org/en/20/core/engines.html#generating-dynamic-authentication-tokens).
87+
88+
Event Hooks:
89+
90+
* `checkout` Event: Triggered when a connection is checked out from the pool. Useful for tasks like setting session-level parameters. each `engine.connect()` will trigger this event.
91+
* `checkin` Event: Triggered when a connection is returned to the pool (reverse operation of `checkout`). Can be used for cleanup tasks.
92+
* `connect` Event:
93+
Type: Notification Event
94+
Purpose: Triggered after a new DBAPI connection has been established.
95+
Usage: Primarily used for performing actions post-connection, such as setting session-level parameters, initializing database schemas, or logging connection details. First `engine.connect()` (not the subsequent) will trigger this event.
96+
* `do_connect` Event:
97+
Type: Customization Hook
98+
Purpose: Allows developers to override or customize the actual process of establishing a new DBAPI connection.
99+
Usage: Useful when you need to implement custom connection logic, integrate with non-standard DBAPI drivers, or modify connection parameters dynamically. First `engine.connect()` (not the subsequent) will trigger this event.
100+
`do_connect` event is triggered before the `connect` event.
101+
102+
```python
103+
from sqlalchemy import event
104+
105+
engine = create_engine("postgresql://user@hostname/dbname")
24106

25-
- https://github.com/sqlalchemy/sqlalchemy/discussions/7148
26-
- https://github.com/sqlalchemy/sqlalchemy/discussions/12133
27-
- https://github.com/sqlalchemy/sqlalchemy/discussions/8349
28-
- https://github.com/sqlalchemy/sqlalchemy/discussions/11806
29-
- https://docs.sqlalchemy.org/en/20/dialects/mssql.html#mssql-pyodbc-access-tokens
30-
- https://community.snowflake.com/s/article/Snowflake-OAuth-Support-Guide
31-
- https://community.snowflake.com/s/article/Create-External-OAuth-Token-Using-Azure-AD-For-The-OAuth-Client-Itself
107+
108+
@event.listens_for(engine, "do_connect")
109+
def provide_token(dialect, conn_rec, cargs, cparams):
110+
cparams["token"] = get_authentication_token()
111+
```
112+
113+
Some vendor specific SQL servers ([Snowflake for .e.g](https://github.com/snowflakedb/snowflake-sqlalchemy/issues/550)) implementations some kind of keep-live heartbeat mechanism to keep the connection alive. Which means once the user is logged in, the connection (user session) will be kept alive until the user logs out even the token is expired. User don't need to send small query to keep alive, as the keep-alive signals are sent in background by the vendor specific module implicitly. This is useful for long running applications.
32114

33115
## mapped_column vs column property
34116

35-
- <https://docs.sqlalchemy.org/en/20/orm/declarative_tables.html#declarative-table-with-mapped-column>
36-
- <https://stackoverflow.com/a/76499049/5095636>
117+
* <https://docs.sqlalchemy.org/en/20/orm/declarative_tables.html#declarative-table-with-mapped-column>
118+
* <https://stackoverflow.com/a/76499049/5095636>
37119

38120
```python title="Column from sqlalchemy directly"
39121
from sqlalchemy import Column
@@ -48,8 +130,8 @@ from sqlalchemy.orm import mapped_column
48130
The [mapped_column()](https://docs.sqlalchemy.org/en/20/orm/mapping_api.html#sqlalchemy.orm.mapped_column) can have type annotations within a special SQLAlchemy type called [Mapped](https://docs.sqlalchemy.org/en/20/orm/internals.html#sqlalchemy.orm.Mapped).
49131
For e.g.:
50132

51-
- `fullname: Mapped[str]` is compiled to SQL: `fullname VARCHAR NOT NULL`
52-
- `fullname: Mapped[Optional[str]]` is compiled to SQL: `fullname VARCHAR`
133+
* `fullname: Mapped[str]` is compiled to SQL: `fullname VARCHAR NOT NULL`
134+
* `fullname: Mapped[Optional[str]]` is compiled to SQL: `fullname VARCHAR`
53135

54136
[Default type map](https://docs.sqlalchemy.org/en/20/orm/declarative_tables.html#mapped-column-derives-the-datatype-and-nullability-from-the-mapped-annotation) ():
55137

@@ -80,34 +162,3 @@ type_map: Dict[Type[Any], TypeEngine[Any]] = {
80162
uuid.UUID: types.Uuid(),
81163
}
82164
```
83-
84-
## Refreshing volatile authentication tokens
85-
86-
Use the [event lister to refresh volatile authentication credentials](https://docs.sqlalchemy.org/en/14/core/engines.html#generating-dynamic-authentication-tokens).
87-
88-
Event Hooks:
89-
90-
- `checkout` Event: Triggered when a connection is checked out from the pool. Useful for tasks like setting session-level parameters. each `engine.connect()` will trigger this event.
91-
- `checkin` Event: Triggered when a connection is returned to the pool (reverse operation of `checkout`). Can be used for cleanup tasks.
92-
- `connect` Event:
93-
Type: Notification Event
94-
Purpose: Triggered after a new DBAPI connection has been established.
95-
Usage: Primarily used for performing actions post-connection, such as setting session-level parameters, initializing database schemas, or logging connection details. First `engine.connect()` (not the subsequent) will trigger this event.
96-
- `do_connect` Event:
97-
Type: Customization Hook
98-
Purpose: Allows developers to override or customize the actual process of establishing a new DBAPI connection.
99-
Usage: Useful when you need to implement custom connection logic, integrate with non-standard DBAPI drivers, or modify connection parameters dynamically. First `engine.connect()` (not the subsequent) will trigger this event.
100-
`do_connect` event is triggered before the `connect` event.
101-
102-
```python
103-
from sqlalchemy import event
104-
105-
engine = create_engine("postgresql://user@hostname/dbname")
106-
107-
108-
@event.listens_for(engine, "do_connect")
109-
def provide_token(dialect, conn_rec, cargs, cparams):
110-
cparams["token"] = get_authentication_token()
111-
```
112-
113-
Some vendor specific SQL servers ([Snowflake for .e.g](https://github.com/snowflakedb/snowflake-sqlalchemy/issues/550)) implementations some kind of keep-live heartbeat mechanism to keep the connection alive. Which means once the user is logged in, the connection (user session) will be kept alive until the user logs out even the token is expired. User don't need to send small query to keep alive, as the keep-alive signals are sent in background by the vendor specific module implicitly. This is useful for long running applications.

0 commit comments

Comments
 (0)