Esempio n. 1
0
 def test_mixed_query_chained_explicit_implicit_joins(self):
     query = Query()
     query.tables.extend(['"product_product"', '"product_template"'])
     query.where_clause.append(
         "product_product.template_id = product_template.id")
     query.add_join(("product_template", "product_category", "categ_id",
                     "id", "categ_id"),
                    implicit=False,
                    outer=False)  # add normal join
     query.add_join(("product_template__categ_id", "res_user", "user_id",
                     "id", "user_id"),
                    implicit=False,
                    outer=True)  # CHAINED outer join
     query.tables.append('"account.account"')
     query.where_clause.append(
         "product_category.expense_account_id = account_account.id"
     )  # additional implicit join
     self.assertEquals(
         query.get_sql()[0].strip(),
         """"product_product","product_template" JOIN "product_category" as "product_template__categ_id" ON ("product_template"."categ_id" = "product_template__categ_id"."id") LEFT JOIN "res_user" as "product_template__categ_id__user_id" ON ("product_template__categ_id"."user_id" = "product_template__categ_id__user_id"."id"),"account.account" """
         .strip())
     self.assertEquals(
         query.get_sql()[1].strip(),
         """product_product.template_id = product_template.id AND product_category.expense_account_id = account_account.id"""
         .strip())
Esempio n. 2
0
 def test_query_chained_explicit_joins(self):
     query = Query()
     query.tables.extend(['"product_product"', '"product_template"'])
     query.where_clause.append("product_product.template_id = product_template.id")
     query.add_join(("product_template", "product_category", "categ_id", "id", "categ_id"), implicit=False, outer=False)  # add normal join
     query.add_join(("product_template__categ_id", "res_user", "user_id", "id", "user_id"), implicit=False, outer=True)  # CHAINED outer join
     self.assertEquals(query.get_sql()[0].strip(),
         """"product_product","product_template" JOIN "product_category" as "product_template__categ_id" ON ("product_template"."categ_id" = "product_template__categ_id"."id") LEFT JOIN "res_user" as "product_template__categ_id__user_id" ON ("product_template__categ_id"."user_id" = "product_template__categ_id__user_id"."id")""".strip())
     self.assertEquals(query.get_sql()[1].strip(), """product_product.template_id = product_template.id""".strip())
Esempio n. 3
0
 def test_basic_query(self):
     query = Query()
     query.tables.extend(['"product_product"', '"product_template"'])
     query.where_clause.append("product_product.template_id = product_template.id")
     query.add_join(("product_template", "product_category", "categ_id", "id", "categ_id"), implicit=False, outer=False)  # add normal join
     query.add_join(("product_product", "res_user", "user_id", "id", "user_id"), implicit=False, outer=True)  # outer join
     self.assertEquals(query.get_sql()[0].strip(),
         """"product_product" LEFT JOIN "res_user" as "product_product__user_id" ON ("product_product"."user_id" = "product_product__user_id"."id"),"product_template" JOIN "product_category" as "product_template__categ_id" ON ("product_template"."categ_id" = "product_template__categ_id"."id") """.strip())
     self.assertEquals(query.get_sql()[1].strip(), """product_product.template_id = product_template.id""".strip())
Esempio n. 4
0
    def _compute_application_count(self):
        self.flush(fnames=['email_from'])
        # Filter and gather emails at the same time
        applicants = self.env['hr.applicant']
        mails = set()
        for applicant in self:
            if applicant.email_from:
                applicants |= applicant
                mails.add(applicant.email_from.lower())
        # Done via SQL since read_group does not support grouping by lowercase field
        if mails:
            query = Query(self.env.cr, self._table, self._table_query)
            query.add_where('LOWER("hr_applicant".email_from) in %s', [tuple(mails)])
            self._apply_ir_rules(query)
            from_clause, where_clause, where_clause_params = query.get_sql()
            query_str = """
            SELECT LOWER("%(table)s".email_from) as l_email_from,
                COUNT("%(table)s".id) as count
            FROM %(from)s
            %(where)s
        GROUP BY l_email_from
            """ % {
                'table': self._table,
                'from': from_clause,
                'where': ('WHERE %s' % where_clause) if where_clause else '',
            }
            self.env.cr.execute(query_str, where_clause_params)

            application_data_mapped = dict((data['l_email_from'], data['count']) for data in self.env.cr.dictfetchall())
        else:
            application_data_mapped = dict()
        for applicant in applicants:
            applicant.application_count = application_data_mapped.get(applicant.email_from.lower(), 1)
        (self - applicants).application_count = False
