Zugriff auf MariaDB 5, Datentyp tinyint

Spezielle Fragen zu PostgreSQL, MySQL, SQLite, SQL ...
Hans35
Foriker
Beiträge: 13
Registriert: Mo 3. Dez 2018, 15:40
Kontaktdaten:

Re: Zugriff auf MariaDB 5, Datentyp tinyint

Beitrag von Hans35 » Mi 5. Dez 2018, 17:48

Hallo 4tionov,

erst mal vielen Dank für deine Hilfe. Ich denke, ich weiß jetzt ziemlich genau, mit welchem Workaround ich die Sache für mein Projekt in den Griff bekomme.

Für eine offizielle Bug-Meldung bin ich sicher der Falsche, sowas hab ich bisher noch nicht gemacht.

Für den Fall, dass du oder jemand anderes das machen möchte, habe ich das Testprogramm nochmal "eingedampft". Dabei habe ich aber festgestellt, dass der Fehler auch bei einer Abfrage ohne WHERE auftritt, solange ausnahmslos alle in der Antwort enthaltenen Zahlen positiv und einstellig sind, also von 0 bis 9. Dann und nur dann werden offenbar vom Dateityp RESULT die Ergebnisse als BOOLEAN und nicht als INTEGER weitergereicht.

Daher habe ich das Testprogramm wieder so aufgebläht, dass auch dieser Effekt deutlich wird. Hoffentlich entsteht dadurch nicht neue Verwirrung.
Anhängend der Gambas-Code und die Ausgabe von PRINT.

Ich denke, die Sache ist damit wohl ausdiskutiert.

Viele Grüße
Hans35

gambas code
' Gambas class file

' Test von tinyint

   Public Con As New Connection

   Public Sub Test()
        Con.Type = "mysql"
        Con.Port = "3306"
        Con.Name = "test"
        Con.Host = "192.168.1.7"
        
        Con.open

        Test_Tiny(-128, 127)
        Test_Tiny(0, 9)
        
        Con.Close()
    End Sub
    
        
    Sub Test_Tiny(A As Integer, B As Integer)
        
        Dim i As Integer
        Dim qry As String
        Dim res As Result
        
        'Alte Tabelle löschen
        qry = "drop table test_tiny;"
        Try con.Exec(qry)
        
        'Tabelle neu anlegen
        qry = "create table test_tiny (k integer, ti tinyint);"
        con.Exec(qry)
        
        'Tabelle mit Itegers füllen
        For i = A To B
           qry = "insert into test_tiny (k, ti) values (" & i & ", " & i & ");"
           Con.Exec(qry)
        Next

        Print "Tabelle von";; A;; "bis";; B;; ": Fehler bei Lesen ohne WHERE"
        qry = "select k, ti from test_tiny;"
        res = con.Exec(qry)
 
        For Each res 
           If res!k <> res!ti Then Print res!k;; res!ti
        Next 


        Print "Tabelle von";; A;; "bis";; B;; ": Fehler beim Lesen mit WHERE"
        For i = A To B
           qry = "select k, ti from test_tiny WHERE k=" & CStr(i) & ";"
           res = Con.Exec(qry) '              =====
    
           If res!k <> res!ti Then Print res!k;; res!ti
        Next
        Return
'
     End Sub

Code: Alles auswählen

Tabelle von -128 bis 127 : Fehler bei Lesen ohne WHERE
Tabelle von -128 bis 127 : Fehler beim Lesen mit WHERE
1 True
2 True
3 True
4 True
5 True
6 True
7 True
8 True
9 True
Tabelle von 0 bis 9  Fehler bei Lesen ohne WHERE
1 True
2 True
3 True
4 True
5 True
6 True
7 True
8 True
9 True
Tabelle von 0 bis 9  Fehler beim Lesen mit WHERE
1 True
2 True
3 True
4 True
5 True
6 True
7 True
8 True
9 True

Benutzeravatar
4tionov
Site Admin
Beiträge: 251
Registriert: So 18. Mai 2014, 22:40
Kontaktdaten:

Re: Zugriff auf MariaDB 5, Datentyp tinyint

Beitrag von 4tionov » Mi 5. Dez 2018, 22:59

Hallo Hans35,

