How to execute multiple cfquery one after another in coldfusion 8? [closed] - coldfusion

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last year.
Improve this question
How to execute multiple cfquery one after another. First execute and completion the first cfquery then proceed to next cfquery execution and move to another cfquery. All the below cfquery are in one single page.
//--------first cfquery--------//
<cfquery name="first" datasource="test">
Delete from tab where id='123'
</cfquery>
//--------second cfquery--------//
<cfquery name="first" datasource="test">
insert into tab (id,name,age) values ('123','xxx','37')
</cfquery>
//--------Third cfquery--------//
<cfquery name="first" datasource="test">
select * from tab where id='123'
</cfquery>

Queries are executed subsequently in ColdFusion. Your issue is rather related to the script being executed several times in parallel.
Executing the script multiple times in parallel causes concurrency issues. That means, the queries get sent to the database server from different script calls at the same time and there is no guaranteed order in which they are executed.
There are two things you should do to avoid these concurrency problems.
Put all of them in one <cfquery>
Putting them all in one <cfquery> the queries get sent to the server all at once. This puts the database server in charge of executing them. And it executes them in order.
<cfquery name="query" datasource="test">
delete from tab where id='123';
insert into tab (id,name,age) values ('123','xxx','37');
select * from tab where id='123';
</cfquery>
Wrap them in a <cftransaction>
Wrapping your queries in a <cftransaction> block allows the database engine to execute all of them as a single transaction. You can imagine that as an "all or nothing" action.
Besides that it allows you to catch errors and revert your changes if something goes wrong.
<cftransaction>
<cftry>
//--------first cfquery--------//
<cfquery name="first" datasource="test">
Delete from tab where id='123'
</cfquery>
//--------second cfquery--------//
<cfquery name="second" datasource="test">
insert into tab (id,name,age) values ('123','xxx','37')
</cfquery>
//--------Third cfquery--------//
<cfquery name="third" datasource="test">
select * from tab where id='123'
</cfquery>
<cftransaction action="commit" />
<cfcatch type="any">
<cftransaction action="rollback" />
</cfcatch>
</cftransaction>

Thanks everyone for the time...much appreciated.
Well, I fixed this issue by separating in two page....first page executes delete operation and second page for insert. Cheers

Related

Cfquery causing XSS and SQL Injection issues

I ran an application scan (IBM) recently and now I'm trying to fix the issues that came up. A good majority of my issues stem from a cfquery (see below). I'm trying to get it so that Stored XSS and SQL injections issues don't show up on my scans. Any help would be greatly appreciated, as this is my first time doing something of the sort.
Thanks!
<cfquery name="enter_question" datasource="#dsn#">
INSERT INTO xx_questions(q_id,
q_name,
q_narrative,
q_used,
q_type)
VALUES( #variables.new_q_id#,
'#form.q_name#',
'#form.q_narrative#',
'n',
#form.q_type#)
</cfquery>
Each query that contains user inputs should have cfqueryparam like so:
<cfquery name="enter_question" datasource="#dsn#">
INSERT INTO xx_questions(q_id,
q_name,
q_narrative,
q_used,
q_type)
VALUES(
<cfqueryparam cfsqltype="CF_SQL_INTEGER" value="#variables.new_q_id#"/>,
<cfqueryparam cfsqltype="CF_SQL_CHAR" value="#form.q_name#"/>,
<cfqueryparam cfsqltype="CF_SQL_CHAR" value="#form.q_narrative#"/>,
<cfqueryparam cfsqltype="CF_SQL_CHAR" value="n"/>,
<cfqueryparam cfsqltype="CF_SQL_INTEGER" value="#form.q_type#"/>)
</cfquery>
The cfsqltype will need to reflect the data type in the xx_questions table for the cooresponding column - but you get the idea.
Binding the variable to a type in this manner automatically protects you against SQLi injection. XSS injection is something else. That's when user input is output onto the page. If a user pushes something (say a script tag) into a column in the DB and then it is output onto the page you haven't really suffered from injection (they gave you a character column, you put in a character column, they did not change the nature of the query). But in a forum app or any other area where user input from one user is shown to another you have the potential for malicious code infections.
For that each of your character types needs to be vetted for malicious code. Using something like Foundeo as a Web application Firewall can do this. You can also protect your page at a server level using the CF admin or at an application level using the scriptprotect attribute of the cfapplication tag or props in the application.cfc.
You can also manually protect within your DB inserts using HTMLEditformat like so:
<cfqueryparam cfsqltype="CF_SQL_CHAR" value="#htmleditformat(form.q_narrative)#"/>,
... or you can check each user input against a list of known allowed inputs (if the data is predictable). These techniques should be part of your "best practice" list if possible. :)
You need to use <cfqueryparam>. Check the documentation at: https://wikidocs.adobe.com/wiki/display/coldfusionen/cfqueryparam
Try something like this (you should change the CFSQLType to match whatever your DB columns are):
<cfquery name="enter_question" datasource="#dsn#">
INSERT INTO xx_questions(q_id,
q_name,
q_narrative,
q_used,
q_type)
VALUES(
<cfqueryparam value="#variables.new_q_id#" CFSQLType="CF_SQL_INTEGER">,
<cfqueryparam value="#form.q_name#" CFSQLType="CF_SQL_VARCHAR">,
<cfqueryparam value="#form.q_narrative#" CFSQLType="CF_SQL_VARCHAR">,
<cfqueryparam value="n" CFSQLType="CF_SQL_CHAR">,
<cfqueryparam value="#form.q_type#" CFSQLType="CF_SQL_INTEGER">
)
</cfquery>

Move a row to the beginning of a query

I have a recordset of messages, some of which are are from a group named "ADMIN". I want all the messages from the "ADMINS" placed at the top of the query object but I can't re-order them within the original query -- I have to do it after I already have the query object. I have a way to see which rows are from "ADMINS" but I'm not sure the best way to extract them from the query object and put them at the top.
<!--- this is the query object of all the messages --->
<cfset messageData = application.message.getMessages(inboxID)>
<!--- this returns a list of which users inside the recordset are ADMINS --->
<cfset getAdmins = application.message.getAdmins(valueList(messageData.useridfk)) />
Now I want to take all the UserIDs returned in #getAdmins#, remove the messages that are theirs in #messageData# and put them at the top of #messageData# so I can output the results. Is this a QoQ or is there a better way?
I can't really get my head around the QoQ, but I'm taking a stab at it. IS there a better way then doing THREE different QoQs?
<!--- this gets all the rows from Admins --->
<cfquery name="getAdminAnswers" dbtype="query">
SELECT *
FROM messageData
WHERE useridfk in ('#getAdmins.id#')
ORDER BY UpvotesNum DESC, posted DESC
</cfquery>
<!--- this gets all the rows from non-RDs --->
<cfquery name="getNonAdminAnswers" dbtype="query">
SELECT *
FROM messageData
WHERE useridfk NOT IN ('#getAdmins.id#')
ORDER BY UpvotesNum DESC, posted DESC
</cfquery>
<!--- join the queries with a UNION in a QoQ --->
<cfquery dbtype="query" name="data">
SELECT * FROM getAdminAnswers
UNION
SELECT * FROM getNonAdminAnswers
</cfquery>
Answer:
Got it: Like this:
<!--- this combines two queries into one --->
<cfquery name="data" dbtype="query">
SELECT *, 1 sortCol
FROM messageData
WHERE useridfk in ('#variables.getAdmins.id#')
UNION
SELECT *, 2 sortCol
FROM messageData
WHERE useridfk NOT IN ('#variables.getAdmins.id#')
ORDER BY sortCol, UpvotesNum DESC, posted DESC
</cfquery>
I can't see that there's a more expedient way of doing this without using QoQ, no. It's kinda what it's for: these exceptional circumstances where the app needs both the original data as from the DB, and a variation of it as well.
Can you say
SELECT *,
(CASE WHEN USERIDFK IN ('#getadmins.id#') THEN 1 ELSE 0 END) as mRank
FROM MessagesTableName
ORDER BY mRank DESC, UpvotesNum DESC, posted DESC
That would be the SQL Server Syntax anyway, I'm not sure what SQL flavor you're using.
I realize that all three queries are QoQs, but with just one query to get your admin list, this direct query to the db might work.
(Previously, I was unsure if you could use CASE in QoQ. You can't, so if this works at all, it would have to a direct query to the database.)

Compare mysql query to sql query

I am a lot more at home manipulating arrays and objects in php or javascript, and do next to no work with coldfusion.
I have one query pulling data from mysql. I would like to store results list or array ( or simpler approach)
WHile looping over a second query from msql that generates html output I need to see if one value is contained in prior mysql array or list.
Have tried playing with varierty of cf array/list methods and really not sure what best approach is to resolve following if.
CF version is 9
<cfquery datasource="Mysql" name="premium_submitters">
SELECT submitter_id from table
</cfquery>
<!--- Need loop to store to array or list??--->
<cfquery datasource="Sql" name="main_data">
SELECT * from table
</cfquery>
<cfoutput query="main_data">
<cfif #submiiter_id# <!---is in Mysql array/list return boolean---> >
</cfif>
</cfoutput>
Use ValueList to get the value of one column of a query into a list.
<cfquery datasource="Mysql" name="premium_submitters">
SELECT submitter_id from table
</cfquery>
<cfset submittersList = ValueList(premium_submitters.submitter_id)>
<cfquery datasource="Sql" name="main_data">
SELECT * from table
</cfquery>
<cfoutput query="main_data">
<cfif ListFind(submittersList, main_data.submitter_id) gt 0>
<!--- is in list, do whatever --->
</cfif>
</cfoutput>

Only show if item is not most recent?

So we have a news/announcement function that pulls info from a database and displays it
<cfquery name="announcement" datasource="#application.datasource#" dbtype="odbc">
SELECT top 2 * FROM NewsEvents
WHERE type = 2 AND active = 1 AND publish_datetime <= #now()# AND show_on_home = 1 AND item_datetime >= #createOdbcDate(now())#
ORDER BY item_datetime ASC
</cfquery>
What we're trying to do is display a piece of HTML within these announcement blocks, conditional on one of the two blocks NOT being the most recent of the two blocks.
The HTML is wrapped in this code:
<cfif announcement.recordCount gt 0>
<cfloop query="announcement">
<cfoutput>
html
</cfoutput>
</cfloop>
<cfelse>
<cfoutput><p>There are currently no announcements.</p></cfoutput>
</cfif>
I want one component of the HTML to only be displayed for the BOTTOM announcement, the one that is not the closest in item_datetime. Any thoughts on how to accomplish this?
You're ordering by date, so just do something like this:
<cfif CurrentRow EQ 1>
We're showing the first record, so show some stuff.
</cfif>
CurrentRow is always available in a loop to show you which record of the query you're currently on. So given your current query (and some made up data straight outta my head, you'll end up with this output:
Record 1: August 29, 2011
We're showing the first record, so show some stuff
Record 2: August 30, 2011
You're sorting by the date ASC, so the oldest record is first, while the newer record is last. I would recommend that you change your sorting to DESC, or you're never going to get newer records once you've added a third announcement after the first two. You could then resort them on the CF side to be in the display order you're after.
You can add a modifier to your CFQUERY statement like so. I would also modify your CFIF recordCount statement to look for more than 1 record at this point.
<cfif announcement.recordCount gt 1>
<cfoutput query="announcement" startRow="2">
<!--- Throw my output here --->
</cfoutput>
<cfelse>
<p>There are currently no announcements.</p>
</cfif>

Session Variables, welcome messages

Why does this not work? My welcome message, it just doesn't show up:
<p>Welcome <cfoutput>#Recordset1.UserID#</cfoutput>.</p>
The session variable on the login page I created is:
<cflock timeout=999 scope="Session" type="Exclusive">
<cfset Session.IDUsers =''>
</cflock>
is this incorrect? On the index page where I'm trying to display my welcome message I have:
<cfquery name="Recordset1" datasource="cfGossip">
SELECT *
FROM users
WHERE users.IDUsers = <cfqueryparam value="#Session.IDUsers#">
</cfquery>
I'm not sure if this works, or is necessary?
If you set the userid stored in the session to be the empty string, when you query on it, you will only get users for whom the id is the empty string, which shouldn't be any of them. Therefore, the query is returning an empty set, and your page is (correctly) not displaying a user id.
How are you initially identifying the user? Are you querying against a database when they log in? Are you storing a cookie? Reading Tarot cards? For this to work, at some point, you have to store the correct userid, probably in the session. To do that, you need to first identify who the user is.
Also, if you are using CF6+, you probably do not need the cflock. It is now used to prevent race conditions, as CF is now thread-safe.
Looks like you're just starting with CF, welcome to the community.
My understanding of your code makes the structure look like the following, if I'm understanding you correctly:
<cfset session.idUsers = '' />
<cfquery datasource = "cfgossip" name = "recordset1">
SELECT * FROM USERS WHERE USERS.ID_USERS = <cfqueryparam cfsqltype = "cf_sql_integer" value = "#session.idUsers# />
</cfquery>
<cfoutput>Welcome #recordset1.userID#</cfoutput>
The reason this doesn't work is because your session.idUsers value is blank. Assuming you have a user in your database with an ID_USERS value of 1, you could change the CFSET to look like and it should return results.
Additionally, while it's great to see you using CFQUERYPARAM, I'd recommend including a CFSQLTYPE attribute in the tag whenever possible to provide an added line of defense against injection attacks. You can check out http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=Tags_p-q_18.html to see the list of available types.
Is there anywhere in your code where you set your session.IDUsers? You initialize it as a blank ''. Coldfusion does not populate it for you. The session scope is a place that will remember things for that user that you put there for a specified period of time inactivity, usually 20 minutes. So hopefully, somewhere before you run your query you have additional logic that fills that in, otherwise you are asking the database for a user named, ''.
This is just a point of style, but the following may work better for you:
<cfset Session.IDUsers =''>
<!--- Do something here to populate Session.IDUsers --->
<!--- Creates a blank query - not necessary, but can reduce errors later --->
<cfset Recordset1 = queryNew("UserID")>
<!--- Populate the query from the database --->
<cfquery name="Recordset1" datasource="cfGossip">
SELECT *
FROM users
WHERE users.IDUsers = <cfqueryparam value="#Session.IDUsers#">
</cfquery>
<!--- If the query has data, use it, otherwise show generic message --->
<cfoutput>
<cfif Recordset1.recordcount>
<p>Welcome #Recordset1.UserID#.</p>
<cfelse>
<p>Welcome new user!</p>
</cfif>
</cfoutput>
<!--- OR since we used queryNew("userID"), we can simplify without throwing an error. ---->
<cfoutput>
<p>Welcome <cfif len(Recordset1.userID)>#Recordset1.userID#.<cfelse>new user!</cfif></p>
</cfoutput>
Putting the cfoutput outside the paragraph block will make it easier if you have additional variables to insert into the text. (but will work either way)
Regardless of all that, unless you forgot to share a bit more of the code, I think the issue is that the session.IDUsers is blank and needs to be populated before the query. I hope this helps!