Esempio n. 5
0
    def test_mixed_query_chained_explicit_implicit_joins(self):
        query = Query(None, 'product_product')
        query.add_table('product_template')
        query.add_where("product_product.template_id = product_template.id")
        # add inner join
        alias = query.join("product_template", "categ_id", "product_category",
                           "id", "categ_id")
        self.assertEqual(alias, 'product_template__categ_id')
        # add CHAINED left join
        alias = query.left_join("product_template__categ_id", "user_id",
                                "res_user", "id", "user_id")
        self.assertEqual(alias, 'product_template__categ_id__user_id')
        # additional implicit join
        query.add_table('account.account')
        query.add_where(
            "product_category.expense_account_id = account_account.id")

        from_clause, where_clause, where_params = query.get_sql()
        self.assertEqual(
            from_clause,
            '"product_product", "product_template", "account.account" JOIN "product_category" AS "product_template__categ_id" ON ("product_template"."categ_id" = "product_template__categ_id"."id") LEFT JOIN "res_user" AS "product_template__categ_id__user_id" ON ("product_template__categ_id"."user_id" = "product_template__categ_id__user_id"."id")'
        )
        self.assertEqual(
            where_clause,
            "product_product.template_id = product_template.id AND product_category.expense_account_id = account_account.id"
        )
Esempio n. 6
0
    def _search_is_authorized(self, operator, value):
        if operator not in ('=', '!=', '<>'):
            raise ValueError('Invalid operator: %s' % (operator, ))

        SS = self.env['sale.subscription']
        tbls = (self._table, SS._table)
        query = Query(tbls,
                      ["%s.subscription_template_id = %s.template_id" % tbls],
                      [])
        SS._apply_ir_rules(query)

        from_clause, where_clause, where_clause_params = query.get_sql()

        self.env.cr.execute(
            """
            SELECT {self}.id
              FROM {from_}
             WHERE {where}
        """.format(self=self._table, from_=from_clause, where=where_clause),
            where_clause_params)
        ids = [i[0] for i in self.env.cr.fetchall()]

        op = 'in' if (operator == '=' and value) or (
            operator != '=' and not value) else 'not in'
        return [('id', op, ids)]
Esempio n. 7
0
    def test_table_expression(self):
        query = Query(None, 'foo')
        from_clause, where_clause, where_params = query.get_sql()
        self.assertEqual(from_clause, '"foo"')

        query = Query(None, 'bar', 'SELECT id FROM foo')
        from_clause, where_clause, where_params = query.get_sql()
        self.assertEqual(from_clause, '(SELECT id FROM foo) AS "bar"')

        query = Query(None, 'foo')
        query.add_table('bar', 'SELECT id FROM foo')
        from_clause, where_clause, where_params = query.get_sql()
        self.assertEqual(from_clause, '"foo", (SELECT id FROM foo) AS "bar"')

        query = Query(None, 'foo')
        query.join('foo', 'bar_id', 'SELECT id FROM foo', 'id', 'bar')
        from_clause, where_clause, where_params = query.get_sql()
        self.assertEqual(
            from_clause,
            '"foo" JOIN (SELECT id FROM foo) AS "foo__bar" ON ("foo"."bar_id" = "foo__bar"."id")'
        )
