mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-26 11:17:57 +08:00
Keep VIEW editor enabled, even if SHOW CREATE VIEW failed. Falling back to INFORMATION_SCHEMA succeeds in cases where the VIEW contains unreferenced columns. Fixes issue #2705.
This commit is contained in:
@ -371,6 +371,7 @@ type
|
|||||||
function GetTableEngines: TStringList; override;
|
function GetTableEngines: TStringList; override;
|
||||||
function GetCollationTable: TDBQuery; override;
|
function GetCollationTable: TDBQuery; override;
|
||||||
function GetCharsetTable: TDBQuery; override;
|
function GetCharsetTable: TDBQuery; override;
|
||||||
|
function GetCreateViewCode(Database, Name: String): String;
|
||||||
procedure SetLockedByThread(Value: TThread); override;
|
procedure SetLockedByThread(Value: TThread); override;
|
||||||
public
|
public
|
||||||
constructor Create(AOwner: TComponent); override;
|
constructor Create(AOwner: TComponent); override;
|
||||||
@ -1432,11 +1433,66 @@ begin
|
|||||||
lntEvent: Column := 3;
|
lntEvent: Column := 3;
|
||||||
else Exception.Create('Unhandled list node type in '+ClassName+'.GetCreateCode');
|
else Exception.Create('Unhandled list node type in '+ClassName+'.GetCreateCode');
|
||||||
end;
|
end;
|
||||||
Result := GetVar('SHOW CREATE '+UpperCase(TmpObj.ObjType)+' '+QuoteIdent(Database)+'.'+QuoteIdent(Name), Column);
|
if NodeType = lntView then
|
||||||
|
Result := GetCreateViewCode(Database, Name)
|
||||||
|
else
|
||||||
|
Result := GetVar('SHOW CREATE '+UpperCase(TmpObj.ObjType)+' '+QuoteIdent(Database)+'.'+QuoteIdent(Name), Column);
|
||||||
TmpObj.Free;
|
TmpObj.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TMySQLConnection.GetCreateViewCode(Database, Name: String): String;
|
||||||
|
var
|
||||||
|
ViewIS: TDBQuery;
|
||||||
|
ViewName, Algorithm, CheckOption, SelectCode, Definer, SQLSecurity: String;
|
||||||
|
AlternativeSelectCode: String;
|
||||||
|
rx: TRegExpr;
|
||||||
|
begin
|
||||||
|
// Get CREATE VIEW code, which can throw privilege errors and errors due to
|
||||||
|
// references to renamed or deleted columns
|
||||||
|
try
|
||||||
|
Result := GetVar('SHOW CREATE VIEW '+QuoteIdent(Database)+'.'+QuoteIdent(Name), 1);
|
||||||
|
except
|
||||||
|
on E:EDatabaseError do begin
|
||||||
|
ViewIS := GetResults('SELECT * FROM INFORMATION_SCHEMA.VIEWS WHERE '+
|
||||||
|
'TABLE_SCHEMA='+EscapeString(Database)+' AND TABLE_NAME='+EscapeString(Name));
|
||||||
|
Result := 'CREATE ';
|
||||||
|
if ViewIS.Col('DEFINER') <> '' then
|
||||||
|
Result := Result + 'DEFINER='+QuoteIdent(ViewIS.Col('DEFINER'), True, '@')+' ';
|
||||||
|
Result := Result + 'VIEW '+QuoteIdent(Name)+' AS '+ViewIS.Col('VIEW_DEFINITION')+' ';
|
||||||
|
if ViewIS.Col('CHECK_OPTION') <> 'NONE' then
|
||||||
|
Result := Result + 'WITH '+Uppercase(ViewIS.Col('CHECK_OPTION'))+' CHECK OPTION';
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
try
|
||||||
|
// Try to fetch original VIEW code from .frm file
|
||||||
|
AlternativeSelectCode := GetVar('SELECT LOAD_FILE(CONCAT(IFNULL(@@GLOBAL.datadir, CONCAT(@@GLOBAL.basedir, '+EscapeString('data/')+')), '+EscapeString(Database+'/'+Name+'.frm')+'))');
|
||||||
|
rx := TRegExpr.Create;
|
||||||
|
rx.ModifierI := True;
|
||||||
|
rx.ModifierG := False;
|
||||||
|
rx.Expression := '\nsource\=(.+)\n\w+\=';
|
||||||
|
if rx.Exec(AlternativeSelectCode) then begin
|
||||||
|
// Put pieces of CREATE VIEW together
|
||||||
|
ParseViewStructure(Result, ViewName, nil,
|
||||||
|
Algorithm, Definer, SQLSecurity, CheckOption, SelectCode);
|
||||||
|
AlternativeSelectCode := UnescapeString(rx.Match[1]);
|
||||||
|
Result := 'CREATE ';
|
||||||
|
if Algorithm <> '' then
|
||||||
|
Result := Result + 'ALGORITHM='+Uppercase(Algorithm)+' ';
|
||||||
|
if Definer <> '' then
|
||||||
|
Result := Result + 'DEFINER='+QuoteIdent(Definer, True, '@')+' ';
|
||||||
|
Result := Result + 'VIEW '+QuoteIdent(Name)+' AS '+AlternativeSelectCode+' ';
|
||||||
|
if CheckOption <> '' then
|
||||||
|
Result := Result + 'WITH '+Uppercase(CheckOption)+' CHECK OPTION';
|
||||||
|
end;
|
||||||
|
rx.Free;
|
||||||
|
except
|
||||||
|
// Do not raise if that didn't work
|
||||||
|
on E:EDatabaseError do;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function TAdoDBConnection.GetCreateCode(Database, Name: String; NodeType: TListNodeType): String;
|
function TAdoDBConnection.GetCreateCode(Database, Name: String; NodeType: TListNodeType): String;
|
||||||
var
|
var
|
||||||
Cols: TDBQuery;
|
Cols: TDBQuery;
|
||||||
@ -4434,36 +4490,9 @@ end;
|
|||||||
|
|
||||||
|
|
||||||
function TDBObject.GetCreateCode: String;
|
function TDBObject.GetCreateCode: String;
|
||||||
var
|
|
||||||
rx: TRegExpr;
|
|
||||||
ViewName, Algorithm, CheckOption, SelectCode, Definer, SQLSecurity: String;
|
|
||||||
AlternativeSelectCode: String;
|
|
||||||
begin
|
begin
|
||||||
if not FCreateCodeFetched then try
|
if not FCreateCodeFetched then try
|
||||||
FCreateCode := Connection.GetCreateCode(Database, Name, NodeType);
|
FCreateCode := Connection.GetCreateCode(Database, Name, NodeType);
|
||||||
if NodeType = lntView then begin
|
|
||||||
// Try to fetch original VIEW code from .frm file
|
|
||||||
AlternativeSelectCode := Connection.GetVar('SELECT LOAD_FILE(CONCAT(IFNULL(@@GLOBAL.datadir, CONCAT(@@GLOBAL.basedir, '+Connection.EscapeString('data/')+')), '+Connection.EscapeString(Database+'/'+Name+'.frm')+'))');
|
|
||||||
rx := TRegExpr.Create;
|
|
||||||
rx.ModifierI := True;
|
|
||||||
rx.ModifierG := False;
|
|
||||||
rx.Expression := '\nsource\=(.+)\n\w+\=';
|
|
||||||
if rx.Exec(AlternativeSelectCode) then begin
|
|
||||||
// Put pieces of CREATE VIEW together
|
|
||||||
Connection.ParseViewStructure(FCreateCode, ViewName, nil,
|
|
||||||
Algorithm, Definer, SQLSecurity, CheckOption, SelectCode);
|
|
||||||
AlternativeSelectCode := Connection.UnescapeString(rx.Match[1]);
|
|
||||||
FCreateCode := 'CREATE ';
|
|
||||||
if Algorithm <> '' then
|
|
||||||
FCreateCode := FCreateCode + 'ALGORITHM='+Uppercase(Algorithm)+' ';
|
|
||||||
if Definer <> '' then
|
|
||||||
FCreateCode := FCreateCode + 'DEFINER='+Connection.QuoteIdent(Definer, True, '@')+' ';
|
|
||||||
FCreateCode := FCreateCode + 'VIEW '+QuotedName+' AS '+AlternativeSelectCode+' ';
|
|
||||||
if CheckOption <> '' then
|
|
||||||
FCreateCode := FCreateCode + 'WITH '+Uppercase(CheckOption)+' CHECK OPTION';
|
|
||||||
end;
|
|
||||||
rx.Free;
|
|
||||||
end;
|
|
||||||
except
|
except
|
||||||
end;
|
end;
|
||||||
FCreateCodeFetched := True;
|
FCreateCodeFetched := True;
|
||||||
|
Reference in New Issue
Block a user