Making ColdFusion's QueryNew() More Readable

Posted December 4, 2006 at 2:08 PM by Ben Nadel

Tags: ColdFusion

The ability to manually create, query, and manipulate ColdFusion record sets is one of the best features of ColdFusion. Maybe, I am crazy, but ColdFusion query of queries are just the cat's pajamas! Some times, as in today, I use the QueryNew() function to create rather large queries. As you know, the QueryNew() method takes two arguments: the query column names and the query column types. As you can imagine, the bigger the query (number of columns) the harder and harder it becomes to see which column types apply to which columns. To remedy this, I have come up with a simple solution to map the column names to column types in a highly readable way:

  • <!--- Create the columns definitions for query new. --->
  • <cfsavecontent variable="strColumns">
  • data :: VARCHAR,
  • rfid :: VARCHAR,
  • date :: VARCHAR,
  • time :: VARCHAR,
  • gross :: VARCHAR,
  • tare :: VARCHAR,
  • net :: VARCHAR,
  • level :: VARCHAR,
  • rollover_id :: VARCHAR,
  • rb_dollars :: DECIMAL,
  • is_valid :: INTEGER,
  • is_invalid_account :: INTEGER,
  • is_invalid_entry :: INTEGER,
  • is_invalid_gross :: INTEGER,
  • is_invalid_tare :: INTEGER,
  • is_invalid_net :: INTEGER,
  • is_duplicate_credit :: INTEGER,
  • useraccount_id :: VARCHAR,
  • rfid_count :: VARCHAR,
  • address_id :: VARCHAR,
  • street1 :: VARCHAR,
  • street2 :: VARCHAR,
  • city :: VARCHAR,
  • state :: VARCHAR,
  • zip :: VARCHAR
  • </cfsavecontent>
  •  
  • <!---
  • Manually create a query using the column mapping
  • defined in the CFSaveContent tag above.
  • --->
  • <cfset qCredit = QueryNew(
  • <!--- Column names. --->
  • strColumns.ReplaceAll( "\s*::[^,]+", "" ).ReplaceAll( ",\s*", ", " ).Trim(),
  •  
  • <!--- Column types. --->
  • strColumns.ReplaceAll( ",[^:]+::\s*", ", " ).ReplaceAll( "^[^:]+::\s*", "" ).Trim()
  • ) />

As you can see, I am creating a mapping between the column names and the column data types that is quite easy to read and maintain. Then, for the actually QueryNew() method call, I am just stripping out the unwanted characters for each QueryNew() argument. Sure, this might not be the fastest method, but I think it will be the best method (for me) for large queries over time. After all, this is the alternative:

  • <cfset qCredit = QueryNew(
  • "data, rfid, date, time, gross, tare, net, level, rolloverid, rb_dollars, is_valid, is_invalid_account, is_invalid_entry, is_invalid_tare, is_duplicate_credit, useraccount_id, rfid_count, address_id, street1, street2, city, state, zip",
  • "VARCHAR, VARCHAR, VARCHAR, VARCHAR, VARCHAR, VARCHAR, VARCHAR, VARCHAR, VARCHAR, DECIMAL, INTEGER, INTEGER, INTEGER, INTEGER, INTEGER, VARCHAR, VARCHAR, VARCHAR, VARCHAR, VARCHAR, VARCHAR, VARCHAR, VARCHAR"
  • ) />

Try telling me what the heck is going on there without counting on your fingers!

The only issue I have is that it requires a bit more code. What would be cool is to be able to make that in to a custom tag; something like:

  • <sys:querynew name="qCredit">
  • data :: VARCHAR,
  • rfid :: VARCHAR,
  • date :: VARCHAR,
  • time :: VARCHAR,
  • gross :: VARCHAR,
  • tare :: VARCHAR,
  • net :: VARCHAR,
  • level :: VARCHAR,
  • rollover_id :: VARCHAR,
  • rb_dollars :: DECIMAL,
  • is_valid :: INTEGER,
  • is_invalid_account :: INTEGER,
  • is_invalid_entry :: INTEGER,
  • is_invalid_gross :: INTEGER,
  • is_invalid_tare :: INTEGER,
  • is_invalid_net :: INTEGER,
  • is_duplicate_credit :: INTEGER,
  • useraccount_id :: VARCHAR,
  • rfid_count :: VARCHAR,
  • address_id :: VARCHAR,
  • street1 :: VARCHAR,
  • street2 :: VARCHAR,
  • city :: VARCHAR,
  • state :: VARCHAR,
  • zip :: VARCHAR
  • </sys:querynew>

That sort of tag would take about 3 seconds to implement and would be quite useful (it would return the qCredit query if that was not clear). I am not a FuseBox guy, but this might be something like what QuerySim tried to do. The difference is that I am not creating records, I am creating record SETS. Anyway, I was quite happy with this solution, thought I would pass it on.



Reader Comments

Dec 4, 2006 at 4:12 PM // reply »
1 Comments

"The difference is that I am not creating records, I am creating record SETS."

In the context of queries, records == record sets. I think what you mean to say is:

"...I am not creating record sets, I'm defining record sets."


Dec 4, 2006 at 4:19 PM // reply »
11,238 Comments

Paul,

Yes, excellent distinction. I am just defining the record set. Thanks for correcting that. I was trying to emphasize that this has nothing to do with adding records (but both methods actually created record sets).


