mirror of
https://github.com/spiral-project/ihatemoney.git
synced 2025-04-28 17:32:38 +02:00
upgrade sqlalchemy-continuum
1.3.10 is needed to remove the patch 1.3.12 is needed for SQLAlchemy 1.4
This commit is contained in:
parent
a14c7c5aaf
commit
1bea93f8a5
3 changed files with 1 additions and 143 deletions
|
@ -21,7 +21,6 @@ from sqlalchemy_continuum.plugins import FlaskPlugin
|
|||
from werkzeug.security import generate_password_hash
|
||||
|
||||
from ihatemoney.currency_convertor import CurrencyConverter
|
||||
from ihatemoney.patch_sqlalchemy_continuum import PatchedBuilder
|
||||
from ihatemoney.utils import get_members, same_bill
|
||||
from ihatemoney.versioning import (
|
||||
ConditionalVersioningManager,
|
||||
|
@ -36,9 +35,6 @@ make_versioned(
|
|||
# Conditionally Disable the versioning based on each
|
||||
# project's privacy preferences
|
||||
tracking_predicate=version_privacy_predicate,
|
||||
# Patch in a fix to a SQLAchemy-Continuum Bug.
|
||||
# See patch_sqlalchemy_continuum.py
|
||||
builder=PatchedBuilder(),
|
||||
),
|
||||
plugins=[
|
||||
FlaskPlugin(
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
"""
|
||||
A temporary work-around to patch SQLAlchemy-continuum per:
|
||||
https://github.com/kvesteri/sqlalchemy-continuum/pull/242
|
||||
|
||||
Source code reproduced under their license:
|
||||
|
||||
Copyright (c) 2012, Konsta Vesterinen
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* The names of the contributors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy_continuum import Operation
|
||||
from sqlalchemy_continuum.builder import Builder
|
||||
from sqlalchemy_continuum.expression_reflector import VersionExpressionReflector
|
||||
from sqlalchemy_continuum.relationship_builder import RelationshipBuilder
|
||||
from sqlalchemy_continuum.utils import adapt_columns, option
|
||||
|
||||
|
||||
class PatchedRelationShipBuilder(RelationshipBuilder):
|
||||
def association_subquery(self, obj):
|
||||
"""
|
||||
Returns an EXISTS clause that checks if an association exists for given
|
||||
SQLAlchemy declarative object. This query is used by
|
||||
many_to_many_criteria method.
|
||||
|
||||
Example query:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
EXISTS (
|
||||
SELECT 1
|
||||
FROM article_tag_version
|
||||
WHERE article_id = 3
|
||||
AND tag_id = tags_version.id
|
||||
AND operation_type != 2
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM article_tag_version as article_tag_version2
|
||||
WHERE article_tag_version2.tag_id = article_tag_version.tag_id
|
||||
AND article_tag_version2.tx_id <=5
|
||||
AND article_tag_version2.article_id = 3
|
||||
GROUP BY article_tag_version2.tag_id
|
||||
HAVING
|
||||
MAX(article_tag_version2.tx_id) =
|
||||
article_tag_version.tx_id
|
||||
)
|
||||
)
|
||||
|
||||
:param obj: SQLAlchemy declarative object
|
||||
"""
|
||||
|
||||
tx_column = option(obj, "transaction_column_name")
|
||||
join_column = self.property.primaryjoin.right.name
|
||||
object_join_column = self.property.primaryjoin.left.name
|
||||
reflector = VersionExpressionReflector(obj, self.property)
|
||||
|
||||
association_table_alias = self.association_version_table.alias()
|
||||
association_cols = [
|
||||
association_table_alias.c[association_col.name]
|
||||
for _, association_col in self.remote_to_association_column_pairs
|
||||
]
|
||||
|
||||
association_exists = sa.exists(
|
||||
sa.select([1])
|
||||
.where(
|
||||
sa.and_(
|
||||
association_table_alias.c[tx_column] <= getattr(obj, tx_column),
|
||||
association_table_alias.c[join_column]
|
||||
== getattr(obj, object_join_column),
|
||||
*[
|
||||
association_col
|
||||
== self.association_version_table.c[association_col.name]
|
||||
for association_col in association_cols
|
||||
],
|
||||
)
|
||||
)
|
||||
.group_by(*association_cols)
|
||||
.having(
|
||||
sa.func.max(association_table_alias.c[tx_column])
|
||||
== self.association_version_table.c[tx_column]
|
||||
)
|
||||
.correlate(self.association_version_table)
|
||||
)
|
||||
return sa.exists(
|
||||
sa.select([1])
|
||||
.where(
|
||||
sa.and_(
|
||||
reflector(self.property.primaryjoin),
|
||||
association_exists,
|
||||
self.association_version_table.c.operation_type != Operation.DELETE,
|
||||
adapt_columns(self.property.secondaryjoin),
|
||||
)
|
||||
)
|
||||
.correlate(self.local_cls, self.remote_cls)
|
||||
)
|
||||
|
||||
|
||||
class PatchedBuilder(Builder):
|
||||
def build_relationships(self, version_classes):
|
||||
"""
|
||||
Builds relationships for all version classes.
|
||||
|
||||
:param version_classes: list of generated version classes
|
||||
"""
|
||||
for cls in version_classes:
|
||||
if not self.manager.option(cls, "versioning"):
|
||||
continue
|
||||
|
||||
for prop in sa.inspect(cls).iterate_properties:
|
||||
if prop.key == "versions":
|
||||
continue
|
||||
builder = PatchedRelationShipBuilder(self.manager, cls, prop)
|
||||
builder()
|
|
@ -40,7 +40,7 @@ install_requires =
|
|||
itsdangerous>=2,<3
|
||||
Jinja2>=3,<4
|
||||
requests>=2.22,<3
|
||||
SQLAlchemy-Continuum>=1.3.9,<2
|
||||
SQLAlchemy-Continuum>=1.3.12,<2
|
||||
SQLAlchemy>=1.3.0,<1.4 # New 1.4 changes API, see #728
|
||||
python-dateutil
|
||||
|
||||
|
|
Loading…
Reference in a new issue