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

  1. Таблицы
  2. Индексы
  3. Ограничения (check, foreign key)
  4. Reflecting без кодогенерации
  5. ...
  6. PROFIT в виде миграций

SQLAlchemy CORE

Query

Запросы в базу данных

  1. select, insert, update
  2. insert from (select ...
  3. on conflict, merge
  4. returning
  5. ...
  6. 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

Способы загрузки отношений

  1. join
  2. subselect
  3. dynamic
  4. noload

Коллекции в том числе и создание

  1. list
  2. dict
  3. set
  4. что угодно

Момент загрузки

  1. lazy
  2. nolazy
  3. readonly
  4. 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