Esempio n. 8
0
 def test_query_chained_explicit_joins(self):
     query = Query()
     query.add_table('product_product')
     query.add_table('product_template')
     query.where_clause.append(
         "product_product.template_id = product_template.id")
     query.add_join(("product_template", "product_category", "categ_id",
                     "id", "categ_id"),
                    implicit=False,
                    outer=False)  # add normal join
     query.add_join(("product_template__categ_id", "res_user", "user_id",
                     "id", "user_id"),
                    implicit=False,
                    outer=True)  # CHAINED outer join
     self.assertEqual(
         query.get_sql()[0].strip(),
         """"product_product","product_template" JOIN "product_category" as "product_template__categ_id" ON ("product_template"."categ_id" = "product_template__categ_id"."id") LEFT JOIN "res_user" as "product_template__categ_id__user_id" ON ("product_template__categ_id"."user_id" = "product_template__categ_id__user_id"."id")"""
         .strip())
     self.assertEqual(
         query.get_sql()[1].strip(),
         """product_product.template_id = product_template.id""".strip())
Esempio n. 9
0
    def test_basic_query(self):
        query = Query(None, 'product_product')
        query.add_table('product_template')
        query.add_where("product_product.template_id = product_template.id")
        # add inner join
        alias = query.join("product_template", "categ_id", "product_category",
                           "id", "categ_id")
        self.assertEqual(alias, 'product_template__categ_id')
        # add left join
        alias = query.left_join("product_product", "user_id", "res_user", "id",
                                "user_id")
        self.assertEqual(alias, 'product_product__user_id')

        from_clause, where_clause, where_params = query.get_sql()
        self.assertEqual(
            from_clause,
            '"product_product", "product_template" JOIN "product_category" AS "product_template__categ_id" ON ("product_template"."categ_id" = "product_template__categ_id"."id") LEFT JOIN "res_user" AS "product_product__user_id" ON ("product_product"."user_id" = "product_product__user_id"."id")'
        )
        self.assertEqual(where_clause,
                         "product_product.template_id = product_template.id")
Esempio n. 10
0
 def _compute_application_count(self):
     self.flush_model(['email_from'])
     applicants = self.env['hr.applicant']
     for applicant in self:
         if applicant.email_from or applicant.partner_phone or applicant.partner_mobile:
             applicants |= applicant
     # Done via SQL since read_group does not support grouping by lowercase field
     if applicants.ids:
         query = Query(self.env.cr, self._table, self._table_query)
         query.add_where('hr_applicant.id in %s', [tuple(applicants.ids)])
         # Count into the companies that are selected from the multi-company widget
         company_ids = self.env.context.get('allowed_company_ids')
         if company_ids:
             query.add_where('other.company_id in %s', [tuple(company_ids)])
         self._apply_ir_rules(query)
         from_clause, where_clause, where_clause_params = query.get_sql()
         # In case the applicant phone or mobile is configured in wrong field
         query_str = """
         SELECT hr_applicant.id as appl_id,
             COUNT(other.id) as count
           FROM hr_applicant
           JOIN hr_applicant other ON LOWER(other.email_from) = LOWER(hr_applicant.email_from)
             OR other.partner_phone = hr_applicant.partner_phone OR other.partner_phone = hr_applicant.partner_mobile
             OR other.partner_mobile = hr_applicant.partner_mobile OR other.partner_mobile = hr_applicant.partner_phone
         %(where)s
     GROUP BY hr_applicant.id
         """ % {
             'where': ('WHERE %s' % where_clause) if where_clause else '',
         }
         self.env.cr.execute(query_str, where_clause_params)
         application_data_mapped = dict(
             (data['appl_id'], data['count'])
             for data in self.env.cr.dictfetchall())
     else:
         application_data_mapped = dict()
     for applicant in applicants:
         applicant.application_count = application_data_mapped.get(
             applicant.id, 1) - 1
     (self - applicants).application_count = False
