[IMP] unaccent: support for the postgres unaccent contrib module.

OpenERP is now able to use the SQL unaccent() function when available,
and when the server is run with the --unaccent flag.

bzr revid: vmt@openerp.com-20110811110118-cyx2l6c3wk58083p
This commit is contained in:
Vo Minh Thu 2011-08-11 13:01:18 +02:00
parent d462db158e
commit 6251434cb9
4 changed files with 78 additions and 7 deletions

View File

@ -435,6 +435,23 @@
domain = [('x','in',['y','z']),('a.v','=','e'),'|','|',('a','=','b'),'!',('c','>','d'),('e','!=','f'),('g','=','h')]
norm_domain = ['&','&','&'] + domain
assert norm_domain == expression.normalize(domain), "Non-normalized domains should be properly normalized"
-
Unaccent. Create a company with an accent in its name.
-
!record {model: res.company, id: ymltest_unaccent_company}:
name: Hélène
-
Test the unaccent-enabled 'ilike'.
-
!python {model: res.company}: |
if self.pool.has_unaccent:
ids = self.search(cr, uid, [('name','ilike','Helene')], {})
assert ids == [ref('ymltest_unaccent_company')]
ids = self.search(cr, uid, [('name','ilike','hélène')], {})
assert ids == [ref('ymltest_unaccent_company')]
ids = self.search(cr, uid, [('name','not ilike','Helene')], {})
assert ref('ymltest_unaccent_company') not in ids
ids = self.search(cr, uid, [('name','not ilike','hélène')], {})
assert ref('ymltest_unaccent_company') not in ids

View File

@ -23,10 +23,12 @@
"""
import logging
import openerp.sql_db
import openerp.osv.orm
import openerp.modules.db
import openerp.tools.config
class Registry(object):
""" Model registry for a particular database.
@ -46,7 +48,11 @@ class Registry(object):
self.db = openerp.sql_db.db_connect(db_name)
cr = self.db.cursor()
self.has_unaccent = openerp.modules.db.has_unaccent(cr)
has_unaccent = openerp.modules.db.has_unaccent(cr)
if openerp.tools.config['unaccent'] and not has_unaccent:
logger = logging.getLogger('unaccent')
logger.warning("The option --unaccent was given but no unaccent() function was found in database.")
self.has_unaccent = openerp.tools.config['unaccent'] and has_unaccent
cr.close()
def do_parent_store(self, cr):

View File

@ -72,6 +72,47 @@ That is, a domain could be a valid operand. But this is not the case. A domain
is really limited to a two-level nature, and can not takes a recursive form: a
domain is not a valid second-level operand.
Unaccent - Accent-insensitive search
OpenERP will use the SQL function 'unaccent' when available for the 'ilike' and
'not ilike' operators. Normally the 'unaccent' function is obtained from the
PostgreSQL 'unaccent' contrib module[0]. The steps to install the module might
differ on specific PostgreSQL versions. We give here some instruction for
PostgreSQL 9.x on a Ubuntu system.
Ubuntu doesn't come yet with PostgreSQL 9.x, so an alternive package source
is used. We use Martin Pitt's PPA available at ppa:pitti/postgresql[1]. See
[2] for instructions. Basically:
> sudo add-apt-repository ppa:pitti/postgresql
> sudo apt-get update
Once the package list is up-to-date, you have to install PostgreSQL 9.0 and
its contrib modules.
> sudo apt-get install postgresql-9.0 postgresql-contrib-9.0
When you want to enable unaccent on some database:
> psql9 <database> -f /usr/share/postgresql/9.0/contrib/unaccent.sql
Here 'psql9' is an alias for the newly installed PostgreSQL 9.0 tool, together
with the correct port if necessary (for instance if PostgreSQL 8.4 is running
on 5432). (Other aliases can be used for createdb and dropdb.)
> alias psql9='/usr/lib/postgresql/9.0/bin/psql -p 5433'
You can check unaccent is working:
> psql9 <database> -c"select unaccent('hélène')"
Finally, to instruct OpenERP to really use the unaccent function, you have to
start the server specifying the --unaccent flag.
[0] http://developer.postgresql.org/pgdocs/postgres/unaccent.html
[1] https://launchpad.net/~pitti/+archive/postgresql
[2] https://launchpad.net/+help/soyuz/ppa-sources-list.html
"""
import logging
@ -82,6 +123,7 @@ import openerp.modules
#.apidoc title: Domain Expressions
# Domain operators.
NOT_OPERATOR = '!'
OR_OPERATOR = '|'
AND_OPERATOR = '&'
@ -678,9 +720,15 @@ class expression(object):
op = {'=like':'like','=ilike':'ilike'}.get(operator, operator)
if left in table._columns:
format = like and '%s' or table._columns[left]._symbol_set[0]
query = '(%s.%s %s %s)' % (table._table, left, op, format)
if self.has_unaccent and op in ('ilike', 'not ilike'):
query = '(unaccent(%s.%s) %s unaccent(%s))' % (table._table, left, op, format)
else:
query = '(%s.%s %s %s)' % (table._table, left, op, format)
else:
query = "(%s.%s %s '%s')" % (table._table, left, op, right)
if self.has_unaccent and op in ('ilike', 'not ilike'):
query = "(unaccent(%s.%s) %s unaccent('%s'))" % (table._table, left, op, right)
else:
query = "(%s.%s %s '%s')" % (table._table, left, op, right)
add_null = False
if like:

View File

@ -250,7 +250,7 @@ class configmanager(object):
"osv_memory tables. This is a decimal value expressed in hours, "
"and the default is 1 hour.",
type="float")
group.add_option("--unaccent", dest="unaccent", my_default=False,
group.add_option("--unaccent", dest="unaccent", my_default=False, action="store_true",
help="Use the unaccent function provided by the database when available.")
parser.add_option_group(group)
@ -337,7 +337,7 @@ class configmanager(object):
'stop_after_init', 'logrotate', 'without_demo', 'netrpc', 'xmlrpc', 'syslog',
'list_db', 'xmlrpcs',
'test_file', 'test_disable', 'test_commit', 'test_report_directory',
'osv_memory_count_limit', 'osv_memory_age_limit',
'osv_memory_count_limit', 'osv_memory_age_limit', 'unaccent',
]
for arg in keys: