Export whole CREATE VIEW code, not only the VIEW body. Fixes issue #2625.

This commit is contained in:
Ansgar Becker
2012-02-04 06:52:21 +00:00
parent c5a52475c5
commit ba14143238
6 changed files with 33 additions and 25 deletions

View File

@ -119,7 +119,7 @@ begin
FForeignKeys.Clear;
case FDBObj.NodeType of
lntTable: FDBObj.Connection.ParseTableStructure(FDBObj.CreateCode, FColumns, FKeys, FForeignKeys);
lntView: FDBObj.Connection.ParseViewStructure(FDBObj.CreateCode, FDBObj.Name, FColumns, Dummy, Dummy, Dummy, Dummy);
lntView: FDBObj.Connection.ParseViewStructure(FDBObj.CreateCode, FDBObj.Name, FColumns, Dummy, Dummy, Dummy, Dummy, Dummy);
else raise Exception.Create('Neither table nor view: '+FDBObj.Name);
end;

View File

@ -18,7 +18,6 @@ type
TDBObject = class(TPersistent)
private
FCreateCode: String;
FViewSelectCode: String;
FCreateCodeFetched: Boolean;
FConnection: TDBConnection;
function GetObjType: String;
@ -39,7 +38,6 @@ type
property ObjType: String read GetObjType;
property ImageIndex: Integer read GetImageIndex;
property CreateCode: String read GetCreateCode write SetCreateCode;
property ViewSelectCode: String read FViewSelectCode;
property Connection: TDBConnection read FConnection;
end;
PDBObject = ^TDBObject;
@ -302,7 +300,8 @@ type
procedure ClearDbObjects(db: String);
procedure ClearAllDbObjects;
procedure ParseTableStructure(CreateTable: String; Columns: TTableColumnList; Keys: TTableKeyList; ForeignKeys: TForeignKeyList);
procedure ParseViewStructure(CreateCode, ViewName: String; Columns: TTableColumnList; var Algorithm, Definer, CheckOption, SelectCode: String);
procedure ParseViewStructure(CreateCode, ViewName: String; Columns: TTableColumnList;
var Algorithm, Definer, SQLSecurity, CheckOption, SelectCode: String);
procedure ParseRoutineStructure(CreateCode: String; Parameters: TRoutineParamList;
var Deterministic: Boolean; var Definer, Returns, DataAccess, Security, Comment, Body: String);
function GetDatatypeByName(Datatype: String): TDBDatatype;
@ -2938,7 +2937,8 @@ begin
end;
procedure TDBConnection.ParseViewStructure(CreateCode, ViewName: String; Columns: TTableColumnList; var Algorithm, Definer, CheckOption, SelectCode: String);
procedure TDBConnection.ParseViewStructure(CreateCode, ViewName: String; Columns: TTableColumnList;
var Algorithm, Definer, SQLSecurity, CheckOption, SelectCode: String);
var
rx: TRegExpr;
Col: TTableColumn;
@ -3800,7 +3800,7 @@ begin
lntTable:
Connection.ParseTableStructure(CreateCode, FColumns, FKeys, FForeignKeys);
lntView:
Connection.ParseViewStructure(CreateCode, TableName, FColumns, Dummy, Dummy, Dummy, Dummy);
Connection.ParseViewStructure(CreateCode, TableName, FColumns, Dummy, Dummy, Dummy, Dummy, Dummy);
end;
FreeAndNil(FUpdateData);
FUpdateData := TUpdateData.Create(True);
@ -4379,7 +4379,6 @@ begin
Size := s.Size;
FCreateCode := s.FCreateCode;
FCreateCodeFetched := s.FCreateCodeFetched;
FViewSelectCode := s.FViewSelectCode;
end else
inherited;
end;
@ -4437,19 +4436,33 @@ end;
function TDBObject.GetCreateCode: String;
var
rx: TRegExpr;
ViewName, Algorithm, CheckOption, SelectCode, Definer, SQLSecurity: String;
AlternativeSelectCode: String;
begin
if not FCreateCodeFetched then try
FCreateCode := Connection.GetCreateCode(Database, Name, NodeType);
if NodeType = lntView then begin
FViewSelectCode := Connection.GetVar('SELECT LOAD_FILE(CONCAT(IFNULL(@@GLOBAL.datadir, CONCAT(@@GLOBAL.basedir, '+Connection.EscapeString('data/')+')), '+Connection.EscapeString(Database+'/'+Name+'.frm')+'))');
// 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(FViewSelectCode) then
FViewSelectCode := Connection.UnescapeString(rx.Match[1])
else
FViewSelectCode := '';
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
end;

View File

@ -256,7 +256,7 @@ begin
if (Obj.Database=comboDatabase.Text) and (Obj.Name=comboTable.Text) then begin
case Obj.NodeType of
lntTable: Obj.Connection.ParseTableStructure(Obj.CreateCode, Columns, nil, nil);
lntView: Obj.Connection.ParseViewStructure(Obj.CreateCode, Obj.Name, Columns, DummyStr, DummyStr, DummyStr, DummyStr);
lntView: Obj.Connection.ParseViewStructure(Obj.CreateCode, Obj.Name, Columns, DummyStr, DummyStr, DummyStr, DummyStr, DummyStr);
end;
end;
end;