nein, die Sache ist nicht ausdiskutiert und es ist auch kein Fehler. Gambas setzt ein von der Datenbank geliefertes Tinyint in Boolean um. 0 wird zu False, alles andere wird True.

Das macht es konsequent, in Mysql und in Sqlite, mit ziemlicher Sicherheit auch mit anderen DB-Treibern.

Wenn du aber ein Boolean extra in Integer umwandelst (mit CInt) wird daraus 0 oder -1. Und ab diesem Moment kannst du damit rechnen. Hier ein Beispiel:
gambas code
' Gambas module file

Public Sub Main()

    Dim i As Integer
    Dim con As New Connection
    Dim qry As String
    Dim res As Result

    i = 5

    With con
        .Type = "sqlite"
        .Host = "test"
        .Open
    End With

    qry = "create table test (ti tinyint);"
    con.Exec(qry)

    ' ------------------------------------------------- Tabelle füllen

    qry = "insert into test (ti) values (" & i & ");"
    con.Exec(qry)

    ' ------------------------------------------------- Test
    qry = "select ti from test;" ' Liefert Tinyint 5
    res = con.Exec(qry)

    Print "CInt von Boolean:"
    Print "CInt(True):";; CInt(True)
    Print "CInt(False):";; CInt(False)

    Print "Ab jetzt verwenden wir Tinyint " & i & " von der Datenbank, wird von Gambas als Boolean umgesetzt:"
    Print "Tinyint " & i & ":";; res!ti
    Print "Int(Tinyint " & i & "):";; Int(res!ti)
    Print "Tinyint von der Datenbank kann man in Gambas mit CInt zu Integer umwandeln:"
    Print "CInt(Tinyint " & i & "):";; CInt(res!ti)
    Print "Und damit nun rechnen:"
    Print "CInt(Tinyint " & i & ") = -1 +  " & i & " ergibt";; CInt(res!ti) + i

Catch
    Print Error.Text

End
Liefert:

Code: Alles auswählen

CInt von Boolean:
CInt(True): -1
CInt(False): 0
Ab jetzt verwenden wir Tinyint 5 von der Datenbank, wird von Gambas als Boolean umgesetzt:
Tinyint 5: True
Int(Tinyint 5): True
Tinyint von der Datenbank kann man in Gambas mit CInt in Integer umwandeln:
CInt(Tinyint 5): -1
Und damit nun rechnen:
CInt(Tinyint 5) = -1 +  5 ergibt 4
Um zu deiner ursprünglichen Frage zurückzukommen ... in Gambas kannst du mit Tinyint-Antworten der Datenbank nicht rechnen. Du müsstest also in der Abfrage dafür sorgen, dass die Datenbank nicht Tinyint sondern Integer liefert und dann ist dein Problem erledigt.

In SQL nennt man das CAST, hier mit Sqlite (Mysql sollte das auch so machen).
gambas code
 qry = "select CAST(ti as Integer) from test;" ' Liefert Integer 5
Und damit kannst du dann schließlich zuverlässig rechnen.
Alles Gute,

4tionov

Benutzeravatar
4tionov
Site Admin
Beiträge: 251
Registriert: So 18. Mai 2014, 22:40
Kontaktdaten:

Re: Zugriff auf MariaDB 5, Datentyp tinyint

Beitrag von 4tionov » Do 6. Dez 2018, 07:53

Noch eine Ergänzung:

Sollte tatsächlich von Mysql oder Mariadb gelieferte Tinyint außerhalb des Bereiches von 0 bis 10 von Gambas als Integer interpretiert werden und nicht als Boolean, wäre das tatsächlich ein Bug und müsste gemeldet und gefixt werden. Wenn Du also dafür einen Beweis liefern kannst, dann melde ich gerne den Bug. :-)

Ansonsten: Ich habe selbst etliche Jahre damit verbracht, eine VBA Datenbank-Applikation zu Gambas zu überführen, wenn Du im Rahmen deines Projektes noch auf weitere Probleme stößt, helfen wir im Forum gerne!
Alles Gute,

4tionov

Hans35
Foriker
Beiträge: 13
Registriert: Mo 3. Dez 2018, 15:40
Kontaktdaten:

Re: Zugriff auf MariaDB 5, Datentyp tinyint

Beitrag von Hans35 » Do 6. Dez 2018, 13:33

