structDelete doesn't affect the shallow copy? - coldfusion

I was playing around onError so I tried to create an error using a large xml document object.
<cfset XMLByRef = variables.parsedXML.XMLRootElement.XMLChildElement>
<cfset structDelete(variables.parsedXML, "XMLRootElement")>
<cfset startXMLShortLoop = getTickCount()>
<cfloop from = "1" to = "#arrayLen(variables.XMLByRef)#" index = "variables.i">
<cfoutput>#variables.XMLByRef[variables.i].id.xmltext#</cfoutput><br />
</cfloop>
<cfset stopXMLShortLoop = getTickCount()>
I expected to get an error because I deleted the structure I was referencing.
From LiveDocs:
Variable Assignment - Creates an
additional reference, or alias, to the
structure. Any change to the data
using one variable name changes the
structure that you access using the
other variable name. This technique is
useful when you want to add a local
variable to another scope or otherwise
change a variable's scope without
deleting the variable from the
original scope.
instead I got
580df1de-3362-ca9b-b287-47795b6cdc17
25a00498-0f68-6f04-a981-56853c0844ed
...
...
...
db49ed8a-0ba6-8644-124a-6d6ebda3aa52
57e57e28-e044-6119-afe2-aebffb549342
Looped 12805 times in 297 milliseconds
<cfdump var = "#variables#">
Shows there's nothing in the structure, just parsedXML.xmlRoot.xmlName with the value of XMLRootElement.
I also tried
<cfset structDelete(variables.parsedXML.XMLRootElement, "XMLChildElement")>
as well as structClear for both.
More information on deleting from the xml document object.
http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec22c24-78e3.html
Can someone please explain my faulty logic? Thanks.

XML data types are a combination of structures and arrays. Unlike Structures, Arrays in CF will pass by value and not by reference and may be what you are seeing.
http://www.coldfusionjedi.com/index.cfm/2009/5/1/ColdFusion-and-Pass-by-Reference-versus-Value

Related

CFSET Invoking Function without variable

New pretty new with this language, started code with it this week.
So my problem is the new company that I started with uses CF11 and they mainly only code with tags. I want to know if is possible to call cfset without a variable declaration.
If not what is the better way to call functions (that don't have return) with tags?
<cfset myFunction()>
I usually call my initiate functions at cfset, but they all have returning.
<cfset something = #initSomething()#>
Yes, invoking a function without capturing the result is perfectly fine. Sadly, there used to be a lot of that syntax in older CF documentation. It gave the erroneous impression you MUST capture the result of a function (and use extra pound signs everywhere). Neither is true. Even if a function does return something, you're not required to capture the result. Only if you wish to use it for something later. You're always free to invoke a function and completely ignore the result. So both of these are valid:
<!--- 1. capture result --->
<cfset result = getTimeNow()>
<!--- 2. ignore result --->
<cfset getTimeNow()>
<!--- sample function --->
<cffunction name="getTimeNow" return="date">
<cfreturn now()>
</cffunction>
Technically, there's nothing stopping you from capturing the result of a function that doesn't return anything. However, the "result" variable will be undefined, so it really serves no purpose.
<cfset result = doNothing()>
<!--- this will error --->
<cfoutput>#result#</cfoutput>
<!--- sample function --->
<cffunction name="doNothing" return="void">
<!--- function that returns nothing --->
</cffunction>

CF9: What is this evaluate statement evaluating?

I'm stuck and need a fresh set of eyes on this, please.
I'm working with someone else's spaghetti code who is no longer around and having a heck of a time figuring out what they were evaluating.
<cfset surveyCount = 0>
<cfloop query="surveys">
<cfif evaluate("defaultReport" & ID)>
<cfset surveyCount = surveyCount + 1>
</cfif>
</cfloop>
In the query dump, I see 9 records which is what I am expecting but because because the evaluate is failing, the surveyCount isn't being incremented. I do not see any columns for defaultReport. In my 15 years of working with CF, I've always avoided evaluate() and now when I need to analyze it, I'm at a complete loss. Can someone offer any guidance?
Added CFDump image (some columns names have been removed for privacy and security):
UPDATE I:
This file has numerous cfinclude statements and very little code formatting. As a result, I overlooked some cfinclude statements. I found the following. I'm still looking but wanted to document this as I dig.
<cfloop query="surveys">
<cfscript>
variables["defaultReport" & ID] = evaluate(thisAssociation & "Price");
</cfscript>
</cfloop>
UPDATE II:
Dumping the variable scope, I did confirm the variable I am looking for (finding the query I posted in UPDATE I helped, too). :)
What they wanted to do is to increase surveyCount but only if this thing: evaluate("defaultReport" & ID) evaluates to true.
From your query dump picture it looks like the IDs are numbers like 144, 145, etc...
In this context, you can think at evaluate("defaultReport" & ID) as something like defaultReport144, defaultReport145, etc... (these are variables set somewhere in the code).
So the code:
<cfif evaluate("defaultReport" & ID)>
<cfset surveyCount = surveyCount + 1>
</cfif>
becomes (for an ID of 144, the first one on your query loop)
<cfif defaultReport144>
<cfset surveyCount = surveyCount + 1>
</cfif>
and so on... for the other IDs
So, search your code for where variables like defaultReport144, defaultReport145, etc... are set to either true or false (0 or 1).
Something like:
<cfset defaultReport144 = true />
or maybe they use some expression that evaluates to true or false, like:
<cfset defaultReport144 = [some expression] />
If you can't find, then maybe the code was changed or removed in the place where these defaultReport... variables were set.
ColdFusion evaluate() documentation:
https://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7f4e.html
You need to look for a variable outside of your query. This variable has a name of default#ID# . It may be called.
variables.default#ID#
form.default#ID#
url.default#ID#
request.default#ID#
attributes.default#ID#
etc.
Basically ColdFusion is going to go through every scope until it finds something. (No this is not a good approach)
If you have to clean this up, I would recommend not using such an ambiguous approach. In short, there is no real way to know what it is evaluating.

