Sqlite pour un gros nul

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Message par flaith »

et l'exemple [test_sqlite.pb] fonctionne pour Linux et Windows :

Code : Tout sélectionner

_SEP_.s = "/"
LIB_TO_LOAD.s = "libsqlite3.so.0"

CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux
    XIncludeFile "include/sqlite3.pbi"
    _SEP_ = "/"
    LIB_TO_LOAD = "libsqlite3.so.0"
  CompilerCase #PB_OS_Windows
    XIncludeFile "include\sqlite3.pbi"
    _SEP_ = "\"
    LIB_TO_LOAD = "sqlite3.dll"
CompilerEndSelect

sDB.s = "DB"+_SEP_+"sample.db"

If SQLite3_InitLib(LIB_TO_LOAD) = #False
  MessageRequester("SQLite3-Demo", SQLite3_GetLastMessage())
  End
EndIf

Debug "Lib version        :"+SQLite3_GetLibVersion()
Debug "Lib version Number :"+Str(SQLite3_GetLibVersionNumber())

; Création d'une base, si elle existe ddéja on ecrase (boolOverwrite = #true)
dbHandle = SQLite3_CreateDatabase(sDB, #True)

If dbHandle = 0
  MessageRequester("SQLite3-Demo", SQLite3_GetLastMessage())
  End
EndIf

; Table test pour les données à remplir

sSQL.s = "Create Table TempData (fld0, fld1, fld2)"
SQLite3_Execute(sSQL, dbHandle)

; Création d'une table temporaire, détruite lors de la fermeture de la base
sSQL.s = "CREATE TEMP TABLE tbl1 (f1 varchar(30) primary key, f2 text, f3 real)"
SQLite3_Execute(sSQL, dbHandle)

temps1= ElapsedMilliseconds()

; Transaction permettant d'accélérer l'insertion multiple de données!
sSQL = "BEGIN TRANSACTION"
SQLite3_Execute(sSQL, dbHandle)

For intI = 0 To 999
  sSQL.s = "Insert Into TempData (fld0, fld1, fld2) Values ('value_0_" + Str(intI) + "', 'value_1_" + Str(intI) + "', 'value_2_" + Str(intI) + "')"
  SQLite3_Execute(sSQL, dbHandle)
Next intI

SQLite3_Execute("insert into tbl1 values('KEY000', 'hello!', 10)", dbHandle)
SQLite3_Execute("insert into tbl1 values('KEY001', 'goodbye', 25.20)", dbHandle)

; Les transactions
sSQL = "COMMIT"
SQLite3_Execute(sSQL, dbHandle)

temps2= ElapsedMilliseconds()

Define.s_Recordset RS ; definir le Recordset-'Object'

; Détermination du nombre d'enregistrement
If SQLite3_GetRecordset("Select Count(*) As Nb_Enr From TempData", dbHandle, @RS )
  
  If RS\Handle
    If SQLite3_GetRecordsetValueByName("Nb_Enr", @RS)
      Debug RS\sValue + " enregistrements insérés en " + Str(temps2-temps1) + " millisecondes."
    Else
      MessageRequester("SQLite3-Demo", SQLite3_GetLastMessage())
    EndIf
  EndIf

Else
  MessageRequester("SQLite3-Demo", SQLite3_GetLastMessage())
EndIf

If SQLite3_GetRecordset("Select * From TempData Limit 5", dbHandle, @RS)
  
  Debug "Valeur de l'index du champ 'fld2': " + Str( SQLite3_GetFieldIndexByName("fld2", @RS) )
  
  If RS\Handle 
    
    ; Recherche et affichage de tous les enregistrements (suivant la limite)
    While RS\EOF = 0
      If SQLite3_GetRecordsetValueByName("fld0", @RS)
        Debug RS\sValue
      Else
        MessageRequester("", SQLite3_GetLastMessage())
      EndIf
      SQLite3_RecordsetMoveNext(@RS)
    Wend
    
    Debug "----------------------"
    
    ; La même chose mais à partir de la fin
    While RS\BOF = 0
      If SQLite3_GetRecordsetValueByName("fld0", @RS)
        Debug RS\sValue
      Else
        MessageRequester("", SQLite3_GetLastMessage())
      EndIf
      SQLite3_RecordsetMovePrevious(@RS)
    Wend
    
    Debug "++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
    
    ; Aller au 1er enregistrement
    SQLite3_RecordsetMoveFirst(@RS)
    
    If SQLite3_GetRecordsetValueByName("fld0", @RS)
      Debug "Zone de contenu du champ 'fld0' du premier enregistrement (ByName):"
      Debug RS\sValue
    Else
      MessageRequester("SQLite3-Demo", SQLite3_GetLastMessage())
    EndIf
    
    If SQLite3_GetRecordsetValueByIndex(0, @RS)
      Debug "Zone de contenu du champ 'fld0' du premier enregistrement (ByIndex):"
      Debug RS\sValue
    Else
      MessageRequester("SQLite3-Demo", SQLite3_GetLastMessage())
    EndIf
    
    Debug "++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
    
    ; Aller au dernier enregistrement
    SQLite3_RecordsetMoveLast(@RS)
    If SQLite3_GetRecordsetValueByName("fld0", @RS)
      Debug "Zone de contenu du champ 'fld0' du dernier enregistrement:"
      Debug RS\sValue
    Else
      MessageRequester("SQLite3-Demo", SQLite3_GetLastMessage())
    EndIf
    
    SQLite3_ReleaseRecordset(@RS)

  Else
    MessageRequester("SQLite3-Demo", SQLite3_GetLastMessage())
  EndIf
   
Else
  MessageRequester("SQLite3-Demo", SQLite3_GetLastMessage())
EndIf

Debug "++++++++++++++++++++++++++++++++++++++++++++++++++++++++"

Define.s_Recordset RS2

If SQLite3_GetRecordset("Select Count(*) As Nb_Enr From tbl1", dbHandle, @RS2)
  SQLite3_GetRecordsetValueByName("Nb_Enr", @RS2)

  Debug "Nombre d'enregistrement pour la table temporaire 'tbl1' = " + RS2\sValue

  ; Recherche dans la table tbl1 quand une partie du champ 'f2' contient "oo"
  ; (notez bien l'importance des % avant et après la partie du mot à rechercher) :
  SQLite3_GetRecordset("Select * from tbl1 where f2 like '%oo%'", dbHandle, @RS2)

  If RS2\Handle
    While RS2\EOF = 0
      SQLite3_GetRecordsetValueByName("f1", @RS2)
      a$ = RS2\sValue
      SQLite3_GetRecordsetValueByName("f2", @RS2)
      b$ = RS2\sValue
      SQLite3_GetRecordsetValueByName("f3", @RS2)
      c$ = RS2\sValue
      Debug a$ + " - "+ b$ + " - " + c$
      SQLite3_RecordsetMoveNext(@RS2)
    Wend
  EndIf
Else
  MessageRequester("SQLite3-Demo", SQLite3_GetLastMessage())
EndIf

SQLite3_CloseDatabase(dbHandle)               ; La table tbl1 n'existe plus

End
Dernière modification par flaith le mar. 24/mars/2009 18:05, modifié 1 fois.
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Message par Kwai chang caine »

Un peu mon neveu que ça interesse au moins un :D

Les examples de SQLITE sont toujours les bienvenus
Merci de ton travail et de ton partage 8)
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Message par flaith »

Kwai chang caine a écrit :Un peu mon neveu que ça interesse au moins un :D

Les examples de SQLITE sont toujours les bienvenus
Merci de ton travail et de ton partage 8)
Merci KCC :D
*** info *** Mise à jour de l'exemple et de l'include pour qu'ils soient compatibles avec la dernière version de la DLL ou de la lib SO
didier69
Messages : 61
Inscription : mer. 30/avr./2008 12:50
Localisation : Villeurbanne (Lyon)

