Guess I can not attach files so maybe as inline text will work :(
Color.cfc
=========
<cfcomponent displayname="Color" extends="TableWrapper" hint="Base Color
methods.">
<cfset this.dsn = "">
<!--- CONSTRUCTOR --->
<cffunction name="init" access="public" returntype="struct"
output="no">
<cfargument name="dsn" type="string"
default="#request.db.dsn#">
<cfset this.dsn = dsn>
<cfset this.tablename = "Colors">
<cfset this.itemkey = "ColorID">
<cfset this.namekey = "ColorName">
<cfset this.orderkey = "ColorName">
<cfset this.fields = GetTableDetails()>
<cfreturn this>
</cffunction>
</cfcomponent>
EditColor.cfm
=============
<CFINCLUDE TEMPLATE="EditColor_Inc.cfm">
<CFOUTPUT>
<FORM ACTION="#CGI.Script_Name#" METHOD="post" NAME="NavForm"
ID="NavForm">
<INPUT TYPE="Hidden" NAME="ColorID"
VALUE="#oColor.GetField('ColorID')#">
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0"
CLASS="listing">
<TR>
<TD>Color Name</TD>
<TD><INPUT TYPE="Text" NAME="ColorName"
MAXLENGTH="#oColor.GetFieldMaxLength('ColorName')#"
VALUE="#oColor.GetField('ColorName')#" STYLE="width: 300px;"></TD>
</TR>
<TR>
<TD>Color Code</TD>
<TD><INPUT TYPE="Text" NAME="ColorCode"
MAXLENGTH="#oColor.GetFieldMaxLength('ColorCode')#"
VALUE="#oColor.GetField('ColorCode')#" STYLE="width: 300px;"></TD>
</TR>
<TR>
<TD>Hex Code 1</TD>
<TD><INPUT TYPE="Text" NAME="HexCode1"
MAXLENGTH="#oColor.GetFieldMaxLength('HexCode1')#"
VALUE="#oColor.GetField('HexCode1')#" STYLE="width: 300px;"></TD>
</TR>
<TR>
<TD>Hex Code 2</TD>
<TD><INPUT TYPE="Text" NAME="HexCode2"
MAXLENGTH="#oColor.GetFieldMaxLength('HexCode2')#"
VALUE="#oColor.GetField('HexCode2')#" STYLE="width: 300px;"></TD>
</TR>
<TR>
<TD COLSPAN="2" ALIGN="center">
<INPUT TYPE="Submit" NAME="Save"
VALUE="Save">
<INPUT TYPE="Submit" NAME="Cancel"
VALUE="Cancel">
</TD>
</TR>
</TABLE>
</FORM>
</CFOUTPUT>
EditColor_Inc.cfm
=================
<CFIF IsDefined("Form.ColorID")>
<CFSET ColorID = Form.ColorID>
<CFELSEIF IsDefined("URL.ColorID")>
<CFSET ColorID = URL.ColorID>
</CFIF>
<CFIF NOT IsNumeric(ColorID)>
<CFSET ColorID = 0>
</CFIF>
<CFINVOKE COMPONENT="#request.cfcs.Color#" METHOD="init"
RETURNVARIABLE="oColor" DSN="#request.db.dsn#">
<CFSET oColor.Load(ColorID)>
<CFIF IsDefined("Form.Save")>
<CFSET oColor.Update(form)>
<CFIF oColor.IsRecordValid()>
<CFSET oColor.Save()>
<CFLOCATION URL="Colors.cfm">
</CFIF>
<CFELSEIF IsDefined("Form.Cancel")>
<CFLOCATION URL="Colors.cfm">
</CFIF>
IsPK.sql
========
CREATE FUNCTION IsPK (@TableName VARCHAR(80), @FieldName VARCHAR(80))
RETURNS INT AS
BEGIN
declare @full_table_name varchar (80)
set @full_table_name [EMAIL PROTECTED]
declare @table_id numeric
SELECT @table_id = object_id(@full_table_name)
declare @curfield varchar(80)
declare @ret int
set @ret = 0
declare cur_pks cursor for
select
COLUMN_NAME = convert(sysname,c.name)
from sysindexes i, syscolumns c, sysobjects o --, syscolumns
c1
where o.id = @table_id
and o.id = c.id
and o.id = i.id
and (i.status & 0x800) = 0x800
and (c.name = index_col (@full_table_name, i.indid, 1)
or
c.name = index_col (@full_table_name, i.indid, 2)
or
c.name = index_col (@full_table_name, i.indid, 3)
or
c.name = index_col (@full_table_name, i.indid, 4)
or
c.name = index_col (@full_table_name, i.indid, 5)
or
c.name = index_col (@full_table_name, i.indid, 6)
or
c.name = index_col (@full_table_name, i.indid, 7)
or
c.name = index_col (@full_table_name, i.indid, 8)
or
c.name = index_col (@full_table_name, i.indid, 9)
or
c.name = index_col (@full_table_name, i.indid, 10)
or
c.name = index_col (@full_table_name, i.indid, 11)
or
c.name = index_col (@full_table_name, i.indid, 12)
or
c.name = index_col (@full_table_name, i.indid, 13)
or
c.name = index_col (@full_table_name, i.indid, 14)
or
c.name = index_col (@full_table_name, i.indid, 15)
or
c.name = index_col (@full_table_name, i.indid, 16)
)
order by 1
open cur_pks
fetch next from cur_pks into @curfield
while @@FETCH_STATUS = 0
begin
if @curfield = @fieldname
begin
set @ret = 1
end
fetch next from cur_pks into @curfield
end
close cur_pks
deallocate cur_pks
return @ret
END
TableWrapper.cfc
================
<cfcomponent displayname="TableWrapper">
<!--- data members --->
<cfparam name="this.dsn"
type="string" default="">
<cfparam name="this.TableName" type="string"
default="">
<cfparam name="this.ItemKey" type="string"
default="">
<cfparam name="this.NameKey" type="string"
default="">
<cfparam name="this.OrderKey" type="string"
default="">
<cfparam name="this.ImportKey" type="string"
default="">
<cfparam name="this.Fields" type="query"
default="#QueryNew('Empty')#">
<cfparam name="this.fieldCacheDuration" type="date"
default="#CreateTimeSpan(0,0,10,0)#">
<!--- methods --->
<!--- Initialize the Table Wrapper --->
<cffunction name="init" access="public" returntype="struct"
output="yes">
<cfargument name="dsn" required="Yes" type="string">
<cfset StructAppend(this, arguments, "Yes")>
<cfset this.fields = getTableDetails()>
<cfreturn this>
</cffunction>
<!--- load a single item, pass values into the fields query --->
<cffunction name="load" access="public" returntype="boolean"
output="yes">
<cfargument name="id" type="numeric" required="yes">
<cfset var qItem = selectData(id)>
<cfloop index="Field" list="#qItem.ColumnList#">
<cfset setField(Field,
evaluate("qItem.#Field#"))>
</cfloop>
<cfreturn true>
</cffunction>
<!---
Description: Get table structure
Parameters: None
Returns: Query of the table structure
Note: Do not put the primary key at
the bottom of
the field definition of
your table.
--->
<cffunction name="getTableDetails" access="public"
returntype="query" output="no">
<cfargument name="reset" type="boolean" default="true">
<cfset var cachePeriod = this.fieldCacheDuration>
<cfif reset>
<cfobjectcache action="clear">
</cfif>
<cfif not this.Fields.recordCount>
<cfquery
name="Application.fields_#this.TableName#" datasource="#this.dsn#"
cachedwithin="#cachePeriod#">
SELECT COLUMN_NAME,
COLUMN_DEFAULT,
rtrim(ltrim(IS_NULLABLE)) as IS_NULLABLE,
DATA_TYPE,
CHARACTER_MAXIMUM_LENGTH,
dbo.IsPK('#this.TableName#', COLUMN_NAME) AS IS_PRIMARYKEY,
'' AS
CURRENT_VALUE,
CF_DATA_TYPE =
CASE
DATA_TYPE
WHEN 'bigint' THEN 'CF_SQL_BIGINT'
WHEN 'char' THEN 'CF_SQL_CHAR'
WHEN 'float' THEN 'CF_SQL_FLOAT'
WHEN 'int' THEN 'CF_SQL_INTEGER'
WHEN 'money' THEN 'CF_SQL_MONEY'
WHEN 'ntext' THEN 'CF_SQL_LONGVARCHAR'
WHEN 'numeric' THEN 'CF_SQL_NUMERIC'
WHEN 'real' THEN 'CF_SQL_REAL'
WHEN 'binary' THEN 'CF_SQL_BLOB'
WHEN 'bit' THEN 'CF_SQL_BIT'
WHEN 'datetime' THEN 'CF_SQL_TIMESTAMP'
WHEN 'decimal' THEN 'CF_SQL_DECIMAL'
WHEN 'image' THEN 'CF_SQL_BLOB'
WHEN 'nchar' THEN 'CF_SQL_CHAR'
WHEN 'nvarchar' THEN 'CF_SQL_VARCHAR'
WHEN 'smalldatetime' THEN 'CF_SQL_DATE'
WHEN 'smallint' THEN 'CF_SQL_SMALLINT'
WHEN 'smallmoney' THEN 'CF_SQL_MONEY'
WHEN 'sql_variant' THEN 'CF_SQL_VARCHAR'
WHEN 'text' THEN 'CF_SQL_LONGVARCHAR'
WHEN 'timestamp' THEN 'CF_SQL_TIMESTAMP'
WHEN 'tinyint' THEN 'CF_SQL_TINYINT'
WHEN 'uniqueidentifier' THEN 'CF_SQL_IDSTAMP'
WHEN 'varbinary' THEN 'CF_SQL_BLOB'
WHEN 'varchar' THEN 'CF_SQL_VARCHAR'
ELSE 'varchar'
END
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME =
'#this.TableName#'
ORDER BY IS_PRIMARYKEY DESC
</cfquery>
<cfset this.Fields =
duplicate(Application["fields_#this.TableName#"])>
</cfif>
<cfreturn this.Fields>
</cffunction>
<!---
Description: Gets a fields value from the Fields
query
Parameters: FieldName = Name of the field
value to get
Returns: Value of the specified field
Throws error if
requested field doesn't exist in
field query
--->
<cffunction name="getField" access="public" returntype="any"
output="no">
<cfargument name="FieldName" type="string"
required="Yes">
<cfargument name="fields" type="query"
default="#this.fields#">
<cfloop query="fields">
<cfif column_name EQ fieldName>
<cfreturn current_value>
</cfif>
</cfloop>
<cfthrow errorcode="TableWrapper::getField"
message="Current field value for (#FieldName#)
could not be retrieved."
detail="Field: '#FieldName#' does not exist in
table: '#this.TableName#'.">
</cffunction>
<cffunction name="getFieldNames" access="public"
returntype="any" output="no">
<CFSET FieldData = this.Fields>
<CFRETURN VaLueList(FieldData.Column_Name)>
</cffunction>
<cffunction name="getFieldMaxLength" access="public"
returntype="any" output="no">
<cfargument name="FieldName" type="string"
required="Yes">
<cfargument name="fields" type="query"
default="#this.fields#">
<cfloop query="fields">
<cfif column_name EQ fieldName>
<cfreturn CHARACTER_MAXIMUM_LENGTH>
</cfif>
</cfloop>
<cfthrow errorcode="TableWrapper::getField"
message="Current field value for (#FieldName#)
could not be retrieved."
detail="Field: '#FieldName#' does not exist in
table: '#this.TableName#'.">
</cffunction>
<cffunction name="getFieldIsNullable" access="public"
returntype="any" output="no">
<cfargument name="FieldName" type="string"
required="Yes">
<cfargument name="fields" type="query"
default="#this.fields#">
<cfloop query="fields">
<cfif column_name EQ fieldName>
<cfreturn Is_Nullable>
</cfif>
</cfloop>
<cfthrow errorcode="TableWrapper::getField"
message="Current field value for (#FieldName#)
could not be retrieved."
detail="Field: '#FieldName#' does not exist in
table: '#this.TableName#'.">
</cffunction>
<!---
Description: Sets a fields value in the Fields query,
validates the
passed in value with the
Fields data type
Parameters: FieldName = Name of the field to
set
FieldValue = Value to
set the field to
Returns: row number modified
--->
<cffunction name="setField" access="public" returntype="numeric"
output="no">
<cfargument name="FieldName" type="string"
required="Yes">
<cfargument name="FieldValue" type="any" required="yes">
<cfset var row = 0>
<!--- find the row with the right column_name --->
<cfloop query="this.Fields">
<cfif column_name eq arguments.fieldname>
<cfswitch expression="#DATA_TYPE#">
<cfcase
value="numeric,int,decimal,bigint,smallint,tinyint,float,real,money,smal
lmoney">
<cfif
isnumeric(arguments.fieldvalue) or (is_nullable and arguments.fieldvalue
eq "")>
<cfset row =
currentRow>
<cfbreak>
</cfif>
</cfcase>
<cfcase value="bit">
<cfif
isboolean(arguments.fieldvalue) or (is_nullable and arguments.fieldvalue
eq "")>
<cfset row =
currentRow>
<cfbreak>
</cfif>
</cfcase>
<cfcase
value="datetime,smalldatetime,timestamp">
<cfif
isdate(arguments.fieldvalue) or (is_nullable and arguments.fieldvalue eq
"")>
<cfset row =
currentRow>
<cfbreak>
</cfif>
</cfcase>
<cfdefaultcase>
<cfset row = currentRow>
<cfbreak>
</cfdefaultcase>
</cfswitch>
</cfif>
</cfloop>
<!--- set the current_value --->
<cfif row>
<cfset this.fields.current_value[row] =
arguments.fieldvalue>
</cfif>
<cfreturn row>
</cffunction>
<!---
Description: Checks to see if the current item's data
is valid.
Compares the fields
values to see if they are empty
and if the field allows
nulls
Parameters: None
Returns: TRUE if data is valid
FALSE if data is not
valid
--->
<cffunction name="isRecordValid" access="public"
returntype="boolean" output="no">
<cfset var datavalid = true>
<cfloop query="this.Fields">
<cfif not is_primarykey>
<cfif not is_nullable and
isblank(current_value)>
<cfset datavalid = false>
<cfbreak>
</cfif>
</cfif>
</cfloop>
<cfreturn datavalid>
</cffunction>
<!---
Description: Checks to see if the passed in value is
blank or not
Parameters: Value = Value to check
Returns: TRUE if value is blank
FALSE if value is not
blank
--->
<cffunction name="isBlank" access="public" returntype="boolean"
output="no">
<cfargument name="str" type="any" required="Yes">
<cfset var isvalueblank = false>
<cfif not len(trim(str))>
<cfset isvalueblank = true>
</cfif>
<cfreturn isvalueblank>
</cffunction>
<!--- public generic db methods --->
<cffunction name="save" access="public" returntype="boolean"
output="no">
<cfset var id = getField(this.itemkey)>
<cfif isnumeric(id) and id>
<cfset id = updateData(id)>
<cfelse>
<cfset id = insertData()>
</cfif>
<cfreturn id>
</cffunction>
<!--- delete the record form the database --->
<cffunction name="remove" access="public" returntype="boolean"
output="no">
<cfargument name="id" type="numeric"
default="#getField(this.itemkey)#">
<cfreturn deleteData(id)>
</cffunction>
<!--- private generic db methods --->
<cffunction name="selectData" returntype="query" output="no"
access="public">
<cfargument name="id" type="numeric" required="Yes">
<cfargument name="ColumnList" type="string"
required="No" default="*">
<cfquery name="qSelect" datasource="#this.dsn#">
SELECT #ColumnList#
FROM [#this.TableName#]
WHERE [#this.ItemKey#] = #id#
</cfquery>
<cfreturn qSelect>
</cffunction>
<cffunction name="updateData" access="private"
returntype="numeric" output="no">
<cfargument name="id" type="numeric" required="yes">
<cfquery name="qUpdate" datasource="#this.dsn#">
UPDATE [#this.TableName#]
SET modified = getdate()
<cfloop query="this.Fields">
<cfif is_primarykey eq 0 and COLUMN_NAME
neq "Modified">
, [#COLUMN_NAME#] =
<cfqueryparam cfsqltype="#CF_DATA_TYPE#" value="#CURRENT_VALUE#"
null="#isBlank(CURRENT_VALUE)#">
</cfif>
</cfloop>
WHERE [#this.ItemKey#] = #id#
</cfquery>
<cfreturn id>
</cffunction>
<cffunction name="insertData" access="private"
returntype="numeric" output="no">
<cfset var id = 0>
<cfquery name="qInsert" datasource="#this.dsn#">
INSERT INTO [#this.TableName#]
(
created
<cfloop query="this.Fields">
<cfif not is_primarykey and
len(current_value)>
, [#COLUMN_NAME#]
</cfif>
</cfloop>
)
VALUES
(
getdate()
<cfloop query="this.Fields">
<cfif not is_primarykey and
len(current_value)>
, <cfqueryparam
cfsqltype="#CF_DATA_TYPE#" value="#dataFormat(CURRENT_VALUE,
DATA_TYPE)#" null="#isBlank(CURRENT_VALUE)#">
</cfif>
</cfloop>
)
SELECT @@IDENTITY AS [#this.ItemKey#]
</cfquery>
<cfset id = qInsert[this.itemKey][1]>
<cfset setfield(this.itemKey, id)>
<cfreturn id>
</cffunction>
<cffunction name="Clear" access="public" output="no">
<cfloop query="this.Fields">
<cfset setField(Column_Name, "")>
</cfloop>
<cfreturn this>
</cffunction>
<cffunction name="dataFormat" access="private" returntype="any"
output="no">
<cfargument name="val" required="yes">
<cfargument name="type" required="yes">
<cfset var result = val>
<!--- convert stuff --->
<cfswitch expression="#type#">
<cfcase value="datetime">
<cfset result = CreateODBCDateTime(val)>
</cfcase>
<cfcase value="date">
<cfset result = CreateODBCDate(val)>
</cfcase>
</cfswitch>
<cfreturn result>
</cffunction>
<cffunction name="deleteData" access="private"
returntype="numeric" output="no">
<cfargument name="id" type="numeric" required="yes">
<cfquery name="qDelete" datasource="#this.dsn#">
delete from [#this.TableName#] WHERE
[#this.ItemKey#] = #id#
</cfquery>
<cfreturn true>
</cffunction>
<!---
Description: Updates the current items Fields with
the values in the updateFields structure.
Only fields that are
different are changed.
Parameters: upadteFields = Structure with
fields to update
Returns: TRUE if fields were changed
FALSE if no fields were
changed
--->
<cffunction name="update" access="public" output="false"
returntype="boolean">
<cfargument name="updateFields" type="struct">
<CFSET var wasModified = FALSE>
<CFTRY>
<CFLOOP QUERY="this.fields">
<CFIF StructKeyExists(updateFields,
column_name)>
<CFIF
Compare(GetField(column_name), updateFields[column_name]) NEQ 0>
<CFSET
SetField(column_name, updateFields[column_name])>
<CFSET wasModified =
TRUE>
</CFIF>
</CFIF>
</CFLOOP>
<CFCATCH>
<CFDUMP VAR="#CFCatch#">
<CFABORT>
</CFCATCH>
</CFTRY>
<cfreturn wasModified>
</cffunction>
<!---
Description: Checks to see if the current field is a
Primary Key.
Parameters: Field = Name of field to check
Returns: TRUE if Field is a Primary Key
FALSE if Field is not a
Primary Key
--->
<cffunction name="isPrimaryKey" access="public"
returntype="boolean" output="no">
<cfargument name="field" TYPE="string" required="yes">
<cfset var ispk = false>
<cfloop query="this.Fields">
<CFIF column_name EQ field>
<cfif is_primarykey>
<cfset ispk = true>
</cfif>
<cfbreak>
</cfif>
</cfloop>
<cfreturn ispk>
</cffunction>
<!--- utilities --->
<cffunction name="dataToStruct" access="public"
returntype="struct" output="no">
<cfset var fields = this.fields>
<cfset var result = structNew()>
<cfloop query="fields">
<cfset StructInsert(result, column_name,
current_value, 1)>
</cfloop>
<cfreturn result>
</cffunction>
</cfcomponent>
-----Original Message-----
From: Trevor Orr [mailto:[EMAIL PROTECTED]
Sent: Thursday, June 02, 2005 12:01 PM
To: CF-Community
Subject: Database Table CFC
I have written a base CFC that I call tablewrapper. It is a CFC that
takes care of all database functions, EG: Insert, Delete, Update. It
automatically grabs all field information for the tabel on init. Allows
to update the current data from a form post. I just wanted to get
peoples opinions on it, either good or bad, suggestions on imporovements
or whatever. For me it is a huge time saver when making site
administrator forms. Attached is the base CFC, and the CFC it extends,
a SQL script to generate the SQL Server UDF and example files for
updating from a form. The one big draw back on this is that it is SQL
Server specific, because of primary keys.
All Comments would be greatly appreciated.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
Stay Ahead of Hackers - Download ZoneAlarm Pro
http://www.houseoffusion.com/banners/view.cfm?bannerid=65
Message: http://www.houseoffusion.com/lists.cfm/link=i:5:159476
Archives: http://www.houseoffusion.com/cf_lists/threads.cfm/5
Subscription: http://www.houseoffusion.com/lists.cfm/link=s:5
Unsubscribe: http://www.houseoffusion.com/cf_lists/unsubscribe.cfm?user=89.70.5
Donations & Support: http://www.houseoffusion.com/tiny.cfm/54