Unnötige Update wegen fkInternalCalc:

Forum für alles rund um die MSEide und MSEgui
Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Unnötige Update wegen fkInternalCalc:

Beitrag von Soner »

Ich habe dein(mse) Text von hier (viewtopic.php?f=53&t=2171) gelesen und mein Beispiel mit MSEGUI/IDE nachgebaut um diesen Fehler(viewtopic.php?f=17&t=11132) zu umgehen.
Erstmal herzlichen Glückwunsch an Martin(mse) obwohl das Endeffekt gleich ist, funktioniert fkInternalCalc-Feld bei seinen DB-Komponenten auf Anhieb, bei SQLDB von FreePascal nur über Umwege und bei ZEOS garnicht.
Das gleiche Problem gibt es auch bei deinen Komponenten, obwohl außer fkInternalCalc-Feld nichts geändert wird, wird des Datensatz gespeichert. Ich weiß nicht ob das gewollt ist oder fehlerhaft ist. Ich lade das Beispielprogramm mit msegui hier noch.

Man braucht employee datenbank für das Beispiel.
Es ist in Ordner: firebird_XY\examples\empbuild

---
Man braucht dass nicht, aber falls man wissen möchte ob der Datensatz geändert wurde, muss man an die Tabelle Customer ein Feld hinzufügen (z.B. mit flamerobin):
1) Feld:
Table: CUSTOMER
Feldname: LASTCHANGE
Feldtype:timestamp

2) Und trigger:

Code: Alles auswählen

 
SET TERM ^ ;
CREATE TRIGGER CUSTOMER_BU FOR CUSTOMER
ACTIVE BEFORE UPDATE
POSITION 0
AS
BEGIN
  NEW.LASTCHANGE = CURRENT_TIMESTAMP;
END^
SET TERM ; ^

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Unnötige Update wegen fkInternalCalc:

Beitrag von Soner »

Hier ist das Beispielprojekt.
Dateianhänge
dbinternalcalc-msegui.7z
(6.79 KiB) 190-mal heruntergeladen

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Unnötige Update wegen fkInternalCalc:

Beitrag von mse »

Soner hat geschrieben:Das gleiche Problem gibt es auch bei deinen Komponenten, obwohl außer fkInternalCalc-Feld nichts geändert wird, wird des Datensatz gespeichert. Ich weiß nicht ob das gewollt ist oder fehlerhaft ist. Ich lade das Beispielprogramm mit msegui hier noch.

Da auch geänderte fkInternalCalc-Felder durch tmsebufdataset.cancelupdate()/cancelupdates() rekonstruiert werden sollen, muss auch dafür ein update record angelegt werden. Die Übertragung an die DB ist natürlich wie du richtig bemängelst für reine fkIinternalCalc-Updates überflüssig. Ich werde mich darum kümmern.

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Unnötige Update wegen fkInternalCalc:

Beitrag von Soner »

Für mich musst du das nicht tun, weil ich noch nicht weiß ob ich Msegui verwenden werde. Aber der Anreiz ist groß. :D
Nach dem ich dein Text gelesen habe, war ich neugierieg ob es mit Msegui funktioniert.
Ich werde in den nächsten Tagen mit Msegui einiges ausprobieren, vielleicht verwende ich es doch.
Ich überlege auch komplett neue Datenbankkomponenten zu schreiben, aber das ist viel arbeit.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Unnötige Update wegen fkInternalCalc:

Beitrag von mse »

mse hat geschrieben:Ich werde mich darum kümmern.

git master 417753a592d19df395060e4f42803c5164a0e73c macht kein DB-Update wenn lediglich Felder ohne optionsfield of_inupdate geändert wurden.
https://gitlab.com/mseide-msegui/mseide-msegui
Für mich musst du das nicht tun, weil ich noch nicht weiß ob ich Msegui verwenden werde.

Das ist ein Bug und Bugs müssen unverzüglich geflickt werden.
Ich überlege auch komplett neue Datenbankkomponenten zu schreiben, aber das ist viel arbeit.

Oh ja! ;-)

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Unnötige Update wegen fkInternalCalc:

Beitrag von Soner »

Aller Achtung du bist aber schnell, respekt. :shock:
Ich schaue deine Änderungen heute zu Hause nach.

Der Vorteil von neuen Datenbankkomponenten wäre neue Wege zu gehen. z.B. Bei allen DB-Bibliotheken werden mit einer Update/Insert-Kommando auch Felder an die DB-Server geschickt, die überhaupt nicht verändert sind.
Mann könnte in der neuen DB-Komponente anstatt update/insert-Befehle Spaltenangaben machen, damit bastelt die Komponente selber update/insert-Befehle undzwar nur für die Felder die geändert wurden.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Unnötige Update wegen fkInternalCalc:

Beitrag von mse »

Soner hat geschrieben:Der Vorteil von neuen Datenbankkomponenten wäre neue Wege zu gehen. z.B. Bei allen DB-Bibliotheken werden mit einer Update/Insert-Kommando auch Felder an die DB-Server geschickt, die überhaupt nicht verändert sind.
Mann könnte in der neuen DB-Komponente anstatt update/insert-Befehle Spaltenangaben machen, damit bastelt die Komponente selber update/insert-Befehle undzwar nur für die Felder die geändert wurden.

Das habe ich bewusst so gemacht, da dadurch mit einmalig "prepared" update-Statements gearbeitet werden kann und der gespeicherte Datenrecord konsistent ist - auch wenn unveränderte Felder durch andere Transaktionen geändert wurden. AFAIK sendet Zeos nur die veränderten Daten.
Was meinst du mit "Spaltenangaben"?

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Unnötige Update wegen fkInternalCalc:

Beitrag von Soner »

Ich habe die Änderungen von dir getestet, es funktioniert wunderbar.

