MySQL (no) sabe sumar números positivos

Ayer en una pequeña aplicación que hice me reportaron un bug, al revisar resulta que por alguna razon un paginador no estaba devolviendo resultados, al ver con detalle resulta que hay una parte de un query que no devuelve lo esperado…

“…semana <= (select max(semana) from datos) and semana >= (select max(semana) from datos)-15…”

Semana es una columna de enteros positivos (integer unsigned), y pues lo primero que hago es ver que devuelve cada sección, y resulta que la segunda (la del -15) devuelve un numero gigantesco (no se si fue suerte o no que no limitara a 2 o 3 dígitos la columna) por lo que obviamente nunca se cumplia la condición, ya que semana nunca era mayor que 20 o 30 tal vez.

Investigando sobre como hace la suma (o resta) de enteros positivos MySQL, resulta que hay un bug ya de años reportado, en el que se explica que cuando una suma de estos da un resultado negativo, en esencia resta el resultado al máximo valor de la columna, de tal manera que por eso me devolvía un numero horroroso, ash lo odio, en vez de hacer lo correcto.

La solución fue relativamente sencilla, y muy poco elegante, pero funciona 🙂

“semana <= (select max(semana) from datos) and semana >= if((select max(semana) from datos)-1000,0,(select max(semana) from datos)-15)”

De esta manera, si el resultado es negativo, me devuelve un cero, en vez de lo que se le da la gana.

A final de cuentas es discutible que realmente MySQL hace lo correcto, el problema es que no es lo esperado (normalmente), y pues así como mucha documentación no hay, y tampoco sirve de mucho hacer un”cast”, o más bien, se tiene que hacer al revés de los esperado, en vez de hacer cast a “integer unsigned”, tienes que hacerlo a “integer), algo así, pero creo que es mucho más claro poner el “IF()”.

Ahi les dejo, buen día

Tags: , ,


4 votes, average: 1.75 out of 54 votes, average: 1.75 out of 54 votes, average: 1.75 out of 54 votes, average: 1.75 out of 54 votes, average: 1.75 out of 5 (4 votes, average: 1.75 out of 5)
You need to be a registered member to rate this post.
Loading...
Bases de Datos, MySQL | RSS 2.0 |     1,378 views

RSS feed

9 Comments »

Comment by leon
2009-01-07 18:37:34

¿no sabe sumar? ¿que no lo que estas haciendo es una resta? ¿por que habría de darte cero si el resultado es negativo?

 
Comment by garaged
2009-01-08 11:13:33

leon, que nombre tiene esta operacion? 1 + (-1) jeje

Y bueno, en el IF puse “-1000” en vez de mayor que “>1000”.

Y por último, pos pa mi tiene más sentido que de cero, a que de “18446744073709551619” no crees ??

El mundo es tan variado que todos queremos algo diferente no ?

Comment by ed
2009-01-08 17:46:57

1 + (-1)
no es una suma de números positivos…

 
 
Comment by Turbo
2009-01-08 12:20:52

Uy Garaged, eso de vivir con la base de datos equivocada… yo por eso uso postgresql 😛

Comment by garaged
2009-01-10 20:39:28

postgres ni siquiera puede soporta columnas de enteros positivos 🙂

El comentario de wainamoinen (WTF!) es muy interesante, aunque obvio, lo que está haciendo mysql en esta resta (las restas son sumas, de la misma manera que las multiplicaciones son divisiones o viceversa) le queda claro a la mayoría aqui, lo incomodo es que mysql devuelve lo correcto no lo esperado 🙂

 
 
Comment by Turbo
2009-01-08 12:21:39

Oye leon ¿como se ponen la imagen del… gato?

 
Comment by leon
2009-01-08 14:49:14

no me acuerdo Turbo, pero deja investigo

 
Comment by leon
2009-01-08 15:00:10

aquí la respuesta: gravatar.com

 
Comment by wainamoinen
2009-01-08 19:20:41

Eso no es un bug.
Si le pones un signo negativo a un tipo de datos entero positivo lo que te hace es calcular el complemento a 2 para operar como si fueran tipo de datos entero con signo.
http://en.wikipedia.org/wiki/Signed_number_representations#Two.27s_complement

De esta forma trabajando en tipos de datos de 64 bits, lo que es -1 en un entero con signo es 18446744073709551615 en un entero sin signo, -2 es 18446744073709551614, et cetera.

Ese es el riesgo de mezclar enteros con signo y enteros sin signo.

La mayoría de los compiladores de C te avisan de un posible error de desbordamiento por mezclar tipos de enteros, que mal que el MySQL no advierta de esta situación. Que claro es originalmente un error por desconocimiento de programador.

 
Name (required)
E-mail (required - never shown publicly)
URI
Your Comment (smaller size | larger size)
You may use <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> in your comment.

Trackback responses to this post