Check query results if no data is returned - coldfusion

I have a query that I am calling to update an email service. Most times it will have data in it, but in testing I came across the situation of it not returning any data because there was no data to return. In the case of no data it returns the error "Variable EDITEDACCTS is undefined".
I have tried wrapping the query in a <cftry> but it doesn't "fail" per se so it does not trip the <cfcatch>. I have also tried defining the variable
var EditedAccts = QueryNew("")
as well as simply trying
<cfif NOT isDefined(#EditedAccts#)>
and it always returns "Variable EDITEDACCTS is undefined".
I need a production ready solution to this and I'm hoping somewhere here on SO can help me out.
Thanks in advance for your help.

I have just found the answer. You set the "result" parameter in the query call and then you can check the recordcount field returned.
<cfquery name="EditedAccts" datasource="mydatasource" result="queryResult">
...query goes here...
</cfquery>
When using the "result" parameter you get a struct returned with the sql used, the cached setting, the execution time and the record count.
Now I can check the record count and proceed from there.
Hopefully this will help someone in the future.

I tried using result="queryResult" but when I tried to reference the query name I got something like this error - "The value of the attribute query, which is currently EditedAccts, is invalid". Instead, I used something like IsDefined("#EditedAccts#") - including the value in quotes did the trick for me. I am only new to ColdFusion but I am learning quickly that values in quotes are entirely different to values not in quotes, in terms of how a function will interpret a parameter.

Related

Handling invalid dates in Oracle

I am writing simple SELECT queries which involve parsing out date from a string.
The dates are typed in by users manually in a web application and are recorded as string in database.
I am having CASE statement to handle various date formats and use correct format specifier accordingly in TO_DATE function.
However, sometimes, users enter something that's not a valid date(e.g. 13-31-2013) by mistake and then the entire query fails. Is there any way to handle such rougue records and replace them with some default date in query so that the entire query does not fail due to single invalid date record?
I have already tried regular expressions but they are not quite reliable when it comes to handling leap years and 30/31 days in months AFAIK.
I don't have privileges to store procedures or anything like that. Its just plain simple SELECT query executed from my application.
This is a client task..
The DB will give you an error for an invalid date (the DB does not have a "TO_DATE_AND_FIX_IF_NOT_CORRECT" function).
If you've got this error- it means you already tried to cast something to an invalid date.
I recommend doing the migration to date on your application server, and in the case of exception from your code - send a default date to the DB.
Also, that way you send to the DB an object of type DbDate and not a string.
That way you achieve two goals:
1. The dates will always be what you want them to be (from the client).
2. You close the door for SQL Injection attacks.
It sounds like in your case you should write the function I mentioned...
it should look something like that:
Create or replace function TO_DATE_SPECIAL(in_date in varchar2) return DATE is
ret_val date;
begin
ret_val := to_date(in_date,'MM-DD-YYYY');
return ret_val;
exception
when others then
return to_date('01-01-2000','MM-DD-YYYY');
end;
within the query - instead of using "to_date" use the new function.
that way instead of failing - it will give you back a default date.
-> There is not IsDate function .. so you'll have to create an object for it...
I hope you've got the idea and how to use it, if not - let me know.
I ended up using crazy regex that checks leap years, 30/31 days as well.
Here it is:
((^(0?[13578]|1[02])[\/.-]?(0?[1-9]|[12][0-9]|3[01])[\/.-]?(18|19|20){0,1}[0-9]{2}$)|(^(0?[469]|11)[\/.-]?(0?[1-9]|[12][0-9]|30)[\/.-]?(18|19|20){0,1}[0-9]{2}$)|(^([0]?2)[\/.-]?(0?[1-9]|1[0-9]|2[0-8])[\/.-]?(18|19|20){0,1}[0-9]{2}$)|(^([0]?2)[\/.-]?29[\/.-]?(((18|19|20){0,1}(04|08|[2468][048]|[13579][26]))|2000|00)$))
It is modified version of the answer by McKay here.
Not the most efficient but it works. I'll wait to see if I get a better alternative.

Find model returns undefined when trying to get the attribute of a model by first finding the model by another attribute?

I would like to do something like:
App.Model.find({unique_attribute_a: 'foo'}).objectAt(0).get('attribute_b')`
basically first finding a model by its unique attribute that is NOT its ID, then getting another attribute of that model. (objectAt(0) is used because find by attribute returns a RecordArray.)
The problem is App.Model.find({unique_attribute_a: 'foo'}).objectAt(0) is always undefined. I don't know why.
Please see the problem in the jsbin.
It looks like you want to use a filter rather than a find (or in this case a findQuery). Example here: http://jsbin.com/iwiruw/438
App.Model.find({ unique_attribute_a: 'foo' }) converts the query to an ajax query string:
/model?unique_attribute_a=foo
Ember data expects your server to return a filtered response. Ember Data then loads this response into an ImmutableArray and makes no assumption about what you were trying to find, it just knows the server returned something that matched your query and groups that result into a non-changable array (you can still modify the record, just not the array).
App.Model.filtler on the other hand just filters the local store based on your filter function. It does have one "magical" side affect where it will do App.Model.find behind the scenes if there are no models in the store although I am not sure if this is intended.
Typically I avoid filters as it can have some performance issues with large data sets and ember data. A filter must materialize every record which can be slow if you have thousands of records
Someone on irc gave me this answer. Then I modified it to make it work completely. Basically I should have used filtered.
App.Office.filter( function(e){return e.get('unique_attribute_a') == 'foo'}).objectAt(0)
Then I can get the attribute like:
App.Office.filter( function(e){return e.get('unique_attribute_a') == 'foo'}).objectAt(0).get('attribute_b')
See the code in jsbin.
Does anyone know WHY filter works but find doesn't? They both return RecordArrays.

Issue with casting a date in query object addParam using cfscript

I am creating a query using cfscript syntax, and I have two query parameters that are dates. I created the date string the first time using
queryservice.addParam(
name="last_update",
value="createODBCDate(now())",
cfsqltype="cf_sql_date");
I would assume this would an analogue to:
<cfqueryparam value="#createODBCDate(now())#" cfsqltype="cf_sql_date">
So, when I run the query, I'm getting:
The cause of this output exception was that: coldfusion.runtime.Cast$DateStringConversionException: The value createODBCDate(now()) cannot be converted to a date.
Fine. So I created a variable,
var currentDate = createODBCDate(now());
added it to
queryservice.addParam(
name="last_update",
value="createODBCDate(now())",
cfsqltype="cf_sql_date");
and got
The cause of this output exception was that: coldfusion.runtime.Cast$DateStringConversionException: The value currentDate cannot be converted to a date.
When I created the query using the standard <cfquery ... syntax it worked fine.
So, I'm assuming that I am doing something wrong, but I can't for the life of me figure out what that is.
By the way, this is really my first time trying to create a query using the <cfscript> syntax.
value="createODBCDate(now())"
You forgot the # signs around the function. Without those, it is just a string. So the function is never invoked and you end up passing in the literal characters "createODBCDate(now())" as the date value.
Update:
As an aside, cf_sql_date automatically removes any time portion. So while using createODBCDate will not hurt anything, it is redundant. You could simply write:
queryservice.addParam(
name="last_update",
value="#now()#",
cfsqltype="cf_sql_date");
Your second attempt needs #'s just like #Leigh mentioned and also didn't reference the variable "currentDate" that you created.

JPA generating an invalid column

Helo there.
I am attempting to a execute a many-to-many get all query. To be clear, I am attepmting to get a collection within a collection to be pulled back. Ie, we will get a result set, but in that result set, there will be a collection of all objects linked to it via a foreign key. Now, to do this, I have a collection which I annotate thusly...
#ManyToMany
#JoinTable(name="QUICK_LAUNCH_DISTLIST",
joinColumns=#JoinColumn(name="QUICK_LAUNCH_ID"),
inverseJoinColumns=#JoinColumn(name="LIST_ID"))
private Collection<QuickLaunchDistlist> distributionLists;
Which seems to be just about text book...
I call a named query which looks like this...
#NamedQuery(name="getQuickLaunch", query = "SELECT q FROM QuickLaunch q")
Which is executed like so...
qlList = emf.createNamedQuery("getQuickLaunch").getResultList();
Every time I make this call, I get back the expected data in the first collection. But none of the collections seem to populate with it. To find out why, I looked at the sql being generated by the call... This is what I find...
I get this exception...
This is a FFDC log generated for the Default Resource Adapter from source:com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.executeQuery
The exception caught:java.sql.SQLSyntaxErrorException: ORA-00904: "T1"."QL_DISTLIST_ID": invalid identifier
SQL Error Code is 904 SQL State is :42000
Along with this query...
SELECT t1.QL_DISTLIST_ID, t2.LIST_ID, t2.CREATE_DATE, t2.CREATE_USERID, t2.description, t2.flag, t2.MOD_DATE, t2.MOD_USERID, t2.ORGANIZATION_ID, t2.owner, t2.STATUS_ID, t1.MESSAGE_TYPE_ID, t1.MOD_DATE, t1.MOD_USERID, t1.QUICK_LAUNCH_ID FROM EPCD13.QUICK_LAUNCH_DISTLIST t0, EPCD13.QUICK_LAUNCH_DISTLIST t1, EPCD13.DISTRIBUTION_LIST t2 WHERE t0.QUICK_LAUNCH_ID = ? AND t0.LIST_ID = t1.QL_DISTLIST_ID AND t1.LIST_ID = t2.LIST_ID(+)
If you look at the first column it request's to pull back you will notice that it selects t1.QL_DISTLIST_ID... Problem is, I have no such named column any where in my db!?!?!? Why on earth is that column being called? How does JPA generate the queries that it calls? If I knew that, I might be a little closer to figuring out what went wrong here or what I did wrong. Any help would be greatly appreciated.

How do I discard a row from a ColdFusion query?

Given a query (pseudo-code):
<cfquery name="myquery">SELECT * FROM stuff</cfquery>
How do I get rid of the first record? In this case, altering the SQL is not an option.
I have tried: myquery.RemoveRows(0,1); but received an error:
No matching Method/Function for Query.REMOVEROWS(numeric, numeric) found
I'm on Railo 3 BTW
Lo and behold:
myquery.RemoveRow(1);
Does exactly what I wanted. Leave it to Railo to do things a little differently!
Can't think of a way offhand to remove a row from the original object. Two things I can think of are:
do a query of queries. That assumes you'd be able to identify the records you don't want and specify them in the WHERE.
construct a new query with queryNew(). Loop over the original query doing a querySetCell() into the new query for the records that you want. This functionality could be incorporated into a UDF pretty easily. In fact, stating that made me think to check cflib.org. See #3
Check cflib.org :) See http://www.cflib.org/udf/QueryDeleteRows
"RemoveRows" is actually a call to the underlying Java method, so you have to cast those numbers. like so:
myquery.RemoveRows(
JavaCast( "int", 0 ) // starting row, zero-based
,JavaCast( "int", 1 ) // number to delete, returns error if too many
)
So probably the method is "int,int", and if you don't cast it, it looks like "numeric,numeric". One might argue that this is undocumented, but it's so succinct that you could (as I did) wrap it in a function, so that if it changes you just need to replace the contents of the function with an alternative workaround.
Railo has added removeRows, see here. My ACF code that uses this method now runs on Railo too, no changes.
With this, the Railo implementation now matches ACF. (Note also that the original Railo implementation was 0 based, while the new one and the ACF version are both 1 based.)
The way I would normally do it is with a query of queries such as the following:
SELECT * FROM myquery
LIMIT {1,10000}
That should work in Railo. What it does is offset the query by one and pulls 10000 records.
You could also do this:
SELECT * FROM myquery
WHERE {primarykey} <> {value}
Where it selects all records except for the primary key value that you pass in.
The awesome thing about ColdFusion is that there are tons of ways to do exactly what you are looking for.
You could just skip the row when you process the results:
<cfoutput query="myquery">
<cfif myquery.currentrow GT 1>
<!---Do the work here. --->
</cfif>
</cfoutput>