Archive for 23 noviembre 2009

h1

Sqlite3: “database is locked” en C++

23/11/2009

Utilizando la API de Sqlite 3 en C++ puede ocurrir el caso de acceder a una base de datos y tras una consulta, quedar ésta bloqueada, produciendo un mensaje de error “database is locked” y en el caso de terceras aplicaciones, generando una consulta “SELECT name FROM sqlite_master WHERE type = ‘table’” que en nada se relaciona con la base de datos en uso. Esto se debe a que si al intentar una base de datos se produce un error, se crea una auxiliar básica que en la mayoría de las veces no sirve para nada.

En el siguiente código se puede comprobar, si se invoca dos o más veces, el error:

CÓDIGO ERRÓNEO - WRONG CODE
std::integer countCrimes (string selectedCrimeID, std::vector trainingFileSet, string pathDB){
sqlite3* db;
char* db_err;
sqlite3_stmt *stmt;

cout << "Openning DB connection" << endl;
string SQLquery = "select count(*) from crimes";
sqlite3_open_v2( pathDB.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
int rc = sqlite3_prepare_v2(db, SQLquery.c_str(), strlen(SQLquery.c_str()), &stmt, NULL);
if (SQLITE_OK != rc) { cout << sqlite3_errmsg(db) << endl; //En el segundo acceso a la BD mostrará "database is locked"}
sqlite3_exec(db, SQLquery.c_str() , NULL, 0, &db_err);

sqlite3_step(stmt);
long int occurrencesFound = atoi (sqlite3_column_name(stmt, 0));
std::cout << occurrencesFound << "files hashes of crime " << selectedCrimeID << " in data base."<< endl;

sqlite3_close(db);
sqlite3_free(db_err);
return trainingFileSet;
}

Pese a que se cierra la conexión y aparentemente todo se realiza correctamente, el problema viene por no incluir la orden que indica a Sqlite que el resultado de esa sentencia SQL ya ha sido recibida y por tanto puede continuar procesando las siguientes que vengan, ya que la base de datos se queda bloqueada por la actual sentencia sql. Por lo tanto, siempre que se ejecute una instrucción, hay que utilizar el método sqlite3_finalize(stmt) para no dejar bloqueada la base de datos.

std::integer countCrimes (string selectedCrimeID, std::vector trainingFileSet, string pathDB){
sqlite3* db;
char* db_err;
sqlite3_stmt *stmt;

cout << "Openning DB connection" << endl;
string SQLquery = "select count(*) from crimes";
sqlite3_open_v2( pathDB.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
int rc = sqlite3_prepare_v2(db, SQLquery.c_str(), strlen(SQLquery.c_str()), &stmt, NULL);
if (SQLITE_OK != rc) { cout << sqlite3_errmsg(db) << endl; }
sqlite3_exec(db, SQLquery.c_str() , NULL, 0, &db_err);

sqlite3_step(stmt);
long int occurrencesFound = atoi (sqlite3_column_name(stmt, 0));
std::cout << occurrencesFound << "files hashes of crime " << selectedCrimeID << " in data base."<< endl;

sqlite3_finalize(stmt);

sqlite3_close(db);
sqlite3_free(db_err);
return trainingFileSet;
}

Fuentes: Igor Tandetnik, DMertl

Anuncios
h1

Gcc error: “Description Resource Path Location Type changes meaning” y “Type declaration of”

23/11/2009

Compilando un proyecto con las librerías Boost se pueden producir  simultaneamente los siguientes errores:

Description    Resource    Path    Location    Type changes meaning of ‘special_values_parser’ from ‘class boost::date_time::special_values_parser<date_type, charT>’ MyProject line 34, external location: /usr/include/boost/date_time/special_values_parser.hpp   C/C++ Problem

Description    Resource    Path    Location    Type declaration of ‘void boost::date_time::date_input_facet<date_type, CharT, InItrT>::special_values_parser(boost::date_time::special_values_parser<date_type, charT>)’    MyProject   line 560, external location: /usr/include/boost/date_time/date_facet.hpp    C/C++ Problem


Son debidos a un cambio de versión de GCC. Por tanto, las soluciones serían:

Solución #1)

Como workaround, añadir el parámetro “-fpermissive” en la compilación para convertir este tipo de errores en warnings.

Solución #2) RECOMENDADA

Aunque resulte evidente, lo más conveniente es arreglar el código para cumplir la normativa de GCC, según se indica en el apartado GCC Name lookup changes. En el caso de Boost, basta con actualizar las librerías Boost a la versión 1.40 o posterior (aunque puede que el bug se halla solucionado en previas versiones). En el caso de Debian/Ubuntu se pueden localizar los paquetes aquí ó en el siguiente repositorio:

deb http://ftp.de.debian.org/debian sid main

h1

Error en Cakephp –> Fatal error: Call to undefined method DboSqlite3::length() in /usr/share/php/cake1.2/libs/model/datasources/dbo/dbo_sqlite3.php on line 198

20/11/2009

Si en Cakephp, al hace un cake bake para crear controladores o modelos, ocurre el siguiente error:

Fatal error: Call to undefined method DboSqlite3::length() in /usr/share/php/cake1.2/libs/model/datasources/dbo/dbo_sqlite3.php on line 198

Ocurre porque se está ejecutando el binario incorrecto:
root@WhenIGrowUp:/var/www/cake_project2/app# cake bake

Es necesario ejecutar el incorporado en la aplicación descargada:
root@WhenIGrowUp:/var/www/cake_project2/app# ../cake/console/cake bake

h1

Cakephp error: Class ‘Fileshash’ not found in /var/www/cake_Example/cake/libs/class_registry.php on line 140

19/11/2009

Si utilizando Cakephp, con el patrón MVC, al ejecutar un scaffold o similar se produce el siguiente error:
Fatal error: Class 'Fileshash' not found in /var/www/cake_Example/cake/libs/class_registry.php on line 140

es necesario revisar la clase que representa al modelo de ese controlador, ya que probablemente el nombre de la clase esté erróneamente escrito. Debe ser el mismo nombre, en singular y sin añadidos. Ejemplo:

<?php
class Fileshash extends AppModel
{
var $name = 'Fileshash';
}
?>

h1

Notice (8) Undefined index id cakephp

16/11/2009

Si en Cakephp 1.2.x se produce el siguiente error:

Notice (8) Undefined index id cakephp

esto es debido a estar utilizando, probablemente en Sqlite, una tabla sin campo nombrado como “id”. En Sqlite la sintaxis estándar recomienda nombrar un campo de cada tabla como “id”. Realizando este cambio, el error se subsana.

h1

Como renombrar una columna en Sqlite 3

16/11/2009

Sqlite 3, al menos hasta su versión 3.6.20, no soporta el renombrado de columnas, por lo que la siguiente sentencia no es funcional:

sqlite> alter table tableName rename OldColumnName to NewName

Para cubrir esta necesidad, se volcarán los datos de la tabla con el mal nombrado de columna a otra similar pero con la columna correctamente nombrada, y posteriormente se renombrará la propia tabla. Esto que parece una tarea farragosa puede realizarse sencillamente así:

1º) Crear una copia de la tabla a tratar con el campo corregido:
sqlite> CREATE TABLE hashes_files_nueva (file varchar(256), id varchar(256), crime varchar(128));

2º) Copiar los datos de la tabla original a la nueva tabla:
sqlite> INSERT INTO hashes_files_nueva (file, id, crime)
SELECT *
FROM hashes_files;

3º) Borrar la tabla inicial:
sqlite> DROP TABLE hashes_files;

4º) Renombrar la tabla:
sqlite> ALTER TABLE hashes_files_nueva RENAME TO hashes_files;

Opcionalmente, como Sqlite por defecto no libera el espacio en disco de una tabla borrada, se puede forzar su liberación:
sqlite> vacuum;

Si se desea hacer con interfaz gráfica, se puede probar Sqlitebrowser ó Firefox Sqlite Manager Plugin.

Fuentes: StackOverFlow, Grass.orgeo.org

h1

Cómo utilizar Sqlite3 en Cakephp 1.2

15/11/2009

La versión de Cakephp 1.2 no ofrece soporte oficial para utilizar las bases de datos Sqlite 3, aunque es compatible con versiones anteriores. Para conseguir conectar con esta versión de Sqlite es necesario utilizar un driver no oficial. Actualmente hay dos soluciones:

Solución #1: Driver sqlite3 en Cakephp

https://trac.cakephp.org/ticket/3003, Proyecto surgido en el propio trac de Cakephp, readaptando el driver de Sqlite2 para hacerlo compatible con Sqlite3. Instrucciones:

1º) Descargar la última versión del driver Sqlite3 para Cakephp o descargarlo del siguiente
mirror driver Sqlite3 – Cakephp 1.2.5 (renombrar a “dbo_sqlite3.php”).

2º) Instalarlo, cambiando lógicamente los paths por los respectivos de la aplicación en la que se va a utilizar.:
carlos@maq1:~$ cp dbo_sqlite3.7.php /var/www/cake_1.2.5/cake/libs/model/datasources/dbo/dbo_sqlite3.php

3º) Configurar la aplicación para que utilice este moto de base de datos.
carlos@maq1:~$ nano /var/www/cake_1.2.5/app/config/database.php

Dejando un fichero similar al siguiente:

<?php
class DATABASE_CONFIG {
var $default = array(
'driver' => 'sqlite3',
'host' => '',
'port' => '',
'login' => '',
'password' => '',
'database' => '/var/www/cake_1.2.5/app/config/myDatabaBase',
'schema' => '',
'prefix' => '',
'encoding' => ''
);
var $test = array(
'driver' => 'sqlite3',
'host' => '',
'port' => '',
'login' => '',
'password' => '',
'database' => '/var/www/cake_1.2.5/app/config/myDatabaBase',
'schema' => '',
'prefix' => '',
'encoding' => ''
);
}
?>

Nota: puede ser necesario la instalación del paquete php5-sqlite (a parte de php5-sqlite3), aunque la versión de Sqlite sea la 3.x.
# sudo apt-get install php5-sqlite



Solución #2: Driver sqlite3_spok en Cakephp

Driver japonés.

http://translate.google.es/translate?u=http%3A%2F%2Fwww.cpa-lab.com%2Ftech%2F%26category%3Fcat%3Dsqlite&sl=ja&tl=es&hl=es&ie=UTF-8.

1º) Descargar la última versión del driver sqlite3_spok (actualmente la 1.0.7beta).

2º) Descomprimir y copiar los archivos:
# cp dbo_sqlite3_spok.php /var/www/cake_1.2.5/cake/libs/model/datasources/dbo/dbo_sqlite3_spok.php
# cp dbo_source.php /var/www/cake_1.2.5/cake/libs/model/datasources/

3º) Borrar la caché de Cakephp:
# rm -Rf /var/www/cake_1.2.5/app/tmp/cache/*

4º) Modificar el fichero de configuración de la base de datos de la siguiente manera:
# nano /var/www/cake_1.2.5/app/config/database.php

<?php
class DATABASE_CONFIG {
var $default = array(
'driver' => 'sqlite3_spok',
'connect' => 'PDO',
'host' => '',
'port' => '',
'login' => '',
'password' => '',
'database' => 'sqlite:/var/www/cake_1.2.5/app/config/myDatabaBase',
'schema' => '',
'prefix' => '',
'encoding' => ''
);
}
?>

Ambas soluciones funcionan, no obstante son drivers no oficiales y con poco soporte.