Hallo 4tionov,

vielen Dank für den Hinweise auf CAST im SQL-Befehl, das kannte ich noch nicht. Damit wird jeder andere Workaround überflüssig, und insofern ist mein Problem gelöst.

Vermutlich funktioniert dasselbe auch mit Boolean (hab ich aber noch nicht ausprbiert).

gambas code
qry = "select CAST(ti as BOOLEAN) from test;" ' liefert False für 0 und True für alles außer 0" 
Und Dank auch für das weitergehende Angebot.

Eine automatische (und in der Regel sicher unerwünschte) Umwandlung von TINYINT in BOOLEAN wird tatsächlich dann und nur dann durchgeführt, wenn alle Integer-Werte, die die Datenbank auf Grund des ausgeführten SQL-Befehls abliefert, ausnahmslos einstellig sind, also zwischen 0 und 9 (incl.) liegen, mag die Antwort der Datenbank nun aus nur einer einzigen Integer-Zahl bestehen (duch Benutzung von WHERE) oder aus mehreren Zahlen, die mit EACH durchgegangen werden können. Wenn ein einziger von der Datenbank gelieferter Wert zwei-, drei- oder vierstellig ist (10 und auch -1 sind zweistellig, -100 ist vierstellig), dann erfolgt die Umwandlung in BOOLEAN nicht, sondern es wird für alle Daten die gespeicherte Integerzahl korrekt zurückgegeben.

Entgegen meiner ursprünglichen Vermutung hat das also nicht unmittelbar etwas mit WHERE zu tun.

Ich denke, das ist tatsächlich ein Bug. Dabei bleibt für mich offen, ob man TINYINT immer als BOOLEAN nutzen wollte, oder nie. Für den jetzt geltenden Mischmasch kann ich mir jedenfalls keine Anwendung vorstellen, wo man solch ein Verhalten sinnvoll nutzen kann. Ganz abgesehen davon, dass es wohl auch nirgends dokumentiert ist .(Jedenfalls hab ich dazu nichts gefunden.)

Das tatsächliche Verhalten kannst du mit dem Programmstück aus meinem letzten Post (von 5.12., 17:48 Uhr) einfach ausprobieren, indem du dort die SUB Test_Tiny (A, B) für beliebige A und B zwischen -128 und +127 aufrufst. Da ist keine Umwandlung mit CInt o.ä. mehr drin, und mit PRINT wird immer dann eine (als "Fehler" bezeichnete) Ausgabe erzeugt, wenn das Lesen ein- und derselben Zahl als INTEGER und als TINYINT ein unterschiedliches Ergebnis bringt; zu übereinstimmenden Egebnissen erfolgt keine Ausgabe. Ich denke, als "Beweis" genügt das.

Viele Grüße
Hans35

Benutzeravatar
4tionov
Site Admin
Beiträge: 251
Registriert: So 18. Mai 2014, 22:40
Kontaktdaten:

Re: Zugriff auf MariaDB 5, Datentyp tinyint

Beitrag von 4tionov » Do 6. Dez 2018, 17:39

Ok, jetzt war ich im Betrieb und nahm die Mysql DB dort, ließ deinen Code laufen (da gibt es keine Fehler), und dann noch mal mit
gambas code
    For Each res
        Print "k:";; res!k;; "ti";; res!ti
    Next
und was kommt raus?

Code: Alles auswählen


k: -15 ti -15
k: -14 ti -14
k: -13 ti -13
k: -12 ti -12
k: -11 ti -11
k: -10 ti -10
k: -9 ti -9
k: -8 ti -8
k: -7 ti -7
k: -6 ti -6
k: -5 ti -5
k: -4 ti -4
k: -3 ti -3
k: -2 ti -2
k: -1 ti -1
k: 0 ti 0
k: 1 ti 1
k: 2 ti 2
k: 3 ti 3
k: 4 ti 4
k: 5 ti 5
k: 6 ti 6
k: 7 ti 7
k: 8 ti 8
k: 9 ti 9
k: 10 ti 10
k: 11 ti 11
k: 12 ti 12
k: 13 ti 13
k: 14 ti 14
k: 15 ti 15
Auf einem Debian Server mit Mysql:
apt show mysql-server
Package: mysql-server
Source: mysql-5.5
Version: 5.5.62-0+deb8u1

