tags:

views:

508

answers:

3

Is it possiblt to Use <cfif> inside <cfquery>?

I have a <cfquery> in a Function like below

<cfquery name = "UpdateRecord"   
   dataSource = #arguments.dbSource#   
   username = #arguments.dbUser#   
   password = #arguments.dbPass# 
   result="updateResult" >  
 <cfoutput>#preserveSingleQuotes(arguments.updateQuery)#/cfoutput>
 </cfquery>

I want to check for TimeoutArgument and make it like below

<cfquery name = "UpdateRecord"   
       dataSource = #arguments.dbSource#   
       username = #arguments.dbUser#   
       password = #arguments.dbPass# 
                            timeout = #arguments.Timeout#>
       result="updateResult" >  
     <cfoutput>#preserveSingleQuotes(arguments.updateQuery)#/cfoutput>
 </cfquery>

Timeout is Optional argument, I wan to make 1st query like second query if only Timeout is passed. How can I do that?

Thanks,

+4  A: 

No, you can't use a cfif in the attribute section of cfquery. You can, however, set a default value:

<cfargument name="arguments.timeout" default="60" />

Then just use the query with arguments.timeout as specified. It will be 60 seconds by default (or some sane value). If the user specifies a value, then that will be used instead. In my opinion this is better than having two separate cfquery statements.

The livedocs for cfargument.

Ryan Emerle
Also if he/she matches the default to the setting in CFAfdmin the query will have the same timeout as if the attribute was not there.
kevink
Well, What about If i have requirement to use the timeout attribute only when I have that value passed as argument?
CFUser
Then you need to have separate cfqueries written inside an if/else block.
Al Everett
Peter Boughton
Ah, yes. I forgot about attribute collection. +1 for you.
Al Everett
+5  A: 

By the way - what's the point of such a thing:

<cfquery 
  name       = "UpdateRecord"   
  dataSource = "#arguments.dbSource#"   
  username   = "#arguments.dbUser#"   
  password   = "#arguments.dbPass#" 
  timeout    = "#arguments.Timeout#"
  result     = "updateResult"
>
  <cfoutput>#preserveSingleQuotes(arguments.updateQuery)#</cfoutput>
</cfquery>

You are passing in every single bit of info that makes a cfquery, including the actual SQL code. This makes no sense whatsoever, you could just as well use cfquery then and there, instead of invoking such an over-generalized function. It would even be less code.

Apart from that,

  • PreserveSingleQuotes(completeSqlString) disables any SQL injection checks ColdFusion has, leaving this function wide open for abuse and SQL syntax errors.
  • <cfoutput> is on by default within CF tag bodies. The <cfoutput> is therefore redundant in the above.

Abstraction is good and everything, but the above is completely pointless, and dangerous at that.

Tomalak
I agree that, if used with any user input, this is dangerous. I've seen it before, though, for calling queries from cfscript.
Ben Doom
This would be the only justification. Then again, if you write cfscript code complex enough to work with "generic" queries, you might be better off writing real CFML.
Tomalak
Well Just to avoid Confusion, I have a requirement to update the what ever I get input(Assuming Validations part like where clauses etc.. already done)
CFUser
I agree wholeheartedly with @Tomalak on this one. If that is the requirement then, assuming the updateQuery isn't properly sanitized (which should always be the first assumption) it is requirement of solution that hasn't been well thought out. At the very least the requirement should afford you some way to utilize cfparam in cfquery statment to increase security and performance.
Ryan Lynch
Looking at your inflexibility of your requirements and your mention of another requirement regarding timeout...I'm beginning to fear that this query is the meat of a web service that some other service is calling remotely to query your database. Please tell me this isn't the case.
Ryan Lynch
The OP never indicated that the query was the whole of the function. While I agree that this is scarily bad, your "answer" doesn't address the question.
Ryan Emerle
@Ryan Emerle: I introduced it with "By the way" - it was never meant to be a full answer. That's why I up-voted yours.
Tomalak
+3  A: 

NOTE: As other have pointed out: you're almost certainly doing things wrong, and are most likely are creating an insecure and inefficient application that will be a nightmare to maintain.


However, in response to your specific question, yes, you can (indirectly) use cfif to control cfquery attributes - by passing a struct to the magic attribute AttributeCollection, like so:

<cfset var QueryAttributes = StructNew() />

<cfset QueryAttributes.Datasource  = Arguments.dbSource />
<cfset QueryAttributes.Username    = Arguments.dbUser />
<cfset QueryAttributes.Password    = Arguments.dbPass />
<cfif StructKeyExists(Arguments,'Timeout')>
 <cfset QueryAttributes.Timeout = Arguments.Timeout />
</cfif>

<cfquery name="UpdateRecord" result="updateResult"
 AttributeCollection="#QueryAttributes#"
    >
 ...
</cfquery>

(This functionality was introduced with CF8.)

Peter Boughton