• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Function Recursion Stopped Working in 2016

New Here ,
Apr 05, 2016 Apr 05, 2016

Copy link to clipboard

Copied

Hi, I have a function that stopped working when I upgraded to 2016, I can't for the life of me see why.  What happens is the second time the query runs it overwrites the first one and stops.  It does not run the full first query.  What am I missing?!

<cffunction name="doThis" access="public" returntype="string">

    <cfargument name="parent" type="numeric" default="0">

    <cfscript>

        var LOCAL = {};

    </cfscript>

    <cfquery name="LOCAL.q">

        SELECT    parentID, title

        FROM    thetable

        WHERE    parentID = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.parent#">

        ORDER BY priority;

    </cfquery>

    <cfsavecontent variable="LOCAL.html">

        <ul>

            <cfoutput query="LOCAL.q">

                <li>

                    <span>#LOCAL.q.title#</span>

                    #doThis(parent=LOCAL.q.sitePageID)#

                </li>

            </cfoutput>

        </ul>

    </cfsavecontent>

    <cfreturn LOCAL.html>

</cffunction>

<cfoutput>#doThis()#</cfoutput>

Views

1.5K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Guide , Apr 05, 2016 Apr 05, 2016

It looks like this might indeed be a bug with ColdFusion 2016: Bug#4126393 - cfloop over a function local scope query ends iteration early


The good news is that it is purportedly fixed.  The bad news is the fix hasn't been released yet.  You might go vote it up.  I'm adding a vote and a comment that other users are affected.

Votes

Translate

Translate
Adobe Employee ,
Apr 05, 2016 Apr 05, 2016

Copy link to clipboard

Copied

Hi Kevin,

Can you share a sample code to repro the behaviour?

Regards,

Anit Kumar

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Apr 05, 2016 Apr 05, 2016

Copy link to clipboard

Copied

Interesting. I pasted it in there... Hopefully it stays this time....

<cffunction name="doThis" access="public" returntype="string">

    <cfargument name="parent" type="numeric" default="0">

    <cfscript>

        var LOCAL = {};

    </cfscript>

    <cfquery name="LOCAL.q">

        SELECT    parentID, title

        FROM    thetable

        WHERE    parentID = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.parent#">

        ORDER BY priority;

    </cfquery>

    <cfsavecontent variable="LOCAL.html">

        <ul>

            <cfoutput query="LOCAL.q">

                <li>

                    <span>#LOCAL.q.title#</span>

                    #doThis(parent=LOCAL.q.sitePageID)#

                </li>

            </cfoutput>

        </ul>

    </cfsavecontent>

    <cfreturn LOCAL.html>

</cffunction>

<cfoutput>#doThis()#</cfoutput>

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Apr 05, 2016 Apr 05, 2016

Copy link to clipboard

Copied

What's interesting is it seems to run until the query returns no results.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Apr 05, 2016 Apr 05, 2016

Copy link to clipboard

Copied

dbldutch21‌ Probably doesn't have anything to do with the problem at hand, but you can eliminate the <cfscript>var LOCAL = {}</cfscript> block entirely.  LOCAL is a defined scope within functions since CF9, so you can just use it like you have throughout your function without explicitly declaring it.  What you are doing, in fact, is creating a LOCAL.LOCAL variable.

If I understand your function's logic, you are selecting records from the "thetable" table, starting possibly with parentID=0 (or some other value initially passed to the function), and then recursively running the function to select "descendant" records.  Is that correct?

Can you clarify what you meant by "until the query returns no results"?  Do you mean that the final output from the initial call to doThis() is empty (no html is returned)?  Or do you mean that the function runs until it has found the last descendant record and stops?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Apr 05, 2016 Apr 05, 2016

Copy link to clipboard

Copied

Hey Carl, I'm just used to putting that in there from the old days, I did try to remove it just in case something changed in 2016.

2016 Output:

<ul>

    <li>

        <span>Item 1</span>

    </li>

</ul>

Coldfusion 2011 Output:

<ul>

    <li>

        <span>Item 1</span>

    </li>

    <li>

        <span>Item 2</span>

        <ul>

            <li>

                <span>Sub 1</span>

            </li>

            <li>

                <span>Sub 2</span>

            </li>

        </ul>

    </li>

    <li>

        <span>Item 3</span>

    </li>

    <li>

        <span>Item 4</span>

    </li>

