SQLite3 unter PB

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Thorsten1867
Beiträge: 1360
Registriert: 04.02.2005 15:40
Computerausstattung: [Windows 10 x64] [PB V5.7x]
Wohnort: Kaufbeuren
Kontaktdaten:

Beitrag von Thorsten1867 »

Ich habe möglicher Weise ein Bug gefunden bzw. ein kleines Problem.

Wenn die "Select"-Anweisung nur 1 Zeile zurückgibt, wird die Schleife (s.u.) nicht durchlaufen, da von Anfang an EOF = 1 ist.
d.h. heißt die Datenbankabfrage muss immer mehr als 2 Zeilen als Ergebnis haben. :|

While RS\EOF = 0
......
WEND

Das Auslesen funktioniert also nur ab 2 Zeilen. Ist das Absicht?
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Wenn Du das Beispiel zu SQLite3 meinst, das ist IMHO so in Ordnung, vielleicht postet Du mal Deinen Code mit dem Fehler
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Thorsten1867
Beiträge: 1360
Registriert: 04.02.2005 15:40
Computerausstattung: [Windows 10 x64] [PB V5.7x]
Wohnort: Kaufbeuren
Kontaktdaten:

Beitrag von Thorsten1867 »

Hier mein aufs Nötigste gekürzter Code:

Code: Alles auswählen

; DBKlasse$ -> Pfad zur Datenbank
; fid -> FachID
DefType.s_RecordSet RS ; Recordset-'Objekt' deklarieren
DBHandle = SQLite3_OpenDatabase(DBKlasse$) ; Datenbank öffnen
If DBHandle
  sql$ = "SELECT noten.note, proben.gew FROM noten, proben WHERE proben.pid = noten.pid AND proben.fid = " + Str(fid) + " And noten.sid = "+SchuelerID(s)+";"
  SQLite3_GetRecordset(sql$, DBHandle, @RS) ; Recordset laden: alle Noten des Schülers
  SQLite3_RecordsetMoveFirst(@RS)
  ncount.w = 0 : nsum.w = 0
  While RS\EOF = 0
    SQLite3_GetRecordsetValueByIndex(0, @RS) : note.w = Val(RS\sValue) ; Note
    SQLite3_GetRecordsetValueByIndex(1, @RS) : gew.b = Val(RS\sValue) ; Gewichtung
    If note >= 1 And note <= 6
      ncount + gew ; Zähler + Gewichtung
      nsum + ( note * gew ); Note addieren
    EndIf
    SQLite3_RecordsetMoveNext(@RS)
  Wend
  SQLite3_ReleaseRecordset(@RS) ;}
  SQLite3_CloseDatabase(DBHandle) ; Datenbank schließen 
EndIf
Ist nur eine Probe in diesem Fach vorhanden, wird der Notendurchschnitt nicht berechnet, was nicht so ganz im Sinne des Erfinders ist. :wink:

Die Frage bleibt nun, ist das beabsichtigt, dass bei nur einer Tabellenzeile EOF von vorneherein auf 1 steht, was den Durchlauf der Schleife verhindert?!?
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

> Die Frage bleibt nun, ist das beabsichtigt, dass bei nur einer Tabellenzeile
> EOF von vorneherein auf 1 steht, was den Durchlauf der Schleife
> verhindert?!?

das scheint ein bekannter Fehler zu sein, den ich in meiner aktuellen
Entwicklungsversion bereits behoben habe.

Stell' mal als Workaround EOF manuell auf 0, bevor Du das
SQLite3_GetRecordset() ausführst.

Code: Alles auswählen

  RS\EOF = 0
  If SQLite3_GetRecordset([...])
    [...]
Grüße ... Kiffi
a²+b²=mc²
Benutzeravatar
Thorsten1867
Beiträge: 1360
Registriert: 04.02.2005 15:40
Computerausstattung: [Windows 10 x64] [PB V5.7x]
Wohnort: Kaufbeuren
Kontaktdaten:

Beitrag von Thorsten1867 »

Danke! Gute Idee, daran habe ich überhaupt nicht gedacht.
Mein momentaner Workaround ist:

Code: Alles auswählen

If RS\Rows
  Repeat
  .....  
  Until RS\EOF = 1
EndIf
Scheint zu funktionieren. Dann werde ich mal mit Spannung der neuen Version entgegenfiebern. :D
Benutzeravatar
nicolaus
Moderator
Beiträge: 1175
Registriert: 11.09.2004 13:09
Kontaktdaten:

Beitrag von nicolaus »

Ist es mit der SQLite auch möglich ne db zu importieren die ich zuvor aus einer MySQL DB von meinem Webserver exportiert habe und nun als *.sql vorliegen habe?
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

> Ist es mit der SQLite auch möglich ne db zu importieren die ich zuvor aus
> einer MySQL DB von meinem Webserver exportiert habe und nun als *.sql
> vorliegen habe?

das SQLite und mySQL-Format unterscheidet sich geringfügig, so dass ein
mySQL-Datenbank-Dump nicht 1:1 in SQLite eingespielt werden kann.

Ich habe allerdings eine kleine "mySQL zu SQLite" - Routine geschrieben, die
ich mit Erscheinen der neuen SQLite-Lib bei Bedarf veröffentlichen kann.

Grüße ... Kiffi
a²+b²=mc²
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

>> Ich habe allerdings eine kleine "mySQL zu SQLite" - Routine geschrieben, die ich mit Erscheinen der neuen SQLite-Lib bei Bedarf veröffentlichen kann

