Orange is my favorite color

I have a fairly complex report system in ColdFusion (v7) that takes one or more queries and joins them together in preparation for filtering and display. Some data comes from a database call and some columns are dynamically added to the query via queryAddColumn(), specifying the datatype as we go along like so:


<cfset queryAddColumn(data, "anotherCol", "VarChar", arrayNew(1))>


<cfloop query="data">
<cfset qryExtra = myCFC.getArbitraryData(id = uidMember)>
<cfif dspShared.recordCount>
<cfset querySetCell(data, "anotherCol", qryExtra.newCol, currentRow)>
</cfif>
</cfloop>

This seems to work, more or less, just fine. The problem is that occasionally, fields which are varchars are being interpreted an integers because the data is primarily numeric. Case in point: zip codes. Most of them are 5 digits but we have a sprinkling of either blank (“”) or Canadian zip codes (“V6Y 4K9″) that are also valid.

When ColdFusion comes to these values, it intermittently (based on what criteria, I’m not sure) bombs out trying to parse the value and throws an error like so:

The value "V6Y 4K9" cannot be converted to a number

You can tell from the top of the stack trace that the problem lies in validating the results and “inferMetaDataTypes” and then “guessColumnType”:

coldfusion.runtime.Cast$NumberConversionException: The value "V6Y 4K9" cannot be converted to a number at coldfusion.runtime.Cast._double(Cast.java:491) at
coldfusion.runtime.Cast._double(Cast.java:522) at
coldfusion.runtime.Cast._long(Cast.java:370) at
coldfusion.sql.imq.rttExpr.castTo(rttExpr.java:515) at
coldfusion.sql.imq.imqTable.guessColumnType(imqTable.java:453) at
coldfusion.sql.QueryTableMetaData.InferMetaDataTypes(QueryTableMetaData.java:350)
at coldfusion.sql.imq.TableList.validate (TableList.java:166) at
coldfusion.sql.imq.rttSelectExprSpec.validate(rttSelectExprSpec.java:498)
at coldfusion.sql.imq.rttSelectStmt.validate(rttSelectStmt.java:84) at
coldfusion.sql.imq.jdbcStatement.fetchResult (jdbcStatement.java:538) at coldfusion.sql.imq.jdbcStatement.execute(jdbcStatement.java:131) at
coldfusion.sql.Executive.executeQuery(Executive.java:719) at

It makes me nervous when computers “guess”.

In my case, I was able to debug slightly further and confirm the data types were the culprit using the following code:

<cftry>
<cfquery name="filteredData" dbtype="query">
SOME QUERY THAT FAILS
</cfquery>

<cfcatch type="any">
<cfdump var="#cfcatch#">
<cftry>
<cfdump var="#getMetaData(filteredData)#">
<cfcatch type="any"></cfcatch>
</cftry>
</cfcatch>
</cftry>

If the query bombs, the getMetaData() function will give you a lot of insight into the actual query object. While most varchars in my query had the type “VARCHAR”, my zip code field had a type of “[undefined struct element]“.

So, how do we fix it? From my post to the CFGURU list, QofQ is definitely a wacky beast. Pretty much everyone who uses it reports some irregularities with datatypes. There are (so far) two options:

  1. CAST() every single column. This is a PITA, but it seems to resolve the problem:
    <cfquery name="filteredData" dbtype="query">
    SELECT CAST(id AS INTEGER) AS id
    ,CAST(name AS VARCHAR) AS name
    ,CAST(zipcode AS VARCHAR) AS zipcode
    FROM existingQuery
    </cfquery>
  2. The other way, discovered by Robert Munn in a project he’s working on, is to explicitly create the query with data types before performing any joins or queries.

Any other successful workarounds?

2 Comments

  1. brian said:

    on August 8, 2006 at 11:39 am

    I just finished fixing my report system and I think queryNew(columnList) is 99% bad. If you’re using queryNew() without specifying the column types (a second parameter supported in CFMX 7) and your data has blanks or NULLs in the data, you’re almost guaranteed going to run into a problem.

    I’m going to start either using queryNew() with the new columnTypes parameter or doing a blank queryNew(“”) and then add each column independently using queryAddColumn(newQuery, “columnName”, “VarChar”, arrayNew(1)).

    This seems to be the only way to be confident that your datatypes will be straight.

  2. Better Living Through Introspection said:

    on August 15, 2006 at 6:27 am

    Quote for the day

    It makes me nervous when computers “guess”….

{ RSS feed for comments on this post}