Wäre jetzt interessant zu wissen, ob es Dein Gambas oder MariaDB ist.

Dein Gambas ist schon recht alt, du verwendest Ubuntu. Vielleicht solltest Du erst mal Gambas updaten. Gambas Stable ist derzeit 3.11.4 und das bekommst Du hier:

https://launchpad.net/~gambas-team/+arc ... tu/gambas3

Und so richtest Du es auf deinem Computer ein:
https://wiki.ubuntuusers.de/Paketquelle ... alten/PPA/

In Kurzform
shell code
sudo add-apt-repository ppa:gambas-team/gambas3
sudo apt update
sudo apt upgrade
Alles Gute,

4tionov

Hans35
Foriker
Beiträge: 13
Registriert: Mo 3. Dez 2018, 15:40
Kontaktdaten:

Re: Zugriff auf MariaDB 5, Datentyp tinyint

Beitrag von Hans35 » Do 6. Dez 2018, 18:48

Das von dir gerechnete Beispiel war offenbar eine Tabelle von A=-15 bis B=15, da kommt bei mir mit EACH für res!ti auch kein BOOLEAN, und damit sind alle res!k und res!ti gleich.

Aber bei A= 0 bis B=9 oder auch bei A= 3 bis B=7 erfolgt die Ausgabe als BOOLEAN. Oder allgemein: Wenn bei EACH kein einziger Wert dabei ist, der kleiner als 0 oder größer als 9 ist.

Das Problem ist also, dass die Wiedergabe einer Zahl zwischen 0 und 9 als INTEGER oder BOOLEAN nicht eindeutig ist, sondern von den anderen Werten abhängt, die mit demselben sql-Befehl als Tabellenspalte übertragen werden. Es geht also darum, ob irgendwo in der Tabellenspalte eine Zahl enthalten ist, die außerhalb des Bereichs von 0 bis 9 liegt: dann gibt es nur noch INTEGER und kein BOOLEAN mehr. Dies, obwohl dieser "andere" Wert mit der jeweils angeschauten Zahl gar nichts zu tun hat und daher dessen Wiedergabe eigentlich unter keinen Umständen beeinflussen darf.

In deinem Beispiel gibt es in der Tabellenspalte die Werte -15 bis -1 und 10 bis 15. Durch diese werden alle Werte als INTEGER ausgegeben, auch die zwischen 0 und 9. Ist so eine Zahl aber nicht dabei (z.B. in einer kleineren Tabelle mit Tabellenwerten nur von 3 bis 7) dann wird alles BOOLEAN. Ein einziger zweistelliger Wert (also <0 oder >9) verhindert für alle Werte der Tabellenspalte die Wiedergabe als BOOLEAN.

Es ist wohl sehr gewöhnungsbedürftig, dass hier ein Wert die Wiedergabe eines anderen Wertes beeinflusst, mit dem er gar nichts zu tun haben darf.

Benutzeravatar
4tionov
Site Admin
Beiträge: 251
Registriert: So 18. Mai 2014, 22:40
Kontaktdaten:

Re: Zugriff auf MariaDB 5, Datentyp tinyint

Beitrag von 4tionov » Do 6. Dez 2018, 19:09

Ok, Test:

3-7

Code: Alles auswählen

k: 3 ti 3
k: 4 ti 4
k: 5 ti 5
k: 6 ti 6
k: 7 ti 7
0-9

Code: Alles auswählen

k: 0 ti 0
k: 1 ti 1
k: 2 ti 2
k: 3 ti 3
k: 4 ti 4
k: 5 ti 5
k: 6 ti 6
k: 7 ti 7
k: 8 ti 8
k: 9 ti 9
Irgendwas ist da bei Dir kaputt.

Hier ist der Code (ich habe Deinen etwas abgeändert):
gambas code
' Gambas module file

Public Con As New Connection

Public Sub Main()

    Test()

End

Public Sub Test()

    With Con

        .Type = "mysql"
        .Port = "3306"
        .Name = "test"
        .User = "tester"
        .Password = "tester"
        .Host = "sagichnicht"

    End With
    Con.open

    Test_Tiny(0, 9)

    Con.Close()

End Sub