Message par didier69 »

Bonjour,

je ne comprends pas bien. SQLite est disponible directement avec PB. A quoi sert cette librairie supplémentaire ?

Cordialement.
pb 5.31
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

Message par GeBonet »

Bonjour,

A quoi ça sert : A gérer une base de donnée (des fichiers)

Mais pas seulement... : C'est aussi sur base d'une "méthode", qui est largement utilisé par pas mal d'autre langage...
Conséquences : être compatible dans la forme et l'usage...

Autrement dit : Qui à fait du SQL ou SQlite sur un système peut le faire avec d'autre langages et inversément.

Ceci dis : Je ne suis pas un "fan", il y a déjà trop de versions... :?
Et j'aime mieux et de loin gérer mes fichiers sans ça ! :lol:

Mais il faut rendre à césar.... C'est quand même beaucoup utilisé. :wink:

Et puisqu'on en parle... Dommage que l'accès direct tel qu'il était
organisé sous les 'ex" QB et autres Power etc... me manque !!!
Bon il a d'autres possibilité... Mais c'était un coup de coeur... :cry:
Bonne journée !
didier69
Messages : 61
Inscription : mer. 30/avr./2008 12:50
Localisation : Villeurbanne (Lyon)

Message par didier69 »

Je sais à quoi sert sqlite je me suis fait une petite application avec. Je me demandais à quoi sert cette librairie par rapport aux fonctions fournies par PB :).
pb 5.31
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

