Zeoslib 7.0.3 und Firebird 2.5

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
jezko
Beiträge: 14
Registriert: Mi 25. Mai 2011, 08:36
OS, Lazarus, FPC: Win7 L 1.2.4 FPC 2.6.4
CPU-Target: 32bit
Wohnort: Österreich

Zeoslib 7.0.3 und Firebird 2.5

Beitrag von jezko »

Hallo zusammen,

ich verwendet Lazarus 1.1 mit FPC 2.6.2, Zeoslib 7.0.3 und Firebird 2.5 (alles 32 Bit) und Windows 7 Professional 64 Bit.

Ich habe eine kleine App geschrieben, in welcher Wechselkurs auf einer eigenene Form gepflegt werden und anschließend in Firebird gespeichert werden. Auf der DB habe ich das Feld "Value" als DECIMAL (18,4) deklariert und auch so in die App übernommen. In der App selbest habe ich beim entsprechenden Feld die Precision auf 4 gesetzt und das DisplayFormat sowie EditFormat auf ##.###,#### gesetzt. Wenn ich nun in der App den Wert z.B. 1,22 eingebe, dann landet in der DB der Wert 1,2199. Gebe ich hingegen 1,2211 ein, so landet genau dieser Wert in der DB.

Weitere Bsp.:
1,2 Eingabe --> 1,199 auf der DB
1,22 Einagbe --> 1,2199 auf der DB
1,24 Eingabe --> 1,2499 auf ded DB
1,1 Einagbe --> 1,1 auf der DB
1,32 Eingabe --> 1,32 auf der DB
2,2 Eingabe --> 2,2 auf der DB
2,4 Eingabe --> 2,399 auf der DB
2,5 Eingabe --> 2,5 auf der DB
4,4 Einagbe --> 4,4 auf der DB
4,6 Eingabe --> 4,599 auf der DB
6,6 Eingabe --> 6,599 auf der DB

usw.

Hat jemand vielleicht eine Idee woran das liegen kann?

Danke für euere Hilfe und lg
Jezko

hde
Beiträge: 556
Registriert: Mi 11. Aug 2010, 02:56

Re: Zeoslib 7.0.3 und Firebird 2.5

Beitrag von hde »

Hab's kurz angetestet unter laz 1.1-2.7.1 - Zeos 7.0.3 stable - mySQl 5.5 - XP-32
und kein Problem festellen können.
decimal 16.6 wird bei allen Werten sauber belegt.

was/wie genau sieht dein code aus?

hde

gocher
Beiträge: 298
Registriert: Di 23. Nov 2010, 23:41
OS, Lazarus, FPC: Ubuntu/Win, Lazarus trunk, FPC trunk
CPU-Target: 32Bit/64Bit
Wohnort: Geldern
Kontaktdaten:

Re: Zeoslib 7.0.3 und Firebird 2.5

Beitrag von gocher »

Versuche es mal mit NUMERIC als Feldtyp, ich glaube bei Firebird gab es einen Unterschied zwischen NUMERIC und DECIMAL, NUMERIC war genauer!
MfG Gocher
akt. Projekt: Webserver(HTTPS HTTP/2) mit integrierten CMS in Free Pascal - www.gocher.me

jezko
Beiträge: 14
Registriert: Mi 25. Mai 2011, 08:36
OS, Lazarus, FPC: Win7 L 1.2.4 FPC 2.6.4
CPU-Target: 32bit
Wohnort: Österreich

Re: Zeoslib 7.0.3 und Firebird 2.5

Beitrag von jezko »

Hallo Gocher,

danke für deinen Hinweis, NUMERIC hat das Problem gelöst.

lg
Jezko

EgonHugeist
Beiträge: 93
Registriert: Di 17. Apr 2012, 22:41

Re: Zeoslib 7.0.3 und Firebird 2.5

Beitrag von EgonHugeist »

@All,

ich hab das problem gefunden und teilweise gelöst.

Code: Alles auswählen

 
procedure TZParamsSQLDA.UpdateBigDecimal(const Index: Integer; Value: Extended);
var
  SQLCode: SmallInt;
  TempStr: string;
  TempFloat: Extended;
begin
  CheckRange(Index);
 
  {$R-}
  with FXSQLDA.sqlvar[Index] do
  begin
    if (sqlind <> nil) and (sqlind^ = -1) then
       Exit;
 
    SQLCode := (sqltype and not(1));
 
    if (sqlscale < 0)  then
    begin //http://code.google.com/p/fbclient/wiki/DatatypeMapping
      case SQLCode of
        SQL_SHORT  : PSmallInt(sqldata)^ := Trunc(Value * IBScaleDivisor[sqlscale]);
        SQL_LONG   : PInteger(sqldata)^  := Trunc(Value * IBScaleDivisor[sqlscale]);
        SQL_INT64,
        SQL_QUAD   : //PInt64(sqldata)^    := Trunc(Value * GetIBScaleDivisor(sqlscale)); EgonHugeist: Trunc seems to have rounding issues!
          begin
            if sqlscale > 0 then
              TempFloat := RoundTo(Value, sqlscale*-1)
            else
              TempFloat := RoundTo(Value, sqlscale);
            TempStr := FloatToStrF(TempFloat * GetIBScaleDivisor(sqlscale), ffFixed, 18, 0);
            //remain issues if decimal digits > scale than we've school learned rounding success randomly only
            //each aproach did fail: RoundTo(Value, sqlscale*-1), Round etc.
            //so the developer has to take to take care for this case
            PInt64(sqldata)^    := StrToInt64(TempStr);
          end;
        SQL_DOUBLE : PDouble(sqldata)^   := Value;                                        //I have tested with Query.ParamByName ().AsCurrency to check this, problem does not lie with straight SQL
 
Die function Trunc(): Int64 verursachte den Ärger. Ich wußte mir nicht anders zu helfen, als den Typ in enen String zu convertieren. Das Patch funktioniert wunderbar, solang die Kommastellen den Erwartungen entsprechen. Sollten jedoch mehr Stellen verfügbar sein, bringt auch RoundTo merkwürdig instabile Resultate...

Patch ist in \testing7.1 (SVN) verfügbar.

Gruß Michael
Zuletzt geändert von Lori am Di 4. Jun 2013, 16:59, insgesamt 1-mal geändert.
Grund: richtiger Highlighter
ZeosDevTeam

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: Zeoslib 7.0.3 und Firebird 2.5

Beitrag von mse »

MSEgui verwendet für DECIMAL ftBCD bis Skalierung 4, ab Skalierung 5 wird ftFloat verwendet, falls <database>.controller.options dbo_bcdtofloatif aktiviert ist. Der code ist hier:
http://gitorious.org/mseide-msegui/msei ... ection.pas
Wichtig die Aufrufe von scaleexp10() in den Zeilen 1060 und 1203 und round() in Zeile 1135.

MSEgui liefert für alle Testfälle von jezko korrekte Ergebnisse, siehe Vergleich mit Flamerobin.
decimal.png
Martin

EgonHugeist
Beiträge: 93
Registriert: Di 17. Apr 2012, 22:41

Re: Zeoslib 7.0.3 und Firebird 2.5

Beitrag von EgonHugeist »

Hallo Martin,

der Ergebniswert für Round(x: real): Int64 war mir zu ungenau für den Typ DECIMAL. Darum mein Workaround. Übrigens für das Bsp. liefert Zeos nun auch perfekte Resultate. Nur, wie beschrieben, wenn SCALE > Expected ist, kann es zu Compiler-bezogenen Rundungsproblemen kommen, welche nicht Zeos zuzuordnen sind.

Grüße Michael
ZeosDevTeam

Antworten