Was hälste von einem Upload auf CVS ? Dann könnte man sich das schon mal laden und testen, vor Veröffentlichung. Ausserdem wird dieser Service ja kaum genutzt :( bis jetzt
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
nicolaus
Moderator
Beiträge: 1175
Registriert: 11.09.2004 13:09
Kontaktdaten:

Beitrag von nicolaus »

Kiffi hat geschrieben:> Ist es mit der SQLite auch möglich ne db zu importieren die ich zuvor aus
> einer MySQL DB von meinem Webserver exportiert habe und nun als *.sql
> vorliegen habe?

das SQLite und mySQL-Format unterscheidet sich geringfügig, so dass ein
mySQL-Datenbank-Dump nicht 1:1 in SQLite eingespielt werden kann.

Ich habe allerdings eine kleine "mySQL zu SQLite" - Routine geschrieben, die
ich mit Erscheinen der neuen SQLite-Lib bei Bedarf veröffentlichen kann.

Grüße ... Kiffi
Wäre doch sehr an der routine interesiert da ich mir sonst selber was schreiben würde.
Könntest du sie schon raus geben?

Danke und Gruß
Nico
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

> Könntest du sie schon raus geben?

ein paar Anmerkungen zu Code:

* Ich verwende z.Zt. die Standarddatei-Funktionalitäten von PB. Mit den
FastFile-Routinen von Rings würde es erheblich schneller laufen. Leider hat
sich im Code von Rings ein kleiner Fehler eingeschlichen, der es
verhindert, Dateien korrekt auszulesen, deren Zeilentrenner nur aus
einem LF besteht. Wenn ich wieder Zeit habe, dann schaue ich mir den
FF-Source noch mal genauer an.

* Im Code verwende ich englische Kommentare. Wäre nett, wenn da
jemand mal drüberschauen würde, der des englischen mächtig ist ;-)

Code: Alles auswählen

; This example converts a mySQL-Database-Dump into
; a SQLite3-Database

Procedure mySQL_2_SQLite(dbHandle.l, mySQLDatabaseDump.s)
  
  FF = ReadFile(#PB_Any, mySQLDatabaseDump)
  
  If FF
    
    While Eof(FF) = 0
      
      sLine.s = ReadString()
      
      If FindString(sLine, "CREATE TABLE", 1)
        
        sQuery.s = sLine
        
        Repeat
          
          sLine.s = ReadString()
          
          If sLine = "" : Break : EndIf
          
          If FindString(sLine, "PRIMARY", 1) = 0 And FindString(sLine, "KEY", 1) = 0 And Left(sLine, 1) <> ")"
            sLine = Trim(sLine)
            pos = FindString(sLine, ")", 1)
            If pos
              sQuery + Left(sLine, pos) + ","
            Else
              sQuery + sLine
            EndIf
          EndIf
          
        ForEver
        
        sQuery = Left(sQuery,Len(sQuery)-1) + ")"
        
        Debug sQuery
        
        SQLite3_Execute(sQuery, dbHandle)
        
        If SQLite3_GetLastMessage() <> "OK"
          Debug ""
          Debug SQLite3_GetLastMessage()
          CallDebugger
        EndIf
        
        TextFields = #False
        
        If FindString(sQuery, "char", 1) Or FindString(sQuery, "text", 1)
          TextFields = #True
        EndIf
        
        For lCounter = 0 To 3
          sLine.s = ReadString()
        Next  
        
        SQLite3_Execute("Begin Transaction;", dbHandle)
        
        Repeat
          
          sLine.s = ReadString()
          
          If sLine = "" : Break : EndIf
          
          If TextFields
            
            ; Some Chars have to be converted before
            ; inserting into the SQLite-Database
            
            sLine = ReplaceString(sLine, "\\'", "'")
            sLine = ReplaceString(sLine, "\'", Chr(34))
            sLine = ReplaceString(sLine, "\" + Chr(34), Chr(34))
            
          EndIf
          
          SQLite3_Execute(sLine, dbHandle)
          
          If SQLite3_GetLastMessage() <> "OK"
            
            ; If an error occurred -> Show actual line
            
            Debug ""
            Debug sLine
            Debug SQLite3_GetLastMessage()
            CallDebugger
            
          EndIf
          
        ForEver
        
        SQLite3_Execute("Commit;", dbHandle)
        
      EndIf
      
    Wend  
    
    CloseFile(FF)
    
  EndIf
  
EndProcedure
 
SQLite3_Init() 

; Please customize the following two pathes
; before running the code!

mySQLDatabaseDump.s = "d:\data\pb-board\german"
SQLite3Database.s   = "d:\data\pb-board\german.db"

dbHandle = SQLite3_CreateDatabase(SQLite3Database, #True)

If dbHandle
  
  ; Some of the textlines are larger than 64.000 Chars
  ; Please customize, if your textlines are larger then 100.000 Chars:
  DG_SetPBStringSize(100000)
  
  z1 = ElapsedMilliseconds()
  
  mySQL_2_SQLite(dbHandle, mySQLDatabaseDump)
  
  SQLite3_CloseDatabase(dbHandle)
  
  SQLite3_End()
  
  z2 = ElapsedMilliseconds()
  
  MessageRequester("mySQL_2_SQLite", "Ready" + #CRLF$ + "Needed time: " + Str((z2-z1)/1000) + " Seconds")
  
Else
  
  MessageRequester("mySQL_2_SQLite", "Couldn't create the SQLite3-Database.")
  
EndIf
Ich habe den Code ebenfalls im webPM eingeloggt.

URL = http://cvs.pureforge.net/pbosl/
User = purebasic
Passwort = purebasic

Nach Einloggen findet man den aktuellen Source hier:

Examples: /PBOSL_SQLite3/PBOSL_mySQL_2_SQLite.pb

Grüße ... Kiffi
a²+b²=mc²
Antworten