erichynds

Hi, I'm Eric Hynds, a front-end website developer living outside of Boston, Massachusetts. I'm passionate about developing functional, standard-compliant, and user-friendly websites.

Archive for the ‘ColdFusion’ Category

A Quick Gotcha With CFML & JSON Serialization

Monday, March 29th, 2010

ColdFusion internally represents structure keys in uppercase when the keys are created using dot notation. Dot notation is typically how programmers write their code and is considered to be best practice when working with structures. To the same effect, ColdFusion’s implementation of serializeJSON() serializes your object with respect to case; therefore, we might end up with something like this:

<cfset struct = {} />
<cfset struct.foo = "bar" />
 
<cfdump var="#serializeJSON(struct)#" />
 
<!---
	Result:  {"FOO":"bar"}
--->

Bummer. You’d probably expect “FOO” to be lowercase since that’s how you wrote it, but unfortunately it’s uppercase according to CF. Serializing a query forces uppercase JSON keys as well because queries act and function similarly to structures. This is rather annoying seeing how JavaScript is case sensitive, and serializeJSON is the way to push data from CF to JS. jQuery UI’s Autocomplete is a fine example of a widget that was not designed with case in mind; your JSON is expected to be returned with either a label or value key or both… in lowercase. (more…)

FamFamFam Silk Icon Set in Base64 Encoding

Wednesday, February 24th, 2010

This one can be filed under both “total impractical” and “somewhat useful”. For those who haven’t heard of this trick before, base64 encoding enables you to embed binary image data directly into your HTML or CSS source. Therefore, instead of the browser requesting two files from the server – the CSS file and the image file – only the CSS file need be requested. There are a number of drawbacks/pros/cons to this approach: IE doesn’t support it, file size limitations, larger CSS files, inability to separately cache CSS vs. images, etc. etc., but if you feel the need to use FamFamFam Silk icon’s in base64, look no further.

I use icons very liberally on all my projects; they’re classy and aid in usability. I typically start with a “.icon” class that configures the correct padding/background details for the element, followed by a “.icon-*” class, which sets the background-image property to that of the desired icon. For example, this CSS:

.icon { background-position:left; background-repeat:no-repeat; padding:3px 0 3px 19px }
.icon-pdf { background-image: url(/images/icons/pdf.png) }

Applied to this anchor element:

<a href="#" class="icon icon-pdf">Download PDF</a>

Produces:  Download PDF

Can you dig it? (more…)

Paginating large datasets with MySQL

Thursday, August 27th, 2009

Web developers typically choose one of two ways to paginate data:

  1. Select every row in one query and use server-side programming to handle the pagination and output.
  2. Use the LIMIT clause in the query to only select the amount of rows necessary for that page of results.

Which ever you choose, each can have a huge performance implication particularly when the data set is in the thousands of rows, or if the query to select the data is not optimized.

The performance hit in option #1 is obvious: you’re selecting ALL the rows when only a fraction of them are going to be displayed to the user at one time. Depending on the situation and if the query can be cached, I suppose this is a fine option, but in my opinion, pagination is a job for your database layer.

In option #2 the query is only going to return XX number of rows out of the entire recordset. We still need to know how many total rows exist in order to figure out how many pages there will be, and to display other meta data to users (showing records 1-100 of 4000, for example). Therefore, a second query still needs to be issued using a COUNT() statement, or the exact same query again without the LIMIT clause… not very efficient.

Although it doesn’t seem well known in the CF community, this scenario is the perfect fit for MySQL’s SQL_CALC_FOUND_ROWS and FOUND_ROWS(). Basically, this statement and function used together gives us the ability to retrieve the total number of rows that would have been returned had the LIMIT statement not been used. Two queries still have to be issued, but this time without the performance hit. Assuming our start_record and records_per_page variables are already set, it works like this:

<cftransaction>
	<cfquery name="getData" datasource="mydatasource">
	SELECT SQL_CALC_FOUND_ROWS field1, field2, field3
	FROM ...
	WHERE ...
	LIMIT #start_record#, #records_per_page#
	</cfquery>
 
	<cfquery name="getDataCount" datasource="mydatasource">
	SELECT FOUND_ROWS() AS totalrecords
	</cfquery>
</cftransaction>

The query getData retrieves only the rows we’re going to output, whereas query getDataCount retrieves the number of rows getData would have returned without the LIMIT restriction. Note that you can issue a SELECT FOUND_ROWS() statement at any time whether you’re paginating or not, and it’ll return the recordcount for whatever the last SELECT was. Therefore, in the example above, I’m wrapping both queries in a cftransaction tag so the FOUND_ROWS() will always reference the getData query. If another query is issued at the same time by another user of your website, selecting FOUND_ROWS() will return the recordcount of that query, not from getData. Here’s a full example of how to build the pagination variables (untested!):

<!--- the current page we're on --->
<cfparam name="url.page" default="1">
 
<!--- number of records to display per page / retrieve in the query --->
<cfset records_per_page = 45>
 
<!--- row to start on during our DB retrieve --->
<cfset start_record = url.page * records_per_page>
 
<!--- get our data --->
<cftransaction>
	<cfquery name="getData" datasource="mydatasource">
	SELECT SQL_CALC_FOUND_ROWS field1, field2, field3
	FROM ...
	WHERE ...
	LIMIT #start_record#, #records_per_page#
	</cfquery>
 
	<!--- get total number of rows --->
	<cfquery name="getDataCount" datasource="mydatasource">
	SELECT FOUND_ROWS() AS totalrecords
	</cfquery>
</cftransaction>
 
<!--- total number of pages --->
<cfset total_pages = ceiling(getDataCount.totalrecords / records_per_page)>

In future versions of ColdFusion it would be nice to see some kind of implementation in the “result” attribute of CFQUERY. If your result variable is “r”, for example, it would be cool to be able to reference #r.found_rows#, much like you can with #r.generated_key# during an INSERT. I’m sure MSSQL and other DBMS’s have something similar, but I’ve only had to use this with MySQL. Happy paginating!