English

## 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 import Base ### Créer ou ouvrir une base de données 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('nom','age','taille') Vous n'avez pas à définir le type des champs. PyDbLite accepte toute valeur qui peut être sérialisée par le module `cPickle` : des chaînes de caractères, des chaînes Unicode, des entiers, réels, dates et dates-heures (instances des classes `date` et `datetime` dans le module `datetime`), des instances de classes définies par l'utilisateur, etc db.exists() indique si la base existe si la base existe déjà, pour l'ouvrir : db.open() on peut passer un paramètre "mode" à la méthode `create()`, pour indiquer ce qu'il faut faire si la base existe déjà sur le disque mode = "open" : db.create('nom','age','taille',mode="open") ouvre la base en ignorant la définition des champs mode = "override" : db.create('nom','age','taille',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 ### Insertion, mise à jour, suppression d'enregistrements insertion d'un nouvel enregistrement par mots-clés : db.insert(nom='homer',age=23,taille=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 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 pour mettre à jour un enregistrement : db.update(record,age=24) 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(liste_d_enregistrements) `liste_d_enregistrements` peut être n'importe quel itérable (liste, tuple, set, etc) qui produit des enregistrements ### Sélection L'instance de `Base` est un itérateur sur les enregistrements. Pour itérer sur tous les enregistrements : for r in db: fais_qqch_avec(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(cle1=val1,cle2=val2) renvoie la liste des enregistrements dont les clés ont les valeurs données db(cle) >= valeur retourne un itérateur sur tous les enregistrements pour lesquels la valeur du champ `cle` est supérieure ou égale à `valeur`. Exemple : for rec in (db("age")>30): print rec["nom"] ces "comparaisons riches" peuvent être combinées avec des & (et) et des | (ou) : for rec in (db("age")>30) & (db("pays") == "France"): print rec["nom"] #### 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['taille'] < 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['nom'] in ('homer','marge') ): faire_qqch_avec(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 : 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 db.add_field('nouveau_champ'[,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 db.drop_field('nom') : 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 len(db) : nombre d'enregistrements dans la base db.fields : la liste des champs (n'inclut pas les champs internes `__id__` et `__version__`)