1.4 Changelog¶
В этом документе подробно описаны отдельные изменения на уровне проблем, внесенные в релиз 1.4. Для получения подробного обзора того, что нового появилось в версии 1.4, смотрите What’s New in SQLAlchemy 1.4?.
1.4.43¶
no release date1.4.42¶
Released: October 16, 2022orm¶
Словарь
Session.execute.bind_arguments
больше не мутирует при передаче вSession.execute()
и подобные; вместо этого он копируется во внутренний словарь при изменении состояния. Помимо прочего, это исправляет проблему, когда «clause», передаваемый методуSession.get_bind()
, неправильно ссылался на конструкциюSelect
, используемую для стратегии синхронизации «fetch», когда фактический запрос былDelete
илиUpdate
. Это помешало бы рецептам для «сессий маршрутизации».References: #8614
В конфигурациях ORM выдается предупреждение, когда явная аннотация
remote()
применяется к столбцам, которые являются локальными для непосредственного сопоставленного класса, когда сопоставленный класс не включает ни одного из тех же столбцов таблицы. В идеале это должно вызывать ошибку в какой-то момент, поскольку это некорректно с точки зрения отображения.References: #7094
Предупреждение выдается при попытке сконфигурировать сопоставленный класс в иерархии наследования, где сопоставителю не задана полиморфная идентичность, но назначен столбец полиморфного дискриминатора. Такие классы должны быть абстрактными, если они никогда не будут загружаться напрямую.
References: #7545
Исправлена регрессия в версии 1.4 в
contains_eager()
, когда логика «обертывания в подзапрос» вjoinedload()
непреднамеренно срабатывала при использовании функцииcontains_eager()
с аналогичными утверждениями (например, использующимиdistinct()
,limit()
илиoffset()
), что приводило к вторичным проблемам с запросами, использующими некоторые комбинации имен SQL-меток и алиасинга. Такая «обертка» не подходит дляcontains_eager()
, который всегда имел договор о том, что пользовательский SQL-запрос не модифицируется, за исключением добавления соответствующих столбцов для извлечения.References: #8569
Исправлена регрессия, при которой использование ORM update() с synchronize_session=“fetch“ приводило к неудаче из-за использования оценщиков, которые теперь используются для определения значения in-Python для выражений в предложении SET при обновлении объектов; если в оценщиках используются математические операторы для нечисловых значений, таких как PostgreSQL JSONB, условие неоценки не будет определено правильно. Теперь оценщик ограничивает использование операторов математической мутации только числовыми типами, за исключением «+», который продолжает работать и для строк. В SQLAlchemy 2.0 это может быть изменено еще больше за счет полного извлечения значений SET вместо использования оценки.
References: #8507
engine¶
Исправлена проблема, из-за которой смешивание «*» с дополнительными явно именованными выражениями столбцов в пункте columns конструкции
select()
приводило к тому, что нацеливание на столбец результата иногда считало имя метки или другие неповторяющиеся имена неоднозначной целью.References: #8536
asyncio¶
Улучшена реализация
asyncio.shield()
, используемого в менеджерах контекста, как добавлено в #8145, таким образом, что операция «закрытия» заключена вasyncio.Task
, на который затем идет сильная ссылка по мере выполнения операции. Это сделано в соответствии с документацией Python, указывающей, что в противном случае задача не является сильно ссылающейся.References: #8516
postgresql¶
aggregate_order_by
теперь поддерживает генерацию кэша.References: #8574
mysql¶
Скорректировано регулярное выражение, используемое для соответствия «CREATE VIEW» при тестировании представлений, для более гибкой работы, больше не требуя специального ключевого слова «ALGORITHM» в середине, которое должно было быть необязательным, но работало неправильно. Это изменение позволяет отражению представлений работать более полно на MySQL-совместимых вариантах, таких как StarRocks. Pull request любезно предоставлен Джоном Бодли.
References: #8588
mssql¶
Исправлена еще одна регрессия в выборке уровня изоляции SQL Server (см. #8231, #8475), на этот раз с «Microsoft Dynamics CRM Database via Azure Active Directory», в которой, очевидно, полностью отсутствует представление
system_views
. Отлов ошибок был расширен, чтобы ни при каких обстоятельствах этот метод никогда не давал сбоев, при условии наличия подключения к базе данных.References: #8525
1.4.41¶
Released: September 6, 2022orm¶
Исправлена проблема прослушивания событий, когда слушатели событий, добавленные в суперкласс, терялись, если создавался подкласс, который затем имел свои собственные слушатели. Практический пример - класс
sessionmaker
, созданный после того, как события были ассоциированы с классомSession
.References: #8467
Усилена стратегия кэширования ключей для конструкций
aliased()
иwith_polymorphic()
. Хотя проблемы с кэшированием фактических утверждений не могут быть легко продемонстрированы (если вообще могут быть), эти две конструкции не включали в свои ключи кэша достаточно того, что делает их уникальными, чтобы кэширование только по псевдослучайной конструкции было точным.References: #8401
Исправлена регрессия, появившаяся в серии 1.4, когда запрос с объединенным наследованием, помещенный в качестве подзапроса во вложенный запрос для той же сущности, не мог корректно отобразить JOIN для внутреннего запроса. Проблема проявлялась двумя разными способами до и после версии 1.4.18 (связанная проблема #6595), в одном случае JOIN отображался дважды, в другом - JOIN полностью терялся. Для решения проблемы условия, при которых применяется «полиморфная загрузка», были изменены таким образом, чтобы они не применялись для простых запросов с объединенным наследованием.
References: #8456
Исправлена проблема в расширении
sqlalchemy.ext.mutable
, когда ссылки коллекции на родительский объект терялись, если объект был объединен сSession.merge()
при одновременной передачеSession.merge.load
как False.References: #8446
Исправлена проблема с
with_loader_criteria()
, когда переменная закрытия, используемая в качестве значения связанного параметра в лямбде, не переносилась корректно в дополнительные загрузчики отношений, такие какselectinload()
иlazyload()
после кэширования утверждения, используя вместо этого устаревшее первоначально кэшированное значение.References: #8399
sql¶
Исправлена проблема, при которой использование конструкции
table()
, передающей строку для параметраtable.schema
, не учитывало строку «schema» при создании ключа кэша, что приводило к коллизии кэширования, если использовалось несколько одноименных конструкцийtable()
с разными схемами.References: #8441
asyncio¶
Интегрирована поддержка вызова метода asyncpg
terminate()
для случаев, когда пул соединений перерабатывает соединение, возможно, завершившееся по таймеру, когда происходит сборка мусора, который не был изящно закрыт, а также когда соединение было признано недействительным. Это позволяет asyncpg отказаться от соединения, не дожидаясь ответа, который может иметь длительный таймаут.References: #8419
mssql¶
Исправлена регрессия, вызванная исправлением для #8231, выпущенным в версии 1.4.40, когда при попытке определить текущий уровень изоляции транзакции соединение не устанавливалось, если у пользователя не было разрешения на запрос системных представлений
dm_exec_sessions
илиdm_pdw_nodes_exec_sessions
.References: #8475
1.4.40¶
Released: August 8, 2022orm¶
Исправлена проблема, при которой многократное обращение к CTE в сочетании с полиморфным SELECT могло привести к созданию нескольких «клонов» одного и того же CTE, в результате чего эти два CTE считались дубликатами. Для решения этой проблемы два CTE подвергаются глубокому сравнению, когда это происходит, чтобы убедиться, что они эквивалентны, а затем рассматриваются как эквивалентные.
References: #8357
Конструкция
select()
, которой передается единственный аргумент „*“ дляSELECT *
, либо через строку, либо черезtext()
, либо черезliteral_column()
, будет интерпретироваться как SQL-оператор уровня Core, а не как оператор уровня ORM. Это делается для того, чтобы*
при расширении на любое количество столбцов приводил к возврату всех столбцов в результат. Интерпретацияselect()
на уровне ORM требует предварительного знания имен и типов всех столбцов ORM, чего нельзя достичь при использовании'*'
.Если
'*
используется среди других выражений одновременно с оператором ORM, возникает ошибка, так как это не может быть правильно интерпретировано ORM.References: #8235
orm declarative¶
Исправлена проблема, при которой иерархия классов, установленная как абстрактные или декларативные классы mixin, не могла объявить отдельные колонки в суперклассе, которые затем корректно копировались в вызываемую переменную
declared_attr
, которая хотела использовать их в классе-потомке.References: #8190
engine¶
Реализована новая опция
Connection.execution_options.yield_per
выполнения дляConnection
в Core, чтобы отразить ту же самую опцию yield_per, доступную в ORM. Опция устанавливает оба параметраConnection.execution_options.stream_results
одновременно с вызовомResult.yield_per()
, чтобы обеспечить наиболее распространенную конфигурацию потокового результата, которая также отражает схему использования ORM.См.также
Использование курсоров на стороне сервера (они же потоковые результаты) - пересмотренная документация
Исправлена ошибка в
Result
, когда при использованииConnection.execution_options.stream_results
не использовалась стратегия буферизованного результата, если используемый диалект не поддерживал явную настройку «курсор на стороне сервера». Это ошибочно, поскольку такие DBAPI, как SQLite и Oracle, уже используют небуферизованную схему получения результатов, которая все еще выигрывает от использования частичной выборки результатов. Теперь стратегия «буферизации» используется во всех случаях, когда установлено значениеConnection.execution_options.stream_results
.Добавлено
FilterResult.yield_per()
, чтобы реализации результата, такие какMappingResult
,ScalarResult
иAsyncResult
, имели доступ к этому методу.References: #8199
sql¶
Скорректирована компиляция SQL для функций конкатенации строк
.contains()
,.startswith()
,.endswith()
, чтобы заставить использовать оператор конкатенации строк, а не полагаться на перегрузку оператора сложения, так что нестандартное использование этих операторов, например, с байтстрингами, по-прежнему приводит к операторам конкатенации строк.References: #8253
mypy¶
Исправлено падение плагина mypy при использовании лямбды в качестве Column по умолчанию. Pull request curtesy of tchapi.
References: #8196
asyncio¶
Добавлено
asyncio.shield()
в процесс освобождения соединения и сессии, в частности, в рамках выхода из контекстного менеджера__aexit__()
, при использованииAsyncConnection
илиAsyncSession
в качестве контекстного менеджера, который освобождает объект по завершении работы контекстного менеджера. Это, по-видимому, помогает при отмене задачи при использовании альтернативных библиотек параллелизма, таких какanyio
,uvloop
, которые в противном случае не обеспечивают асинхронный контекст для пула соединений, чтобы правильно освободить соединение при отмене задачи.References: #8145
postgresql¶
Исправлена проблема в диалекте psycopg2, когда функция «нескольких хостов», реализованная для #4392, где несколько пар
host:port
могли быть переданы в строке запроса как?host=host1:port1&host=host2:port2&host=host3:port3
, была реализована неправильно, так как она не распространяла параметр «порт» соответствующим образом. Соединения, которые не использовали другой «порт», скорее всего, работали без проблем, а соединения, которые имели «порт» для некоторых записей, могли неправильно передавать это имя хоста. Теперь формат исправлен, чтобы передавать хосты/порты должным образом.В рамках этого изменения была сохранена поддержка другого стиля мультихостов, который работал непреднамеренно, а именно разделенных запятыми
?host=h1,h2,h3&port=p1,p2,p3
. Этот формат более соответствует формату строк запросов libpq, в то время как предыдущий формат вдохновлен другим аспектом формата URI libpq, но это не совсем то же самое.Если эти два стиля смешиваются вместе, возникает ошибка, так как это двусмысленно.
References: #4392
mssql¶
Исправлены проблемы, из-за которых новые шаблоны использования DML с объектами ORM, представленные в Использование INSERT, UPDATE и ON CONFLICT (т.е. upsert) для возврата объектов ORM, не работали корректно с диалектом SQL Server pyodbc.
References: #8210
Исправлена проблема, при которой запрос диалекта SQL Server на текущий уровень изоляции не выполнялся в Azure Synapse Analytics из-за того, как эта база данных обрабатывает откат транзакций после возникновения ошибки. Начальный запрос был изменен, чтобы больше не полагаться на поимку ошибки при попытке определить соответствующее системное представление. Кроме того, для лучшей поддержки очень специфического поведения «отката» этой базы данных, реализован новый параметр
ignore_no_transaction_on_rollback
, указывающий, что при откате следует игнорировать ошибку Azure Synapse „Соответствующая транзакция не найдена. (111214)», которая возникает в случае отсутствия транзакции в конфликте с Python DBAPI.Первоначальный патч и ценная помощь в отладке любезно предоставлены @ww2406.
См.также
azure_synapse_ignore_no_transaction_on_rollback
References: #8231
misc¶
Исправлена проблема, когда оператор
TypeDecorator
некорректно проксировал оператор__getitem__()
при оформлении типа данныхARRAY
без явного обходного пути.References: #7249
1.4.39¶
Released: June 24, 2022orm¶
Исправлена регрессия, вызванная #8133, когда формат pickle для изменяемых атрибутов был изменен без отката для распознавания старого формата, что приводило к тому, что обновления SQLAlchemy на месте больше не могли читать pickle-данные из предыдущих версий. Теперь установлена проверка плюс откат для старого формата.
References: #8133
1.4.38¶
Released: June 23, 2022orm¶
Исправлена регрессия, вызванная #8064, когда определенная проверка соответствия столбцов была сделана слишком либеральной, что приводило к некорректному отображению для некоторых подзапросов ORM, например, использующих
PropComparator.has()
илиPropComparator.any()
в сочетании с запросами с объединенным наследованием, которые также используют унаследованные функции алиасинга.References: #8162
Исправлена проблема, при которой
GenerativeSelect.fetch()
не применялось при выполнении оператора с использованием ORM.References: #8091
Исправлена проблема, когда опция
with_loader_criteria()
не могла быть отбираемой, что необходимо, когда она переносится для распространения в ленивые загрузчики в сочетании со схемой кэширования. В настоящее время единственная форма, которая поддерживается как picklable - это передача «where criteria» в виде фиксированной вызываемой функции на уровне модуля, которая производит SQL-выражение. Специальная «лямбда» не может быть пикирована, а объект SQL-выражения обычно не может быть полностью пикирован напрямую.References: #8109
engine¶
Исправлен декоратор класса с предупреждением об устаревании, который не позволял ключевым объектам, таким как
Connection
, иметь правильный атрибут__weakref__
, что приводило к ошибкам в операциях, таких как стандартная библиотека Pythoninspect.getmembers()
.References: #8115
sql¶
Исправлено несколько наблюдаемых условий гонки, связанных с
lambda_stmt()
, включая начальную проблему «dogpile», когда новый объект кода Python первоначально анализируется в нескольких одновременных потоках, что создавало как проблему производительности, так и некоторое внутреннее повреждение состояния. Кроме того, было исправлено состояние гонки, которое могло возникнуть при «клонировании» конструкции выражения, которая также находится в процессе компиляции или иного доступа в другом потоке из-за мемоизированных атрибутов, изменяющих__dict__
во время итерации, для версий Python до 3.10; в частности, конструкция lambda SQL чувствительна к этому, поскольку она постоянно удерживает один объект оператора. Итерация была усовершенствована, чтобы вместо нее использоватьdict.copy()
с дополнительной итерацией или без нее.References: #8098
Усовершенствован механизм
Cast
и других «обертывающих» конструкций колонок для более полного сохранения обернутой конструкцииLabel
, включая то, что имя метки будет сохранено в коллекции.c
коллекцииSubquery
. Метка уже была способна корректно отображаться в SQL на внешней стороне конструкции, внутри которой она была обернута.References: #8084
Исправлено исправление, сделанное для #8056, которое корректировало экранирование имен связанных параметров со специальными символами таким образом, что экранированные имена транслировались после шага компиляции SQL, что нарушало опубликованный в FAQ рецепт, иллюстрирующий, как объединить имена параметров в строковый вывод скомпилированной строки SQL. Это изменение восстанавливает экранированные имена, идущие от
compiled.params
, и добавляет условный параметр кSQLCompiler.construct_params()
с именемescape_names
, который по умолчанию принимает значениеTrue
, восстанавливая старое поведение по умолчанию.References: #8113
schema¶
Исправлены ошибки, связанные с параметрами
Table.include_columns
иTable.resolve_fks
наTable
; эти малоиспользуемые параметры, очевидно, не работали для столбцов, ссылающихся на ограничения внешнего ключа.В первом случае не включенные столбцы, ссылающиеся на внешние ключи, все равно будут пытаться создать объект
ForeignKey
, выдавая ошибки при попытке разрешить столбцы для ограничения внешнего ключа в рамках рефлексии; ограничения внешнего ключа, ссылающиеся на пропущенные столбцы, теперь исключаются из процесса рефлексии таблицы так же, как это происходит для объектовIndex
иUniqueConstraint
с теми же условиями. Однако предупреждение не выдается, так как в версии 2.0 мы, вероятно, захотим убрать предупреждения include_columns для всех ограничений.В последнем случае создание псевдонимов таблиц или подзапросов будет завершаться неудачей, если FK связанная таблица не найдена, несмотря на наличие
resolve_fks=False
; логика была исправлена таким образом, что если связанная таблица не найдена, объектForeignKey
по-прежнему проксируется в псевдонимы таблицы или подзапроса (эти объектыForeignKey
обычно используются при создании условий присоединения), но он отправляется с флагом, что он не разрешимый. После этого псевдослужебная таблица / подзапрос будет работать нормально, за исключением того, что она не может быть использована для автоматического создания условия присоединения, поскольку информация о внешнем ключе отсутствует. Такое поведение уже было для подобных ограничений по внешнему ключу, созданных с помощью методов без отражения, например, при соединенииTable
объектов из разныхMetaData
коллекций.Исправлена проблема, при которой объекты
Table
, использующие столбцы IDENTITY с типом данныхNumeric
, выдавали ошибки при попытке согласования столбца «autoincrement», не позволяя построитьColumn
с использованием параметраColumn.autoincrement
, а также выдавая ошибки при попытке вызвать конструкциюInsert
.References: #8111
extensions¶
Исправлена ошибка в
Mutable
, когда при пикировке и распикировке отображаемого экземпляра ORM некорректно восстанавливалось состояние для отображений, содержащих несколько включенных атрибутовMutable
.References: #8133
1.4.37¶
Released: May 31, 2022orm¶
Исправлена проблема, при которой использование конструкции
column_property()
, содержащей подзапрос к уже сопоставленному атрибуту столбца, неправильно применяло поведение ORM-компиляции к подзапросу, включая то, что выражение «IN», добавленное для выражения наследования одной таблицы, не включалось.References: #8064
Исправлена проблема, при которой результаты ORM применяли неправильные имена ключей к возвращаемым объектам
Row
в случае, когда набор выбираемых столбцов был изменен, например, при использованииSelect.with_only_columns()
.References: #8001
Исправлена ошибка, вероятно, регрессия из версии 1.3, когда использование имен столбцов, требующих экранирования связанных параметров, более конкретно при использовании Oracle с именами столбцов, требующими кавычек, например, начинающихся с подчеркивания, или в менее распространенных случаях с некоторыми драйверами PostgreSQL при использовании имен столбцов, содержащих знаки процента, приводило к некорректной работе функции версионирования ORM, если сам столбец версионирования имел такое имя, поскольку ORM предполагал определенные соглашения об именовании связанных параметров, которым мешали кавычки. Этот выпуск связан с #8053 и по существу пересматривает подход к устранению этой проблемы, пересматривая исходный выпуск #5653, который создал первоначальную реализацию для обобщенного цитирования имен связанных параметров.
References: #8056
engine¶
sql¶
Исправлена ошибка, при которой метод PostgreSQL
Insert.on_conflict_do_update()
и метод SQLiteInsert.on_conflict_do_update()
не могли правильно разместить столбец с отдельным «.key» при указании столбца по имени ключа в словаре, передаваемом вInsert.on_conflict_do_update.set_
, а также при использовании коллекцииInsert.excluded
непосредственно в качестве словаря.References: #8014
Информативная ошибка возникает для случая, когда
Insert.from_select()
передается объект «compound select», такой как UNION, но оператор INSERT должен добавить дополнительные столбцы для поддержки Python-стороны или явных умолчаний SQL из метаданных таблицы. В этом случае следует передать подзапрос составного объекта.References: #8073
Исправлена проблема, при которой использование
bindparam()
без явного указания данных или типа могло приводить к неправильному типу при использовании в выражениях, например, при использованииComparator.any()
иComparator.all()
.References: #7979
Возникает информативная ошибка, если два отдельных объекта
BindParameter
имеют одинаковое имя, но один из них используется в «расширяющем» контексте (обычно выражение IN), а другой - нет; смешивание одного и того же имени в этих двух различных стилях использования не поддерживается, и обычно параметрexpanding=True
должен быть установлен для параметров, которые должны получать значения списка вне выражений IN (гдеexpanding
установлен по умолчанию).References: #8018
mysql¶
Дальнейшие корректировки диалекта MySQL PyODBC для обеспечения полного соединения, которое ранее не работало, несмотря на исправления в #7871.
References: #7966
Добавлен код отключения для ошибки MySQL 4031, появившейся в MySQL >= 8.0.24 и указывающей на превышение времени ожидания соединения. В частности, это устраняет проблему, когда предварительный пинг не мог переподключиться при превышении таймаута соединения. Pull request любезно предоставлен valievkarim.
References: #8036
mssql¶
oracle¶
Добавлены два новых кода ошибок для обработки отсоединения Oracle для поддержки раннего тестирования нового драйвера «python-oracledb», выпущенного Oracle.
References: #8066
Исправлена проблема компилятора SQL, когда функция «bind processing» для связанного параметра неправильно применялась к связанному значению, если имя связанного параметра было «экранировано». Конкретно это относится, в частности, к Oracle, когда
Column
имеет имя, которое само требует кавычек, так что требующее кавычек имя затем используется для связанных параметров, создаваемых в операторах DML, а используемый тип данных требует обработки связывания, например, тип данныхEnum
.References: #8053
1.4.36¶
Released: April 26, 2022orm¶
Исправлена регрессия, при которой изменение, внесенное в конструкцию #7861, выпущенную в версии 1.4.33, в результате которого конструкция
Insert
частично распознавалась как оператор с поддержкой ORM, не передавало правильное состояние маппера / сопоставленной таблицы вSession
, вызывая сбой методаSession.get_bind()
дляSession
, который был привязан к движкам и/или соединениям с помощью параметраSession.binds
.References: #7936
orm declarative¶
Модифицирован метакласс
DeclarativeMeta
для передачиcls.__dict__
в процесс декларативного сканирования для поиска атрибутов, а не отдельного словаря, передаваемого в метод__init__()
типа. Это позволяет пользовательским базовым классам, добавляющим атрибуты в__init_subclass__()
, работать так, как ожидается, поскольку__init_subclass__()
может влиять только на самcls.__dict__
, а не на другой словарь. Технически это является регрессом по сравнению с версией 1.3, где использовался метод__dict__
.References: #7900
engine¶
Исправлена утечка памяти в расширениях C, которая могла произойти при обращении к именованным членам
Row
, когда член не существует в Python 3; в частности, это могло произойти во время преобразований NumPy, когда он пытался вызвать такие члены, как.__array__
, но проблема была вокруг любогоAttributeError
, брошенного объектомRow
. Эта проблема не относится к версии 2.0, которая уже перешла на Cython. Большое спасибо Себастьяну Бергу за выявление проблемы.References: #7875
Добавлено предупреждение относительно ошибки, которая существует в методе
Result.columns()
при передаче 0 для индекса в сочетании сResult
, который возвращает одну сущность ORM, что указывает на то, что текущее поведениеResult.columns()
нарушено в этом случае, поскольку объектResult
будет давать скалярные значения, а не объектыRow
. Эта проблема будет исправлена в версии 2.0, что будет обратно несовместимым изменением для кода, который полагается на текущее нарушенное поведение. Код, который хочет получить коллекцию скалярных значений, должен использовать методResult.scalars()
, который вернет новый объектScalarResult
, выдающий скалярные объекты без рядов.References: #7953
schema¶
Исправлена ошибка, при которой соглашения об именах
ForeignKeyConstraint
, использующие ключ соглашения об именахreferred_column_0
, не работали, если ограничение внешнего ключа было установлено как объектForeignKey
, а не как явный объектForeignKeyConstraint
. Поскольку это изменение использует обратный перенос некоторых исправлений из версии 2.0, также исправлена дополнительная малоизвестная возможность, которая, вероятно, была нарушена в течение многих лет, а именно: объектForeignKey
может ссылаться на ссылающуюся таблицу только по имени таблицы без использования имени столбца, если имя ссылающегося столбца совпадает с именем ссылающегося столбца.Ключ именования
referred_column_0
ранее не тестировался с объектомForeignKey
, толькоForeignKeyConstraint
, и эта ошибка показывает, что функция никогда не работала правильно, еслиForeignKeyConstraint
не использовалась для всех ограничений FK. Эта ошибка восходит к первоначальному внедрению функции, введенной для #3989.References: #7958
asyncio¶
Исправлена обработка объектов
contextvar.ContextVar
внутри асинхронных адаптированных обработчиков событий. Ранее значения, применяемые кContextVar
, не распространялись в конкретном случае вызова ожидаемых объектов внутри не ожидаемого кода.References: #7937
postgresql¶
Исправлена ошибка в типе данных
ARRAY
в сочетании сEnum
на PostgreSQL, когда использование методов.any()
или.all()
для визуализации SQL ANY() или ALL(), учитывая в качестве аргументов члены перечисления Python, приводило к сбою адаптации типа на всех драйверах.References: #6515
Реализован атрибут
UUID.python_type
для объекта типа PostgreSQLUUID
. Атрибут возвращает либоstr
, либоuuid.UUID
в зависимости от настройки параметраUUID.as_uuid
. Ранее этот атрибут был нереализован. Pull request любезно предоставлен Алексом Грёнхольмом.References: #7943
Исправлена проблема в диалекте psycopg2 при использовании параметра
create_engine.pool_pre_ping
, которая приводила к случайному сбросу настроенного пользователем уровня изоляцииAUTOCOMMIT
обработчиком «ping».References: #7930
mysql¶
tests¶
Для сторонних диалектов исправлено недостающее требование для теста набора
SimpleUpdateDeleteTest
, который не проверял наличие рабочей функции «rowcount» на целевом диалекте.References: #7919
1.4.35¶
Released: April 6, 2022sql¶
Исправлена ошибка в недавно реализованной функции
FunctionElement.table_valued.joins_implicitly
, когда параметр не распространялся автоматически от исходного объектаTableValuedAlias
к вторичному объекту, создаваемому при вызовеTableValuedAlias.render_derived()
илиTableValuedAlias.alias()
.Дополнительно исправлены эти проблемы в
TableValuedAlias
:исправлена потенциальная проблема с памятью, которая могла возникнуть при многократном вызове
TableValuedAlias.render_derived()
против последовательных копий одного и того же объекта (для .alias() мы в настоящее время должны продолжать цепочку с предыдущего элемента. не уверены, можно ли это улучшить, но это стандартное поведение для .alias() в других местах).исправлена проблема, при которой отдельные типы элементов терялись при вызове
TableValuedAlias.render_derived()
илиTableValuedAlias.alias()
.
References: #7890
Исправлена регрессия, вызванная #7823, которая влияла на систему кэширования, в результате чего связанные параметры, которые были «клонированы» в операциях ORM, таких как полиморфная загрузка, в некоторых случаях не получали своего правильного значения во время выполнения, что приводило к отображению неправильных значений привязки.
References: #7903
1.4.34¶
Released: March 31, 2022orm¶
postgresql¶
Изменено исправление, сделанное в #6581, где режим «исполняемых значений» для psycopg2 был отключен для всех стилей INSERT «ON CONFLICT», чтобы не применять его к предложению «ON CONFLICT DO NOTHING», которое не включает никаких параметров и безопасно для режима «исполняемых значений». «ON CONFLICT DO UPDATE» все еще блокируется от «executemany values», так как в предложении DO UPDATE могут быть дополнительные параметры, которые не могут быть объединены в пакет (это первоначальная проблема, исправленная в #6581).
References: #7880
1.4.33¶
Released: March 31, 2022orm¶
Добавлена функция
with_polymorphic.adapt_on_names
к функцииwith_polymorphic()
, которая позволяет указать полиморфную нагрузку (обычно с конкретным отображением) против альтернативного selectable, который будет адаптироваться к оригинальному mapped selectable только по именам столбцов.References: #7805
Добавлены новые атрибуты
UpdateBase.returning_column_descriptions
иUpdateBase.entity_description
для проверки атрибутов и сущностей ORM, которые установлены как часть конструкцииInsert
,Update
илиDelete
. АксессорSelect.column_descriptions
теперь также реализован для селекторов, предназначенных только для Core.References: #7861
Улучшение использования памяти ORM, удаление значительного набора промежуточных объектов выражения, которые обычно хранятся при создании копии объекта выражения. Эти клоны были значительно уменьшены, сократив общее количество объектов выражения, хранящихся в памяти при отображениях ORM, примерно на 30%.
References: #7823
Исправлена регрессия в стратегии «динамического» загрузчика, когда метод
Query.filter_by()
не получал соответствующую сущность для фильтрации, в случае, когда «вторичная» таблица присутствовала в запрашиваемом отношении, и сопоставление было с чем-то сложным, таким как «с полиморфизмом».References: #7868
Исправлена ошибка, при которой атрибуты
composite()
не работали в сочетании со стратегией загрузчикаselectin_polymorphic()
для наследования объединенных таблиц.References: #7801
Исправлена проблема, при которой опция загрузчика
selectin_polymorphic()
не работала с отображателями объединенного наследования, не имеющими фиксированного столбца «polymorphic_on». Дополнительно добавлена поддержка тестов для более широкого разнообразия шаблонов использования этой конструкции.References: #7799
Исправлена ошибка в функции
with_loader_criteria()
, когда критерии загрузчика не применялись к объединенной ускоренной загрузке, которая была вызвана в рамках операции обновления для родительского объекта.References: #7862
Исправлена проблема, когда
Mapper
слишком агрессивно уменьшал пользовательский аргументMapper.primary_key
, в случае отображения наUNION
, где для некоторых записей SELECT два столбца по сути эквивалентны, а для других - нет, например, в рекурсивном CTE. Логика здесь была изменена, чтобы принимать заданный пользовательский PK как заданный, где столбцы будут связаны с отображаемым selectable, но больше не «уменьшены», так как эта эвристика не может учесть все ситуации.References: #7842
engine¶
Добавлен новый параметр
Engine.dispose.close
, по умолчанию равный True. При значении False утилизация движка вообще не трогает соединения в старом пуле, просто сбрасывая пул и заменяя его. Это нужно для того, чтобы при передаче исходного пула от родительского процесса родительский процесс мог продолжать использовать эти соединения.См.также
Использование пулов соединений с многопроцессорной обработкой или os.fork() - пересмотренная документация
Уточнено протоколирование на уровне соединения, чтобы указать, что сообщения BEGIN, ROLLBACK и COMMIT не указывают на реальную транзакцию, когда используется уровень изоляции AUTOCOMMIT; расширен обмен сообщениями, чтобы включить само сообщение BEGIN, а также исправлен обмен сообщениями, чтобы учесть, когда параметр уровня
Engine
create_engine.isolation_level
использовался напрямую.References: #7853
sql¶
Добавлен новый параметр
FunctionElement.table_valued.joins_implicitly
для конструкцииFunctionElement.table_valued()
. Этот параметр указывает, что данная таблично-значная функция неявно присоединяется к таблице, на которую она ссылается, по существу отключая функцию «from linting», т.е. предупреждение о «картезианском произведении», от действия из-за наличия этого параметра. Может использоваться для таких функций, какfunc.json_each()
.References: #7845
Параметр
bindparam.literal_execute
теперь принимает участие в генерации кэшаbindparam()
, поскольку он изменяет sql-строку, генерируемую компилятором. Ранее использовались правильные значения привязки, ноliteral_execute
игнорировался при последующих выполнениях одного и того же запроса.References: #7876
Исправлена регрессия, вызванная #7760, когда новые возможности
TextualSelect
не были полностью реализованы в компиляторе должным образом, что приводило к проблемам с составленными конструкциями INSERT, такими как «INSERT FROM SELECT» и «INSERT…ON CONFLICT» в сочетании с CTE и текстовыми операторами.References: #7798
schema¶
Добавлена поддержка того, что вызываемая функция
Table.to_metadata.referred_schema_fn
, переданная вTable.to_metadata()
, может возвращать значениеBLANK_SCHEMA
, чтобы указать, что ссылающийся внешний ключ должен быть сброшен в None. СимволRETAIN_SCHEMA
также может быть возвращен из этой функции для указания «без изменений», который будет вести себя так же, как иNone
в настоящее время, который также указывает на отсутствие изменений.References: #7860
sqlite¶
Исправлена ошибка, при которой имя ограничений CHECK в SQLite не отражалось, если имя было создано с использованием кавычек, как это бывает, когда в имени используется смешанный регистр или специальные символы.
References: #5463
mssql¶
misc¶
Улучшено сообщение об ошибке, которое выдается в случае, когда конструкция
association_proxy()
пытается получить доступ к целевому атрибуту на уровне класса, и этот доступ не удается. В данном случае речь идет о проксировании к гибридному атрибуту, который не имеет рабочей реализации на уровне класса.References: #7827
1.4.32¶
Released: March 6, 2022orm¶
Исправлена регрессия, при которой ORM исключение, которое должно быть вызвано, когда INSERT молча не может вставить ряд (например, из триггера), не достигалось из-за того, что исключение во время выполнения было вызвано раньше времени из-за отсутствующего значения первичного ключа, таким образом, вызывая неинформативное исключение, а не правильное. В версии 1.4 и выше для этого случая добавлено новое
FlushError
, которое поднимается раньше, чем предыдущее исключение «null identity» в версии 1.3, так как ситуация, когда количество фактически вводимых строк не соответствует ожидаемому, является более критичной в версии 1.4, поскольку она препятствует корректной работе пакетной обработки нескольких объектов. Это не относится к ситуации, когда только что извлеченный первичный ключ извлекается как NULL, что продолжает вызывать существующее исключение «null identity».References: #7594
Исправлена проблема, при которой использование полного пути для имени класса в
relationship()
, который, тем не менее, содержал неправильное имя для маркеров пути, не являющихся первым маркером, не вызывало информативной ошибки и вместо этого приводило к случайному отказу на более позднем шаге.References: #7697
engine¶
Скорректировано ведение журнала для ключевых компонентов SQLAlchemy, включая
Engine
,Connection
, для установки соответствующего параметра уровня стека, так что токены Python для ведения журналаfuncName
иlineno
при использовании в пользовательских форматерах ведения журнала будут сообщать правильную информацию, что может быть полезно при фильтрации вывода журнала; поддерживается на Python 3.8 и выше. Pull request любезно предоставлен Маркусом Герстелем.References: #7612
sql¶
Исправлены сообщения об ошибках, связанных с типами, которые не срабатывали для значений, являющихся кортежами, из-за синтаксиса форматирования строк, включая компиляцию неподдерживаемых литеральных значений и недопустимых булевых значений.
References: #7721
Исправлены проблемы с типом данных MySQL
SET
, а также с общим типом данныхEnum
, когда метод__repr__()
не отображал все необязательные параметры в строковом выводе, что влияло на использование этих типов в автогенерации Alembic. Pull request для MySQL любезно предоставлен Yuki Nishimine.Тип данных
Enum
теперь выдает предупреждение, если аргументEnum.length
указан без указания аргументаEnum.native_enum
как False, поскольку в противном случае параметр молча игнорируется в этом случае, несмотря на то, что тип данныхEnum
будет по-прежнему отображать VARCHAR DDL на бэкендах, не имеющих встроенного типа данных ENUM, таких как SQLite. Это поведение может измениться в будущем выпуске, чтобы «длина» учитывалась для всех неродных типов «enum» независимо от настройки «native_enum».Исправлена проблема, при которой метод
HasCTE.add_cte()
, вызываемый на экземпляреTextualSelect
, не учитывался компилятором SQL. Исправление дополнительно добавляет более «SELECT»-подобное поведение компилятора дляTextualSelect
, включая возможность обработки DML CTE, таких как UPDATE и INSERT.References: #7760
asyncio¶
Исправлена проблема, при которой не выдавалось описательное сообщение об ошибке для некоторых классов событий, прослушиваемых с помощью механизма async, который вместо этого должен быть экземпляром механизма sync.
Исправлена проблема, при которой метод
AsyncSession.execute()
не вызывал информативного исключения, если использовалась опция выполненияConnection.execution_options.stream_results
, что несовместимо с объектомResult
в стиле синхронизации при использовании стиля вызова asyncio, так как операция получения большего количества строк должна была ожидаться. Теперь в этом случае возникает исключение, аналогичное тому, которое уже возникало, когда опцияConnection.execution_options.stream_results
использовалась с методомAsyncConnection.execute()
.Кроме того, для повышения стабильности работы с драйверами баз данных, чувствительными к состоянию, такими как asyncmy, курсор теперь закрывается при возникновении этой ошибки; ранее при использовании диалекта asyncmy соединение переходило в недействительное состояние с сохранением нерассмотренных результатов на стороне сервера.
References: #7667
postgresql¶
Добавлена поддержка компилятором фразы PostgreSQL
NOT VALID
при выводе DDL для конструкций схемCheckConstraint
,ForeignKeyConstraint
иForeignKey
. Pull request любезно предоставлен Гилбертом Гилбсом.См.также
postgresql_constraint_options
References: #7600
mysql¶
Исправлена регрессия, вызванная #7518, когда изменение синтаксиса «SHOW VARIABLES» на «SELECT @@» нарушало совместимость с версиями MySQL старше 5.6, включая ранние релизы 5.0. Хотя это очень старые версии MySQL, изменение совместимости не планировалось, поэтому была восстановлена логика, зависящая от версии, чтобы вернуться к «SHOW VARIABLES» для версий сервера MySQL < 5.6.
References: #7518
mariadb¶
Исправлена регрессия в диалекте mariadbconnector начиная с версии mariadb connector 1.0.10, при которой DBAPI перестал предварительно буферизировать cursor.lastrowid, что приводило к ошибкам при вставке объектов с помощью ORM, а также к недоступности атрибута
CursorResult.inserted_primary_key
. Теперь диалект получает это значение проактивно в ситуациях, когда оно применимо.References: #7738
sqlite¶
Добавлена поддержка отражения встроенных уникальных ограничений SQLite, когда имена столбцов форматируются с помощью «спасательных кавычек» SQLite
[]
или`
, которые отбрасываются базой данных при создании имени столбца.References: #7736
Исправлена проблема, при которой отражение уникальных ограничений в SQLite не обнаруживало встроенное в столбец ограничение UNIQUE, если в имени столбца присутствовало подчеркивание.
References: #7736
oracle¶
Исправлена проблема в диалекте Oracle, когда использование имени столбца, требующего кавычек при записи в качестве связанного параметра, например,
"_id"
, не позволяло корректно отслеживать значение по умолчанию, сгенерированное Python, из-за того, что при переписывании связанного параметра это значение отсутствовало, что приводило к возникновению ошибки Oracle.References: #7676
Добавлена поддержка разбора кодов ошибок «DPI» из объектов исключений cx_Oracle, таких как
DPI-1080
иDPI-1010
, которые теперь указывают на сценарий разъединения, начиная с версии cx_Oracle 8.3.References: #7748
tests¶
Улучшена интеграция тестового пакета с pytest таким образом, что плагин «warnings», если он включен вручную, не будет мешать работе тестового пакета. Таким образом, сторонние разработчики могут включить плагин warnings или использовать параметр
-W
, и тестовый пакет SQLAlchemy будет продолжать работать. Кроме того, модернизировано обнаружение плагина «pytest-xdist», так что плагины могут быть глобально отключены с помощью PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 без нарушения тестового набора, если xdist все еще установлен. Фильтры предупреждений, переводящие предупреждения об износе в ошибки, теперь локализованы на предупреждения, специфичные для SQLAlchemy, или на источники, специфичные для SQLAlchemy, для общих предупреждений об износе Python, так что предупреждения об износе, выдаваемые плагинами pytest, не относящимися к SQLAlchemy, также не должны влиять на набор тестов.References: #7599
Внесены исправления в конфигурацию pytest по умолчанию относительно того, как настраивается обнаружение тестов, чтобы устранить проблему, когда тестовый набор не настраивал предупреждения правильно, а также пытался загрузить примеры наборов в качестве тестов, в конкретном случае, когда проверка SQLAlchemy располагалась в абсолютном пути, который имел супердиректорию с именем «test».
References: #7045
1.4.31¶
Released: January 20, 2022orm¶
Исправлена проблема в
Session.bulk_save_objects()
, когда сортировка, происходящая, когда параметрpreserve_order
установлен в False, частично сортировала объектыMapper
, что отвергается в Python 3.11.References: #7591
postgresql¶
mysql¶
mssql¶
Добавлена поддержка
FILESTREAM
при использованииVARBINARY(max)
в MSSQL.См.также
VARBINARY.filestream
References: #7243
1.4.30¶
Released: January 19, 2022orm¶
Исправлена проблема в загрузке функциональности дополнительных атрибутов в глубоком многоуровневом наследовании, когда промежуточная таблица, не содержащая столбцов, не включалась в объединенные таблицы, вместо этого связывая эти таблицы с их идентификаторами первичных ключей. Хотя это работает нормально, тем не менее, в версии 1.4 это начало выдавать предупреждение компилятора о картезианском произведении. Логика была изменена таким образом, чтобы эти промежуточные таблицы включались независимо от этого. Хотя при этом в запрос включаются дополнительные таблицы, которые технически не нужны, это происходит только в крайне необычном случае глубокого наследования на 3+ уровнях с промежуточными таблицами, не имеющими столбцов с первичными ключами, поэтому ожидается, что потенциальное влияние на производительность будет незначительным.
References: #7507
Исправлена проблема, при которой вызов функции
registry.map_imperatively()
более одного раза для одного и того же класса выдавал неожиданную ошибку, а не информативное сообщение о том, что целевой класс уже сопоставлен. Такое поведение отличалось от поведения функцииmapper()
, которая уже сообщала информативное сообщение.References: #7579
Добавлен недостающий метод
AsyncSession.invalidate()
в классAsyncSession
.References: #7524
Исправлена регрессия, появившаяся в 1.4.23, которая в некоторых случаях могла привести к неправильной обработке опций загрузчика, в частности, при использовании наследования объединенных таблиц в сочетании с опцией
polymorphic_load="selectin"
, а также ленивой загрузки отношений, что приводило к появлениюTypeError
.References: #7557
Исправлена регрессия ORM, когда вызов функции
aliased()
на существующую конструкциюaliased()
приводил к некорректному SQL, если существующая конструкция была направлена на фиксированную таблицу. Исправление позволяет игнорировать исходную конструкциюaliased()
, если она была только против таблицы, которая теперь заменяется. Оно также позволяет обеспечить правильное поведение при построенииaliased()
без выбираемого аргумента противaliased()
, который направлен на подзапрос, для создания псевдонима этого подзапроса (т.е. для изменения его имени).Поведение вложенности
aliased()
сохраняется для случая, когда внешний объектaliased()
находится против подзапроса, который в свою очередь ссылается на внутренний объектaliased()
. Это относительно новая функция версии 1.4, которая помогает удовлетворить случаи использования, которые ранее обслуживались устаревшим методомQuery.from_self()
.References: #7576
Исправлена проблема, когда метод
Select.correlate_except()
, при передаче либо значенияNone
, либо отсутствия аргументов, не коррелировал ни с какими элементами при использовании в контексте ORM (то есть, передавая сущности ORM как предложения FROM), вместо того, чтобы заставить все элементы FROM считаться «коррелированными», как это происходит при использовании конструкций только Core.References: #7514
Исправлена регрессия из версии 1.3, когда стратегия загрузчика «subqueryload» при использовании в запросе, использующем
Query.from_statement()
илиSelect.from_statement()
, приводила к ошибке с трассировкой стека. Поскольку подзапрос требует модификации исходного оператора, он не совместим с вариантом использования «from_statement», особенно для запросов, составленных с использованием конструкцииtext()
. Теперь поведение эквивалентно поведению в версии 1.3 и предыдущих версиях, которое заключается в том, что стратегия загрузчика тихо деградирует и не используется для таких утверждений, обычно возвращаясь к использованию стратегии lazyload.References: #7505
sql¶
Добавлено дополнительное правило к системе, определяющей реализации
TypeEngine
из литералов Python, для применения второго уровня корректировки типа, так что Python datetime с или без tzinfo может устанавливать параметрtimezone=True
на возвращаемый объектDateTime
, а такжеTime
. Это помогает при некоторых сценариях обхода в чувствительных к типу диалектах PostgreSQL, таких как asyncpg, psycopg3 (только 2.0).References: #7537
Добавлено информативное сообщение об ошибке при передаче объекта метода в конструкцию SQL. Ранее, когда передавались такие callable, что является распространенной типографской ошибкой при работе с SQL-конструкциями, связанными с методами, они интерпретировались как цели «лямбда SQL», которые должны были быть вызваны во время компиляции, что приводило к тихим сбоям. Поскольку эта возможность не предназначалась для использования с методами, объекты методов теперь отвергаются.
References: #7032
mypy¶
Исправлено падение Mypy при запуске режима демона id, вызванное отсутствием атрибута у внутреннего экземпляра mypy
Var
.References: #7321
asyncio¶
Добавлен новый метод
AdaptedConnection.run_async()
в интерфейс соединения DBAPI, используемый драйверами asyncio, который позволяет вызывать методы против базового соединения «драйвера» непосредственно в функции стиля sync, где нельзя использовать ключевое словоawait
, например, в функциях обработчиков событий SQLAlchemy. Этот метод аналогичен методуAsyncConnection.run_sync()
, который переводит вызовы в стиле async в вызовы в стиле sync. Метод полезен для таких вещей, как обработчики connection-pool on-connect, которым необходимо вызывать ожидающие методы на соединении драйвера при его первом создании.References: #7580
postgresql¶
Добавлен строковый рендеринг к типу данных
UUID
, так что строка оператора с «literal_binds», использующего этот тип, будет отображать соответствующее строковое значение для бэкенда PostgreSQL. Pull request любезно предоставлен Жозе Дуарте.References: #7561
Улучшена поддержка asyncpg обработки TIME WITH TIMEZONE, которая была реализована не полностью.
References: #7537
Исправлено отражение охватывающих индексов, чтобы сообщать
include_columns
как часть записиdialect_options
в словаре отраженного индекса, что позволяет завершить цикл отражение->создание. Включенные столбцы продолжают также присутствовать под ключомinclude_columns
для обратной совместимости.References: #7382
Исправлена обработка массивов значений перечислений, требующих использования управляющих символов.
References: #7418
mysql¶
Замените оператор
SHOW VARIABLES LIKE
на эквивалентныйSELECT @@variable
в инициализации диалектов MySQL и MariaDB. Это позволит избежать борьбы за мьютекс, вызваннойSHOW VARIABLES
, что улучшит производительность инициализации.References: #7518
Удалена ненужная зависимость от PyMySQL из диалекта asyncmy. Pull request любезно предоставлен long2ice.
References: #7567
1.4.29¶
Released: December 22, 2021orm¶
Добавлен параметр
Session.get.execution_options
, который ранее отсутствовал в методеSession.get()
.References: #7410
Исправлена проблема в новом методе «критерии загрузчика»
PropComparator.and_()
, когда при использовании стратегии загрузчика типаselectinload()
против столбца, являющегося членом коллекции.c.
объекта подзапроса, где подзапрос динамически добавляется в предложение FROM оператора, в кэше SQL-оператора появлялись устаревшие значения параметров в подзапросе, поскольку процесс, используемый стратегией загрузчика для замены параметров во время выполнения, не мог учесть подзапрос при получении его в таком виде.References: #7489
Исправлено переполнение рекурсии, которое могло возникнуть при компиляции операторов ORM при использовании функции
with_loader_criteria()
или методаPropComparator.and_()
в стратегии загрузчика в сочетании с подзапросом, который ссылался на одну и ту же сущность, изменяемую опцией критериев или загружаемую стратегией загрузчика. Для этого сценария была добавлена проверка на рекурсивное использование одного и того же параметра критериев загрузчика.References: #7491
Исправлена проблема, когда метод
__class_getitem__()
сгенерированного декларативного базового классаas_declarative()
приводил к недоступным атрибутам класса, таким как__table__
, в случаях, когда в иерархии классов использовалось объявление типизации в стилеGeneric[T]
. Это является продолжением базового добавления__class_getitem__()
в #7368. Pull request любезно предоставлен Каем Мюллером.Исправлена проблема, связанная с кэшированием, когда использование опции загрузчика вида
lazyload(aliased(A).bs).joinedload(B.cs)
приводило к тому, что объединенная загрузка не вызывалась для запусков, следующих за кэшированием запроса, из-за несоответствия опций/путей объектов, применяемых к объектам, загружаемым для запроса с ведущей сущностью, в котором использовалосьaliased()
.References: #7447
engine¶
Исправлено сообщение об ошибке для
AttributeError
, возникающее при попытке записи в атрибут классаRow
, который является неизменяемым. Предыдущее сообщение утверждало, что столбец не существует, что вводит в заблуждение.References: #7432
Исправлена регрессия в функции
make_url()
, используемой для разбора строк URL, когда при разборе строки запроса происходило переполнение рекурсии, если использовалась строка Python 2u''
.References: #7446
mypy¶
Исправлена регрессия mypy, когда релиз mypy 0.930 добавил дополнительные внутренние проверки формата «именованных типов», требуя, чтобы они были полностью квалифицированными и локализуемыми. Это нарушало работу плагина mypy для SQLAlchemy, вызывая ошибку утверждения, поскольку использовались такие символы, как
__builtins__
и другие нелокализованные или неквалифицированные имена, которые ранее не вызывали никаких утверждений.References: #7496
asyncio¶
Добавлена функция
async_engine_config()
для создания асинхронного движка из диктанта конфигурации. В остальном она ведет себя так же, какengine_from_config()
.References: #7301
mariadb¶
Исправлены классы ошибок, проверяемые для проверки «is_disconnect» для диалекта
mariadbconnector
, который не срабатывал для отключений, которые происходили из-за общих кодов ошибок MySQL/MariaDB, таких как 2006; похоже, что DBAPI в настоящее время использует класс исключенийmariadb.InterfaceError
для ошибок отключения, таких как код ошибки 2006, который был добавлен в список проверяемых классов.References: #7457
tests¶
Исправлена регрессия в тестовом наборе, когда тест, вызываемый
CompareAndCopyTest::test_all_present
, не выполнялся на некоторых платформах из-за обнаружения дополнительных артефактов тестирования. Pull request любезно предоставлен Nils Philippsen.References: #7450
1.4.28¶
Released: December 9, 2021platform¶
Python 3.10 отказался от использования «distutils» в пользу явного использования «setuptools» в PEP 632; setup.py SQLAlchemy заменил импорты соответствующим образом. Однако, поскольку сам setuptools только недавно добавил символы замены, упомянутые в pep-632 по состоянию на ноябрь 2021 года в версии 59.0.1,
setup.py
по-прежнему имеет обратный импорт в distutils, поскольку SQLAlchemy 1.4 не имеет жесткого требования к версии setuptools на данный момент. Ожидается, что SQLAlchemy 2.0 будет использовать полную схему установки PEP 517, которая будет указывать на соответствующую версионность setuptools заранее.References: #7311
orm¶
Исправлена проблема, при которой внутреннее клонирование, используемое методом
PropComparator.any()
наrelationship()
в случае, когда связанный класс также использует полиморфную загрузку ORM, заканчивалось неудачей, если гибридное свойство связанного полиморфного класса использовалось в качестве критерия для операцииany()
.References: #7425
Исправлена проблема, при которой декоратор
as_declarative()
и подобные функции, используемые для генерации декларативного базового класса, не копировали метод__class_getitem__()
из данного суперкласса, что препятствовало использованию pep-484 generics в сочетании с классомBase
. Pull request любезно предоставлен Каем Мюллером.References: #7368
Исправлена регрессия ORM, когда новое поведение «eager loaders run on unexpire», добавленное в #1763, приводило к тому, что ошибки опций загрузчика возникали неуместно в случае, когда один
Query
илиSelect
использовался для загрузки нескольких типов сущностей, вместе с опциями загрузчика, которые применяются только к одному из этих типов сущностей, напримерjoinedload()
, а затем объекты обновляются после истечения срока действия, где опции загрузчика пытаются быть применены к несоответствующему типу объекта и затем вызывают исключение. Теперь проверка на это несоответствие обходится без выдачи ошибки для этого случая.References: #7318
Определяемые пользователем опции ORM, такие как проиллюстрированные в примере dogpile.caching, которые подкласс
UserDefinedOption
, по определению обрабатываются при каждом выполнении оператора и не должны рассматриваться как часть ключа кэша для оператора. Кэширование базового классаExecutableOption
было изменено таким образом, что он больше не является непосредственно подклассомHasCacheKey
, так что наличие определяемых пользователем объектов опций не будет иметь нежелательного побочного эффекта отключения кэширования утверждений. Теперь в системе кэширования участвуют только специфические для ORM опции загрузчика и критериев, которые являются внутренними для SQLAlchemy.References: #7394
Исправлена проблема, из-за которой связки, использующие
synonym()
и потенциально другие виды «прокси» атрибутов, не во всех случаях успешно генерировали ключ кэша для своих SQL-операторов, что приводило к снижению производительности этих операторов.References: #7394
Исправлена проблема, при которой список, отображенный с помощью
relationship()
, попадал в бесконечный цикл, если in-place добавлялся к самому себе, т.е. использовался оператор+=
, а также если.extend()
получал тот же список.References: #7389
Исправлена проблема, при которой если возникало исключение, когда
Session
закрывал соединение в методеSession.commit()
, при использовании менеджера контекста дляSession.begin()
, он пытался сделать откат, который был невозможен, так какSession
находился между фиксацией транзакции и возвратом соединения в пул, вызывая исключение «this sessiontransaction is in the committed state». Это исключение может возникнуть в основном в контексте asyncio, где может быть вызван CancelledError.References: #7388
Отменен недокументированный синтаксис опций загрузчика
".*"
, который, по-видимому, ничем не отличается от передачи одной звездочки, и при его использовании будет выдаваться предупреждение об устаревании. Возможно, этот синтаксис был для чего-то предназначен, но в настоящее время в нем нет необходимости.References: #4390
engine¶
Добавлена поддержка
copy()
иdeepcopy()
в классURL
. Pull request любезно предоставлен Томом Ритчфордом.References: #7400
sql¶
Методы «Compound select», такие как
Select.union()
,Select.intersect_all()
и т.д., теперь принимают в качестве аргумента*other
, а неother
, что позволяет объединять несколько дополнительных SELECT с родительским оператором одновременно. В частности, изменения вCTE.union()
иCTE.union_all()
теперь позволяют создавать так называемые «нелинейные CTE» с помощью конструкцииCTE
, тогда как раньше не было возможности иметь более двух подэлементов CTE в UNION вместе и при этом корректно обращаться к CTE рекурсивным способом. Pull request любезно предоставлен Эриком Массераном.References: #7259
Поддержка нескольких элементов клаузулы в методе
Exists.where()
, унифицируя api с тем, который представляет обычная конструкцияselect()
.References: #7386
Расширение атрибута
TypeDecorator.cache_ok
и соответствующего предупреждающего сообщения, если этот флаг не определен, поведение, впервые установленное дляTypeDecorator
как часть #6436, чтобы также иметь место дляUserDefinedType
, путем обобщения флага и соответствующей логики кэширования на новую общую базу для этих двух типов,ExternalType
, чтобы создатьUserDefinedType.cache_ok
.Это изменение означает, что любое текущее значение
UserDefinedType
теперь приведет к тому, что кэширование операторов SQL не будет происходить для операторов, использующих этот тип данных, наряду с выдачей предупреждения, если только класс не определит флагUserDefinedType.cache_ok
как True. Если тип данных не может сформировать детерминированный, хэшируемый ключ кэша, полученный из его аргументов, атрибут может быть установлен в False, что приведет к отключению кэширования, но подавит предупреждение. В частности, пользовательские типы данных, используемые в таких пакетах, как SQLAlchemy-utils, должны будут реализовать этот флаг. Проблема была замечена в результате использования в SQLAlchemy-utils типа данных, который в настоящее время не кэшируется.См.также
ExternalType.cache_ok
References: #7319
Пользовательские элементы SQL, диалекты сторонних разработчиков, пользовательские или сторонние типы данных будут генерировать последовательные предупреждения, если они явно не согласны с кэшированием операторов SQL, что достигается установкой соответствующих атрибутов для каждого типа класса. Предупреждение ссылается на разделы документации, в которых указывается соответствующий подход для каждого типа объектов, чтобы кэширование было включено.
References: #7394
Исправлены отсутствующие директивы кэширования для нескольких менее используемых классов в SQL Core, которые приводили к регистрации
[no key]
для элементов, использующих их.References: #7394
mypy¶
Исправлено падение Mypy, которое происходило при использовании плагина Mypy в коде, использующем методы
declared_attr
для не отображаемых имен, таких как__mapper_args__
,__table_args__
или других имен, поскольку плагин пытался интерпретировать их как отображаемые атрибуты, которые впоследствии неправильно обрабатывались. В рамках этого изменения декорированная функция по-прежнему преобразуется плагином в общий оператор присваивания (например,__mapper_args__: Any
), так что сигнатуру аргумента можно продолжать аннотировать так же, как и для любого другого@classmethod
без того, чтобы Mypy жаловался на неправильный тип аргумента для метода, который не является явно@classmethod
.References: #7321
postgresql¶
Исправлены отсутствующие директивы кэширования для конструкций
hstore
иarray
, которые приводили к тому, что для этих элементов регистрировалось[no key]
.References: #7394
tests¶
Реализована поддержка корректной работы тестового набора под Pytest 7. Ранее для Python 3 поддерживался только Pytest 6.x, однако эта версия не была привязана к верхней границе в tox.ini. Pytest не привязан в tox.ini к версии ниже 8, так что версии SQLAlchemy, выпущенные с текущей кодовой базой, смогут быть протестированы под tox без изменений в окружении. Большое спасибо разработчикам Pytest за помощь в решении этого вопроса.
1.4.27¶
Released: November 11, 2021orm¶
Исправлена ошибка в функции «связь с псевдонимом класса», введенной в Отношения с чужим классом, когда невозможно было создать опцию стратегии загрузчика, нацеленную на атрибут цели с помощью конструкции
aliased()
непосредственно во второй опции загрузчика, напримерselectinload(A.aliased_bs).joinedload(aliased_b.cs)
, без явной квалификации с помощьюPropComparator.of_type()
на предыдущем элементе пути. Кроме того, прямое обращение к несглаженному классу будет принято (неуместно), но будет тихо провалено, напримерselectinload(A.aliased_bs).joinedload(B.cs)
; теперь это вызывает ошибку, указывающую на несоответствие типов.References: #7224
Все объекты
Result
теперь будут последовательно подниматьResourceClosedError
, если они используются после жесткого закрытия, что включает «жесткое закрытие», которое происходит после вызова методов «одной строки или значения», таких какResult.first()
иResult.scalar()
. Такое поведение уже было характерно для наиболее распространенного класса объектов результатов, возвращаемых при выполнении операторов Core, то есть тех, которые основаны наCursorResult
, поэтому такое поведение не является новым. Однако изменение было расширено, чтобы должным образом приспособиться к «фильтрации» объектов результатов ORM, возвращаемых при использовании ORM-запросов в стиле 2.0, которые ранее вели себя в стиле «мягкого закрытия», возвращая пустые результаты, или вообще не «мягко закрывались» и продолжали получать данные от базового курсора.В рамках этого изменения мы также добавили
Result.close()
к базовому классуResult
и реализовали его для реализаций фильтрованных результатов, используемых ORM, чтобы можно было вызвать методCursorResult.close()
на базовомCursorResult
, когда используется опция выполненияyield_per
, чтобы закрыть курсор на стороне сервера до того, как будут извлечены оставшиеся результаты ORM. Это уже было доступно для наборов результатов Core, но данное изменение делает это доступным и для результатов ORM в стиле 2.0.References: #7274
Исправлена регрессия 1.4, когда
Query.filter_by()
некорректно функционировал наQuery
, который был произведен изQuery.union()
,Query.from_self()
или подобных.References: #7239
Исправлена проблема, при которой отложенная полиморфная загрузка атрибутов из подкласса наследования объединенной таблицы не могла корректно заполнить атрибут, если для первоначального исключения этого атрибута использовалась опция
load_only()
, в случае, когда load_only спускалась от опции загрузчика отношений. Исправление позволяет другим допустимым опциям, таким какdefer(..., raiseload=True)
и т.д., функционировать так, как ожидается.References: #7304
Исправлена регрессия 1.4, когда
Query.filter_by()
не функционировал правильно, когдаQuery.join()
присоединялись к сущности, которая использовалаPropComparator.of_type()
для указания псевдослучайной версии целевой сущности. Проблема также относится к ORM-запросам будущего стиля, построенным с использованиемselect()
.References: #7244
engine¶
Исправлена проблема в будущем объекте
Connection
, когда методConnection.execute()
не принимал в качестве словаря параметров объект отображения без диктанта, например, собственный объект SQLAlchemyRowMapping
или другой объектabc.collections.Mapping
.References: #7291
Исправлена регрессия, при которой метод
CursorResult.fetchmany()
не мог автозакрыть курсор на стороне сервера (т.е. при использованииstream_results
илиyield_per
, либо Core, либо ORM-ориентированных результатов), когда результаты были полностью исчерпаны.References: #7274
Исправлена проблема в будущем
Engine
, когда вызовEngine.begin()
и вход в контекстный менеджер не закрывал соединение, если фактическая операция BEGIN не выполнялась по какой-либо причине, например, обработчик события вызывал исключение; этот случай использования не был протестирован для будущей версии движка. Обратите внимание, что «будущие» менеджеры контекста, которые обрабатывают блокиbegin()
в Core и ORM, фактически не выполняют операцию «BEGIN» до тех пор, пока не будут введены менеджеры контекста. Это отличается от старой версии, в которой операция «BEGIN» выполняется заранее.References: #7272
sql¶
Добавлено
TupleType
в пространство имен импорта верхнего уровняsqlalchemy
.Исправлена регрессия, при которой объекты строк, возвращаемые для ORM-запросов, которые теперь являются обычными объектами
Row
, не интерпретировались операторомColumnOperators.in_()
как значения кортежа, которые должны быть разбиты на отдельные связанные параметры, и вместо этого передавались драйверу как одиночные значения, что приводило к сбоям. Изменение системы «расширяющегося IN» теперь учитывает, что выражение уже имеет типTupleType
и обрабатывает значения соответствующим образом. В редких случаях использования «tuple-in» с нетипизированным выражением, например, текстовым выражением без информации о типе, значение кортежа определяется для значений, реализующихcollections.abc.Sequence
, но не являющихсяstr
илиbytes
, как всегда при проверке наSequence
.References: #7292
Исправлена проблема, при которой функция использования строковой метки для упорядочивания или группировки, описанная в Упорядочивание или группировка по метке, не работала корректно, если использовалась в конструкции
CTE
, когда CTE были встроены внутрь охватывающего оператораSelect
, который сам был настроен как скалярный подзапрос.References: #7269
Исправлена регрессия, при которой конструкция
text()
больше не принималась в качестве целевого случая в списке «whens» внутри конструкцииcase()
. Регрессия, по-видимому, связана с попыткой защиты от некоторых форм буквальных значений, которые считались неоднозначными при передаче сюда; однако нет причин, по которым целевые случаи не должны интерпретироваться как произвольные выражения SQL, как и везде, и буквальная строка или кортеж будет преобразована в связанный параметр, как это было бы в других случаях.References: #7287
schema¶
Исправлена проблема в
Table
, когда параметрTable.implicit_returning
не размещался корректно при передаче вместе сTable.extend_existing
для дополнения существующегоTable
.References: #7295
postgresql¶
Добавлены переопределяемые методы
PGDialect_asyncpg.setup_asyncpg_json_codec
иPGDialect_asyncpg.setup_asyncpg_jsonb_codec
codec, которые выполняют необходимую задачу регистрации JSON/JSONB кодеков для этих типов данных при использовании asyncpg. Изменение заключается в том, что методы разбиты на отдельные, переопределяемые методы для поддержки диалектов сторонних разработчиков, которым необходимо изменить или отключить настройку этих конкретных кодеков.References: #7284
Изменен диалект asyncpg для привязки типа
Float
к типу PostgreSQL «float» вместо «numeric», чтобы можно было разместить значениеfloat(inf)
. Добавлена поддержка тестового набора для сохранения значения «inf».References: #7283
Улучшение работы с массивами при использовании PostgreSQL с диалектом pg8000.
References: #7167
mysql¶
Реорганизован список зарезервированных слов в два отдельных списка, один для MySQL и один для MariaDB, чтобы можно было более точно управлять этими разными наборами слов; настроен диалект MySQL/MariaDB для переключения между этими списками на основе явно настроенного или определяемого по версии сервера бэкенда «MySQL» или «MariaDB». Добавлены все текущие зарезервированные слова для MySQL 8 и текущих версий MariaDB, включая недавно добавленные ключевые слова, такие как «lead». Pull request любезно предоставлен Кевином Кирше.
References: #7167
Исправлена проблема в MySQL
Insert.on_duplicate_key_update()
, которая при использовании выражения в выражении VALUES выводила неверное имя столбца. Pull request любезно предоставлен Кристианом Сабайлой.References: #7281
mssql¶
Скорректирована генерация компилятором символов «после компиляции», включая символы, используемые для «расширения IN», а также для «карты трансляции схемы», чтобы они не основывались непосредственно на строках, заключенных в скобки с подчеркиванием, поскольку это напрямую противоречит формату цитирования SQL Server, также использующему скобки, что приводит к ложным совпадениям, когда компилятор заменяет символы «после компиляции» и «трансляции схемы». Проблема создала легко воспроизводимые примеры как с методом
Inspector.get_schema_names()
при использовании в сочетании с функциейConnection.execution_options.schema_translate_map
, так и в маловероятном случае, когда символ, перекрывающий внутреннее имя «POSTCOMPILE», будет использоваться с функцией типа «expanding in».References: #7300
1.4.26¶
Released: October 19, 2021orm¶
Улучшено сообщение об исключении, генерируемое при настройке отображения с наследованием объединенных таблиц, когда в двух таблицах либо не установлены отношения внешних ключей, либо установлены несколько отношений внешних ключей. Сообщение теперь специфично для ORM и включает контекст, в котором говорится, что параметр
Mapper.inherit_condition
может понадобиться, особенно в случае неоднозначных внешних ключей.Исправлена проблема с функцией
with_loader_criteria()
, когда критерии ON не добавлялись в JOIN для запроса видаselect(A).join(B)
, указывающего цель при использовании неявного предложения ON.References: #7189
Исправлена ошибка, при которой «плагин» ORM, необходимый для корректной работы таких функций, как
with_loader_criteria()
, не применялся кselect()
, который запрашивался из выражения столбца ORM, если в нем использовался модификаторColumnElement.label()
.References: #7205
Добавьте недостающие методы, добавленные в #6991 в
scoped_session
иasync_scoped_session()
.References: #7103
К функциональности
Query.join()
и ORM-версииSelect.join()
был добавлен дополнительный слой предупреждающих сообщений, в котором несколько мест, где продолжает встречаться «автоматическое псевдонирование», теперь будут названы паттерном, которого следует избегать, в основном это относится к области наследования объединенных таблиц, где классы, имеющие общие базовые таблицы, объединяются вместе без использования явных псевдонимов. В одном случае выдается предупреждение о наследуемом шаблоне, который не рекомендуется использовать, в другом случае он полностью устарел.Автоматическое выравнивание в ORM join(), которое происходит для перекрывающихся сопоставленных таблиц, не работает последовательно со всеми API, такими как
contains_eager()
, и вместо того, чтобы продолжать пытаться заставить эти случаи использования работать везде, замена на более явный пользовательский шаблон более понятна, менее подвержена ошибкам и еще больше упрощает внутреннее устройство SQLAlchemy.Предупреждения содержат ссылки на страницу errors.rst, где демонстрируется каждый паттерн, а также рекомендации по его исправлению.
Исправлена ошибка, когда итерация
Result
изSession
после того, какSession
были закрыты, частично присоединяла объекты к этой сессии в недействительном состоянии. Теперь он вызывает исключение со ссылкой на новую документацию, если небуферизованный результат итерируется изSession
, который был закрыт или иным образом имел методSession.expunge_all()
, вызванный после того, как был сгенерированResult
. Опция выполненияprebuffer_rows
, которая автоматически используется расширением asyncio для клиентских наборов результатов, может быть использована для созданияResult
, где объекты ORM предварительно буферизированы, и в этом случае итерация результата приведет к созданию серии отделенных объектов.References: #7128
Связано с #7153, исправлена проблема, при которой поиск столбцов результатов был неудачным для «адаптированных» операторов SELECT, которые выбирали для выражений «постоянные» значения, чаще всего выражение NULL, что происходило в таких местах, как объединенная ускоренная загрузка в сочетании с ограничением/смещением. В целом это была регрессия, вызванная выпуском #6259, который удалял всю «адаптацию» для констант типа NULL, «true» и «false» при переписывании выражений в операторе SQL, но это нарушало ситуацию, когда та же логика адаптации использовалась для преобразования константы в маркированное выражение для целей нацеливания набора результатов.
References: #7154
Исправлена регрессия, при которой загруженные объекты ORM не могли быть пикированы в случаях, когда опции загрузчика, использующие
"*"
, использовались в определенных комбинациях, таких как сочетание стратегии загрузчикаjoinedload()
сraiseload('*')
вложенных элементов.References: #7134
Исправлена регрессия, при которой использование атрибута
hybrid_property
или сопоставленного атрибутаcomposite()
в качестве ключа, передаваемого в методUpdate.values()
для оператораUpdate
с поддержкой ORM, а также при использовании его через традиционный методQuery.update()
, обрабатывались на предмет входящих ORM/гибридных/композитных значений на этапе компиляции оператора UPDATE, что означало, что в тех случаях, когда происходило кэширование, последующие вызовы того же оператора уже не получали правильных значений. Это касается не только гибридов, использующих методhybrid_property.update_expression()
, но и любого использования обычного гибридного атрибута. Для композитов эта проблема приводила к генерации неповторяющегося ключа кэша, что нарушало кэширование и могло заполнить кэш утверждений повторяющимися утверждениями.Конструкция
Update
теперь обрабатывает пары ключ/значение, переданные вUpdate.values()
иUpdate.ordered_values()
заранее, когда конструкция генерируется впервые, до генерации ключа кэша, чтобы пары ключ/значение обрабатывались каждый раз, и чтобы ключ кэша генерировался по отдельным парам столбцов/значений, которые в конечном итоге будут использоваться в операторе.References: #7209
Передача объекта
Query
вSession.execute()
не является предполагаемым использованием этого объекта, и теперь будет выдано предупреждение об устаревании.References: #6284
examples¶
Исправлены примеры в examples/versioned_rows для корректного использования API SQLAlchemy 1.4; эти примеры были пропущены, когда были сделаны изменения в API, такие как удаление «passive» из
Session.is_modified()
, а также добавлен крючок событияSessionEvents.do_orm_execute()
.References: #7169
engine¶
Исправлена проблема, при которой предупреждение об устаревании конструктора
URL
, указывающее на необходимость использования методаURL.create()
, не выдавалось, если передавался полный список позиционных аргументов из семи аргументов; кроме того, при вызове конструктора таким образом теперь будет происходить проверка аргументов URL, которая ранее пропускалась.References: #7130
Метод
Inspector.reflect_table()
теперь поддерживает отражение таблиц, в которых нет столбцов, определенных пользователем. Это позволяетMetaData.reflect()
правильно завершить отражение на базах данных, содержащих такие таблицы. В настоящее время известно, что только PostgreSQL поддерживает такую конструкцию среди распространенных бэкендов баз данных.References: #3247
Реализованы надлежащие методы
__reduce__()
для всех объектов исключений SQLAlchemy, чтобы гарантировать, что все они поддерживают чистые обходы при пикинге, поскольку объекты исключений часто сериализуются для целей различных инструментов отладки.References: #7077
sql¶
Исправлена проблема, при которой SQL-запросы, использующие конструкцию
FunctionElement.within_group()
, не могли быть травлены, обычно при использовании расширенияsqlalchemy.ext.serializer
, но также и при общем травлении.References: #6520
Исправлена проблема в новом параметре
HasCTE.cte.nesting
, введенном в #4123, когда рекурсивныйCTE
, использующийHasCTE.cte.recursive
в типичной комбинации с UNION, компилировался некорректно. Дополнительно внесены некоторые изменения, чтобы конструкцияCTE
создавала правильный ключ кэша. Pull request любезно предоставлен Эриком Массераном.References: #4123
Учет параметра
table.schema
, переданного в конструкциюtable()
, таким образом, чтобы он учитывался при обращении к атрибутуTableClause.fullname
.References: #7061
Исправлено несоответствие в функциях/методах
ColumnOperators.any_()
/ColumnOperators.all_()
, когда специальное поведение этих функций по «переворачиванию» выражения таким образом, что выражение «ANY» / «ALL» всегда находится справа, не работало, если сравнение проводилось со значением None, то есть «column.any_() == None» должно давать такое же SQL выражение, как и «null() == column.any_()». Добавлена дополнительная документация для разъяснения этого, а также упоминание о том, что any_() / all_() в целом заменяет версию ARRAY «any()» / «all()».References: #7140
Исправлена проблема, при которой «расширение IN» не работало правильно с типами данных, использующими метод
TypeEngine.bind_expression()
, когда метод должен был применяться к каждому элементу выражения IN, а не к самому выражению IN в целом.References: #7177
Скорректировали логику «разграничения столбцов», которая появилась в 1.4, когда одно и то же выражение повторяется и получает «дополнительную анонимную» метку, так, чтобы логика более агрессивно дедуплицировала эти метки, когда повторяющийся элемент является одним и тем же объектом выражения Python каждый раз, как это происходит в случаях использования «одиночных» значений типа
null()
. Это основано на наблюдении, что по крайней мере некоторые базы данных (например, MySQL, но не SQLite) выдают ошибку, если одна и та же метка повторяется внутри подзапроса.References: #7153
mypy¶
Исправлена проблема в плагине mypy для улучшения некоторых проблем с обнаружением типов
Enum()
SQL, содержащих пользовательские классы перечислений Python. Pull request любезно предоставлен Хироши Огавой.References: #6435
postgresql¶
Добавлено условие «разъединения» для ошибки «SSL SYSCALL error: Плохой адрес», о котором сообщил psycopg2. Pull request любезно предоставлен Зиком Брехтелем.
References: #5387
Исправлена проблема, когда выражения IN против серии элементов массива, как это можно сделать в PostgreSQL, не работали правильно из-за многочисленных проблем в функции «расширяющего IN» SQLAlchemy Core, которая была стандартизирована в версии 1.4. Диалект psycopg2 теперь использует метод
TypeEngine.bind_expression()
сARRAY
для переносимого применения правильного приведения к элементам. Диалект asyncpg не был затронут этой проблемой, так как он применяет приведения на уровне биндов на уровне драйвера, а не на уровне компилятора.References: #7177
mysql¶
Исправления для адаптации к серии MariaDB 10.6, включая обратно несовместимые изменения как в Python-драйвере mariadb-connector (поддерживается только в SQLAlchemy 1.4), так и в родных клиентских библиотеках 10.6, которые автоматически используются mysqlclient DBAPI (применяется как к 1.3, так и к 1.4). Символ кодировки «utf8mb3» теперь сообщается этими клиентскими библиотеками, когда кодировка указана как «utf8», что приводит к ошибкам поиска и кодировки в диалекте MySQL, который не ожидает этого символа. Обновления внесены как в базовую библиотеку MySQL, чтобы учесть этот символ utf8mb3, так и в тестовый пакет. Спасибо Георгу Рихтеру за поддержку.
This change is also backported to: 1.3.25
Исправлена проблема в конструкции MySQL
match()
, когда передача выражения клаузы, такого какbindparam()
или другого SQL выражения для параметра «against» приводила к неудаче. Pull request любезно предоставлен Антоном Ковалевичем.References: #7144
Исправлена проблема установки, при которой модуль
sqlalchemy.dialects.mysql
не импортировался, если не был установлен «greenlet».References: #7204
mssql¶
Добавлена поддержка отражения для опций внешнего ключа SQL Server, включая «ON UPDATE» и «ON DELETE» значения «CASCADE» и «SET NULL».
Исправлена проблема с
Inspector.get_foreign_keys()
, когда внешние ключи были пропущены, если они были установлены против уникального индекса вместо уникального ограничения.References: #7160
Исправлена проблема с
Inspector.has_table()
, когда при запросе к tempdb возвращалась False, если локальная временная таблица с тем же именем из другой сессии возвращалась первой. Это продолжение #6910, которое учитывало, что временная таблица существует только в альтернативной сессии, а не в текущей.References: #7168
Исправлена ошибка в типе данных SQL Server
DATETIMEOFFSET
, когда реализация ODBC не генерировала корректный DDL, в случаях, когда тип был преобразован с помощью методаdialect.type_descriptor()
, использование которого показано в некоторых документированных примерах дляTypeDecorator
, хотя и не является необходимым для большинства типов данных. Регрессия была введена в #6366. В рамках этого изменения полный список типов дат SQL Server был изменен, чтобы вернуть «dialect impl», который генерирует то же имя DDL, что и супертип.References: #7129
1.4.25¶
Released: September 22, 2021platform¶
Исправлена регрессия, вызванная #7024, когда при реорганизации имен «platform machine», используемых зависимостью
greenlet
, неправильно писалось «aarch64» и дополнительно опускалось заглавное «AMD64», что необходимо для машин Windows. Pull request любезно предоставлен Джеймсом Доу.References: #7024
1.4.24¶
Released: September 22, 2021platform¶
Дополнительно скорректирован спецификатор пакета «greenlet» в setup.cfg для использования длинной цепочки выражений «или», так что сравнение
platform_machine
с определенным идентификатором соответствует только полной строке.References: #7024
orm¶
Добавлены опции загрузчика в
Session.merge()
иAsyncSession.merge()
через новый параметрSession.merge.options
, который будет применять заданные опции загрузчика кget()
, используемому внутри merge, позволяя применять ускоренную загрузку отношений и т.д., когда процесс merge загружает новый объект. Pull request любезно предоставлен Дэниелом Стоуном.References: #6955
Исправлена проблема ORM, когда выражения столбцов, переданные в
query()
или ORM-enabledselect()
, дедуплицировались на идентичность объекта, например, фраза типаselect(A.id, null(), null())
выдавала только одно выражение «NULL», чего ранее не было в 1.3. Однако, это изменение также позволяет ORM-выражениям отображаться как заданные, например,select(A.data, A.data)
будет выдавать строку результата с двумя столбцами.References: #6979
Исправлена проблема в недавно исправленном методе
Query.with_entities()
, когда флаг, определяющий автоматическую уникальность только для унаследованных объектов ORMQuery
, устанавливался в значениеTrue
в случаях, когда вызовwith_entities()
устанавливалQuery
на возврат строк только для столбцов, которые не являются уникальными.References: #6924
engine¶
Улучшить интерфейс, используемый адаптированными драйверами, такими как asyncio, для доступа к фактическому объекту соединения, возвращаемому драйвером.
Объект
_ConnectionFairy
имеет два новых атрибута:_ConnectionFairy.dbapi_connection
всегда представляет собой объект, совместимый с DBAPI. Для драйверов pep-249 это соединение DBAPI, каким оно всегда было, доступ к которому ранее осуществлялся через атрибут.connection
. Для драйверов asyncio, которые SQLAlchemy адаптирует в интерфейс pep-249, возвращаемый объект обычно будет объектом адаптации SQLAlchemy под названиемAdaptedConnection
._ConnectionFairy.driver_connection
всегда представляет фактический объект соединения, поддерживаемый сторонним pep-249 DBAPI или используемым асинхронным драйвером. Для стандартных pep-249 DBAPI это всегда будет тот же объект, что и вdbapi_connection
. Для драйвера asyncio это будет базовый объект соединения только для asyncio.
Атрибут
.connection
остается доступным и теперь является унаследованным псевдонимом.dbapi_connection
.References: #6832
Добавлены новые методы
Session.scalars()
,Connection.scalars()
,AsyncSession.scalars()
иAsyncSession.stream_scalars()
, которые обеспечивают короткий путь к случаю получения ориентированного на строки объектаResult
и преобразования его в объектScalarResult
с помощью методаResult.scalars()
, чтобы вернуть список значений, а не список строк. Новые методы аналогичны давно существующим методамSession.scalar()
иConnection.scalar()
, используемым для возврата единственного значения только из первой строки. Pull request любезно предоставлен Мигелем Гринбергом.References: #6990
Исправлена проблема, при которой возможность метода
ConnectionEvents.before_execute()
изменять переданный объект SQL-оператора, возвращая новый объект для вызова, была непреднамеренно удалена. Это поведение было восстановлено.References: #6913
Убедитесь, что
str()
вызывается на аргументе anURL.create.password
, что позволяет использовать в качестве атрибутов пароля объекты, реализующие метод__str__()
. Также уточнено, что один такой объект не подходит для динамического изменения пароля для каждого соединения с базой данных; вместо него следует использовать подходы на Генерация динамических маркеров аутентификации.References: #6958
Исправлена проблема в
URL
, когда проверка «drivername» не реагировала должным образом на значениеNone
, где ожидалась строка.References: #6983
Исправлена проблема, при которой движок, имеющий флаг
create_engine.implicit_returning
, установленный в False, не работал, если функция PostgreSQL «fast insertmany» использовалась в сочетании сSequence
, а также если любой вид «executemany» с «return_defaults()» использовался в сочетании сSequence
. Обратите внимание, что PostgreSQL «fast insertmany» использует «RETURNING» по определению, когда SQL оператор передается драйверу; в целом, флагcreate_engine.implicit_returning
является унаследованным и не имеет реального использования в современной SQLAlchemy, и будет устаревшим в отдельном изменении.References: #6963
sql¶
Добавлен новый параметр
HasCTE.cte.nesting
в конструкторCTE
и методHasCTE.cte()
, который отмечает CTE как такой, который должен оставаться вложенным в окружающий CTE, а не перемещаться на верхний уровень внешнего SELECT. Хотя в подавляющем большинстве случаев нет никакой разницы в функциональности SQL, пользователи выявили различные граничные случаи, когда истинная вложенность конструкций CTE является желательной. Большое спасибо Эрику Массерану за большую работу над этой сложной функцией.References: #4123
Реализованы отсутствующие методы в
FunctionElement
, которые, будучи неиспользуемыми, приводили к тому, что pylint сообщал о них как о нереализованных абстрактных методах.References: #7052
Исправлены две проблемы, когда комбинации
select()
иjoin()
при адаптации для формирования копии элемента не полностью копировали состояние всех объектов колонок, связанных с подзапросами. Ключевая проблема, вызванная этим, заключалась в том, что использование методаClauseElement.params()
(который, вероятно, следует перенести в категорию наследия, поскольку он неэффективен и чреват ошибками) оставляло копии старых объектовBindParameter
, что приводило к проблемам с правильной установкой параметров во время выполнения.References: #7055
Исправлена проблема, связанная с новой функцией
HasCTE.add_cte()
, когда при одновременном использовании двух операторов «INSERT…FROM SELECT» терялся смысл двух независимых операторов SELECT, что приводило к неправильному SQL.References: #7036
Исправлена проблема, при которой использование выражений столбцов ORM в качестве ключей в списке словарей, переданных в
Insert.values()
для «многозначной вставки», не обрабатывалось корректно в правильные выражения столбцов.References: #7060
mypy¶
Исправлена проблема, из-за которой плагин mypy аварийно завершал работу при интерпретации конструкции
query_expression()
.References: #6950
Исправлена проблема в плагине mypy, когда столбцы на mixin не интерпретировались корректно, если отображаемый класс полагался на процедуру
__tablename__
, пришедшую из суперкласса.References: #6937
asyncio¶
Добавлена начальная поддержка драйвера базы данных
asyncmy
asyncio для MySQL и MariaDB. Этот драйвер очень новый, но, похоже, является единственной альтернативой драйверуaiomysql
, который в настоящее время не поддерживается и не работает с текущими версиями Python. Большое спасибо long2ice за pull request для этого диалекта.См.также
References: #6993
AsyncSession
теперь поддерживает переопределение того, какойSession
он использует в качестве проксируемого экземпляра. Пользовательский классSession
можно передать с помощью параметраAsyncSession.sync_session_class
или путем подклассификацииAsyncSession
и указания пользовательскогоAsyncSession.sync_session_class
.References: #6746
Исправлена ошибка в
AsyncSession.execute()
иAsyncSession.stream()
, которая требовала, чтобыexecution_options
при определении был экземпляромimmutabledict
. Теперь он корректно принимает любое отображение.References: #6943
Добавлены недостающие аргументы
**kw
в методAsyncSession.connection()
.Исправьте использование
scoped_session
с драйверами asyncio. При использовании Asyncio вместо него следует использоватьasync_scoped_session
.References: #6746
postgresql¶
Квалифицируйте вызов
version()
, чтобы избежать проблем с тенью, если пользователь настроил другой путь поиска.References: #6912
Тип данных
ENUM
является нативным для PostgreSQL и поэтому не должен использоваться с флагомnative_enum=False
. Теперь этот флаг игнорируется при передаче типу данныхENUM
и выдается предупреждение; ранее флаг приводил к некорректной работе объекта типа.References: #6106
sqlite¶
Исправлена ошибка, при которой сообщение об ошибке недействительного уровня изоляции SQLite на драйвере pysqlite не указывало, что «AUTOCOMMIT» является одним из допустимых уровней изоляции.
mssql¶
Исправлена проблема, когда
sqlalchemy.engine.reflection.has_table()
возвращалоTrue
для локальных временных таблиц, которые на самом деле принадлежали другому сеансу SQL Server (соединению). Теперь выполняется дополнительная проверка, чтобы убедиться, что обнаруженная временная таблица действительно принадлежит текущему сеансу.References: #6910
oracle¶
Добавлен CAST(VARCHAR2(128)) к «имени таблицы», «владельцу» и другим параметрам DDL-имени, используемым в запросах на отражение к системным представлениям Oracle, таким как ALL_TABLES, ALL_TAB_CONSTRAINTS и т.д., чтобы лучше обеспечить возможность индексирования по этим столбцам, поскольку ранее они неявно обрабатывались как NVARCHAR2 из-за использования в Python Unicode для строк; эти столбцы документированы во всех версиях Oracle как VARCHAR2 с длиной от 30 до 128 символов в зависимости от версии сервера. Кроме того, была включена поддержка тестирования структур DDL с именами Unicode в базах данных Oracle.
References: #4486
1.4.23¶
Released: August 18, 2021general¶
Требования к установке были изменены таким образом, что
greenlet
является требованием по умолчанию только для тех платформ, для которых хорошо известна возможность установкиgreenlet
и для которых уже есть предварительно собранный бинарник на pypi; текущий список -x86_64 aarch64 ppc64le amd64 win32
. Для других платформ greenlet не будет устанавливаться по умолчанию, что позволит установить и запустить тестовый пакет SQLAlchemy 1.4 на платформах, не поддерживающихgreenlet
, исключая любые возможности asyncio. Для установки с включенной зависимостьюgreenlet
на архитектуру машины, не входящую в приведенный выше список, дополнительная зависимость[asyncio]
может быть включена путем выполнения командыpip install sqlalchemy[asyncio]
, которая затем попытается установитьgreenlet
.Кроме того, набор тестов был исправлен таким образом, чтобы тесты могли полностью завершаться, когда greenlet не установлен, с соответствующими пропусками для тестов, связанных с asyncio.
References: #6136
orm¶
Добавлен новый атрибут
Select.columns_clause_froms
, который будет извлекать список FROM, подразумеваемый предложением columns оператораSelect
. Это отличается от старой коллекцииSelect.froms
тем, что она не выполняет никаких шагов компиляции ORM, которые обязательно деаннотируют элементы FROM и делают такие вещи, как вычисление объединенных нагрузок и т.д., что делает ее неподходящим кандидатом для методаSelect.select_from()
. Дополнительно добавляет новый параметрSelect.with_only_columns.maintain_column_froms
, который передает эту коллекцию вSelect.select_from()
перед заменой коллекции столбцов.Кроме того,
Select.froms
переименована вSelect.get_final_froms()
, чтобы подчеркнуть, что эта коллекция не является простым аксессором, а вычисляется с учетом полного состояния объекта, что может быть дорогим вызовом при использовании в контексте ORM.Дополнительно исправляет регрессию, связанную с функцией
with_only_columns()
для поддержки применения критериев к элементам колонок, которые были заменены наSelect.with_only_columns()
илиQuery.with_entities()
, которая была сломана в #6503, выпущенной в версии 1.4.19.References: #6808
Исправлена проблема, при которой «клонированный» объект связанного параметра вызывал конфликт имен в компиляторе, если в одном операторе одновременно использовалось более одного клона этого параметра. Это могло произойти, в частности, с такими вещами, как запросы на наследование одной таблицы ORM, которые указывали одно и то же значение «дискриминатора» несколько раз в одном запросе.
References: #6824
Исправлена проблема в стратегиях загрузчика, когда использование метода
Load.options()
, особенно при вложении нескольких вызовов, генерировало слишком длинный и, что более важно, недетерминированный ключ кэша, что приводило к очень большим ключам кэша, которые также не позволяли эффективно использовать кэш, как с точки зрения общей используемой памяти, так и количества записей, используемых в самом кэше.References: #6869
Пересмотрены средства, с помощью которых аксессор
ORMExecuteState.user_defined_options
получаетUserDefinedOption
и связанные с ним объекты опций из контекста, с особым упором на стратегию «selectinload» на загрузчике, где ранее это не работало; в других стратегиях этой проблемы не было. Объекты, связанные с текущим выполняемым запросом, а не с кэшируемым запросом, теперь распространяются безусловно. Это, по сути, отделяет их от опций «стратегии загрузчика», которые явно связаны с компилированным состоянием запроса и должны использоваться по отношению к кэшируемому запросу.Эффект этого исправления заключается в том, что определяемая пользователем опция, например, используемая в примере dogpile.caching, а также в других рецептах, таких как определение «идентификатора шарда» для расширения горизонтального обмена, будет корректно передаваться нетерпеливым и ленивым загрузчикам независимо от того, был ли в конечном итоге вызван кэшированный запрос.
References: #6887
Исправлена проблема, когда единица работы внутренне использовала 2.0-устаревшую форму выражения SQL, выдавая предупреждение об устаревании, если была включена функция SQLALCHEMY_WARN_20.
References: #6812
Исправлена проблема в
selectinload()
, когда использование новой функцииPropComparator.and_()
внутри опций, вложенных более чем на один уровень вглубь, не приводило к обновлению значений связанных параметров, которые находились во вложенных критериях, как побочный эффект кэширования SQL-операторов.References: #6881
Скорректированы внутренние компоненты ORM-загрузчика, чтобы больше не использовать систему «лямбда-кэширования», которая была добавлена в 1.4, а также исправлено одно место, которое все еще использовало предыдущую систему «запеченных запросов» для запроса. Система лямбда-кэширования остается эффективным способом снижения накладных расходов на создание запросов, которые имеют относительно фиксированные шаблоны использования. В случае стратегий загрузчика используемые запросы отвечают за перемещение по множеству произвольных опций и критериев, которые генерируются и иногда потребляются кодом конечного пользователя, что делает концепцию лямбда-кэша не более эффективной, чем ее неиспользование, ценой большей сложности. В частности, проблемы, отмеченные #6881 и #6887, становятся значительно менее сложными, если убрать эту возможность из внутреннего кода.
Исправлена проблема, при которой конструкция
Bundle
не создавала надлежащие ключи кэша, что приводило к неэффективному использованию кэша запросов. Это оказывало некоторое влияние на стратегию «selectinload» и было определено как часть #6889.References: #6889
sql¶
Исправление проблемы в
CTE
, когда новый методHasCTE.add_cte()
, добавленный в версии 1.4.21 / #6752, не работал правильно для структур «compound select», таких какunion()
,union_all()
,except()
и т.д. Pull request любезно предоставлен Эриком Массераном.References: #6752
Исправлена проблема в методе
CacheKey.to_offline_string()
, используемом в примере dogpile.caching, когда при попытке создать правильный ключ кэша из специального «лямбда» запроса, сгенерированного ленивым загрузчиком, значения параметров не включались, что приводило к неправильному ключу кэша.References: #6858
Скорректирована функция предупреждения «from linter», чтобы приспособиться к цепочке объединений глубиной более одного уровня, в которой клаузулы ON не имеют явного соответствия целей, например, выражение типа «ON TRUE». Этот способ использования предназначен для отмены предупреждения о картезианском произведении просто по факту наличия JOIN от «a к b», что не работало для случая, когда цепочка объединений имела более одного элемента.
References: #6886
Исправлена проблема в системе лямбда-кэширования, когда элемент запроса, не создающий ключ кэша, например, элемент пользовательской опции или клаузулы, все равно заполнял выражение в «лямбда-кэше» неподобающим образом.
schema¶
Унифицируйте поведение
Enum
в родной и неродной реализации относительно принимаемых значений для перечисления с алиасированными элементами. КогдаEnum.omit_aliases
равноFalse
, все значения, включая псевдонимы, принимаются как допустимые. КогдаEnum.omit_aliases
равноTrue
, только значения без псевдонимов принимаются как допустимые.References: #6146
mypy¶
Добавлена поддержка определения классов SQLAlchemy в пользовательском коде с использованием синтаксиса «общего класса», определенного
sqlalchemy2-stubs
, напримерColumn[String]
, без необходимости квалификации этих конструкций в блокеTYPE_CHECKING
путем реализации специального метода Python__class_getitem__()
, который позволяет этому синтаксису проходить без ошибок во время выполнения.
postgresql¶
Добавлен флаг «is_comparison» к операторам PostgreSQL «overlaps», «contained_by», «contains», чтобы они работали в соответствующих контекстах ORM, а также в сочетании с функцией «from linter».
References: #6886
mssql¶
Исправлена проблема, при которой флаг компилятора
literal_binds
, используемый для вывода связанных параметров в строку, не работал при использовании с определенным классом параметров, известным как «literal_execute», который охватывает такие вещи, как значения LIMIT и OFFSET для диалектов, в которых драйверы не позволяют связанный параметр, например, клаузулу «TOP» SQL Server. На местном уровне проблема, похоже, затрагивает только диалект MSSQL.References: #6863
misc¶
Исправлена проблема, при которой расширение горизонтального шардинга некорректно учитывало обычный текстовый SQL-запрос, переданный в
Session.execute()
.References: #6816
1.4.22¶
Released: July 21, 2021orm¶
Исправлена проблема в новом методе
Table.table_valued()
, когда результирующая конструкцияTableValuedColumn
некорректно реагировала на адаптацию псевдонимов, как это используется в ORM, например, для нетерпеливой загрузки, полиморфной загрузки и т.д.References: #6775
Исправлена проблема, при которой использование метода
Result.unique()
с результатом ORM, включающим выражения столбцов с нехешируемыми типами, такими какJSON
илиARRAY
, использующими не кортежи, молча возвращалось к использованию функцииid()
, вместо того, чтобы выдать ошибку. Теперь это приводит к ошибке, когда методResult.unique()
используется в запросе ORM в стиле 2.0. Кроме того, хэшируемость принимается за True для значений результата неизвестного типа, что часто случается при использовании SQL-функций с неизвестным возвращаемым типом; если значения действительно не хэшируемы, то сама функцияhash()
будет выдавать ошибку.Для старых запросов ORM, поскольку старый объект
Query
уникализируется во всех случаях, старые правила остаются в силе, а именно: использоватьid()
для значений результата неизвестного типа, поскольку эта унаследованная уникализация в основном предназначена для уникализации сущностей ORM, а не значений столбцов.References: #6769
Исправлена проблема, при которой очистка мапперов во время таких операций, как завершение тестового набора, могла вызвать предупреждение «размер словаря изменился» во время сборки мусора, из-за итерации словаря со слабыми ссылками. Для предотвращения влияния одновременного GC на эту операцию была применена
list()
.References: #6771
Исправлена критическая проблема кэширования, когда функция сохранения ORM с помощью INSERT..RETURNING кэшировала некорректный запрос при смешивании форм INSERT «bulk save» и стандартного «flush».
References: #6793
engine¶
Добавлены некоторые меры защиты от
KeyError
в системе событий, чтобы учесть случай, когда интерпретатор завершает работу в то же время, когда вызываетсяEngine.dispose()
, что привело бы к предупреждениям о трассировке стека.References: #6740
sql¶
Исправлена проблема, при которой использование параметра
case.whens
, передающего словарь позиционно, а не в качестве аргумента ключевого слова, выдавало предупреждение об устаревании версии 2.0, ссылаясь на устаревание передачи списка позиционно. Формат словаря «whens», передаваемый позиционно, по-прежнему поддерживается и случайно был помечен как устаревший.References: #6786
Исправлена проблема, при которой обработчики связанных параметров, специфичные для конкретного типа, не вызывались в случае использования метода
Insert.values()
со значением PythonNone
; в частности, это было заметно при использовании типа данныхJSON
, а также связанных с ним типов PostgreSQL, таких какJSONB
, которые не кодировали значение PythonNone
в JSON null, однако проблема была обобщена на любой обработчик связанных параметров в сочетании с этим специфичным методомInsert
.References: #6770
1.4.21¶
Released: July 14, 2021orm¶
Изменен подход, используемый для отслеживания истории отношений скалярных объектов, которые не являются отношениями «многие-к-одному», т.е. отношения «один-к-одному», которые в противном случае были бы отношениями «один-ко-многим». При замене значения один-к-одному «старое» значение, которое будет заменено, больше не загружается немедленно, а обрабатывается в процессе смыва. Это устраняет исторически неприятную ленивую загрузку, которая часто возникает при присвоении атрибута один-к-одному, и особенно неприятна при использовании «lazy=“raise“», а также в случаях использования asyncio.
Это изменение вызывает изменение поведения события
AttributeEvents.set()
, которое, тем не менее, в настоящее время документировано, а именно: событие, примененное к такому атрибуту один-к-одному, больше не будет получать «старый» параметр, если оно выгружено и флагrelationship.active_history
не установлен. Как документировано вAttributeEvents.set()
, если обработчику события необходимо получить «старое» значение при срабатывании события, флаг active_history должен быть установлен либо у слушателя события, либо у отношения. Это уже поведение с другими видами атрибутов, такими как многие-к-одному и ссылки на значения столбцов.Это изменение дополнительно отложит обновление обратного ссылки на «старое» значение в менее распространенном случае, когда «старое» значение локально присутствует в сессии, но не загружено в рассматриваемое отношение, до следующей очистки. Если это вызывает проблему, опять же, обычный флаг
relationship.active_history
может быть установлен вTrue
для отношения.References: #6708
Исправлена регрессия, возникшая в 1.4.19 из-за #6503 и связанных с ним
Query.with_entities()
, когда используемая новая структура неправомерно передавалась в объемлющийQuery
при использовании операций с множествами, таких какQuery.union()
, в результате чего инструкции JOIN внутри применялись и к внешнему запросу.References: #6698
Исправлена регрессия, появившаяся в версии 1.4.3 из-за #6060, когда правила, ограничивающие ORM-адаптацию производных selectables, вмешивались в другие случаи, основанные на ORM-адаптации, в данном случае при применении адаптации для
with_polymorphic()
к отображению, использующемуcolumn_property()
, которое в свою очередь использует скалярный select, включающийaliased()
объект отображаемой таблицы.References: #6762
Исправлена регрессия ORM, когда специальные имена меток, создаваемые для гибридных свойств и потенциально других подобных типов выражений с поддержкой ORM, обычно распространялись наружу через подзапросы, что позволяло сохранить имя в конечных ключах набора результатов даже при выборе из подзапросов. В этом случае отслеживается дополнительное состояние, которое не теряется, когда гибрид выбирается из Core select / подзапроса.
References: #6718
sql¶
Добавлен новый метод
HasCTE.add_cte()
к каждой из конструкцийselect()
,insert()
,update()
иdelete()
. Этот метод добавит данныйCTE
в качестве «независимого» CTE оператора, то есть он безоговорочно отображается в предложение WITH над оператором, даже если на него нет других ссылок в основном операторе. Это популярный случай использования в базе данных PostgreSQL, когда CTE используется для оператора DML, который работает со строками базы данных независимо от основного оператора.References: #6752
Исправлена проблема в конструкциях CTE, когда рекурсивный CTE, ссылающийся на SELECT с дублирующимися именами столбцов, которые обычно дедуплицируются с помощью логики маркировки в 1.4, не мог правильно сослаться на дедуплицированное имя метки в предложении WITH.
References: #6710
Исправлена регрессия, при которой конструкция
tablesample()
была неисполнимой, если она строилась с учетом значения выборки с плавающей точкой, не встроенной в функцию SQL.References: #6735
postgresql¶
Исправлена проблема в
Insert.on_conflict_do_nothing()
иInsert.on_conflict_do_update()
, когда имя уникального ограничения, переданное в качестве параметраconstraint
, не усекалось по длине, если оно было основано на соглашении об именовании, которое создавало слишком длинное имя для максимальной длины идентификатора PostgreSQL в 63 символа, аналогично тому, как это происходит в операторе CREATE TABLE.References: #6755
Исправлена проблема, из-за которой тип данных PostgreSQL
ENUM
, встроенный в тип данныхARRAY
, не работал корректно в режиме create/drop, когда также использовалась функцияschema_translate_map
. Кроме того, была устранена связанная с этим проблема, когда та же функцияschema_translate_map
не работала для типа данныхENUM
в комбинации сCAST
, что также присуще тому, как комбинацияARRAY(ENUM)
работает в диалекте PostgreSQL.References: #6739
Исправлена проблема в
Insert.on_conflict_do_nothing()
иInsert.on_conflict_do_update()
, когда имя уникального ограничения, переданное в качестве параметраconstraint
, не заключалось в кавычки, если содержало символы, требующие кавычек.References: #6696
mssql¶
Исправлена регрессия, при которой специальная обработка точечных имен схем для диалекта SQL Server работала неправильно, если точечное имя схемы использовалось в функции
schema_translate_map
.References: #6697
1.4.20¶
Released: June 28, 2021orm¶
Исправлена регрессия в ORM, касающаяся внутреннего шага восстановления для конструкции
with_polymorphic()
, когда объект, обращенный к пользователю, собирается в мусор в процессе обработки запроса. Восстановление не обеспечивало обработку подсубъектов для «полиморфного» случая, что приводило к появлениюAttributeError
.References: #6680
Скорректировано
Query.union()
и аналогичные операции с множествами для корректной совместимости с новыми возможностями, только что добавленными в #6661, с SQLAlchemy 1.4. 19, так что операторы SELECT, отображаемые как элементы операции UNION или другого набора, будут включать непосредственно сопоставленные столбцы, которые отображаются как отложенные; это устраняет регрессию, связанную с союзами с несколькими уровнями вложенности, которые приводили к несоответствию столбцов, а также позволяет использовать опциюundefer()
на верхнем уровне такогоQuery
без необходимости применять опцию к каждому из элементов внутри UNION.References: #6678
Скорректирована проверка в маппере для вызываемого объекта, который используется как функция валидатора
@validates
или функция реконструкции@reconstructor
, для более свободной проверки «вызываемого», например, для размещения объектов, основанных на фундаментальных атрибутах, таких как__func__
и__call__
, вместо проверки наMethodType
/FunctionType
, что позволяет таким вещам, как функции cython, работать правильно. Pull request courtesy Miłosz Stypiński.References: #6538
engine¶
Исправлена проблема в расширении C для класса
Row
, которая могла привести к утечке памяти в маловероятном случае, когда объектRow
ссылался на объект ORM, который затем мутировал, чтобы снова ссылаться на самRow
, создавая цикл. API Python C для отслеживания циклов GC был добавлен в родную реализациюRow
, чтобы учесть этот случай.References: #5348
Исправлена старая проблема, когда при выполнении
select()
против маркера «*», который затем давал ровно один столбец, имя столбцаcursor.description
не удавалось правильно организовать в ключи объекта результата.References: #6665
sql¶
Добавьте параметр impl в конструктор
PickleType
, позволяющий использовать любой произвольный тип вместо реализации по умолчаниюLargeBinary
. Pull request любезно предоставлен jason3gb.References: #6646
Исправлена иерархия классов для базы
Sequence
и более общей базыDefaultGenerator
, поскольку они являются «исполняемыми» как утверждения, они должны включатьExecutable
в свою иерархию, а не толькоStatementRole
, как это произвольно применялось кSequence
ранее. Исправление позволяетSequence
работать во всех методах.execute()
, включаяSession.execute()
, который не работал в случае, если был также создан обработчикSessionEvents.do_orm_execute()
.References: #6668
schema¶
Исправлена проблема, при которой передача
None
для значенияTable.prefixes
сохраняла не пустой список, а константуNone
, что могло быть неожиданным для сторонних диалектов. Проблема выявлена при использовании в последних версиях Alembic, которые передаютNone
для этого значения. Pull request любезно предоставлен Каем Мюллером.References: #6685
mysql¶
Внесена небольшая корректировка в функцию отражения таблиц в диалекте MySQL для адаптации к альтернативным базам данных, ориентированным на MySQL, таким как TiDB, которые включают свои собственные директивы «комментарий» в конце директивы ограничения в «CREATE TABLE», где формат не имеет дополнительного символа пробела после комментария, в данном случае функция TiDB «кластерный индекс». Pull request любезно предоставлен Daniël van Eeden.
References: #6659
misc¶
Исправлена регрессия в расширении
sqlalchemy.ext.automap
, из-за которой случай создания явного сопоставленного класса с таблицей, которая также являетсяrelationship.secondary
элементомrelationship()
, генерируемого automap, выдавал предупреждения «перекрытия», введенные в 1.4 и обсуждаемые в отношение X скопирует столбец Q в столбец P, что противоречит отношению(ям): „Y“. Хотя генерация этого случая из automap все еще подвержена тем же предостережениям, к которым относится предупреждение «перекрытия», поскольку automap предназначен для более специальных случаев использования, условие, вызывающее предупреждение, отключается, когда генерируется отношение «многие-ко-многим» с этим конкретным шаблоном.References: #6679
1.4.19¶
Released: June 22, 2021orm¶
Исправлены дальнейшие регрессии в той же области, что и в #6052, где опции загрузчика, а также вызовы таких методов, как
Query.join()
, будут неудачными, если левая часть утверждения, от которого зависит опция/соединение, будет заменена с помощью методаQuery.with_entities()
, или при использовании запросов в стиле 2.0 с помощью методаSelect.with_only_columns()
. К объектам был добавлен новый набор состояний, который отслеживает «левые» сущности, по отношению к которым были сделаны опции/соединения, которые мемоизируются при изменении ведущих сущностей.Усовершенствовано поведение рендеринга подзапросов ORM в отношении отложенных столбцов и свойств столбцов, чтобы сделать его более совместимым с 1.3 и в то же время обеспечить более новые возможности 1.4. Поскольку подзапрос в 1.4 не использует опции загрузчика, включая
undefer()
, подзапрос, направленный на сущность ORM с отложенными атрибутами, теперь будет отображать те отложенные атрибуты, которые ссылаются непосредственно на сопоставленные столбцы таблицы, поскольку они необходимы во внешнем SELECT, если внешний SELECT использует эти столбцы; однако отложенные атрибуты, которые ссылаются на составленное SQL-выражение, как мы обычно делаем сcolumn_property()
, не будут частью подзапроса, поскольку они могут быть выбраны явно, если это необходимо в подзапросе. Если сущность выбирается из этого подзапроса, то выражение столбца все равно может отображаться «снаружи» в терминах производных столбцов подзапроса. Это приводит к такому же поведению, как и при работе с 1.3. Однако в этом случае исправление также должно гарантировать, что коллекция.selected_columns
в коллекцииselect()
с поддержкой ORM также следует этим правилам, что, в частности, позволяет рекурсивным CTE корректно отображаться в этом сценарии, которые ранее не отображались корректно из-за этой проблемы.References: #6661
sql¶
Исправлена проблема в конструкциях CTE, в основном относящаяся к случаям использования ORM, когда рекурсивный CTE против «анонимных» меток, таких как те, что встречаются в связках ORM
column_property()
, приводил в секцииWITH RECURSIVE xyz(...)
их необработанную внутреннюю метку, а не чистое анонимизированное имя.References: #6663
mypy¶
Исправлена проблема в плагине mypy, когда информация о классе для пользовательской декларативной базы не обрабатывалась корректно при кэшированном проходе mypy, что приводило к возникновению ошибки AssertionError.
References: #6476
asyncio¶
Реализована
async_scoped_session
для решения некоторых асинхронных несовместимостей междуscoped_session
иAsyncSession
, в которых некоторые методы (в частности, методasync_scoped_session.remove()
) должны использоваться с ключевым словомawait
.См.также
References: #6583
Исправлена ошибка в реализации asyncio, когда система адаптации greenlet не распространяла подклассы
BaseException
, особенно включаяasyncio.CancelledError
, на логику обработки исключений, используемую движком для аннулирования и очистки соединения, тем самым предотвращая корректную утилизацию соединений при отмене задачи.References: #6652
postgresql¶
Исправлена проблема, при которой тип данных
INTERVAL
в PostgreSQL и Oracle выдавалAttributeError
при использовании в контексте операции сравнения с объектомtimedelta()
. Pull request любезно предоставлен MajorDallas.References: #6649
Исправлена проблема, когда функция «pre ping» пула неявно запускала транзакцию, что мешало использованию пользовательских транзакционных флагов, таких как режим «только чтение» PostgreSQL, при использовании с драйвером psycopg2.
References: #6621
mysql¶
Добавлена новая конструкция
match
, которая обеспечивает полный спектр возможностей оператора MySQL MATCH, включая поддержку нескольких столбцов и модификаторы. Pull request любезно предоставлен Антоном Ковалевичем.См.также
match
References: #6132
mssql¶
Внесены улучшения в regexp версии сервера, используемый диалектом pymssql, для предотвращения переполнения regexp в случае недопустимой строки версии.
Исправлена ошибка, при которой функция «schema_translate_map» не работала корректно в сочетании с INSERT в таблицу с колонкой IDENTITY, где значение колонки IDENTITY указывалось в значениях INSERT, тем самым вызывая функцию SQLAlchemy по установке IDENTITY INSERT в значение «on»; именно в этой директиве карта перевода схемы не выполнялась.
References: #6658
1.4.18¶
Released: June 10, 2021orm¶
Исправлена регрессия, связанная с тем, как ORM разрешает заданный сопоставленный столбец в строку результата, когда в таких случаях, как объединенная нетерпеливая загрузка, для установки этого разрешения мог иметь место немного более дорогой «откат» из-за некоторой логики, которая была удалена с версии 1.3. Эта проблема также может привести к выдаче предупреждений об устаревании, связанных с разрешением столбцов, при использовании запросов в стиле 1.4 с объединенной ускоренной загрузкой.
References: #6596
Уточнено текущее назначение флага
relationship.bake_queries
, который в версии 1.4 используется для включения или отключения «лямбда-кэширования» утверждений в рамках стратегий загрузчика «lazyload» и «selectinload»; это отделено от более фундаментального кэша SQL-запросов, который используется для большинства утверждений. Кроме того, ленивый загрузчик больше не использует свой собственный кэш для SQL-запросов типа «многие к одному», что было причудой реализации, не существующей ни для одного другого сценария загрузчика. Наконец, предупреждение «lru cache», которое стратегии lazyloader и selectinloader могли выдавать при работе с широким набором комбинаций классов/отношений, было удалено; на основе анализа некоторых случаев конечных пользователей, это предупреждение не указывает на какую-либо существенную проблему. Хотя установкаbake_queries=False
для такого отношения удалит этот кэш из использования, особого выигрыша в производительности в этом случае нет, так как использование без кэширования по сравнению с использованием кэша, который нужно часто обновлять, скорее всего, все равно выигрывает в пользу используемого кэширования.Скорректировано средство, с помощью которого такие классы, как
scoped_session
иAsyncSession
генерируются из базового классаSession
, так что пользовательским подклассамSession
, например, используемым в Flask-SQLAlchemy, не нужно реализовывать позиционные аргументы при вызове метода суперкласса, и они могут продолжать использовать те же стили аргументов, что и в предыдущих выпусках.References: #6285
Исправлена проблема, когда при создании запроса для объединенной загрузки со сложной левой стороной, включающей наследование объединенных таблиц, мог не получиться корректный запрос из-за проблемы адаптации клаузулы.
References: #6595
Исправлена проблема в экспериментальном примере использования «select ORM objects from INSERT/UPDATE», когда возникала ошибка, если оператор был направлен против подкласса, наследующего одну таблицу.
References: #6591
Предупреждение, выдаваемое для
relationship()
, когда несколько отношений будут перекрывать друг друга в части атрибутов внешнего ключа, теперь включает в себя конкретный аргумент «overlaps», который следует использовать для каждого предупреждения, чтобы заглушить предупреждение без изменения отображения.References: #6400
asyncio¶
Реализована новая архитектура реестра, которая позволяет
Async
версии объекта, напримерAsyncSession
,AsyncConnection
и т.д., быть доступной для поиска, учитывая проксированный «синхронный» объект, т.е.Session
,Connection
. Ранее, когда использовались такие функции поиска, объектAsync
создавался каждый раз заново, что было менее чем идеально, так как идентичность и состояние объекта «async» не сохранялись при каждом вызове.Отсюда были добавлены новые вспомогательные функции
async_object_session()
,async_session()
, а также новый атрибутInstanceState
InstanceState.async_session
, которые используются для получения исходногоAsyncSession
, связанного с ORM mapped object,Session
, связанного сAsyncSession
, иAsyncSession
, связанного сInstanceState
, соответственно.В этом патче также реализованы новые методы
AsyncSession.in_nested_transaction()
,AsyncSession.get_transaction()
,AsyncSession.get_nested_transaction()
.References: #6319
Исправлена проблема, возникавшая при использовании
NullPool
илиStaticPool
с асинхронным механизмом. В основном это касалось диалекта aiosqlite.References: #6575
Добавлены
asyncio.exceptions.TimeoutError
,asyncio.exceptions.CancelledError
как так называемые «исключения выхода», класс исключений, включающий такие вещи, какGreenletExit
иKeyboardInterrupt
, которые считаются событиями, дающими основание считать соединение DBAPI непригодным для использования и подлежащим утилизации.References: #6592
postgresql¶
Исправлена регрессия, при которой использование структуры PostgreSQL «INSERT..ON CONFLICT» не работало с драйвером psycopg2, если она использовалась в контексте «executemany» вместе со связанными параметрами в предложении «SET», из-за неявного использования помощников быстрого выполнения psycopg2, которые не подходят для этого стиля оператора INSERT; поскольку эти помощники используются по умолчанию в 1.4, это фактически является регрессией. Были добавлены дополнительные проверки, чтобы исключить этот тип оператора из данного конкретного расширения.
References: #6581
sqlite¶
Добавьте примечание относительно прагм, связанных с шифрованием, для pysqlcipher, передаваемого в url.
This change is also backported to: 1.3.25
References: #6589
Исправление для pysqlcipher, выпущенное в версии 1.4.3 #5848, к сожалению, было нерабочим, поскольку новый хук
on_connect_url
ошибочно не получал объектURL
при нормальном использованииcreate_engine()
, а вместо него получал необработанную строку; набор тестов не смог полностью установить реальные условия, при которых вызывается этот хук. Это было исправлено.References: #6586
1.4.17¶
Released: May 29, 2021orm¶
Исправлена регрессия, вызванная только что выпущенным исправлением производительности, упомянутым в #6550, когда запрос query.join() к отношению мог выдать ошибку AttributeError, если запрос выполнялся только к не-ORM структурам, что является довольно необычным шаблоном вызова.
References: #6558
1.4.16¶
Released: May 28, 2021general¶
orm¶
Исправлена проблема при использовании параметра
relationship.cascade_backrefs
, установленного вFalse
, который в соответствии с cascade_backrefs behavior deprecated for removal in 2.0 станет стандартным поведением в SQLAlchemy 2.0, когда добавление элемента в коллекцию, которая уникализирует, например,set
илиdict
, не вызывало каскадного события, если объект уже был связан с этой коллекцией через обратную ссылку. Это исправление представляет собой фундаментальное изменение в механике коллекций, вводя новое состояние события, которое может сработать при мутации коллекции, даже если в коллекции нет чистых изменений; теперь это действие выполняется с помощью нового хука событияAttributeEvents.append_wo_mutation()
.References: #6471
Исправлена регрессия, связанная с адаптацией пунктов для маркированных составных элементов ORM, таких как выражения дискриминатора наследования одной таблицы с условиями или CASE-выражения, что могло привести к неправильной адаптации псевдослучайных выражений, таких как используемые в операциях ORM join / joinload, например, обращение к неправильной таблице в пункте ON в соединении.
Это изменение также улучшает недостаток производительности, который возникал в процессе вызова
Select.join()
, когда в качестве цели указывался атрибут ORM.References: #6550
Исправлена регрессия, при которой полная комбинация объединенного наследования, глобальных отношений with_polymorphic, самореферентных отношений и объединенной загрузки не могла создать запрос с областью действия ленивых загрузок и операций обновления объектов, которые также пытались отобразить объединенный загрузчик.
References: #6495
Усовершенствованы правила разрешения привязки для
Session.execute()
, так что когда не-ORM утверждение, такое как конструкцияinsert()
, тем не менее строится против ORM объектов, в максимально возможной степени ORM сущность будет использоваться для разрешения привязки, например, дляSession
, который имеет карту привязки, установленную на общем суперклассе без конкретных мапперов или таблиц, названных в карте.References: #6484
engine¶
Исправлена проблема, при которой знак
@
в части URL, посвященной базе данных, интерпретировался неправильно, если URL также содержал раздел имя пользователя:пароль.References: #6482
Исправлена давняя проблема с
URL
, когда параметры запроса, следующие за вопросительным знаком, не обрабатывались правильно, если URL не содержал часть базы данных с обратной косой чертой.References: #6329
sql¶
Исправлена регрессия в стратегии динамического загрузчика и
relationship()
overall, когда параметрrelationship.order_by
хранился как изменяемый список, который затем мог быть изменен в сочетании с дополнительными методами «order_by», используемыми против объекта динамического запроса, что приводило к повторяющемуся росту критериев ORDER BY.References: #6549
mssql¶
Реализована поддержка использования конструкции
CTE
непосредственно в качестве цели конструкцииdelete()
, т.е. «WITH … AS cte DELETE FROM cte». Это представляется полезной функцией SQL Server.References: #6464
misc¶
Исправлено предупреждение об устаревании, которое выдавалось при использовании
automap_base()
без передачи существующегоBase
.References: #6529
Удалить типы pep484 из кода. Текущие усилия направлены на пакет заглушек, а наличие типов в двух местах ухудшает ситуацию, так как типы в исходниках SQLAlchemy обычно устарели по сравнению с версиями в заглушках.
References: #6461
Исправлена регрессия в расширении
sqlalchemy.ext.instrumentation
, из-за которой утилизация инструментов не работала полностью. Это исправление включает в себя как исправление регрессии в версии 1.4, так и исправление связанной с ней проблемы, которая существовала и в версии 1.3. В рамках этого изменения классsqlalchemy.ext.instrumentation.InstrumentationManager
теперь имеет новый методunregister()
, который заменяет предыдущий методdispose()
, который не вызывался начиная с версии 1.4.References: #6390
1.4.15¶
Released: May 11, 2021general¶
Новый подход был применен к системе предупреждений в SQLAlchemy для точного динамического предсказания соответствующего уровня стека для каждого предупреждения. Это позволяет более просто оценить источник предупреждений, генерируемых SQLAlchemy, и предупреждений об устаревании, поскольку предупреждение будет указывать на исходную строку в коде конечного пользователя, а не на произвольный уровень в собственном исходном коде SQLAlchemy.
References: #6241
orm¶
Исправлена дополнительная регрессия, вызванная функцией #1763 «eager loaders run on unexpire», когда функция запускалась для опции
contains_eager()
eagerload в случае, еслиcontains_eager()
были соединены в цепь с дополнительной опцией eager loader, что приводило к некорректному запросу, так как исходные критерии объединения, связанные с запросом, больше не присутствовали.References: #6449
Исправлена проблема в стратегии загрузчика подзапросов, из-за которой кэширование не работало корректно. В журналах это выглядело как сообщение «generated» вместо «cached» для всех SQL-запросов, выдаваемых при загрузке подзапросов, что, насыщая кэш новыми ключами, снижало общую производительность; это также вызывало предупреждения «LRU size alert».
References: #6459
sql¶
Скорректирована логика, добавленная в 1.4.12 в качестве части #6397, таким образом, чтобы внутренняя мутация объекта
BindParameter
происходила на этапе построения клаузы, как это было раньше, а не на этапе компиляции. В последнем случае мутация все еще производила побочные эффекты против входящей конструкции и, кроме того, могла потенциально вмешиваться в работу других процедур внутренней мутации.References: #6460
mysql¶
Добавлена поддержка параметра
ssl_check_hostname=
в URIs соединений mysql и обновлена документация по диалекту mysql относительно безопасных соединений. Оригинальный pull request любезно предоставлен Джерри Чжао.References: #5397
1.4.14¶
Released: May 6, 2021orm¶
Исправлена регрессия, связанная с загрузчиком
lazy='dynamic'
в сочетании с отделенным объектом. Предыдущее поведение заключалось в том, что динамический загрузчик при вызове методов типа.all()
возвращает пустые списки для отсоединенных объектов без ошибок, это было восстановлено; однако теперь выдается предупреждение, поскольку это не является правильным результатом. Другие сценарии динамического загрузчика корректно возвращаютDetachedInstanceError
.References: #6426
engine¶
Применили последовательное поведение к случаю вызова
.commit()
или.rollback()
внутри существующего.begin()
менеджера контекста, с добавлением потенциально возможного испускания SQL внутри блока после фиксации или отката. Это изменение продолжает изменение, впервые добавленное в #6155, где был предложен случай использования вызова «rollback» внутри блока контекстного менеджера.begin()
:вызов
.commit()
или.rollback()
теперь будет разрешен без ошибок и предупреждений во всех диапазонах, включая унаследованные и будущиеEngine
, ORMSession
, asyncioAsyncEngine
. РанееSession
запрещал это.Затем закрывается оставшаяся область действия менеджера контекста; когда блок завершается, выдается проверка, была ли транзакция уже завершена, и если да, то блок возвращается без каких-либо действий.
Теперь будет возникать ошибка, если последующий SQL любого вида будет выдан внутри блока, после вызова
.commit()
или.rollback()
. Блок должен быть закрыт, так как состояние исполняемого объекта в этом случае будет неопределенным.
References: #6288
Установлен путь устаревания для вызова метода
CursorResult.keys()
для оператора, который не возвращает строк, чтобы обеспечить поддержку устаревших шаблонов, используемых пакетом «records», а также любых других немигрированных приложений. Ранее метод вызывал безусловную ошибкуResourceClosedException
, как и при попытке получить строки. Хотя это правильное поведение в дальнейшем, объект_cursor.LegacyCursorResult
теперь в этом случае будет возвращать пустой список для.keys()
, как это было в версии 1.3, а также выдавать предупреждение об устаревании версии 2.0. Объект_cursor.CursorResult
, используемый при использовании движка «будущего» в стиле 2.0, будет продолжать возвращать пустой список, как и сейчас.References: #6427
sql¶
Исправлена регрессия, вызванная изменением «пусто в», только что сделанным в #6397 1.4.12, где выражение должно быть заключено в скобки для случая использования «не в», иначе условие будет мешать другим критериям фильтрации.
References: #6428
Класс
TypeDecorator
теперь будет выдавать предупреждение при использовании в компиляции SQL с кэшированием, если флаг.cache_ok
не установлен наTrue
илиFalse
. Можно установить новый атрибут уровня классаTypeDecorator.cache_ok
, который будет использоваться как признак того, что все параметры, переданные объекту, безопасны для использования в качестве ключа кэша, если установлено значениеTrue
,False
означает, что нет.References: #6436
1.4.13¶
Released: May 3, 2021orm¶
Исправлена регрессия в стратегии загрузчика
selectinload
, из-за которой он некорректно кэшировал свое внутреннее состояние при работе с отношениями, объединяющими более одного столбца, например, при использовании составного внешнего ключа. Некорректное кэширование приводило к сбою других несвязанных операций загрузчика.References: #6410
Исправлена регрессия, при которой
Query.filter_by()
не работал, если ведущей сущностью была SQL-функция или другое выражение, производное от первичной сущности, а не простая сущность или столбец этой сущности. Кроме того, улучшено поведениеSelect.filter_by()
в целом для работы с выражениями столбцов даже в не-ORM контексте.References: #6414
Исправлена ошибка, при которой использование
selectinload()
иsubqueryload()
для загрузки пути глубиной в два уровня приводило к ошибке атрибута.References: #6419
Исправлена регрессия, при которой использование стратегии загрузчика
noload()
в сочетании с «динамическим» отношением приводило к ошибке атрибута, поскольку стратегия noload пыталась применить себя к динамическому загрузчику.References: #6420
engine¶
Восстановлено устаревшее транзакционное поведение, которое было непреднамеренно удалено из
Connection
, так как оно никогда не тестировалось как известный случай использования в предыдущих версиях, когда вызов методаConnection.begin_nested()
при отсутствии транзакции вообще не создает SAVEPOINT, а вместо этого запускает внешнюю транзакцию, возвращая объектRootTransaction
вместо объектаNestedTransaction
. Затем этот объектRootTransaction
будет выдавать настоящий COMMIT на соединение с базой данных при фиксации. Ранее поведение в стиле 2.0 присутствовало во всех случаях, которые автозапускали транзакцию, но не фиксировали ее, что является изменением поведения.При использовании объекта соединения 2.0 style поведение не изменилось по сравнению с предыдущими версиями 1.4; вызов
Connection.begin_nested()
«автозапускает» внешнюю транзакцию, если она еще не существует, а затем, согласно инструкциям, выдает SAVEPOINT, возвращая объектNestedTransaction
. Внешняя транзакция фиксируется вызовомConnection.commit()
, как и положено при использовании стиля «commit-as-you-go».В режиме без «будущего», хотя старое поведение восстанавливается, оно также выдает предупреждение об обесценивании 2.0, поскольку это унаследованное поведение.
References: #6408
asyncio¶
Исправлена регрессия, вызванная #6337, которая создавала
asyncio.Lock
, который мог быть присоединен к неправильному циклу при инстанцировании движка async до запуска любого цикла asyncio, что приводило к сообщению об ошибке asyncio при попытке использовать движок при определенных обстоятельствах.References: #6409
postgresql¶
Добавьте поддержку курсоров на стороне сервера в диалекте pg8000 для PostgreSQL. Это позволяет использовать опцию
Connection.execution_options.stream_results
.References: #6198
1.4.12¶
Released: April 29, 2021orm¶
Исправлена проблема в
Session.bulk_save_objects()
при использовании с постоянными объектами, из-за которой не удавалось отследить первичный ключ в связках, где имя столбца первичного ключа отличалось от имени атрибута.This change is also backported to: 1.3.25
References: #6392
Fixed critical regression where bound parameter tracking as used in the SQL caching system could fail to track all parameters for the case where the same SQL expression containing a parameter were used in an ORM-related query using a feature such as class inheritance, which was then embedded in an enclosing expression which would make use of that same expression multiple times, such as a UNION. The ORM would individually copy the individual SELECT statements as part of compilation with class inheritance, which then embedded in the enclosing statement would fail to accommodate for all parameters. The logic that tracks this condition has been adjusted to work for multiple copies of a parameter.
References: #6391
Fixed two distinct issues mostly affecting
hybrid_property
, which would come into play under common mis-configuration scenarios that were silently ignored in 1.3, and now failed in 1.4, where the «expression» implementation would return a nonClauseElement
such as a boolean value. For both issues, 1.3’s behavior was to silently ignore the mis-configuration and ultimately attempt to interpret the value as a SQL expression, which would lead to an incorrect query.Fixed issue regarding interaction of the attribute system with hybrid_property, where if the
__clause_element__()
method of the attribute returned a non-ClauseElement
object, an internalAttributeError
would lead the attribute to return theexpression
function on the hybrid_property itself, as the attribute error was against the name.expression
which would invoke the__getattr__()
method as a fallback. This now raises explicitly. In 1.3 the non-ClauseElement
was returned directly.Fixed issue in SQL argument coercions system where passing the wrong kind of object to methods that expect column expressions would fail if the object were altogether not a SQLAlchemy object, such as a Python function, in cases where the object were not just coerced into a bound value. Again 1.3 did not have a comprehensive argument coercion system so this case would also pass silently.
References: #6350
Fixed issue where using a
Select
as a subquery in an ORM context would modify theSelect
in place to disable eagerloads on that object, which would then cause that sameSelect
to not eagerload if it were then re-used in a top-level execution context.References: #6378
Fixed issue where the new autobegin behavior failed to «autobegin» in the case where an existing persistent object has an attribute change, which would then impact the behavior of
Session.rollback()
in that no snapshot was created to be rolled back. The «attribute modify» mechanics have been updated to ensure «autobegin», which does not perform any database work, does occur when persistent attributes change in the same manner as whenSession.add()
is called. This is a regression as in 1.3, the rollback() method always had a transaction to roll back and would expire every time.Fixed regression in ORM where using hybrid property to indicate an expression from a different entity would confuse the column-labeling logic in the ORM and attempt to derive the name of the hybrid from that other class, leading to an attribute error. The owning class of the hybrid attribute is now tracked along with the name.
References: #6386
Fixed regression in hybrid_property where a hybrid against a SQL function would generate an
AttributeError
when attempting to generate an entry for the.c
collection of a subquery in some cases; among other things this would impact its use in cases like that ofQuery.count()
.References: #6401
Adjusted the declarative scan for dataclasses so that the inheritance behavior of
declared_attr()
established on a mixin, when using the new form of having it inside of adataclasses.field()
construct and not actually a descriptor attribute on the class, correctly accommodates the case when the target class to be mapped is a subclass of an existing mapped class which has already mapped thatdeclared_attr()
, and therefore should not be re-applied to this class.References: #6346
Fixed an issue with the (deprecated in 1.4)
ForeignKeyConstraint.copy()
method that caused an error when invoked with theschema
argument.References: #6353
engine¶
Fixed issue where usage of an explicit
Sequence
would produce inconsistent «inline» behavior for anInsert
construct that includes multiple values phrases; the first seq would be inline but subsequent ones would be «pre-execute», leading to inconsistent sequence ordering. The sequence expressions are now fully inline.References: #6361
sql¶
Revised the «EMPTY IN» expression to no longer rely upon using a subquery, as this was causing some compatibility and performance problems. The new approach for selected databases takes advantage of using a NULL-returning IN expression combined with the usual «1 != 1» or «1 = 1» expression appended by AND or OR. The expression is now the default for all backends other than SQLite, which still had some compatibility issues regarding tuple «IN» for older SQLite versions.
Third party dialects can still override how the «empty set» expression renders by implementing a new compiler method
def visit_empty_set_op_expr(self, type_, expand_op)
, which takes precedence over the existingdef visit_empty_set_expr(self, element_types)
which remains in place.Fixed regression where usage of the
text()
construct inside the columns clause of aSelect
construct, which is better handled by using aliteral_column()
construct, would nonetheless prevent constructs likeunion()
from working correctly. Other use cases, such as constructing subuqeries, continue to work the same as in prior versions where thetext()
construct is silently omitted from the collection of exported columns. Also repairs similar use within the ORM.References: #6343
Fixed regression involving legacy methods such as
Select.append_column()
where internal assertions would fail.References: #6261
Fixed regression caused by #5395 where tuning back the check for sequences in
select()
now caused failures when doing 2.0-style querying with a mapped class that also happens to have an__iter__()
method. Tuned the check some more to accommodate this as well as some other interesting__iter__()
scenarios.References: #6300
schema¶
Ensure that the MySQL and MariaDB dialect ignore the
Identity
construct while rendering theAUTO_INCREMENT
keyword in a create table.The Oracle and PostgreSQL compiler was updated to not render
Identity
if the database version does not support it (Oracle < 12 and PostgreSQL < 10). Previously it was rendered regardless of the database version.References: #6338
postgresql¶
Fixed very old issue where the
Enum
datatype would not inherit theMetaData.schema
parameter of aMetaData
object when that object were passed to theEnum
usingEnum.metadata
.References: #6373
sqlite¶
Default to using
SingletonThreadPool
for in-memory SQLite databases created using URI filenames. Previously the default pool used was theNullPool
that precented sharing the same database between multiple engines.References: #6379
mssql¶
Add
TypeEngine.as_generic()
support forsqlalchemy.dialects.mysql.BIT
columns, mapping them toBoolean
.References: #6345
Fixed regression caused by #6306 which added support for
DateTime(timezone=True)
, where the previous behavior of the pyodbc driver of implicitly dropping the tzinfo from a timezone-aware date when INSERTing into a timezone-naive DATETIME column were lost, leading to a SQL Server error when inserting timezone-aware datetime objects into timezone-native database columns.References: #6366
1.4.11¶
Released: April 21, 2021orm declarative¶
Fixed regression where recent changes to support Python dataclasses had the inadvertent effect that an ORM mapped class could not successfully override the
__new__()
method.References: #6331
engine¶
1.4.10¶
Released: April 20, 2021orm¶
Altered some of the behavior repaired in #6232 where the
immediateload
loader strategy no longer goes into recursive loops; the modification is that an eager load (joinedload, selectinload, or subqueryload) from A->bs->B which then statesimmediateload
for a simple manytoone B->a->A that’s in the identity map will populate the B->A, so that this attribute is back-populated when the collection of A/A.bs are loaded. This allows the objects to be functional when detached.Fixed bug in new
with_loader_criteria()
feature where using a mixin class withdeclared_attr()
on an attribute that were accessed inside the custom lambda would emit a warning regarding using an unmapped declared attr, when the lambda callable were first initialized. This warning is now prevented using special instrumentation for this lambda initialization step.References: #6320
Fixed additional regression caused by the «eagerloaders on refresh» feature added in #1763 where the refresh operation historically would set
populate_existing
, which given the new feature now overwrites pending changes on eagerly loaded objects when autoflush is false. The populate_existing flag has been turned off for this case and a more specific method used to ensure the correct attributes refreshed.References: #6326
Fixed an issue when using 2.0 style execution that prevented using
Result.scalar_one()
orResult.scalar_one_or_none()
after callingResult.unique()
, for the case where the ORM is returning a single-element row in any case.References: #6299
sql¶
Fixed issue in SQL compiler where the bound parameters set up for a
Values
construct wouldn’t be positionally tracked correctly if inside of aCTE
, affecting database drivers that support VALUES + ctes and use positional parameters such as SQL Server in particular as well as asyncpg. The fix also repairs support for compiler flags such asliteral_binds
.References: #6327
Repaired and solidified issues regarding custom functions and other arbitrary expression constructs which within SQLAlchemy’s column labeling mechanics would seek to use
str(obj)
to get a string representation to use as an anonymous column name in the.c
collection of a subquery. This is a very legacy behavior that performs poorly and leads to lots of issues, so has been revised to no longer perform any compilation by establishing specific methods onFunctionElement
to handle this case, as SQL functions are the only use case that it came into play. An effect of this behavior is that an unlabeled column expression with no derivable name will be given an arbitrary label starting with the prefix"_no_label"
in the.c
collection of a subquery; these were previously being represented either as the generic stringification of that expression, or as an internal symbol.References: #6256
schema¶
Fixed issue where
next_value()
was not deriving its type from the correspondingSequence
, instead hardcoded toInteger
. The specific numeric type is now used.References: #6287
mypy¶
Fixed issue where mypy plugin would not correctly interpret an explicit
Mapped
annotation in conjunction with arelationship()
that refers to a class by string name; the correct annotation would be downgraded to a less specific one leading to typing errors.References: #6255
mssql¶
The
DateTime.timezone
parameter when set toTrue
will now make use of theDATETIMEOFFSET
column type with SQL Server when used to emit DDL, rather thanDATETIME
where the flag was silently ignored.References: #6306
misc¶
Fixed
instrument_declarative()
that called a non existing registry method.References: #6291
1.4.9¶
Released: April 17, 2021orm¶
Established support for
synoynm()
in conjunction with hybrid property, assocaitionproxy is set up completely, including that synonyms can be established linking to these constructs which work fully. This is a behavior that was semi-explicitly disallowed previously, however since it did not fail in every scenario, explicit support for assoc proxy and hybrids has been added.References: #6267
Fixed a critical performance issue where the traversal of a
select()
construct would traverse a repetitive product of the represented FROM clauses as they were each referred towards by columns in the columns clause; for a series of nested subqueries with lots of columns this could cause a large delay and significant memory growth. This traversal is used by a wide variety of SQL and ORM functions, including by the ORMSession
when it’s configured to have «table-per-bind», which while this is not a common use case, it seems to be what Flask-SQLAlchemy is hardcoded as using, so the issue impacts Flask-SQLAlchemy users. The traversal has been repaired to uniqify on FROM clauses which was effectively what would happen implicitly with the pre-1.4 architecture.References: #6304
Fixed regression where an attribute that is mapped to a
synonym()
could not be used in column loader options such asload_only()
.References: #6272
sql¶
Fixed regression where an empty in statement on a tuple would result in an error when compiled with the option
literal_binds=True
.References: #6290
postgresql¶
Fixed an argument error in the default and PostgreSQL compilers that would interfere with an UPDATE..FROM or DELETE..FROM..USING statement that was then SELECTed from as a CTE.
References: #6303
1.4.8¶
Released: April 15, 2021orm¶
Fixed a cache leak involving the
with_expression()
loader option, where the given SQL expression would not be correctly considered as part of the cache key.Additionally, fixed regression involving the corresponding
query_expression()
feature. While the bug technically exists in 1.3 as well, it was not exposed until 1.4. The «default expr» value ofnull()
would be rendered when not needed, and additionally was also not adapted correctly when the ORM rewrites statements such as when using joined eager loading. The fix ensures «singleton» expressions likeNULL
andtrue
aren’t «adapted» to refer to columns in ORM statements, and additionally ensures that aquery_expression()
with no default expression doesn’t render in the statement if awith_expression()
isn’t used.References: #6259
Fixed issue in the new feature of
Session.refresh()
introduced by #1763 where eagerly loaded relationships are also refreshed, where thelazy="raise"
andlazy="raise_on_sql"
loader strategies would interfere with theimmediateload()
loader strategy, thus breaking the feature for relationships that were loaded withselectinload()
,subqueryload()
as well.References: #6252
engine¶
The
Dialect.has_table()
method now raises an informative exception if a non-Connection is passed to it, as this incorrect behavior seems to be common. This method is not intended for external use outside of a dialect. Please use theInspector.has_table()
method or for cross-compatibility with older SQLAlchemy versions, theEngine.has_table()
method.
sql¶
The tuple returned by
CursorResult.inserted_primary_key
is now aRow
object with a named tuple interface on top of the existing tuple interface.References: #3314
Fixed regression where the
BindParameter
object would not properly render for an IN expression (i.e. using the «post compile» feature in 1.4) if the object were copied from either an internal cloning operation, or from a pickle operation, and the parameter name contained spaces or other special characters.References: #6249
Fixed regression where the introduction of the INSERT syntax «INSERT… VALUES (DEFAULT)» was not supported on some backends that do however support «INSERT..DEFAULT VALUES», including SQLite. The two syntaxes are now each individually supported or non-supported for each dialect, for example MySQL supports «VALUES (DEFAULT)» but not «DEFAULT VALUES». Support for Oracle has also been enabled.
References: #6254
mypy¶
Updated Mypy plugin to only use the public plugin interface of the semantic analyzer.
Revised the fix for
OrderingList
from version 1.4.7 which was testing against the incorrect API.References: #6205
asyncio¶
Fix typo that prevented setting the
bind
attribute of anAsyncSession
to the correct value.References: #6220
mssql¶
Fixed an additional regression in the same area as that of #6173, #6184, where using a value of 0 for OFFSET in conjunction with LIMIT with SQL Server would create a statement using «TOP», as was the behavior in 1.3, however due to caching would then fail to respond accordingly to other values of OFFSET. If the «0» wasn’t first, then it would be fine. For the fix, the «TOP» syntax is now only emitted if the OFFSET value is omitted entirely, that is,
Select.offset()
is not used. Note that this change now requires that if the «with_ties» or «percent» modifiers are used, the statement can’t specify an OFFSET of zero, it now needs to be omitted entirely.References: #6265
1.4.7¶
Released: April 9, 2021orm¶
Fixed regression where the
subqueryload()
loader strategy would fail to correctly accommodate sub-options, such as adefer()
option on a column, if the «path» of the subqueryload were more than one level deep.References: #6221
Fixed regression where the
merge_frozen_result()
function relied upon by the dogpile.caching example was not included in tests and began failing due to incorrect internal arguments.References: #6211
Fixed critical regression where the
Session
could fail to «autobegin» a new transaction when a flush occurred without an existing transaction in place, implicitly placing theSession
into legacy autocommit mode which commit the transaction. TheSession
now has a check that will prevent this condition from occurring, in addition to repairing the flush issue.Additionally, scaled back part of the change made as part of #5226 which can run autoflush during an unexpire operation, to not actually do this in the case of a
Session
using legacySession.autocommit
mode, as this incurs a commit within a refresh operation.References: #6233
Fixed regression where the ORM compilation scheme would assume the function name of a hybrid property would be the same as the attribute name in such a way that an
AttributeError
would be raised, when it would attempt to determine the correct name for each element in a result tuple. A similar issue exists in 1.3 but only impacts the names of tuple rows. The fix here adds a check that the hybrid’s function name is actually present in the__dict__
of the class or its superclasses before assigning this name; otherwise, the hybrid is considered to be «unnamed» and ORM result tuples will use the naming scheme of the underlying expression.References: #6215
Fixed critical regression caused by the new feature added as part of #1763, eager loaders are invoked on unexpire operations. The new feature makes use of the «immediateload» eager loader strategy as a substitute for a collection loading strategy, which unlike the other «post-load» strategies was not accommodating for recursive invocations between mutually-dependent relationships, leading to recursion overflow errors.
References: #6232
engine¶
Fixed up the behavior of the
Row
object when dictionary access is used upon it, meaning converting to a dict viadict(row)
or accessing members using strings or other objects i.e.row["some_key"]
works as it would with a dictionary, rather than raisingTypeError
as would be the case with a tuple, whether or not the C extensions are in place. This was originally supposed to emit a 2.0 deprecation warning for the «non-future» case usingLegacyRow
, and was to raiseTypeError
for the «future»Row
class. However, the C version ofRow
was failing to raise thisTypeError
, and to complicate matters, theSession.execute()
method now returnsRow
in all cases to maintain consistency with the ORM result case, so users who didn’t have C extensions installed would see different behavior in this one case for existing pre-1.4 style code.Therefore, in order to soften the overall upgrade scheme as most users have not been exposed to the more strict behavior of
Row
up through 1.4.6,LegacyRow
andRow
both provide for string-key access as well as support fordict(row)
, in all cases emitting the 2.0 deprecation warning whenSQLALCHEMY_WARN_20
is enabled. TheRow
object still uses tuple-like behavior for__contains__
, which is probably the only noticeable behavioral change compared toLegacyRow
, other than the removal of dictionary-style methodsvalues()
anditems()
.References: #6218
sql¶
Enhanced the «expanding» feature used for
ColumnOperators.in_()
operations to infer the type of expression from the right hand list of elements, if the left hand side does not have any explicit type set up. This allows the expression to support stringification among other things. In 1.3, «expanding» was not automatically used forColumnOperators.in_()
expressions, so in that sense this change fixes a behavioral regression.References: #6222
Fixed the «stringify» compiler to support a basic stringification of a «multirow» INSERT statement, i.e. one with multiple tuples following the VALUES keyword.
schema¶
Fixed regression where usage of a token in the
Connection.execution_options.schema_translate_map
dictionary which contained special characters such as braces would fail to be substituted properly. Use of square bracket characters[]
is now explicitly disallowed as these are used as a delimiter character in the current implementation.References: #6216
mypy¶
Fixed issue in Mypy plugin where the plugin wasn’t inferring the correct type for columns of subclasses that don’t directly descend from
TypeEngine
, in particular that ofTypeDecorator
andUserDefinedType
.
tests¶
Added a new flag to
DefaultDialect
calledsupports_schemas
; third party dialects may set this flag toFalse
to disable SQLAlchemy’s schema-level tests when running the test suite for a third party dialect.
1.4.6¶
Released: April 6, 2021orm¶
Fixed regression where a deprecated form of
Query.join()
were used, passing a series of entities to join from without any ON clause in a singleQuery.join()
call, would fail to function correctly.References: #6203
Fixed critical regression where the
Query.yield_per()
method in the ORM would set up the internalResult
to yield chunks at a time, however made use of the newResult.unique()
method which uniques across the entire result. This would lead to lost rows since the ORM is usingid(obj)
as the uniquing function, which leads to repeated identifiers for new objects as already-seen objects are garbage collected. 1.3’s behavior here was to «unique» across each chunk, which does not actually produce «uniqued» results when results are yielded in chunks. As theQuery.yield_per()
method is already explicitly disallowed when joined eager loading is in place, which is the primary rationale for the «uniquing» feature, the «uniquing» feature is now turned off entirely whenQuery.yield_per()
is used.This regression only applies to the legacy
Query
object; when using 2.0 style execution, «uniquing» is not automatically applied. To prevent the issue from arising from explicit use ofResult.unique()
, an error is now raised if rows are fetched from a «uniqued» ORM-levelResult
if any yield per API is also in use, as the purpose ofyield_per
is to allow for arbitrarily large numbers of rows, which cannot be uniqued in memory without growing the number of entries to fit the complete result size.References: #6206
sql¶
Fixed further regressions in the same area as that of #6173 released in 1.4.5, where a «postcompile» parameter, again most typically those used for LIMIT/OFFSET rendering in Oracle and SQL Server, would fail to be processed correctly if the same parameter rendered in multiple places in the statement.
References: #6202
Executing a
Subquery
usingConnection.execute()
is deprecated and will emit a deprecation warning; this use case was an oversight that should have been removed from 1.4. The operation will now execute the underlyingSelect
object directly for backwards compatibility. Similarly, theCTE
class is also not appropriate for execution. In 1.3, attempting to execute a CTE would result in an invalid «blank» SQL statement being executed; since this use case was not working it now raisesObjectNotExecutableError
. Previously, 1.4 was attempting to execute the CTE as a statement however it was working only erratically.References: #6204
schema¶
The
Table
object now raises an informative error message if it is instantiated without passing at least theTable.name
andTable.metadata
arguments positionally. Previously, if these were passed as keyword arguments, the object would silently fail to initialize correctly.This change is also backported to: 1.3.25
References: #6135
mypy¶
Applied a series of refactorings and fixes to accommodate for Mypy «incremental» mode across multiple files, which previously was not taken into account. In this mode the Mypy plugin has to accommodate Python datatypes expressed in other files coming in with less information than they have on a direct run.
Additionally, a new decorator
declarative_mixin()
is added, which is necessary for the Mypy plugin to be able to definifitely identify a Declarative mixin class that is otherwise not used inside a particular Python file.References: #6147
Fixed issue where the Mypy plugin would fail to interpret the «collection_class» of a relationship if it were a callable and not a class. Also improved type matching and error reporting for collection-oriented relationships.
References: #6205
asyncio¶
Added accessors
.sqlstate
and synonym.pgcode
to the.orig
attribute of the SQLAlchemy exception class raised by the asyncpg DBAPI adapter, that is, the intermediary exception object that wraps on top of that raised by the asyncpg library itself, but below the level of the SQLAlchemy dialect.References: #6199
1.4.5¶
Released: April 2, 2021orm¶
Fixed regression where the
joinedload()
loader strategy would not successfully joinedload to a mapper that is mapper against aCTE
construct.References: #6172
Scaled back the warning message added in #5171 to not warn for overlapping columns in an inheritance scenario where a particular relationship is local to a subclass and therefore does not represent an overlap.
References: #6171
sql¶
Fixed bug in new
FunctionElement.render_derived()
feature where column names rendered out explicitly in the alias SQL would not have proper quoting applied for case sensitive names and other non-alphanumeric names.References: #6183
Fixed regression where use of the
Operators.in_()
method with aSelect
object against a non-table-bound column would produce anAttributeError
, or more generally using aScalarSelect
that has no datatype in a binary expression would produce invalid state.References: #6181
Added a new flag to the
Dialect
class calledDialect.supports_statement_cache
. This flag now needs to be present directly on a dialect class in order for SQLAlchemy’s query cache to take effect for that dialect. The rationale is based on discovered issues such as #6173 revealing that dialects which hardcode literal values from the compiled statement, often the numerical parameters used for LIMIT / OFFSET, will not be compatible with caching until these dialects are revised to use the parameters present in the statement only. For third party dialects where this flag is not applied, the SQL logging will show the message «dialect does not support caching», indicating the dialect should seek to apply this flag once they have verified that no per-statement literal values are being rendered within the compilation phase.References: #6184
schema¶
Introduce a new parameter
Enum.omit_aliases
inEnum
type allow filtering aliases when using a pep435 Enum. Previous versions of SQLAlchemy kept aliases in all cases, creating database enum type with additional states, meaning that they were treated as different values in the db. For backward compatibility this flag defaults toFalse
in the 1.4 series, but will be switched toTrue
in a future version. A deprecation warning is raise if this flag is not specified and the passed enum contains aliases.References: #6146
mypy¶
Fixed issue in mypy plugin where newly added support for
as_declarative()
needed to more fully add theDeclarativeMeta
class to the mypy interpreter’s state so that it does not result in a name not found error; additionally improves how global names are setup for the plugin including theMapped
name.References: #sqlalchemy/sqlalchemy2-stubs/#14
asyncio¶
Fixed issue where the asyncio extension could not be loaded if running Python 3.6 with the backport library of
contextvars
installed.References: #6166
postgresql¶
Fixed regression caused by #6023 where the PostgreSQL cast operator applied to elements within an
ARRAY
when using psycopg2 would fail to use the correct type in the case that the datatype were also embedded within an instance of theVariant
adapter.Additionally, repairs support for the correct CREATE TYPE to be emitted when using a
Variant(ARRAY(some_schema_type))
.This change is also backported to: 1.3.25
References: #6182
Fixed typo in the fix for #6099 released in 1.4.4 that completely prevented this change from working correctly, i.e. the error message did not match what was actually emitted by pg8000.
References: #6099
Fixed issue where the PostgreSQL
PGInspector
, when generated against anEngine
, would fail for.get_enums()
,.get_view_names()
,.get_foreign_table_names()
and.get_table_oid()
when used against a «future» style engine and not the connection directly.References: #6170
mysql¶
Fixed regression in the MySQL dialect where the reflection query used to detect if a table exists would fail on very old MySQL 5.0 and 5.1 versions.
References: #6163
mssql¶
Fixed a regression in MSSQL 2012+ that prevented the order by clause to be rendered when
offset=0
is used in a subquery.References: #6163
oracle¶
Fixed critical regression where the Oracle compiler would not maintain the correct parameter values in the LIMIT/OFFSET for a select due to a caching issue.
References: #6173
1.4.4¶
Released: March 30, 2021orm¶
Fixed critical issue in the new
PropComparator.and_()
feature where loader strategies that emit secondary SELECT statements such asselectinload()
andlazyload()
would fail to accommodate for bound parameters in the user-defined criteria in terms of the current statement being executed, as opposed to the cached statement, causing stale bound values to be used.This also adds a warning for the case where an object that uses
lazyload()
in conjunction withPropComparator.and_()
is attempted to be serialized; the loader criteria cannot reliably be serialized and deserialized and eager loading should be used for this case.References: #6139
Fixed missing method
Session.get()
from theScopedSession
interface.References: #6144
engine¶
Modified the context manager used by
Transaction
so that an «already detached» warning is not emitted by the ending of the context manager itself, if the transaction were already manually rolled back inside the block. This applies to regular transactions, savepoint transactions, and legacy «marker» transactions. A warning is still emitted if the.rollback()
method is called explicitly more than once.References: #6155
Repair wrong arguments to exception handling method in CursorResult.
References: #6138
postgresql¶
Fixed issue in PostgreSQL reflection where a column expressing «NOT NULL» will supersede the nullability of a corresponding domain.
This change is also backported to: 1.3.24
References: #6161
Modified the
is_disconnect()
handler for the pg8000 dialect, which now accommodates for a newInterfaceError
emitted by pg8000 1.19.0. Pull request courtesy Hamdi Burak Usul.References: #6099
misc¶
Adjusted the usage of the
importlib_metadata
library for loading setuptools entrypoints in order to accommodate for some deprecation changes.
1.4.3¶
Released: March 25, 2021orm¶
Fixed a bug where python 2.7.5 (default on CentOS 7) wasn’t able to import sqlalchemy, because on this version of Python
exec "statement"
andexec("statement")
do not behave the same way. The compatibilityexec_()
function was used instead.References: #6069
Fixed bug where ORM queries using a correlated subquery in conjunction with
column_property()
would fail to correlate correctly to an enclosing subquery or to a CTE whenSelect.correlate_except()
were used in the property to control correlation, in cases where the subquery contained the same selectables as ones within the correlated subquery that were intended to not be correlated.References: #6060
Fixed bug where combinations of the new «relationship with criteria» feature could fail in conjunction with features that make use of the new «lambda SQL» feature, including loader strategies such as selectinload and lazyload, for more complicated scenarios such as polymorphic loading.
References: #6131
Repaired support so that the
ClauseElement.params()
method can work correctly with aSelect
object that includes joins across ORM relationship structures, which is a new feature in 1.4.References: #6124
Fixed issue where a «removed in 2.0» warning were generated internally by the relationship loader mechanics.
References: #6115
orm declarative¶
engine¶
Restored the
ResultProxy
name back to thesqlalchemy.engine
namespace. This name refers to theLegacyCursorResult
object.References: #6119
schema¶
Adjusted the logic that emits DROP statements for
Sequence
objects among the dropping of multiple tables, such that allSequence
objects are dropped after all tables, even if the givenSequence
is related only to aTable
object and not directly to the overallMetaData
object. The use case supports the sameSequence
being associated with more than oneTable
at a time.This change is also backported to: 1.3.24
References: #6071
mypy¶
Added support for the Mypy extension to correctly interpret a declarative base class that’s generated using the
as_declarative()
function as well as theregistry.as_declarative_base()
method.Fixed bug in Mypy plugin where the Python type detection for the
Boolean
column type would produce an exception; additionally implemented support forEnum
, including detection of a string-based enum vs. use of Pythonenum.Enum
.References: #6109
postgresql¶
Adjusted the psycopg2 dialect to emit an explicit PostgreSQL-style cast for bound parameters that contain ARRAY elements. This allows the full range of datatypes to function correctly within arrays. The asyncpg dialect already generated these internal casts in the final statement. This also includes support for array slice updates as well as the PostgreSQL-specific
ARRAY.contains()
method.This change is also backported to: 1.3.24
References: #6023
Fixed reflection of identity columns in tables with mixed case names in PostgreSQL.
References: #6129
sqlite¶
Added support for the aiosqlite database driver for use with the SQLAlchemy asyncio extension.
См.также
References: #5920
Repaired the
pysqlcipher
dialect to connect correctly which had regressed in 1.4, and added test + CI support to maintain the driver in working condition. The dialect now imports thesqlcipher3
module for Python 3 by default before falling back topysqlcipher3
which is documented as now being unmaintained.См.также
References: #5848
1.4.2¶
Released: March 19, 2021orm¶
Added support for the
declared_attr
object to work in the context of dataclass fields.References: #6100
Fixed issue in new ORM dataclasses functionality where dataclass fields on an abstract base or mixin that contained column or other mapping constructs would not be mapped if they also included a «default» key within the dataclasses.field() object.
References: #6093
Fixed regression where the
Query.selectable
accessor, which is a synonym forQuery.__clause_element__()
, got removed, it’s now restored.References: #6088
Fixed regression where use of an unnamed SQL expression such as a SQL function would raise a column targeting error if the query itself were using joinedload for an entity and was also being wrapped in a subquery by the joinedload eager loading process.
References: #6086
Fixed regression where the
Query.filter_by()
method would fail to locate the correct source entity if theQuery.join()
method had been used targeting an entity without any kind of ON clause.References: #6092
Fixed regression where the SQL compilation of a
Function
would not work correctly if the object had been «annotated», which is an internal memoization process used mostly by the ORM. In particular it could affect ORM lazy loads which make greater use of this feature in 1.4.References: #6095
Fixed regression where the
ConcreteBase
would fail to map at all when a mapped column name overlapped with the discriminator column name, producing an assertion error. The use case here did not function correctly in 1.3 as the polymorphic union would produce a query that ignored the discriminator column entirely, while emitting duplicate column warnings. As 1.4’s architecture cannot easily reproduce this essentially broken behavior of 1.3 at theselect()
level right now, the use case now raises an informative error message instructing the user to use the.ConcreteBase._concrete_discriminator_name
attribute to resolve the conflict. To assist with this configuration,.ConcreteBase._concrete_discriminator_name
may be placed on the base class only where it will be automatically used by subclasses; previously this was not the case.References: #6090
engine¶
Restored top level import for
sqlalchemy.engine.reflection
. This ensures that the baseInspector
class is properly registered so thatinspect()
works for third party dialects that don’t otherwise import this package.
sql¶
Fixed issue where using a
func
that includes dotted packagenames would fail to be cacheable by the SQL caching system due to a Python list of names that needed to be a tuple.References: #6101
Fixed regression in the
case()
construct, where the «dictionary» form of argument specification failed to work correctly if it were passed positionally, rather than as a «whens» keyword argument.References: #6097
mypy¶
Fixed issue in MyPy extension which crashed on detecting the type of a
Column
if the type were given with a module prefix likesa.Integer()
.References: #sqlalchemy/sqlalchemy2-stubs/2
postgresql¶
Rename the column name used by a reflection query that used a reserved word in some postgresql compatible databases.
References: #6982
1.4.1¶
Released: March 17, 2021orm¶
Fixed regression where producing a Core expression construct such as
select()
using ORM entities would eagerly configure the mappers, in an effort to maintain compatibility with theQuery
object which necessarily does this to support many backref-related legacy cases. However, coreselect()
constructs are also used in mapper configurations and such, and to that degree this eager configuration is more of an inconvenience, so eager configure has been disabled for theselect()
and other Core constructs in the absence of ORM loading types of functions such asLoad
.The change maintains the behavior of
Query
so that backwards compatibility is maintained. However, when using aselect()
in conjunction with ORM entities, a «backref» that isn’t explicitly placed on one of the classes until mapper configure time won’t be available unlessconfigure_mappers()
or the newerconfigure()
has been called elsewhere. Prefer usingrelationship.back_populates
for more explicit relationship configuration which does not have the eager configure requirement.References: #6066
Fixed a critical regression in the relationship lazy loader where the SQL criteria used to fetch a related many-to-one object could go stale in relation to other memoized structures within the loader if the mapper had configuration changes, such as can occur when mappers are late configured or configured on demand, producing a comparison to None and returning no object. Huge thanks to Alan Hamlett for their help tracking this down late into the night.
References: #6055
Fixed regression where the
Query.exists()
method would fail to create an expression if the entity list of theQuery
were an arbitrary SQL column expression.References: #6076
Fixed regression where calling upon
Query.count()
in conjunction with a loader option such asjoinedload()
would fail to ignore the loader option. This is a behavior that has always been very specific to theQuery.count()
method; an error is normally raised if a givenQuery
has options that don’t apply to what it is returning.References: #6052
Fixed regression in
Session.identity_key()
, including that the method and related methods were not covered by any unit test as well as that the method contained a typo preventing it from functioning correctly.References: #6067
orm declarative¶
Fixed bug where user-mapped classes that contained an attribute named «registry» would cause conflicts with the new registry-based mapping system when using
DeclarativeMeta
. While the attribute remains something that can be set explicitly on a declarative base to be consumed by the metaclass, once located it is placed under a private class variable so it does not conflict with future subclasses that use the same name for other purposes.References: #6054
engine¶
The Python
namedtuple()
has the behavior such that the namescount
andindex
will be served as tuple values if the named tuple includes those names; if they are absent, then their behavior as methods ofcollections.abc.Sequence
is maintained. Therefore theRow
andLegacyRow
classes have been fixed so that they work in this same way, maintaining the expected behavior for database rows that have columns named «index» or «count».References: #6074
mssql¶
Fixed regression where a new setinputsizes() API that’s available for pyodbc was enabled, which is apparently incompatible with pyodbc’s fast_executemany() mode in the absence of more accurate typing information, which as of yet is not fully implemented or tested. The pyodbc dialect and connector has been modified so that setinputsizes() is not used at all unless the parameter
use_setinputsizes
is passed to the dialect, e.g. viacreate_engine()
, at which point its behavior can be customized using theDialectEvents.do_setinputsizes()
hook.См.также
mssql_pyodbc_setinputsizes
References: #6058
misc¶
Added back
items
andvalues
toColumnCollection
class. The regression was introduced while adding support for duplicate columns in from clauses and selectable in ticket #4753.References: #6068
1.4.0¶
Released: March 15, 2021orm¶
Removed very old warning that states that passive_deletes is not intended for many-to-one relationships. While it is likely that in many cases placing this parameter on a many-to-one relationship is not what was intended, there are use cases where delete cascade may want to be disallowed following from such a relationship.
This change is also backported to: 1.3.24
References: #5983
Fixed issue where the process of joining two tables could fail if one of the tables had an unrelated, unresolvable foreign key constraint which would raise
NoReferenceError
within the join process, which nonetheless could be bypassed to allow the join to complete. The logic which tested the exception for significance within the process would make assumptions about the construct which would fail.This change is also backported to: 1.3.24
References: #5952
Fixed issue where the
MutableComposite
construct could be placed into an invalid state when the parent object was already loaded, and then covered by a subsequent query, due to the composite properties“ refresh handler replacing the object with a new one not handled by the mutable extension.This change is also backported to: 1.3.24
References: #6001
Fixed regression where the
relationship.query_class
parameter stopped being functional for «dynamic» relationships. TheAppenderQuery
remains dependent on the legacyQuery
class; users are encouraged to migrate from the use of «dynamic» relationships to usingwith_parent()
instead.References: #5981
Fixed regression where
Query.join()
would produce no effect if the query itself as well as the join target were against aTable
object, rather than a mapped class. This was part of a more systemic issue where the legacy ORM query compiler would not be correctly used from aQuery
if the statement produced had not ORM entities present within it.References: #6003
The API for
AsyncSession.delete()
is now an awaitable; this method cascades along relationships which must be loaded in a similar manner as theAsyncSession.merge()
method.References: #5998
The unit of work process now turns off all «lazy=“raise“» behavior altogether when a flush is proceeding. While there are areas where the UOW is sometimes loading things that aren’t ultimately needed, the lazy=»raise» strategy is not helpful here as the user often does not have much control or visibility into the flush process.
References: #5984
engine¶
Fixed bug where the «schema_translate_map» feature failed to be taken into account for the use case of direct execution of
DefaultGenerator
objects such as sequences, which included the case where they were «pre-executed» in order to generate primary key values when implicit_returning was disabled.This change is also backported to: 1.3.24
References: #5929
Improved engine logging to note ROLLBACK and COMMIT which is logged while the DBAPI driver is in AUTOCOMMIT mode. These ROLLBACK/COMMIT are library level and do not have any effect when AUTOCOMMIT is in effect, however it’s still worthwhile to log as these indicate where SQLAlchemy sees the «transaction» demarcation.
References: #6002
Fixed a regression where the «reset agent» of the connection pool wasn’t really being utilized by the
Connection
when it were closed, and also leading to a double-rollback scenario that was somewhat wasteful. The newer architecture of the engine has been updated so that the connection pool «reset-on-return» logic will be skipped when theConnection
explicitly closes out the transaction before returning the pool to the connection.References: #6004
sql¶
Altered the compilation for the
CTE
construct so that a string is returned representing the inner SELECT statement if theCTE
is stringified directly, outside of the context of an enclosing SELECT; This is the same behavior ofFromClause.alias()
andSelect.subquery()
. Previously, a blank string would be returned as the CTE is normally placed above a SELECT after that SELECT has been generated, which is generally misleading when debugging.Fixed bug where the «percent escaping» feature that occurs with dialects that use the «format» or «pyformat» bound parameter styles was not enabled for the
Operators.op()
andcustom_op
constructs, for custom operators that use percent signs. The percent sign will now be automatically doubled based on the paramstyle as necessary.References: #6016
Fixed regression where the «unsupported compilation error» for unknown datatypes would fail to raise correctly.
References: #5979
Fixed regression where usage of the standalone
distinct()
used in the form of being directly SELECTed would fail to be locatable in the result set by column identity, which is how the ORM locates columns. While standalonedistinct()
is not oriented towards being directly SELECTed (useselect.distinct()
for a regularSELECT DISTINCT..
) , it was usable to a limited extent in this way previously (but wouldn’t work in subqueries, for example). The column targeting for unary expressions such as «DISTINCT <col>» has been improved so that this case works again, and an additional improvement has been made so that usage of this form in a subquery at least generates valid SQL which was not the case previously.The change additionally enhances the ability to target elements in
row._mapping
based on SQL expression objects in ORM-enabled SELECT statements, including whether the statement was invoked byconnection.execute()
orsession.execute()
.References: #6008
schema¶
Fixed issue where the CHECK constraint generated by
Boolean
orEnum
would fail to render the naming convention correctly after the first compilation, due to an unintended change of state within the name given to the constraint. This issue was first introduced in 0.9 in the fix for issue #3067, and the fix revises the approach taken at that time which appears to have been more involved than what was needed.This change is also backported to: 1.3.24
References: #6007
Repaired / implemented support for primary key constraint naming conventions that use column names/keys/etc as part of the convention. In particular, this includes that the
PrimaryKeyConstraint
object that’s automatically associated with aTable
will update its name as new primary keyColumn
objects are added to the table and then to the constraint. Internal failure modes related to this constraint construction process including no columns present, no name present or blank name present are now accommodated.This change is also backported to: 1.3.24
References: #5919
Deprecated all schema-level
.copy()
methods and renamed to_copy()
. These are not standard Python «copy()» methods as they typically rely upon being instantiated within particular contexts which are passed to the method as optional keyword arguments. TheTable.tometadata()
method is the public API that provides copying forTable
objects.References: #5953
mypy¶
Rudimentary and experimental support for Mypy has been added in the form of a new plugin, which itself depends on new typing stubs for SQLAlchemy. The plugin allows declarative mappings in their standard form to both be compatible with Mypy as well as to provide typing support for mapped classes and instances.
References: #4609
postgresql¶
Added an
asyncio.Lock()
within SQLAlchemy’s emulated DBAPI cursor, local to the connection, for the asyncpg and aiomysql dialects for the scope of thecursor.execute()
andcursor.executemany()
methods. The rationale is to prevent failures and corruption for the case where the connection is used in multiple awaitables at once.While this use case can also occur with threaded code and non-asyncio dialects, we anticipate this kind of use will be more common under asyncio, as the asyncio API is encouraging of such use. It’s definitely better to use a distinct connection per concurrent awaitable however as concurrency will not be achieved otherwise.
For the asyncpg dialect, this is so that the space between the call to
prepare()
andfetch()
is prevented from allowing concurrent executions on the connection from causing interface error exceptions, as well as preventing race conditions when starting a new transaction. Other PostgreSQL DBAPIs are threadsafe at the connection level so this intends to provide a similar behavior, outside the realm of server side cursors.For the aiomysql dialect, the mutex will provide safety such that the statement execution and the result set fetch, which are two distinct steps at the connection level, won’t get corrupted by concurrent executions on the same connection.
References: #5967
Fixed issue where using
aggregate_order_by
would return ARRAY(NullType) under certain conditions, interfering with the ability of the result object to return data correctly.This change is also backported to: 1.3.24
References: #5989
mssql¶
Fix a reflection error for MSSQL 2005 introduced by the reflection of filtered indexes.
References: #5919
misc¶
Add new parameter
AutomapBase.prepare.reflection_options
to allow passing ofMetaData.reflect()
options likeonly
or dialect-specific reflection options likeoracle_resolve_synonyms
.References: #5942
The
sqlalchemy.ext.mutable
extension now tracks the «parents» collection using theInstanceState
associated with objects, rather than the object itself. The latter approach required that the object be hashable so that it can be inside of aWeakKeyDictionary
, which goes against the behavioral contract of the ORM overall which is that ORM mapped objects do not need to provide any particular kind of__hash__()
method and that unhashable objects are supported.References: #6020
1.4.0b3¶
Released: February 15, 2021orm¶
The ORM used in 2.0 style can now return ORM objects from the rows returned by an UPDATE..RETURNING or INSERT..RETURNING statement, by supplying the construct to
Select.from_statement()
in an ORM context.Fixed issue in new 1.4/2.0 style ORM queries where a statement-level label style would not be preserved in the keys used by result rows; this has been applied to all combinations of Core/ORM columns / session vs. connection etc. so that the linkage from statement to result row is the same in all cases. As part of this change, the labeling of column expressions in rows has been improved to retain the original name of the ORM attribute even if used in a subquery.
References: #5933
engine¶
Continued with the improvement made as part of #5653 to further support bound parameter names, including those generated against column names, for names that include colons, parenthesis, and question marks, as well as improved test support, so that bound parameter names even if they are auto-derived from column names should have no problem including for parenthesis in psycopg2’s «pyformat» style.
As part of this change, the format used by the asyncpg DBAPI adapter (which is local to SQLAlchemy’s asyncpg dialect) has been changed from using «qmark» paramstyle to «format», as there is a standard and internally supported SQL string escaping style for names that use percent signs with «format» style (i.e. to double percent signs), as opposed to names that use question marks with «qmark» style (where an escaping system is not defined by pep-249 or Python).
References: #5941
sql¶
Enhance
set_
keyword ofOnConflictDoUpdate
to accept aColumnCollection
, such as the.c.
collection from aSelectable
, or the.excluded
contextual object.References: #5939
Fixed bug where the «cartesian product» assertion was not correctly accommodating for joins between tables that relied upon the use of LATERAL to connect from a subquery to another subquery in the enclosing context.
References: #5924
Fixed 1.4 regression where the
Function.in_()
method was not covered by tests and failed to function properly in all cases.References: #5934
Fixed regression where use of an arbitrary iterable with the
select()
function was not working, outside of plain lists. The forwards/backwards compatibility logic here now checks for a wider range of incoming «iterable» types including that a.c
collection from a selectable can be passed directly. Pull request compliments of Oliver Rice.References: #5935
1.4.0b2¶
Released: February 3, 2021general¶
Fixed a SQLite source file that had non-ascii characters inside of its docstring without a source encoding, introduced within the «INSERT..ON CONFLICT» feature, which would cause failures under Python 2.
platform¶
Adjusted some elements related to internal class production at import time which added significant latency to the time spent to import the library vs. that of 1.3. The time is now about 20-30% slower than 1.3 instead of 200%.
References: #5681
orm¶
Added
ORMExecuteState.bind_mapper
andORMExecuteState.all_mappers
accessors toORMExecuteState
event object, so that handlers can respond to the target mapper and/or mapped class or classes involved in an ORM statement execution.Added
AsyncSession.scalar()
,AsyncSession.get()
as well as support forsessionmaker.begin()
to work as an async context manager withAsyncSession
. Also addedAsyncSession.in_transaction()
accessor.Mapper «configuration», which occurs within the
configure_mappers()
function, is now organized to be on a per-registry basis. This allows for example the mappers within a certain declarative base to be configured, but not those of another base that is also present in memory. The goal is to provide a means of reducing application startup time by only running the «configure» process for sets of mappers that are needed. This also adds theregistry.configure()
method that will run configure for the mappers local in a particular registry only.References: #5897
Added a comprehensive check and an informative error message for the case where a mapped class, or a string mapped class name, is passed to
relationship.secondary
. This is an extremely common error which warrants a clear message.Additionally, added a new rule to the class registry resolution such that with regards to the
relationship.secondary
parameter, if a mapped class and its table are of the identical string name, theTable
will be favored when resolving this parameter. In all other cases, the class continues to be favored if a class and table share the identical name.This change is also backported to: 1.3.21
References: #5774
Fixed bug involving the
restore_load_context
option of ORM events such asInstanceEvents.load()
such that the flag would not be carried along to subclasses which were mapped after the event handler were first established.This change is also backported to: 1.3.21
References: #5737
Fixed issue in new
Session
similar to that of theConnection
where the new «autobegin» logic could be tripped into a re-entrant (recursive) state if SQL were executed within theSessionEvents.after_transaction_create()
event hook.References: #5845
Improved the unit of work topological sorting system such that the toplogical sort is now deterministic based on the sorting of the input set, which itself is now sorted at the level of mappers, so that the same inputs of affected mappers should produce the same output every time, among mappers / tables that don’t have any dependency on each other. This further reduces the chance of deadlocks as can be observed in a flush that UPDATEs among multiple, unrelated tables such that row locks are generated.
References: #5735
Fixed regression where the
Bundle.single_entity
flag would take effect for aBundle
even though it were not set. Additionally, this flag is legacy as it only makes sense for theQuery
object and not 2.0 style execution. a deprecation warning is emitted when used with new-style execution.References: #5702
Fixed regression where creating an
aliased
construct against a plain selectable and including a name would raise an assertionerror.References: #5750
Related to the fixes for the lambda criteria system within Core, within the ORM implemented a variety of fixes for the
with_loader_criteria()
feature as well as theSessionEvents.do_orm_execute()
event handler that is often used in conjunction [ticket:5760]:fixed issue where
with_loader_criteria()
function would fail if the given entity or base included non-mapped mixins in its descending class hierarchy [ticket:5766]The
with_loader_criteria()
feature is now unconditionally disabled for the case of ORM «refresh» operations, including loads of deferred or expired column attributes as well as for explicit operations likeSession.refresh()
. These loads are necessarily based on primary key identity where additional WHERE criteria is never appropriate. [ticket:5762]Added new attribute
ORMExecuteState.is_column_load
to indicate that aSessionEvents.do_orm_execute()
handler that a particular operation is a primary-key-directed column attribute load, where additional criteria should not be added. Thewith_loader_criteria()
function as above ignores these in any case now. [ticket:5761]Fixed issue where the
ORMExecuteState.is_relationship_load
attribute would not be set correctly for many lazy loads as well as all selectinloads. The flag is essential in order to test if options should be added to statements or if they would already have been propagated via relationship loads. [ticket:5764]
Fixed 1.4 regression where the use of
Query.having()
in conjunction with queries with internally adapted SQL elements (common in inheritance scenarios) would fail due to an incorrect function call. Pull request courtesy esoh.References: #5781
Fixed an issue where the API to create a custom executable SQL construct using the
sqlalchemy.ext.compiles
extension according to the documentation that’s been up for many years would no longer function if onlyExecutable, ClauseElement
were used as the base classes, additional classes were needed if wanting to useSession.execute()
. This has been resolved so that those extra classes aren’t needed.Fixed ORM unit of work regression where an errant «assert primary_key» statement interferes with primary key generation sequences that don’t actually consider the columns in the table to use a real primary key constraint, instead using
mapper.primary_key
to establish certain columns as «primary».References: #5867
orm declarative¶
Added an alternate resolution scheme to Declarative that will extract the SQLAlchemy column or mapped property from the «metadata» dictionary of a dataclasses.Field object. This allows full declarative mappings to be combined with dataclass fields.
References: #5745
engine¶
Dialect-specific constructs such as
Insert.on_conflict_do_update()
can now stringify in-place without the need to specify an explicit dialect object. The constructs, when called upon forstr()
,print()
, etc. now have internal direction to call upon their appropriate dialect rather than the «default»dialect which doesn’t know how to stringify these. The approach is also adapted to generic schema-level create/drop such asAddConstraint
, which will adapt its stringify dialect to one indicated by the element within it, such as theExcludeConstraint
object.Added new execution option
Connection.execution_options.logging_token
. This option will add an additional per-message token to log messages generated by theConnection
as it executes statements. This token is not part of the logger name itself (that part can be affected using the existingcreate_engine.logging_name
parameter), so is appropriate for ad-hoc connection use without the side effect of creating many new loggers. The option can be set at the level ofConnection
orEngine
.References: #5911
Fixed bug in the 2.0 «future» version of
Engine
where emitting SQL during theEngineEvents.begin()
event hook would cause a re-entrant (recursive) condition due to autobegin, affecting among other things the recipe documented for SQLite to allow for savepoints and serializable isolation support.References: #5845
Adjusted the «setinputsizes» logic relied upon by the cx_Oracle, asyncpg and pg8000 dialects to support a
TypeDecorator
that includes an override theTypeDecorator.get_dbapi_type()
method.Added the «future» keyword to the list of words that are known by the
engine_from_config()
function, so that the values «true» and «false» may be configured as «boolean» values when using a key such assqlalchemy.future = true
orsqlalchemy.future = false
.
sql¶
Implemented support for «table valued functions» along with additional syntaxes supported by PostgreSQL, one of the most commonly requested features. Table valued functions are SQL functions that return lists of values or rows, and are prevalent in PostgreSQL in the area of JSON functions, where the «table value» is commonly referred towards as the «record» datatype. Table valued functions are also supported by Oracle and SQL Server.
Features added include:
the
FunctionElement.table_valued()
modifier that creates a table-like selectable object from a SQL functionA
TableValuedAlias
construct that renders a SQL function as a named tableSupport for PostgreSQL’s special «derived column» syntax that includes column names and sometimes datatypes, such as for the
json_to_recordset
function, using theTableValuedAlias.render_derived()
method.Support for PostgreSQL’s «WITH ORDINALITY» construct using the
FunctionElement.table_valued.with_ordinality
parameterSupport for selection FROM a SQL function as column-valued scalar, a syntax supported by PostgreSQL and Oracle, via the
FunctionElement.column_valued()
methodA way to SELECT a single column from a table-valued expression without using a FROM clause via the
FunctionElement.scalar_table_valued()
method.
См.также
Функции с табличными значениями - in the Самоучитель SQLAlchemy 1.4 / 2.0
References: #3566
Multiple calls to «returning», e.g.
Insert.returning()
, may now be chained to add new columns to the RETURNING clause.References: #5695
Added
Select.outerjoin_from()
method to complementSelect.join_from()
.Adjusted the «literal_binds» feature of
Compiler
to render NULL for a bound parameter that hasNone
as the value, either explicitly passed or omitted. The previous error message «bind parameter without a renderable value» is removed, and a missing orNone
value will now render NULL in all cases. Previously, rendering of NULL was starting to happen for DML statements due to internal refactorings, but was not explicitly part of test coverage, which it now is.While no error is raised, when the context is within that of a column comparison, and the operator is not «IS»/»IS NOT», a warning is emitted that this is not generally useful from a SQL perspective.
References: #5888
Fixed issue in new
Select.join()
method where chaining from the current JOIN wasn’t looking at the right state, causing an expression like «FROM a JOIN b <onclause>, b JOIN c <onclause>» rather than «FROM a JOIN b <onclause> JOIN c <onclause>».References: #5858
Deprecation warnings are emitted under «SQLALCHEMY_WARN_20» mode when passing a plain string to
Session.execute()
.References: #5754
A wide variety of fixes to the «lambda SQL» feature introduced at Использование ламбдас для значительного увеличения скорости создания операторов have been implemented based on user feedback, with an emphasis on its use within the
with_loader_criteria()
feature where it is most prominently used [ticket:5760]:fixed issue where boolean True/False values referred towards in the closure variables of the lambda would cause failures [ticket:5763]
Repaired a non-working detection for Python functions embedded in the lambda that produce bound values; this case is likely not supportable so raises an informative error, where the function should be invoked outside the lambda itself. New documentation has been added to further detail this behavior. [ticket:5770]
The lambda system by default now rejects the use of non-SQL elements within the closure variables of the lambda entirely, where the error suggests the two options of either explicitly ignoring closure variables that are not SQL parameters, or specifying a specific set of values to be considered as part of the cache key based on hash value. This critically prevents the lambda system from assuming that arbitrary objects within the lambda’s closure are appropriate for caching while also refusing to ignore them by default, preventing the case where their state might not be constant and have an impact on the SQL construct produced. The error message is comprehensive and new documentation has been added to further detail this behavior. [ticket:5765]
Fixed support for the edge case where an
in_()
expression against a list of SQL elements, such asliteral()
objects, would fail to be accommodated correctly. [ticket:5768]
An informative error message is now raised for a selected set of DML methods (currently all part of
Insert
constructs) if they are called a second time, which would implicitly cancel out the previous setting. The methods altered include:on_conflict_do_update
,on_conflict_do_nothing
(SQLite),on_conflict_do_update
,on_conflict_do_nothing
(PostgreSQL),on_duplicate_key_update
(MySQL)References: #5169
Fixed issue in new
Values
construct where passing tuples of objects would fall back to per-value type detection rather than making use of theColumn
objects passed directly toValues
that tells SQLAlchemy what the expected type is. This would lead to issues for objects such as enumerations and numpy strings that are not actually necessary since the expected type is given.References: #5785
Fixed issue where a
RemovedIn20Warning
would erroneously emit when the.bind
attribute were accessed internally on objects, particularly when stringifying a SQL construct.References: #5717
Properly render
cycle=False
andorder=False
asNO CYCLE
andNO ORDER
inSequence
andIdentity
objects.References: #5722
Replace
Query.with_labels()
andGenerativeSelect.apply_labels()
with explicit getters and settersGenerativeSelect.get_label_style()
andGenerativeSelect.set_label_style()
to accommodate the three supported label styles:LABEL_STYLE_DISAMBIGUATE_ONLY
,LABEL_STYLE_TABLENAME_PLUS_COL
, andLABEL_STYLE_NONE
.In addition, for Core and «future style» ORM queries,
LABEL_STYLE_DISAMBIGUATE_ONLY
is now the default label style. This style differs from the existing «no labels» style in that labeling is applied in the case of column name conflicts; withLABEL_STYLE_NONE
, a duplicate column name is not accessible via name in any case.For cases where labeling is significant, namely that the
.c
collection of a subquery is able to refer to all columns unambiguously, the behavior ofLABEL_STYLE_DISAMBIGUATE_ONLY
is now sufficient for all SQLAlchemy features across Core and ORM which involve this behavior. Result set rows since SQLAlchemy 1.0 are usually aligned with column constructs positionally.For legacy ORM queries using
Query
, the table-plus-column names labeling style applied byLABEL_STYLE_TABLENAME_PLUS_COL
continues to be used so that existing test suites and logging facilities see no change in behavior by default.References: #4757
schema¶
Added
TypeEngine.as_generic()
to map dialect-specific types, such assqlalchemy.dialects.mysql.INTEGER
, with the «best match» generic SQLAlchemy type, in this caseInteger
. Pull request courtesy Andrew Hannigan.См.также
Отражение с помощью типов, не зависящих от базы данных - example usage
References: #5659
The
DDLEvents.column_reflect()
event may now be applied to aMetaData
object where it will take effect for theTable
objects local to that collection.См.также
DDLEvents.column_reflect()
Автоматизация схем именования столбцов из отраженных таблиц - in the ORM mapping documentation
automap_intercepting_columns - in the Automap documentation
References: #5712
Added parameters
CreateTable.if_not_exists
,CreateIndex.if_not_exists
,DropTable.if_exists
andDropIndex.if_exists
to theCreateTable
,DropTable
,CreateIndex
andDropIndex
constructs which result in «IF NOT EXISTS» / «IF EXISTS» DDL being added to the CREATE/DROP. These phrases are not accepted by all databases and the operation will fail on a database that does not support it as there is no similarly compatible fallback within the scope of a single DDL statement. Pull request courtesy Ramon Williams.References: #2843
Altered the behavior of the
Identity
construct such that when applied to aColumn
, it will automatically imply that the value ofColumn.nullable
should default toFalse
, in a similar manner as when theColumn.primary_key
parameter is set toTrue
. This matches the default behavior of all supporting databases whereIDENTITY
impliesNOT NULL
. The PostgreSQL backend is the only one that supports addingNULL
to anIDENTITY
column, which is here supported by passing aTrue
value for theColumn.nullable
parameter at the same time.References: #5775
asyncio¶
The
AsyncEngine
,AsyncConnection
andAsyncTransaction
objects may be compared using Python==
or!=
, which will compare the two given objects based on the «sync» object they are proxying towards. This is useful as there are cases particularly forAsyncTransaction
where multiple instances ofAsyncTransaction
can be proxying towards the same syncTransaction
, and are actually equivalent. TheAsyncConnection.get_transaction()
method will currently return a new proxyingAsyncTransaction
each time as theAsyncTransaction
is not otherwise statefully associated with its originatingAsyncConnection
.Adjusted the greenlet integration, which provides support for Python asyncio in SQLAlchemy, to accommodate for the handling of Python
contextvars
(introduced in Python 3.7) forgreenlet
versions greater than 0.4.17. Greenlet version 0.4.17 added automatic handling of contextvars in a backwards-incompatible way; we’ve coordinated with the greenlet authors to add a preferred API for this in versions subsequent to 0.4.17 which is now supported by SQLAlchemy’s greenlet integration. For greenlet versions prior to 0.4.17 no behavioral change is needed, version 0.4.17 itself is blocked from the dependencies.References: #5615
Implemented «connection-binding» for
AsyncSession
, the ability to pass anAsyncConnection
to create anAsyncSession
. Previously, this use case was not implemented and would use the associated engine when the connection were passed. This fixes the issue where the «join a session to an external transaction» use case would not work correctly for theAsyncSession
. Additionally, added methodsAsyncConnection.in_transaction()
,AsyncConnection.in_nested_transaction()
,AsyncConnection.get_transaction()
,AsyncConnection.get_nested_transaction()
andAsyncConnection.info
attribute.References: #5811
Fixed bug in asyncio connection pool where
asyncio.TimeoutError
would be raised rather thanTimeoutError
. Also repaired thecreate_engine.pool_timeout
parameter set to zero when using the async engine, which previously would ignore the timeout and block rather than timing out immediately as is the behavior with regularQueuePool
.References: #5827
When using an asyncio engine, the connection pool will now detach and discard a pooled connection that is was not explicitly closed/returned to the pool when its tracking object is garbage collected, emitting a warning that the connection was not properly closed. As this operation occurs during Python gc finalizers, it’s not safe to run any IO operations upon the connection including transaction rollback or connection close as this will often be outside of the event loop.
The
AsyncAdaptedQueue
used by default on async dpapis should instantiate a queue only when it’s first used to avoid binding it to a possibly wrong event loop.References: #5823
The SQLAlchemy async mode now detects and raises an informative error when an non asyncio compatible DBAPI is used. Using a standard
DBAPI
with async SQLAlchemy will cause it to block like any sync call, interrupting the executing asyncio loop.
postgresql¶
Added new parameter
ExcludeConstraint.ops
to theExcludeConstraint
object, to support operator class specification with this constraint. Pull request courtesy Alon Menczer.This change is also backported to: 1.3.21
References: #5604
Added a read/write
.autocommit
attribute to the DBAPI-adaptation layer for the asyncpg dialect. This so that when working with DBAPI-specific schemes that need to use «autocommit» directly with the DBAPI connection, the same.autocommit
attribute which works with both psycopg2 as well as pg8000 is available.Fixed issue where the psycopg2 dialect would silently pass the
use_native_unicode=False
flag without actually having any effect under Python 3, as the psycopg2 DBAPI uses Unicode unconditionally under Python 3. This usage now raises anArgumentError
when used under Python 3. Added test support for Python 2.Enhanced the performance of the asyncpg dialect by caching the asyncpg PreparedStatement objects on a per-connection basis. For a test case that makes use of the same statement on a set of pooled connections this appears to grant a 10-20% speed improvement. The cache size is adjustable and may also be disabled.
См.также
asyncpg_prepared_statement_cache
Fixed regression introduced in 1.3.2 for the PostgreSQL dialect, also copied out to the MySQL dialect’s feature in 1.3.18, where usage of a non
Table
construct such astext()
as the argument toSelect.with_for_update.of
would fail to be accommodated correctly within the PostgreSQL or MySQL compilers.This change is also backported to: 1.3.21
References: #5729
Fixed a small regression where the query for «show standard_conforming_strings» upon initialization would be emitted even if the server version info were detected as less than version 8.2, previously it would only occur for server version 8.2 or greater. The query fails on Amazon Redshift which reports a PG server version older than this value.
References: #5698
Established support for
Column
objects as well as ORM instrumented attributes as keys in theset_
dictionary passed to theInsert.on_conflict_do_update()
andInsert.on_conflict_do_update()
methods, which match to theColumn
objects in the.c
collection of the targetTable
. Previously, only string column names were expected; a column expression would be assumed to be an out-of-table expression that would render fully along with a warning.References: #5722
Fixed bug in asyncpg dialect where a failure during a «commit» or less likely a «rollback» should cancel the entire transaction; it’s no longer possible to emit rollback. Previously the connection would continue to await a rollback that could not succeed as asyncpg would reject it.
References: #5824
mysql¶
Added support for the aiomysql driver when using the asyncio SQLAlchemy extension.
См.также
References: #5747
Fixed issue where reflecting a server default on MariaDB only that contained a decimal point in the value would fail to be reflected correctly, leading towards a reflected table that lacked any server default.
This change is also backported to: 1.3.21
References: #5744
sqlite¶
Implemented INSERT… ON CONFLICT clause for SQLite. Pull request courtesy Ramon Williams.
См.также
sqlite_on_conflict_insert
References: #4010
Use python
re.search()
instead ofre.match()
as the operation used by theColumn.regexp_match()
method when using sqlite. This matches the behavior of regular expressions on other databases as well as that of well-known SQLite plugins.References: #5699
mssql¶
Decimal accuracy and behavior has been improved when extracting floating point and/or decimal values from JSON strings using the
Comparator.as_float()
method, when the numeric value inside of the JSON string has many significant digits; previously, MySQL backends would truncate values with many significant digits and SQL Server backends would raise an exception due to a DECIMAL cast with insufficient significant digits. Both backends now use a FLOAT-compatible approach that does not hardcode significant digits for floating point values. For precision numerics, a new methodComparator.as_numeric()
has been added which accepts arguments for precision and scale, and will return values as PythonDecimal
objects with no floating point conversion assuming the DBAPI supports it (all but pysqlite).References: #5788
oracle¶
Fixed regression which occurred due to #5755 which implemented isolation level support for Oracle. It has been reported that many Oracle accounts don’t actually have permission to query the
v$transaction
view so this feature has been altered to gracefully fallback when it fails upon database connect, where the dialect will assume «READ COMMITTED» is the default isolation level as was the case prior to SQLAlchemy 1.3.21. However, explicit use of theConnection.get_isolation_level()
method must now necessarily raise an exception, as Oracle databases with this restriction explicitly disallow the user from reading the current isolation level.This change is also backported to: 1.3.22
References: #5784
Oracle two-phase transactions at a rudimentary level are now no longer deprecated. After receiving support from cx_Oracle devs we can provide for basic xid + begin/prepare support with some limitations, which will work more fully in an upcoming release of cx_Oracle. Two phase «recovery» is not currently supported.
References: #5884
The Oracle dialect now uses
select sys_context( 'userenv', 'current_schema' ) from dual
to get the default schema name, rather thanSELECT USER FROM DUAL
, to accommodate for changes to the session-local schema name under Oracle.References: #5716
tests¶
Improve documentation and add test for sub-second pool timeouts. Pull request courtesy Jordan Pittier.
References: #5582
misc¶
The internal mechanics of the engine connection routine has been altered such that it’s now guaranteed that a user-defined event handler for the
PoolEvents.connect()
handler, when established usinginsert=True
, will allow an event handler to run that is definitely invoked before any dialect-specific initialization starts up, most notably when it does things like detect default schema name. Previously, this would occur in most cases but not unconditionally. A new example is added to the schema documentation illustrating how to establish the «default schema name» within an on-connect event.Fixed bug where the now-deprecated
autoload
parameter was being called internally within the reflection routines when a related table were reflected.References: #5684
Fixed regression where a connection pool event specified with a keyword, most notably
insert=True
, would be lost when the event were set up. This would prevent startup events that need to fire before dialect-level events from working correctly.References: #5708
Fixed issue where connection pool would not return connections to the pool or otherwise be finalized upon garbage collection under pypy if the checked out connection fell out of scope without being closed. This is a long standing issue due to pypy’s difference in GC behavior that does not call weakref finalizers if they are relative to another object that is also being garbage collected. A strong reference to the related record is now maintained so that the weakref has a strong-referenced «base» to trigger off of.
References: #5842
1.4.0b1¶
Released: November 2, 2020general¶
»python setup.py test» is no longer a test runner, as this is deprecated by Pypa. Please use «tox» with no arguments for a basic test run.
References: #4789
Refactored the internal conventions used to cross-import modules that have mutual dependencies between them, such that the inspected arguments of functions and methods are no longer modified. This allows tools like pylint, Pycharm, other code linters, as well as hypothetical pep-484 implementations added in the future to function correctly as they no longer see missing arguments to function calls. The new approach is also simpler and more performant.
platform¶
The
importlib_metadata
library is used to scan for setuptools entrypoints rather than pkg_resources. as importlib_metadata is a small library that is included as of Python 3.8, the compatibility library is installed as a dependency for Python versions older than 3.8.References: #5400
Installation has been modernized to use setup.cfg for most package metadata.
References: #5404
Dropped support for python 3.4 and 3.5 that has reached EOL. SQLAlchemy 1.4 series requires python 2.7 or 3.6+.
References: #5634
Removed all dialect code related to support for Jython and zxJDBC. Jython has not been supported by SQLAlchemy for many years and it is not expected that the current zxJDBC code is at all functional; for the moment it just takes up space and adds confusion by showing up in documentation. At the moment, it appears that Jython has achieved Python 2.7 support in its releases but not Python 3. If Jython were to be supported again, the form it should take is against the Python 3 version of Jython, and the various zxJDBC stubs for various backends should be implemented as a third party dialect.
References: #5094
orm¶
The ORM can now generate queries previously only available when using
Query
using theselect()
construct directly. A new system by which ORM «plugins» may establish themselves within a CoreSelect
allow the majority of query building logic previously inside ofQuery
to now take place within a compilation-level extension forSelect
. Similar changes have been made for theUpdate
andDelete
constructs as well. The constructs when invoked usingSession.execute()
now do ORM-related work within the method. ForSelect
, theResult
object returned now contains ORM-level entities and results.References: #5159
Added the ability to add arbitrary criteria to the ON clause generated by a relationship attribute in a query, which applies to methods such as
Query.join()
as well as loader options likejoinedload()
. Additionally, a «global» version of the option allows limiting criteria to be applied to particular entities in a query globally.См.также
Добавление критериев к параметрам загрузчика
Добавление глобальных критериев WHERE / ON
with_loader_criteria()
References: #4472
The ORM Declarative system is now unified into the ORM itself, with new import spaces under
sqlalchemy.orm
and new kinds of mappings. Support for decorator-based mappings without using a base class, support for classical style-mapper() calls that have access to the declarative class registry for relationships, and full integration of Declarative with 3rd party class attribute systems likedataclasses
andattrs
is now supported.См.также
Declarative is now integrated into the ORM with new features
Python Dataclasses, attrs Supported w/ Declarative, Imperative Mappings
References: #5508
Eager loaders, such as joined loading, SELECT IN loading, etc., when configured on a mapper or via query options will now be invoked during the refresh on an expired object; in the case of selectinload and subqueryload, since the additional load is for a single object only, the «immediateload» scheme is used in these cases which resembles the single-parent query emitted by lazy loading.
References: #1763
Added support for direct mapping of Python classes that are defined using the Python
dataclasses
decorator. Pull request courtesy Václav Klusák. The new feature integrates into new support at the Declarative level for systems such asdataclasses
andattrs
.См.также
Python Dataclasses, attrs Supported w/ Declarative, Imperative Mappings
Declarative is now integrated into the ORM with new features
References: #5027
Added «raiseload» feature for ORM mapped columns via
defer.raiseload
parameter ondefer()
anddeferred()
. This provides similar behavior for column-expression mapped attributes as theraiseload()
option does for relationship mapped attributes. The change also includes some behavioral changes to deferred columns regarding expiration; see the migration notes for details.См.также
References: #4826
The evaluator that takes place within the ORM bulk update and delete for synchronize_session=»evaluate» now supports the IN and NOT IN operators. Tuple IN is also supported.
References: #1653
Enhanced logic that tracks if relationships will be conflicting with each other when they write to the same column to include simple cases of two relationships that should have a «backref» between them. This means that if two relationships are not viewonly, are not linked with back_populates and are not otherwise in an inheriting sibling/overriding arrangement, and will populate the same foreign key column, a warning is emitted at mapper configuration time warning that a conflict may arise. A new parameter
relationship.overlaps
is added to suit those very rare cases where such an overlapping persistence arrangement may be unavoidable.References: #5171
The ORM bulk update and delete operations, historically available via the
Query.update()
andQuery.delete()
methods as well as via theUpdate
andDelete
constructs for 2.0 style execution, will now automatically accommodate for the additional WHERE criteria needed for a single-table inheritance discriminator in order to limit the statement to rows referring to the specific subtype requested. The newwith_loader_criteria()
construct is also supported for with bulk update/delete operations.Update
relationship.sync_backref
flag in a relationship to make it implicitlyFalse
inviewonly=True
relationships, preventing synchronization events.References: #5237
The condition where a pending object being flushed with an identity that already exists in the identity map has been adjusted to emit a warning, rather than throw a
FlushError
. The rationale is so that the flush will proceed and raise aIntegrityError
instead, in the same way as if the existing object were not present in the identity map already. This helps with schemes that are using theIntegrityError
as a means of catching whether or not a row already exists in the table.References: #4662
A selection of Core and ORM query objects now perform much more of their Python computational tasks within the compile step, rather than at construction time. This is to support an upcoming caching model that will provide for caching of the compiled statement structure based on a cache key that is derived from the statement construct, which itself is expected to be newly constructed in Python code each time it is used. This means that the internal state of these objects may not be the same as it used to be, as well as that some but not all error raise scenarios for various kinds of argument validation will occur within the compilation / execution phase, rather than at statement construction time. See the migration notes linked below for complete details.
The automatic uniquing of rows on the client side is turned off for the new 2.0 style of ORM querying. This improves both clarity and performance. However, uniquing of rows on the client side is generally necessary when using joined eager loading for collections, as there will be duplicates of the primary entity for each element in the collection because a join was used. This uniquing must now be manually enabled and can be achieved using the new
Result.unique()
modifier. To avoid silent failure, the ORM explicitly requires the method be called when the result of an ORM query in 2.0 style makes use of joined load collections. The newerselectinload()
strategy is likely preferable for eager loading of collections in any case.References: #4395
The ORM will now warn when asked to coerce a
select()
construct into a subquery implicitly. This occurs within places such as theQuery.select_entity_from()
andQuery.select_from()
methods as well as within thewith_polymorphic()
function. When aSelectBase
(which is what’s produced byselect()
) orQuery
object is passed directly to these functions and others, the ORM is typically coercing them to be a subquery by calling theSelectBase.alias()
method automatically (which is now superseded by theSelectBase.subquery()
method). See the migration notes linked below for further details.References: #4617
The «KeyedTuple» class returned by
Query
is now replaced with the CoreRow
class, which behaves in the same way as KeyedTuple. In SQLAlchemy 2.0, both Core and ORM will return result rows using the sameRow
object. In the interim, Core uses a backwards-compatibility classLegacyRow
that maintains the former mapping/tuple hybrid behavior used by «RowProxy».References: #4710
The bulk update and delete methods
Query.update()
andQuery.delete()
, as well as their 2.0-style counterparts, now make use of RETURNING when the «fetch» strategy is used in order to fetch the list of affected primary key identites, rather than emitting a separate SELECT, when the backend in use supports RETURNING. Additionally, the «fetch» strategy will in ordinary cases not expire the attributes that have been updated, and will instead apply the updated values directly in the same way that the «evaluate» strategy does, to avoid having to refresh the object. The «evaluate» strategy will also fall back to expiring attributes that were updated to a SQL expression that was unevaluable in Python.Implemented support for the psycopg2
execute_values()
extension within the ORM flush process via the enhancements to Core made in #5401, so that this extension is used both as a strategy to batch INSERT statements together as well as that RETURNING may now be used among multiple parameter sets to retrieve primary key values back in batch. This allows nearly all INSERT statements emitted by the ORM on behalf of PostgreSQL to be submitted in batch and also via theexecute_values()
extension which benches at five times faster than plain executemany() for this particular backend.References: #5263
A query that is against a mapped inheritance subclass which also uses
Query.select_entity_from()
or a similar technique in order to provide an existing subquery to SELECT from, will now raise an error if the given subquery returns entities that do not correspond to the given subclass, that is, they are sibling or superclasses in the same hierarchy. Previously, these would be returned without error. Additionally, if the inheritance mapping is a single-inheritance mapping, the given subquery must apply the appropriate filtering against the polymorphic discriminator column in order to avoid this error; previously, theQuery
would add this criteria to the outside query however this interferes with some kinds of query that return other kinds of entities as well.References: #5122
The internal attribute symbols NO_VALUE and NEVER_SET have been unified, as there was no meaningful difference between these two symbols, other than a few codepaths where they were differentiated in subtle and undocumented ways, these have been fixed.
References: #4696
Fixed bug where a versioning column specified on a mapper against a
select()
construct where the version_id_col itself were against the underlying table would incur additional loads when accessed, even if the value were locally persisted by the flush. The actual fix is a result of the changes in #4617, by fact that aselect()
object no longer has a.c
attribute and therefore does not confuse the mapper into thinking there’s an unknown column value present.References: #4194
An
UnmappedInstanceError
is now raised forInstrumentedAttribute
if an instance is an unmapped object. Prior to this anAttributeError
was raised. Pull request courtesy Ramon Williams.References: #3858
The
Session
object no longer initiates aSessionTransaction
object immediately upon construction or after the previous transaction is closed; instead, «autobegin» logic now initiates the newSessionTransaction
on demand when it is next needed. Rationale includes to remove reference cycles from aSession
that has been closed out, as well as to remove the overhead incurred by the creation ofSessionTransaction
objects that are often discarded immediately. This change affects the behavior of theSessionEvents.after_transaction_create()
hook in that the event will be emitted when theSession
first requires aSessionTransaction
be present, rather than whenever theSession
were created or the previousSessionTransaction
were closed. Interactions with theEngine
and the database itself remain unaffected.References: #5074
Added new entity-targeting capabilities to the ORM query context help with the case where the
Session
is using a bind dictionary against mapped classes, rather than a single bind, and theQuery
is against a Core statement that was ultimately generated from a method such asQuery.subquery()
. First implemented using a deep search, the current approach leverages the unifiedselect()
construct to keep track of the first mapper that is part of the construct.References: #4829
An
ArgumentError
is now raised if both theselectable
andflat
parameters are set to True inwith_polymorphic()
. The selectable name is already aliased and applying flat=True overrides the selectable name with an anonymous name that would’ve previously caused the code to break. Pull request courtesy Ramon Williams.References: #4212
Fixed issue in polymorphic loading internals which would fall back to a more expensive, soon-to-be-deprecated form of result column lookup within certain unexpiration scenarios in conjunction with the use of «with_polymorphic».
References: #4718
An error is raised if any persistence-related «cascade» settings are made on a
relationship()
that also sets up viewonly=True. The «cascade» settings now default to non-persistence related settings only when viewonly is also set. This is the continuation from #4993 where this setting was changed to emit a warning in 1.3.References: #4994
Improved declarative inheritance scanning to not get tripped up when the same base class appears multiple times in the base inheritance list.
References: #4699
Fixed bug in ORM versioning feature where assignment of an explicit version_id for a counter configured against a mapped selectable where version_id_col is against the underlying table would fail if the previous value were expired; this was due to the fact that the mapped attribute would not be configured with active_history=True.
References: #4195
An exception is now raised if the ORM loads a row for a polymorphic instance that has a primary key but the discriminator column is NULL, as discriminator columns should not be null.
References: #4836
Accessing a collection-oriented attribute on a newly created object no longer mutates
__dict__
, but still returns an empty collection as has always been the case. This allows collection-oriented attributes to work consistently in comparison to scalar attributes which returnNone
, but also don’t mutate__dict__
. In order to accommodate for the collection being mutated, the same empty collection is returned each time once initially created, and when it is mutated (e.g. an item appended, added, etc.) it is then moved into__dict__
. This removes the last of mutating side-effects on read-only attribute access within the ORM.См.также
Accessing an uninitialized collection attribute on a transient object no longer mutates __dict__
References: #4519
The refresh of an expired object will now trigger an autoflush if the list of expired attributes include one or more attributes that were explicitly expired or refreshed using the
Session.expire()
orSession.refresh()
methods. This is an attempt to find a middle ground between the normal unexpiry of attributes that can happen in many cases where autoflush is not desirable, vs. the case where attributes are being explicitly expired or refreshed and it is possible that these attributes depend upon other pending state within the session that needs to be flushed. The two methods now also gain a new flagSession.expire.autoflush
andSession.refresh.autoflush
, defaulting to True; when set to False, this will disable the autoflush that occurs on unexpire for these attributes.References: #5226
The behavior of the
relationship.cascade_backrefs
flag will be reversed in 2.0 and set toFalse
unconditionally, such that backrefs don’t cascade save-update operations from a forwards-assignment to a backwards assignment. A 2.0 deprecation warning is emitted when the parameter is left at its default ofTrue
at the point at which such a cascade operation actually takes place. The new behavior can be established as always by setting the flag toFalse
on a specificrelationship()
, or more generally can be set up across the board by setting the theSession.future
flag to True.References: #5150
The «slice index» feature used by
Query
as well as by the dynamic relationship loader will no longer accept negative indexes in SQLAlchemy 2.0. These operations do not work efficiently and load the entire collection in, which is both surprising and undesirable. These will warn in 1.4 unless theSession.future
flag is set in which case they will raise IndexError.References: #5606
Calling the
Query.instances()
method without passing aQueryContext
is deprecated. The original use case for this was that aQuery
could yield ORM objects when given only the entities to be selected as well as a DBAPI cursor object. However, for this to work correctly there is essential metadata that is passed from a SQLAlchemyResultProxy
that is derived from the mapped column expressions, which comes originally from theQueryContext
. To retrieve ORM results from arbitrary SELECT statements, theQuery.from_statement()
method should be used.References: #4719
Using strings to represent relationship names in ORM operations such as
Query.join()
, as well as strings for all ORM attribute names in loader options likeselectinload()
is deprecated and will be removed in SQLAlchemy 2.0. The class-bound attribute should be passed instead. This provides much better specificity to the given method, allows for modifiers such asof_type()
, and reduces internal complexity.Additionally, the
aliased
andfrom_joinpoint
parameters toQuery.join()
are also deprecated. Thealiased()
construct now provides for a great deal of flexibility and capability and should be used directly.Deprecated logic in
Query.distinct()
that automatically adds columns in the ORDER BY clause to the columns clause; this will be removed in 2.0.References: #5134
Passing keyword arguments to methods such as
Session.execute()
to be passed into theSession.get_bind()
method is deprecated; the newSession.execute.bind_arguments
dictionary should be passed instead.References: #5573
The
eagerload()
andrelation()
were old aliases and are now deprecated. Usejoinedload()
andrelationship()
respectively.References: #5192
All long-deprecated «extension» classes have been removed, including MapperExtension, SessionExtension, PoolListener, ConnectionProxy, AttributeExtension. These classes have been deprecated since version 0.7 long superseded by the event listener system.
References: #4638
Remove the deprecated loader options
joinedload_all
,subqueryload_all
,lazyload_all
,selectinload_all
. The normal version with method chaining should be used in their place.References: #4642
Remove deprecated function
comparable_property
. Please refer to thehybrid
extension. This also removes the functioncomparable_using
in the declarative extension.Remove deprecated function
compile_mappers
. Please useconfigure_mappers()
Remove deprecated method
collection.linker
. Please refer to theAttributeEvents.init_collection()
andAttributeEvents.dispose_collection()
event handlers.Remove deprecated method
Session.prune
and parameterSession.weak_identity_map
. See the recipe at Поведение при обращении к сеансам for an event-based approach to maintaining strong identity references. This change also removes the classStrongInstanceDict
.Remove deprecated parameter
mapper.order_by
. UseQuery.order_by()
to determine the ordering of a result set.Remove deprecated parameter
Session._enable_transaction_accounting
.Remove deprecated parameter
Session.is_modified.passive
.References: #4643
engine¶
Implemented an all-new
Result
object that replaces the previousResultProxy
object. As implemented in Core, the subclassCursorResult
features a compatible calling interface with the previousResultProxy
, and additionally adds a great amount of new functionality that can be applied to Core result sets as well as ORM result sets, which are now integrated into the same model.Result
includes features such as column selection and rearrangement, improved fetchmany patterns, uniquing, as well as a variety of implementations that can be used to create database results from in-memory structures as well.См.также
SQLAlchemy now includes support for Python asyncio within both Core and ORM, using the included asyncio extension. The extension makes use of the greenlet library in order to adapt SQLAlchemy’s sync-oriented internals such that an asyncio interface that ultimately interacts with an asyncio database adapter is now feasible. The single driver supported at the moment is the asyncpg driver for PostgreSQL.
References: #3414
Implemented the
create_engine.future
parameter which enables forwards compatibility with SQLAlchemy 2. is used for forwards compatibility with SQLAlchemy 2. This engine features always-transactional behavior with autobegin.См.также
References: #4644
Reworked the «setinputsizes()» set of dialect hooks to be correctly extensible for any arbitrary DBAPI, by allowing dialects individual hooks that may invoke cursor.setinputsizes() in the appropriate style for that DBAPI. In particular this is intended to support pyodbc’s style of usage which is fundamentally different from that of cx_Oracle. Added support for pyodbc.
References: #5649
Added new reflection method
Inspector.get_sequence_names()
which returns all the sequences defined andInspector.has_sequence()
to check if a particular sequence exits. Support for this method has been added to the backend that supportSequence
: PostgreSQL, Oracle and MariaDB >= 10.3.References: #2056
The
Table.autoload_with
parameter now accepts anInspector
object directly, as well as anyEngine
orConnection
as was the case before.References: #4755
The
RowProxy
class is no longer a «proxy» object, and is instead directly populated with the post-processed contents of the DBAPI row tuple upon construction. Now namedRow
, the mechanics of how the Python-level value processors have been simplified, particularly as it impacts the format of the C code, so that a DBAPI row is processed into a result tuple up front. The object returned by theResultProxy
is now theLegacyRow
subclass, which maintains mapping/tuple hybrid behavior, however the baseRow
class now behaves more fully like a named tuple.См.также
RowProxy is no longer a «proxy»; is now called Row and behaves like an enhanced named tuple
References: #4710
The pool «pre-ping» feature has been refined to not invoke for a DBAPI connection that was just opened in the same checkout operation. pre ping only applies to a DBAPI connection that’s been checked into the pool and is being checked out again.
References: #4524
Disabled the «unicode returns» check that runs on dialect startup when running under Python 3, which for many years has occurred in order to test the current DBAPI’s behavior for whether or not it returns Python Unicode or Py2K strings for the VARCHAR and NVARCHAR datatypes. The check still occurs by default under Python 2, however the mechanism to test the behavior will be removed in SQLAlchemy 2.0 when Python 2 support is also removed.
This logic was very effective when it was needed, however now that Python 3 is standard, all DBAPIs are expected to return Python 3 strings for character datatypes. In the unlikely case that a third party DBAPI does not support this, the conversion logic within
String
is still available and the third party dialect may specify this in its upfront dialect flags by setting the dialect level flagreturns_unicode_strings
to one ofString.RETURNS_CONDITIONAL
orString.RETURNS_BYTES
, both of which will enable Unicode conversion even under Python 3.References: #5315
Revised the
Connection.execution_options.schema_translate_map
feature such that the processing of the SQL statement to receive a specific schema name occurs within the execution phase of the statement, rather than at the compile phase. This is to support the statement being efficiently cached. Previously, the current schema being rendered into the statement for a particular run would be considered as part of the cache key itself, meaning that for a run against hundreds of schemas, there would be hundreds of cache keys, rendering the cache much less performant. The new behavior is that the rendering is done in a similar manner as the «post compile» rendering added in 1.4 as part of #4645, #4808.References: #5004
The
Connection
object will now not clear a rolled-back transaction until the outermost transaction is explicitly rolled back. This is essentially the same behavior that the ORMSession
has had for a long time, where an explicit call to.rollback()
on all enclosing transactions is required for the transaction to logically clear, even though the DBAPI-level transaction has already been rolled back. The new behavior helps with situations such as the «ORM rollback test suite» pattern where the test suite rolls the transaction back within the ORM scope, but the test harness which seeks to control the scope of the transaction externally does not expect a new transaction to start implicitly.References: #4712
Adjusted the dialect initialization process such that the
Dialect.on_connect()
is not called a second time on the first connection. The hook is called first, then theDialect.initialize()
is called if that connection is the first for that dialect, then no more events are called. This eliminates the two calls to the «on_connect» function which can produce very difficult debugging situations.References: #5497
The
URL
object is now an immutable named tuple. To modify a URL object, use theURL.set()
method to produce a new URL object.См.также
The URL object is now immutable - notes on migration
References: #5526
The
MetaData.bind
argument as well as the overall concept of «bound metadata» is deprecated in SQLAlchemy 1.4 and will be removed in SQLAlchemy 2.0. The parameter as well as related functions now emit aRemovedIn20Warning
when SQLAlchemy 2.0 Deprecations Mode is in use.References: #4634
The
server_side_cursors
engine-wide parameter is deprecated and will be removed in a future release. For unbuffered cursors, theConnection.execution_options.stream_results
execution option should be used on a per-execution basis.The
Connection.connect()
method is deprecated as is the concept of «connection branching», which copies aConnection
into a new one that has a no-op «.close()» method. This pattern is oriented around the «connectionless execution» concept which is also being removed in 2.0.References: #5131
The
case_sensitive
flag oncreate_engine()
is deprecated; this flag was part of the transition of the result row object to allow case sensitive column matching as the default, while providing backwards compatibility for the former matching method. All string access for a row should be assumed to be case sensitive just like any other Python mapping.References: #4878
»Implicit autocommit», which is the COMMIT that occurs when a DML or DDL statement is emitted on a connection, is deprecated and won’t be part of SQLAlchemy 2.0. A 2.0-style warning is emitted when autocommit takes effect, so that the calling code may be adjusted to use an explicit transaction.
As part of this change, DDL methods such as
MetaData.create_all()
when used against anEngine
will run the operation in a BEGIN block if one is not started already.См.также
References: #4846
Deprecated the behavior by which a
Column
can be used as the key in a result set row lookup, when thatColumn
is not part of the SQL selectable that is being selected; that is, it is only matched on name. A deprecation warning is now emitted for this case. Various ORM use cases, such as those involvingtext()
constructs, have been improved so that this fallback logic is avoided in most cases.References: #4877
Deprecated remaining engine-level introspection and utility methods including
Engine.run_callable()
,Engine.transaction()
,Engine.table_names()
,Engine.has_table()
. The utility methods are superseded by modern context-manager patterns, and the table introspection tasks are suited by theInspector
object.References: #4755
Remove deprecated method
get_primary_keys
in theDialect
andInspector
classes. Please refer to theDialect.get_pk_constraint()
andInspector.get_primary_keys()
methods.Remove deprecated event
dbapi_error
and the methodConnectionEvents.dbapi_error
. Please refer to theConnectionEvents.handle_error()
event. This change also removes the attributesExecutionContext.is_disconnect
andExecutionContext.exception
.References: #4643
The internal dialect method
Dialect.reflecttable
has been removed. A review of third party dialects has not found any making use of this method, as it was already documented as one that should not be used by external dialects. Additionally, the privateEngine._run_visitor
method is also removed.References: #4755
The long-deprecated
Inspector.get_table_names.order_by
parameter has been removed.References: #4755
The
Inspector.reflecttable()
was renamed toInspector.reflect_table()
.References: #5244
sql¶
Added «from linting» as a built-in feature to the SQL compiler. This allows the compiler to maintain graph of all the FROM clauses in a particular SELECT statement, linked by criteria in either the WHERE or in JOIN clauses that link these FROM clauses together. If any two FROM clauses have no path between them, a warning is emitted that the query may be producing a cartesian product. As the Core expression language as well as the ORM are built on an «implicit FROMs» model where a particular FROM clause is automatically added if any part of the query refers to it, it is easy for this to happen inadvertently and it is hoped that the new feature helps with this issue.
References: #4737
Added new «post compile parameters» feature. This feature allows a
bindparam()
construct to have its value rendered into the SQL string before being passed to the DBAPI driver, but after the compilation step, using the «literal render» feature of the compiler. The immediate rationale for this feature is to support LIMIT/OFFSET schemes that don’t work or perform well as bound parameters handled by the database driver, while still allowing for SQLAlchemy SQL constructs to be cacheable in their compiled form. The immediate targets for the new feature are the «TOP N» clause used by SQL Server (and Sybase) which does not support a bound parameter, as well as the «ROWNUM» and optional «FIRST_ROWS()» schemes used by the Oracle dialect, the former of which has been known to perform better without bound parameters and the latter of which does not support a bound parameter. The feature builds upon the mechanisms first developed to support «expanding» parameters for IN expressions. As part of this feature, the Oracleuse_binds_for_limits
feature is turned on unconditionally and this flag is now deprecated.References: #4808
Add support for regular expression on supported backends. Two operations have been defined:
ColumnOperators.regexp_match()
implementing a regular expression match like function.ColumnOperators.regexp_replace()
implementing a regular expression string replace function.
Supported backends include SQLite, PostgreSQL, MySQL / MariaDB, and Oracle.
References: #1390
The
select()
construct and related constructs now allow for duplication of column labels and columns themselves in the columns clause, mirroring exactly how column expressions were passed in. This allows the tuples returned by an executed result to match what was SELECTed for in the first place, which is how the ORMQuery
works, so this establishes better cross-compatibility between the two constructs. Additionally, it allows column-positioning-sensitive structures such as UNIONs (i.e._selectable.CompoundSelect
) to be more intuitively constructed in those cases where a particular column might appear in more than one place. To support this change, theColumnCollection
has been revised to support duplicate columns as well as to allow integer index access.References: #4753
Enhanced the disambiguating labels feature of the
select()
construct such that when a select statement is used in a subquery, repeated column names from different tables are now automatically labeled with a unique label name, without the need to use the full «apply_labels()» feature that combines tablename plus column name. The disambiguated labels are available as plain string keys in the .c collection of the subquery, and most importantly the feature allows an ORMaliased()
construct against the combination of an entity and an arbitrary subquery to work correctly, targeting the correct columns despite same-named columns in the source tables, without the need for an «apply labels» warning.См.также
Выборка из самого запроса как подзапрос, например, «from_self()». - Illustrates the new disambiguation feature as part of a strategy to migrate away from the
Query.from_self()
method.References: #5221
The «expanding IN» feature, which generates IN expressions at query execution time which are based on the particular parameters associated with the statement execution, is now used for all IN expressions made against lists of literal values. This allows IN expressions to be fully cacheable independently of the list of values being passed, and also includes support for empty lists. For any scenario where the IN expression contains non-literal SQL expressions, the old behavior of pre-rendering for each position in the IN is maintained. The change also completes support for expanding IN with tuples, where previously type-specific bind processors weren’t taking effect.
References: #4645
Along with the new transparent statement caching feature introduced as part of #4369, a new feature intended to decrease the Python overhead of creating statements is added, allowing lambdas to be used when indicating arguments being passed to a statement object such as select(), Query(), update(), etc., as well as allowing the construction of full statements within lambdas in a similar manner as that of the «baked query» system. The rationale of using lambdas is adapted from that of the «baked query» approach which uses lambdas to encapsulate any amount of Python code into a callable that only needs to be called when the statement is first constructed into a string. The new feature however is more sophisticated in that Python literal values that would be passed as parameters are automatically extracted, so that there is no longer a need to use bindparam() objects with such queries. Use of the feature is optional and can be used to as small or as great a degree as is desired, while still allowing statements to be fully cacheable.
References: #5380
The
Index.create()
andIndex.drop()
methods now have a parameterIndex.create.checkfirst
, in the same way as that ofTable
andSequence
, which when enabled will cause the operation to detect if the index exists (or not) before performing a create or drop operation.References: #527
The
true()
andfalse()
operators may now be applied as the «onclause» of ajoin()
on a backend that does not support «native boolean» expressions, e.g. Oracle or SQL Server, and the expression will render as «1=1» for true and «1=0» false. This is the behavior that was introduced many years ago in #2804 for and/or expressions.Change the method
__str
ofColumnCollection
to avoid confusing it with a python list of string.References: #5191
Add support to
FETCH {FIRST | NEXT} [ count ] {ROW | ROWS} {ONLY | WITH TIES}
in the select for the supported backends, currently PostgreSQL, Oracle and MSSQL.References: #5576
Additional logic has been added such that certain SQL expressions which typically wrap a single database column will use the name of that column as their «anonymous label» name within a SELECT statement, potentially making key-based lookups in result tuples more intuitive. The primary example of this is that of a CAST expression, e.g.
CAST(table.colname AS INTEGER)
, which will export its default name as «colname», rather than the usual «anon_1» label, that is,CAST(table.colname AS INTEGER) AS colname
. If the inner expression doesn’t have a name, then the previous «anonymous label» logic is used. When using SELECT statements that make use ofSelect.apply_labels()
, such as those emitted by the ORM, the labeling logic will produce<tablename>_<inner column name>
in the same was as if the column were named alone. The logic applies right now to thecast()
andtype_coerce()
constructs as well as some single-element boolean expressions.References: #4449
The «clause coercion» system, which is SQLAlchemy Core’s system of receiving arguments and resolving them into
ClauseElement
structures in order to build up SQL expression objects, has been rewritten from a series of ad-hoc functions to a fully consistent class-based system. This change is internal and should have no impact on end users other than more specific error messages when the wrong kind of argument is passed to an expression object, however the change is part of a larger set of changes involving the role and behavior ofselect()
objects.References: #4617
Added a core
Values
object that enables a VALUES construct to be used in the FROM clause of an SQL statement for databases that support it (mainly PostgreSQL and SQL Server).References: #4868
The
select()
construct is moving towards a new calling form that isselect(col1, col2, col3, ..)
, with all other keyword arguments removed, as these are all suited using generative methods. The single list of column or table arguments passed toselect()
is still accepted, however is no longer necessary if expressions are passed in a simple positional style. Other keyword arguments are disallowed when this form is used.References: #5284
As part of the SQLAlchemy 2.0 migration project, a conceptual change has been made to the role of the
SelectBase
class hierarchy, which is the root of all «SELECT» statement constructs, in that they no longer serve directly as FROM clauses, that is, they no longer subclassFromClause
. For end users, the change mostly means that any placement of aselect()
construct in the FROM clause of anotherselect()
requires first that it be wrapped in a subquery first, which historically is through the use of theSelectBase.alias()
method, and is now also available through the use ofSelectBase.subquery()
. This was usually a requirement in any case since several databases don’t accept unnamed SELECT subqueries in their FROM clause in any case.References: #4617
Added a new Core class
Subquery
, which takes the place ofAlias
when creating named subqueries against aSelectBase
object.Subquery
acts in the same way asAlias
and is produced from theSelectBase.subquery()
method; for ease of use and backwards compatibility, theSelectBase.alias()
method is synonymous with this new method.References: #4617
An all-encompassing reorganization and refactoring of Core and ORM internals now allows all Core and ORM statements within the areas of DQL (e.g. SELECTs) and DML (e.g. INSERT, UPDATE, DELETE) to allow their SQL compilation as well as the construction of result-fetching metadata to be fully cached in most cases. This effectively provides a transparent and generalized version of what the «Baked Query» extension has offered for the ORM in past versions. The new feature can calculate the cache key for any given SQL construction based on the string that it would ultimately produce for a given dialect, allowing functions that compose the equivalent select(), Query(), insert(), update() or delete() object each time to have that statement cached after it’s generated the first time.
The feature is enabled transparently but includes some new programming paradigms that may be employed to make the caching even more efficient.
References: #4639
Fixed issue where when constructing constraints from ORM-bound columns, primarily
ForeignKey
objects but alsoUniqueConstraint
,CheckConstraint
and others, the ORM-levelInstrumentedAttribute
is discarded entirely, and all ORM-level annotations from the columns are removed; this is so that the constraints are still fully pickleable without the ORM-level entities being pulled in. These annotations are not necessary to be present at the schema/metadata level.References: #5001
Registered function names based on
GenericFunction
are now retrieved in a case-insensitive fashion in all cases, removing the deprecation logic from 1.3 which temporarily allowed multipleGenericFunction
objects to exist with differing cases. AGenericFunction
that replaces another on the same name whether or not it’s case sensitive emits a warning before replacing the object.Creating an
and_()
oror_()
construct with no arguments or empty*args
will now emit a deprecation warning, as the SQL produced is a no-op (i.e. it renders as a blank string). This behavior is considered to be non-intuitive, so for empty or possibly emptyand_()
oror_()
constructs, an appropriate default boolean should be included, such asand_(True, *args)
oror_(False, *args)
. As has been the case for many major versions of SQLAlchemy, these particular boolean values will not render if the*args
portion is non-empty.References: #5054
Improved the
tuple_()
construct such that it behaves predictably when used in a columns-clause context. The SQL tuple is not supported as a «SELECT» columns clause element on most backends; on those that do (PostgreSQL, not surprisingly), the Python DBAPI does not have a «nested type» concept so there are still challenges in fetching rows for such an object. Use oftuple_()
in aselect()
orQuery
will now raise aCompileError
at the point at which thetuple_()
object is seen as presenting itself for fetching rows (i.e., if the tuple is in the columns clause of a subquery, no error is raised). For ORM use,theBundle
object is an explicit directive that a series of columns should be returned as a sub-tuple per row and is suggested by the error message. Additionally ,the tuple will now render with parenthesis in all contexts. Previously, the parenthesization would not render in a columns context leading to non-defined behavior.References: #5127
Improved support for column names that contain percent signs in the string, including repaired issues involving anonymous labels that also embedded a column name with a percent sign in it, as well as re-established support for bound parameter names with percent signs embedded on the psycopg2 dialect, using a late-escaping process similar to that used by the cx_Oracle dialect.
References: #5653
Custom functions that are created as subclasses of
FunctionElement
will now generate an «anonymous label» based on the «name» of the function just like any otherFunction
object, e.g."SELECT myfunc() AS myfunc_1"
. While SELECT statements no longer require labels in order for the result proxy object to function, the ORM still targets columns in rows by using objects as mapping keys, which works more reliably when the column expressions have distinct names. In any case, the behavior is now made consistent between functions generated byfunc
and those generated as customFunctionElement
objects.References: #4887
Reworked the
ClauseElement.compare()
methods in terms of a new visitor-based approach, and additionally added test coverage ensuring that allClauseElement
subclasses can be accurately compared against each other in terms of structure. Structural comparison capability is used to a small degree within the ORM currently, however it also may form the basis for new caching features.References: #4336
Deprecate usage of
DISTINCT ON
in dialect other than PostgreSQL. Deprecate old usage of string distinct in MySQL dialectReferences: #4002
The ORDER BY clause of a
_selectable.CompoundSelect
, e.g. UNION, EXCEPT, etc. will not render the table name associated with a given column when applyingCompoundSelect.order_by()
in terms of aTable
- bound column. Most databases require that the names in the ORDER BY clause be expressed as label names only which are matched to names in the first SELECT statement. The change is related to #4617 in that a previous workaround was to refer to the.c
attribute of the_selectable.CompoundSelect
in order to get at a column that has no table name. As the subquery is now named, this change allows both the workaround to continue to work, as well as allows table-bound columns as well as theCompoundSelect.selected_columns
collections to be usable in theCompoundSelect.order_by()
method.References: #4617
The
Join
construct no longer considers the «onclause» as a source of additional FROM objects to be omitted from the FROM list of an enclosingSelect
object as standalone FROM objects. This applies to an ON clause that includes a reference to another FROM object outside the JOIN; while this is usually not correct from a SQL perspective, it’s also incorrect for it to be omitted, and the behavioral change makes theSelect
/Join
behave a bit more intuitively.References: #4621
The
Join.alias()
method is deprecated and will be removed in SQLAlchemy 2.0. An explicit select + subquery, or aliasing of the inner tables, should be used instead.References: #5010
The
Table
class now raises a deprecation warning when columns with the same name are defined. To replace a column a new parameterTable.append_column.replace_existing
was added to theTable.append_column()
method.The
ColumnCollection.contains_column()
will now raises an error when called with a string, suggesting the caller to usein
instead.The «threadlocal» execution strategy, deprecated in 1.3, has been removed for 1.4, as well as the concept of «engine strategies» and the
Engine.contextual_connect
method. The «strategy=“mock“» keyword argument is still accepted for now with a deprecation warning; usecreate_mock_engine()
instead for this use case.См.также
Стратегия «потокового локального» двигателя устарела - from the 1.3 migration notes which discusses the rationale for deprecation.
References: #4632
Removed the
sqlalchemy.sql.visitors.iterate_depthfirst
andsqlalchemy.sql.visitors.traverse_depthfirst
functions. These functions were unused by any part of SQLAlchemy. Theiterate()
andtraverse()
functions are commonly used for these functions. Also removed unused options from the remaining functions including «column_collections», «schema_visitor».Removed the concept of a bound engine from the
Compiler
object, and removed the.execute()
and.scalar()
methods fromCompiler
. These were essentially forgotten methods from over a decade ago and had no practical use, and it’s not appropriate for theCompiler
object itself to be maintaining a reference to anEngine
.Remove deprecated methods
Compiled.compile
,ClauseElement.__and__
andClauseElement.__or__
and attributeOver.func
.Remove deprecated
FromClause.count
method. Please use thecount
function available from thefunc
namespace.References: #4643
Remove deprecated parameters
text.bindparams
andtext.typemap
. Please refer to theTextClause.bindparams()
andTextClause.columns()
methods.Remove deprecated parameter
Table.useexisting
. Please useTable.extend_existing
.References: #4643
Table
parametermustexist
has been renamed toTable.must_exist
and will now warn when used.The
SelectBase.as_scalar()
andQuery.as_scalar()
methods have been renamed toSelectBase.scalar_subquery()
andQuery.scalar_subquery()
, respectively. The old names continue to exist within 1.4 series with a deprecation warning. In addition, the implicit coercion ofSelectBase
,Alias
, and other SELECT oriented objects into scalar subqueries when evaluated in a column context is also deprecated, and emits a warning that theSelectBase.scalar_subquery()
method should be called explicitly. This warning will in a later major release become an error, however the message will always be clear whenSelectBase.scalar_subquery()
needs to be invoked. The latter part of the change is for clarity and to reduce the implicit decisionmaking by the query coercion system. TheSubquery.as_scalar()
method, which was previouslyAlias.as_scalar
, is also deprecated;.scalar_subquery()
should be invoked directly from `select()
object orQuery
object.This change is part of the larger change to convert
select()
objects to no longer be directly part of the «from clause» class hierarchy, which also includes an overhaul of the clause coercion system.References: #4617
Several operators are renamed to achieve more consistent naming across SQLAlchemy.
The operator changes are:
isfalse
is nowis_false
isnot_distinct_from
is nowis_not_distinct_from
istrue
is nowis_true
notbetween
is nownot_between
notcontains
is nownot_contains
notendswith
is nownot_endswith
notilike
is nownot_ilike
notlike
is nownot_like
notmatch
is nownot_match
notstartswith
is nownot_startswith
nullsfirst
is nownulls_first
nullslast
is nownulls_last
isnot
is nowis_not
not_in_
is nownot_in
Because these are core operators, the internal migration strategy for this change is to support legacy terms for an extended period of time – if not indefinitely – but update all documentation, tutorials, and internal usage to the new terms. The new terms are used to define the functions, and the legacy terms have been deprecated into aliases of the new terms.
Allow specifying the data type when creating a
Sequence
in PostgreSQL by using the parameterSequence.data_type
.References: #5498
The «NO ACTION» keyword for foreign key «ON UPDATE» is now considered to be the default cascade for a foreign key on all supporting backends (SQlite, MySQL, PostgreSQL) and when detected is not included in the reflection dictionary; this is already the behavior for PostgreSQL and MySQL for all previous SQLAlchemy versions in any case. The «RESTRICT» keyword is positively stored when detected; PostgreSQL does report on this keyword, and MySQL as of version 8.0 does as well. On earlier MySQL versions, it is not reported by the database.
References: #4741
Added support for reflecting «identity» columns, which are now returned as part of the structure returned by
Inspector.get_columns()
. When reflecting fullTable
objects, identity columns will be represented using theIdentity
construct. Currently the supported backends are PostgreSQL >= 10, Oracle >= 12 and MSSQL (with different syntax and a subset of functionalities).
schema¶
The
Enum.create_constraint
andBoolean.create_constraint
parameters now default to False, indicating when a so-called «non-native» version of these two datatypes is created, a CHECK constraint will not be generated by default. These CHECK constraints present schema-management maintenance complexities that should be opted in to, rather than being turned on by default.References: #5367
Cleaned up the internal
str()
for datatypes so that all types produce a string representation without any dialect present, including that it works for third-party dialect types without that dialect being present. The string representation defaults to being the UPPERCASE name of that type with nothing else.References: #4262
Remove deprecated class
Binary
. Please useLargeBinary
.References: #4643
Renamed the
Table.tometadata()
method toTable.to_metadata()
. The previous name remains with a deprecation warning.References: #5413
Added the
Identity
construct that can be used to configure identity columns rendered with GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY. Currently the supported backends are PostgreSQL >= 10, Oracle >= 12 and MSSQL (with different syntax and a subset of functionalities).
extensions¶
Custom compiler constructs created using the
sqlalchemy.ext.compiled
extension will automatically add contextual information to the compiler when a custom construct is interpreted as an element in the columns clause of a SELECT statement, such that the custom element will be targetable as a key in result row mappings, which is the kind of targeting that the ORM uses in order to match column elements into result tuples.References: #4887
Added new parameter
AutomapBase.prepare.autoload_with
which supersedesAutomapBase.prepare.reflect
andAutomapBase.prepare.engine
.References: #5142
postgresql¶
Added support for PostgreSQL «readonly» and «deferrable» flags for all of psycopg2, asyncpg and pg8000 dialects. This takes advantage of a newly generalized version of the «isolation level» API to support other kinds of session attributes set via execution options that are reliably reset when connections are returned to the connection pool.
См.также
postgresql_readonly_deferrable
References: #5549
The maximum buffer size for the
BufferedRowResultProxy
, which is used by dialects such as PostgreSQL whenstream_results=True
, can now be set to a number greater than 1000 and the buffer will grow to that size. Previously, the buffer would not go beyond 1000 even if the value were set larger. The growth of the buffer is also now based on a simple multiplying factor currently set to 5. Pull request courtesy Soumaya Mauthoor.References: #4914
When using the psycopg2 dialect for PostgreSQL, psycopg2 minimum version is set at 2.7. The psycopg2 dialect relies upon many features of psycopg2 released in the past few years, so to simplify the dialect, version 2.7, released in March, 2017 is now the minimum version required.
The psycopg2 dialect now defaults to using the very performant
execute_values()
psycopg2 extension for compiled INSERT statements, and also implements RETURNING support when this extension is used. This allows INSERT statements that even include an autoincremented SERIAL or IDENTITY value to run very fast while still being able to return the newly generated primary key values. The ORM will then integrate this new feature in a separate change.См.также
psycopg2 dialect features «execute_values» with RETURNING for INSERT statements by default - full list of changes regarding the
executemany_mode
parameter.References: #5401
The pg8000 dialect has been revised and modernized for the most recent version of the pg8000 driver for PostgreSQL. Pull request courtesy Tony Locke. Note that this necessarily pins pg8000 at 1.16.6 or greater, which no longer has Python 2 support. Python 2 users who require pg8000 should ensure their requirements are pinned at
SQLAlchemy<1.4
.The pygresql and py-postgresql dialects are deprecated.
References: #5189
Remove support for deprecated engine URLs of the form
postgres://
; this has emitted a warning for many years and projects should be usingpostgresql://
.References: #4643
mysql¶
Added support for MariaDB Connector/Python to the mysql dialect. Original pull request courtesy Georg Richter.
References: #5459
Added a new dialect token «mariadb» that may be used in place of «mysql» in the
create_engine()
URL. This will deliver a MariaDB dialect subclass of the MySQLDialect in use that forces the «is_mariadb» flag to True. The dialect will raise an error if a server version string that does not indicate MariaDB in use is received. This is useful for MariaDB-specific testing scenarios as well as to support applications that are hardcoding to MariaDB-only concepts. As MariaDB and MySQL featuresets and usage patterns continue to diverge, this pattern may become more prominent.References: #5496
Added support for use of the
Sequence
construct with MariaDB 10.3 and greater, as this is now supported by this database. The construct integrates with theTable
object in the same way that it does for other databases like PostgreSQL and Oracle; if is present on the integer primary key «autoincrement» column, it is used to generate defaults. For backwards compatibility, to support aTable
that has aSequence
on it to support sequence only databases like Oracle, while still not having the sequence fire off for MariaDB, the optional=True flag should be set, which indicates the sequence should only be used to generate the primary key if the target database offers no other option.References: #4976
The MySQL and MariaDB dialects now query from the information_schema.tables system view in order to determine if a particular table exists or not. Previously, the «DESCRIBE» command was used with an exception catch to detect non-existent, which would have the undesirable effect of emitting a ROLLBACK on the connection. There appeared to be legacy encoding issues which prevented the use of «SHOW TABLES», for this, but as MySQL support is now at 5.0.2 or above due to #4189, the information_schema tables are now available in all cases.
The «skip_locked» keyword used with
with_for_update()
will render «SKIP LOCKED» on all MySQL backends, meaning it will fail for MySQL less than version 8 and on current MariaDB backends. This is because those backends do not support «SKIP LOCKED» or any equivalent, so this error should not be silently ignored. This is upgraded from a warning in the 1.3 series.References: #5568
MySQL dialect’s server_version_info tuple is now all numeric. String tokens like «MariaDB» are no longer present so that numeric comparison works in all cases. The .is_mariadb flag on the dialect should be consulted for whether or not mariadb was detected. Additionally removed structures meant to support extremely old MySQL versions 3.x and 4.x; the minimum MySQL version supported is now version 5.0.2.
References: #4189
The OurSQL dialect is deprecated.
References: #5189
Remove deprecated dialect
mysql+gaerdbms
that has been deprecated since version 1.0. Use the MySQLdb dialect directly.Remove deprecated parameter
quoting
fromENUM
andSET
in themysql
dialect. The values passed to the enum or the set are quoted by SQLAlchemy when needed automatically.References: #4643
sqlite¶
Dropped support for right-nested join rewriting to support old SQLite versions prior to 3.7.16, released in 2013. It is expected that all modern Python versions among those now supported should all include much newer versions of SQLite.
References: #4895
mssql¶
Added support for the
JSON
datatype on the SQL Server dialect using theJSON
implementation, which implements SQL Server’s JSON functionality against theNVARCHAR(max)
datatype as per SQL Server documentation. Implementation courtesy Gord Thompson.References: #4384
Added support for «CREATE SEQUENCE» and full
Sequence
support for Microsoft SQL Server. This removes the deprecated feature of usingSequence
objects to manipulate IDENTITY characteristics which should now be performed usingmssql_identity_start
andmssql_identity_increment
as documented at mssql_identity. The change includes a new parameterSequence.data_type
to accommodate SQL Server’s choice of datatype, which for that backend includes INTEGER, BIGINT, and DECIMAL(n, 0). The default starting value for SQL Server’s version ofSequence
has been set at 1; this default is now emitted within the CREATE SEQUENCE DDL for all backends.Improved support for covering indexes (with INCLUDE columns). Added the ability for postgresql to render CREATE INDEX statements with an INCLUDE clause from Core. Index reflection also report INCLUDE columns separately for both mssql and postgresql (11+).
References: #4458
Added support for inspection / reflection of partial indexes / filtered indexes, i.e. those which use the
mssql_where
orpostgresql_where
parameters, withIndex
. The entry is both part of the dictionary returned byInspector.get_indexes()
as well as part of a reflectedIndex
construct that was reflected. Pull request courtesy Ramon Williams.References: #4966
Added support for reflection of temporary tables with the SQL Server dialect. Table names that are prefixed by a pound sign «#» are now introspected from the MSSQL «tempdb» system catalog.
References: #5506
SQL Server OFFSET and FETCH keywords are now used for limit/offset, rather than using a window function, for SQL Server versions 11 and higher. TOP is still used for a query that features only LIMIT. Pull request courtesy Elkin.
References: #5084
Fixed an issue where
sqlalchemy.engine.reflection.has_table()
always returnedFalse
for temporary tables.References: #5597
Fixed the base class of the
DATETIMEOFFSET
datatype to be based on theDateTime
class hierarchy, as this is a datetime-holding datatype.References: #4980
The adodbapi and mxODBC dialects are deprecated.
References: #5189
The mssql dialect will assume that at least MSSQL 2005 is used. There is no hard exception raised if a previous version is detected, but operations may fail for older versions.
As part of the support for reflecting
Identity
objects, the methodInspector.get_columns()
no longer returnsmssql_identity_start
andmssql_identity_increment
as part of thedialect_options
. Use the information in theidentity
key instead.References: #5527
Deprecated the
legacy_schema_aliasing
parameter tosqlalchemy.create_engine()
. This is a long-outdated parameter that has defaulted to False since version 1.1.References: #4809
oracle¶
The max_identifier_length for the Oracle dialect is now 128 characters by default, unless compatibility version less than 12.2 upon first connect, in which case the legacy length of 30 characters is used. This is a continuation of the issue as committed to the 1.3 series which adds max identifier length detection upon first connect as well as warns for the change in Oracle server.
См.также
oracle_max_identifier_lengths - in the Oracle dialect documentation
References: #4857
The LIMIT / OFFSET scheme used in Oracle now makes use of named subqueries rather than unnamed subqueries when it transparently rewrites a SELECT statement to one that uses a subquery that includes ROWNUM. The change is part of a larger change where unnamed subqueries are no longer directly supported by Core, as well as to modernize the internal use of the select() construct within the Oracle dialect.
Correctly render
Sequence
andIdentity
column optionsnominvalue
andnomaxvalue
asNOMAXVALUE` and ``NOMINVALUE
on oracle database.The
INTERVAL
class of the Oracle dialect is now correctly a subclass of the abstract version ofInterval
as well as the correct «emulated» base class, which allows for correct behavior under both native and non-native modes; previously it was only based onTypeEngine
.References: #4971
firebird¶
The Firebird dialect is deprecated, as there is now a 3rd party dialect that supports this database.
References: #5189
misc¶
The Sybase dialect is deprecated.
References: #5189