Permalink
Browse files

Refactor exclusion of virtual columns in various places:

* introduce TDBQuery.ColIsVirtal() returning a boolean for a column index, and use that instead of examining a columns virtuality everywhere
* exclude virtual column when exporting SQL code in the grid export dialog - see #53
* sql export dialog must not activate edit mode on a result, as this introduces endless loops
* instead, move some code out of PrepareEditing into PrepareColumnAttributes, which we can now call separately without activating edit mode
  • Loading branch information...
ansgarbecker committed Dec 22, 2017
1 parent c5f6557 commit 19a1c3fbb4e96e3d7953de9e436f8829b0818db7
Showing with 36 additions and 17 deletions.
  1. +26 −6 source/dbconnection.pas
  2. +6 −3 source/exportgrid.pas
  3. +1 −3 source/main.pas
  4. +3 −5 source/tabletools.pas
View
@@ -595,6 +595,7 @@ TDBQuery = class(TComponent)
function ColIsPrimaryKeyPart(Column: Integer): Boolean; virtual; abstract;
function ColIsUniqueKeyPart(Column: Integer): Boolean; virtual; abstract;
function ColIsKeyPart(Column: Integer): Boolean; virtual; abstract;
function ColIsVirtual(Column: Integer): Boolean;
function ColAttributes(Column: Integer): TTableColumn;
function IsNull(Column: Integer): Boolean; overload; virtual; abstract;
function IsNull(Column: String): Boolean; overload;
@@ -615,6 +616,7 @@ TDBQuery = class(TComponent)
function TableName: String; virtual; abstract;
function QuotedDbAndTableName: String;
procedure DiscardModifications;
procedure PrepareColumnAttributes;
procedure PrepareEditing;
property RecNo: Int64 read FRecNo write SetRecNo;
property Eof: Boolean read FEof;
@@ -6109,7 +6111,7 @@ function TDBQuery.ColAttributes(Column: Integer): TTableColumn;
Result := nil;
if (Column < 0) or (Column >= FColumnOrgNames.Count) then
raise EDatabaseError.CreateFmt(_('Column #%s not available.'), [IntToStr(Column)]);
if FEditingPrepared then begin
if FColumns <> nil then begin
for i:=0 to FColumns.Count-1 do begin
if FColumns[i].Name = FColumnOrgNames[Column] then begin
Result := FColumns[i];
@@ -6181,6 +6183,18 @@ function TPGQuery.ColIsKeyPart(Column: Integer): Boolean;
end;
function TDBQuery.ColIsVirtual(Column: Integer): Boolean;
var
Col: TTableColumn;
begin
Result := False;
Col := ColAttributes(Column);
if Col <> nil then begin
Result := not Col.Virtuality.IsEmpty;
end;
end;
function TMySQLQuery.IsNull(Column: Integer): Boolean;
begin
if FEditingPrepared and Assigned(FCurrentUpdateRow) then
@@ -6256,17 +6270,14 @@ function TPGQuery.HasResult: Boolean;
end;
procedure TDBQuery.PrepareEditing;
procedure TDBQuery.PrepareColumnAttributes;
var
CreateCode, Dummy, DB: String;
DBObjects: TDBObjectList;
LObj, Obj: TDBObject;
begin
// Try to fetch column names and keys
if FEditingPrepared then
Exit;
// This is probably a VIEW, so column names need to be fetched differently
Obj := nil;
if FDBObject <> nil then
Obj := FDBObject
@@ -6293,7 +6304,16 @@ procedure TDBQuery.PrepareEditing;
Connection.ParseTableStructure(CreateCode, FColumns, FKeys, FForeignKeys);
lntView:
Connection.ParseViewStructure(CreateCode, Obj, FColumns, Dummy, Dummy, Dummy, Dummy, Dummy);
end;
end;
end;
procedure TDBQuery.PrepareEditing;
begin
// Try to fetch column names and keys and init update data
if FEditingPrepared then
Exit;
PrepareColumnAttributes;
FreeAndNil(FUpdateData);
FUpdateData := TUpdateData.Create(True);
FEditingPrepared := True;
View
@@ -759,7 +759,7 @@ procedure TfrmExportGrid.btnOKClick(Sender: TObject);
tmp := tmp + ' (';
Col := Grid.Header.Columns.GetFirstVisibleColumn;
while Col > NoColumn do begin
if Col <> ExcludeCol then
if (Col <> ExcludeCol) and (not GridData.ColIsVirtual(Col)) then
tmp := tmp + GridData.Connection.QuoteIdent(Grid.Header.Columns[Col].Text)+', ';
Col := Grid.Header.Columns.GetNextVisibleColumn(Col);
end;
@@ -829,7 +829,9 @@ procedure TfrmExportGrid.btnOKClick(Sender: TObject);
end;
efSQLInsert, efSQLReplace, efSQLDeleteInsert: begin
if GridData.IsNull(Col) then
if GridData.ColIsVirtual(Col) then
Data := ''
else if GridData.IsNull(Col) then
Data := 'NULL'
else if (GridData.DataType(Col).Index = dtBit) and GridData.Connection.Parameters.IsMySQL then
Data := 'b' + esc(Data)
@@ -839,7 +841,8 @@ procedure TfrmExportGrid.btnOKClick(Sender: TObject);
Data := esc(Data)
else if Data = '' then
Data := esc(Data);
tmp := tmp + Data + ', ';
if not Data.IsEmpty then
tmp := tmp + Data + ', ';
end;
efPHPArray: begin
View
@@ -4533,7 +4533,6 @@ procedure TMainForm.actDataInsertExecute(Sender: TObject);
i: Integer;
Value: String;
IsNull, AllowNewNode: Boolean;
TableCol: TTableColumn;
begin
Grid := ActiveGrid;
Results := GridResult(Grid);
@@ -4559,8 +4558,7 @@ procedure TMainForm.actDataInsertExecute(Sender: TObject);
continue; // Ignore invisible key column
if Results.ColIsPrimaryKeyPart(i) then
continue; // Empty value for primary key column
TableCol := Results.ColAttributes(i);
if (TableCol <> nil) and (not TableCol.Virtuality.IsEmpty) then
if Results.ColIsVirtual(i) then
continue; // Don't copy virtual column value
Results.RecNo := DupeNum^;
Value := Results.Col(i);
View
@@ -1602,9 +1602,6 @@ procedure TfrmTableTools.DoExport(DBObj: TDBObject);
TargetDbAndObject := Quoter.QuoteIdent(DBObj.Name);
if ToDb then
TargetDbAndObject := Quoter.QuoteIdent(FinalDbName) + '.' + TargetDbAndObject;
// Parse columns, so we can check for special things like virtual columns
ColumnList := TTableColumnList.Create(True);
DBObj.Connection.ParseTableStructure(DBObj.CreateCode, ColumnList, nil, nil);
Offset := 0;
RowCount := 0;
// Calculate limit so we select ~100MB per loop
@@ -1623,14 +1620,15 @@ procedure TfrmTableTools.DoExport(DBObj: TDBObject);
Inc(Offset, Limit);
if Data.RecordCount = 0 then
break;
Data.PrepareColumnAttributes;
BaseInsert := 'INSERT INTO ';
if comboExportData.Text = DATA_INSERTNEW then
BaseInsert := 'INSERT IGNORE INTO '
else if comboExportData.Text = DATA_UPDATE then
BaseInsert := 'REPLACE INTO ';
BaseInsert := BaseInsert + TargetDbAndObject + ' (';
for i:=0 to Data.ColumnCount-1 do begin
if ColumnList[i].Virtuality.IsEmpty then
if not Data.ColIsVirtual(i) then
BaseInsert := BaseInsert + Quoter.QuoteIdent(Data.ColumnNames[i]) + ', ';
end;
Delete(BaseInsert, Length(BaseInsert)-1, 2);
@@ -1644,7 +1642,7 @@ procedure TfrmTableTools.DoExport(DBObj: TDBObject);
if not IsFirstRowInChunk then
Row := Row + ','+CRLF+#9+'(';
for i:=0 to Data.ColumnCount-1 do begin
if not ColumnList[i].Virtuality.IsEmpty then
if Data.ColIsVirtual(i) then
Continue;
if Data.IsNull(i) then
Row := Row + 'NULL'

0 comments on commit 19a1c3f

Please sign in to comment.