<commit_before>"""
Django-multilingual: a QuerySet subclass for models with translatable fields.
"""
from copy import deepcopy

from django.db.models.query import QuerySet
from django.db.models.sql.query import Query
from django.db.models.sql.where import AND

from multilingual.languages import get_translation_table_alias, get_translated_field_alias, get_default_language, \
    get_language_code_list


__ALL__ = ['MultilingualModelQuerySet']


class MultilingualQuery(Query):
    def setup_joins(self, names, opts, alias, dupe_multis, allow_many=True,
            allow_explicit_fk=False, can_reuse=None, negate=False,
            process_extras=True):
        """
        This overrides setup_joins method in case we want to join multilingual field.
        This is hell good place to rewrite something because it is called for every time when we care.
        """
        trans_opts = opts.translation_model._meta
        # So far we only handle fields that are local for TranslationModel (not related)
        # so we can only take care of first of names, see NotImplementedError lower
        field_name = names[0]
        field_and_lang = trans_opts.translated_fields.get(field_name)

        # Field is not multilingual, proceed as usual
        if not field_and_lang:
            return super(MultilingualQuery, self).setup_joins(names, opts, alias, dupe_multis, allow_many,
                                                              allow_explicit_fk, can_reuse, negate, process_extras)

        if len(names) > 1:
            raise NotImplementedError('MultilingualQuery can not now handle relations through multilingual fields')

        field, language_code = field_and_lang
        if language_code is None:
            language_code = get_default_language()
        trans_table_name = trans_opts.db_table
        table_alias = get_translation_table_alias(trans_table_name, language_code)

        # Exclude table aliases for other languages to prevent language mismatch
        # TEST: filter(name_en="some", name_cs="neco")
        exclusions = set(self.table_map.get(trans_table_name, [])) - set([table_alias])

        # Enable reusing of translation table alias for required language so translations for one language are
        # added only once
        # TEST: filter(name_en="some").values('name_en')
        reuse = can_reuse or set()
        reuse.add(table_alias)

        # Important step 1: join translation table under language-specific alias
        # QUESTION: is LEFT OUTER JOIN always required?
        # HACK: this is hell of a hack, but it is only way that django enables for extra joins now :-(
        #       Still hopes, that it will get better someday and there will be correct way how add condition into join
        right_column = '"master_id" AND \'%s\' = "%s"."language_code"' % (language_code, table_alias)
        trans_alias = self.join((alias, trans_table_name, opts.pk.column, right_column), always_create=True,
                        reuse=reuse, exclusions=exclusions, promote=True, nullable=True)

        # Important step 2: if required alias has not been defined yet, new alias is created in during join
        # We change the alias to language-specific alias, so we can check whether it is already present
        if trans_alias != table_alias:
            self.change_aliases({trans_alias: table_alias})
<commit_msg>Quick fix of main HACK, so queries with joins to multilingual tables work in MySQL. Proper fix is still needed.<commit_after>"""
Django-multilingual: a QuerySet subclass for models with translatable fields.
"""
from copy import deepcopy

from django.db import connection
from django.db.models.query import QuerySet
from django.db.models.sql.query import Query
from django.db.models.sql.where import AND

from multilingual.languages import get_translation_table_alias, get_translated_field_alias, get_default_language, \
    get_language_code_list


__ALL__ = ['MultilingualModelQuerySet']


class MultilingualQuery(Query):
    def setup_joins(self, names, opts, alias, dupe_multis, allow_many=True,
            allow_explicit_fk=False, can_reuse=None, negate=False,
            process_extras=True):
        """
        This overrides setup_joins method in case we want to join multilingual field.
        This is hell good place to rewrite something because it is called for every time when we care.
        """
        trans_opts = opts.translation_model._meta
        # So far we only handle fields that are local for TranslationModel (not related)
        # so we can only take care of first of names, see NotImplementedError lower
        field_name = names[0]
        field_and_lang = trans_opts.translated_fields.get(field_name)

        # Field is not multilingual, proceed as usual
        if not field_and_lang:
            return super(MultilingualQuery, self).setup_joins(names, opts, alias, dupe_multis, allow_many,
                                                              allow_explicit_fk, can_reuse, negate, process_extras)

        if len(names) > 1:
            raise NotImplementedError('MultilingualQuery can not now handle relations through multilingual fields')

        field, language_code = field_and_lang
        if language_code is None:
            language_code = get_default_language()
        trans_table_name = trans_opts.db_table
        table_alias = get_translation_table_alias(trans_table_name, language_code)

        # Exclude table aliases for other languages to prevent language mismatch
        # TEST: filter(name_en="some", name_cs="neco")
        exclusions = set(self.table_map.get(trans_table_name, [])) - set([table_alias])

        # Enable reusing of translation table alias for required language so translations for one language are
        # added only once
        # TEST: filter(name_en="some").values('name_en')
        reuse = can_reuse or set()
        reuse.add(table_alias)

        # Important step 1: join translation table under language-specific alias
        # QUESTION: is LEFT OUTER JOIN always required?
        # HACK: this is hell of a hack, but it is only way that django enables for extra joins now :-(
        #       Still hopes, that it will get better someday and there will be correct way how add condition into join
        # XXX: did not work in MySQL, so take quoting from default database until correctly fixed
        qn = connection.ops.quote_name
        right_column = '%s AND \'%s\' = %s.%s' % (
                            qn('master_id'),
                            language_code,
                            table_alias, # do not quote, it is alias
                            qn('language_code')
                       )
        trans_alias = self.join((alias, trans_table_name, opts.pk.column, right_column), always_create=True,
                        reuse=reuse, exclusions=exclusions, promote=True, nullable=True)

        # Important step 2: if required alias has not been defined yet, new alias is created in during join
        # We change the alias to language-specific alias, so we can check whether it is already present
        if trans_alias != table_alias:
            self.change_aliases({trans_alias: table_alias})

{'fraction_non_alphanumeric': 0.0669165625433847, 'fraction_numerical': 0.0011106483409690406, 'mean_word_length': 2.840085287846482, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6679698', 'n_tokens_mistral': 1955, 'n_tokens_neox': 1866, 'n_words': 666}