Sub Test_Tiny(A As Integer, B As Integer)

    Dim i As Integer
    Dim qry As String
    Dim res As Result

    'Alte Tabelle löschen
    qry = "drop table test_tiny;"
    Try con.Exec(qry)

    'Tabelle neu anlegen
    qry = "create table test_tiny (k integer, ti tinyint);"
    con.Exec(qry)

    'Tabelle mit Itegers füllen
    For i = A To B
        qry = "insert into test_tiny (k, ti) values (" & i & ", " & i & ");"
        Con.Exec(qry)
    Next

    'Print "Tabelle von";; A;; "bis";; B;; ": Fehler bei Lesen ohne WHERE"
    qry = "select k, ti from test_tiny;"
    res = con.Exec(qry)

    For Each res
        Print "k:";; res!k;; "ti";; res!ti
    Next

End Sub

Alles Gute,

4tionov

Hans35
Foriker
Beiträge: 13
Registriert: Mo 3. Dez 2018, 15:40
Kontaktdaten:

Re: Zugriff auf MariaDB 5, Datentyp tinyint

Beitrag von Hans35 » Do 6. Dez 2018, 20:43

Was war bei deinem Post vom 5. Dez 2018, 22:59 anders?
Da hat du ja in Zeile 36 mit gambas code
          Print "Tinyint " & i & ":";; res!ti
auch "True" statt 5 erzeugt.

Könnte es damit zusammenhängen, dass du jetzt "im Betrieb" eine andere (vielleicht neuere) Gambas-Version zur Verfügung hat, in der der Bug bereits beseitigt ist? Ich habe hier (nur) Gambas 3.8.3 installiert.

Benutzeravatar
4tionov
Site Admin
Beiträge: 251
Registriert: So 18. Mai 2014, 22:40
Kontaktdaten:

Re: Zugriff auf MariaDB 5, Datentyp tinyint

Beitrag von 4tionov » Do 6. Dez 2018, 23:31

Hans35 hat geschrieben:
Do 6. Dez 2018, 20:43
Was war bei deinem Post vom 5. Dez 2018, 22:59 anders?
Da hat du ja in Zeile 36 mit gambas code
          Print "Tinyint " & i & ":";; res!ti
auch "True" statt 5 erzeugt.
SQLite. Ich verwandte SQLite. Schrieb ich doch ...
Könnte es damit zusammenhängen, dass du jetzt "im Betrieb" eine andere (vielleicht neuere) Gambas-Version zur Verfügung hat, in der der Bug bereits beseitigt ist? Ich habe hier (nur) Gambas 3.8.3 installiert.
Ja, könnte sein. Schrieb ich auch. ;-)

Sag mal wie alt bist Du? Brauchst du eine Brille?

:-)

Ich meine, ich kenne mich da auch aus ...
Alles Gute,

4tionov

Hans35
Foriker
Beiträge: 13
Registriert: Mo 3. Dez 2018, 15:40
Kontaktdaten:

Re: Zugriff auf MariaDB 5, Datentyp tinyint

Beitrag von Hans35 » Fr 7. Dez 2018, 13:37

