Bug db_query datetime columns ?

killua99's picture

Hola,

Como desarrollador de Drupal abro esta discusión en busca de ayuda y/o confirmación sobre un posible bug que estoy viendo que se me esta presentando a la hora de crear un modulo.

Explico el bug que me esta ocurriendo.

Síntomas:

A la hora de crear un SQL para obtener una simple fecha la función db_query me retorna sin el día correcto por ejemplo:

<?php
$sql
= 'SELECT DATE_FORMAT(date_added,\'%d-%m-%Y\') as date FROM {tabla_test} GROUP BY date_added ORDER BY date_added LIMIT 1'; // LIMIT 1 para obtener solo un resultado para test
$res = db_query($sql);

print
db_result($res); // resultado 0-06-2010
?>

Sin embargo al usar la función _db_query(). Regresa el valor correcto (08-06-2010) de la fecha seleccionada.

La causa de esto no la encuentro por ningún motivo. Al revisar en el api de drupal sobre db_query observo que revisa si la función posee argumentos o opciones para remplazar según sea el caso.

Mi solución ha sido utilizar _db_query(). Pero quiero confirmar que no este realizando algo erróneo, de ser así que los pasos que este utilizando sean los correctos publicare el issue respecto al db_query(). y la forma en que trata las fechas a la hora de no presentar otro argumento.

La forma de duplicar este error sería el siguiente.

Crear un modulo.
test.info

; $Id: info.info,v 0.1a killua99 Exp $
name = Test bug DATE_FORMAT
description = Test bug with sql DATE_FORMAT and db_query.
package = Aa BUG TEST
core = 6.x
; Information added by drupal.org packaging script on 2009-11-05
version = "6.x-0.1a"
core = "6.x"
project = "Test bug"

test.install

<?php
// $Id: test.install v 0.1a killua99 Exp $

/<em>
* @
file Prueba sobre el posible bug con DATE_FORMAT y db_query().
*/

/</
em>
*
Implementation of hook_schema().
<
em>/
function
test_schema(){
 
$schema = array();

 
$schema['test_handled'] = array(
   
'description' => 'Test table',
   
'fields'      => array(
     
'rid'     => array(
       
'description' => 'Identifier',
       
'type'        => 'serial',
       
'unsigned'    => TRUE,
       
'not null'    => TRUE,
      ),
     
'nid'     => array(
       
'description' => 'Node ID',
       
'type'        => 'int',
       
'size'        => 'normal',
       
'unsigned'    => TRUE,
       
'not null'    => TRUE,
      ),
     
'vid'     => array(
       
'description' => 'Version ID',
       
'type'        => 'int',
       
'size'        => 'normal',
       
'unsigned'    => TRUE,
       
'not null'    => TRUE,
      ),
     
'date_added'    => array(
       
'description' => 'Creation date',
       
'type'        => 'datetime',
       
'not null'    => TRUE,
      ),
     
'data'    => array(
       
'description' => 'Json data encode',
       
'type'        => 'text',
       
'not null'    => TRUE,
      ),
     
'success' => array(
       
'description' => 'Boolean to confirm',
       
'type'        => 'int',
       
'size'        => 'tiny',
       
'default'     => 1,
       
'not null'    => TRUE,
      ),
    ),
   
'primary key' => array('rid'),
  );

  return
$schema
}

/</
em>
*
Implementation of hook_install().
<
em>/
function
test_install() {

 
// Execute install schema
 
drupal_install_schema('test');

}

/</
em>
*
Implementation of hook_uninstall().
*/
function
test_uninstall() {

 
drupal_uninstall_schema('test');
}

// Recordar que el cierre del PHP ? > es una mala practica para los módulos. Lo uso en este caso para detallar los colores de PHP
?>

test.module

<?php
// $Id: test.module v 0.1a killua Exp $
/<em>
* @
file Functions
*/

/</
em>
*
Implementation hook_perm().
<
em>/
function
test_perm() {
  return array(
   
'access test',
  );
}


/</
em>
*
Implementation of hook_menu().
<
em>/
function
test_menu(){
 
$items = array();

 
$items['admin/test_bug'] = array(
   
'title'                    => t('Test DATE_FORMAT'),
   
'description'           => t('Test module bug DATE_FORMAT with db_query'),
   
'access arguments' => array('access test'),
   
'page callback'       => 'test_page',
   
'type'                   => MENU_NORMAL_ITEM,
  );

  return
$items;
}

/</
em>
*
*/
function
test_page(){
 
$output = '';

 
$headers = array(t('Date with db_query'),t('Date with _db_query'));

 
$sql = 'SELECT DATE_FORMAT(date_added,\'%d-%m-%Y\') as date FROM {test_handled} GROUP BY date_added ORDER BY date_added LIMIT 1';
 
$res = db_query($sql);
 
$sql_x = 'SELECT DATE_FORMAT(date_added,\'%d-%m-%Y\') as date FROM test_handled GROUP BY date_added ORDER BY date_added LIMIT 1';
 
$res_x = _db_query($sql_x);

 
$tr[] = array(
   
db_result($res),
 
db_result($res_x)
  );

 
$output .= theme('table',$headers,$tr);


  return
$output;
}

// Recordar que el cierre del PHP ? > es una mala practica para los módulos. Lo uso en este caso para detallar los colores de PHP
?>

Una vez creado el modulo hay que ingresar registros a parte. Utilice el phpmyadmin para realizar esta tarea.

Luego de activar el modulo podrán notar que al realizar la llamada del campo datetime el día de hoy 09-06-2010 se presenta como 0-06-2010 utilizando db_query(). en cambio _db_query(). regresa el valor correcto 08-06-2010.

No se si me este perdiendo alguna propiedad básica de como generar un SQL, o como es el manejo del date time con db_query().

Saludos.

Comments

Confusión con placeholders de db_query()

markus_petrux's picture

La función db_query() va a querer substituir %d por un argumento de función, por lo que el formato de fecha escrito de ese modo se "estropea".

Como alternativa, se me ocurren dos maneras de enfocarlo:

1) Utiliza %% para que db_query() no se confunda entre sus placeholders y el formato de fecha:

<?php
$sql
= "SELECT DATE_FORMAT(date_added,'%%d-%%m-%%Y') as date FROM {test_handled} GROUP BY date_added ORDER BY date_added LIMIT 1";
?>

2) Pásale el formato de fecha como un argumento de tipo %s para db_query():

<?php
$sql
= "SELECT DATE_FORMAT(date_added,'%s') as date FROM {test_handled} GROUP BY date_added ORDER BY date_added LIMIT 1";
$res = db_query($sql, '%d-%m-%Y');
?>

Comprendo el %%

killua99's picture

Ya logro captar mi problema.

La confusión que sufre db_query al no saber interpretar el % literalmente y no como placeholder.

La primera solución que me das me gusta mas que la otra. Así me ahorro tener que estar identificando de mas.

%% = literalmente %.

Gracias por responder a mi duda.

[at]killua99 ~~

¿Por qué datetime en lugar de int?

gbarrigap's picture

Hola, el tema ya está solucionado, pero me quedó una duda.

¿Por qué usaste datetime en lugar de int? Lo pregunto porque después de haber tenido un par de problemas manipulando fechas, me dí cuenta de que los módulos del core usan un entero para almacenar las fechas mediante unix timestamp. Así es mucho más fácil manipular las fechas con las funciones de presentación que incluye Drupal, como format_date(). De esta forma, la lógica de presentación no se define en la consulta SQL.

Si no sabías eso, espero haber ayudado.

Saludos cordiales.

Use de guia al CCK

killua99's picture

Hola, la verdad es que use de guía la estructura en que el CCK formaba las tablas que contenían datos de fecha. CCK genera en datetime la estructura de datos.

Esa es la razón por el cual uso datetime y no int. Ademas el problema no es el formato si no a la hora de comparar las fechas con los placeholders.

y el uso de los DATE_FORMAT en SQL para no tener que recoger los datos en variables para comprar lo hago directamente en el SQL y me ahorro uso de memoria.

Saludos.

[at]killua99 ~~

Madrid

Group organizers

Group events

Add to calendar

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: