SQLiteBooks, metodos hydrate y dehydrate
09 July 2008
En este post vamos a desglosar y analizar los metodos hydrate y dehydrate del ejemplo SQLiteBooks que talvez muchos no tenemos muy claro como funciona:
Estos métodos sirven para cargar y descargar nuestros datos de la memoria. Empecemos con hydrate:
En el ejemplo, tenemos un metodo llamado initWithPrimaryKey: que recupera el nombre del libro, con hydrate nos aseguramos de traer el resto de los datos a nuestro objeto.
Los argumentos que se pasan a sqlite3_prepare_v2 son: el nombre de la base de datos, la consulta, la longitud de la consulta en bytes, la consulta compilada y el puntero a una porción no usada de la consulta (en el ejemplo NULL).
[cpp](void)hydrate {
// Verificamos si es necesario cargar los datos, si ya estan en memoria no se realiza ninguna acción.
if (hydrated) return;
//Para que se ejecute una consulta es necesario compilarla previamente, para esto se emplea sqlite3_prepare_v2
if (hydrate_statement == nil) {
const char *sql = "SELECT author, copyright FROM book WHERE pk=?";
if (sqlite3_prepare_v2(database, sql, -1, &hydrate_statement, NULL) != SQLITE_OK) {
NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
}
// Enlazamos el parametro "primaryKey" a la consulta
sqlite3_bind_int(hydrate_statement, 1, primaryKey);
// Ejecutamos la consulta que nos devuelve SQLITE_ROW
int success =sqlite3_step(hydrate_statement);
if (success == SQLITE_ROW) {
char *str = (char *)sqlite3_column_text(hydrate_statement, 0);
self.author = (str) ? [NSString stringWithUTF8String:str] : @"";
self.copyright = [NSDate dateWithTimeIntervalSince1970:sqlite3_column_double(hydrate_statement, 1)];
} else {
// Si la consulta no generó resultados
self.author = @"Unknown";
self.copyright = [NSDate date];
}
// Reseteamos la consulta para un proximo uso
sqlite3_reset(hydrate_statement);
// Actualizamos el estado del objeto a hydrated
hydrated = YES;
}[/cpp]
El metodo dehydrate descarga de la memoria todos los datos excepto la llave primaria y nos permite realizar cualquier cambio en los datos:
[cpp]- (void)dehydrate {
if (dirty) {
////Para que se ejecute una consulta es necesario compilarla previamente, para esto se emplea sqlite3_prepare_v2
if (dehydrate_statement == nil) {
const char *sql = "UPDATE book SET title=?, author=?, copyright=? WHERE pk=?";
if (sqlite3_prepare_v2(database, sql, -1, &dehydrate_statement, NULL) != SQLITE_OK) {
NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
}
// Enlazamos las variables de la consulta
sqlite3_bind_text(dehydrate_statement, 1, [title UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(dehydrate_statement, 2, [author UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_double(dehydrate_statement, 3, [copyright timeIntervalSince1970]);
sqlite3_bind_int(dehydrate_statement, 4, primaryKey);
// Ejecutamos la consulta
int success = sqlite3_step(dehydrate_statement);
// Reseteamos la consulta para un proximo uso
sqlite3_reset(dehydrate_statement);
// Manejamos los errores
if (success != SQLITE_DONE) {
NSAssert1(0, @"Error: failed to dehydrate with message '%s'.", sqlite3_errmsg(database));
}
// Actualizamos el estado del objeto respecto a los cambios
dirty = NO;
}
//Finalmente liberamos nuestras variables de la memoria
[author release];
author = nil;
[copyright release];
copyright = nil;
[data release];
data = nil;
// Actualizamos el estado del objeto a hydrated = NO
hydrated = NO;
}
[/cpp]
Espero que el post haya servido para aclarar algunas dudas y bueno cualquier comentario o pregunta son bienvenidos.
Estos métodos sirven para cargar y descargar nuestros datos de la memoria. Empecemos con hydrate:
En el ejemplo, tenemos un metodo llamado initWithPrimaryKey: que recupera el nombre del libro, con hydrate nos aseguramos de traer el resto de los datos a nuestro objeto.
Los argumentos que se pasan a sqlite3_prepare_v2 son: el nombre de la base de datos, la consulta, la longitud de la consulta en bytes, la consulta compilada y el puntero a una porción no usada de la consulta (en el ejemplo NULL).
[cpp](void)hydrate {
// Verificamos si es necesario cargar los datos, si ya estan en memoria no se realiza ninguna acción.
if (hydrated) return;
//Para que se ejecute una consulta es necesario compilarla previamente, para esto se emplea sqlite3_prepare_v2
if (hydrate_statement == nil) {
const char *sql = "SELECT author, copyright FROM book WHERE pk=?";
if (sqlite3_prepare_v2(database, sql, -1, &hydrate_statement, NULL) != SQLITE_OK) {
NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
}
// Enlazamos el parametro "primaryKey" a la consulta
sqlite3_bind_int(hydrate_statement, 1, primaryKey);
// Ejecutamos la consulta que nos devuelve SQLITE_ROW
int success =sqlite3_step(hydrate_statement);
if (success == SQLITE_ROW) {
char *str = (char *)sqlite3_column_text(hydrate_statement, 0);
self.author = (str) ? [NSString stringWithUTF8String:str] : @"";
self.copyright = [NSDate dateWithTimeIntervalSince1970:sqlite3_column_double(hydrate_statement, 1)];
} else {
// Si la consulta no generó resultados
self.author = @"Unknown";
self.copyright = [NSDate date];
}
// Reseteamos la consulta para un proximo uso
sqlite3_reset(hydrate_statement);
// Actualizamos el estado del objeto a hydrated
hydrated = YES;
}[/cpp]
El metodo dehydrate descarga de la memoria todos los datos excepto la llave primaria y nos permite realizar cualquier cambio en los datos:
[cpp]- (void)dehydrate {
if (dirty) {
////Para que se ejecute una consulta es necesario compilarla previamente, para esto se emplea sqlite3_prepare_v2
if (dehydrate_statement == nil) {
const char *sql = "UPDATE book SET title=?, author=?, copyright=? WHERE pk=?";
if (sqlite3_prepare_v2(database, sql, -1, &dehydrate_statement, NULL) != SQLITE_OK) {
NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
}
// Enlazamos las variables de la consulta
sqlite3_bind_text(dehydrate_statement, 1, [title UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(dehydrate_statement, 2, [author UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_double(dehydrate_statement, 3, [copyright timeIntervalSince1970]);
sqlite3_bind_int(dehydrate_statement, 4, primaryKey);
// Ejecutamos la consulta
int success = sqlite3_step(dehydrate_statement);
// Reseteamos la consulta para un proximo uso
sqlite3_reset(dehydrate_statement);
// Manejamos los errores
if (success != SQLITE_DONE) {
NSAssert1(0, @"Error: failed to dehydrate with message '%s'.", sqlite3_errmsg(database));
}
// Actualizamos el estado del objeto respecto a los cambios
dirty = NO;
}
//Finalmente liberamos nuestras variables de la memoria
[author release];
author = nil;
[copyright release];
copyright = nil;
[data release];
data = nil;
// Actualizamos el estado del objeto a hydrated = NO
hydrated = NO;
}
[/cpp]
Espero que el post haya servido para aclarar algunas dudas y bueno cualquier comentario o pregunta son bienvenidos.

Deja un comentario