Moteur pur-Python

Le moteur pur-Python consiste en un module unique, pydblite.py. Pour l’utiliser, importer la classe Base depuis ce module:

from pydblite.pydblite import Base

Create or open a database

créer une instance de base de données, en donnant un nom de fichier comme argument

db = Base('test.pdl')

Pour une nouvelle base, définissez les noms des champs

db.create('name', 'age', 'size')

Vous n’avez pas à définir le type des champs. PyDbLite accepte toute valeur qui peut être sérialisée par le module cPickle

  • strings
  • Unicode strings
  • integers
  • floats
  • dates and datetimes (instances of the date and datetime classes in the datetime module)
  • user-defined classes

db.exists() indique si la base existe exists.

si la base existe déjà, pour l’ouvrir

if db.exists():
    db.open()

on peut passer un paramètre “mode” à la méthode :func:`create() <pydblite.pydblite._Base.create>`pour indiquer ce qu’il faut faire si la base existe déjà sur le disque

  • mode = “open” : db.create('name', 'age', 'size', mode="open") ouvre la base en ignorant la définition des champs

  • mode = “override” : db.create('name', 'age', 'size', mode="override") efface la base existante et en crée une nouvelle avec les définitions de champs

  • si le mode n’est pas précisé et que la base existe déjà, une exception IOError est déclenchée

Insert, update, delete a record

insert a new record

par mots-clés

db.insert(name='homer', age=23, size=1.84)

Si certains champs manquent, ils sont initialisés à la valeur None

par arguments positionnels

db.insert('homer', 23, 1.84)

Les arguments doivent être fournis dans le même ordre que dans la méthode create()

pour sauvegarder les changements sur le disque

db.commit()

Si vous ne confirmez pas les changements, les opérations d’insertion, de suppression et de mise à jour ne seront pas sauvegardés sur le disque

pour supprimer un enregistrement

db.delete(record)

ou, si vous connaissez l’identifiant

del db[rec_id]

pour supprimer une liste d’enregistrements

db.delete(list_of_records)

liste_d_enregistrements peut être n’importe quel itérable (liste, tuple, set, etc) qui produit des enregistrements

to update a record

db.update(record, age=24)
  • En plus des champs passés à la méthode create(), un champ interne appelé __id__ est ajouté. C’est un entier, unique et inchangé pour chaque enregistrement, il peut donc être utilisé comme identifiant pour l’enregistrement

  • un autre champ interne appelé __version__ est également géré par le moteur de base de données. Il s’agit d’un entier qui est initialisé à 0 quand l’enregistrement est créé, et incrémenté de 1 à chaque fois que l’enregistrement est mis à jour. Ceci sert pour la détection des accès concurrents, par exemple dans une application web dans laquelle deux utilisateurs veulent mettre à jour le même enregistrement en même temps.

Sélection

L’instance de Base est un itérateur sur les enregistrements

Pour itérer sur tous les enregistrements

for r in db:
    do_something_with(r)

Accès direct

On peut accéder directement à un enregistrement par son identifiant

record = db[rec_id]

retourne l’enregistrement tel que record['__id__'] == rec_id

Sélection simples

  • db(key1=val1, key2=val2) renvoie la liste des enregistrements dont les clés ont les valeurs données

  • db(key) >= val retourne un itérateur sur tous les enregistrements pour lesquels la val du champ cle est supérieure ou égale à val.

Exemple

for rec in (db("age") > 30):
     print rec["name"]

ces “comparaisons riches” peuvent être combinées avec des & (et) et des | (ou)

for rec in (db("age") > 30) & (db("country") == "France"):
    print rec["name"]

Listes en intension

la sélection d’enregistrements peut utiliser la syntaxe des listes en intension (“list comprehensions”) de Python

recs = [r for r in db if 30 > r['age'] >= 18 and r['size'] < 2]

retourne les enregistrements de la base pour lesquels l’âge est compris entre 18 et 30 ans, et la taille est inférieure à 2 mètres. L’enregistrement est un dictionnaire, où la clé est le nom de champ et la valeur est la valeur de ce champ

la syntaxe des générateurs d’expression Python peut aussi être utilisée

for r in (r for r in db if r['name'] in ('homer', 'marge')):
    do_something_with(r)

itère sur les enregistrements dont le nom est ‘homer’ ou ‘marge’

Index

Pour accélérer les sélections, un index peut être créé sur un champ create_index('field')

db.create_index('age')

Quand un index est créé, l’instance de la base de données a un attribut (ici _age : noter le signe de soulignement initial, pour éviter les conflits de noms avec des noms internes). Cet attribut est un objet de type dictionnaire, où les clés sont les valeurs prises par le champ, et les valeurs sont les enregistrements dont le champ a la même valeur que la clé :

records = db._age[23] retourne la liste des enregistrements avec age == 23

Si aucun enregistrement n’a cette valeur, la recherche par cette valeur retourne une liste vide

L’index supporte l’itération sur les valeurs du champ, et la méthode keys() retourne toutes les valeurs existantes pour le champ

Autres attributs et méthodes

  • add_field('new_field'[,default=v]): ajoute un nouveau champ à la base de données. default est une valeur par défaut ; elle vaut None si elle n’est pas précisée

  • drop_field('field'): supprime un champ existant

  • db.path: the chemin de la base de données dans le système de fichiers

  • db.name: le nom de la base de données : le nom de base du chemin (sans le répertoire), auquel on a enlevé l’extension

  • db.fields: la liste des champs (n’inclut pas les champs internes __id__ et __version__)

  • len(db) : nombre d’enregistrements dans la base