Tom Wellige  

About Me
Home
My Blog

Favourites
Books
Drink

Open Source
Miscellaneous
CAN M3S Driver
HPShell
Web DB Editor
Open Queue

Miscellaneous
Wiki
Bookmark

My Programming Page - UTE




UTE - Universal Table Editor

Contents of this page




UTE.ASP
<%@ language = "VBScript" %>
<% 
'---------------------------------------------------------------------------
'
'   Project:    UTE - (U)niversal ASP (T)able (E)ditor
'
'   Module:     UTE Active Server Page
'
'   Version:    3.01
'
'   Comments:   This module does the following things:
'                   1. Creates the HTML frame for UTE class
'                   2. Inserts the UTE class
'
'---------------------------------------------------------------------------
'
'   (c) in 2000-2003 by Tom Wellige                    
'   http://www.wellige.com  mailto:tom@wellige.com     
'                                               
'   This project is released under the "GNU General Public License (GPL)" 
'   http://www.gnu.org/licenses/gpl.html
'
'   and is maintained on SourceForge at
'   http://sourceforge.net/projects/ute-asp/
'
'   and can also be found on CodeProject at
'   http://www.codeproject.com/asp/ute.asp
'
'---------------------------------------------------------------------------

    option explicit 

%>
<!--#include file ="ute_definition.inc"-->
<%
    Dim sDSN
    ' To use a DSN-Less Connection use the following sDSN definition.
    ' !!! By using this, UTE is able to detect Primary Keys accurately.
    sDSN = "Provider=Microsoft.Jet.OLEDB.4.0;" &_
        "Data Source=" & Server.MapPath("test.mdb")

    ' To use a DSN (ODBC) Connection use the following sDSN defintion.
    ' You need to setup an ODBC data source.
    ' !!! By using this, UTE is *NOT* always able to detect Primary Keys accurately.                                        
    ' sDSN = "test"

    Dim ute
    Set ute = new clsUTE

    ute.DBName      = "TEST.MDB"  ' Name of Database. For display purpose only
    'ute.ReadOnly    = True       ' readonly mode
    'ute.ListTables  = False      ' display toolbutton to list all tables within db
    'ute.Filters     = False      ' display toolbutton to define and activate filters
    'ute.Export      = False      ' display toolbutton to export all data to CSV file
    'ute.SQL         = False      ' display toolbutton to show current sql statement
    'ute.Definitions = False      ' display toolbutton to show field defintions

    ute.Init sDSN   ' init must be called *before* any HTML code is
                    ' is written, otherwise the export feature doesn't work !

%>
<!doctype html public "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
  <title><%=ute.HeadLine%> - Universal Table Editor</title>
  <link rel="stylesheet" type="text/css" href="ute_style.css">
</head>
<body bgcolor="#FFFFFF" link="#0000A0" vlink="#0000A0" alink="#0000A0">
<%
    ute.Draw
    Set ute = Nothing
%>
</body>
</html>

page up


UTE_CLASS.INC
<%
'---------------------------------------------------------------------------
'
'   Project:    UTE - (U)niversal ASP (T)able (E)ditor
'
'   Module:     UTE class
'
'   Version:    3.01
'
'   Comments:   This module does the following things:
'                   1. Defines the class "clsUTE" with all it's 
'                      properties and functions.
'
'---------------------------------------------------------------------------
'
'   (c) in 2000-2003 by Tom Wellige                    
'   http://www.wellige.com  mailto:tom@wellige.com     
'                                               
'   This project is released under the "GNU General Public License (GPL)" 
'   http://www.gnu.org/licenses/gpl.html
'
'   and is maintained on SourceForge at
'   http://sourceforge.net/projects/ute-asp/
'
'   and can also be found on CodeProject at
'   http://www.codeproject.com/asp/ute.asp
'
'---------------------------------------------------------------------------
'
'   Public Properties    (R = read, W = write)
'
'      DBName      R/W  Name of Database. For display purpose only.
'
'      HeadLine    R    Headline of page (e.g. to be used as <title>)
'      TableName   R    Name of current table
'
'      ReadOnly    W    display table in readonly mode                    (default: false)
'
'      ListTables  W    display toolbutton to list all tables             (default: true)
'      Filters     W    display toolbutton to define and activate filters (default: true)
'      Export      W    display toolbutton to export all data to CSV file (default: true)
'      SQL         W    display toolbutton to show current sql statement  (default: true)
'      Definitions W    display toolbutton to show field defintions       (default: true)
'
'      ImageDir    R/W  name of image directory, must end with "/"  (default: images/ )
'
'   Public Functions
'      Init    (sDSN)   must be called *before* any other HTML output
'      Draw    ()       writes complete HTML code
'      getHTML ()       returns complete HTML code
'
'---------------------------------------------------------------------------