Mit oder ohne Brille, sqlite hab ich jedenfalls nicht, sondern nur nach wie vor MariaDB5.
(Und falls es dich wirklich interessiert: Ich werde nächstes Jahr 70 und 'ne Brille hab ich schon.)

Aber ich habe Gambas, wie von dir empfohlen, neu installiert und jetzt läuft hier statt Gambas 3.8.3 nun Gambas 3.11.90.
Und jetzt ist der Fehler verschwunden.

Was ich auch immer ausprobieren mag, es lässt sich aus den TINYINT-Daten keine Ausgabe als BOOLEAN (also "True" oder "False") mehr erzeugen. "Fehler" gibt es nur noch, wenn ich den zulässigen Datenbereich (-128 bis 127) überschreite.

Es war offenbar wirklich ein Bug in Gambas, der in der neueren Version behoben ist. Das Einzige, was noch (aber nicht von uns) zu überlegen ist, wäre wohl, wie ein solcher Bug sich durch die Endkontrolle geschlichen haben kann. Aber von Qualitätssicherung bei Software habe ich wirklich keine Ahnung.
Evtl. sollte man aber die älteren Versionen aus den Repositories entfernen, denn auch Gambas 3.8.3 hatte ich erst vor einigen Wochen arglos installiert, in der fälschlichen Annahme, wenn man nichts Besonderes angibt, bekommt man immer die neueste stabile Fassung.

Nochmal vielen Dank für deine Mühe.
Hans35

besenmuckel
Foriker
Beiträge: 86
Registriert: Di 4. Nov 2014, 21:11
Kontaktdaten:

Re: Zugriff auf MariaDB 5, Datentyp tinyint

Beitrag von besenmuckel » Fr 7. Dez 2018, 20:33

Welche Version installiert wird liegt an deinen verwendeten Betriebssystem.
Standard wird bei Ubuntu 16.04 oder Distri wie Mint die auf Ubuntu basieren die Version Gambas 3.8.4 installiert. Welche Version bei den neueren Ubuntu bzw. Mint installiert wird weiss ich nicht. Du kannst ja per PPA dir die Quellen für das neuste Gambas hinzufügen und installieren mit evtl. Abängigkeiten. Bei den aktuellen Debian-Stretch wird Gambas3 Version 3.9.1 installiert. Wenn ich hier auf Online-Gambas-Buch klicke, steht dort z. Z. heute 3.11.4 Das ist nun einmal so. Bin über 60 aber unter 70 komme auch nur mit Brille Klar. :roll:

Benutzeravatar
4tionov
Site Admin
Beiträge: 251
Registriert: So 18. Mai 2014, 22:40
Kontaktdaten:

Re: Zugriff auf MariaDB 5, Datentyp tinyint

Beitrag von 4tionov » Sa 8. Dez 2018, 09:01

So, von unserer Diskussionsrunde bin ich der jüngste, ich gehe auf die sechzig zu. Und natürlich mit einem Haufen Brillen, die überall rumliegen und die ich bei Gelegenheit dann trotzdem nicht finde.
Hans35 hat geschrieben:
Fr 7. Dez 2018, 13:37
Es war offenbar wirklich ein Bug in Gambas, der in der neueren Version behoben ist. Das Einzige, was noch (aber nicht von uns) zu überlegen ist, wäre wohl, wie ein solcher Bug sich durch die Endkontrolle geschlichen haben kann. Aber von Qualitätssicherung bei Software habe ich wirklich keine Ahnung.
Evtl. sollte man aber die älteren Versionen aus den Repositories entfernen, denn auch Gambas 3.8.3 hatte ich erst vor einigen Wochen arglos installiert, in der fälschlichen Annahme, wenn man nichts Besonderes angibt, bekommt man immer die neueste stabile Fassung.
Mit einem Ubuntu bekommst du als "stabil" angesehene Software, auch mit "stabilen" Bugs. Das wird da wohl nicht gefixt werden, zumal es ja die Möglichkeit gibt, sich ein moderneres Gambas aufzuspielen. Gefixt werden da nur sicherheitskritische Bugs, die zum Beispiel einem Benutzer versehentlich Root-Rechte geben.

Warum das nicht entdeckt wird? Nun, irgendwann entdeckt es jemand, in dem Falle Du. Warum es nicht früher entdeckt wurde? Naja, wenn jemand Ganzzahlen speichern möchte, verwendet die Person in der Regel Integer, auch wenn es nur ein kleiner Range ist. Tinyint wird, wenn überhaupt, in der Regel gerne für Boolean (0,-1) genommen, wenn man nicht die (proprietäre) Repräsentation der Datenbank verwenden möchte, was auch sinnvoll ist und wenn man natürlich dafür nicht Integer verwendet, was eigentlich auch die Regel ist.

Also ich würde mal behaupten, dass Du quasi einen seltenen Fall darstellt.

Warum das durch die "Endkontrolle" geht. Es gibt bei Gambas keine "Endkontrolle". Das ist z.B. was, was bei Gambas fehlt, aber dafür ist nicht die nötige Manpower da. Und Testroutinen fehlen aufgrund fehlender Unittests bei Gambas. Vielleicht kommen die bald noch.

Trotzdem ist die Sprache sehr stabil und auch elegant, übersichtlich, performant und schön zu programmieren. Man sollte allerdings keine Raketen damit steuern.
Nochmal vielen Dank für deine Mühe.
Gerne!
Alles Gute,

4tionov

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast