2010-03-16 6 views
3

Je tente de stocker NSMutableDictionaries en tant que blobs dans sqlite, en le convertissant d'abord en NSData via NSPropertyListSerialization ou NSKeyedArchiver.NSData est tronqué lorsqu'il est stocké dans la base de données SQLite

Lorsque je stocke le blob, la longueur de l'objet NSData est dans les milliers (plage de Ko). Quand je l'ai récupéré, il a été tronqué à 10 octets. Lorsque je vérifie la base de données via SQLite Browser, la plupart des données ont disparu (je peux reconnaître les clés dans l'enregistrement si je stocke le dictionnaire en tant que NSPropertyListSerialization, mais les valeurs du dictionnaire ont disparu). Cela se produit indépendamment de si j'utilise NSPropertyListSerialization ou NSKeyedArchiver pour sérialiser mes données.

NSMutableDictionary* item = [items objectAtIndex:i]; 
NSData *dictionary = [NSKeyedArchiver archivedDataWithRootObject:item]; 
sqlite3_bind_blob( compiledStatement, 5, [dictionary bytes], [dictionary length], SQLITE_TRANSIENT); 

Ceci est en fait un extrait de mon code, la section complète de laquelle j'ai posté dans une autre question connexe.

Bulk inserts into sqlite db on the iphone

Vérification de la valeur de [longueur dictionnaire] en utilisant GDB ou NSLog on obtient le même résultat: La longueur de données est dans la gamme KB.

Quand je vérifie récupérer les données plus tard:

NSData* raw = [[NSData alloc] initWithBytes:sqlite3_column_blob(compiledStatement, 1) length:sqlite3_column_bytes(compiledStatement, 1)]; 
[raw release]; 

Vérification [longueur brute] me donne seulement 10 octets. Cela est vrai pour chaque instance de données que j'ai essayé de stocker dans cette colonne, quelle que soit leur taille de départ, ils finissent par 10 octets à la fin. Il n'y a rien de mal avec ma requête de récupération. Je l'ai exécuté dans la ligne de commande et dans SQL Browser, et j'obtiens les enregistrements et les colonnes corrects, mais les données qui ont été stockées dans l'enregistrement pour cette colonne spécifique sont incorrectes.

Qu'est-il arrivé au reste de mes données? Y a-t-il quelque chose qui ne va pas dans la façon dont j'utilise sqlite3_bind_blob? J'ai vérifié la documentation sqlite pour les caractères de fin ou les limites de taille maximum. Mes données sont bien dans la taille maximale d'une entrée blob, et je ne peux trouver aucune information sur les terminaux qui pourraient couper mes données à la taille.

+1

Je vérifierais la taille maximale par défaut pour les blobs et les moyens de l'ajuster. Cela ou vous tamponnez les données quelque part et seulement le premier morceau le fait. –

+0

Il n'y a pas de taille max 'par défaut', AFAICT des docs ... juste une taille max. Ce qui est énorme. Beaucoup plus gros que ce que j'essaie de stocker. Je vérifie les valeurs juste avant l'appel de liaison, et l'instance de NSData est active et valide jusqu'à ce moment. Pendant l'appel de bind, passer SQLITE_TRANSIENT comme paramètre est censé copier les données que je lui ai données ... de sorte que les données perdues plus tard ne devraient pas être un problème. – akaii

+0

Qu'est-ce que dans les 10 octets? Est-ce réellement une troncature des données du dictionnaire? – Chuck

Répondre

0

J'ai trouvé l'auteur dans cette poursuite bien folle ... Je prenais la valeur de la colonne 1 au lieu de la colonne 0, qui était la colonne réelle qui contenait mes données. J'ai supposé que puisque les valeurs de liaison à votre requête commence à la colonne 1, l'extraction des colonnes à partir des résultats de la requête commencerait également à 1. Mon erreur. Les 10 octets par ligne n'étaient en fait PAS mes données de dictionnaire, mais l'horodatage que j'utilisais pour trier mes résultats.

2

Avez-vous vérifié le type de retour de cette liaison? Il est possible qu'il renvoie un code d'erreur (l'instruction s'exécutera probablement dans cet événement, juste incorrectement). Pour contourner le problème, avez-vous essayé de créer une ZEROBLOB et d'y écrire en utilisant les routines d'E/S BLOB décrites dans le SQLite documentation? Ce serait la prochaine chose que j'essaie après avoir regardé les codes d'erreur.

+0

Il renvoie SQLITE_OK. Je vais donner un coup de blob i/o, mais c'est une façon incroyablement détournée de soumettre un blob à la base de données, quand vous ne stockez pas de façon incrémentielle. – akaii

+0

En outre, après avoir vérifié cette méthode plus en profondeur, je suis inquiet au sujet des frais généraux. Je devrais d'abord insérer l'enregistrement, puis le mettre à jour immédiatement après avoir obtenu un blob par la suite? Je suppose que cela n'a aucun sens d'être capable d'écrire dans le zéro avant même qu'il existe, mais cela va prendre plus de temps pour ma transaction, et je suis sérieusement préoccupé par la performance. – akaii

+0

Le zéro est juste un espace réservé - il n'occupe pas d'espace (ou de performance) jusqu'à ce que vous écriviez des données BLOB réelles. Donc, ne vous inquiétez pas de la performance à moins que ce ne soit un problème. –

Questions connexes