View File

@ -4746,7 +4746,7 @@ var
lntTable:
Conn.ParseTableStructure(Obj.CreateCode, Columns, nil, nil);
lntView:
Conn.ParseViewStructure(Obj.CreateCode, Obj.Name, Columns, Dummy, Dummy, Dummy, Dummy);
Conn.ParseViewStructure(Obj.CreateCode, Obj.Name, Columns, Dummy, Dummy, Dummy, Dummy, Dummy);
end;
for Col in Columns do begin
Proposal.InsertList.Add(Col.Name);
@ -6885,7 +6885,7 @@ begin
lntTable:
FActiveDbObj.Connection.ParseTableStructure(FActiveDbObj.CreateCode, SelectedTableColumns, SelectedTableKeys, SelectedTableForeignKeys);
lntView:
FActiveDbObj.Connection.ParseViewStructure(FActiveDbObj.CreateCode, FActiveDbObj.Name, SelectedTableColumns, DummyStr, DummyStr, DummyStr, DummyStr);
FActiveDbObj.Connection.ParseViewStructure(FActiveDbObj.CreateCode, FActiveDbObj.Name, SelectedTableColumns, DummyStr, DummyStr, DummyStr, DummyStr, DummyStr);
end;
except on E:EDatabaseError do
ErrorDialog(E.Message);

View File

@ -644,7 +644,7 @@ begin
Columns := TTableColumnList.Create(True);
case DBObj.NodeType of
lntTable: DBObj.Connection.ParseTableStructure(DBObj.CreateCode, Columns, nil, nil);
lntView: DBObj.Connection.ParseViewStructure(DBObj.CreateCode, DBObj.Name, Columns, Dummy, Dummy, Dummy, Dummy);
lntView: DBObj.Connection.ParseViewStructure(DBObj.CreateCode, DBObj.Name, Columns, Dummy, Dummy, Dummy, Dummy, Dummy);
else AddNotes(DBObj.Database, DBObj.Name, STRSKIPPED+'a '+LowerCase(DBObj.ObjType)+' does not contain rows.', '');
end;
if Columns.Count > 0 then begin
@ -1216,7 +1216,7 @@ begin
if not FSecondExportPass then begin
// Create temporary VIEW replacement
ColumnList := TTableColumnList.Create(True);
DBObj.Connection.ParseViewStructure(DBObj.CreateCode, DBObj.Name, ColumnList, Dummy, Dummy, Dummy, Dummy);
DBObj.Connection.ParseViewStructure(DBObj.CreateCode, DBObj.Name, ColumnList, Dummy, Dummy, Dummy, Dummy, Dummy);
Struc := '-- Creating temporary table to overcome VIEW dependency errors'+CRLF+
'CREATE TABLE ';
if ToDb then
@ -1235,8 +1235,6 @@ begin
Struc := Struc + Quoter.QuoteIdent(DBObj.Name);
Output(Struc, True, True, True, True, True);
Struc := DBObj.CreateCode;
if DBObj.ViewSelectCode <> '' then
Struc := DBObj.ViewSelectCode;
if ToDb then
Insert(Quoter.QuoteIdent(FinalDbName)+'.', Struc, Pos('VIEW', Struc) + 5 );
end;

View File

@ -61,7 +61,7 @@ end;
}
procedure TfrmView.Init(Obj: TDBObject);
var
Algorithm, CheckOption, SelectCode, Definer: String;
Algorithm, CheckOption, SelectCode, Definer, SQLSecurity: String;
begin
inherited;
lblDisabledWhy.Font.Color := clRed;
@ -71,16 +71,13 @@ begin
if Obj.Name <> '' then begin
// Edit mode
editName.Text := Obj.Name;
Obj.Connection.ParseViewStructure(Obj.CreateCode, Obj.Name, nil, Algorithm, Definer, CheckOption, SelectCode);
Obj.Connection.ParseViewStructure(Obj.CreateCode, Obj.Name, nil, Algorithm, Definer, SQLSecurity, CheckOption, SelectCode);
comboDefiner.Text := Definer;
rgAlgorithm.ItemIndex := rgAlgorithm.Items.IndexOf(Algorithm);
rgCheck.ItemIndex := rgCheck.Items.IndexOf(CheckOption);
if rgCheck.ItemIndex = -1 then
rgCheck.ItemIndex := 0;
if Obj.ViewSelectCode <> '' then
SynMemoSelect.Text := Obj.ViewSelectCode
else
SynMemoSelect.Text := SelectCode;
SynMemoSelect.Text := SelectCode;
// User may not be allowed to run SHOW CREATE VIEW, in which case we have an empty CreateCode.
// Disable editor in this case.
lblDisabledWhy.Visible := SelectCode = '';