CF11 QoQ search for a square bracket character - coldfusion

In a ColdFusion 11 application, I have a query object that contains strings that include an opening square bracket character - [. I need to be able to do a query of queries (QoQ) search of that query object to find any records that include the [ character, but I can't seem to find a way to escape it.
The best suggestion I've found - LIKE '%[[]%' - returns no results.
This code returns an error message:
<cfquery name="temp" dbType="query">
SELECT *
FROM myQuery
WHERE myField LIKE '%[%'
</cfquery>
This code also returns an error message:
<cfquery name="temp" dbType="query">
SELECT *
FROM myQuery
WHERE myField LIKE '%\[%' ESCAPE '\'
</cfquery>
And this code returns no records at all, even though I know the character is there:
<cfquery name="temp" dbType="query">
SELECT *
FROM myQuery
WHERE myField LIKE '%[[]%'
</cfquery>
Any suggestions would be greatly appreciated. Thanks.

You were close. Using the link that gfrobenius posted, you get this:
<cfquery name="temp" dbType="query">
SELECT *
FROM myQuery
WHERE myField LIKE '%[\[ ]%'
</cfquery>

Related

Is there a shorter way to do this than qoq in coldfusion

I often have to switch between a code and name from a query in my code. Here's what it looks like:
<cfquery name="AllLocations" >
Select Name, Code From Locations
</cfquery>
Later in the page I will need the name and have the code, or visa-versa:
<cfquery name="ThisLocation" dbtype="query >
Select Name From Locations where Code = '#Code#'
</cfquery>
<cfoutput>#ThisLocation.Name#</cfoutput>
Is there a shorter way to do this so I don't have to do the qoq every time?
You could do something like this:
<cfoutput>
#allLocations.name[listfind(valuelist(allLocations.code), code)]#
</cfoutput>
Edit starts here
Given the comment about performance, I understand that arrays are faster than lists.
<cfoutput>
#allLocations.name[arrayFind(allLocations['code'], code)]#
</cfoutput>

Var scoping issue possibly?

A few times in my functions I have stuff like this:
<cffunction name="mergeData">
<cfquery name="myQuery">
SELECT columnName FROM tableName
</cfquery>
<cfquery dbtype="query" name="myOtherQuery">
SELECT columnName FROM myQuery
</cfquery>
</cffunction>
<cfset resulta = mergeData(queryA) />
<cfset resultb = mergeData(queryB) />
<cfset resultc = mergeData(queryC) />
Occasionally then I get the error The select column reference [myQuery.columnname] is not found in table [myQuery].
So what could be causing this. How can I diagnose. I was thinking it could be a scoping issue, so I'm going to add <cfquery name="local.myQuery"> just to make sure things are contained in the function (I should be doing that anyway probably). But when something only happens sometimes I have a hard time figuring out how to diagnose.
EDIT: Added some clarity on why it's most likely a scoping issue. My thought is that myQuery is poossibly being referenced in other calls. I mean, it's not like it's running multiple threads on the data, but is it possible that that could be the cause? Are there other causes? This isn't always the case when I get the error. I also get it on a page where it function is only running once.
In the query of queries, use brackets around the local scope prefix.
<cffunction name="mergeData">
<cfquery name="local.myQuery">
SELECT columnName FROM tableName
</cfquery>
<cfquery dbtype="query" name="local.myOtherQuery">
SELECT columnName FROM [local].myQuery
</cfquery>
</cffunction>
<cfset resulta = mergeData(queryA) />
<cfset resultb = mergeData(queryB) />
<cfset resultc = mergeData(queryC) />
I've never gotten LOCAL to work in query of queries in a function.
So I do this....
<cffunction>
<cfquery name="VARIABLES.myQuery">
SELECT columnName FROM tableName
</cfquery>
<cfquery dbtype="query" name="myOtherQuery">
SELECT columnName FROM VARIABLES.myQuery
</cfquery>
<cffunction>
I strongly suggest using a more explicit name for your query, especially in query of queries.

Stripping CGI.HTTP_REFERER and CGI.SCRIPT_NAME in Coldfusion

I have the block of code below which runs a query and checks for an existing record and runs a second insert query if no record is found.
<cffunction name="EndRequestFunc" access="public" returnType="string">
<!---Queries Table To Get Requested Record--->
<cfquery name="qryGetPageRecord" datasource="First_Main_Dev"
dbname="First_Services_Dev">
SELECT pageName
FROM tblCFMPageRequest
WHERE pageName = '#CGI.HTTP_REFERER#' AND scriptName =
'#CGI.SCRIPT_NAME#'
</cfquery>
<!---Conditional Check for record count equal to 0--->
<cfif qryGetPageRecord.recordCount eq 0>
<!---If record count equal to 0, recordset query executed--->
<cfquery name="setNewRecord" datasource="First_Main_Dev"
dbname="First_Services_Dev">
INSERT INTO tblCFMPageRequest
VALUES ('#CGI.HTTP_REFERER#', '#CGI.SCRIPT_NAME#')
</cfquery>
</cfif>
</cffunction>
What I need to do is strip the values of the two CGI variables of all formatting so that a value like this "example.com/portal/mypage.cfm" will be stripped of http and everything else down everything to just mypage.cfm before its inserted by the query. Any guidance would be appreciated.
Update: Thank to the advice given, I was able to eliminate the http://example.com/ portion of the URL using the ListLast function.
I was short sighted in not remembering my urls have characters that need to be eliminated after the "cfm" point. Here is one of my actual results from ListLast: client_modify.cfm?uid=248&al=1&a_trigger=1.
I've tried using some other List functions in Coldfusion to no avail as of yet. Any advice on how to eliminate the bold portion of:
client_modify.cfm ?uid=248&al=1&a_trigger=1 so I'm just left with a clean client_modify.cfm
Use ListLast() function with / as a delimiter. Also, always try to use cfqueryparam to put values in queries. Like this.
<cfquery name="setNewRecord" datasource="First_Main_Dev" bname="First_Services_Dev">
INSERT INTO tblCFMPageRequest
VALUES (<cfqueryparam cfsqltype="cf_sql_varchar" value="#ListLast(CGI.HTTP_REFERER,'/')#">, <cfqueryparam cfsqltype="cf_sql_varchar" value="#ListLast(CGI.SCRIPT_NAME,'/')#">)
</cfquery>
CGI variables shouldn't have any "formatting", so your question is a bit confusing.
If you're just looking to get the filename at the end of the string, you can use the list functions.
fileIwant = ListLast(CGI.SCRIPT_NAME,"/");
If CGI.SCRIPT_NAME is /wwwroot/example/index.cfm, fileIwant will result in index.cfm.
Have a care with the referrer, as it may not be defined and parsing it out will throw an error.

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.)

can't define id ColdFusion

here is my ColdFusion code:
Example1:
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT PRODUCT_CATID
FROM PRODUCT_CAT
WHERE PRODUCT_CATID = PRODUCT_CATID
</cfquery>
#get_brand.product_catid#
But it shows all the time number 1, i just can't understand why, and how do i make it work properly, this code should have defined the brand_id, but instead shows 1.
The system is Workcube.
Here is my example for getting from the static product's id, its dynamic price:
Example 2:
<cfset product_id = 630>
<cfquery name="price_standart" datasource="#dsn3#">
SELECT
PRICE_STANDART.PRICE PRICE
FROM
PRICE_STANDART
WHERE
PRICE_STANDART.PRODUCT_ID =
<cfqueryparam value="#product_id#" cfsqltype="cf_sql_integer">
</cfquery>
But this time i need to get from dynamic product's ID its dynamic brand id.
This script works the same way as the Example 1:
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT BRAND_ID
FROM PRODUCT_BRANDS
WHERE BRAND_ID = BRAND_ID
</cfquery>
#get_brand.BRAND_ID#
As Andreas shows in his code, your query isn't going to work as written. The statement WHERE PRODUCT_CATID = PRODUCT_CATID doesn't actually pass a value - it would actually just be self-referential within the table values. In this case, it would return everything in the table.
You should instead have:
WHERE PRODUCT_CATID = #PRODUCT_CATID#
Where #PRODUCT_CATID# represents a variable. Better yet, use cfqueryparam as Andreas shows (this prevents SQL injection and improves query performance). However, I am not even sure that is what you intend since if you have the product ID why do you need to get it from the database? Instead, I assume you probably want to get the brands from the product in a particular category. Not knowing your table structure, it's hard to write that query for you but it might look something like:
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT PRODUCT.BRAND_ID
FROM PRODUCT
INNER JOIN PRODUCT_CAT
ON PRODUCT.PRODUCT_CATID = PRODUCT_CAT.PRODUCT_CATID
WHERE PRODUCT_CATID = <cfqueryparam cfsqltype="cf_sql_integer" value="#product_catid#">
</cfquery>
Lastly, as both comments indicate, you would need to loop through the results to see all the records returned.
You need to wrap the statement in tags like this.
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT PRODUCT_CATID FROM PRODUCT_CAT WHERE PRODUCT_CATID = PRODUCT_CATID
</cfquery>
<cfoutput query =GET_Brand">
#get_brand.product_catid#
</cfoutput>
It's not very clear what your question really is about, but let me guess:
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT PRODUCT_CATID
FROM PRODUCT_CAT
WHERE PRODUCT_CATID = <cfqueryparam cfsqltype="cf_sql_integer" value="#product_catid#">
</cfquery>
where #product_catid# refers to a variable you defined earlier in your code or received via form or url scope.
<cfloop query="GET_BRAND">
#get_brand.product_catid#<br />
</cfloop>
will show a list of all the product_catid's returned by the query.
It's not too clear what you are after here, but in the queries there are at least 2 problems. First your WHERE clause
WHERE PRODUCT_CATID = PRODUCT_CATID
is like saying
WHERE 1=1
This will return the full recordset. You can see this by adding
<cfdump var="#GET_BRAND#">
under your code to see the query output. I'm guessing this will show all records in the table.
To match just one record you need your WHERE clause to be like
WHERE PRODUCT_CATID = 3
or have the #...# wrapped around the variable you are trying to match to make it dynamic.
Secondly to the query result may be more than one record, and to see any more than the first record you need to loop over the output. One way is to use
<cfoutput query="GET_BRAND">
#BRAND_ID# <br>
</cfoutput>
My guess of what you are after is
<cfset ID_TO_MATCH=3>
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT BRAND_ID
FROM PRODUCT_CAT
WHERE PRODUCT_CATID = #ID_TO_MATCH#
</cfquery>
<cfoutput query="GET_BRAND">
#BRAND_ID# <br>
</cfoutput>