Esempio n. 11
0
        def _read_from_database(self, field_names, inherited_field_names=[]):
            """ Read the given fields of the records in ``self`` from the database,
                and store them in cache. Access errors are also stored in cache.

                :param field_names: list of column names of model ``self``; all those
                    fields are guaranteed to be read
                :param inherited_field_names: list of column names from parent
                    models; some of those fields may not be read
            """
            if not self:
                return

            env = self.env
            cr, user, context = env.args

            # make a query object for selecting ids, and apply security rules to it
            param_ids = object()
            query = Query(['"%s"' % self._table],
                          ['"%s".id IN %%s' % self._table], [param_ids])
            self._apply_ir_rules(query, 'read')

            # determine the fields that are stored as columns in tables; ignore 'id'
            fields_pre = [
                field
                for field in (self._fields[name]
                              for name in field_names + inherited_field_names)
                if field.name != 'id'
                if field.base_field.store and field.base_field.column_type
                if not (
                    field.inherited and callable(field.base_field.translate))
            ]

            # the query may involve several tables: we need fully-qualified names
            def qualify(field):
                col = field.name
                res = self._inherits_join_calc(self._table, field.name, query)
                if field.type == 'binary' and (context.get('bin_size') or
                                               context.get('bin_size_' + col)):
                    # PG 9.2 introduces conflicting pg_size_pretty(numeric) -> need ::cast
                    res = 'pg_size_pretty(length(%s)::bigint)' % res
                return '%s as "%s"' % (res, col)

            qual_names = [
                qualify(name) for name in [self._fields['id']] + fields_pre
            ]

            # determine the actual query to execute
            from_clause, where_clause, params = query.get_sql()
            query_str = "SELECT %s FROM %s WHERE %s" % (
                ",".join(qual_names), from_clause, where_clause)

            result = []
            param_pos = params.index(param_ids)
            for sub_ids in cr.split_for_in_conditions(self.ids):
                params[param_pos] = tuple(sub_ids)
                cr.execute(query_str, params)
                result.extend(cr.dictfetchall())

            ids = [vals['id'] for vals in result]
            fetched = self.browse(ids)

            if ids:
                # translate the fields if necessary
                if context.get('lang'):
                    for field in fields_pre:
                        if not field.inherited and callable(field.translate):
                            name = field.name
                            translate = field.get_trans_func(fetched)
                            for vals in result:
                                vals[name] = translate(vals['id'], vals[name])

                # store result in cache
                for vals in result:
                    record = self.browse(vals.pop('id'), self._prefetch)
                    record._cache.update(
                        record._convert_to_cache(vals, validate=False))

                # determine the fields that must be processed now;
                # for the sake of simplicity, we ignore inherited fields
                for name in field_names:
                    field = self._fields[name]
                    if not field.column_type:
                        field.read(fetched)

            # Warn about deprecated fields now that fields_pre and fields_post are computed
            for name in field_names:
                field = self._fields[name]
                if field.deprecated:
                    _logger.warning('Field %s is deprecated: %s', field,
                                    field.deprecated)

            # store failed values in cache for the records that could not be read
            missing = self - fetched
            if missing:
                extras = fetched - self
                if extras:
                    raise AccessError(
                        _("Database fetch misses ids ({}) and has extra ids ({}), may be caused by a type incoherence in a previous request"
                          ).format(
                              missing._ids,
                              extras._ids,
                          ))
                # mark non-existing records in missing
                forbidden = missing.exists()
                if forbidden:
                    _logger.info(
                        _('The requested operation cannot be completed due to record rules: Document type: %s, Operation: %s, Records: %s, User: %s') % \
                        (self._name, 'read', ','.join([str(r.id) for r in self][:6]), self._uid))
                    # store an access error exception in existing records
                    exc = AccessError(
                        # _('The requested operation cannot be completed due to security restrictions. Please contact your system administrator.\n\n(Document type: %s, Operation: %s)') % \
                        # (self._name, 'read')
                        # Modificación del mensaje de error: José Candelas
                        _('The requested operation cannot be completed due to security restrictions. Please contact your system administrator.\n\n(Document type: %s, Operation: %s, Forbidden: %s)') % \
                        (self._name, 'read', forbidden)
                    )
                    self.env.cache.set_failed(forbidden, self._fields.values(),
                                              exc)