</ul>

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Apr 05, 2016 Apr 05, 2016

Copy link to clipboard

Copied

Sorry for restating the obvious in my previous response - I flashed right past the title of your post which clearly stated "recursive".

Anyway, do you have debugging output turned on so you can see all of the queries that are being executed?  Is the query only run once?

You might want to add a check around the <cfsavecontent> block to verify the query returns rows before doing anything else.  Here's a slightly revised version of your function that might help:

<cffunction name="doThis" access="public" returntype="string">

    <cfargument name="parent" type="numeric" default="0">

    <cfset var q = ''>

    <cfset var html = ''>

    <cfquery name="q">

        SELECT    parentID, title

        FROM    thetable

        WHERE    parentID = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.parent#">

        ORDER BY priority;

    </cfquery>

     <cfif q.RecordCount>

         <cfsavecontent variable="html">

             <ul>

                 <cfoutput query="q">

                     <li>

                         <span>#q.title#</span>

                         #doThis(parent=q.sitePageID)#

                     </li>

                 </cfoutput>

             </ul>

         </cfsavecontent>

     </cfif>

    <cfreturn html>

</cffunction>

<cfoutput>#doThis()#</cfoutput>

Does that help?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Apr 05, 2016 Apr 05, 2016

Copy link to clipboard

Copied

Carl, thanks for the help, sorry that did not work though.  I've created a test that you can copy and paste into a file to save.  You can run it on Coldfusion 11 and Coldfusion 2016 and get 2 different results.  I'm honestly not sure what is happening, I'd love to hear that it is a simple setting in the admin!

Code to Paste into new file:

<cfscript>

    db = QueryNew("ID,parentID,title,priority", "Integer,Integer,VarChar,Integer");

    queryAddRow(db, [

        {ID=1, parentID=0, title="Main 1", priority=1},

        {ID=2, parentID=1, title="Main 2 - Sub 1", priority=1},

        {ID=3, parentID=1, title="Main 2 - Sub 2", priority=2},

        {ID=4, parentID=3, title="Main 2 - Sub 2 - Deep 1", priority=1},

        {ID=5, parentID=3, title="Main 2 - Sub 2 - Deep 2", priority=2},

        {ID=6, parentID=1, title="Main 2 - Sub 3", priority=3},

        {ID=7, parentID=0, title="Main 2", priority=2},

        {ID=8, parentID=0, title="Main 3", priority=3},

        {ID=9, parentID=0, title="Main 4", priority=4},

        {ID=10, parentID=0, title="Main 5", priority=5}

    ]);

</cfscript>

<cffunction name="doThis" access="public" returntype="string">

    <cfargument name="parent" type="numeric" default="0">

    <cfscript>

        var LOCAL = {};

    </cfscript>

    <cfquery name="LOCAL.q" dbtype="query">

        SELECT    ID, parentID, title

        FROM    db

        WHERE    parentID = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.parent#">

        ORDER BY priority;

    </cfquery>

    <cfsavecontent variable="LOCAL.html">

        <cfif LOCAL.q.RecordCount>

            <ul>

                <cfoutput query="LOCAL.q">

                    <li>

                        <span>#LOCAL.q.title#</span>

                        #doThis(parent=LOCAL.q.ID)#

                    </li>

                </cfoutput>

            </ul>

        </cfif>

    </cfsavecontent>

    <cfreturn LOCAL.html>

</cffunction>

<cfoutput>#doThis()#</cfoutput>

In Coldfusion 2016:

<ul>

    <li>

        <span>Main 1</span>

        <ul>

            <li><span>Main 2 - Sub 1</span></li>

            <li>

                <span>Main 2 - Sub 2</span>

                <ul>

                    <li><span>Main 2 - Sub 2 - Deep 1</span></li>

                    <li><span>Main 2 - Sub 2 - Deep 2</span></li>

                </ul>

            </li>

        </ul>

    </li>

</ul>

In Coldfusion 11:

<ul>

    <li>

        <span>Main 1</span>

        <ul>

            <li><span>Main 2 - Sub 1</span></li>

            <li>

                <span>Main 2 - Sub 2</span>

                <ul>

                    <li><span>Main 2 - Sub 2 - Deep 1</span></li>

                    <li><span>Main 2 - Sub 2 - Deep 2</span></li>

                </ul>

            </li>

            <li><span>Main 2 - Sub 3</span></li>

        </ul>

    </li>

    <li><span>Main 2</span></li>

    <li><span>Main 3</span></li>

    <li><span>Main 4</span></li>

    <li><span>Main 5</span></li>