Aber das Hauptproblem bleibt bestehen, nämlich dass die SQLDB unnötige Updates macht. :(
Vielleicht kann ich es dort korregieren, weil ich eben etwas dazu gelernt habe. Ich habe gerade die FreeIBComponents angeschaut, es sah einfach aus. Dort Änderungen gemacht, jetzt arbeitet TFIBDataSet genauso wie ich mir das vorgestellt habe oder wie die Datenbank komponenten von dir. Nur bis Heute wußte ich FreeIBComponents nicht, ich weiß nicht ob die zuverlässig arbeiten, deshalb muss ich mal schauen.
https://sourceforge.net/projects/fibl/
Mein Fehler gestern war, dass ich versucht habe TDateSet zu verändern, es ging schief. Ich glaube ich muss die Lösung bei BufDataset suchen, villeicht ist die Lösung dass "TRecUpdateBuffer".UpdateKind nicht ukModify wird. So ähnlich habe ich es bei TFIBDATASET gemacht.

mse hat geschrieben:... AFAIK sendet Zeos nur die veränderten Daten...

Meinst du die TZTable oder TZQuery ohne TZUpdateSQL-Komponente? Ich verwende bei TZQuery die TZUpdateSQL-Komponente und ich kann mir nicht vorstellen, dass ZEOS mein Update-SQL-Kommando auseinander nimmt und neu zusammensetzt.

mse hat geschrieben:... Was meinst du mit "Spaltenangaben"?

Damit meine ich Datenfelder. Eine SQL-Abfrage besteht doch meistens über mehrere TAbellen und da ist es schwierig herauszufinden welches Feld zu welche Tabelle gehört und welches Feld dann aktualisiert werden soll. Man konnte dafür für ein neuen Dataset zwei dimensionale string array machen oder bestehende persistente Felder erweitern:

Code: Alles auswählen

 
Feld               Tabelle
=======        ===============
Feld1            Tabelle1
Feld2            Tabelle1
Feld1            Tabelle2
...
 


Und noch eine "Where"-Liste um bei Update Datenfelder lokalisieren zu können:

Code: Alles auswählen

 
Tabelle              Where-Kondition
==========       =================
Tabelle1            Feld1= :feld1
Tabelle2            (Feld1= :feld1) AND (Feldxyz=2)
 


Damit kann die Dataset-Komponente nur für veränderte Felder dynamisch Update-SQL-Kommandos erstellen und ausführen, sogar für mehrere verschiedene Tabellen.

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Unnötige Update wegen fkInternalCalc:

Beitrag von Soner »

@mse:
I habe eine Frage zu tdbstringgrid (von msegui) was ich im Beispiel von oben verwendet habe.
Wenn man in eine Spalte F2 drückt schaltet der Datensatz zu Editmodus, der Zelleninhalt ist selektiert und jetzt wenn man jetzt linke, rechte, obere oder untere Cursortaste drückt, dann wird Editmodus verlassen und nächste Spalte gewählt, je nach dem welche Taste man gedrückt hat.
Ist das gewollt oder Fehler?
Bisher bin ich gewohnt, dass im Editmodus der Bildschirmcursor zwischen Buchstaben bewegt wird, zumindest mit der linken und rechten Cursortaste. Bei dir funktioniert das auch aber man muss erst die Auswahl entweder mit der Maus oder Pos1/Home-Tasten aufheben.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Unnötige Update wegen fkInternalCalc:

Beitrag von mse »

Soner hat geschrieben:
mse hat geschrieben:... AFAIK sendet Zeos nur die veränderten Daten...

Meinst du die TZTable oder TZQuery ohne TZUpdateSQL-Komponente?

Es ist lange her seit ich die Zeos Komponenten in MSEgui integriert habe. Das habe ich auf die Schnelle gefunden:

Code: Alles auswählen

 
 
procedure TZGenericCachedResolver.DefineUpdateColumns(
  Columns: TObjectList; OldRowAccessor, NewRowAccessor: TZRowAccessor);
var
  I: Integer;
  ColumnIndices: TIntegerDynArray;
  CompareFuncs: TCompareFuncs;
begin
  { Use precached parameters. }
  if UpdateAll and (UpdateColumns.Count > 0) then
  begin
    CopyResolveParameters(UpdateColumns, Columns);
    Exit;
  end;
 
  { Defines parameters for UpdateAll mode. }
  if UpdateAll then
  begin
    for I := FirstDbcIndex to Metadata.GetColumnCount{$IFDEF GENERIC_INDEX}-1{$ENDIF} do
    begin
      if (Metadata.GetTableName(I) <> '') and (Metadata.GetColumnName(I) <> '')
        and Metadata.IsWritable(I) then
      begin
        UpdateColumns.Add(TZResolverParameter.Create(I,
          Metadata.GetColumnName(I), Metadata.GetColumnType(I), True, ''));
      end;
    end;
    CopyResolveParameters(UpdateColumns, Columns);
  end
  { Defines parameters for UpdateChanged mode. }
  else
  begin
    SetLength(ColumnIndices, 1);
    SetLength(CompareFuncs, 1);
    for I := FirstDbcIndex to Metadata.GetColumnCount{$IFDEF GENERIC_INDEX}-1{$ENDIF} do
    begin
      ColumnIndices[0] := I;
      CompareFuncs[0] := NewRowAccessor.GetCompareFunc(I, ckEquals);
      if (Metadata.GetTableName(I) <> '') and (Metadata.GetColumnName(I) <> '')
        and Metadata.IsWritable(I) and ( OldRowAccessor.CompareBuffers(
        OldRowAccessor.RowBuffer, NewRowAccessor.RowBuffer, ColumnIndices, CompareFuncs)  <> 0) then
      begin
        Columns.Add(TZResolverParameter.Create(I,
          Metadata.GetColumnName(I), Metadata.GetColumnType(I), True, ''));
      end;
    end;
  end;
end;
 
function TZGenericCachedResolver.FormUpdateStatement(Columns: TObjectList;
  OldRowAccessor, NewRowAccessor: TZRowAccessor): string;
var
  I: Integer;
  Current: TZResolverParameter;
  TableName: string;
  Temp: string;
begin
  TableName := DefineTableName;
  DefineUpdateColumns(Columns, OldRowAccessor, NewRowAccessor);
  if Columns.Count = 0 then
  begin
    Result := '';
    Exit;
  end;
 
  Temp := '';
  for I := 0 to Columns.Count - 1 do
  begin
    Current := TZResolverParameter(Columns[I]);
    if Temp <> '' then
      Temp := Temp + ',';
    Temp := Temp + IdentifierConvertor.Quote(Current.ColumnName) + '=?';
  end;
 
  Result := Format('UPDATE %s SET %s', [TableName, Temp]);
  DefineWhereKeyColumns(Columns);
  Result := Result + FormWhereClause(Columns, OldRowAccessor);
end;
 
 

"UpdateChanged"-mode scheint nur die geänderten Felder zu speichern. Wie gesagt, der Nachteil ist, dass für jedes record-update das SQL-statement neu gebildet und prepared werden muss.
Wenn man in eine Spalte F2 drückt schaltet der Datensatz zu Editmodus, der Zelleninhalt ist selektiert und jetzt wenn man jetzt linke, rechte, obere oder untere Cursortaste drückt, dann wird Editmodus verlassen und nächste Spalte gewählt, je nach dem welche Taste man gedrückt hat.

Bei mir ist es so, dass mit ArrowUp die vorhergehende und mit ArrowDown die nächste Zeile gewählt wird. Ein Zeilenwechsel entspricht einem Datensatzwechsel und erzeugt ein TDataSet.Post() durch TDataset.CheckBrowseMode() -> der Editmodus wird verlassen.
ArrowRight selektiert die nächste Spalte wenn die ganze Zelle gewählt ist oder bewegt das Eingabecaret ein Zeichen nach rechts. Der DB-Editstatus wird nicht verändert. ArrowLeft macht das Entsprechende in die andere Richtung.
Bisher bin ich gewohnt, dass im Editmodus der Bildschirmcursor zwischen Buchstaben bewegt wird, zumindest mit der linken und rechten Cursortaste. Bei dir funktioniert das auch aber man muss erst die Auswahl entweder mit der Maus oder Pos1/Home-Tasten aufheben.

Korrekt. Die End-Taste ist eine weitere Möglichkeit. In MSEgui kann man mit den Pfeiltasten in Formularen "geographisch" navigieren.

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Unnötige Update wegen fkInternalCalc:

Beitrag von Soner »

Ich glaube, dass Zeos das nur für TZTAble und TZQuery ohne UpdateObject macht, aus dem Quelltext kann man sehen, dass Spalten- und Tabellenname aus Metadaten geholt wird.

Ich habe eben TDropdownlistedit (msegui) entdeckt, dass ist richtig gut. Bei Delphi und Lazarus habe ich es selber gemacht. Aber deiner sieht besser aus und sogar mit Spaltenüberschriften.

Ich will etwas probieren, du brauchst nicht lange zu antworten, ja/nein oder Komponentenname reicht mir.
Wenn Ich zeit habe, möchte ich mein Kassenbuch mit MSEGUI nachbauen um MSEGUI richtig kennenzulernen.
Ich habe einige Integerfelder, 2 Lookupfelder (Konto, Gegenkonto), Datumsfeld, Textfeld, 2 Currency-Felder, 1 Currencyfeld als fkInternalCalc-Field.
Ich verwende bei Lazarus TDbGrid und Ich habe die TDbGrid von Lazarus um Summenzeile erweitert, die Summen rechne ich selber.
Als Db-Komponente verwende ich ZEOS and kann auch zu den eingebauten DB-Komponenten wechseln.

1) Welche Grid soll ich bei Msegui nehmen, tdbstringgrid oder tdbwidgetgrid?
2) Hat der Report von msegui PDF-Export?

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Unnötige Update wegen fkInternalCalc:

