<% '============================================================================= ' 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 '----------------------------------------------------------------------------- ' FUNCTION: PropagateControllerToDualpathMachines ' PURPOSE: When a PC controls a machine, also assign it to dualpath'd machines ' PARAMETERS: ' conn (ADODB.Connection) - Database connection object ' equipmentMachineid (Integer) - The equipment machine being controlled ' pcMachineid (Integer) - The PC that controls the equipment ' RETURNS: Integer - Number of relationships created ' USAGE: Call after creating a "Controls" relationship '----------------------------------------------------------------------------- Function PropagateControllerToDualpathMachines(conn, equipmentMachineid, pcMachineid) On Error Resume Next Dim rsDP, rsDPCheck, controlsTypeID, dualpathMachineId, cnt cnt = 0 ' Get Controls relationship type ID Set rsDP = conn.Execute("SELECT relationshiptypeid FROM relationshiptypes WHERE relationshiptype = 'Controls'") If rsDP.EOF Then PropagateControllerToDualpathMachines = 0 rsDP.Close Set rsDP = Nothing Exit Function End If controlsTypeID = CLng(rsDP("relationshiptypeid")) rsDP.Close Set rsDP = Nothing ' Find all machines with dualpath relationship to this equipment Set rsDP = conn.Execute("SELECT related_machineid FROM machinerelationships mr " & _ "JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid " & _ "WHERE mr.machineid = " & CLng(equipmentMachineid) & " " & _ "AND rt.relationshiptype = 'Dualpath' AND mr.isactive = 1") Do While Not rsDP.EOF dualpathMachineId = CLng(rsDP("related_machineid")) ' Check if this dualpath machine already has a Controls relationship with this PC Set rsDPCheck = conn.Execute("SELECT relationshipid FROM machinerelationships " & _ "WHERE machineid = " & CLng(pcMachineid) & " " & _ "AND related_machineid = " & dualpathMachineId & " " & _ "AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1") If rsDPCheck.EOF Then ' Create Controls relationship: PC -> Dualpath Machine Dim cmdDP Set cmdDP = Server.CreateObject("ADODB.Command") cmdDP.ActiveConnection = conn cmdDP.CommandText = "INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive) VALUES (?, ?, ?, 1)" cmdDP.Parameters.Append cmdDP.CreateParameter("@pcid", 3, 1, , CLng(pcMachineid)) cmdDP.Parameters.Append cmdDP.CreateParameter("@equipid", 3, 1, , dualpathMachineId) cmdDP.Parameters.Append cmdDP.CreateParameter("@reltypeid", 3, 1, , controlsTypeID) cmdDP.Execute Set cmdDP = Nothing cnt = cnt + 1 End If rsDPCheck.Close Set rsDPCheck = Nothing rsDP.MoveNext Loop rsDP.Close Set rsDP = Nothing PropagateControllerToDualpathMachines = cnt End Function '----------------------------------------------------------------------------- ' FUNCTION: PropagateControllerFromDualpathMachine ' PURPOSE: When creating a dualpath relationship, copy controller from partner ' PARAMETERS: ' conn (ADODB.Connection) - Database connection object ' machineId1 (Integer) - First machine in dualpath ' machineId2 (Integer) - Second machine in dualpath ' RETURNS: Integer - Number of relationships created ' USAGE: Call after creating a dualpath relationship '----------------------------------------------------------------------------- Function PropagateControllerFromDualpathMachine(conn, machineId1, machineId2) On Error Resume Next Dim rsCtrl, rsCheck, controlsTypeID, pcMachineid, cnt cnt = 0 ' Get Controls relationship type ID Set rsCtrl = conn.Execute("SELECT relationshiptypeid FROM relationshiptypes WHERE relationshiptype = 'Controls'") If rsCtrl.EOF Then PropagateControllerFromDualpathMachine = 0 rsCtrl.Close Set rsCtrl = Nothing Exit Function End If controlsTypeID = CLng(rsCtrl("relationshiptypeid")) rsCtrl.Close Set rsCtrl = Nothing ' Check if machine1 has a controller, copy to machine2 if machine2 doesn't have one Set rsCtrl = conn.Execute("SELECT machineid FROM machinerelationships " & _ "WHERE related_machineid = " & CLng(machineId1) & " " & _ "AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1") If Not rsCtrl.EOF Then pcMachineid = CLng(rsCtrl("machineid")) rsCtrl.Close Set rsCtrl = Nothing ' Check if machine2 already has this controller Set rsCheck = conn.Execute("SELECT relationshipid FROM machinerelationships " & _ "WHERE machineid = " & pcMachineid & " AND related_machineid = " & CLng(machineId2) & " " & _ "AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1") If rsCheck.EOF Then ' Create: PC -> Controls -> machine2 Dim cmdCtrl Set cmdCtrl = Server.CreateObject("ADODB.Command") cmdCtrl.ActiveConnection = conn cmdCtrl.CommandText = "INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive) VALUES (?, ?, ?, 1)" cmdCtrl.Parameters.Append cmdCtrl.CreateParameter("@pcid", 3, 1, , pcMachineid) cmdCtrl.Parameters.Append cmdCtrl.CreateParameter("@equipid", 3, 1, , CLng(machineId2)) cmdCtrl.Parameters.Append cmdCtrl.CreateParameter("@reltypeid", 3, 1, , controlsTypeID) cmdCtrl.Execute Set cmdCtrl = Nothing cnt = cnt + 1 End If rsCheck.Close Set rsCheck = Nothing Else rsCtrl.Close Set rsCtrl = Nothing End If ' Now check if machine2 has a controller, copy to machine1 if machine1 doesn't have one Set rsCtrl = conn.Execute("SELECT machineid FROM machinerelationships " & _ "WHERE related_machineid = " & CLng(machineId2) & " " & _ "AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1") If Not rsCtrl.EOF Then pcMachineid = CLng(rsCtrl("machineid")) rsCtrl.Close Set rsCtrl = Nothing ' Check if machine1 already has this controller Set rsCheck = conn.Execute("SELECT relationshipid FROM machinerelationships " & _ "WHERE machineid = " & pcMachineid & " AND related_machineid = " & CLng(machineId1) & " " & _ "AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1") If rsCheck.EOF Then ' Create: PC -> Controls -> machine1 Dim cmdCtrl2 Set cmdCtrl2 = Server.CreateObject("ADODB.Command") cmdCtrl2.ActiveConnection = conn cmdCtrl2.CommandText = "INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive) VALUES (?, ?, ?, 1)" cmdCtrl2.Parameters.Append cmdCtrl2.CreateParameter("@pcid", 3, 1, , pcMachineid) cmdCtrl2.Parameters.Append cmdCtrl2.CreateParameter("@equipid", 3, 1, , CLng(machineId1)) cmdCtrl2.Parameters.Append cmdCtrl2.CreateParameter("@reltypeid", 3, 1, , controlsTypeID) cmdCtrl2.Execute Set cmdCtrl2 = Nothing cnt = cnt + 1 End If rsCheck.Close Set rsCheck = Nothing Else rsCtrl.Close Set rsCtrl = Nothing End If PropagateControllerFromDualpathMachine = cnt End Function %>