Dynamic variable containing numbers

I've tried everything I've found that might be applicable to this, without success to date.
I have variables that look like
x000Foo
I'm trying to create one of these dynamically in form scope from query results and have tried the following, and a few others, without success:
<cfloop query="qFormFields">
<cfset "form.x000#fieldname#" = 0>
You have attempted to dereference a scalar variable of type class coldfusion.sql.QueryColumn as a structure with members
<cfset "form.x[000]#fieldname#" = 0>
The value x000AA_report cannot be converted to a number.
<cfset form["x000#fieldname#"] = 0>
The value x000AA_report cannot be converted to a number.
</cfloop
I know it's related to the zeros, but I'm not sure how to get around it without resorting to renaming these variables throughout the application.
I'm on ColdFusion2016
I'm not sure if this is what you're trying to do: but here's how you can do dynamic variables:
<cfset fieldname = "foo">
<cfset form["x000" & fieldname] = 0>
<cfdump var="#form#">
<!--- variable form.x000Foo = 0 --->
Runnable example on TryCF.com
you can try evaluate function read more
<cfloop query="qFormFields">
<cfset fieldvalue = Evaluate("form.x000#fieldname#")>
<cfdump var="#fieldvalue#">
</cfloop>
let me know if it is working or not.

Reading a value from a session variable into a local variable in Coldfusion