Beitrag von mse »

Soner hat geschrieben:Ich habe einige Integerfelder, 2 Lookupfelder (Konto, Gegenkonto), Datumsfeld, Textfeld, 2 Currency-Felder, 1 Currencyfeld als fkInternalCalc-Field.
Ich verwende bei Lazarus TDbGrid und Ich habe die TDbGrid von Lazarus um Summenzeile erweitert, die Summen rechne ich selber.
Als Db-Komponente verwende ich ZEOS and kann auch zu den eingebauten DB-Komponenten wechseln.

1) Welche Grid soll ich bei Msegui nehmen, tdbstringgrid oder tdbwidgetgrid?

T(DB)WidgetGrid ist fast immer die bessere Wahl da universeller. In T*WidgetGrid werden die Spalten der entsprechenden Datatypen durch Einfügen von T*EditWidgets gebildet. Für Integer-Felder aus dem Reiter 'DBe' TDBIntegeredit, für Konto und Gegenkonto TDBEnumEditDB (ohne zusätzliches Lookupfeld!), Textfeld -> TDBStringEdit, Currency-Feld -> TDBRealEdit. Optimal ist, bei TDBEnumDB.Dropdown.OptionsDB odb_directdata zu setzen, da dann das lookup-dataset beim Auswählen nicht gescrolled wird. Im lookup-dataset müssen lokale Indizes auf das Schlüsselfeld und das Namenfeld bestehen. Ich werde ein entsprechendes Beispiel machen.
2) Hat der Report von msegui PDF-Export?

