Probléme d'insertion de données dans SQLite avec iPhone

Marroucha

Membre enregistré
30 Juin 2011
7
0
35
Bonjour tt le monde,
Voilà je suis arrivée à parser mon fichier xml et je veux enregistrer son contenu dans une base de donnée SQLite
Pour cela j'ai créé une nouvelle base dans SQLite Manager que j'ai appelé essai, ainsi qu'une classe SQLManager dont le code est le suivant:
Bloc de code:
@implementation SQLManager
@synthesize aliments;

-(id) initDatabase{
    
    if (self = [super init]) {
        //Nom de la base de données
        databaseName = @"Essai3.sqlite";
        
        // Obtenir le chemins complet de la base de donées
        NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDir = [documentPaths objectAtIndex:0];
        databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
    }
    
    return self;
}

-(void) checkAndCreateDatabase{
       // On vérifie si la BDD a déjà été sauvegardée dans l'iPhone de l'utilisateur
      BOOL success;
         
       // Crée un objet FileManagerCreate qui va servir à vérifer le status
        // de la base de données et de la copier si nécessaire
        NSFileManager *fileManager = [NSFileManager defaultManager];
       
       // Vérifie si la BDD a déjà été créée  dans les fichiers system de l'utilisateur
       success = [fileManager fileExistsAtPath:databasePath];
      
        // Si la BDD existe déjà "return" sans faire la suite
    if(success) {return;}
         
            // Si ce n'est pas le cas alors on copie la BDD de l'application vers les fichiers système de l'utilisateur
        
            // On récupère le chemin vers la BDD dans l'application
            NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
            
            // On copie la BDD de l'application vers le fichier systeme de l'application
            [fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
            
            [fileManager release];
        }
- (void)insertIntoDatabase:(aliment*)newAliment {
         
         sqlite3_stmt *compiledStatement=nil;
        sqlite3 *database;
        
    
        // On ouvre la BDD à partir des fichiers système
        if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
               
            // Préparation de la requête SQL qui va permettre d'ajouter un score à la BDD       
            if(compiledStatement == nil) {
            const char *sqlStatement = "insert into aliment2 (name,quantity_unit,energy_unit) Values(?,?,?)";    
            //NSString *sqlStat = [[[NSString alloc] initWithFormat:@"INSERT INTO aliment2 (name,quantity_unit,energy_unit) VALUES ('%@','%@', '%@');" ,newAliment.name,newAliment.quantity_unit,newAliment.energy_unit ] autorelease];
               
             //const char *sqlStatement = [sqlStat cStringUsingEncoding : [NSString defaultCStringEncoding]];
            if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) != SQLITE_OK) {
                
                NSAssert1(0, @"Error while creating add statement. '%s'", sqlite3_errmsg(database));
                
            }
             sqlite3_bind_text(compiledStatement, 1, [newAliment.name UTF8String], -1, SQLITE_TRANSIENT);
                sqlite3_bind_text(compiledStatement, 2, [newAliment.quantity_unit UTF8String], -1, SQLITE_TRANSIENT);
                sqlite3_bind_text(compiledStatement, 3, [newAliment.energy_unit UTF8String], -1, SQLITE_TRANSIENT);

                
                //Evaluation du succes de la requete
                if(SQLITE_DONE != sqlite3_step(compiledStatement)) {
                    //Envois une exception en cas de probleme de requete
                    NSAssert1(0, @"Erreur :. '%s'", sqlite3_errmsg(database));
                    NSLog(@"Erreur1:'%s'", sqlite3_errmsg(database));
                }
                
                
                // Finalisation de la requete pour liberer la memoire
            
            }
            else {
                //Envois une exception en cas de probleme de requete
                NSAssert1(0, @"Erreur :. '%s'", sqlite3_errmsg(database));
                NSLog(@"Erreur2:'%s'", sqlite3_errmsg(database));

            }
            
            
        }
        else {
            //Envois une exception en cas de probleme d'ouverture
            NSAssert(0, @"Erreur d'ouverture de la base de donnees");
            NSLog(@"Erreur d'ouverture de la base de donnees");

        }
    sqlite3_reset(compiledStatement);
    sqlite3_finalize(compiledStatement);
    
    //Fermer la base de donnees
    sqlite3_close(database);
    
}
            //Creation d'une liste des noms de colonnes pour obtenir son ID