Class clsUTE

    '-----------------------------------------------------------------------
    ' Private Member Variables
    '
    Private m_DB            ' database connection object
    Private m_RS            ' recordset object
    Private m_RSForm        ' recordset object for form view
    
    Private m_sSQL          ' SQL statement being used to read data from db

    Private m_nMode         ' View mode: mdTable, mdForm, mdExport
    Private m_nFormMode     ' Form mode: mdEdit, mdInsert, mdDelete

    Private m_sDSN          ' odbc connect string
    Private m_sDBName               ' database name (for display purpose only)
    Private m_sTable        ' table name
    Private m_nPage         ' current page
    Private m_nPageSize     ' size of current page
    Private m_bSortFields       ' sort fields alphabetically (columns) ?
    Private m_bViewDefinitions  ' show field definitions ?
    Private m_bViewSQL              ' show sql statement ?
    Private m_bAutoPKDetection  ' detect primary key fields ?
    Private m_bSubmitted            ' form was submitted

    Private m_bReadOnly     ' display table in readonly mode

    Private m_bListTables           ' display toolbutton to list all tables within db
    Private m_bFilters              ' display toolbutton to define and activate filters
    Private m_bShowExportLink   ' display toolbutton to export all data to CSV file
    Private m_bShowSQL      ' display toolbutton to show current sql statement
    Private m_bShowDefLink      ' display toolbutton to show field defintions

    Private m_PrimaryKeyFields()    ' array holding names of all primary key fields
    Private m_PrimaryKeyTypes() ' array holding types of all primary key fields
    Private m_StandardFields()  ' array holding names of all other fields
    Private m_StandardTypes()   ' array holding types of all other fields

    Private m_SortFields()      ' array holding names of the fields for the ORDER BY clause
    Private m_SortFieldsOrder() ' array holding the directions for the ORDER BY clause

    Private m_nNumberOfFilters  ' number of filters
    Private m_FilterFields()    ' array holding names of fields of the filters
    Private m_FilterCompares()  ' array holding the comparisons for the filters
    Private m_FilterValues()    ' array holding the values of the filters
    Private m_FilterCombines()  ' array holding the combinitions of the filters

    Private m_sHeadLine             ' Headline

    Private m_sUTEScript        ' name of UTE script file
    Private m_sIMAGEDir     ' name of image directory

    Private m_nRecord               ' number of record to be edited/deleted
    Private m_ErrorField()
    Private m_ErrorMessage()


    '-----------------------------------------------------------------------
    ' Property Functions
    '

    ' ---- HeadLine (read) ----
    Property Get HeadLine()
        HeadLine = m_sHeadLine
    End Property

    ' ---- DBName (read/write) ----
    Property Let DBName(s)
        m_sDBName = s
    End Property

    Property Get DBName()
        DBName = m_sDBName
    End Property

    ' ---- TableName (read) ----
    Property Get TableName()
        TableName = m_sTable
    End Property

    ' ---- ReadOnly (write) ----
    Property Let ReadOnly(b)
        m_bReadOnly = b
    End Property

    ' ---- ListTables (write) ----
    Property Let ListTables(b)
        m_bListTables = b
    End Property

    ' ---- Definitions (write) ----
    Property Let Definitions(b)
        m_bShowDefLink = b
    End Property

    ' ---- SQL (write) ----
    Property Let SQL(b)
        m_bShowSQL = b
    End Property
    
    ' ---- Filter (write) ----
    Property Let Filters(b)
        m_bFilters = b
    End Property

    ' ---- Export (write) ----
    Property Let Export(b)
        m_bShowExportLink = b
    End Property

    ' ---- ImageDir (read/write)----
    Property Let ImageDir(s)
        m_sIMAGEDir = s
    End Property

    Property Get ImageDir()
        ImageDir = m_sIMAGEDir
    End Property


    '-----------------------------------------------------------------------
    ' Private Member Functions
    '

    ''----------------------------------------------------------------------
    '' Name:     Class_Initialize
    ''           ================
    '' 
    '' Constructor.
    ''
    ''----------------------------------------------------------------------
    Private Sub Class_Initialize()

        Set m_DB           = Server.CreateObject("ADODB.Connection")
        Set m_RS           = Server.CreateObject("ADODB.Recordset")

        m_nMode            = DEF_MODE
        m_nFormMode        = DEF_FORM_MODE

        m_sDSN             = ""
        m_sDBName          = ""
        m_sTable           = ""
        m_sSQL             = ""
        m_nPage            = DEF_PAGE
        m_nPageSize        = DEF_PAGE_SIZE
        m_bSortFields      = DEF_SORT_FIELDS
        m_bViewDefinitions = DEF_VIEW_DEFINITIONS
        m_bViewSQL         = DEF_VIEW_SQL
        m_bAutoPKDetection = DEF_PK_DETECTION
        m_bSubmitted       = False

        m_bReadOnly        = DEF_READONLY 

        m_bListTables      = DEF_LIST_TABLES
        m_bShowDefLink     = DEF_SHOW_DEF_LINK
        m_bShowExportLink  = DEF_EXPORT_LINK
        m_bShowSQL         = DEF_SQL_LINK
        m_bFilters         = DEF_FILTERS
        m_nNumberOfFilters = DEF_NUM_FILTER

        m_sUTEScript       = Request.ServerVariables("SCRIPT_NAME")
        m_sIMAGEDir        = DEF_IMAGE_DIR

        Redim m_PrimaryKeyFields(0)
        Redim m_PrimaryKeyTypes(0)
        Redim m_StandardFields(0)
        Redim m_StandardTypes(0)

        Redim m_SortFields(0)
        Redim m_SortFieldsOrder(0)

        Redim m_FilterFields(0)
        Redim m_FilterCompares(0)
        Redim m_FilterValues(0)
        Redim m_FilterCombines(0)

        Redim m_ErrorField(0)
        Redim m_ErrorMessage(0)

    End Sub

    ''----------------------------------------------------------------------
    '' Name:     Class_Terminate
    ''           ===============
    '' 
    '' Destructor.
    ''
    ''----------------------------------------------------------------------
    Private Sub Class_Terminate()
        Redim m_PrimaryKeyFields(0)
        Redim m_StandardFields(0)
        Set m_RS = Nothing
        Set m_DB = Nothing
        if IsObject(m_RSForm) then
            Set m_RSForm = Nothing
        end if
    End Sub


    ''----------------------------------------------------------------------
    '' Name:     SetURLParameter
    ''           ===============
    '' 
    '' Sets a given parameter to a URL parameter string. If the parameter is
    '' already present in the URL string it will be updated, otherwise it will
    '' simply be added.
    ''
    '' Parameter: 
    ''      sURL        URL string to set/update the parameter in
    ''      sName       name of parameter to be set
    ''      sValue      value of parameter to be set
    ''
    '' return value:
    ''      string      new URL parameter string
    ''
    ''----------------------------------------------------------------------
    Private Function SetURLParameter (sURL, sName, sValue)
        Dim iPos
        Dim sLink, sReturn, sLeft, sRight

        sLink = sURL
        sReturn = ""

        if InStr(sLink, sName & "=") <> 0 then
            ' update exisiting parameter
            iPos = InStr(sLink, sName & "=")
            sLeft = Left(sLink, iPos+Len(sName))

            sRight = Right(sLink, Len(sLink) - (iPos + Len(sName)))
            if InStr(sRight, "&") <> 0 then
                ' at least one following parameter
                iPos = InStr(sRight, "&")
                sRight = Right(sRight, Len(sRight)-iPos+1)

                sReturn = sReturn & sLeft & sValue & sRight
            else
                ' no following parameter
                sReturn = sReturn & sLeft & sValue
            end if
        else
            ' add parameter
            if Len(sLink) <> 0 then
                sReturn = sReturn & sLink & "&" & sName & "=" & sValue
            else
                sReturn = sReturn & sName & "=" & sValue
            end if
        end if

        SetURLParameter = sReturn
    End Function


    ''----------------------------------------------------------------------
    '' Name:     buildLink
    ''           =========
    '' 
    '' Returns a string containing all UTE relevant URL parameters, such
    '' as tablename, page or primary key fields.
    ''
    '' Parameter: 
    ''      sCurrent    current URL string
    ''
    '' return value:
    ''      string      link
    ''
    ''----------------------------------------------------------------------
    Private Function buildLink (sCurrent)
        Dim i
        Dim sReturn, sDefs, sSQL, sSort, sSubmitted

        ' preserve current URL string
        sReturn = sCurrent

        sSQL = "0"
        if m_bViewSQL then sSQL = "1"
        sDefs = "0"
        if m_bViewDefinitions then sDefs = "1"
        sSort = "0"
        if m_bSortFields then sSort = "1"
        sSubmitted = "0"
        if m_bSubmitted then sSubmitted = "1"

        ' set all UTE URL params
        sReturn = SetURLParameter(sReturn, sParamTable,      m_sTable)
        sReturn = SetURLParameter(sReturn, sParamMode,       CStr(m_nMode))
        sReturn = SetURLParameter(sReturn, sParamFormMode,   CStr(m_nFormMode))
        sReturn = SetURLParameter(sReturn, sParamPage,       CStr(m_nPage))
        sReturn = SetURLParameter(sReturn, sParamPageSize,   CStr(m_nPageSize))
        sReturn = SetURLParameter(sReturn, sParamSQL,        sSQL)
        sReturn = SetURLParameter(sReturn, sParamDefs,       sDefs)
        sReturn = SetURLParameter(sReturn, sParamSortFields, sSort)
        sReturn = SetURLParameter(sReturn, sParamSubmitted,  sSubmitted)
        sReturn = SetURLParameter(sReturn, sParamRecord,     CStr(m_nRecord))

        ' add primary key fields
        for i = 1 to UBound(m_PrimaryKeyFields)
            sReturn = SetURLParameter(sReturn, sParamPKey & CStr(i), m_PrimaryKeyFields(i))
        next

        ' add sort fields
        for i = 1 to UBound(m_SortFields)
            sReturn = SetURLParameter(sReturn, sParamSort & CStr(i),    m_SortFields(i))
            sReturn = SetURLParameter(sReturn, sParamSortDir & CStr(i), m_SortFieldsOrder(i))
        next

        buildLink = sReturn

    End Function


    ''----------------------------------------------------------------------
    '' Name:     GetLink
    ''           =======
    '' 
    '' Adds the given parameter to a compelte UTE link. An UTE link includes
    '' all possible URL parameters and is used to switch table pages or open
    '' the record form.
    ''
    '' Parameter: 
    ''      sScript     name of script to be called, e.g. ute.asp
    ''      sCurrent    current link, if "" the function build a complete new link
    ''      sParam      name of parameter to be set
    ''      sValue      value to be set
    ''
    '' return value:
    ''      string      complete link
    ''
    ''----------------------------------------------------------------------
    Private Function GetLink ( sScript, sCurrent, sParam, sValue )

        Dim iPos
        Dim sReturn, sLeft, sRight

        ' check if we already have a complete UTE URL string ?
        if InStr(sCurrent, sParamMode) <> 0 then
            ' use current link
            iPos = InStr(sCurrent, "?")
            sReturn = "&" & Right(sCurrent, Len(sCurrent)-iPos)
        else
            ' build new link
            sReturn = "&" & buildLink(sCurrent)
        end if

        sReturn = SetURLParameter(sReturn, sParam, sValue)

        ' add script name, repleace leading "&" by "?"
        sReturn = sScript & "?" & Right(sReturn, Len(sReturn)-1)

        GetLink = sReturn
    End Function


    ''----------------------------------------------------------------------
    '' Name:     RemoveParameter
    ''           ===============
    '' 
    '' Removes parameter from given URL string.
    ''
    '' Parameter: 
    ''      sLink       string containing the link
    ''      sParam      parameter name
    ''
    '' return value:
    ''      string
    ''
    ''----------------------------------------------------------------------
    Private Function RemoveParameter ( sLink, sParam )
        Dim sLeft, sRight, sReturn
        Dim iPos
        sReturn = sLink

        while InStr(sReturn, sParam & "=") <> 0
            iPos   = InStr(sReturn, sParam & "=")
            sLeft  = Left(sReturn, iPos-1)
            iPos   = InStr(iPos, sReturn, "&")
            sRight = ""
            if iPos <> 0 then sRight = Right(sReturn, Len(sReturn)-iPos)
            sReturn = sLeft & sRight
        wend

        if Right(sReturn, 1) = "&" then sReturn = Left(sReturn, Len(sReturn)-1)

        RemoveParameter = sReturn
    End Function

    
    ''----------------------------------------------------------------------
    '' Name:     RemoveCountedParameters
    ''           =======================
    '' 
    '' Removes so called "counted parameters" like "pkey[n]" or "sort[n]"
    '' from the given link. The start counter defines the start value for [n].
    '' E.g.: sParam = sort, nStartCounter = 2
    '' -> removes all sort2, sort3, sort4, ... from the link
    ''
    '' Parameter: 
    ''      sLink       string containing the link
    ''      sParam      parameter name
    ''      nStarCount  start counter
    ''
    '' return value:
    ''      string
    ''
    ''----------------------------------------------------------------------
    Private Function RemoveCountedParameters ( sLink, sParam, nStartCount )
        Dim sReturn
        Dim n
        n = nStartCount
        sReturn = sLink

        while InStr(sReturn, sParam & CStr(n)) <> 0
            sReturn = RemoveParameter(sReturn, sParam & CStr(n))
            n = n + 1
        wend

        RemoveCountedParameters = sReturn
    End Function

    
    ''----------------------------------------------------------------------
    '' Name:     GetParameter
    ''           ============
    '' 
    '' Gets all parameters from URL and throw excaption if neccessary.
    ''
    '' Parameter: 
    ''      none
    ''
    '' return value:
    ''      none
    ''
    ''----------------------------------------------------------------------
    Private Sub GetParameter()

        Dim i, j
        Dim sTemp
        Dim sError

        ' ---- ODBC connect string ----
        if m_sDSN = "" then
            '"Invalid ODBC Connection String"
            sError = STR_ERR_1001 
            err.Raise vbObjectError + 1001, "ute_table", sError
        end if

        ' ---- Tablename ----
        if Request.QueryString(sParamTable) <> "" then
            m_sTable = Request.QueryString(sParamTable)
        else
            m_nMode = MD_DATABASE
        end if


        ' ---- Tablename ----
        m_sTable = Request.QueryString(sParamTable)
        if m_bListTables then
            ' if no table set, display all tables within database
            if Request.QueryString(sParamTable) = "" then
                m_nMode = MD_DATABASE
            end if
        else
            ' if no table set throw error
            if Request.QueryString(sParamTable) = "" then
                '"Missing ""%1"" URL parameter."
                sError = Replace(STR_ERR_1002, "%1", sParamTable) 
                err.Raise vbObjectError + 1002, "ute_table", sError
            end if
        end if

        ' ---- Mode ----
        if Request.QueryString(sParamMode) <> "" then
            sTemp = Request.QueryString(sParamMode)
            if not IsNumeric(sTemp) then
                '"Invalid ""%1"" URL parameter. Must be numeric."
                sError = Replace(STR_ERR_1003, "%1", sParamMode) 
                err.Raise vbObjectError + 1003, "ute_table", sError
            end if
            m_nMode = CInt(sTemp)
            if (m_nMode < MD_DATABASE) or (m_nMode > MD_FILTER) then
                '"Invalid ""%1"" URL parameter. Must be ""1"", ""2"" or ""3""."
                sError = Replace(STR_ERR_1004, "%1", sParamMode)
                err.Raise vbObjectError + 1004, "ute_table", sError
            end if
        end if

        ' ---- FormMode ----
        if Request.QueryString(sParamFormMode) <> "" then
            sTemp = Request.QueryString(sParamFormMode)
            if not IsNumeric(sTemp) then
                '"Invalid ""%1"" URL parameter. Must be numeric."
                sError = Replace(STR_ERR_1003, "%1", sParamFormMode) 
                err.Raise vbObjectError + 1003, "ute_table", sError
            end if
            m_nFormMode = CInt(sTemp)
            if (m_nFormMode < 1) or (m_nFormMode > 3) then
                '"Invalid ""%1"" URL parameter. Must be ""1"", ""2"" or ""3""."
                sError = Replace(STR_ERR_1004, "%1", sParamFormMode)
                err.Raise vbObjectError + 1004, "ute_table", sError
            end if
        end if

        ' ---- Page ----
        if Request.QueryString(sParamPage) <> "" then
            sTemp = Request.QueryString(sParamPage)
            if not IsNumeric(sTemp) then
                '"Invalid ""%1"" URL parameter. Must be numeric."
                sError = Replace(STR_ERR_1003, "%1", sParamPage) 
                err.Raise vbObjectError + 1003, "ute_table", sError
            end if
            m_nPage = CInt(sTemp)
        end if

        ' ---- Page Size ----
        if Request.QueryString(sParamPageSize) <> "" then
            sTemp = Request.QueryString(sParamPageSize)
            if not IsNumeric(sTemp) then
                '"Invalid ""%1"" URL parameter. Must be numeric."
                sError = Replace(STR_ERR_1003, "%1", sParamPageSize) 
                err.Raise vbObjectError + 1003, "ute_table", sError
            end if
            m_nPageSize = CInt(sTemp)
        end if

        ' ---- Sort Fields Alphabetically ----
        if Request.QueryString(sParamSortFields) <> "" then
            sTemp = Request.QueryString(sParamSortFields)
            if (sTemp <> "0") and (sTemp <> "1") then
                '"Invalid ""%1"" URL parameter. Must be either ""%2"" or ""%3""."
                sError = Replace(STR_ERR_1005, "%1", sParamSortDir) 
                sError = Replace(sError, "%2", "0") 
                sError = Replace(sError, "%3", "1")
                err.Raise vbObjectError + 1005, "ute_table", sError
            end if
            m_bSortFields = (sTemp = "1")
        end if

        ' ---- View SQL Statement ----
        if Request.QueryString(sParamSQL) <> "" then
            sTemp = Request.QueryString(sParamSQL)
            if (sTemp <> "0") and (sTemp <> "1") then
                '"Invalid ""%1"" URL parameter. Must be either ""%2"" or ""%3""."
                sError = Replace(STR_ERR_1005, "%1", sParamSQL) 
                sError = Replace(sError, "%2", "0") 
                sError = Replace(sError, "%3", "1")
                err.Raise vbObjectError + 1005, "ute_table", sError
            end if
            m_bViewSQL = (sTemp = "1")
        end if

        ' ---- View Field Definitions ----
        if Request.QueryString(sParamDefs) <> "" then
            sTemp = Request.QueryString(sParamDefs)
            if (sTemp <> "0") and (sTemp <> "1") then
                '"Invalid ""%1"" URL parameter. Must be either ""%2"" or ""%3""."
                sError = Replace(STR_ERR_1005, "%1", sParamDefs) 
                sError = Replace(sError, "%2", "0") 
                sError = Replace(sError, "%3", "1")
                err.Raise vbObjectError + 1005, "ute_table", sError
            end if
            m_bViewDefinitions = (sTemp = "1")
        end if

        ' ---- Submitted ----
        if Request.QueryString(sParamSubmitted) <> "" then
            sTemp = Request.QueryString(sParamSubmitted)
            if (sTemp <> "0") and (sTemp <> "1") then
                '"Invalid ""%1"" URL parameter. Must be either ""%2"" or ""%3""."
                sError = Replace(STR_ERR_1005, "%1", sParamSubmitted) 
                sError = Replace(sError, "%2", "0") 
                sError = Replace(sError, "%3", "1")
                err.Raise vbObjectError + 1005, "ute_table", sError
            end if
            m_bSubmitted = (sTemp = "1")
        end if

        ' ---- Record ----
        if Request.QueryString(sParamRecord) <> "" then
            sTemp = Request.QueryString(sParamRecord)
            if not IsNumeric(sTemp) then
                '"Invalid ""%1"" URL parameter. Must be numeric."
                sError = Replace(STR_ERR_1003, "%1", sParamRecord) 
                err.Raise vbObjectError + 1003, "ute_table", sError
            end if
            m_nRecord = CInt(sTemp)
        end if


        ' ---- Primary Keys ----
        i = 1
        while Request.QueryString(sParamPKey & CStr(i)) <> ""
            ' switch off auto primary key detection 
            m_bAutoPKDetection = False
            ' "-1" will force SetPrimaryKeyFieldType to set the field type properly
            AddPrimaryKeyField Request.QueryString(sParamPKey & CStr(i)), -1
            i = i + 1
        wend


        ' ---- Sort Field ----
        ' This can be either "sort" (for compatebility purpose) or "sort[n]"
        if Request.QueryString(sParamSort) <> "" then
            AddSortField Request.QueryString(sParamSort)
            if Request.QueryString(sParamSortDir) <> "" then
                sTemp = LCase(Request.QueryString(sParamSortDir))
                if (sTemp <> SORT_ASC) and (sTemp <> SORT_DESC) then
                    '"Invalid ""%1"" URL parameter. Must be either ""%2"" or ""%3""."
                    sError = Replace(STR_ERR_1005, "%1", sParamSortDir) 
                    sError = Replace(sError, "%2", SORT_ASC) 
                    sError = Replace(sError, "%3", SORT_DESC)
                    err.Raise vbObjectError + 1005, "ute_table", sError
                end if
                AddSortOrder sTemp
            else
                ' default sort order
                AddSortOrder DEF_SORT_DIR
            end if
        else
            i = 1
            while Request.QueryString(sParamSort & CStr(i)) <> ""
                AddSortField Request.QueryString(sParamSort & CStr(i))

                if Request.QueryString(sParamSortDir & CStr(i)) <> "" then
                    sTemp = LCase(Request.QueryString(sParamSortDir & CStr(i)))
                    if (sTemp <> SORT_ASC) and (sTemp <> SORT_DESC) then
                        '"Invalid ""%1"" URL parameter. Must be either ""%2"" or ""%3""."
                        sError = Replace(STR_ERR_1005, "%1", sParamSortDir & CStr(i)) 
                        sError = Replace(sError, "%2", SORT_ASC) 
                        sError = Replace(sError, "%3", SORT_DESC)
                        err.Raise vbObjectError + 1005, "ute_table", sError
                    end if
                    AddSortOrder sTemp
                else
                    ' default sort order
                    AddSortOrder DEF_SORT_DIR
                end if

                i = i + 1
            wend
        end if 

        ' ---- Number of Filters ----
        if Request.QueryString(sParamFilterCount) <> "" then
            sTemp = Request.QueryString(sParamFilterCount)
            if not IsNumeric(sTemp) then
                '"Invalid ""%1"" URL parameter. Must be numeric."
                sError = Replace(STR_ERR_1003, "%1", sParamFilterCount) 
                err.Raise vbObjectError + 1003, "ute_table", sError
            end if
            m_nNumberOfFilters = CInt(sTemp)
        end if

        ' ---- General Filter Parameters ----
        if Request.QueryString(sParamFilterCompare & "1") <> "" then

            ' ---- Filter Compares ----
            i = 1
            while (Request.QueryString(sParamFilterCompare & CStr(i)) <> "") and (i <= m_nNumberOfFilters)
                Redim Preserve m_FilterCompares(UBound(m_FilterCompares)+1)
                m_FilterCompares(UBound(m_FilterCompares)) = Request.QueryString(sParamFilterCompare & CStr(i))
                i = i + 1
            wend

            ' ---- Filter Fields ----
            for j = 1 to i
                Redim Preserve m_FilterFields(UBound(m_FilterFields)+1)
                m_FilterFields(UBound(m_FilterFields)) = Request.QueryString(sParamFilterField & CStr(j))
            next

            ' ---- Filter Values ----
            for j = 1 to i
                Redim Preserve m_FilterValues(UBound(m_FilterValues)+1)
                m_FilterValues(UBound(m_FilterValues)) = Request.QueryString(sParamFilterValue & CStr(j))
            next

            ' ---- Filter Combines ----
            for j = 1 to i - 1
                Redim Preserve m_FilterCombines(UBound(m_FilterCombines)+1)
                m_FilterCombines(UBound(m_FilterCombines)) = Request.QueryString(sParamFilterCombine & CStr(j))
            next
            
        end if

    End Sub


    ''----------------------------------------------------------------------
    '' Name:     AddPrimaryKeyField
    ''           ==================
    '' 
    '' Add's a primary key field to the array
    ''
    '' Parameter:                
    ''      sField      name of field
    ''      nType       type of field
    ''
    '' return value:
    ''      none
    ''
    ''----------------------------------------------------------------------
    Private Sub AddPrimaryKeyField (sField, nType)
        Redim Preserve m_PrimaryKeyFields(UBound(m_PrimaryKeyFields)+1)
        Redim Preserve m_PrimaryKeyTypes(UBound(m_PrimaryKeyFields))
        m_PrimaryKeyFields(UBound(m_PrimaryKeyFields)) = sField
        m_PrimaryKeyTypes(UBound(m_PrimaryKeyTypes)) = nType
    End Sub


    ''----------------------------------------------------------------------
    '' Name:     AddStandardField
    ''           ================
    '' 
    '' Add's a "standard" field to the array
    ''
    '' Parameter: 
    ''      sField      name of field
    ''      nType       type of field
    ''
    '' return value:
    ''      none
    ''
    ''----------------------------------------------------------------------
    Private Sub AddStandardField (sField, nType)
        Redim Preserve m_StandardFields(UBound(m_StandardFields)+1)
        Redim Preserve m_StandardTypes(UBound(m_StandardFields))
        m_StandardFields(UBound(m_StandardFields)) = sField
        m_StandardTypes(UBound(m_StandardTypes)) = nType
    End Sub


    ''----------------------------------------------------------------------
    '' Name:     AddSortField
    ''           ============
    '' 
    '' Add's a field the table should be sorted after to the array
    ''
    '' Parameter:                
    ''      sField      name of field
    ''
    '' return value:
    ''      none
    ''
    ''----------------------------------------------------------------------
    Private Sub AddSortField (sField)
        Redim Preserve m_SortFields(UBound(m_SortFields)+1)
        m_SortFields(UBound(m_SortFields)) = sField
    End Sub


    ''----------------------------------------------------------------------
    '' Name:     AddSortOrder
    ''           ============
    '' 
    '' Add's the sort order of a field to the array
    ''
    '' Parameter:                
    ''      sField      name of field
    ''
    '' return value:
    ''      none
    ''
    ''----------------------------------------------------------------------
    Private Sub AddSortOrder (sOrder)
        Redim Preserve m_SortFieldsOrder(UBound(m_SortFieldsOrder)+1)
        m_SortFieldsOrder(UBound(m_SortFieldsOrder)) = sOrder
    End Sub


    ''----------------------------------------------------------------------
    '' Name:     SetPrimaryKeyFieldType
    ''           ======================
    '' 
    '' Sets the type of a primary key field to the types array if the
    '' current type is -1. This will be used if there are primary keys
    '' being set via URL. In this case we need to set the type afterwards.
    ''
    '' Parameter:                
    ''      sField      Name of the field
    ''      nType       Type of the field
    ''
    '' return value:
    ''      none
    ''
    ''----------------------------------------------------------------------
    Private Sub SetPrimaryKeyFieldType ( sField, nType )
        Dim i
        for i = 1 to UBound(m_PrimaryKeyFields)
            if (m_PrimaryKeyFields(i) = sField) and (m_PrimaryKeyFields(i) = -1) then
                m_PrimaryKeyTypes(i) = nType
            end if
        next
    End Sub


    ''----------------------------------------------------------------------
    '' Name:     IsKnownPrimaryKey
    ''           =================
    '' 
    '' Checks if the given field is already known as primary key
    ''
    '' Parameter: 
    ''      sField      Name of field
    ''
    '' return value:
    ''      boolean
    ''
    ''----------------------------------------------------------------------
    Private Function IsKnownPrimaryKey ( sField ) 
        Dim i
        Dim bReturn
        bReturn = False
        for i = 1 to UBound(m_PrimaryKeyFields)
            if m_PrimaryKeyFields(i) = sField then bReturn = True
        next
        IsKnownPrimaryKey = bReturn
    End Function


    ''----------------------------------------------------------------------
    '' Name:     IsPrimaryKey_inDBSchema
    ''           =======================
    '' 
    '' Checks if the given field is defined in db schema
    ''
    '' Parameter: 
    ''      sField      name of field
    ''
    '' return value:
    ''      boolean
    ''
    ''----------------------------------------------------------------------
    Private Function IsPrimaryKey_inDBSchema ( sField )
        Dim bReturn
        bReturn = False

        Dim rsSchema
        Set rsSchema = Server.CreateObject("ADODB.Recordset")
        rsSchema.CursorType = adOpenDynamic
        
        ' Getting the adSchemaPrimaryKeys will only supported by oledb 
        ' providers, not by simple ODBC connections. They will throw an
        ' error.
        on error resume next
        Set rsSchema = m_DB.openSchema(adSchemaPrimaryKeys)
        if Err = 0 then
            do while