Making ColdFusion's QueryNew() More Readable

Posted December 4, 2006 at 2:08 PM

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:

 Launch code in new window » Download code as text file »

  • <!--- 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:

 Launch code in new window » Download code as text file »

  • <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:

 Launch code in new window » Download code as text file »

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

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Other Searches  |  Print Page



Learning ColdFusion 9 - ColdFusion 9 tutorials, samples, examples, demos

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 »
7,572 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 »
7,572 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 »
7,572 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 »
45 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 »
45 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 »
7,572 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 »
45 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 »
7,572 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 »
45 Comments

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


Post Comment  |  Ask Ben

Recent Blog Comments
Lee
Mar 22, 2010 at 10:08 AM
Javascript's Implicit Boolean Conversions
I would certainly still use if(strValue.length > 0) over if(strValue) simply because I believe it makes the code more self-documenting. Not everyone knows that an empty string evaluates to false. ... read »
Mar 22, 2010 at 7:43 AM
Terms Of Service / Privacy Policy Document Generator
Thankyou for this very helpful form. You've made my life much easier today. I'll have a look around your site... I'm sure there's some more good stuff here..Thanks Dave ... read »
Mar 22, 2010 at 7:21 AM
Encountered "(. Incorrect Select Statement, Expecting a 'FROM', But Encountered '(' Instead, A Select Statement Should Have a 'FROM' Construct.
I got this exception now. In case you're using var-es local struct, CF gives you couple of "new" exceptions: Encountered "local. and Encountered "id. Incorrect Select List, Incorrect select colum ... read »
Mar 22, 2010 at 3:08 AM
Ask Ben: Selecting XML Attributes Given Other XML Attributes
Thanks for the response. I finally discovered that I was getting this error because I had cfsetting enablecfoutputonly="yes" in Application.cfc, and was neither setting it to false elsewhere nor brac ... read »
Mar 21, 2010 at 8:57 PM
The Bourne Ultimatum Starring Matt Damon And Julia Stiles
late to the party, but my observation is this: rewatch carefully for the platonic nature of the relationship between nicki and jason. she never flirts with him. he never comes on to her. they alway ... read »
Mar 21, 2010 at 7:40 PM
Is Simulating User-Input Events With jQuery Ever A Good Idea?
A couple of things. One you embed the initial state of of more-info in the CSS. IMHO, that behavior should be in jQuery: moreInfo.hide(); It shows that the behavior your toggling and closing is mor ... read »
Mar 21, 2010 at 3:59 PM
Exploring ColdFusion Component Runtime Class Properties And Serialization
@Elliott, according to Ben's experiment, serializeJSON() doesn't access the private data by default - it doesn't even access the getHair() method - so trying to clone a Girl.cfc via serializeJSON/des ... read »
Mar 21, 2010 at 3:49 PM
Ask Ben: Javascript String Replace Method
I'm confused a bit by what you are asking, but if had this sentence: The color, red, is in the style statement; style: red;. and wanted to remove all or change all of the commas, colons, and semi-c ... read »