August 9, 2010
I submitted a bug for this but the system seems to have swallowed it up without giving me the bug number (probably because I submitted as cf 9.0.1).
what I consider to be a serious bug an issue with ColdFusion's
ehache implementation and query objects that may bite you if you're not aware of how it works. If I take a query object and stick it in cache, then perform an operation on the original query
object such as adding a column or performing certain query of query
operations, ColdFusion is treating the query object that's in cache as
if it were a copy by reference to the original query object. That is,
if I make a change to the original query object, ColdFusion is also
applying the change to the version that's in cache. As far as I'm concerned, cache represents a boundary that ColdFusion
should not implicitly cross. With most caching systems I've worked with in the past (such as memcached), the cache always acted as a dumb key/value store. Unless I perform an explicit cachePut(), I wouldn't expect that CF would update values in the cache. Here's
two code snippets that reproduces the case. The first uses the
cfartgallery data source:
<cfquery name="getArtists" datasource="cfartgallery">
<!--- dump the original query --->
<!--- put the query in cache --->
<cfset cachePut("artistsQuery", getArtists,
<!--- add a column to the query --->
<!--- clear the query --->
<!--- get the query from cache again - note that the added column is
The second example shows how this can be done with a query of a query, based on a different bug Ray found previously (see http://www.coldfusionjedi.com/index.cfm/2009/8/28/Another-example-of-the-QofQ-Bug). In this sample, note that the date gets reformatted by the query of a query and both the original query and the cached version get updated:
<cfloop index="loop1" from="1" to="5">
<cfset newrow = queryaddrow(mydata, 1)>
<cfset temp = querysetcell(mydata, "mydate", #dateformat(now()-
<cfset temp = querysetcell(mydata, "rannum", 55.65, #loop1#)>
<cfset cachePut("myQuery", myData, '#createTimeSpan(0,0,5,0)#',
<cfquery dbtype="query" name="query4graph">
select mydate, rannum from mydata
The work around for this problem is to use the duplicate() function to make a clone of the query object before doing the cachePut(). Although this works, there are other potential consequences from having two copies of the query around, so be careful.
Update: It looks like this is actually expected behavior in Ehcache. Unfortunately, it's not documented in the ColdFusion documentation anywhere, but Ehcache actually has two configurable parameters (as of v. 2.10) called copyOnRead and copyOnWrite that determine whether values returned from the cache are by reference or copies of the original values. By default, items are returned by reference. Unfortunately we can't take advantage of these parameters right now as CF 9.0.1 implements Ehcache 2.0.
I can live with this, but it's not what I expected as I've always viewed Ehcache as a "dumb" key-value store and certainly didn't expect this behavior. Even if ColdFusion was running v 2.10 of Ehcache, it's still not something we could easily configure. Since ColdFusion currently doesn't have a cacheNew() function for creating new user-defined cache regions, the only way to turn this functionality off would be to hard-code your cache configuration in your ehcache.xml file for each user-defined region where you want to disable copyOnRead and copyOnWrite.