1
votes

I've only just started learning Pascal so please excuse my ineptitude if I've missed something glaringly obvious.

I have a program that connects to a DB, retrieves a list of accounts and displays them in a StringGrid. I am now trying to extend the program so that selecting a row in the grid will perform a further search using parameters returned from the grid.

I have the grid setup correctly (I think!), I've managed to write the accountID value into a variable and am using it to construct a query.

When the time comes to run the query a segfault is issued and I don't understand why, the error message is

Project SQLConnect raised exception class 'External: SIGSEGV' at address 583166

The Assembler window shows the following gobbledygook:

00583166 8b09                     mov    (%ecx),%ecx

Here are the procedures I'm using to return data

Initial return before selecting row, this works - on its own:

procedure TForm1.sendQueryClick(Sender: TObject);
begin
  CreateConnection;
  CreateTransaction;
try
  Query := GetQuery;
  Query.SQL.Text := 'SELECT * FROM tbl_accounts LEFT JOIN tbl_properties ON tbl_accounts.ClientID = tbl_properties.PropertyID LEFT JOIN tbl_clients ON tbl_accounts.ClientID = tbl_clients.ClientID ORDER BY tbl_accounts.AccountID DESC';
  AConnection.Open;
  Query.Open;
  while not Query.Eof do
  begin
     accID :=  Query.FieldByName('AccountID').AsString;
     accountNo := Query.FieldByName('AccountNumber').AsString;
     mortgagors := Query.FieldByName('Mortgagors').AsString;
     address :=  Query.FieldByName('Address').AsString;
     accResults.RowCount := accResults.RowCount + 1;
         accResults.Cells[0, accResults.RowCount - 1] := accID;
         accResults.Cells[1, accResults.RowCount - 1] := accountNo;
         accResults.Cells[2, accResults.RowCount - 1] := mortgagors;
         accResults.Cells[3, accResults.RowCount - 1] := address;
     Query.Next;
  end;
finally
    Query.Close;
    AConnection.Close;
    Query.Free;
    ATransaction.Free;
    AConnection.Free;
end;
end;

This is the row select query, which causes the segfault:

procedure TForm1.accResultsSelectCell(Sender: TObject; aCol, aRow: Integer; var CanSelect: Boolean);
begin
 // Hide Account ID Column
 accResults.ColWidths[0] := 0;
 CurrCol := 0;
 CurrRow := aRow;
 // Grab Account ID value from cell
 CellValue := accResults.Cells[CurrCol, CurrRow];
 selectedRow.Text := CellValue;
 // Setup Query
 try
     TestQuery := GetQuery;
     TestQuery.SQL.Text := 'SELECT * FROM tbl_accounts LEFT JOIN tbl_properties ON tbl_accounts.ClientID = tbl_properties.PropertyID LEFT JOIN tbl_clients ON tbl_accounts.ClientID = tbl_clients.ClientID WHERE AccountID = :AccID';
     TestQuery.Params.ParamByName('AccID').AsString := CellValue;
 // Open Database connection
 AConnection.Open;
 TestQuery.Open;
 begin

 end;
 finally
        TestQuery.Close;
        AConnection.Close;
        TestQuery.Free;
        ATransaction.Free;
        AConnection.Free;
 end;
end;
1
Which line actually raises the exception? - Ken White
Hi Ken, annoyingly, no exceptions are highlighted by the debugger and the program compiles with no issues. When I run it everything works until the 1st row is selected at which point the segfault occurs. - Funk247
Well, if it works "until the 1st row is selected", it would seem that you should be able to set a breakpoint at accResults.ColWidths[0] := 0; and step through in the debugger from there. You should be able to inspect the variables and class references from there to see where the problem occurs. (In Delphi, anyway, that would be pretty trivial to do.) - Ken White
That was helpful, it steps through each line until it gets to TestQuery.Open; at which point the access violation is generated. It seems to be something to do with opening the DB connection, the faulting register is under DB_TCUSTOMCONNECTION_$__OPEN in the debugger - Funk247
Your sendQueryClick calls CreateConnection (which presumably creates the AConnection), but frees it in the finally. Your accResultsSelectCell, however, does NOT create the connection; it just accesses it to open it. Accessing an object after it's been freed is not usually a good thing. :-) - Ken White

1 Answers

0
votes

IIRC: Make sure that the type of the parameter is not ftunknown.