Message par GeBonet »

didier69 a écrit :Je sais à quoi sert sqlite je me suis fait une petite application avec. Je me demandais à quoi sert cette librairie par rapport aux fonctions fournies par PB :).
Ben voilà, je suis content que tu sache...
Mais je dis aussi :
GeBonet a écrit :Mais pas seulement... : C'est aussi sur base d'une "méthode", qui est largement utilisé par pas mal d'autre langage...
Conséquences : être compatible dans la forme et l'usage...
Autrement dit : Qui à fait du SQL ou SQlite sur un système peut le faire avec d'autre langages et inversément.
C'est donc pour apporter un plus que de base PB n'a pas sous cette forme. Avant... Il fallait appeler la Lib pour s'en servir...
Maintenant elle est incluse.

Et si tu l'as utilisé, tu dois bien te rendre compte que c'est pas tout à fait la même manière de gérer les fichiers... ??? Non ?? :?:

A++ :lol: :lol:
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

GeBonet a écrit : Et puisqu'on en parle... Dommage que l'accès direct tel qu'il était
organisé sous les 'ex" QB et autres Power etc... me manque !!!
l'usage de la fonction "FileSeek(#Fichier, Position.q)
", peut etre une forme d'accés direct, non ? 8O

ya longtemps que j'ai plus utilisé "l'accés direct" , vais replonger dans les bouquins, pour me remémorrer le truc :)

[Ré edit]

oui c'est bien ce qu'il me semblais la fonction FileSeek(#Fichier, Position.q)
fait office d'accés direct !!

il suffit de lui donner l'offset au parametre "Position" :)

ensuite on ecrit ou lit !!

bien sur l'ideal est de creer un fichier a l'avance avec des "champs"
ces champs etant délimité par une valeur précise !!

d'ailleurs ce peut etre une ligne ascii avec le caractere de fin de ligne
ce caractere fesant office de délimiteur :)

donc un simple writestringN(space(255)) suffirai a creer un champ :)
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

Message par GeBonet »

Dobro a écrit :l'usage de la fonction "FileSeek(#Fichier, Position.q)
", peut etre une forme d'accés direct, non ? 8O
ya longtemps que j'ai plus utilisé "l'accés direct" , vais replonger dans les bouquins, pour me remémorrer le truc :)
Oui, c'est de l'accès direct...
Et en quelque sorte plus "direct" puisqu'il est au byte près...
Soit comme le faisait QB en mode Binaire...
Le mode "direct" dont je parle est celui qui était lié à un Fichier ouvert comme tel avec une taille de Buffer bien définis...
Il lisait/ecrivait un bloc de taille "X". Et l'accès direct se fait à l'enregistrement (directement au bloc)
Et le "Buffer" tu le découpais "dynamiquement"... Ou de manière fixe comme avec une Structure de PB (via "Field").
Personnellement j'utilisais toujours le dynamique tant pour la description que pour les données.
Beaucoup plus souple et complètement maitre puisque je pouvais avec des variable déclarer des structures.
Avec PB aussi, mais plus compliqué, il faut créer le système... Du moins au stade de mes connaissance de PB :(
(Sauf si on utilise SQlite justement... qui viens simplifié tout (tiens encore une raison :roll:))

En fait dans PB... On ouvre un fichier puis on lis ou écrit en séquentiel ou on se déplace n'importe ou grâce à FileSeek(#Fichier, Position.q)
et la on lit/écrit ce que l'on veux... Même des blocs mémoire. Mais pour cela il faut convenablement gérer ses blocs :lol: (Ce qu'était les "Buffers" de QB..).
Ce qui n'empêchais d'ailleurs pas de lire en séquentiel un binaire ou un direct... Ce que équivalait à FilleSeek était simplement Seek...
Par contre pas de "Field" en PB !
Bref, il suffit de s'adapter... :lol: :lol: :lol: :lol:
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

