Upgraded from CF10 to CF11 update 5 ( with hotfix hf1100-3971083.jar )
DB (DB2 v10.2)
getting an error on code that calls a stored proc.
Error Executing Database Query.
[Macromedia][DB2 JDBC Driver][DB2]ILLEGAL SYMBOL =;
The error occurred in ...: line 238
236 : <cfstoredproc datasource="#application.dsn#" procedure="LIVE.SP" >
237 : <cfprocparam type="In" cfsqltype="CF_SQL_BIGINT" dbvarname="STOPID" null="yes" />
238 : <cfprocparam type="In" cfsqltype="CF_SQL_INTEGER" dbvarname="POID" null="no" value="#val( qry.id )#" />
239 : </cfstoredproc>
The actual code looks like this - and works fine in CF10....
"qry" IS returning a value for "id"
<cfloop query="qry" >
<cfstoredproc datasource="#application.dsn#" procedure="LIVE.SP" >
<cfprocparam type="In" cfsqltype="CF_SQL_BIGINT" dbvarname="STOPID" null="yes" />
<cfprocparam type="In" cfsqltype="CF_SQL_INTEGER" dbvarname="POID" null="no" value="#val( qry.id )#" />
</cfstoredproc>
</cfloop>
This happens IF or NOT the 'debugging' is turned on (per hotfix hf1100-3971083.jar)
It seems there are others claiming cfprocparam issues - but the solutions to those issues are not fixing THIS issue.
Any Ideas?
After a couple days of trying multiple suggestions from people.
I removed the "dbvarname" arguments, made sure my arguments were an ordinal match to the procedure, and that gets me past the error.
<cfstoredproc datasource="#application.dsn#" procedure="LIVE.SP" >
<cfprocparam type="In" cfsqltype="CF_SQL_BIGINT" null="yes" />
<cfprocparam type="In" cfsqltype="CF_SQL_INTEGER" null="no" value="#val( qry.id )#" />
</cfstoredproc>
This works without error. I can't say I LIKE the solution. but oh well.
The other solution that probably would have worked was to use
<cfquery...>
call 'procName' ( arg => value, arg2 => val2 );
</cfquery>
however, this is legacy code which hopefully wont exist for more then a year longer (...hopefully...). So Im not going to fret about it.
Related
<cfoutput>
<cfloop from="1" to="10" index="i">
#i#<br />
<cfif i EQ 3>
<cfset i -= 3 />
blarg #i# <br >
</cfif>
</cfloop>
</cfoutput>
How can i decrease, one decrement value with forloop
and my expected output should be
1
2
3
blarg 0
3
4
5
6
7
8
9
10
The value of i in your example is controlled by the inner workings of <cfloop>, and its value simply exposed to the code within the loop block. You can change it within that block, but <cfloop> will simply expose the next value in the iteration each time.
To do what you want to do, either use a for(;;) loop, or a <cfloop> equivalent of same:
<cfset i=1>
<cfloop condition="i LTE 10">
<!--- your logic here--->
<cfset i++>
</cfloop>
I have a jQuery Mobile app that has several dynamic forms. What I am trying to do is parse the form submissions and get the value of the form field. When the data is received from the processing script, it looks as follows.
str:app_EAD17776-155D-D714-FB34E569AA814746_ser=a&app_EAD17776-155D-D714-FB34E569AA814746_app=A1234Washer%2C+ABC&app_EAD17776-155D-D714-FB34E569AA814746_chk=&app_EAD17776-155D-D714-FB34E569AA814747_ser=a&app_EAD17776-155D-D714-FB34E569AA814747_app=A1234Dryer%2C+ABC&app_EAD17776-155D-D714-FB34E569AA814747_chk=
What I need to do from there is get the values of each of these an put them in a 2 dimensional array.
I need to further explain the formfields in order for you to seem my problem. I will break down the formfield.
This formfield is an appliance serial number:
app_EAD17776-155D-D714-FB34E569AA814746_ser=a
The applianceType is: EAD17776-155D-D714-FB34E569AA814746
EAD17776-155D-D714-FB34E569AA814746 = Washer
Serial Number = a
This formfield is the Brand and Name of Appliance:
app_EAD17776-155D-D714-FB34E569AA814746_app=A1234Washer%2C+ABC
The appliance type is: EAD17776-155D-D714-FB34E569AA814746
Washer Brand and Name: A1234Washer, ABC
This formfield is an active checkbox:
app_EAD17776-155D-D714-FB34E569AA814746_chk=
The applianceType is: EAD17776-155D-D714-FB34E569AA814746
So what I am trying to do with this information is loop over this data and insert the form values along with the appropriate applianceType. First I query the active appliance types.
<cfquery name="qApplianceTypes">
SELECT *
FROM ApplianceTypes
WHERE Active = <cfqueryparam value="1" cfsqltype="cf_sql_bit">
</cfquery>
Then I loop over the results and match up the formfields applianceTypes in order to get the values and apply it to the array.
<cfset applianceTypeArray = ArrayNew(2)>
<cfset count = 1>
<cfloop query="qqApplianceTypes">
<!--- [1] appliance id ---->
<cfset applianceTypeArray[count][1] = qApplianceType.ApplianceTypeID>
<!--- loop over formfields to find relative id --->
<cfloop index="i" list="#Form.str#" delimiters=",">
<cfif right(i, 4) IS "_IDd" and qApplianceType.ApplianceTypeID is "#GetToken(ListFirst(i,' '),2,'_')#" >
<!--- [4] appliance ---->
<cfset applianceTypeArray[count][2] = #FORM[i]#>
</cfif>
</cfloop>
<!--- loop over formfields to find relative serialnumbers --->
<cfloop index="i" list="#Form.str#" delimiters=",">
<cfif right(i, 4) IS "_ser" and qApplianceType.ApplianceTypeID is "#GetToken(ListFirst(i,' '),2,'_')#" >
<!--- [3] serial number ---->
<cfset applianceTypeArray[count][3] = #FORM[i]#>
</cfif>
</cfloop>
<!--- loop over formfields to find relative appliance --->
<cfloop index="i" list="#Form.str#" delimiters=",">
<cfif right(i, 4) IS "_app" and qApplianceType.ApplianceTypeID is "#GetToken(ListFirst(i,' '),2,'_')#" >
<!--- [4] appliance ---->
<cfset applianceTypeArray[count][4] = #FORM[i]#>
</cfif>
</cfloop>
<cfset applianceTypeArray[count][5] = qApplianceType.ApplianceTypeID>
<!--- loop over formfields to find relative active or innactive --->
<cfloop index="i" list="#Form.str#" delimiters=",">
<cfif right(i, 4) IS "_chk" and qApplianceType.ApplianceTypeID is "#GetToken(ListFirst(i,' '),2,'_')#" >
<!--- [2] active ---->
<cfset applianceTypeArray[count][6] = #FORM[i]#>
</cfif>
</cfloop>
<cfset qloopcount2 = #count#>
<cfset count = count+1>
</cfloop>
Once I get the applianceTypeArray populated, I simply loop over the array to populate the database.
The problem is that I am not getting the values. It works is a form post but I have to use a get. When I dump the array, I get the following data.
0: "EAD17776-155D-D714-FB34E569AA814746"
1: null
2: null
3: null
4: "EAD17776-155D-D714-FB34E569AA814746"
0: "EAD17776-155D-D714-FB34E569AA814747"
1: null
2: null
3: null
4: "EAD17776-155D-D714-FB34E569AA814747"
First issue is that the elements start with 0 instead of 1 and I am not getting a elements 6. Second is that elements 0 - 4 are not the values but rather the appliance type ids.
Any suggestions?
I've heard that if you do not specify output="false" on a ColdFusion function that unnecessary buffering would occur which could hinder performance. So I wanted to run a test to see if I could prove this. My test is below. I saw no difference at all between output="true" or output="false".
So my question is: if I have functions used within large loops should I not have to worry about this setting? Or am I not testing this correctly?
My test was to call the same function 1,000,000 times. I ran it 3 times with output="false" and 3 times with output="true". All 6 tests finished at exactly 20-21 seconds.
The Test Code:
<cffunction name="good" output="false" returntype="Numeric" access="private">
<cfargument name="numIn" type="numeric" required="true">
<cfset var x = 0>
<cfset x = arguments.numIn + 1>
<cfreturn x>
</cffunction>
<cffunction name="bad" output="true" returntype="Numeric" access="private">
<cfargument name="numIn" type="numeric" required="true">
<cfset var x = 0>
<cfset x = arguments.numIn + 1>
<cfreturn x>
</cffunction>
<cfset loopNum = 1000000>
<cfset x = 0>
<cfoutput>
x = #x#<br>
Running bad function #loopNum# times...<br>
</cfoutput>
<cfset tBegin = GetTickCount()>
<cfloop from="1" to="#loopNum#" index="i">
<cfset x = bad(i)>
</cfloop>
<cfset tEnd = GetTickCount()>
<cfset scriptTime = (tEnd - tBegin)>
<cfoutput>
x = #x#<br>
Time to complete: #scriptTime#<br>
</cfoutput>
<!---
<cfset x = 0>
<cfoutput>
x = #x#<br>
Running good function #loopNum# times...<br>
</cfoutput>
<cfset tBegin = GetTickCount()>
<cfloop from="1" to="#loopNum#" index="i">
<cfset x = good(i)>
</cfloop>
<cfset tEnd = GetTickCount()>
<cfset scriptTime = (tEnd - tBegin)>
<cfoutput>
x = #x#<br>
Time to complete: #scriptTime#<br>
</cfoutput>
--->
I agree that it is best practice to always include output="false" in your functions unless you have a very specific and very good reason not to (it's okay in some of the Application.cfc methods like onRequest() for example). But I've never heard anyone say that the reason for this had anything to do with performance, either processor utilization or memory consumption. The primary reason I maintain it is so that you don't have sudden unexpected errors at runtime (caused by that same unnecessary buffering).
Here's an easy example:
<cffunction name="getFlag" output="true">
<cfreturn true />
</cffunction>
<cfif getFlag()><p>Hello World!</p></cfif>
<cfxml variable="doc"><cfoutput><root flag="#getFlag()#" /></cfoutput></cfxml>
<cfif doc.root.xmlAttributes.flag><p>Hello world!</p></cfif>
You might write something like this, thinking everything should be fine, since the first <cfif> test works fine and you can dump out the xml document and it looks okay from the output of a <cfdump>. And then later you would get the error message this example creates:
cannot convert the value " true" to a boolean
Because the white-space from the function bled into the XML attribute and while CF will allow you to treat the string "true" as a boolean, it won't convert the string " true". And then like many of us have before, you might spend a long time banging your head, trying to figure out why there's extra white-space in your XML document when there is no extra space in the return value from your function. It happened to me once when custom functions were introduced in CF5. ;)
I'm still trying to get my grips on Coldfusion...
I need to create a directy of files (say there are 10 files) and output 5 random files. Getting and outputting files is ok, but I'm not sure where to fit in the randrange. Here is my code:
<cfdirectory action="list" directory="#expandpath("img/")#" filter="some*.*" name="dir">
<!--- imgID --->
<CFSET imgID= #RandRange(1, #dir.allRecords#)#>
<!--- this only grabs the first 5 files --->
<cfoutput query="dir" maxrows="5">
<cfif FileExists("#expandpath("img/#name#")#")>
<cfimage source="#expandpath("img/#name#")#" name="myImage"> <cfif IsImage(myImage) is true>
<cfset ImageSetAntialiasing(myImage,"on")>
<cfset ImageScaleToFit(myImage,"highestQuality")>
<!--- append to a list --->
<li><cfimage source="#myImage#" action="writeToBrowser"></li>
</cfif>
</cfif>
</cfoutput>
This works ok in displaying the first 5 images. However, I would like to have 5 random images.
Thanks for some insights!
EDIT:
This is how I ended up doing it - ONE QUESTION UNSOLVED -
<!-- get the directy, listinfo="name" because I only need filenames --->
<cfdirectory action="list" LISTINFO="name" directory="#expandpath(" logos/")#" filter="marke*.*" name="dir">
<cfset images=[ ]>
<!-- since dir is not indexable, like dir[pos], I need another array!-->
<cfset dirArr=[ ]>
<cfset blocker="false">
<cfset maxLogos=5>
<!-- fill new dirArr(ay) -->
<cfoutput query="dir">
<cfset #ArrayAppend(dirArr, #expandpath( "logos/#name#")#)#>
</cfoutput>
<!-- loop -->
<cfloop condition="blocker eq false">
<-- random position -->
<cfset pos=R andRange(1, #dir.recordcount#)>
<cfif #dir.recordcount# eq 0 OR #ArrayLen(images)# gte #maxLogos#>
<-- STOP loop -->
<cfset blocker="true">
</cfif>
<cfset ArrayAppend(images, #dirArr[pos]#)>
<!-- BROKEN unknown ARRAYDELETE -->
<!--- <cfset ArrayDelete(dirArr, #dirArr[pos]#)> --->
<!-- IMG -->
<cfimage source="#dirArr[pos]#" name="myImage">
<cfif IsImage(myImage) is true>
<cfoutput>
<li data-icon="false">
<cfimage source="#myImage#" action="writeToBrowser">
</li>
</cfoutput>
</cfif>
</cfloop>
The problem is the ArrayDelete does not work variable ARRAYDELETE is undefined, Coldfusion(8) tells me. Any idea what I'm doing wrong?
A simple alternative is to shuffle the array once and then take the first five items:
<cfset MaxLogos = 5 />
<cfset Images = [] />
<cfset Files = DirectoryList( expandPath("logos") , false, "name" , "marke*.jpg" ) />
<cfset createObject( "java", "java.util.Collections" ).shuffle( Files ) />
<cfloop index="i" from="1" to=#Min(MaxLogos,ArrayLen(Files))# >
<cfset ArrayAppend( Images , Files[i] ) />
</cfloop>
<cfdump var=#Images# />
I'm not sure if your code will actually work as there appears to be several syntactical errors in it. Also you're doing a directory list on img but then pulling images from logos and you've not made it clear what the relationship is between these directories
those issues aside, here is how i would handle this.
<cfscript>
// this code is untested, but should get you going
// get list of image file names as an array
dir = directoryList(expandPath("imgs"), false, "name", "*.jpg");
images = [];
while(true) {
// if out directory list is now empty or we have 5 results, we're done
if(!arrayLen(dir) or arrayLen(images) gte 5) break;
// get an image from a random point in the list
pos = randrange(1, arrayLen(dir));
// append it to our images array
arrayAppend(images, dir[pos]);
// delete form the source array, this avoids duplicates in further iterations
arrayDeleteAt(dir, pos);
}
</cfscript>
This gives you an array of images, with between 0 and 5 elements, which you can then output as a list.
As a side note, its not advisable to use <cfimage> and related functions repeatedly. If you need to resize or manipulate an image you should then cache it back to disk rather than repeating the manipulation every request.
Is it possible to undefine a variable in ColdFusion?
For example, something like this:
<cfset myVar = "lsajflksd" />
<cfoutput>
<p>myVar is Defined? #IsDefined("myVar")#</p> <!--- Prints YES --->
</cfoutput>
<cfset Undefine(myVar) /> <!--- Doesn't exist... --->
<cfoutput>
<p>myVar is Defined? #IsDefined("myVar")#</p> <!--- I want it to print NO --->
</cfoutput>
<cfset StructDelete(Variables, "myVar") />
Variables is the default scope for most variables in most contexts.
In modern versions, you can also use the struct.delete() member function.
myVar = "lsajflksd";
variables.delete('myVar');
https://docs.lucee.org/reference/objects/struct/delete.html
FYI...
<cffunction name="voidFunc" returntype="void">
</cffunction>
<cfset myVar = voidFunc()>
<cfoutput>#IsDefined("myVar")#</cfoutput> <!--- will show NO --->
I found out from this blog entry: cfinvoke destroys returnVariable for methods that return void