Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

SQLAlchemy

Глава 20 из книги "Архитектура приложений с открытым исходным кодом", том 2.

Оригинал: SQLAlchemy
Автор: Michael Bayer
Перевод: А. Панин

20.7. Методы выполнения запросов и загрузки данных

SQLAlchemy инициирует все связанные с загрузкой объектов действия с помощью объекта с именем Query. Стандартный процесс инициализации объекта Query начинается с включения примитивов (entites), которые формируют список классов, используемых для отображения и/или индивидуальных SQL-запросов, которые должны быть выполнены. Он также содержит ссылку на объект Session, который представляет соединение с одной или большим количеством баз данных, а также кэш данных, который был собран при осуществлении транзакций в ходе использования этих соединений. Ниже представлен элементарный пример использования этих объектов:
from sqlalchemy.orm import Session
session = Session(engine)
query = session.query(User)

Мы создаем объект Query, который использует экземпляры класса User, относящиеся к новому объекту сессии Session, который мы создали. Объект Query использует генеративный шаблон проектирования builder таким же образом, как и описанная ранее конструкция select, где дополнительные критерии и модификаторы ассоциировались с конструкциями выражений для выполнения одного вызова метода в каждый момент времени. Когда итеративная операция выполняется в отношении объекта Query, он создает конструкцию SQL-запроса SELECT, выполняет этот запрос с помощью базы данных, после чего интерпретирует результирующий набор строк как результирующие данные объектно-реляционного отображения в соответствии с набором изначально запрашиваемых элементов.

Объект Query производит жесткое разделение между частями операции, относящимися к формированию SQL-запросов (SQL rendering) и частями операции, относящимися к загрузке данных (data loading). Первый случай относится к созданию запроса SELECT, а второй - к интерпретации полученных после выполнения SQL-запроса строк как конструкций объектно-реляционного отображения. Фактически данные могут обрабатываться без выполнения шага, заключающегося в формировании SQL-запроса, так как объект Query может интерпретировать результаты выполнения текстового запроса, сформированного пользователем вручную.

И в процессе формирования SQL-запроса, и в процессе загрузки данных используется рекурсивный обход графа, образованного наборами объектов Mapper, причем каждый содержащий данные столбца или SQL-запроса объект ColumnProperty рассматривается как узел, а каждый объект RelationshipProperty, который включается в запрос с помощью так называемой стратегии "eager-load" - как ребро графа, ведущее к другой представленной объектом Mapper вершине. Обход и выполнение действия при достижении каждого из узлов в конечном счете является задачей каждого объекта LoaderStrategy, ассоциированного с каждым объектом MapperProperty, осуществляющим добавление столбцов и объединений к запросу SELECT, создаваемому на этапе формирования запроса и создающему функции языка Python для обработки результирующих строк на этапе загрузки данных.

Все функции языка Python, создающиеся на этапе загрузки данных, получают по строке из базы данных по мере извлечения и в результате производят возможные изменения состояния отображенного атрибута в памяти. Они создаются для определенного атрибута в соответствии с условием, базирующимся на исследовании первой строки из полученного набора результирующих данных, а так же на параметрах загрузки. Если загрузка атрибута не производится, пригодной для вызова функции не создается.

Рисунок 20.12 иллюстрирует обход нескольких объектов LoaderStrategy при сценарии загрузки данных в соответствии со стратегией "joined eager loading" с указанием на их объединение с формируемым SQL-запросом, который появляется в ходе вызова метода _compile_context объекта Query. На нем также показан процесс генерации функций обработки строк (row population functions), которые получают результирующие строки и задают отдельные атрибуты объектов, причем сам этот процесс инициируется с помощью метода instances объекта Query.

Обход объектов при использовании стратегий загрузки, включая стратегию
Рисунок 20.12: Обход объектов при использовании стратегий загрузки, включая стратегию "joined eager load"

Ранее в SQLAlchemy использовался подход, заключающийся в сборе результатов, полученных после вызовов фиксированных, ассоциированных с каждой стратегией методов объектов для получения каждой строки таблицы и выполнения соответствующих действий. Система загрузки с возможностью вызова функций была впервые представлена в версии 0.5 и позволила значительно повысить производительность системы, так как большое количество решений в отношении обработки строк таблицы могло быть принято прямо перед началом их обработки вместо повторного принятия решений для каждой строки, а также большое количество не имеющих эффекта вызовов функций могло быть устранено.


Продолжение статьи: Сессия и индивидуальное отображение