Issue with ColdFusion Query of Query after upgrading ColdFusion server from CF9 to CF21 - coldfusion

I cannot figure this out. My company recently upgraded our ColdFusion Server from CF9 to CF2021. One of my pages uses queries of queries to run. Prior to the upgrade the page worked fine. However after the upgrade the query of query where statement is not returning any results. Even though the original query has the data. The data is coming from DB2 data source in case that changed with the new version.
<cfquery name = "query_data_sample" dbtype="query">
SELECT
SAMPLE_DATE
, SAMPLE_NBR
, SAMPLE_MISC_NBR
, SUM (RECD_QTY) AS TTL_RECD_QTY
, SUM (MISC_QTY_1) AS TTL_MISC_QTY_1
, SUM ( 1 ) AS TTL_COUNT
FROM original_query_result
WHERE 1=1
AND SAMPLE_DATE = <cfqueryparam value = "#original_query_result.SAMPLE_DATE#" cfsqltype = "CF_SQL_DATE">
AND SAMPLE_NBR = <cfqueryparam value = "#trim(original_query_result.SAMPLE_NBR)#" cfsqltype = "CF_SQL_CHAR">
AND SAMPLE_MISC_NBR = <cfqueryparam value = "#trim(original_query_result.SAMPLE_MISC_NBR)#" cfsqltype = "CF_SQL_CHAR">
GROUP BY
SAMPLE_DATE
, SAMPLE_NBR
, SAMPLE_MISC_NBR
</cfquery>
When I comment out the AND statements and dump out the above query I can see the output of the original_query_result with all the TTL values and Sample rows. However if I want to grab just one row with the AND statements then the query comes back as not finding the row. I am doing a cfoutput query = original_query_result and trying to get the total quantity to display on each row in my output grid table.
Any help would be greatly appreciated. I have been trying to figure this out for more then a week now.

I saw something similar a while back and found this post:
https://web.archive.org/web/20180210052449/http://blog.dkferguson.com/index.cfm/2010/2/17/Using-Querie-of-Queries-with-CFDirectory
Basically I had to CAST the date and use cfqueryparam (as you are):
SAMPLE_DATE = CAST(<cfqueryparam value="#original_query_result.SAMPLE_DATE#" cfsqltype="CF_SQL_DATE"> AS date)
The post said they had to cast both sides but I didn't find this.

Related

Character dropped in BIND expression

I have run into an interesting situation while upgrading some legacy code from CF10 to CF2018. A query is segmented in string pieces in a webpage and passed through a CFGRID BIND statement to a query in a .cfc file.
The .CFC handles several webpages for the CFGRID. The various webpages provide input fields for filtering the data in the grid, such as searches, dates, etc.
Several of the queries use the JOIN (+) shortcut notation in the WHERE statement.
My problem is that somewhere between the CFGRID and the .CFC, the "+" is getting dropped and replaced with a space.
DisplayHistoryReceived.cfm
Conditions = "t.CPNId = pn.CPNId(+)
AND t.PartId = p.PartId
AND t.POId = po.POId(+)
AND t.LocationId = l.LocationId
AND l.BuildingId = b.BuildingId
AND t.StatusCodeId = sc.StatusCodeId(+)
AND t.TransTypesId = 1
AND po.OwnerId = o.OwnerId"
DisplayGrid-HTML.cfm
<CFGRID
BIND="cfc:#application.area#.Components.Global.DrillDown.SearchGrid({dSource},{queryFieldNames},
{tableNames},{Conditions},{SearchField#change},SearchInput#keyup},{BooleanSelect#change},{BoolField},
{DFilters},DFilterLine1},{DFilterLine2},{DFilterLine3},{DateRange},{DateAfter},{DateBefore},{OrderBy},
{GroupBy},{pSize},{cfgridsortcolumn},{cfgridsortdirection},{cfgridpage},{cfgridpagesize})"
DrillDown.cfc
<CFQUERY NAME="grd" DATASOURCE="#dSource#">
SELECT DISTINCT #Fields#
FROM #PreserveSingleQuotes(Tables)#
WHERE #PreserveSingleQuotes(Conditions)#
<!--- Used to filter based on a TEXT search --->
<cfif '#sInput#' neq ''>
AND #sField# like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#sInput#%"/>
</cfif>
[more CFIF statements follow]
The error message that I get is: [Macromedia][Oracle JDBC Driver][Oracle]ORA-00904: "SC"."STATUSCODEID": invalid identifier
But this excerpt from the error message leads me to think that something may have happened in CF2018 instead:
WHERE t.CPNId = pn.CPNId( )
AND t.PartId = p.PartId
AND t.POId = po.POId( )
AND t.LocationId = l.LocationId
AND l.BuildingId = b.BuildingId
AND t.StatusCodeId = sc.StatusCodeId( )
AND t.TransTypesId = 1
AND po.OwnerId = o.OwnerId
Any ideas, besides rewriting all the queries with standard JOINS? There are several pages scattered throughout the site that use this.

