Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

queryset update method fails Hvad 1.2.1 #250

Closed
jmalinens opened this issue Jun 30, 2015 · 3 comments
Closed

queryset update method fails Hvad 1.2.1 #250

jmalinens opened this issue Jun 30, 2015 · 3 comments
Milestone

Comments

@jmalinens
Copy link

Traceback:
https://gist.github.com/jmalinens/4321303b1c6d9c222e96

class GeonamesCityManager(TranslationManager):
    def get_queryset(self):
        return  super(GeonamesCityManager, self).get_queryset().model.objects.language().fallbacks('lv', 'ru', 'en').order_by('title').distinct()

queryset:

            nRowsUpdated = GeonamesCity.objects.filter(id=field_id).update(published=published)

generated sql:

UPDATE "commissions_geonamescity"
SET "published" = % s
WHERE "commissions_geonamescity".
"id"
IN
  (SELECT V0.
    "id"
    AS "id"
    FROM "commissions_geonamescity"
    V0 INNER JOIN "commissions_geonamescity_translation"
    V1 ON(V0.
      "id" = V1.
      "master_id") WHERE V1.
    "id"
    IN(SELECT DISTINCT U0.
      "id"
      FROM "commissions_geonamescity_translation"
      U0 LEFT OUTER JOIN "commissions_geonamescity_translation"
      U2 ON(U0.
        "master_id" = U2.
        "master_id"
        AND((CASE U2.language_code WHEN 'lv'
          THEN 0 WHEN 'ru'
          THEN 1 WHEN 'en'
          THEN 2 ELSE 3 END) < (CASE U0.language_code WHEN 'lv'
          THEN 0 WHEN 'ru'
          THEN 1 WHEN 'en'
          THEN 2 ELSE 3 END) OR(U2.language_code = U0.language_code AND U2.id < U0.id))) WHERE(U0.
        "master_id" = % s AND(T3.id IS NULL) AND U0.
        "master_id"
        IS NOT NULL)))

in HVAD:

C:\xampp\htdocs\transferta\env\lib\site-packages\hvad\manager.py in update
            qs = self._clone()._add_language_filter()
            shared, translated = qs._split_kwargs(**kwargs)
            count = 0
            if translated:
                count += super(TranslationQueryset, qs).update(**translated)
            if shared:
                shared_qs = qs._get_shared_queryset()
                count += shared_qs.update(**shared)
     ...
            return count
        update.alters_data = True
        #===========================================================================
        # Queryset/Manager API that return another queryset
        #===========================================================================Local vars
Variable    Value
count   
0
qs  
Error in formatting: Queryset is already tagged. This is a bug in hvad
self    
[<GeonamesCity: St Croix, Saint Croix Island>]
kwargs  
{'published': True}
translated  
{}
shared  
{'published': True}
shared_qs   
Error in formatting: missing FROM-clause entry for table "t3"
LINE 1: ...d < U0.id))) WHERE (U0."master_id" = 4796512 AND (T3.id IS N...
@jmalinens jmalinens changed the title queryset update method fails queryset update method fails Hvad 1.2.1 Jun 30, 2015
@spectras
Copy link
Collaborator

Hello,

Thanks for reporting. Okay, so let's see. The Error in formatting: Queryset is already tagged is normal, because due to where the exception is raised, the debugger will attempt to re-process an already-processed queryset. In normal conditions this should not happen, and there is a safeguard to detect it, that gets triggered there.

The main issue is for some reason one of the tables just went missing. Namely, the table from the original request. My guess is it is related to the fallbacks / update combination.

Actually, for your request you don't need the translations. Could you try to do this instead?

nRowsUpdated = GeonamesCity.objects.untranslated().filter(id=field_id).update(published=published)

It will be better for performance as it won't have to read and match the translations. Also, it should not trigger this problem.

@spectras
Copy link
Collaborator

Can confirm the issue: update() will generate a subquery, but fallbacks() won't work as a subquery because it relies on adding some extra filters. But when Django builds a subquery, it renames all tables so the extra filters break.

That could be fixed by ditching the extra() call and creating the proper internal ORM structure. That requires fiddling with the ORM though, which is not something I'd take lightly. I did manage to build a proof of concept though, so if it can be confined to a small and well documented case, it might be worth it.

In any case, when performing requests where you know you don't need translations, use the GeonamesCity.objects.untranslated() method. It will be (slightly) faster.

@jmalinens
Copy link
Author

thanks for suggestions!

spectras added a commit to spectras/django-hvad that referenced this issue Jul 13, 2015
…() filter. Will not break if Django decides to relabel tables. Fixes KristianOellegaard#250.
spectras added a commit to spectras/django-hvad that referenced this issue Jul 13, 2015
…() filter. Will not break if Django decides to relabel tables. Fixes KristianOellegaard#250.
spectras added a commit to spectras/django-hvad that referenced this issue Jul 13, 2015
…() filter. Will not break if Django decides to relabel tables. Fixes KristianOellegaard#250.
@spectras spectras added this to the v1.3.0 milestone Jul 13, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants