Sanitizar consultas con cláusulas “IN” con $wpdb en WordPress

Uno de los métodos que incluye la clase wpdb es prepare, que permite preparar una consulta a la base de datos para asegurarnos que se ejecute de forma segura.

Su utilización es bastante sencilla — y si hasta ahora no la estás utilizando deberías leer inmediatamente la sección sobre cómo proteger tus consultas ante ataques de inyección SQL — pero hasta hace poco no había ideado una forma sencilla de preparar consultas con cláusulas IN.

Una solución bastante sencilla que podemos aplicar es la siguiente:

// obtener un listado de IDs de entradas "especiales"
// $special_entries = array(1, 3, 5, 8, 13, [...]);
$special_entries = get_option('my_special_entries');

// ¿cuántas condiciones se van a seleccionar?
$how_many = count($special_entries);

// prepara la cantidad adecuada de reemplazos
// si se buscarán strings, el último parámetro sería '%s'
$placeholders = array_fill(0, $how_many, '%d');

// unir los reemplazos con comas
// $format = '%d, %d, %d, %d, %d, [...]'
$format = implode(', ', $placeholders);

// la consulta
$query = "SELECT ID, post_title, post_name, post_parent FROM $wpdb->posts WHERE post_parent IN($format)";

// obtener los resultados de forma segura
$results = $wpdb->get_results( $wpdb->prepare($query, $special_entries) );

Computer Modern Typewriter, una bella fuente para tu código

Una buena fuente para tu código puede ser tan importante como elegir un buen editor.

Durante algún tiempo he deambulado entre diversas alternativas, como Inconsolata, Ubuntu Mono e incluso la reciente Source Code Pro de Adobe (todas ellas tienen licencias de código abierto y se pueden descargar desde los enlaces indicados).

Pero hoy encontré una nueva que es realmente una belleza: Computer Modern Typewriter.

La fuente es parte de una familia bastante amplia, que incluye variantes con y sin serifas en negritas e itálicas. Tiene soporte para Unicode y es una de las fuentes incluídas originalmente con TeX.

También tiene una licencia de código abierto, y se puede descargar desde su sitio web.

Actualización (28 octubre 2012): en Ubuntu (y supongo que también en otras distribuciones) está disponible Latin Modern, que puedes instalar desde repositorios con apt-get install lmodern.

Generar dumps versionables de la base de datos

Otro tip rápido: si deseas mantener un dump de tu base de datos en algún sistema de control de versiones con mysqldump, siempre utiliza la opción --skip-extended-insert.

¿Por qué? De modo predeterminado, mysqldump utiliza “extended inserts”, en los que una sola gran línea se ocupa de agregar múltiples registros a la base de datos. El problema es que estas sentencias por lo general van en una sola línea, por lo que si cambia cualquier dato en los muchos registros que se insertan en alguna de las tablas, el control de versiones identificará la diferencia de la línea y las diferencias entre cada versión serán muy grandes.

En comparación, al utilizar --skip-extended-insert cada INSERT usa una línea, por lo que sólo se registrarán las diferencias de las filas que tengan cambios. El dump será más grande, pero las diferencias entre cada versión son menores, y se almacenarán de modo más eficiente en tu control de versiones.

Por cierto, si tus tablas son de tipo InnoDB, recuerda también usar la opcion --no-autocommit para mejorar la velocidad de importación del dump.

Mejorar la velocidad de carga de dumps de MySQL con InnoDB

Un tip rápido: si notas que al importar dumps de bases de datos que utilizan InnoDB la carga es mucho más lenta que en bases de datos con MyISAM, puedes mejorar bastante la velocidad de carga con algunas opciones de mysqldump:

  • En primer lugar, está la opción --opt, que habilita una serie de alternativas que hacen que la importación sea bastante rápida…
  • … pero si por alguna razón debes utilizar alguna opción no predeterminada al crear el dump (en mi caso, era --skip-extended-insert), puedes utilizar --no-autocommit, que hace que la importación sea tan rápida como utilizando MyISAM

¿La explicación?

Como InnoDB es transaccional, lleva un registro de cada operación.

Con la primera alternativa, sólo se ejecuta un INSERT por tabla, por lo que no necesita realizar muchas operaciones de registro.

Con la segunda alternativa, a pesar que se indican muchos INSERT, sólo se confirman los cambios una vez por tabla ya que los bloques de INSERT van rodeados con set autocommit=0; y un único COMMIT al final.