Die MSEgui Reportkomponenten werden mit TPostscriptPrinter verwendet. Der erzeugte Postscript-Code kann mit ps2pdf in PDF gewandelt werden:
https://www.ghostscript.com/doc/current/Ps2pdf.htm
Zur Vorschau kann ein beliebiger Postscript-Viewer dienen, z.B. GSview:
http://pages.cs.wisc.edu/~ghost/gsview/get50.htm
Ein Projekt mit diesem System:
https://gitlab.com/mseide-msegui/mseuni ... SEkicadBOM
https://gitlab.com/mseide-msegui/mseuni ... /kicad/bom

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Unnötige Update wegen fkInternalCalc:

Beitrag von mse »

mse hat geschrieben:Ich werde ein entsprechendes Beispiel machen.

Hier für Sqlite3:
https://gitlab.com/mseide-msegui/mseuni ... lookupedit
Wenn du etwas entsprechendes mit Firebird machen willst, erzeuge die primary key Werte in der DB mit einem Generator im "before insert" Trigger und aktiviere optionsfield of_refreshinsert der pk-Felder damit die Werte automatisch in die Datasets übernommen werden.
lookupedit.png
lookupedit.png (14.5 KiB) 4950 mal betrachtet

Edit: Habe eine Detail-Löschsperre für verwendete Datensätze eingebaut.
Zuletzt geändert von mse am Di 17. Okt 2017, 15:10, insgesamt 1-mal geändert.

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Unnötige Update wegen fkInternalCalc:

Beitrag von Soner »

Danke, du brauchtest nicht zu viel zu machen.
Ich werde das zu Hause probieren.

Ghostscript kannst du vergessen. Es lohnt für mich nicht das noch zu lernen, weil alle Pdf erwarten, verwende ich überall PDF. Versuch mal eine Ghostscript-Rechnung per Email zu senden :P
Ich habe schon alles, ich muß nur einiges auf Msegui umbauen, falls ich Msegui verwende.

Die "Primarykeys" hole ich bei ZEOS auch erst beim BeforeApplyUpdates-Ereignis um unnötige Generatorerhöhung zu vermeiden.

Ich schaue mir das ganze nachher an, danke.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Unnötige Update wegen fkInternalCalc:

Beitrag von mse »

Soner hat geschrieben:Ghostscript kannst du vergessen. Es lohnt für mich nicht das noch zu lernen, weil alle Pdf erwarten, verwende ich überall PDF. Versuch mal eine Ghostscript-Rechnung per Email zu senden :P

Ein Missverständnis? Ghostscript ist unter Linux die Standard Render-Engine für Postscript und PDF und auch für Windows erhältlich. Das erwähnte ps2pdf-Script zur Umwandlung von Postscript->PDF beruht ebenfalls auf Ghostscript.

Antworten