PreparedStatement.setNString(int,java.lang.String) error trying to use Query of Queries

I have a simple Query of Queries statement like this:
<cfquery name="rsProductTypeID" dbtype="query">
SELECT
ProductTypeID
FROM
rsProductTypes
WHERE
ProductType = <cfqueryparam value="Computers" cfsqltype="cf_sql_nvarchar"/>;
</cfquery>
All it is doing is asking for the primary key value (ProductTypeID) from the recordset rsProductType depending on which ProductType we are asking for.
For some reason the above query gives me this error:
PreparedStatement.setNString(int,java.lang.String)
But if I change the Query of Queries and remove the <cfqueryparam> part and replace it with normal text, then it works fine. Here is the working code:
<cfquery name="rsProductTypeID" dbtype="query">
SELECT
ProductTypeID
FROM
rsProductTypes
WHERE
ProductType = 'Computers';
</cfquery>
I can't tell what the difference is between the code that is causing it to fail when using <cfqueryparam> and not.
I think I figured it out... when ColdFusion returns a recordset, it doesn't maintain the original datatype from the database. In my database ProductType is defined as nvarchar(50) but ColdFusion returns it as varchar format. So the cfsqltype attribute was causing the error. I changed the cfsqltype attribute to cf_sql_varchar and it works fine. Very annoying but what can you do.
I posted it as a self-answer in case anyone else gets this error. Not sure if that's against the rules or not.
cf_sql_nvarchar is not a valid value for the cfsqltype attribute of cfqueryparam
Docs: https://wikidocs.adobe.com/wiki/display/coldfusionen/cfqueryparam

CF QoQ is throwing runtime error. "Column reference is not a column in any of the tables of the FROM table list."

