diff --git a/source/dbconnection.pas b/source/dbconnection.pas index ce04c457..73ebed3d 100644 --- a/source/dbconnection.pas +++ b/source/dbconnection.pas @@ -595,6 +595,7 @@ type 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 @@ type 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 @@ begin 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 @@ begin 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 @@ begin 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 @@ begin 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; diff --git a/source/exportgrid.pas b/source/exportgrid.pas index 5667077d..d1ed73e2 100644 --- a/source/exportgrid.pas +++ b/source/exportgrid.pas @@ -759,7 +759,7 @@ begin 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 @@ begin 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 @@ begin Data := esc(Data) else if Data = '' then Data := esc(Data); - tmp := tmp + Data + ', '; + if not Data.IsEmpty then + tmp := tmp + Data + ', '; end; efPHPArray: begin diff --git a/source/main.pas b/source/main.pas index a8ca9755..f664e2c0 100644 --- a/source/main.pas +++ b/source/main.pas @@ -4533,7 +4533,6 @@ var i: Integer; Value: String; IsNull, AllowNewNode: Boolean; - TableCol: TTableColumn; begin Grid := ActiveGrid; Results := GridResult(Grid); @@ -4559,8 +4558,7 @@ begin 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); diff --git a/source/tabletools.pas b/source/tabletools.pas index 75ac2e17..ea48cacd 100644 --- a/source/tabletools.pas +++ b/source/tabletools.pas @@ -1602,9 +1602,6 @@ begin 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,6 +1620,7 @@ begin Inc(Offset, Limit); if Data.RecordCount = 0 then break; + Data.PrepareColumnAttributes; BaseInsert := 'INSERT INTO '; if comboExportData.Text = DATA_INSERTNEW then BaseInsert := 'INSERT IGNORE INTO ' @@ -1630,7 +1628,7 @@ begin 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 @@ begin 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'