2009-04-28 8 views
0

J'essaie de réutiliser une instruction sqlite dans mon application dans une méthode. Voici le code correspondantPourquoi je reçois sqlite3error?

if(getsets_statement == nil){ 
    const char *sql = "SELECT DISTINCT num,roll FROM mytable WHERE cls like ? and divname like ?"; 
    if(sqlite3_prepare_v2(database, sql, -1, &getsets_statement, NULL) != SQLITE_OK){ 
     NSAssert1(0, @"Error: Failed to prepare stmt with message '%s'", sqlite3_errmsg(database)); 
    }  
} 

sqlite3_bind_text(getsets_statement, 1, [cls UTF8String], -1, SQLITE_TRANSIENT); 
sqlite3_bind_text(getsets_statement, 2, [divname UTF8String], -1, SQLITE_TRANSIENT); 

while(sqlite3_step(getsets_statement) == SQLITE_ROW){ 

    setNumber= sqlite3_column_int(getsets_statement, 0);   

    roll = sqlite3_column_int(getsets_statement, 1); 

    [numArr addObject:[NSNumber numberWithInt:setNumber]]; 
    [rollArr addObject:[NSNumber numberWithInt:roll]]; 
} 

sqlite3_reset(getsets_statement); 

L'instruction s'exécute parfaitement la première fois qu'elle est appelée. Mais la prochaine fois que j'appelle cette méthode, j'obtiens un sqlite3error. Les valeurs de divname et cls sont présentes (a fait un NSLog et vérifié) mais je ne comprends pas pourquoi je reçois cette erreur. J'ai l'erreur à la première déclaration bind_text.

C'est dans la console gdb

Program received signal: “EXC_BAD_ACCESS”. 
(gdb) where 
#0 0x9041857f in sqlite3Error() 
#1 0x9041acea in vdbeUnbind() 
#2 0x9041b2c8 in bindText() 

Toute aide?

+0

Etes-vous sûr que cls et divname sont des objets valides? –

Répondre

2

Assurez-vous que rien d'autre n'est en fait le problème (la base de données est-elle fermée ailleurs? Le getsets_statement pointe-t-il sur le même objet? A-t-il été finalisé?). Ensuite, essayez d'utiliser NULL ou SQLITE___STATIC au lieu de SQLITE_TRANSIENT. Puisque [NSString UTF8String] renvoie des données qui n'ont pas besoin d'être libérées (par vous), il n'a évidemment pas besoin d'un destructeur, et il restera valide jusqu'à la fin de votre fonction, après quoi vous avez fini d'exécuter l'instruction.

+0

Les docs disent, "Si le cinquième argument est la valeur spéciale SQLITE_STATIC, SQLite suppose que l'information est dans un espace statique, non géré et n'a pas besoin d'être libérée Si le cinquième argument a la valeur SQLITE_TRANSIENT, alors SQLite fait sa propre copie privée des données immédiatement, avant le sqlite3_bind_ *() retourne la routine. " Je pense que l'un ou l'autre devrait bien se passer ici, mais SQLITE_TRANSIENT est le pari sûr (mais à un coût de performance), car une copie est faite immédiatement. –

+1

appelait finaliser.Cela causait le problème. Merci. – lostInTransit

+0

@lostInTransit vous devriez mettre cela comme votre réponse, puisque votre commentaire ici est la solution au même problème que j'avais. – gdbj

0

Je crois que vous devez appeler et sqlite3_clear_bindings sur l'instruction préparée avant de tenter de le réutiliser. En outre, vous devriez vraiment vérifier vos codes de retour.

+0

Je pensais qu'une réinitialisation était suffisante. Quoi qu'il en soit, c'est ce que tous les exemples Apple utilisent. Mais je vais essayer. Merci. – lostInTransit

+0

J'ai essayé d'ajouter sqlite3_clear_bindings. Il renvoie SQLITE_OK. Mais je reçois toujours l'erreur. – lostInTransit

+0

Pour réinitialiser les liaisons à null, vous devez appeler clear_bindings, mais dans ce cas, cela n'a aucune importance car l'instruction n'a que 2 paramètres et les deux sont liés à chaque invocation. –

Questions connexes