Dec 5, 2006 at 4:26 AM // reply »
15 Comments

Why include the commas in your custom tag, when newline is a perfectly good delimiter, and means you can't suffer from the annoying "oh crap, I missed the last comma /again/" thing.


Dec 5, 2006 at 7:13 AM // reply »
11,238 Comments

Excellent point. There is no real need for the comma. I think I just had it in because I was thinking about stripping away characters. Without the comma in the original data, I would need to add it in during the ReplaceAll()s, which would not be complicated.


Apr 2, 2008 at 10:39 AM // reply »
1 Comments

I am using querynew() to create a query on the fly..
Getting errors in Production environment that i did not get in DEV..
I am suspecting it has to do with the versions of Coldfusion we have installed on the different environment..

In DEV i get no error..

In PROD...i am getting slammed by:
***************************************************
Parameter validation error for function QUERYNEW. The function takes 1 parameter.
The error occurred on line 86.
***************************************************

My question is, is there a difference in the versions..? 6 vs 7 or 7.0.2?

Thanks.


May 13, 2008 at 8:27 AM // reply »
11,238 Comments

@Victor,

Yeah, QueryNew() starts taking more parameters in the new versions. Specifically, I think the data type column options.

I know you probably already know this, but you should probably have the same version of ColdFusion in your dev and your production environments :P sorry, that's just the teacher in my coming out.


Nov 1, 2009 at 12:54 PM // reply »
50 Comments

When my xmlquery gets to be 800 rows or more it takes a long time to load, if it gets to 1600 rows it times out (20 seconds). Much slower then pulling from database. any performance tips for querynew. or other alternatives. I'm probably doing something wrong ?


Nov 1, 2009 at 1:53 PM // reply »
50 Comments

Its seems to me that it is faster to do a cffile read and only loop throught part of the dataset, using find() or something like to filter. I can read and find stuff in a secound, with basic find() and cffile. But when i use querynew it always takes 20 secs or timeout with larger datasets. It all depends how much you are outputting with cffile on the speed. I only want to display 12 files at a time so this works much better. If I wanted to display all the results on one page it would be same speed.


Nov 1, 2009 at 2:43 PM // reply »
11,238 Comments

@James,

What kind of data are you storing? May I ask why you are using a file rather than a database?


Nov 2, 2009 at 5:18 PM // reply »
50 Comments

@ Ben
I am trying to max out my gdidy account. They only offer up to 200 simultaneous mysql transactions. But unlimited data transfer, and storage.

So i am trying to leverage what really needs database access (which is easier, faster etc) and what I can store in xml for access. And what I can make static. And a bit of normalizing. I liked how the query new object worked but its Slow !. really really really slow. But very convenient, since its so similar. But it takes 20 secounds to pull what the database takes in 2-3 secs. So its cant be an option unless I can make it faster.

But for the most part im storing text. For which to be searched.

My questions might sound nutz , im not formally trained.


Nov 3, 2009 at 12:28 PM // reply »
11,238 Comments

@James,

Have you considering serializing the query into XML via WDDX and then saving that file. That way, you can de-serialize the WDDX file back into a query - it might be faster?


Nov 3, 2009 at 6:28 PM // reply »
50 Comments

No - but I will now, just got to figure it out, never used WDDX method before.


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 20, 2013 at 4:38 PM
Using A Dynamic Column Name With ValueList() In ColdFusion
@Dana, Your confusion is well founded, since this is a very confusing features. In fact, it ONLY works if you use array notation. Meaning, that this: arrayToList( query[ "columnName" ] ) ... read »
May 20, 2013 at 4:34 PM
Using A Dynamic Column Name With ValueList() In ColdFusion
I was thinking chicken and the egg, I wouldn't have expected it to work in the valuelist going in I guess. Maybe I just need a beer, long day :) ... read »
May 20, 2013 at 4:29 PM
Using A Dynamic Column Name With ValueList() In ColdFusion
@Dana, That's if you're trying to reference a specific row. In this case, we're trying to reference the entire query column as one cohesive value. So, you are correct that if you wanted to output a ... read »
May 20, 2013 at 4:24 PM
Using A Dynamic Column Name With ValueList() In ColdFusion
I thought when you used array notation to reference queries you always had to have the row or it would throw a similar error as well? ... read »
May 20, 2013 at 11:45 AM
Using jQuery's Animate() Step Callback Function To Create Custom Animations
This is really useful. I found out that you don't actually have to use a dummy css property (surprisingly). To animate a property in a linear-gradient for instance I did this this.css('someLinearGra ... read »
May 20, 2013 at 10:51 AM
Using A Dynamic Column Name With ValueList() In ColdFusion
@Josh, Oh snap! You're totally right! I'm not sure I've ever tried that. I did know that you can call a number of other array-methods on ColdFusion query columns: http://www.bennadel.com/blog/167 ... read »
May 20, 2013 at 10:45 AM
Using A Dynamic Column Name With ValueList() In ColdFusion
@Ben - I believe you can achieve the same functionality with ColdFusion's built in ArrayToList() function. ArrayToList( users[ "id" ] ); ... read »
May 20, 2013 at 10:21 AM
My Experience With AngularJS - The Super-heroic JavaScript MVW Framework
Is there any error logging and handling framework in angularjs, if not then in what way I can do this. ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools