Sorpresas con comparaciones en columnas TIMESTAMP WITH DEFAULT

A veces te encuentras sorpresas en el día a día. Hoy di con algo sorprendente respecto de las comparaciones con timestamps:

Vamos a hacer una pequeña prueba de comparaciones de TIMESTAMPs con mayor estricto para colunas definidas con ‘WITH DEFAULT’:

 BTEQ -- Enter your SQL request or BTEQ command:
CREATE MULTISET TABLE CARLOS.PRUEBA01
   ( ID_N INTEGER NOT NULL,
     TS_TIMESTAMP TIMESTAMP(0) NOT NULL WITH DEFAULT )
;


 *** Table has been created.
 *** Total elapsed time was 1 second.


 BTEQ -- Enter your SQL request or BTEQ command:


INSERT INTO CARLOS.PRUEBA01(ID_N) VALUES ( 1 )
;INSERT INTO CARLOS.PRUEBA01(ID_N) VALUES ( 2 )
;INSERT INTO CARLOS.PRUEBA01(ID_N) VALUES ( 3 )
;


 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.

 *** Insert completed. One row added.

 *** Insert completed. One row added.

 BTEQ -- Enter your SQL request or BTEQ command:


SELECT *
  FROM CARLOS.PRUEBA01
;


 *** Query completed. 3 rows found. 2 columns returned.
 *** Total elapsed time was 1 second.

       ID_N         TS_TIMESTAMP
-----------  -------------------
          3  2014-09-18 18:27:58
          2  2014-09-18 18:27:58
          1  2014-09-18 18:27:58

 BTEQ -- Enter your SQL request or BTEQ command:
INSERT INTO CARLOS.PRUEBA01(ID_N) VALUES ( 4 );


 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.


 BTEQ -- Enter your SQL request or BTEQ command:


SELECT *
  FROM CARLOS.PRUEBA01
;


 *** Query completed. 4 rows found. 2 columns returned.
 *** Total elapsed time was 1 second.

       ID_N         TS_TIMESTAMP
-----------  -------------------
          3  2014-09-18 18:27:58
          4  2014-09-18 18:28:52
          2  2014-09-18 18:27:58
          1  2014-09-18 18:27:58

 BTEQ -- Enter your SQL request or BTEQ command:
SELECT *
  FROM CARLOS.PRUEBA01
 WHERE TS_TIMESTAMP > TIMESTAMP '2014-09-18 18:27:58'
;


 *** Query completed. One row found. 2 columns returned.
 *** Total elapsed time was 1 second.

       ID_N         TS_TIMESTAMP
-----------  -------------------
          4  2014-09-18 18:28:52

Todo perfecto: Las filas reciben el CURRENT_TIMESTAMP(0) para la columna TS_TIMESTAMP y la comparación en la ‘query’ final sólo devuelve una fila estrictamente mayor a TIMESTAMP ‘2014-09-18 18:27:58’ (como debe ser).

Ahora empieza lo divertido:

Vamos a crear la misma tabla sin la columna TS_TIMESTAMP. Haremos las inserciones y después añadiremos la columna TS_TIMESTAMP con el NOT NULL WITH DEFAULT (esto debe hacer que todas las filas tomen el TIMESTAMP del momento del ALTER TABLE para la nueva columna):

 BTEQ -- Enter your SQL request or BTEQ command:
DROP TABLE CARLOS.PRUEBA01;


 *** Table has been dropped.
 *** Total elapsed time was 2 seconds.


 BTEQ -- Enter your SQL request or BTEQ command:
CREATE MULTISET TABLE CARLOS.PRUEBA01
   ( ID_N INTEGER NOT NULL)
;


 *** Table has been created.
 *** Total elapsed time was 1 second.


 BTEQ -- Enter your SQL request or BTEQ command:


INSERT INTO CARLOS.PRUEBA01(ID_N) VALUES ( 1 )
;INSERT INTO CARLOS.PRUEBA01(ID_N) VALUES ( 2 )
;INSERT INTO CARLOS.PRUEBA01(ID_N) VALUES ( 3 )
;


 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.

 *** Insert completed. One row added.

 *** Insert completed. One row added.

 BTEQ -- Enter your SQL request or BTEQ command:
ALTER TABLE CARLOS.PRUEBA01
ADD TS_TIMESTAMP TIMESTAMP(0) NOT NULL WITH DEFAULT;


 *** Table has been modified.
 *** Total elapsed time was 1 second.


 BTEQ -- Enter your SQL request or BTEQ command:
SELECT *
  FROM CARLOS.PRUEBA01
;


 *** Query completed. 3 rows found. 2 columns returned.
 *** Total elapsed time was 1 second.

       ID_N         TS_TIMESTAMP
-----------  -------------------
          3  2014-09-18 18:34:03
          2  2014-09-18 18:34:03
          1  2014-09-18 18:34:03

Añadimos una fila más como marcador:

BTEQ -- Enter your SQL request or BTEQ command:
INSERT INTO CARLOS.PRUEBA01(ID_N) VALUES ( 4 );

*** Insert completed. One row added.
*** Total elapsed time was 1 second.

BTEQ -- Enter your SQL request or BTEQ command:

SELECT *
FROM CARLOS.PRUEBA01
;

*** Query completed. 4 rows found. 2 columns returned.
*** Total elapsed time was 1 second.

ID_N TS_TIMESTAMP
----------- -------------------
3 2014-09-18 18:34:03
4 2014-09-18 18:34:19
2 2014-09-18 18:34:03
1 2014-09-18 18:34:03

Si hacemos la misma comparación con el mayor estricto para el TIMESTAMP vemos que:

 BTEQ -- Enter your SQL request or BTEQ command:
SELECT *
  FROM CARLOS.PRUEBA01
 WHERE TS_TIMESTAMP > TIMESTAMP '2014-09-18 18:34:03'
;


 *** Query completed. 4 rows found. 2 columns returned.
 *** Total elapsed time was 1 second.

       ID_N         TS_TIMESTAMP
-----------  -------------------
          3  2014-09-18 18:34:03
          4  2014-09-18 18:34:19
          2  2014-09-18 18:34:03
          1  2014-09-18 18:34:03

Y aunque hemos comparado con un mayor estricto, la ‘SELECT’ devuelve valores como si fuera un mayor o igual.

Pero esto sólo ocurre para las filas que fueron afectadas por el ALTER TABLE, ya que la fila que se insertó con la columna TS_TIMESTAMP ya incorporada, se comporta bien en las comparaciones con mayor estricto:

 BTEQ -- Enter your SQL request or BTEQ command:
SELECT *
  FROM CARLOS.PRUEBA01
WHERE TS_TIMESTAMP > TIMESTAMP '2014-09-18 18:34:19';


 *** Query completed. No rows found.
 *** Total elapsed time was 1 second.

Como los buenos prestidigitadores, mostramos la estructura de la tabla para demostrar que no hay trampa ni cartón:

 BTEQ -- Enter your SQL request or BTEQ command:
SHOW TABLE CARLOS.PRUEBA01;


 *** Text of DDL statement returned.
 *** Total elapsed time was 1 second.

-----------------------------------------------------------------------
CREATE MULTISET TABLE CARLOS.PRUEBA01 ,NO FALLBACK ,
     NO BEFORE JOURNAL,
     NO AFTER JOURNAL,
     CHECKSUM = DEFAULT,
     DEFAULT MERGEBLOCKRATIO
     (
      ID_N INTEGER NOT NULL,
      TS_TIMESTAMP TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0))
PRIMARY INDEX ( ID_N );

A mí esto me suena a ‘bug‘… y ocurre en las versiones 13.10 y 14.10 (¡!).

Así que, cuidadito con los ALTER TABLE añadiendo columnas TIMESTAMP WITH DEFAULT, te puedes llevar la misma sorpresa que me llevé yo hoy…

Saludos.

Carlos.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: