MySQL (no) sabe sumar números positivos

0
(0)

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

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

9 thoughts on “MySQL (no) sabe sumar números positivos

  1. 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 ?

    1. 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 🙂

  2. 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.

Leave a Reply