Créer et utiliser sqlite3

Bonjour à  tous



Je débute sous cocoa et j'aimerais utiliser sqlite pour la gestion de base de données. J'ai trouvé un tuto qui me semblait très intéressant : TUTO – Comment utiliser SQLite avec Objective-C " " Bad Monkey Bad Monkey mais j'ai quelques problèmes malgré tout, et ce, dès le début.



Je cherche donc à  créer une base et donc la créer sur mon disque. Voici le code proposé :


<br />
//<br />
//  SQLmanager.m<br />
//  SQlite_Tuto<br />
<br />
//<br />
#import &quot;SQLmanager.h&quot;<br />
#import &lt;sqlite3.h&gt;<br />
<br />
@implementation SQLmanager<br />
-(id) initDataBase<br />
{<br />
if(self = [super init])<br />
{<br />
  //DataBse name<br />
  databaseName = @&quot;abdname.sqlite&quot;;<br />
<br />
  //Getting DB path<br />
  NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask , YES);<br />
  NSLog(@&quot;  documentPaths = %@&quot;,documentPaths);<br />
  NSString * documentDir = [documentPaths objectAtIndex:0];<br />
  NSLog(@&quot;  documentDir = %@&quot;,documentDir);<br />
  databasePath = [documentDir stringByAppendingPathComponent:databaseName];<br />
  NSLog(@&quot;  databasePath = %@&quot;,databasePath);<br />
<br />
  [self checkAndCreateDatabaseWithOverwrite:YES];<br />
}<br />
return self;<br />
}<br />
//Validation et creation de la base de donnees<br />
-(void) checkAndCreateDatabaseWithOverwrite:(BOOL)overwriteDB<br />
{<br />
NSLog(@&quot;  passé &quot;);<br />
	// BOOL qui servira de verification de l&#39;existance de la BD<br />
	BOOL success;<br />
<br />
	// Objet pour faire des operations sur le systeme de fichiers<br />
	NSFileManager *fileManager = [NSFileManager defaultManager];<br />
<br />
	// Verifier de la BD dans databasePath<br />
	success = [fileManager fileExistsAtPath:databasePath];<br />
<br />
	// Retourner si la BD existe et que le BOOL overwriteDB n&#39;est pas à  oui<br />
	if (success &amp;&amp; &#33;overwriteDB)<br />
{<br />
  NSLog(@&quot;  success = %i  et overwriteDB : %i&quot;,success, overwriteDB);<br />
		return;<br />
	}<br />
<br />
	// Chaines de caracteres avec le chemin de la BD dans l&#39;app Bundle<br />
	NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];<br />
NSLog(@&quot;  databasePathFromApp = %@ &quot;,databasePathFromApp);<br />
	// Copier la BD de l&#39;app Bundle vers le repertoire de documents<br />
	id error =  [fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];<br />
NSLog(@&quot;  error = %@ &quot;,error);<br />
}<br />
@end<br />




Ceci étant, rien ne s'inscrit sur mon disque.

En suivant les NSLog, j'ai bien le nom de ma base, l'endroit où je veux la stocker mais elle n'est pas enregistrée.



Quelqu'un peut il m'aider sur ce sujet ?

Merci d'avance