Message par GeBonet »

@Dobro (c'est comme ça qu'on fait ? :? )
Je vais en ajouter une couche... Justement au moment ou j'allais 'arrêter.. Je travaillais sur une gestion de fichier avec des enregistrement à longueur variable...
@Pour tous
Les "Buffers" de longueurs fixes provoquaient trop de perte de place à mon gout... (et c'est encore le cas).
Et j'ai réalisé un prototype à l'époque. Et il y a quelque temps (maintenant) que je viens de reprendre le projet.
Car j'ai justement vu directement les absences de "Buffer fixe" de PB et en même temps le FileSeek la soeur de mon Seek de l'époque à la
base de la gestion de fichier à "enregistrement de longueur variable".

En fait ce qui me gêne c'est justement le fait de ne pas avoir la possibilité d'utiliser des variables pour définir des "structures".
La solution... Se passer de Structure et de paramétrer tout ou le nécessaire ? Je suis sur une piste !
Dans l'entretemps... Nous avons gagné de la mémoire à en revendre ce qui modifie radicalement la manière de traiter
les fichiers au point de pouvoir traiter des fichiers entier en mémoire (pas forcément conseillé mais possible).
Et il y a PB... Qui pour moi, reste encore une grande découverte à faire... :roll: Et détient peut-être la solution... :roll:
Bon, au travaille ! :lol:
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Message par flaith »

En créant un fichier d'index (la belle époque du fichier indexé) reprenant l'index (qui représente l'enregistrement que l'on recherche et sa position dans le fichier des données : la valeur du FileSeek en fait), tu peux ainsi travailler avec des longueurs d'enregistrements variables mais limité par la taille du FileSeek, surtout si tes enregistrements sont longs.

Je me comprends mais suis-je clair? :wink:
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

Message par GeBonet »

Tout à fait... Je connais très bien la technique, les Indexés séquentiels qui sont effectivement resté très longtemps "au pouvoirs"
et le sont encore... Btrieve, Wbtrieve.dll de Novell pour ne cité que lui, ou plus loin encore l'ISAM 80 (année 80) :lol: .
Aujourd'hui on parle de dictionnaire pour l'Index... Et le fichier des données.

J'en ai utilisé et pour finir développé un qui m'a servis pendant 15 ans jusqu'à ce que je m'arrête. Et c'est justement cela que j'étais en train de remplacer par un système de gestion de fichier à enregistrement de longueur variable n'étant limité par rien (à part la capacité du support).

Souvent avec les indexés séquentiels on travaillais avec les index (clefs et pointeurs) et les fichiers direct géré par une bitmap en début de fichier.
La bitmap chargé en mémoire était une carte binaire ou les 0 pointaient les place vacantes et les 1 occupées (initialisé en première utilisation de programme.
D'ou la séquence on repère la place dans la MAP, on l'écrit dans le fichier puis on place dans l'index la ou les clef avec le pointeur de la place qu'on viens de trouver... Et inversement pour retrouver...

Et il peut d'ailleurs être tout à fait indépendant du fichier de donnée...

- Les enregistrements à longueur variables posent le GROS problème de l'effacement des enregistrements... En effet il n'y a aucune place les mêmes et le nouvel enregistrement ne pourra pas forcément s'incrire à la place du dernier effacé. D'où la nécessité de réorganisation fréquentes.
Ce qui posait de gros problèmes... Aujourd'hui cela devient plus relatif, vu que l'on dispose de vraiment beaucoup de mémoire... Et surtout des possibilités de traitement "en parallèle"... Soit quand nous ne faisons rien...
L'autre problème c'est la sécurité des données, et la nécessite de disposer d'un système de reconstitution des enchainements voir des index en cas de "crash", soit rupture de continuité dans les chainages et forcément de la bitmap.

Comme PB n'a pas d'autres système que le séquentiel et le "binaire", soit accès direct au byte près... (à par le SQlite qui est loin d'être rien et pourrait servir d'index d'ailleurs)... Et aussi une série d'instructions, pointeurs pour gérer et accéder facilement à la mémoire, il est très bien pour construire un nouveau système de gestion de fichier...

C'est aussi ce sur quoi je travaille en même temps que mon apprentissage du PB... Dès que cela sera un tant soit peu opérationnel, je le mettrais à disposition... L'ancien était déjà prometteur... Celui ci devrait-être mieux :roll: Enfin, j'espère...
Répondre