Make data in VIEWs editable again by fetching table name and column names in a slightly different way. Fixes issue #1999.

This commit is contained in:
Ansgar Becker
2010-06-20 16:45:17 +00:00
parent da0d3d18a7
commit b215089ada

View File

@ -1914,16 +1914,23 @@ end;
procedure TMySQLQuery.PrepareEditing; procedure TMySQLQuery.PrepareEditing;
var var
Res: TMySQLQuery;
CreateTable: String; CreateTable: String;
begin begin
// Try to fetch column names and keys // Try to fetch column names and keys
if FEditingPrepared then if FEditingPrepared then
Exit; Exit;
CreateTable := Connection.GetVar('SHOW CREATE TABLE ' + QuotedDbAndTableName, 1); Res := Connection.GetResults('SHOW CREATE TABLE ' + QuotedDbAndTableName);
CreateTable := Res.Col(1);
FColumns := TTableColumnList.Create; FColumns := TTableColumnList.Create;
FKeys := TTableKeyList.Create; FKeys := TTableKeyList.Create;
FForeignKeys := TForeignKeyList.Create; FForeignKeys := TForeignKeyList.Create;
ParseTableStructure(CreateTable, FColumns, FKeys, FForeignKeys); // This is probably a VIEW, so column names need to be fetched differently
if UpperCase(Res.ColumnNames[0]) = 'TABLE' then
ParseTableStructure(CreateTable, FColumns, FKeys, FForeignKeys)
else
ParseViewStructure(Res.Col(0), FColumns);
FreeAndNil(Res);
FUpdateData := TUpdateData.Create(True); FUpdateData := TUpdateData.Create(True);
FEditingPrepared := True; FEditingPrepared := True;
end; end;
@ -2241,9 +2248,26 @@ var
Field: PMYSQL_FIELD; Field: PMYSQL_FIELD;
i: Integer; i: Integer;
tbl, db: AnsiString; tbl, db: AnsiString;
Objects: TDBObjectList;
Obj: TDBObject;
begin begin
for i:=0 to ColumnCount-1 do begin for i:=0 to ColumnCount-1 do begin
Field := mysql_fetch_field_direct(FCurrentResults, i); Field := mysql_fetch_field_direct(FCurrentResults, i);
if Field.table <> Field.org_table then begin
// Probably a VIEW, in which case we rely on the first column's table name.
// TODO: This is unsafe when joining a view with a table/view.
Objects := Connection.GetDBObjects(Connection.DecodeAPIString(Field.db));
for Obj in Objects do begin
if (Obj.Name = Connection.DecodeAPIString(Field.table)) and (Obj.NodeType = lntView) then begin
tbl := Field.table;
break;
end;
end;
if tbl <> '' then
break;
end;
if (Field.org_table <> '') and (tbl <> '') and ((tbl <> Field.org_table) or (db <> Field.db)) then if (Field.org_table <> '') and (tbl <> '') and ((tbl <> Field.org_table) or (db <> Field.db)) then
raise EDatabaseError.Create('More than one table involved.'); raise EDatabaseError.Create('More than one table involved.');
if Field.org_table <> '' then begin if Field.org_table <> '' then begin