In my code, I first create the Query Object:
<cfset memberData = QueryNew('slug,pos,firstname,lastname,email') />
<cfset temp = QueryAddRow(memberData, #numMembers#) />
<!--- LOOP POPULATES QUERY OBJECT --->
<cfloop...</cfloop>
I can then verify that it has been populated by running the following (which outputs as expected):
<cfoutput query="memberData">
#slug# - #pos#<br>
</cfoutput>
I then try to query the memberData Query Object and all hell breaks loose. If I run:
<cfquery name="members" dbtype="query">
SELECT slug,pos,firstname,lastname
FROM memberData
WHERE slug = #slug#
</cfquery>
I get this error:
Query Of Queries runtime error.
The select column reference [university] is not a column in any of the tables of the FROM table list.
In the output test mentioned above, I can verify that "university" is one of the values in the slug column. Clearly I'm missing something in my approach, but I'm baffled as to what it might be. Any help would be greatly appreciated!
Query Of Queries runtime error.
The select column reference
[university] is not a column in any of the tables of the FROM table
list
Your error was caused by absence of quotes in where clause and nothing else:
This expression find rows where the value in slug column equals the value in CF slug variable (String):
WHERE slug = '#slug#'
On the other hand this expression means find rows where value in the slug column equals the value contained in the column named in the CF slug variable (String):
WHERE slug = #slug#
The most likely cause of why you needed to change to SELECT * is CF query caching. So changing it back now should solve the problem. And always use <cfqueryparam .../> as suggested by "Al Everett"
Well, it's not quite answering the question asked, but it's close enough for what I needed:
<cfquery name="members" dbtype="query">
SELECT *
FROM memberData
WHERE slug = '#slug#'
</cfquery>
I had tried the wrapping #slug# in single quotes prior to posting with no success, but doing that plus changing the query to SELECT * fixed the issue. For my content, * only adds one more value retrieved, so not really a problem in slowing down the process.

How can I insert an expiration date into a table and having messages expire without breaking functionality?

I’m using Coldfusion 9,0,0,251028 on Windows 7 64-bit, with a Microsoft Access 97 database.
The code is for an application that takes a submitted message from a form and posts it to a different page (breakingnews.cfm). The form values are inserted into the "news" table on a database, including the date the message was submitted (mes_dat) and the date it should expire (exp_dat).
On the database, the is_current and display columns have a default value of 0.
The form action is new_process.cfm, which does two things:
1) Does <cfset expdate = createdate(end_year, end_month, end_day)>. End_year, end_month, and end_day are dropdown selectors that set the expiration date. A problem I have had is expdate not being able to be inserted by post_breaking.cfm, but only when it is put online, on my local testing server there seems to be no problem.
2) Includes a template named "post_breaking.cfm", which runs these queries:
<cfquery name="get_init_info" datasource="#db#">
select id
from news
where is_current = 1
</cfquery>
<cfquery name="update_info_1" datasource="#db#">
update news
set is_current = 0, scrollshow = 0
</cfquery>
<cfif get_init_info.recordcount NEQ 0>
<cfquery name="update_info_2" datasource="#db#">
update news
set display = 1
where id = #get_init_info.id#
</cfquery>
</cfif>
<cfquery name="put_in_info" datasource="#db#">
insert into news
(is_current, display, mes_dat,mes_tim,mes_sub,mes_text,scrollshow, exp_dat)
values
(1,0, #createodbcdate(now())#, #createodbctime(now())#, '#subject#', '#message#',1, #expdate#)
</cfquery>
The message is then displayed on breakingnews.cfm if the column is_current on the news table is 1. This is code I have inherited, so I'm not sure how it does it, but the code only allows 5 messages at a time to have is_current = 1.
The part I'm trying to make happen is having a query run when breakingnews.cfm loads that checks if exp_dat is between now() and mes_dat to set is_current to 1, while still maintaining only 5 items having an is_current of 1.
When breakingnews.cfm is accessed it runs these queries:
<cfquery name="get_info" datasource="#db#">
select *
from news
where
<cfif not isdefined("id")>
is_current = 1
<cfelse>
id = #id#
</cfif>
order by mes_dat desc, mes_tim desc
</cfquery>
<cfquery name="add_exp" datasource="#db#">
UPDATE news
SET is_current = 1
WHERE now() BETWEEN mes_dat AND exp_dat
</cfquery>
<cfquery name="remove_exp" datasource="#db#">
UPDATE news
SET is_current = 0
WHERE now() NOT BETWEEN mes_dat AND exp_dat
</cfquery>
This will cause the messages that have an exp_dat between now() and mes_dat to be displayed and otherwise not display on breakingnews.cfm.
However, when a new message is submitted, upon accessing breakingnews.cfm the first time, only the newly submitted message is displayed.
If the page is refreshed, the messages that were filtered correctly will be displayed under the new message, but there will now be six items displaying on the page when there should only be five.
How can I get the correct amount of messages, and have them display the first time without needing a refresh?
I've gotten advice to replace the get_init_info query with
<cfquery name="get_init_info" datasource="#db#">
select id
from news
where exp_dat > now()
</cfquery>
but that caused all other rows in is_current and scrollshow to be changed to 0 after creating a new message (though the new message's scrollshow and is_current are 1).
My fist thought is to change how the system gets the news to display, but since you sppear not to have control of that, here's my suggestion. Please bear in mind that I've never used Access, so I'm using MS-SQ syntax.
Get the ids of the 5 items you want
select top 5 id
from bews
where exp_date > #createodbcdate(now)#
and display = 1
Now, set display = 0 on all items.
Finally, re-display the ids you found earlier.
update news
set display = 1
where id in #valuelist(query, "id")
If you have questions or corrections, feel free to comment.

ColdFusion Executing Queries Parallel (Data not updating)

I do an update and then I try to get back the updated value of the field of which was updated. The issue however, is I am not getting the updated value, rather the prior value. I know the update works correctly because if I query it shows the returned data. I have tried cftransaction isolation="serializable" but it does not work.
My code is below, is there a way around this or will I have to make 2 AJAX request for simpe issue?
<cfquery datasource="#application.datasource#">
UPDATE gt_timesheet
SET
phaseid=<cfqueryparam value="#form.phase#" cfsqltype="CF_SQL_INTEGER">,
projectid=<cfqueryparam value="#form.project#" cfsqltype="CF_SQL_INTEGER">
WHERE
timesheetid=<cfqueryparam value="#form.timesheetid#" cfsqltype="CF_SQL_INTEGER">
</cfquery>
<cfquery name="phase" datasource="#application.datasource#">
SELECT status,
(
SELECT ROUND(sum(time_to_sec(duration))/3600,2)
FROM gt_timesheet
WHERE gt_timesheet.phaseid=gt_phases.phaseid
) as billedbillablehours,
(
SELECT ROUND(sum(time_to_sec(hours))/3600,2)
FROM gt_services
WHERE gt_phases.phaseid=gt_services.phaseid
) as billablehours
FROM gt_phases
WHERE phaseid=<cfqueryparam value="#form.phase#" cfsqltype="CF_SQL_INTEGER">
</cfquery>
This is making me go nuts because this language is constantly making tasks that should be simple tedious.
You don't have a CF problem, you have an SQL problem, and I think its the subqueries. First why a subquery and not a join?
Can you confirm that they are 1:1 relationships in the subqueries, because if they are one to many you are just going to get the first match.
I don't know your database schema, but doing it the way you currently are i think the SELECT needs to have the table match based on the form field you have just updated
<cfquery name="phase" datasource="#application.datasource#">
SELECT status,
(
SELECT ROUND(sum(time_to_sec(duration))/3600,2)
FROM gt_timesheet
WHERE gt_timesheet.phaseid=<cfqueryparam value="#form.phase#" cfsqltype="CF_SQL_INTEGER">
) as billedbillablehours,
(
SELECT ROUND(sum(time_to_sec(hours))/3600,2)
FROM gt_services
WHERE gt_services.phaseid=<cfqueryparam value="#form.phase#" cfsqltype="CF_SQL_INTEGER">
) as billablehours
FROM gt_phases
WHERE phaseid=<cfqueryparam value="#form.phase#" cfsqltype="CF_SQL_INTEGER">
</cfquery>
Hope that gets you somewhere, if not I think you need to explain the database schema more.
ColdFusion does not execute anything in the same request in Parallel unless you use <cfthread>
How is the duration updated after you run the first Update statement? Does it call a trigger? Possibly that is causing the update of the "duration" field to run after the second query. You could try adding a 1 second sleep after the first query to make sure the second query gets the correct value.
I guess you are missing something in the update statement. Why don't you re-evaluate the query's once again.