Query struct gets added to the Variables scope of Application.cfc, whether you like it or not.

{ Posted By : Eric Cobb on March 29, 2010 }
4399 Views
Related Categories: CFML, ColdFusion

I've been spending a lot of time lately working on porting a legacy ColdFusion application over from Application.cfm to Application.cfc on ColdFusion 8. One of the things I'm paying close attention to is what gets put into the variables scope inside of my Application.cfc. I don't want to accidentally have stuff floating around in there and causing problems. So, my constantly checking the variables scope of various methods is how I found this little gem.

Did you know that, even if a query name is var scoped in Application.cfc, you'll still get CFQUERY.EXECUTIONTIME stored in the variables scope of your CFC? Try this:

<cfcomponent displayname="Application" output="false">

    <!--- Application name --->
    <cfset this.name = "Test">

    <!--- Run onRequestStart --->
    <cffunction name="onRequestStart" returntype="boolean" output="false">
        <cfargument name="thePage" type="string" required="true" />
        
        <!--- create a struct to hold our local variables. --->
        <cfset var loc = structNew() >
        
        <!--- query our db. --->
        <cfquery name="loc.getPrice" datasource="cfartgallery">
            Select PRICE
            From Art
        </cfquery>

        <!--- dump our variables and "loc" scopes. --->        
        <cfdump var="#variables#" /><br /><cfdump var="#loc#" />
        <cfabort />
        <cfreturn true />
    </cffunction>

</cfcomponent>

You should see CFQUERY.EXECUTIONTIME at the top of your dump output.

However, I was able to find a work around for this. If you specify the result attribute in the query, then var scope that variable, that seems to keep your query information from getting put in the variables scope.

<cfcomponent displayname="Application" output="false">

    <!--- Application name --->
    <cfset this.name = "Test">

    <!--- Run onRequestStart --->
    <cffunction name="onRequestStart" returntype="boolean" output="false">
        <cfargument name="thePage" type="string" required="true" />
        
        <!--- create a struct to hold our local variables. --->
        <cfset var loc = structNew() >
        
        <!--- query our db. --->
        <cfquery name="loc.getPrice" datasource="cfartgallery" result="loc.q">
            Select PRICE
            From Art
        </cfquery>
        
        <!--- dump our variables and "loc" scopes. --->
        <cfdump var="#variables#" /><br /><cfdump var="#loc#" />
        <cfabort />
        <cfreturn true />
    </cffunction>

</cfcomponent>

Now you should see that the CFQUERY structure has moved to our "loc" scope, and is no longer in the variables dump.

Does having that one little variable in the CFC's variables scope really matter? No, I guess not. But it bugs me that it's showing up there even though (I thought) I explicitly told it not to go there by var scoping my query. Now I can't help but wonder what else is getting stuck in the Variables scope when it's not supposed to. Does this happen for all queries in all CFCs? No wonder CF gets memory leaks that are so hard to track down!

Comments
Ben Nadel's Gravatar I wonder if this happens for other tags? There's a number of tags that create implicit objects (like CFFile). That's a really interesting thought regarding memory issues. For Application.cfc I would say it probably doesn't matter since it's created new each request; but for singleton objects, I wonder if this becomes an issue. I wonder if it can become a garbage collection is (as you have unknown references to values you are no longer actively using).
# Posted By Ben Nadel | 3/30/10 1:06 PM
Eric Cobb's Gravatar @Ben - I could definitely see it becoming an issue on high traffic, CFC heavy applications, although I don't know if it would ever be a big enough to cause any real problems. My gut feeling is that this is a bug (in CF 8, I haven't checked CF 9). It's odd that it only seemed to do it with CFQUERY.EXECUTIONTIME, but not with the other items in the CFQUERY struct like COLUMNLIST or RECORDCOUNT.
# Posted By Eric Cobb | 3/30/10 2:09 PM
Ben Nadel's Gravatar @Eric,

Oh that's too odd - when I read this the first time, it never even occurred to me that it wasn't getting the whole struct. It's like my mind didn't let me see the CFDump :) Yeah, that is totally odd! Got to be a bug.
# Posted By Ben Nadel | 3/30/10 2:12 PM
Eric Cobb's Gravatar Interestingly enough, I just tested this on Railo and got the exact same results. So, if it's a bug they've caught it too! ;)
# Posted By Eric Cobb | 3/30/10 2:28 PM
Ben Nadel's Gravatar Hmm, that's funky. There must be something to it if two entirely different engines are showing the same behavior??
# Posted By Ben Nadel | 3/30/10 2:30 PM
Eric Cobb's Gravatar When I saw it happening in both places, I asked the Railo list about it and Barny Boisvert cleared it up.

He said "That's legacy CFML behaviour - CFQUERY always dumped out it's execution time into a CFQUERY struct in the current scope. But there's no reason to use it now that CFQUERY accepts a 'result' attribute in addition to 'name' for getting that info. So while it's weird that it leaks like that, as long as you don't rely on it it's not an issue.

Railo has it for compatibility with ACF, not as the result of the same bug cropping up in both implementations."

Mystery solved! :)
# Posted By Eric Cobb | 3/30/10 3:14 PM
Ben Nadel's Gravatar Ahh, good detective work :)
# Posted By Ben Nadel | 3/31/10 7:23 AM