Ay de aquel

por José Angel Buesa

Ay de aquel que sólo vive despierto
y que alza sobre las cosas una sola mirada
porque al llegar a luz o a la sombra no sabrá nada,
ni para qué ha vivido ni por qué ha muerto.
Mirad las flores, mirad las mariposas.
Y ateos o creyentes, mirad la luz del día.
Pues si Dios no existiera, ¿quién haría estas cosas?
Pero si Dios existe, ¿para qué las haría?

 

Pues hace un tiempo (de casualidad) me topé con éste poema y me parece que vale la pena compartirlo las veces que sea. Lo mejor es la declamación, calza perfectamente con el espíritu del poema.

Tomen un minuto de su tiempo para escucharla (pueden ignorar el resto)

¿Nos invaden los venezolanos?

En realidad no u_u

Pues en una ciudad como Lima casi todos somos una suerte de ‘invasores’, muchos provenimos de un lugar remoto, olvidado por el estado, de difícil acceso, dónde no abundan los productos de primera necesidad, dónde hay un creciente descontento, un lugar que es muy rico en recursos pero son mal aprovechados, dónde todo es difícil -desde nacer y vivir-, dónde hay hambre y una lista interminable de adversidades que son solamente parte del día a día…

¿No les parece familiar la descripción?

Pues te escribo a ti venezolano que estás rondando por alguna zona de Lima (o del Perú) seguramente sentiste algo como:

    • Que estás en un lugar donde no conoces a (casi) nadie.
    • Que sientes que te miran raro por ser de un lugar diferente.
    • Que ven tus costumbres y maneras de hablar como algo novedoso.
    • Como todo es «diferente», cuando encuentras personas que hacen lo mismo que tu te sientes como en casa y te unes a la fiesta.
    • Que te traten como parte de una «plaga incontrolable».

Te digo que todos hemos sentido lo mismo (en mayor o menor dimensión) por que casi todo somos inmigrantes de todas partes del Perú y quizás sin conocer a casi nadie han (re)hecho su vida en Lima.

No se sientan extraños en ésta tierra (es el mismo planeta recuerden) y dejen de decir que vienen de Venezuela para agregarle más dramatismo a su discurso por que muchas de sus tragedias ya son harto conocidas por nosotros y sumado a todo eso: El Terrorismo. Hablen de Venezuela como el lugar bonito que es y las cosas que mas extrañan, por que eso les dará fuerza para seguir adelante, sabemos que no es fácil, sabemos que se sufre… pero así es la vida misma amigos míos.

Un abrazo.

Actualizar bash para evitar ataques Shellshock

Cuando vi el titular dije: «Debe tratarse de IE o algo con Windows…» pero cuando leí el contenido: WTF!! bash metido en esto? no puede ser!!

Aún no hay una solución precisa que resuelva el problema pero por lo pronto debemos actualizar bash «rait nau». Para saber si tu sistema es vulnerable puedes ejecutar los siguientes comandos en consola:

Comando 1:

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

Si el comando muestra `vulnerable` entonces tu sistema lo es.

Comando 2:

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

Si el comando muestra una fecha, sigues siendo vulnerable.

Comando 3:

env -i X=' () { }; echo hello' bash -c 'date'

Si el comando anterior muestra `hello` sigues siendo vulnerable.

Como actualizar bash?

En Ubuntu/Debian: (solo para versiones LTS)

sudo apt-get update && sudo apt-get install --only-upgrade bash

En Centos/Redhat/Fedora:

sudo yum update bash

 

Esto hasta que publiquen una solución definitiva, sería buena idea realizar esas actualizaciones a diario hasta que la alerta roja desaparezca.

 

Tomado de: shellshocker

Consultas de referencias cruzadas en MySQL

Hace algún tiempo que uso Redmine para gestionar proyectos, la herramienta en general es buena pero a veces necesitaba de reportes diarios de tiempo utilizado por los miembros del proyecto.

En este punto se me ocurrió si podría lograr una consulta de referencias cruzadas (al estilo MS Excel), MySQL no soporta consultas de ese tipo pero pueden simularse:

1. Escribir la consulta principal que contenga las filas más importantes: project identifier, task subject y total_hours, todo en un rango de fechas.

select p.identifier, 
	e.issue_id, i.subject, round(sum(e.hours),2) as total_hours
	from redmine_nsp.time_entries e
	inner join redmine_nsp.issues i on e.issue_id = i.id
	inner join redmine_nsp.projects p on e.project_id = p.id
	where e.spent_on between '2014-07-01' and '2014-07-07'
 group by p.identifier,e.issue_id;

Resultado:

+------------+----------+----------------------------+-------------+
| identifier | issue_id | subject                    | total_hours |
+------------+----------+----------------------------+-------------+
| bg02       |     3223 | Gestion de proyecto        |        0.25 |
| bg04       |     3256 | 1.1 Preparación del entor  |        0.63 |
| emision    |     3251 | Desarrollar la aplicación  |        3.97 |
| nsp00      |     3236 | Preparar propuesta para G  |        2.02 |
| nsp02      |     3234 | Subida al servidor de pro  |        0.52 |
| nsp02      |     3240 | Agregar funcionalidad de   |        0.55 |
| nsp02      |     3241 | Revertir el Documento      |        2.80 |
| nsp02      |     3242 | Agregar Filtros en las vi  |        0.72 |
| nsp02      |     3243 | Reportes de Cargo de entr  |        2.35 |
| nsp02      |     3254 | Control de sesiones        |        3.23 |
| nsp05      |     3252 | Mantenimiento del servido  |        0.18 |
| nsp05      |     3253 | Mantenimiento a redmine    |        0.53 |
| nsp06      |     3203 | Elaborar el visualzador d  |        0.23 |
| nsp06      |     3228 | Evitar que se tome mas de  |        0.25 |
| nsp06      |     3255 | Actualizar el porcentaje   |        1.50 |
| nsp08      |     3239 | Asistencia remota          |        1.38 |
+------------+----------+----------------------------+-------------+

2. Ahora queda averiguar quienes han estado activos en ese mismo rango de tiempo:

select e.user_id, u.login
from redmine_nsp.time_entries e
	inner join redmine_nsp.users u on e.user_id = u.id 
where e.spent_on between '2014-07-01' and '2014-07-07'
group by e.user_id;
+---------+----------+
| user_id | login    |
+---------+----------+
|       1 | user1    |
|       4 | user2    |
|       5 | user3    |
|       6 | user4    |
+---------+----------+

3. La tarea es insertar ese resultado como columnas del primer resultado, de tal modo que tengamos una consulta de referencias cruzadas. He creado un procedimiento (no explico mucho al respecto) que hace esa tarea recibiendo como parámetros las fechas:

DELIMITER $$

CREATE PROCEDURE `get_range_summary`(dDate1 date,dDate2 date)
BEGIN

DECLARE done INT DEFAULT 0;
declare p_user_id int;
declare p_sql text;
declare p_login varchar(255);
declare c_users cursor for
	select e.user_id, u.login
	from redmine_nsp.time_entries e
		inner join redmine_nsp.users u on e.user_id = u.id 
	where e.spent_on between  dDate1 and dDate2 
	group by e.user_id;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;

set p_sql = 'select s.codigo,s.issue_id,s.subject ';
open c_users;

read_loop: LOOP
	FETCH c_users INTO p_user_id, p_login;
    IF done THEN
      LEAVE read_loop;
    END IF;
	set p_sql = concat(p_sql,
      ', (select round(sum(t.hours),2) as total
		from redmine_nsp.time_entries t
		where t.spent_on between \'',dDate1,'\' and \'',dDate2,'\'  
        and t.issue_id = s.issue_id
		and t.user_id = ',p_user_id,') as `',p_login,'` ');

END LOOP;

set @sql = concat(p_sql,' ,s.total_hours from 
	(select p.identifier, e.issue_id, i.subject, 
         round(sum(e.hours),2) as total_hours
	from redmine_nsp.time_entries e
	inner join redmine_nsp.issues i on e.issue_id = i.id
	inner join redmine_nsp.projects p on e.project_id = p.id
	where e.spent_on between \'',dDate1,'\' and \'',dDate2,'\' group by p.identifier,e.issue_id) as s');


close c_users;

PREPARE stmt1 FROM @sql;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1; 

END

Al probar con la llamada: call get_range_summary(‘2014-07-01′,’2014-07-07’):

+---------+----------+----------------------------+-------+--------+---------+----------+-------------+
| identif | issue_id | subject                    | user1 | user2  |  user3  |   user4  | total_hours |
+---------+----------+----------------------------+-------+--------+---------+----------+-------------+
| bg02    |       23 | Gestion de proyecto        |  NULL |   0.25 |    NULL |     NULL |        0.25 |
| bg04    |       56 | 1.1 Preparación del entor  |  NULL |   0.63 |    NULL |     NULL |        0.63 |
| emision |       51 | Desarrollar la aplicación  |  NULL |   NULL |    3.97 |     NULL |        3.97 |
| nsp00   |       36 | Preparar propuesta para G  |  NULL |   2.02 |    NULL |     NULL |        2.02 |
| nsp02   |       34 | Subida al servidor de pro  |  NULL |   0.52 |    NULL |     NULL |        0.52 |
| nsp02   |       40 | Agregar funcionalidad de   |  NULL |   NULL |    0.55 |     NULL |        0.55 |
| nsp02   |       41 | Revertir el Documento      |  1.40 |   NULL |    1.40 |     NULL |        2.80 |
| nsp02   |       42 | Agregar Filtros en las vi  |  NULL |   NULL |    0.72 |     NULL |        0.72 |
| nsp02   |       43 | Reportes de Cargo de entr  |  NULL |   NULL |    NULL |     2.35 |        2.35 |
| nsp02   |       54 | Control de sesiones        |  NULL |   NULL |    NULL |     3.23 |        3.23 |
| nsp05   |       52 | Mantenimiento del servidor |  NULL |   0.18 |    NULL |     NULL |        0.18 |
| nsp05   |       53 | Mantenimiento a redmine    |  NULL |   0.53 |    NULL |     NULL |        0.53 |
| nsp06   |        3 | Elaborar el visualzador de |  NULL |   0.23 |    NULL |     NULL |        0.23 |
| nsp06   |       28 | Evitar que se tome mas de  |  NULL |   0.25 |    NULL |     NULL |        0.25 |
| nsp06   |       55 | Actualizar el porcentaje d |  NULL |   1.50 |    NULL |     NULL |        1.50 |
| nsp08   |       39 | Asistencia remota          |  NULL |   1.38 |    NULL |     NULL |        1.38 |
+---------+----------+----------------------------+-------+--------+---------+----------+-------------+

Es todo! Luego con ese resultado es fácil crear un pequeño reporte diario/semanal sobre las horas utilizadas por cada usuario.

Acostumbrado?

Lo primero que me preguntan al saber vivo en Lima  un poco más de dos años es ¿Y ya te acostumbraste?

Para no alargar la conversación, les digo «Sí, ya me acostumbré» y me suelen decir después «Si pues, Lima es otra cosa». Luego me digo a mi mismo «WTF!!!?», lo que en realidad quiero responder es:

¿Acostumbrarme a caminar mirando en cada esquina si hay alguien sospechoso del cual deba cuidarme? ¿Acostumbrarme a no ver las estrellas ni las nubes blancas junto aun cielo con muchas tonalidades de azul? ¿A escuchar una historia peor que la anterior en los buses? ¿A sentir el hedor de todos los días? ¿A perder valiosas horas diarias para ir al trabajo? ¿A ver lo poco que vale la vida? ¿Acostumbrarme a no ver tantas cosas que no sabía que iba a extrañar? Cosas que que para mí eran «normales» y hasta vi con humor cuando alguien, recién llegado a mi pueblito, se quedó mirando el cielo diciendo «mira esas nubes ¿bien blancas no?»

Si pudiera mandar todo a la mierda y regresar… lo haría, pero todos tenemos una voz que nos dice «un momentito… !, basta de padecimientos infantiles, todos pasan por lo mismo y finalmente terminan acostumbrándose y no andan publicando cojudeces en sus blogs».

El tiempo pasa y las cosas cambian.

Copia de seguridad de sqlite a la unidad sdcard en Android

Cuando ya tenemos una aplicación en producción y ocurre un problema causado por la base de datos suele ser complicado averiguar donde esta el problema, es buena idea tener una copia de la misma base de datos para ver exactamente que esta pasando.

Hace un tiempo que estaba buscando la manera de sacar un backup de la base de datos de una aplicación en Android, después de probar varias opciones encontré un segmento de código que sí ha funcionado:

public void backupdDatabase(){
    try {
	    File sd = Environment.getExternalStorageDirectory();
	    File data = Environment.getDataDirectory();
	    String packageName  = "com.yourapp.package";
	    String sourceDBName = "mydb.db";
	    String targetDBName = "mydb";
	    if (sd.canWrite()) {
	    	Date now = new Date();
		String currentDBPath = "data/" + packageName + "/databases/" + sourceDBName;
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm"); 
		String backupDBPath = targetDBName + dateFormat.format(now) + ".db";

		File currentDB = new File(data, currentDBPath);
		File backupDB = new File(sd, backupDBPath);

		Log.i("backup","backupDB=" + backupDB.getAbsolutePath());
		Log.i("backup","sourceDB=" + currentDB.getAbsolutePath());

		FileChannel src = new FileInputStream(currentDB).getChannel();
		FileChannel dst = new FileOutputStream(backupDB).getChannel();
		dst.transferFrom(src, 0, src.size());
		src.close();
		dst.close();
	    }
	} catch (Exception e) {
		Log.i("Backup", e.toString());
	}
}

Ustedes ya se encargan de cambiar los valores y mostrar los mensajes de error.

Me olvidaba que necesitarán del permiso para escribir en la memoria SD:

   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

 

Obtenido de: Stackoverflow

 

Comer solo no es tan malo

Puede resultar muy extraño para la gran mayoría de ustedes, es complicado de explicar el por que no me agrada comer solo, no me refiero a comer unas papas fritas cerca a la computadora, me refiero a almorzar/cenar en un restaurante (incluso en casa).

Debo confesar que algunas veces usé la escusa de «no puedo comer solo» para ligar a alguien, pero en realidad es cierto… muy difícil para mi comer solo. Me asusta un poco la idea de estar sentado en la mesa de un restaurante comiendo solo, me cuesta mucho hacerlo, al punto que muchas veces he preferido no ir a comer –si no hay mucha hambre– o pedir para llevar y «tragar» en la privacidad de mi cuarto.

foreveralone

Siento el equivalente a ir a un bar, sentarse en la barra, pedir algo fuerte, tomar el trago sin conversar con nadie mas que tu conciencia y retirarte después de pagar la cuenta ¿Suena patético no?

Vivir solo, lejos de casa, de la familia y de los amigos mas entrañables hacen más difícil todo ya que no es tan fácil conseguir un acompañante, por mas delicioso que sea el menú no se come con gusto.

He tenido que aprender a convivir con esa fobia, manejar ese oscuro sentimiento, tragar las sensaciones que me aquejan para finalmente decir que comer solo no es tan malo como parece, muchos lo hacen y parece que no tienen problemas con ello.

No he superado el «problema» pero viviré. Tu que me estas leyendo podrás decir: «¿tengo muchos problemas y este tipo se hace un mundo para ir a comer?… JA!!!» pues sí… tal vez este post se vea patético, pero tenía que decirlo.

Buen provecho!

MySQL, el extraño caso de un campo timestamp

Hace un tiempo descubrí una característica (tal vez sea un bug) sobre los campos timestamp de MySQL. Es probable que este documentado en alguna parte que todavía no he leído:

Cuando se añade un campo timestamp a una tabla, MySQL agrega mágicamente algunas características al nuevo campo creado como un «trigger» y la fecha actual como valor por defecto.

Aquí esta el script donde se produce el caso:

-- CREANDO UNA TABLA CUALQUIERA E INSERTANDO DATOS 
mysql> create table t(
    -> id int not null primary key auto_increment,
    -> val varchar(50)
    -> );
Query OK, 0 rows affected (0.15 sec)

mysql> insert into t (val) values ("foo") ,("var");
Query OK, 2 rows affected (0.08 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from t;
+----+------+
| id | val  |
+----+------+
|  1 | foo  |
|  2 | var  |
+----+------+
2 rows in set (0.00 sec)


-- AGREGANDO UN CAMPO TIMESTAMP Y MAS DATOS
mysql> alter table t add ts_field timestamp;
Query OK, 2 rows affected (0.35 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into t (val) values ("foo 2") ,("var 2");
Query OK, 2 rows affected (0.06 sec)
Records: 2  Duplicates: 0  Warnings: 0

-- HE AQUI LA MAGIA:
mysql> select * from t;
+----+-------+---------------------+
| id | val   | ts_field            |
+----+-------+---------------------+
|  1 | foo   | 0000-00-00 00:00:00 |
|  2 | var   | 0000-00-00 00:00:00 |
|  3 | foo 2 | 2013-01-09 23:20:01 |    <---
|  4 | var 2 | 2013-01-09 23:20:01 |    <---
+----+-------+---------------------+
4 rows in set (0.00 sec)

¿¡Pero que acaba de pasar!?
no lo sé.

La nueva estructura de la tabla es:

CREATE TABLE `t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `val` varchar(50) DEFAULT NULL,
  `ts_field` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1

Esto sólo pasa cuando en la tabla no existe otro campo timestamp aún.

Ahora, es útil? tal vez. Es un BUG? tal vez.

El "extraño caso" se repite en MySQL 5.1 y 5.5.

Update: Es una característica documentada en https://dev.mysql.com/doc/refman/5.5/en/timestamp-initialization.html , me disculpo por el post que finalmente resultó ser una chorrada, un lapsus, un horror.