<%
'=============================================================================
' FILE: db_helpers.asp
' PURPOSE: Database helper functions for parameterized queries
' CREATED: 2025-10-10
' VERSION: 2.0 - Fixed rs variable conflicts (2025-10-13)
'=============================================================================

'-----------------------------------------------------------------------------
' FUNCTION: ExecuteParameterizedQuery
' PURPOSE: Executes a SELECT query with parameters (prevents SQL injection)
' PARAMETERS:
'   conn (ADODB.Connection) - Database connection object
'   sql (String) - SQL query with ? placeholders
'   params (Array) - Array of parameter values
' RETURNS: ADODB.Recordset - Result recordset
' EXAMPLE:
'   Set rs = ExecuteParameterizedQuery(objConn, "SELECT * FROM machines WHERE machineid = ?", Array(machineId))
'-----------------------------------------------------------------------------
Function ExecuteParameterizedQuery(conn, sql, params)
    On Error Resume Next

    Dim cmd, param, i
    Set cmd = Server.CreateObject("ADODB.Command")

    cmd.ActiveConnection = conn
    cmd.CommandText = sql
    cmd.CommandType = 1 ' adCmdText

    ' Add parameters
    If IsArray(params) Then
        For i = 0 To UBound(params)
            Set param = cmd.CreateParameter("param" & i, GetADOType(params(i)), 1, Len(CStr(params(i))), params(i))
            cmd.Parameters.Append param
        Next
    End If

    ' Execute and return recordset
    Set ExecuteParameterizedQuery = cmd.Execute()

    ' Check for errors
    If Err.Number <> 0 Then
        Call CheckForErrors()
    End If

    Set cmd = Nothing
End Function

'-----------------------------------------------------------------------------
' FUNCTION: ExecuteParameterizedUpdate
' PURPOSE: Executes an UPDATE query with parameters
' PARAMETERS:
'   conn (ADODB.Connection) - Database connection object
'   sql (String) - SQL UPDATE statement with ? placeholders
'   params (Array) - Array of parameter values
' RETURNS: Integer - Number of records affected
'-----------------------------------------------------------------------------
Function ExecuteParameterizedUpdate(conn, sql, params)
    On Error Resume Next

    Dim cmd, param, i, recordsAffected
    Set cmd = Server.CreateObject("ADODB.Command")

    cmd.ActiveConnection = conn
    cmd.CommandText = sql
    cmd.CommandType = 1 ' adCmdText

    ' Add parameters
    If IsArray(params) Then
        For i = 0 To UBound(params)
            Set param = cmd.CreateParameter("param" & i, GetADOType(params(i)), 1, Len(CStr(params(i))), params(i))
            cmd.Parameters.Append param
        Next
    End If

    ' Execute
    cmd.Execute recordsAffected

    ' Check for errors
    If Err.Number <> 0 Then
        Call CheckForErrors()
    End If

    ExecuteParameterizedUpdate = recordsAffected
    Set cmd = Nothing
End Function

'-----------------------------------------------------------------------------
' FUNCTION: ExecuteParameterizedInsert
' PURPOSE: Executes an INSERT query with parameters
' PARAMETERS:
'   conn (ADODB.Connection) - Database connection object
'   sql (String) - SQL INSERT statement with ? placeholders
'   params (Array) - Array of parameter values
' RETURNS: Integer - Number of records affected
'-----------------------------------------------------------------------------
Function ExecuteParameterizedInsert(conn, sql, params)
    On Error Resume Next

    Dim cmd, param, i, recordsAffected
    Set cmd = Server.CreateObject("ADODB.Command")

    cmd.ActiveConnection = conn
    cmd.CommandText = sql
    cmd.CommandType = 1 ' adCmdText

    ' Add parameters
    If IsArray(params) Then
        For i = 0 To UBound(params)
            Set param = cmd.CreateParameter("param" & i, GetADOType(params(i)), 1, Len(CStr(params(i))), params(i))
            cmd.Parameters.Append param
        Next
    End If

    ' Execute
    cmd.Execute recordsAffected

    ' Check for errors
    If Err.Number <> 0 Then
        Call CheckForErrors()
    End If

    ExecuteParameterizedInsert = recordsAffected
    Set cmd = Nothing
End Function

