Commit aac3b08b authored by Julien Muchembled's avatar Julien Muchembled

ZSQLCatalog: optimize rendering of values

parent a162f0a5
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
############################################################################## ##############################################################################
from zLOG import LOG from zLOG import LOG
from DateTime import DateTime
from Products.ZSQLCatalog.interfaces.operator import IOperator from Products.ZSQLCatalog.interfaces.operator import IOperator
from Products.ZSQLCatalog.Utils import sqlquote as escapeString from Products.ZSQLCatalog.Utils import sqlquote as escapeString
from zope.interface.verify import verifyClass from zope.interface.verify import verifyClass
...@@ -50,16 +51,18 @@ def valueNoneRenderer(value): ...@@ -50,16 +51,18 @@ def valueNoneRenderer(value):
return 'NULL' return 'NULL'
value_renderer = { value_renderer = {
'int': str, int: str,
'long': str, long: str,
'float': valueFloatRenderer, float: valueFloatRenderer,
'DateTime': valueDateTimeRenderer, DateTime: valueDateTimeRenderer,
'NoneType': valueNoneRenderer, None.__class__: valueNoneRenderer,
'bool': int, bool: int,
str: escapeString,
unicode: escapeString,
} }
value_search_text_renderer = { value_search_text_renderer = {
'DateTime': str, DateTime: str,
} }
def valueDefaultSearchTextRenderer(value): def valueDefaultSearchTextRenderer(value):
...@@ -111,7 +114,9 @@ class OperatorBase(object): ...@@ -111,7 +114,9 @@ class OperatorBase(object):
def getOperatorSearchText(self): def getOperatorSearchText(self):
return self.operator_search_text return self.operator_search_text
def _render(self, column, value): def _render(self, column, value,
value_renderer_get={k.__name__: v
for k, v in value_renderer.iteritems()}.get):
""" """
Render given column and value for use in SQL. Render given column and value for use in SQL.
Value is rendered to convert it to SQL-friendly value. Value is rendered to convert it to SQL-friendly value.
...@@ -125,26 +130,25 @@ class OperatorBase(object): ...@@ -125,26 +130,25 @@ class OperatorBase(object):
if isinstance(value, dict): if isinstance(value, dict):
type = value['type'] type = value['type']
column = column_renderer.get(type, columnDefaultRenderer)(column, format=value['format']) column = column_renderer.get(type, columnDefaultRenderer)(column, format=value['format'])
value = value_renderer.get(type, valueDefaultRenderer)(value['query']) value = value_renderer_get(type, valueDefaultRenderer)(value['query'])
else: else:
value = self._renderValue(value) value = self._renderValue(value)
return column, value return column, value
def _renderValue(self, value): def _renderValue(self, value,
value_renderer_get=value_renderer.get,
valueDefaultRenderer=valueDefaultRenderer):
""" """
Render given value as string. Render given value as string.
value (int, float, long, DateTime, string, None) value (int, float, long, DateTime, string, None)
Value to render as a string for use in SQL (quoted, escaped). Value to render as a string for use in SQL (quoted, escaped).
""" """
if isinstance(value, basestring): return value_renderer_get(value.__class__, valueDefaultRenderer)(value)
value = escapeString(value)
else:
value = value_renderer.get(value.__class__.__name__, valueDefaultRenderer)(value)
return value
def asSearchText(self, value): def asSearchText(self, value):
return value_search_text_renderer.get(value.__class__.__name__, valueDefaultSearchTextRenderer)(value) return value_search_text_renderer.get(value.__class__,
valueDefaultSearchTextRenderer)(value)
def asSQLExpression(self, column, value_list, only_group_columns): def asSQLExpression(self, column, value_list, only_group_columns):
raise NotImplementedError, 'This method must be overloaded by a subclass ' \ raise NotImplementedError, 'This method must be overloaded by a subclass ' \
......
  • I see you committed profiler-related stuff before this. Was this code a hot-spot ? How much improvement can we expect ?

  • For SQL queries with a condition on many security_uids, you can certainly get measurable improvement. In my case, I am trying to optimize a request that took ~20 seconds with cProfile enabled, calling OperatorBase._renderValue 243266 times: 7.22% of total time, 4.7% self. With this commit, total time is now 4.01%, 2.89 self.

    Unfortunately, the instance runs on a CPU whose speed is so unstable that I can't give better stats (even % above should be taken with care). On a unit test instance with much fewer security_uid, speed up is less significant (about 1%).

Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment