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).

I've found 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:

view plain print about
1<!--- Demo code to show that ColdFusion's passig query values by reference is crossing boundaries and updating a query stored in cache --->
2<cfquery name="getArtists" datasource="cfartgallery">
3select *
4from artists
5</cfquery>
6
7<!--- dump the original query --->
8<cfdump var="#getArtists#">
9
10<!--- put the query in cache --->
11<cfset cachePut("artistsQuery", getArtists,
12'#createTimeSpan(0,0,5,0)#', '#createTimeSpan(0,0,5,0)#')
>

13
14<!--- add a column to the query --->
15<cfset queryAddColumn(getArtists,"newColumn",arrayNew(1))>
16<cfdump var="#getArtists#">
17
18<!--- clear the query --->
19<cfset getArtists="">
20<cfdump var="#getArtists#">
21
22<!--- get the query from cache again - note that the added column is
23there! --->

24<cfdump var="#cacheGet("artistsQuery")#">

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:

view plain print about
1<cfset mydata = queryNew("mydate, rannum")>
2
3 <cfloop index="loop1" from="1" to="5">
4 <cfset newrow = queryaddrow(mydata, 1)>
5 <cfset temp = querysetcell(mydata, "mydate", #dateformat(now()-
6loop1,"dd-mmm-yy")#, #loop1#)
>

7 <cfset temp = querysetcell(mydata, "rannum", 55.65, #loop1#)>
8 </cfloop>
9
10<cfdump var="#mydata#">
11
12<cfset cachePut("myQuery", myData, '#createTimeSpan(0,0,5,0)#',
13'#createTimeSpan(0,0,5,0)#')
>

14
15<cfdump var="#mydata#">
16
17<cfquery dbtype="query" name="query4graph">
18 select mydate, rannum from mydata
19 </cfquery>
20
21 <cfdump var="#query4graph#">
22
23 <cfdump var="#cacheGet("myQuery")#">

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.