'-----------------------------------------------------------------------------
' FUNCTION: GetADOType
' PURPOSE: Determines ADO data type for a parameter value
' PARAMETERS:
'   value (Variant) - Value to check
' RETURNS: Integer - ADO data type constant
'-----------------------------------------------------------------------------
Function GetADOType(value)
    ' ADO Type Constants:
    ' 2 = adSmallInt, 3 = adInteger, 4 = adSingle, 5 = adDouble
    ' 6 = adCurrency, 7 = adDate, 11 = adBoolean
    ' 200 = adVarChar, 201 = adLongVarChar

    If IsNull(value) Then
        GetADOType = 200 ' adVarChar
    ElseIf IsNumeric(value) Then
        If InStr(CStr(value), ".") > 0 Then
            GetADOType = 5 ' adDouble
        Else
            GetADOType = 3 ' adInteger
        End If
    ElseIf IsDate(value) Then
        GetADOType = 7 ' adDate
    ElseIf VarType(value) = 11 Then ' vbBoolean
        GetADOType = 11 ' adBoolean
    Else
        GetADOType = 200 ' adVarChar (default for strings)
    End If
End Function

'-----------------------------------------------------------------------------
' FUNCTION: GetLastInsertId
' PURPOSE: Gets the last auto-increment ID inserted (MySQL specific)
' PARAMETERS:
'   conn (ADODB.Connection) - Database connection object
' RETURNS: Integer - Last insert ID
'-----------------------------------------------------------------------------
Function GetLastInsertId(conn)
    On Error Resume Next

    Dim rsLocal
    Set rsLocal = conn.Execute("SELECT LAST_INSERT_ID() AS id")

    If Err.Number <> 0 Then
        GetLastInsertId = 0
        Exit Function
    End If

    If Not rsLocal.EOF Then
        GetLastInsertId = CLng(rsLocal("id"))
    Else
        GetLastInsertId = 0
    End If

    rsLocal.Close
    Set rsLocal = Nothing

    If Err.Number <> 0 Then
        GetLastInsertId = 0
    End If
End Function

'-----------------------------------------------------------------------------
' FUNCTION: RecordExists
' PURPOSE: Checks if a record exists based on criteria
' PARAMETERS:
'   conn (ADODB.Connection) - Database connection object
'   tableName (String) - Table to check
'   fieldName (String) - Field to check
'   fieldValue (Variant) - Value to look for
' RETURNS: Boolean - True if record exists
'-----------------------------------------------------------------------------
Function RecordExists(conn, tableName, fieldName, fieldValue)
    On Error Resume Next

    Dim sql, rsLocal
    sql = "SELECT COUNT(*) AS cnt FROM " & tableName & " WHERE " & fieldName & " = ?"

    Set rsLocal = ExecuteParameterizedQuery(conn, sql, Array(fieldValue))

    If Err.Number <> 0 Then
        RecordExists = False
        Exit Function
    End If

    If Not rsLocal.EOF Then
        RecordExists = (CLng(rsLocal("cnt")) > 0)
    Else
        RecordExists = False
    End If

    rsLocal.Close
    Set rsLocal = Nothing

    If Err.Number <> 0 Then
        RecordExists = False
    End If
End Function

'-----------------------------------------------------------------------------
' FUNCTION: GetRecordCount
' PURPOSE: Gets count of records matching criteria
' PARAMETERS:
'   conn (ADODB.Connection) - Database connection object
'   tableName (String) - Table to query
'   whereClause (String) - WHERE clause (without WHERE keyword) - use ? for params
'   params (Array) - Array of parameter values for WHERE clause
' RETURNS: Integer - Count of matching records
'-----------------------------------------------------------------------------
Function GetRecordCount(conn, tableName, whereClause, params)
    On Error Resume Next

    Dim sql, rsLocal
    If whereClause <> "" Then
        sql = "SELECT COUNT(*) AS cnt FROM " & tableName & " WHERE " & whereClause
    Else
        sql = "SELECT COUNT(*) AS cnt FROM " & tableName
    End If

    Set rsLocal = ExecuteParameterizedQuery(conn, sql, params)

    If Err.Number <> 0 Then
        GetRecordCount = 0
        Exit Function
    End If

    If Not rsLocal.EOF Then
        GetRecordCount = CLng(rsLocal("cnt"))
    Else
        GetRecordCount = 0
    End If

    rsLocal.Close
    Set rsLocal = Nothing

    If Err.Number <> 0 Then
        GetRecordCount = 0
    End If
End Function
%>
