summaryrefslogtreecommitdiff
path: root/openerp/sql_db.py
diff options
context:
space:
mode:
authorRaphael Collet <rco@openerp.com>2016-01-27 18:00:48 +0100
committerRaphael Collet <rco@openerp.com>2016-01-29 09:37:27 +0100
commitf0646cb51b236a3afd5e7289f5cd5986c88da8f6 (patch)
tree0358c6bbcdba40ef316d7094389f106ae1753b7d /openerp/sql_db.py
parent6f4e7867f0a005b7588e16160765e23036ce7abc (diff)
[IMP] fields: use a "lazy" cursor to compute attribute `digits`
Borrowing a cursor each time you access `field.digits` may be costly, because of the connection reset. Moreover, in most cases, the cursor is not used at all, since the decimal precision are kept in cache. For the installation of module `product` with its demo data, the number of cursor allocations was reduced from ~1500 to about 50!
Diffstat (limited to 'openerp/sql_db.py')
-rw-r--r--openerp/sql_db.py34
1 files changed, 34 insertions, 0 deletions
diff --git a/openerp/sql_db.py b/openerp/sql_db.py
index f389a847548..a3af4be677a 100644
--- a/openerp/sql_db.py
+++ b/openerp/sql_db.py
@@ -443,6 +443,40 @@ class TestCursor(Cursor):
self.execute("ROLLBACK TO SAVEPOINT test_cursor")
self.execute("SAVEPOINT test_cursor")
+class LazyCursor(object):
+ """ A proxy object to a cursor. The cursor itself is allocated only if it is
+ needed. This class is useful for cached methods, that use the cursor
+ only in the case of a cache miss.
+ """
+ def __init__(self, dbname=None):
+ self._dbname = dbname
+ self._cursor = None
+ self._depth = 0
+
+ @property
+ def dbname(self):
+ return self._dbname or threading.currentThread().dbname
+
+ def __getattr__(self, name):
+ cr = self._cursor
+ if cr is None:
+ from openerp import registry
+ cr = self._cursor = registry(self.dbname).cursor()
+ for _ in xrange(self._depth):
+ cr.__enter__()
+ return getattr(cr, name)
+
+ def __enter__(self):
+ self._depth += 1
+ if self._cursor is not None:
+ self._cursor.__enter__()
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ self._depth -= 1
+ if self._cursor is not None:
+ self._cursor.__exit__(exc_type, exc_value, traceback)
+
class PsycoConnection(psycopg2.extensions.connection):
pass