Commit cf53db45 authored by Aurel's avatar Aurel

Implement cache of getInventory results

Create a sql cache for getInventory call
Remove full-inventory optimisation as it now useless
Implement full-inventory feature directly into stock
Make erp5_pdm depends on this optimisation
Install optimisation for all unit tests
parent 3f484980
<catalog_method>
<item key="sql_catalog_object_list" type="int">
<value>1</value>
</item>
</catalog_method>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="SQL" module="Products.ZSQLMethods.SQL"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>arguments_src</string> </key>
<value> <string>isInventory\r\n
uid\r\n
getDestinationUid\r\n
getDestinationSectionUid\r\n
getDestinationPaymentUid\r\n
getStartDate\r\n
isFullInventory\r\n
getSimulationState</string> </value>
</item>
<item>
<key> <string>connection_id</string> </key>
<value> <string>erp5_sql_connection</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>z_catalog_inventory_list</string> </value>
</item>
<item>
<key> <string>src</string> </key>
<value> <string encoding="cdata"><![CDATA[
<dtml-let row_list="[]">\n
\n
<dtml-in prefix="loop" expr="_.range(_.len(uid))">\n
<dtml-if expr="isInventory[loop_item]">\n
<dtml-if expr="getStartDate[loop_item] is not None">\n
<dtml-call expr="row_list.append((\n
uid[loop_item],\n
getDestinationUid[loop_item],\n
getDestinationSectionUid[loop_item],\n
getDestinationPaymentUid[loop_item],\n
getStartDate[loop_item],\n
isFullInventory[loop_item],\n
getSimulationState[loop_item]))">\n
</dtml-if>\n
</dtml-if>\n
</dtml-in>\n
\n
<dtml-if expr="len(row_list)">\n
REPLACE INTO\n
inventory\n
(`uid`, `node_uid`, `section_uid`, `payment_uid`, `date`, `is_full_inventory`, `simulation_state`)\n
VALUES\n
<dtml-in prefix="row" expr="row_list">\n
(<dtml-sqlvar expr="row_item[0]" type="int">,\n
<dtml-sqlvar expr="row_item[1]" type="int" optional>,\n
<dtml-sqlvar expr="row_item[2]" type="int" optional>,\n
<dtml-sqlvar expr="row_item[3]" type="int" optional>,\n
<dtml-sqlvar expr="row_item[4]" type="datetime">,\n
<dtml-sqlvar expr="row_item[5] or 0" type="int">,\n
<dtml-sqlvar expr="row_item[6]" type="string">\n
)<dtml-if sequence-end><dtml-else>,</dtml-if>\n
</dtml-in>\n
</dtml-if>\n
</dtml-let>
]]></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
erp5_base
\ No newline at end of file
erp5_base
erp5_stock_cache
571
\ No newline at end of file
573
\ No newline at end of file
erp5_base
\ No newline at end of file
erp5_base
......@@ -6,7 +6,7 @@
<value>1</value>
</item>
<item key="_filter_expression_archive" type="str">
<value>python: context.providesIMovement() and context.isInventoryMovement()</value>
<value>python: context.providesIMovement() and not context.isInventoryMovement()</value>
</item>
<item key="_filter_expression_cache_key_archive" type="tuple">
<value>portal_type</value>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>from Products.ERP5Type.Errors import ProgrammingError\n
\n
min_date = None\n
for loop_item in xrange(len(uid)):\n
if not isInventoryMovement[loop_item] and isMovement[loop_item] and getResourceUid[loop_item]:\n
if getDestinationUid[loop_item] and getStopDate[loop_item]:\n
if min_date:\n
min_date = min(min_date, getStopDate[loop_item])\n
else:\n
min_date = getStopDate[loop_item]\n
if getSourceUid[loop_item] and getStartDate[loop_item]:\n
if min_date:\n
min_date = min(min_date, getStartDate[loop_item])\n
else:\n
min_date = getStartDate[loop_item]\n
if min_date:\n
try:\n
context.SimulationTool_zTrimInventoryCacheFromDateOnCatalog(date=min_date)\n
except ProgrammingError:\n
# Create table if it does not exits\n
# Then no need to flush an empty table\n
context.SimulationTool_zCreateInventoryCache()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>uid, isMovement, isInventoryMovement, getResourceUid, getDestinationUid, getStopDate, getSourceUid, getStartDate</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SQLCatalog_trimInventoryCacheOnCatalog</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>from Products.ERP5Type.Errors import ProgrammingError\n
\n
try:\n
context.SimulationTool_zTrimInventoryCacheFromDateOnUncatalog(uid=uid)\n
except ProgrammingError:\n
# Create table if it does not exits\n
# Then no need to flush an empty table\n
context.SimulationTool_zCreateInventoryCache()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>uid</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SQLCatalog_trimInventoryCacheOnUncatalog</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>erp5_stock_cache</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -6,14 +6,32 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>allow_simple_one_argument_traversal</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>arguments_src</string> </key>
<value> <string>column_value_list_list:list\r\n
column_id_list:list\r\n
group_by_expression\r\n
date\r\n
simulation_state=delivered\r\n
where_expression</string> </value>
<value> <string>query\r\n
date</string> </value>
</item>
<item>
<key> <string>cache_time_</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>class_file_</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>class_name_</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>connection_hook</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>connection_id</string> </key>
......@@ -21,39 +39,31 @@ where_expression</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Resource_zGetFullInventoryDate</string> </value>
<value> <string>Resource_zGetInventoryCacheResult</string> </value>
</item>
<item>
<key> <string>max_cache_</string> </key>
<value> <int>100</int> </value>
</item>
<item>
<key> <string>max_rows_</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>src</string> </key>
<value> <string encoding="cdata"><![CDATA[
SELECT\n
MAX(date) as date,\n
<dtml-var group_by_expression>\n
FROM\n
inventory\n
WHERE\n
is_full_inventory = TRUE\n
<dtml-if simulation_state>\n
AND simulation_state = <dtml-sqlvar simulation_state type="string">\n
</dtml-if>\n
<dtml-in prefix="loop" expr="_.range(_.len(column_id_list))">\n
AND <dtml-var expr="column_id_list[loop_item]"> IN (\n
<dtml-in expr="column_value_list_list[loop_item]">\n
<dtml-sqlvar sequence-item type="int">\n
<dtml-if sequence-end><dtml-else>,</dtml-if>\n
</dtml-in>\n
)\n
</dtml-in>\n
<dtml-if date>\n
AND date <= <dtml-sqlvar date type="string">\n
</dtml-if>\n
<dtml-if where_expression>\n
AND <dtml-var where_expression>\n
</dtml-if>\n
GROUP BY\n
<dtml-var group_by_expression>\n
SELECT \n
date, \n
result \n
FROM \n
inventory_cache \n
WHERE \n
inventory_cache.query=<dtml-sqlvar query type="string"> \n
AND \n
inventory_cache.date <= <dtml-sqlvar date type="datetime"> \n
ORDER BY \n
date DESC
]]></string> </value>
</item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="SQL" module="Products.ZSQLMethods.SQL"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>arguments_src</string> </key>
<value> <string>query\r\n
date\r\n
result</string> </value>
</item>
<item>
<key> <string>connection_id</string> </key>
<value> <string>erp5_sql_connection</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Resource_zInsertInventoryCacheResult</string> </value>
</item>
<item>
<key> <string>src</string> </key>
<value> <string encoding="cdata"><![CDATA[
Insert into inventory_cache(`query`, `date`, `result`) values (<dtml-sqlvar query type="string">, <dtml-sqlvar date type="datetime">, <dtml-sqlvar result type="string">)
]]></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string># XXX To be implemented\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SimulationTool_flushInventoryCache</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>"""\n
Returns a duration, in days, for stock cache management.\n
If data in stock cache is older than lag compared to query\'s date\n
(at_date or to_date), then it becomes a "soft miss": use found value,\n
but add a new entry to cache at query\'s date minus half the lag.\n
So this value should be:\n
- Small enough that few enough rows need to be table-scanned for\n
verage queries (probably queries against current date).\n
- Large enough that few enough documents get modified past that date,\n
therwise cache entries would be removed from cache all the time.\n
"""\n
\n
return 60\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SimulationTool_getInventoryCacheLag</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -16,11 +16,17 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>z0_drop_inventory</string> </value>
<value> <string>SimulationTool_zCreateInventoryCache</string> </value>
</item>
<item>
<key> <string>src</string> </key>
<value> <string>DROP TABLE IF EXISTS inventory</string> </value>
<value> <string>Create table `inventory_cache` (\n
`query` BINARY(16) NOT NULL,\n
`date` datetime NOT NULL,\n
`result` LONGBLOB NOT NULL,\n
PRIMARY KEY (`query`, `date`),\n
KEY (`date`)\n
) Engine=InnoDB</string> </value>
</item>
<item>
<key> <string>title</string> </key>
......
......@@ -6,6 +6,12 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_col</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>arguments_src</string> </key>
<value> <string></string> </value>
......@@ -16,11 +22,11 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>z0_drop_inventory_stock</string> </value>
<value> <string>SimulationTool_zDropInventoryCache</string> </value>
</item>
<item>
<key> <string>src</string> </key>
<value> <string>DROP TABLE IF EXISTS inventory_stock</string> </value>
<value> <string>DROP TABLE IF EXISTS inventory_cache</string> </value>
</item>
<item>
<key> <string>title</string> </key>
......
......@@ -8,7 +8,7 @@
<dictionary>
<item>
<key> <string>arguments_src</string> </key>
<value> <string>uid</string> </value>
<value> <string>date</string> </value>
</item>
<item>
<key> <string>connection_id</string> </key>
......@@ -16,13 +16,16 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>z0_uncatalog_inventory_stock</string> </value>
<value> <string>SimulationTool_zTrimInventoryCacheFromDateOnCatalog</string> </value>
</item>
<item>
<key> <string>src</string> </key>
<value> <string encoding="cdata"><![CDATA[
DELETE FROM inventory_stock WHERE <dtml-sqltest uid op=eq type=int>
DELETE FROM \n
inventory_cache \n
WHERE \n
date > <dtml-sqlvar expr="date" type="datetime">
]]></string> </value>
</item>
......
......@@ -16,13 +16,13 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>z0_uncatalog_inventory</string> </value>
<value> <string>SimulationTool_zTrimInventoryCacheFromDateOnUncatalog</string> </value>
</item>
<item>
<key> <string>src</string> </key>
<value> <string encoding="cdata"><![CDATA[
DELETE FROM inventory WHERE <dtml-sqltest uid op=eq type=int>
DELETE FROM inventory_cache WHERE date > (SELECT min(date) from stock where <dtml-sqltest uid op=eq type=int>)
]]></string> </value>
</item>
......
2013-02-05 Aurel
Initial version
\ No newline at end of file
Copyright (c) 2001-2013 Nexedi SA
\ No newline at end of file
erp5_core
\ No newline at end of file
This bt5 contains code to activate the stock caching optimisation
\ No newline at end of file
GPL
\ No newline at end of file
aurel
\ No newline at end of file
4
\ No newline at end of file
erp5_mysql_innodb/SQLCatalog_trimInventoryCacheOnCatalog
erp5_mysql_innodb/SQLCatalog_trimInventoryCacheOnUncatalog
\ No newline at end of file
erp5_stock_cache
\ No newline at end of file
erp5_stock_cache
\ No newline at end of file
1.0
\ No newline at end of file
......@@ -74,7 +74,7 @@ class Inventory(Delivery):
def appendToCategoryList(self, category_list, value, base_category):
category_list.append("%s/%s" %(base_category, value))
def splitAndExtendToCategoryList(self, category_list, value, *args, **kw):
if value is not None:
value_list = value.split('\n')
......@@ -101,16 +101,16 @@ class Inventory(Delivery):
# with not all properties defined and thus making
# request with no condition in mysql
object_list = [self]
immediate_reindex_archive = sql_catalog_id is not None
immediate_reindex_archive = sql_catalog_id is not None
self.portal_catalog.catalogObjectList(object_list,
sql_catalog_id = sql_catalog_id,
disable_archive=disable_archive,
immediate_reindex_archive=immediate_reindex_archive)
immediate_reindex_archive=immediate_reindex_archive)
return
connection_id = None
if sql_catalog_id is not None:
# try to get connection used in the catalog
# try to get connection used in the catalog
catalog = self.portal_catalog[sql_catalog_id]
for method in catalog.objectValues():
if method.meta_type == "Z SQL Method":
......@@ -139,10 +139,10 @@ class Inventory(Delivery):
},
)
method = self._getTypeBasedMethod('getDefaultInventoryCalculationList')
method = self._getTypeBasedMethod('getDefaultInventoryCalculationList')
if method is not None:
default_inventory_calculation_list = method()
if temp_constructor is None:
from Products.ERP5Type.Document import newTempMovement
......@@ -165,13 +165,11 @@ class Inventory(Delivery):
current_inventory_dict = {}
current_inventory_key_id_list = [x["key"] for x in inventory_calculation_dict['first_level']]
for line in current_inventory_list:
current_inventory_key = [line[x] for x in current_inventory_key_id_list]
for x in xrange(len(current_inventory_key)):
if current_inventory_key[x] is None:
current_inventory_key[x] = ""
current_inventory_key = tuple(current_inventory_key)
current_inventory_key = tuple(current_inventory_key)
if inventory_calculation_dict.has_key("second_level"):
# two level of variation
......@@ -189,10 +187,13 @@ class Inventory(Delivery):
current_inventory_dict[current_inventory_key] = line['total_quantity']
# Browse all movements on inventory and create diff line when necessary
not_used_inventory_dict = {}
if self.isFullInventory():
not_used_inventory_dict = current_inventory_dict
else:
not_used_inventory_dict = {}
inventory_id = self.getId()
list_method = inventory_calculation_dict['list_method']
method = getattr(self, list_method)
list_method = inventory_calculation_dict['list_method']
method = getattr(self, list_method)
for movement in method():
if movement.getResourceValue() is not None and \
movement.getInventoriatedQuantity() not in (None, ''):
......@@ -219,26 +220,26 @@ class Inventory(Delivery):
second_key_list = tuple(second_key_list)
if inventory_value.has_key(second_key_list):
total_quantity = inventory_value.pop(second_key_list)
# Put remaining subvariation in a dict to know which one
# Put remaining subvariation in a dict to know which one
# to removed at end
not_used_inventory_dict[tuple(key_list)] = inventory_value
diff_quantity = movement_quantity - total_quantity
else:
# Inventory for new resource/variation/sub_variation
diff_quantity = movement_quantity
# Put remaining subvariation in a dict to know which one
# Put remaining subvariation in a dict to know which one
# to removed at end
not_used_inventory_dict[tuple(key_list)] = inventory_value
else:
# we got the quantity from first level key
diff_quantity = movement_quantity - inventory_value
# Create tmp movement
kwd = {'uid': movement.getUid(),
'start_date': stop_date}
temp_delivery_line = temp_constructor(self,
inventory_id)
# set category on it only if quantity not null
# thus line with same uid will be deleted but we
# don't insert line with null quantity as we test
......@@ -246,7 +247,7 @@ class Inventory(Delivery):
# before insert but not before delete
if diff_quantity != 0:
kwd['quantity'] = diff_quantity
category_list = self.getCategoryList()
category_list = self.getCategoryList()
setter_list = [x['setter'] for x in inventory_calculation_dict['first_level']]
if inventory_calculation_dict.has_key("second_level"):
......@@ -267,13 +268,14 @@ class Inventory(Delivery):
temp_delivery_line.edit(**kwd)
stock_append(temp_delivery_line)
# Now create line to remove some subvariation text not present
# Now create line to remove some subvariation text not present
# in new inventory
if len(not_used_inventory_dict):
inventory_uid = self.getUid()
for first_level_key in not_used_inventory_dict.keys():
inventory_value = \
not_used_inventory_dict[tuple(first_level_key)]
# XXX-Aurel : this code does not work with only one level of variation
for second_level_key in inventory_value.keys():
diff_quantity = - inventory_value[tuple(second_level_key)]
......@@ -284,7 +286,7 @@ class Inventory(Delivery):
temp_delivery_line = temp_constructor(self,
inventory_id)
kwd['quantity'] = diff_quantity
category_list = self.getCategoryList()
category_list = self.getCategoryList()
setter_list = [x['setter'] for x in inventory_calculation_dict['first_level']]
if inventory_calculation_dict.has_key("second_level"):
......@@ -307,7 +309,7 @@ class Inventory(Delivery):
# Reindex objects
object_list = [self]
immediate_reindex_archive = sql_catalog_id is not None
immediate_reindex_archive = sql_catalog_id is not None
self.portal_catalog.catalogObjectList(object_list,
sql_catalog_id = sql_catalog_id,
disable_archive=disable_archive,
......
This diff is collapsed.
......@@ -15,9 +15,6 @@
<key>effective_date</key>
<key>expiration_date</key>
<key>grouping_date</key>
<key>inventory.date</key>
<key>inventory_stock.date</key>
<key>inventory_stock.mirror_date</key>
<key>item.date</key>
<key>mirror_date</key>
<key>modification_date</key>
......@@ -34,4 +31,4 @@
<key>stop_date_range_min</key>
<key>versioning.effective_date</key>
<key>versioning.expiration_date</key>
</key_list>
\ No newline at end of file
</key_list>
<catalog_method>
<item key="sql_uncatalog_object" type="int">
<value>1</value>
</item>
<item key="_is_filtered_archive" type="int">
<value>1</value>
</item>
<item key="_filter_expression_archive" type="str">
<value>python: context.isInventory()</value>
</item>
<item key="_filter_expression_cache_key_archive" type="tuple">
<value>portal_type</value>
</item>
</catalog_method>
<catalog_method>
<item key="sql_catalog_object_list" type="int">
<value>1</value>
</item>
</catalog_method>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="SQL" module="Products.ZSQLMethods.SQL"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>arguments_src</string> </key>
<value> <string>isInventory\r\n
uid\r\n
getDestinationUid\r\n
getDestinationSectionUid\r\n
getDestinationPaymentUid\r\n
getStartDate\r\n
isFullInventory\r\n
getSimulationState</string> </value>
</item>
<item>
<key> <string>connection_id</string> </key>
<value> <string>erp5_sql_connection</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>z_catalog_inventory_list</string> </value>
</item>
<item>
<key> <string>src</string> </key>
<value> <string encoding="cdata"><![CDATA[
<dtml-let row_list="[]">\n
\n
<dtml-in prefix="loop" expr="_.range(_.len(uid))">\n
<dtml-if expr="isInventory[loop_item]">\n
<dtml-if expr="getStartDate[loop_item] is not None">\n
<dtml-call expr="row_list.append((\n
uid[loop_item],\n
getDestinationUid[loop_item],\n
getDestinationSectionUid[loop_item],\n
getDestinationPaymentUid[loop_item],\n
getStartDate[loop_item],\n
isFullInventory[loop_item],\n
getSimulationState[loop_item]))">\n
</dtml-if>\n
</dtml-if>\n
</dtml-in>\n
\n
<dtml-if expr="len(row_list)">\n
REPLACE INTO\n
inventory\n
(`uid`, `node_uid`, `section_uid`, `payment_uid`, `date`, `is_full_inventory`, `simulation_state`)\n
VALUES\n
<dtml-in prefix="row" expr="row_list">\n
(<dtml-sqlvar expr="row_item[0]" type="int">,\n
<dtml-sqlvar expr="row_item[1]" type="int" optional>,\n
<dtml-sqlvar expr="row_item[2]" type="int" optional>,\n
<dtml-sqlvar expr="row_item[3]" type="int" optional>,\n
<dtml-sqlvar expr="row_item[4]" type="datetime">,\n
<dtml-sqlvar expr="row_item[5] or 0" type="int">,\n
<dtml-sqlvar expr="row_item[6]" type="string">\n
)<dtml-if sequence-end><dtml-else>,</dtml-if>\n
</dtml-in>\n
</dtml-if>\n
</dtml-let>
]]></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="SQL" module="Products.ZSQLMethods.SQL"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>arguments_src</string> </key>
<value> <string>uid\r\n
getResourceUid\r\n
getInventoriatedQuantity\r\n
getSourceUid\r\n
getDestinationUid\r\n
getSourceSectionUid\r\n
getDestinationSectionUid\r\n
isMovement\r\n
getSourcePaymentUid\r\n
getDestinationPaymentUid\r\n
getSourceFunctionUid\r\n
getDestinationFunctionUid\r\n
getSourceProjectUid\r\n
getDestinationProjectUid\r\n
getSourceFundingUid\r\n
getDestinationFundingUid\r\n
getSourcePaymentRequestUid\r\n
getDestinationPaymentRequestUid\r\n
getSimulationState\r\n
getSourceInventoriatedTotalAssetPrice\r\n
getDestinationInventoriatedTotalAssetPrice\r\n
getStartDate\r\n
getStopDate\r\n
isAccountable\r\n
getPortalType\r\n
getVariationText\r\n
getSubVariationText</string> </value>
</item>
<item>
<key> <string>connection_id</string> </key>
<value> <string>erp5_sql_connection</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>z_catalog_inventory_stock_list</string> </value>
</item>
<item>
<key> <string>src</string> </key>
<value> <string encoding="cdata"><![CDATA[
DELETE FROM\n
inventory_stock\n
WHERE\n
<dtml-in uid>\n
uid=<dtml-sqlvar sequence-item type="int"><dtml-if sequence-end><dtml-else> OR </dtml-if>\n
</dtml-in>\n
\n
<dtml-var sql_delimiter>\n
\n
<dtml-let row_list="[]" uid_dict="{}">\n
<dtml-in prefix="loop" expr="_.range(_.len(uid))">\n
<dtml-if "isMovement[loop_item] and isAccountable[loop_item] and getResourceUid[loop_item]">\n
<dtml-if "getDestinationUid[loop_item]">\n
<dtml-call expr="uid_dict.update({uid[loop_item]: uid_dict.get(uid[loop_item], -1) + 1})">\n
<dtml-call expr="row_list.append([\n
uid[loop_item], \n
uid_dict[uid[loop_item]],\n
getDestinationUid[loop_item],\n
getDestinationSectionUid[loop_item],\n
getDestinationPaymentUid[loop_item],\n
getDestinationFunctionUid[loop_item],\n
getDestinationProjectUid[loop_item], \n
getDestinationFundingUid[loop_item], \n
getDestinationPaymentRequestUid[loop_item], \n
getSourceSectionUid[loop_item], \n
getSourceUid[loop_item], \n
getResourceUid[loop_item],\n
getInventoriatedQuantity[loop_item],\n
getStopDate[loop_item], \n
getStartDate[loop_item], \n
getDestinationInventoriatedTotalAssetPrice[loop_item], \n
getPortalType[loop_item], \n
getSimulationState[loop_item], \n
getVariationText[loop_item],\n
getSubVariationText[loop_item]])">\n
</dtml-if>\n
<dtml-if "getSourceUid[loop_item]">\n
<dtml-call expr="uid_dict.update({uid[loop_item]: uid_dict.get(uid[loop_item], -1) + 1})">\n
<dtml-call expr="row_list.append([\n
uid[loop_item], \n
uid_dict[uid[loop_item]],\n
getSourceUid[loop_item],\n
getSourceSectionUid[loop_item],\n
getSourcePaymentUid[loop_item],\n
getSourceFunctionUid[loop_item],\n
getSourceProjectUid[loop_item], \n
getSourceFundingUid[loop_item], \n
getSourcePaymentRequestUid[loop_item], \n
getDestinationSectionUid[loop_item], \n
getDestinationUid[loop_item], \n
getResourceUid[loop_item],\n
-(getInventoriatedQuantity[loop_item] or 0), \n
getStartDate[loop_item], \n
getStopDate[loop_item],\n
getSourceInventoriatedTotalAssetPrice[loop_item], \n
getPortalType[loop_item], \n
getSimulationState[loop_item], \n
getVariationText[loop_item],\n
getSubVariationText[loop_item]])">\n
</dtml-if>\n
</dtml-if>\n
</dtml-in> \n
\n
<dtml-if "row_list">\n
INSERT INTO\n
inventory_stock\n
VALUES\n
<dtml-in prefix="row" expr="row_list">\n
(\n
<dtml-sqlvar expr="row_item[0]" type="int">,\n
<dtml-sqlvar expr="row_item[1]" type="int">,\n
<dtml-sqlvar expr="row_item[2]" type="int">,\n
<dtml-sqlvar expr="row_item[3]" type="int" optional>,\n
<dtml-sqlvar expr="row_item[4]" type="int" optional>,\n
<dtml-sqlvar expr="row_item[5]" type="int" optional>,\n
<dtml-sqlvar expr="row_item[6]" type="int" optional>,\n
<dtml-sqlvar expr="row_item[7]" type="int" optional>,\n
<dtml-sqlvar expr="row_item[8]" type="int" optional>,\n
<dtml-sqlvar expr="row_item[9]" type="int" optional>,\n
<dtml-sqlvar expr="row_item[10]" type="int" optional>,\n
<dtml-sqlvar expr="row_item[11]" type="int">,\n
<dtml-sqlvar expr="row_item[12]" type="float" optional>,\n
1, <dtml-comment>only accountable</dtml-comment>\n
<dtml-sqlvar expr="row_item[13]" type="datetime" optional>,\n
<dtml-sqlvar expr="row_item[14]" type="datetime" optional>,\n
<dtml-sqlvar expr="row_item[15]" type="float" optional>,\n
<dtml-sqlvar expr="row_item[16]" type="string" optional>,\n
<dtml-sqlvar expr="row_item[17]" type="string" optional>,\n
<dtml-sqlvar expr="row_item[18]" type="string" optional>,\n
<dtml-sqlvar expr="row_item[19]" type="string" optional>\n
)\n
<dtml-if sequence-end><dtml-else>,</dtml-if>\n
</dtml-in>\n
</dtml-if>\n
</dtml-let>\n
]]></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -92,7 +92,6 @@ WHERE\n
;\n
\n
<dtml-var "\'\\0\'">\n
\n
<dtml-let row_list="[]" uid_dict="{}">\n
<dtml-in prefix="loop" expr="_.range(_.len(uid))">\n
<dtml-if "not(isInventoryMovement[loop_item]) and isMovement[loop_item] and getResourceUid[loop_item]">\n
......@@ -152,7 +151,6 @@ WHERE\n
</dtml-if>\n
</dtml-if>\n
</dtml-in> \n
\n
<dtml-if "row_list">\n
INSERT INTO\n
stock\n
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="SQL" module="Products.ZSQLMethods.SQL"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>arguments_src</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>connection_id</string> </key>
<value> <string>erp5_sql_connection</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>z_create_inventory</string> </value>
</item>
<item>
<key> <string>src</string> </key>
<value> <string>CREATE TABLE `inventory` (\n
`uid` BIGINT(20) UNSIGNED NOT NULL,\n
`node_uid` BIGINT(20) UNSIGNED NULL,\n
`section_uid` BIGINT(20) UNSIGNED NULL,\n
`payment_uid` BIGINT(20) UNSIGNED NULL,\n
`date` DATETIME NOT NULL,\n
`is_full_inventory` BOOL NOT NULL DEFAULT FALSE,\n
`simulation_state` VARCHAR(255) NOT NULL DEFAULT \'\',\n
PRIMARY KEY `uid` (`uid`),\n
KEY `node_index` (`is_full_inventory`, `simulation_state`, `node_uid`),\n
KEY `section_index` (`is_full_inventory`, `simulation_state`, `section_uid`),\n
KEY `payment_index` (`is_full_inventory`, `simulation_state`, `payment_uid`)\n
) ENGINE=InnoDB</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="SQL" module="Products.ZSQLMethods.SQL"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>arguments_src</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>connection_id</string> </key>
<value> <string>erp5_sql_connection</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>z_create_inventory_stock</string> </value>
</item>
<item>
<key> <string>src</string> </key>
<value> <string>CREATE TABLE `inventory_stock` (\n
`uid` BIGINT UNSIGNED NOT NULL,\n
`order_id` TINYINT UNSIGNED NOT NULL,\n
`node_uid` BIGINT UNSIGNED,\n
`section_uid` BIGINT UNSIGNED,\n
`payment_uid` BIGINT UNSIGNED,\n
`function_uid` BIGINT UNSIGNED,\n
`project_uid` BIGINT UNSIGNED,\n
`funding_uid` BIGINT UNSIGNED,\n
`payment_request_uid` BIGINT UNSIGNED,\n
`mirror_section_uid` BIGINT UNSIGNED,\n
`mirror_node_uid` BIGINT UNSIGNED,\n
`resource_uid` BIGINT UNSIGNED,\n
`quantity` real ,\n
`is_accountable` BOOLEAN,\n
`date` datetime,\n
`mirror_date` datetime,\n
`total_price` real ,\n
`portal_type` VARCHAR(255),\n
`simulation_state` varchar(255) default \'\',\n
`variation_text` VARCHAR(255),\n
`sub_variation_text` VARCHAR(255),\n
PRIMARY KEY (`uid`, `order_id`),\n
KEY `quantity` (`quantity`),\n
KEY `section_uid` (`section_uid`),\n
KEY `mirror_section_uid` (`mirror_section_uid`),\n
KEY `mirror_node_uid` (`mirror_node_uid`),\n
KEY `node_uid` (`node_uid`),\n
KEY `payment_uid` (`payment_uid`),\n
KEY `function_uid` (`function_uid`),\n
KEY `project_uid` (`project_uid`),\n
KEY `simulation_state` (`simulation_state`),\n
KEY `resource_node_uid` (`resource_uid`, `node_uid`),\n
KEY `resource_section_node_uid` (`resource_uid`, `section_uid`, `node_uid`, `simulation_state`),\n
KEY `date` (`date`)\n
) ENGINE=InnoDB\n
</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -3,8 +3,6 @@
<key>catalog</key>
<key>category</key>
<key>delivery</key>
<key>inventory</key>
<key>inventory_stock</key>
<key>item</key>
<key>predicate</key>
<key>predicate_category</key>
......
......@@ -12,9 +12,6 @@ delivery.start_date_range_min
delivery.stop_date
delivery.stop_date_range_max
delivery.stop_date_range_min
inventory.date
inventory_stock.date
inventory_stock.mirror_date
item.date
mirror_date
modification_date
......
......@@ -7,8 +7,6 @@ erp5_mysql_innodb/z0_drop_alarm
erp5_mysql_innodb/z0_drop_catalog
erp5_mysql_innodb/z0_drop_category
erp5_mysql_innodb/z0_drop_delivery
erp5_mysql_innodb/z0_drop_inventory
erp5_mysql_innodb/z0_drop_inventory_stock
erp5_mysql_innodb/z0_drop_item
erp5_mysql_innodb/z0_drop_measure
erp5_mysql_innodb/z0_drop_predicate
......@@ -23,8 +21,6 @@ erp5_mysql_innodb/z0_drop_translation
erp5_mysql_innodb/z0_drop_versioning
erp5_mysql_innodb/z0_uncatalog_alarm
erp5_mysql_innodb/z0_uncatalog_category
erp5_mysql_innodb/z0_uncatalog_inventory
erp5_mysql_innodb/z0_uncatalog_inventory_stock
erp5_mysql_innodb/z0_uncatalog_item
erp5_mysql_innodb/z0_uncatalog_measure
erp5_mysql_innodb/z0_uncatalog_predicate
......@@ -35,8 +31,6 @@ erp5_mysql_innodb/z0_uncatalog_transformation
erp5_mysql_innodb/z0_uncatalog_versioning
erp5_mysql_innodb/z_catalog_alarm_list
erp5_mysql_innodb/z_catalog_delivery_list
erp5_mysql_innodb/z_catalog_inventory_list
erp5_mysql_innodb/z_catalog_inventory_stock_list
erp5_mysql_innodb/z_catalog_item_list
erp5_mysql_innodb/z_catalog_measure_list
erp5_mysql_innodb/z_catalog_movement_category_list
......@@ -58,8 +52,6 @@ erp5_mysql_innodb/z_create_alarm
erp5_mysql_innodb/z_create_catalog
erp5_mysql_innodb/z_create_category
erp5_mysql_innodb/z_create_delivery
erp5_mysql_innodb/z_create_inventory
erp5_mysql_innodb/z_create_inventory_stock
erp5_mysql_innodb/z_create_item
erp5_mysql_innodb/z_create_measure
erp5_mysql_innodb/z_create_predicate
......
......@@ -2,8 +2,6 @@ catalog
category
alarm
delivery
inventory
inventory_stock
item
predicate
predicate_category
......
This diff is collapsed.
This diff is collapsed.
......@@ -1554,8 +1554,12 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor):
# Do a hot reindex in the reverse way, but this time a more
# complicated hot reindex
portal_catalog.manage_hotReindexAll(self.new_catalog_id,
self.original_catalog_id)
portal_catalog.manage_hotReindexAll(
source_sql_catalog_id=self.new_catalog_id,
destination_sql_catalog_id=self.original_catalog_id,
source_sql_connection_id_list=destination_sql_connection_id_list,
destination_sql_connection_id_list=source_sql_connection_id_list,
update_destination_sql_catalog=True)
self.commit()
self.assertEquals(portal_catalog.getHotReindexingState(),
HOT_REINDEXING_RECORDING_STATE)
......@@ -1735,6 +1739,17 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor):
# Check more cached methods of SQLCatalog by building SQLQuery
query = portal_catalog.getSQLCatalog().buildQuery(kw={'dummy.dummy_title': 'Foo'})
self.assertTrue(query.query_list)
# We need to reset SQL connections in skin folder's zsql methods
sql_connection_id_dict = {}
for destination_sql_connection_id, source_sql_connection_id in \
zip(destination_sql_connection_id_list,
source_sql_connection_id_list):
if source_sql_connection_id != destination_sql_connection_id:
sql_connection_id_dict[destination_sql_connection_id] = \
source_sql_connection_id
portal_catalog.changeSQLConnectionIds(
folder=portal.portal_skins,
sql_connection_id_dict = sql_connection_id_dict)
def test_47_Unrestricted(self, quiet=quiet, run=run_all_test):
"""test unrestricted search/count results.
......
......@@ -6,7 +6,9 @@
from Products.PythonScripts.Utility import allow_class
from Products.CMFCore.WorkflowCore import WorkflowException
from MySQLdb import ProgrammingError
allow_class(ProgrammingError)
class DeferredCatalogError(Exception):
......@@ -53,3 +55,4 @@ allow_class(WorkflowException)
allow_class(UnsupportedWorkflowMethod)
allow_class(TransformationRuleError)
allow_class(SimulationError)
......@@ -14,7 +14,6 @@ import os
import random
import re
import socket
import shutil
import sys
import time
import traceback
......@@ -26,7 +25,6 @@ from glob import glob
from hashlib import md5
from warnings import warn
from ExtensionClass import pmc_init_of
from ZTUtils import make_query
from DateTime import DateTime
# XXX make sure that get_request works.
......@@ -148,17 +146,17 @@ def _getConnectionStringDict():
def _getConversionServerDict():
""" Returns a dict with hostname and port for Conversion Server (Oood)
"""
conversion_server_hostname = os.environ.get('conversion_server_hostname',
conversion_server_hostname = os.environ.get('conversion_server_hostname',
'localhost')
conversion_server_port = os.environ.get('conversion_server_port',
'8008')
return dict(hostname=conversion_server_hostname,
return dict(hostname=conversion_server_hostname,
port=int(conversion_server_port))
def _getVolatileMemcachedServerDict():
"""Returns a dict with hostname and port for volatile memcached Server
"""
hostname = os.environ.get('volatile_memcached_server_hostname',
hostname = os.environ.get('volatile_memcached_server_hostname',
'localhost')
port = os.environ.get('volatile_memcached_server_port', '11211')
return dict(hostname=hostname, port=port)
......@@ -166,7 +164,7 @@ def _getVolatileMemcachedServerDict():
def _getPersistentMemcachedServerDict():
"""Returns a dict with hostname and port for persistent memcached Server
"""
hostname = os.environ.get('persistent_memcached_server_hostname',
hostname = os.environ.get('persistent_memcached_server_hostname',
'localhost')
port = os.environ.get('persistent_memcached_server_port', '12121')
return dict(hostname=hostname, port=port)
......@@ -478,7 +476,7 @@ class ERP5TypeTestCaseMixin(ProcessingNodeTestCase, PortalTestCase):
if searchable_business_template_list is None:
searchable_business_template_list = ["erp5_base"]
# Assume that the public official repository is a valid repository
# Assume that the public official repository is a valid repository
public_bt5_repository_list = ['http://www.erp5.org/dists/snapshot/bt5/']
template_list = []
......@@ -620,7 +618,7 @@ class ERP5TypeTestCaseMixin(ProcessingNodeTestCase, PortalTestCase):
from AccessControl.SecurityManagement import getSecurityManager
from AccessControl.SecurityManagement import setSecurityManager
# Save current security manager
sm = getSecurityManager()
......@@ -703,7 +701,7 @@ class ERP5TypeCommandLineTestCase(ERP5TypeTestCaseMixin):
def _app(self):
'''Opens a ZODB connection and returns the app object.
We override it to patch HTTP_ACCEPT_CHARSET into REQUEST to get the zpt
unicode conflict resolver to work properly'''
app = PortalTestCase._app(self)
......@@ -818,7 +816,8 @@ class ERP5TypeCommandLineTestCase(ERP5TypeTestCaseMixin):
if update_business_templates and erp5_load_data_fs:
update_only = os.environ.get('update_only', None)
template_list = (erp5_catalog_storage, 'erp5_property_sheets',
'erp5_core', 'erp5_xhtml_style') + tuple(template_list)
'erp5_core', 'erp5_xhtml_style') \
+ tuple(template_list)
# Update only specified business templates, regular expression
# can be used.
if update_only is not None:
......@@ -837,6 +836,10 @@ class ERP5TypeCommandLineTestCase(ERP5TypeTestCaseMixin):
light_install = self.enableLightInstall()
create_activities = self.enableActivityTool()
hot_reindexing = self.enableHotReindexing()
# We want to always have optimisation available
if "erp5_stock_cache" not in template_list:
template_list = list(template_list)
template_list.append("erp5_stock_cache")
self.setUpERP5Site(business_template_list=template_list,
light_install=light_install,
create_activities=create_activities,
......
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