Comparing with three values without repeating it three times - coldfusion

Is this correct on ColdFusion (do not have a running environment until next week)?
<cfif variableName IN (11,12,13,14,15,16) >
.................
................
</cfif>
or do I have to repeat it 6 times?
<cfif variableName EQ 11 OR variableName EQ 12 OR variableName EQ 13 OR
variableName EQ 14 OR variableName EQ 15 OR variableName EQ 16>
..........................
..........................
</cfif>

Nope. However, you can enclose the list of values in quotes and use list functions like ListFind or ListFindNoCase:
<cfif listFind("11,12,13,14,15,16", variableName)>
variableName was found. do something.
</cfif>
do not have a running environment until next week
You can always download CF Express in the interim. Just download the .zip, extract and double click the {cf_root}\bin\cfstart.bat file to start CF using the built in web server (note - runs on port 8500 by default).
For quick tests, another option is online sites like http://trycf.com or http://cflive.net/.

Related

Trying to replace all evaluate functions with dynamic notation in ColdFusion 9

Hello I have been tasked with replacing all evaluate() functions in this coldfusion app. I am having some issues with some fairly complex evaluations and I just can't figure it ou.
When it is a simple change like
This:
<cfif isNumeric(evaluate("form.value_#REPORT_FIELD_ID#"))>
To This:
<cfif isNumeric(form["value_" & REPORT_FIELD_ID])>
It's all good but for this:
<cfif evaluate("qrySearch.#qryReportFields.FIELD_NAME[qryReportFields.currentRow]#") eq true>
Not so much
I have tried several things. I thought this would work
<cfif qrySearch[#qryReportFields.FIELD_NAME[qryReportFields.currentRow]#] eq true>
But it throws a Complex object types cannot be converted to simple values. error.
Any help would be greatly appreciated.
I believe if you use bracket notation for query column name you have to also include row number.
<cfif qrySearch[qryReportFields.FIELD_NAME[qryReportFields.currentRow]][qrySearch.currentrow] eq true>
Or just pass 1 instead of currentrow if only one record, not in loop, etc

Access a coldfusion variable without knowing the name

Is there a syntax in coldfusion that will let me do that following?
<cfif DataSet2.RecordCount gt 0 >
<cfset append = #ArrayAppend(DataSet2Results,VAL(DataSet2.RecordCount))# >
</cfif>
Replacing the '2' in each case with an variable name (an index in a loop in this case).
So it would look like:
<cfif DataSet#index#.RecordCount gt 0 >
<cfset append = #ArrayAppend(DataSet#index#Results,VAL(DataSet#index#.RecordCount))# >
</cfif>
I know I can do a two dimensional array for this, but it would save me a slice of time if this can be done.
I found the answer to my own question. I used Variables["DataSet#index#"].recordcount and so on.

Is there any limitation with number queries/statements we can write inside cftransaction?

Today while fixing bugs in some existing code I found a strange error.
Branch target offset too large for short
After searching I found that it is something to do with Java byte code conversion. Here are the links I found:
Branch target offset too large for short
Branch Target Offset Error
Why does a long cfc file work in CF8, but not CF9? Getting "Branch target offset too large for short" error
In my case cftransaction contains around 870 statements and it's working fine. But I need to add 2 more queries to this transaction. Now I am getting this error when I am adding even one line of code inside cftransaction. Currently I can not move any of the existing cfquery out of the cftransaction.
Here is the overall structure of the code:
<cftransaction action="begin">
<cfif URL.action eq 'add'>
Around 200 lines of queries/statements
<cfelseif URL.action eq 'edit'>
Around 200 lines of queries/statements
</cfif>
<cfif URL.action eq 'add' or URL.action 'edit'>
Around 450 lines of queries/statements
</cfif>
</cftransaction>
Is there any workaround to fix this problem?
Branch offset has to do with the size of the module/function. It can also be caused due to a large conditional code block of cfif/cfelse or cfswitch.
Technically, I am not sure if there is any cap on the no. of queries you can put inside the cftransaciton block. It has nothing to do with the code migration from CF8 to CF9 but the length of your code inside conditional blocks.
I would want to split the function and try to put the each of the big sized conditional blocks as a separate function inside the cfc:
<cffunction name="myFunc1">
<cftransaction action="begin">
<cfif URL.action eq 'add'>
<!--- function call with your xxx lines of queries/statements --->
<cfinvoke component="MyCfc" method="firstQueryBlock" result="result1">
<cfelseif URL.action eq 'edit'>
<!--- second function call with your yyy lines of queries/statements --->
<cfinvoke component="MyCfc" method="secondQueryBlock" result="result2">
</cfif>
<cfif URL.action eq 'add' or URL.action 'edit'>
<!--- third function call with your zzz lines of queries/statements --->
<cfinvoke component="MyCfc" method="thirdQueryBlock" result="result3">
</cfif>
</cftransaction>
</cffunction>

Show where column equals a specific data?

I have a column(cse_dept) where it has integers , I would only like to show the columns where it equals 12 or 39.
Is there a way to do this?
<cfif (#GetCurrentUser.cse_dept# eq '12'39') >
<h1>test</h1>
</cfif>
It does not show me a error it just doesn't work the way I would like it.
You can use listFind. If the value of GetCurrentUser.cse_dept is 12 or 39 listFind will return the a number greater than 0
<cfif listFind('12,39', GetCurrentUser.cse_dept)>
<h1>test</h1>
</cfif>
listFind is case sensitive in case you were searching for something other than numbers. If you need a case-insensitve search you can use listFindNoCase
Alternatively you could check for each value separately
<cfif GetCurrentUser.cse_dept EQ 12 OR GetCurrentUser.cse_dept EQ 39>
<h1>test</h1>
</cfif>
If you want to check if GetCurrentUser.cse_dept is 12 or 39 for any result in your query you can do
<cfif listFind(valueList(getCurrentUser), 12) OR listFind(valueList(getCurrentUser), 39)>
<h1>test</h1>
</cfif>
There are a few ways to do this:
Method 1 - Query of Queries
<cfquery name="q1" dbtype="query">
select count(*) records
from GetCurrentUser
where cse_dept in (12,39)
</cfquery>
<cfif q1.records gt 0>
do something
</cfif>
Method 2 - List Functions
<cfif ListFind(ValueList(GetCurrentUser.cse_dept), 12)
+
ListFind(ValueList(GetCurrentUser.cse_dept), 39) gt 0>
do something
</cfif>
Method 3 - Array Functions
<cfif ArrayFind(GetCurrentUser['cse_dept'], 12)
+
ArrayFind(GetCurrentUser['cse_dept'], 39) gt 0>
do something
</cfif>
Method 2 is very similar to Matt's second suggstion. One difference is the use of a ValueList function. The second is that instead of using "or", I added the function results together. The results are the same.
Method 3 is probably the fastest. However, depending on where those numbers 12 and 39 come from, Method 1 might be a better approach.

Having some trouble understanding loops

I created this for some reason neither one of the queries are being updated
<cfloop index="i" from="1" to="#ArrayLen(location)#">
<cfif location[i] NEQ "" AND #locationID# EQ "" >
<cfquery Name="UpdateAddActivity" DATASOURCE="#DS#">
INSERT INTO tblProjectLocations
(
projectID,
locationID
)
VALUES
(
#ProjectName#,
#location[i]#
)
</cfquery>
</cfif>
<cfif location[i] EQ "" AND #locationID# NEQ "" >
<cfquery Name="UpdateAddActivity" DATASOURCE="#DS#">
DELETE FROM tblProjectLocations
WHERE locationID = #locationID# AND projectID = #ProjectName#
</cfquery>
</cfif>
</cfloop>
Am I looping correctly? It doesn't seem like to me that the accumulator is ever going to be updated but loops are done this way every place that I've looked.
Your cfloop tag is fine - you only need index/from/to attributes for a basic loop.
The index variable is incremented (and the loop re-processed) at the position of the closing tag. Or to put it another way, the body code is executed once for each index value between from and to (inclusive).
For information, you can change the default increment (of 1) by specifying the step attribute (though that obviously doesn't make sense for an array loop).
When your code isn't performing as expected, you can debug it with the dump tag:
<cfloop ... >
...
<cfdump var=#locationID# abort />
...
</cfloop>
The abort attribute will stop processing - the loop will not iterate and the current page content will be returned (it's shorthand for specifying cfabort tag separately.
You can use multiple dumps, and the label attribute to help identify which is which, but obviously if using abort attribute make sure only the last one has it.
As has been mentioned locationID isn't defined in the snippet you've provided, so may be the issue.
Sometimes spaces can cause issues - you may want to use the trim function to ensure you're dealing with empty strings (though blindly wrapping trim functions everywhere is ugly - always try if possible avoid introducing spaces).
Shortcut Array Looping
The from/to loop you've got there is only one type of cfloop - there are others.
Specifically, when you don't need the numeric index, there is a shorthand array loop:
<cfloop index="CurLocation" array=#Location# >
...
</cfloop>
Which is equivalent to:
<cfloop index="i" from=1 to=#ArrayLen(Location)# >
<cfset CurLocation = Location[i] />
...
</cfloop>
But without the unused i variable. (If you need the i variable, stick to from/to.)
Note that inside a function you should almost always write index="local.i" and index="local.CurLocation" to ensure the variables are appropriately scoped. This isn't unique to loops - it applies to any tags that create variables. You can also do <cfset var i = 0 /> prior to the loop to do the same thing.
Unrelated Issues
There are a couple of other issues with your code.
Most importantly, the code you're showing is potentially at risk of SQL injection. You should almost never write SQL with bare hashes in, and instead parameterise your queries - using cfqueryparam tag - to solve this. (In the situations where you can't use parameters (e.g. within ORDER BY) make sure you have appropriately sanitized any dynamic text.
Less important -- it doesn't change how the code works, but does betray a lack of experience and understanding -- are the superfluous hashes around locationID. A simplified explanation is that you generally only need #s inside strings (i.e. where the contents would otherwise be treated as text, rather than being a variable's value.)
When in doubt, look at your data.
<cfoutput>
<cfloop index="i" from="1" to="#ArrayLen(location)#">
i is #i# <br>
<cfif location[i] NEQ "" AND locationID EQ "" >
true location is #location[i]# <br>
<cfelse>
false location [i] is is #location[i]# and
locationid is #locationID# <br>
</cfif>
<cfif location[i] EQ "" AND locationID NEQ "" >
same as above
</cfif>
</cfloop>
</cfoutput>
Then you'll know why you are not getting the results you expect.
As long as there are items in your location array, the loop will run and the CFLoop tag will take care of incrementing i.
What I'd guess is happening is that you are checking two conditions within the loop and if neither match, no code will run. You're handling these:
location[i] NEQ "" AND #locationID# EQ ""
location[i] EQ "" AND #locationID# NEQ ""
but not these:
location[i] EQ "" AND #locationID# EQ ""
location[i] NEQ "" AND #locationID# NEQ ""
Could that be it?