Réponses

  • mpergandmpergand Membre
    juillet 2012 modifié #2
    Salut,



    Bon, je vois aucune instruction de création d'une BD dans ton code !

    Tu essayes de copier un fichier du bundle de ton app dans le dossier document, mais ce fichier il sort d'où ?



    Voici mon code pour la création d'un BD:


    <br />
    @implementation SQLiteManager<br />
    <br />
    +(int) createDBAtPath:(NSString*)filePath encoding:(int)encoding schema:(NSString*)schema<br />
    {<br />
    sqlite3* sql=NULL;<br />
    char*  errMsg=NULL;<br />
    int err;<br />
    <br />
    if(encoding==SQLiteEncoding_UTF8)<br />
      err=sqlite3_open([filePath fileSystemRepresentation],&amp;sql);<br />
    else<br />
      err=sqlite3_open16([filePath fileSystemRepresentation],&amp;sql);<br />
    <br />
    errMsg=(char*)sqlite3_errmsg(sql);<br />
      <br />
    if( (err==SQLITE_OK)&amp;&amp;(schema&#33;=nil) )<br />
      {<br />
      err=sqlite3_exec(   sql,	 // An open database	<br />
    	   [schema UTF8String], // SQL to be executed  <br />
    	   NULL,	 // Callback function  <br />
    	   NULL,	 // 1st argument to callback function<br />
    	   &amp;errMsg	 // Error msg written here  <br />
    	  );<br />
      }<br />
    <br />
    if(err&#33;=SQLITE_OK)<br />
      {<br />
      NSLog(@&quot;[SQLite] error:%d %s&quot;,err,errMsg);<br />
      sqlite3_free(errMsg);<br />
      }<br />
    <br />
    sqlite3_close(sql);<br />
    <br />
    return err;<br />
    }<br />
    




    Le shema est un fichier de description des différents champs de la base, par ex:




    CREATE TABLE auteur ( nom TEXT PRIMARY KEY, date_naissance DATE, commentaire TEXT, image_auteur BLOB);

    ....



    CREATE INDEX ind_auteur ON livre (id_auteur);

    ....




    Ce fichier n'est pas indispensable, tu peux créer ces champs par code dans ton prog.

    (si mes souvenirs sont bons, car ça fait un moment que je n'ai pas touché à  sqlite ...)
  • Merci mpergand. Je regarde ça et je te tiens au courant
  • Bonjour Mgergand.

    Bon je n'ai pas compris grand à  ton code. Cependant, ta 2e citation me parle plus car cela ressemble plus à  Qt.

    Ceci étant, n'y aurait-il pas l'équivalent de Qt justement pour le code suivant, avec ce principe de requète :


    <br />
    		int verif = 0;<br />
    		QStringList table = db.tables();<br />
    		for (int i = 0; i &lt; table.count();i++)<br />
    		{<br />
    			if(table.at(i) == nom)<br />
    			{<br />
    				QMessageBox::critical(0, &quot;Stock&quot;,&quot;Ce nom existe déjà  &#33;&quot;);<br />
    				db.close();<br />
    				verif = 1;<br />
    				return;<br />
    			}<br />
    		}<br />
    		if (verif == 0)<br />
    		{<br />
    			QSqlQuery requeteCreate;<br />
    			QString requete;<br />
    			requete = &quot;CREATE TABLE &quot;;<br />
    			requete += nom;<br />
    			requete += &quot; (id INTEGER PRIMARY KEY, ref VARCHAR(30), qte INTEGER)&quot;;<br />
    			requeteCreate.exec(requete);<br />
    			db.commit();<br />
    			db.close();<br />
    		}<br />
    




    merci d'avance
  • Salut Mpergand

    Je viens de tester ta proposition mais dans ton code :


    <br />
    if(encoding==SQLiteEncoding_UTF8)<br />
      err=sqlite3_open([filePath fileSystemRepresentation],&amp;sql);<br />
    else<br />
      err=sqlite3_open16([filePath fileSystemRepresentation],&amp;sql);<br />
    errMsg=(char*)sqlite3_errmsg(sql);<br />
    




    j'ai le warning suivant : Local declaration of 'sql' hides instance variable



    Qu'est ce que ça veut dire ?



    Merci d'avance
  • mpergandmpergand Membre
    juillet 2012 modifié #6
    'Fred20' a écrit:


    j'ai le warning suivant : Local declaration of 'sql' hides instance variable



    Qu'est ce que ça veut dire ?



    Merci d'avance




    Exactement ce qui est dit: tu as une variable d'instance nommée sql !



    Tu remarqueras que ma méthode createDBAtPath: est une méthode de classe (signe +) ...




    Ceci étant, n'y aurait-il pas l'équivalent de Qt justement pour le code suivant, avec ce principe de requète :




    Nan, c'est du c++.


    <br />
    -(int) execute:(NSString*) sqlStr<br />
    {<br />
    char* errMsg=NULL;<br />
    const char* cmd=[self cString:sqlStr];  // conversion en utf8 (voir mon commentaire plus bas)<br />
    <br />
    int err=sqlite3_exec(  pSQL,	// An open database	<br />
    	   cmd,	// SQL to be executed  <br />
    		 NULL,	// Callback function  <br />
    		 NULL,	// 1st argument to callback function<br />
    	   &amp;errMsg	// Error msg written here  <br />
    	  );<br />
    	  <br />
    <br />
    if(err&#33;=SQLITE_OK)<br />
      {<br />
      // erreur<br />
      [self setLastErr:err msg:errMsg];<br />
      sqlite3_free(errMsg);<br />
      }<br />
    <br />
    return err;<br />
    




    Pour simplifier on va supposer que tu inities la base en UTF8.

    Le problème est qu'il faut convertir les chaines NSString en UTF8 et vice versa.

    NSString -> char* utiliser :

    - (const char *)UTF8String



    char* -> NSString utiliser :

    + (id)stringWithCString:(const char *)cString encoding:(NSStringEncoding)enc

    avec encoding= NSUTF8StringEncoding





    Dans mon code je récupère la dernière erreur (setLastError) ce n'est pas une obligation, à  toi de l'implémenter si tu le désires.
  • Merci mpergand. Je regarde et je te tiens au courant
  • Ok, je viens de regarder ta réponse.



    Plusieurs questions même si j'ai compris la globalité (j'ai réussit à  l'adapter à  mon projet !) :

    - pourquoi tu dois passer par une méthode de classe (+) pour que ça marche sans warning ?

    - dans ton 2e exemple, d'où viens pSQL ?



    Merci d'avance
  • mpergandmpergand Membre
    juillet 2012 modifié #9
    pSQL est la variable qui contient la BD ouverte dans mon prog par:

    err=sqlite3_open([filePath fileSystemRepresentation],&pSQL);




    - pourquoi tu dois passer par une méthode de classe (+) pour que ça marche sans warning ?




    Les variables d'instance sont inaccessibles dans une méthode de classe.
  • 'mpergand' a écrit:


    pSQL est la variable qui contient la BD ouverte dans mon prog par:

    err=sqlite3_open([filePath fileSystemRepresentation],&pSQL);









    Les variables d'instance sont inaccessibles dans une méthode de classe.




    justement, dans ton 2e exemple, tu n'ouvres pas de BD. Je suppose donc qu'il faille l'inscrire au début de ton exemple dans la méthode execute ?
  • mpergandmpergand Membre
    juillet 2012 modifié #11
    Ben ouais, c'est mieux avant de faire un execute image/tongue.png' class='bbc_emoticon' alt=':P' />



    Mais t'as lu un peu la doc ?

    C'est tout marqué dedans ...



    http://www.sqlite.org/quickstart.html
  • oui oui, mais autant je peux demander une bière dans un pub, autant lire cette doc me pose problème. Je ne suis pas assez pointu en anglais pour la comprendre afin d'apprendre correctement image/crybaby.gif' class='bbc_emoticon' alt=' :'( ' />
  • mpergandmpergand Membre
    juillet 2012 modifié #13
    Si tu ne maitrises pas l'anglais technique, tu vas au devant d'énormes difficultés, Apple ne fournit sa doc qu'en anglais ...

    Force toi (moi aussi j'en suis passé par là ) c'est l'affaire de quelque mois.



    En ce qui concerne sqlite, ça se programme en C, donc tout exemple en C fonctionnera, la seule différence c'est qu'il faut convertir les chaines char* -> NSString et NSString -> char*.
  • merci de ton encouragement. Ceci étant que me conseilles tu pour récupérer les données de sqlite : quel type de tableau ?
  • mpergandmpergand Membre
    juillet 2012 modifié #15
    NSDictionary

    http://www.iphonedev...-databases.html



    Fais une recherche sur ce forum, ya plein de sujets sur sqlite.
  • Mais NSDictionary n'est pas a key -> value unique ?
Connectez-vous ou Inscrivez-vous pour répondre.