@end
et dans RootViewController j'ai cette méthode
Bloc de code:
- (void)viewDidLoad {
    
    // initialisation de la BDD
    sqlManager = [[SQLManager alloc] initDatabase];
    //Vérification et création de la BDD
    [sqlManager checkAndCreateDatabase];
    tableau = [[NSMutableArray alloc] init];
    NSURL *url = [NSURL URLWithString: @"http://www.inov-tech.fr/YourFit/frenshFoodDB.xml"];
    XMLToObjectParser *myParser = [[XMLToObjectParser alloc] parseXMLAtURL:url toObject:@"aliment" parseError:nil];
    int arrayCount = [[myParser items] count]; 
    //NSLog(@"%d",arrayCount);
    for(int i = 0; i<=arrayCount-1 ; i++) {
        
        aliment *new = [[aliment alloc] init];
        new = (aliment *)[[myParser items] objectAtIndex:i];
        [tableau addObject:new];
        [sqlManager insertIntoDatabase:new];
        [new release];
    }
    
        
    [super viewDidLoad];
}
avec aliment l'instance représentant un élément du document xml et voici son header
Bloc de code:
#import <Foundation/Foundation.h>
#import <sqlite3.h>

@interface aliment : NSObject {
    
    NSString *name;
    int quantity;
    int energy;
    NSString *quantity_unit;
    NSString *energy_unit;
    NSString *type;

}

@property(nonatomic,retain) NSString *name;
@property(nonatomic,retain) NSString *quantity_unit;
@property(nonatomic,retain) NSString *energy_unit;
@property(nonatomic,retain) NSString *type;
@property(nonatomic,assign) int quantity;
@property(nonatomic,assign) int energy;




@end

En éxécuttant l'application je n'ai aucune erreur les éléments du fichier apparaissent dans le TableView mais elles ne sont pas stockés dans la base (En consultant SQLite Manager la base est vide)
Je suis complétement plantée depuis hier sans arrivée à trouver la solution:confused:
Prière aidez moi à résoudre ce problème
Merci

---------- Nouveau message ajouté à 15h06 ---------- Le message précédent a été envoyé à 14h30 ----------

Pas de réponse?
 
Je ne suis pas grand spécialiste mais n'inverses-tu pas deux éléments ?

1) tu prépares le string avec paramètres :

const char *sqlStatement = "insert into aliment2 (name,quantity_unit,energy_unit) Values(?,?,?)";

2) tu le charges :
sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL)

3) tu mets les paramètres :
Sqlite3_bind_text(compiledStatement, 1, [newAliment.name UTF8String], -1, SQLITE_TRANSIENT);


J'essaierai en mettant 3 avant 2 mais je le répète, je ne suis pas une foudre en SQL.
 
L'inversement des deux étapes n'a rien changé. L'application s'exécute sans errer et j'ai vérifié que SQLITE_DONE == sqlite3_step(compiledStatement) donc que la requète est exécutée mais la table aliment2 est encore vide dans SQLite Manager de Firefox
Sincèrement je vois pas ou se trouve le problème(ça fait longtemps que je suis bloquée)
Dans tous les cas merci pour votre intérêt
 
As-tu essayé un simple "INSERT INTO () " avec directement les valeurs dans la commande ?
 
Bonjour, j'ai commencé à spécifié le probléme mais il n'est pas encore résolu :(
En fait il fallait que j'ajoutait commit, pour cette raison avant d'appeler le méthode insertInDatabase j'ai ajouté ce bout de code:
Bloc de code:
sqlite3 * db=[sqlManager returnDataBase];//ouvre la base et renvoie un sqlite3 *
    NSLog(@"Opned");
    sqlite3_get_autocommit(db);
    char* errmsg1;
    int result1 = sqlite3_exec(db, "BEGIN", NULL, NULL, &errmsg1);
    NSLog(@"BEGIN:%s",errmsg1);
    sqlite3_free(errmsg1);
et aprés la boucle pour qui fait l'ittération sur les éléments du document xml j'ai ajouté:
Bloc de code:
char* errmsg;
    int result = sqlite3_exec(db, "commit;", NULL, NULL, &errmsg);
    NSLog(@"erreurCommitting:%s",errmsg);    
    sqlite3_free(errmsg);

Ce que j'obtient c'est les messages d'erreur suivants:
BEGIN:(null)
erreurCommitting:(null)
je ne vois pas comment résoudre ceci
Aidez moi s'il vous plait
 
Essaye peut-être de poster sur un forum dédié au SQLite..

Ne copie colle pas tout ton code, mais prend les points clés "SQL".

Sethy
 
Le probléme est enfin résolu
C'était à cause de la méthode initDataBase qui ne fournit pas le path correct de la base de donnée (J'ai pris ce code d'un tuto que malheureusement j'ai pas eu l'idée de vérifier sa validité :( )
En entrant le path manuellement tt est réglé:up:
 
Content pour toi ;)

Passe peut-être le message en résolu.

Sethy