I really hope you can help me.
I usually read my session variables into a local variable, so that I don't have to create endless read locks.
But I came across some interesting behavior. Note that I have not applied any write locks for brevity's sake:
Consider the following:
EXAMPLE 1:
<cfset session.testvalue = 1 />
<cfset lcktestvalue = session.testvalue />
<cfoutput>#lcktestvalue#</cfoutput><br />
<cfset session.testvalue = 2 />
<cfoutput>#lcktestvalue#</cfoutput>
OUTPUT:
1
1
EXAMPLE 2:
<cfset session.testvalue1.item = 1 />
<cfset lcktestvalue1 = session.testvalue1 />
<cfoutput>#lcktestvalue1.item#</cfoutput><br />
<cfset session.testvalue1.item = 2 />
<cfoutput>#lcktestvalue1.item#</cfoutput>
OUTPUT:
1
2
I am trying to work out why the second example, updates the 'lcktestvalue1.item', when the value was only read once?
I would have expected example 1 & 2 to produce the same output, and the following to produce the second example's output:
EXAMPLE 3:
<cfset session.testvalue1.item = 1 />
<cfset lcktestvalue1 = session.testvalue1 />
<cfoutput>#lcktestvalue1.item#</cfoutput><br />
<cfset session.testvalue1.item = 2 />
<cfset lcktestvalue1 = session.testvalue1 />
<cfoutput>#lcktestvalue1.item#</cfoutput>
OUTPUT:
1
2
The only reason for this behavior, I can think of, is that the second example, uses a structure inside a structure.
But,I cannot expand on this concept. Can you?
I really need to understand this, because I am creating a shopping cart, which makes extensive use of the methodology in example 2. It actually works fine, but I am not sure why, and I am afraid under load, it may fail?
Thank you for any help you can give me on this.
Because your second example is making a pointer, or a reference, from the original value to the new value. You can think of it is an imaginary string between the two such that when one is changed - the other is as well. This happens with structures. You can get around this by using duplicate.
But NOTE! The need to obsessively cflock session/app/server variables has NOT been necessary for nearly ten years. You still have to worry about race conditions, but for 99% of the time this is not your concern.
Charles, This is is expected behavior. Structures and objects are passed by reference - meaning you are actually just setting a pointer to a memory location to get at the underlying object. When the set statement is dealing with a primitive (a string, number, date etc) it copies the data into your new variable - so this:
<Cfset session.testvalue = 1/>
<cfset testvalue = session.testvalue/>
...actually creates 2 locations each containing a "1"
When you are dealing with an object however (a structure, component, function, query etc. - anything not primitive), like this:
<cfset session.testvalue.item1 = 1/>
<cfset testvalue = session.testvalue/>
The variables.testvalue variable is actually a pointer to the structure you created in the set statement (session.testvalue.item1 implicitely creates a structure).
This is important fundamental stuff - especially when dealing with CFCs, functions, application scopes etc. This post on Primitive vs complex variables explains it in more detail.
It has nothing to do with locking by the way. Unless you have some demonstratable race condition you need not go overbord with locking.
I would note that your practice here is probably not a great idea - you should probably be scoping your local vars as variables.varName any way in which case pushing session variables to that scope is not saving you any effort.
NOTE: While I was writing this Ray chimed in with a short concise answer exactly to the point (while I was being verbose).
NOTE 2: In ColdFusion there is one nuance that some find unexpected - arrays are passed by value (as a copy) and not by reference. This can throw you sometimes - and if you ever do an array of objects
You should use Duplicate() if you want to copy/clone the structure and not just make a reference to the object stored in SESSION.
<cfset session.testvalue1.item = 1 />
<cfset lcktestvalue1 = Duplicate(session.testvalue1) />
<cfoutput>#lcktestvalue1.item#</cfoutput><br />
<cfset session.testvalue1.item = 2 />
<cfoutput>#lcktestvalue1.item#</cfoutput>
Output
1
1
Coldfusion WikiDocs

Coldfusion Regex get strings between tags

We currently have some application variables being defined on our apps and also have a special set of tags that are processed within our templates. However I'm finding it to be a bit difficult to split the tags, so I can convert them to application variables when parsed by the template.
<cfset mystring = "[pss]'fetchMessages','VWO-Tracking-Code'[end_pss]">
<cfset the_match = REMatch("\[pss\]\s*(((?!\[pss\]|\[end_pss\]).)+)\s*\[end_pss\]",mystring) />
<cfdump var="#the_match#" />
Our goal is to split the strings between the "[pss] and [end_pss]"
The regex above simply takes the string and applies it to a CF array, which is all good. However I strictly want the code between it as I'll be able to convert it to
<cfset application.snippets['VWO-Tracking-Code']>
Right now it returns everything as one string and I also require the first portion to determine what type of functionality is required.
Any ideas on how to do this would be greatly appreciated.
We are currently using CF 8 and the structure of the code is exactly the same all the time. The only thing is it can be contained within other strings of code as well...
If you're only doing this for one set of tags you can use the replaceList function rather than regEx
<cfset mystring = "[pss]'fetchMessages','VWO-Tracking-Code'[end_pss]">
<cfset mystring = replaceList(mystring,"[pss],[end_pss],'",'')>
<cfset firstitem = listfirst(mystring)>
<cfset seconditem = listlast(mystring)>
<cfdump var="#firstitem#">
<cfdump var="#seconditem#">
This outputs fetchMessages and VWO-Tracking-Code. If you want/need the single quotes on your strings then you can remove the ,' from the 2nd parameter of the replaceList function.