</ul>

It appears to me that the LOCAL.q is actually getting overwritten each time, it isn't actually being stored LOCALLY.  I've tried your suggestion with var q as well and it was the same.

Thanks!!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Apr 05, 2016 Apr 05, 2016

Copy link to clipboard

Copied

It looks like this might indeed be a bug with ColdFusion 2016: Bug#4126393 - cfloop over a function local scope query ends iteration early


The good news is that it is purportedly fixed.  The bad news is the fix hasn't been released yet.  You might go vote it up.  I'm adding a vote and a comment that other users are affected.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Apr 05, 2016 Apr 05, 2016

Copy link to clipboard

Copied

Thanks Carl! Have you ever heard when the first update will be released?  Trying to decide if I want to go through the pain of downgrading.  Thanks!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Employee ,
Apr 05, 2016 Apr 05, 2016

Copy link to clipboard

Copied

Hi Kevin,

The CF2016 Update 1 will be released very soon. No need for you to downgrade.

Regards,

Anit Kumar

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Apr 06, 2016 Apr 06, 2016

Copy link to clipboard

Copied

I'm kinda stuck and can't work until that release is out.  I'm sure you can't tell me the exact date but I really can't lose another couple days.  Is "very soon" in a couple days or do I need to downgrade to continue working?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Apr 06, 2016 Apr 06, 2016

Copy link to clipboard

Copied

It's a long shot, but have you tried using the result attribute?:

<cfquery name="tmpqry" result="LOCAL.q" dbtype="query">

I don't have CF2016, so I can't test it for you.

If that also doesn't work, a possible workaround (until you get the fix) is to dynamically create the query name. The following works in CF11, try it in CF2016:

<cfscript>

    db = QueryNew("ID,parentID,title,priority", "Integer,Integer,VarChar,Integer");

    queryAddRow(db, [

        {ID=1, parentID=0, title="Main 1", priority=1},

        {ID=2, parentID=1, title="Main 2 - Sub 1", priority=1},

        {ID=3, parentID=1, title="Main 2 - Sub 2", priority=2},

        {ID=4, parentID=3, title="Main 2 - Sub 2 - Deep 1", priority=1},

        {ID=5, parentID=3, title="Main 2 - Sub 2 - Deep 2", priority=2},

        {ID=6, parentID=1, title="Main 2 - Sub 3", priority=3},

        {ID=7, parentID=0, title="Main 2", priority=2},

        {ID=8, parentID=0, title="Main 3", priority=3},

        {ID=9, parentID=0, title="Main 4", priority=4},

        {ID=10, parentID=0, title="Main 5", priority=5}

    ]);

</cfscript>

<cffunction name="doThis" access="public" returntype="string">

    <cfargument name="parent" type="numeric" default="0">

    <cfscript>

        var LOCAL = {};

        var sName = 'qry' & arguments.parent;

    </cfscript>

  <cfquery name="#sName#" dbtype="query">

        SELECT    ID, parentID, title

        FROM    db

        WHERE    parentID = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.parent#">

        ORDER BY priority;

    </cfquery>

    <cfsavecontent variable="LOCAL.html">

        <cfif evaluate('#sName#.RecordCount')>

            <ul>

                <cfoutput query="#sName#">

                    <li>

                        <span>#title#</span>

                        #doThis(parent=ID)#

                    </li>

                </cfoutput>

            </ul>

        </cfif>

    </cfsavecontent>

    <cfreturn LOCAL.html>

</cffunction>

<cfoutput>#doThis()#</cfoutput>

Here's hoping.

Cheers

Eddie

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Apr 24, 2016 Apr 24, 2016

Copy link to clipboard

Copied

LATEST

Please use JVM argument -Dcoldfusion.udf.reuseTagInstances=false, mentioned in CF2016's release notes for this and other issues*, while waiting for CF2016's Update 1. I've added a comment on ticket 4126393.

* - not all issues fixable using that JVM argument are listed in the Release Notes

Thanks!,

-Aaron

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources
Documentation