SQL Alchemy
Катаев Денис
SQL Alchemy
о чем доклад
SQL
в 2018 году
modern-sql.com
RedBook.io
5 издание
10 лет спустя 4го издания

Комментарии к академическим статьям по базам данных
Object-relational
impedance mismatch
Vietnam
of Computer Science
- Концепты ООП
- Разница в типах данных
- Структурные и интеграционные различия
- Разница в управлении
- Разница в транзакциях
SQLAlchemy
SQLAlchemy considers the database to be a relational algebra engine, not just a collection of tables.
SQLAlchemy
представлена в 2005 году
автор: Michael Bayer

http://aosabook.org/en/sqlalchemy.html
SQLAlchemy
CORE & ORM

SQLAlchemy CORE
DDL
Data Definition Language
- Таблицы
- Индексы
- Ограничения (check, foreign key)
- Reflecting без кодогенерации
- ...
- PROFIT в виде миграций
SQLAlchemy CORE
Query
Запросы в базу данных
- select, insert, update
- insert from (select ...
- on conflict, merge
- returning
- ...
- PROFIT
SQLAlchemy CORE
SELECT m.*
FROM chatmessage m
JOIN chatthread th ON m.threadid = th.threadid
JOIN chatvisitsession s ON th.visitsessionid = s.visitsessionid
WHERE m.kind NOT IN %s
AND s.visitorid = %s
AND floor(m.insertedts/1e6) > %s
AND th.state != %s
import sqlalchemy as sa
from webim.database import Chat, Message, VisitSession
def query():
kinds = sa.bindparam('kinds', expanding=True)
visitor_id = sa.bindparam('visitor_id')
time = sa.bindparam('time')
state = sa.bindparam('state')
join = sa.join(Message, Chat).join(VisitSession)
clause = Message.kind.notin_(kinds)
clause &= VisitSession.visitor_guid == visitor_id
clause &= sa.func.floor(Message.inserted_ts / 1e6) > time
clause &= Chat.state != state
return sa.select([Message], clause, from_obj=join)
SQLAlchemy CORE
Абстракция над движкам
+ Graceful Degradation
SQLAlchemy CORE
Фичи движков
поддержка на python
enum, json, fts, array types, index types, function index
SQLAlchemy CORE
Расширяемость
Красивый код на python
долой RAW запросы
SQLAlchemy Recipes
SQLAlchemy ORM
User defined class
+ polymorph mapper
Можно прикрутить любой python класс к базе незаметно для него

SQLAlchemy ORM
Declarative
Описываем сразу таблицу как класс
Но не получаем ни каких артефактов в добавок
Нет классического active record паттерна, т.е нет:
- .remove()
- .save()
- и т.д
SQLAlchemy ORM
Session
Близнец транзакции на стороне Python
Явный объект который создаешь когда хочешь,
а не на каждый запрос
session.add(user1) # insert session.delete(user2) # delete user3.name = 'new name' session.add(user3) # update
SQLAlchemy ORM
Relationships
Связь без FK или FK без связи – это ОК

SQLAlchemy ORM
Relationships
Способы загрузки отношений
- join
- subselect
- dynamic
- noload
Коллекции в том числе и создание
- list
- dict
- set
- что угодно
Момент загрузки
- lazy
- nolazy
- readonly
- raiseload
SQLAlchemy ORM
Relationships
Отношения без PK
user = User('foo') user.dep = Department('bar') user.save() user.dep.save()
SQLAlchemy ORM
Query
Превращаем строки таблицы в объекты
в т.ч из запросов core
session.query(User).filter(User.name == 'test')
У колонок переопределены многие операторы сравнений
(User.name == 'foo') | (User.name == 'bar')
В том числе любой доступный в базе и определять свои
User.id.op('#')(0xff) # bitwise xor postgresql
SQLAlchemy ORM
Query
встроенного get_or_create нет и не будет
Поскольку он завязан на поведение определенного уровня изоляции READ COMMITTED
А что если он нужен (привыкли к нему)?
SQLAlchemy
Other
- sqlalchemy-utils
- wtforms
- flask-admin
- flask-restless
- ...
asyncio?
Спасибо за внимание
SQL Alchemy
By Denis Kataev
SQL Alchemy
- 1,076