From 935a99c429bbbbd46591183d19887626598776d6 Mon Sep 17 00:00:00 2001 From: Kevin Locke Date: Wed, 3 Jun 2015 00:42:27 -0600 Subject: [PATCH] Rewrite multi-table delete of wp_options During schema upgrade, populate_options() deletes all expired transients and their corresponding transient timeouts. The queries produce the following errors: Error running : DELETE a, b FROM wp_options a, wp_options b WHERE a.option_name LIKE '\_transient\_%' AND a.option_name NOT LIKE '\_transient\_timeout\_%' AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) ) AND b.option_value < 1433110465 ---- converted to ---- DELETE a, b FROM wp_options a, wp_options b WHERE a.option_name LIKE '\_transient\_%' AND a.option_name NOT LIKE '\_transient\_timeout\_%' AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) ) AND b.option_value < 1433110465 ----> ERROR: syntax error at or near "a" LINE 1: DELETE a, b FROM wp_options a, wp_options b ^ --------------------- Error running : DELETE a, b FROM wp_options a, wp_options b WHERE a.option_name LIKE '\_site\_transient\_%' AND a.option_name NOT LIKE '\_site\_transient\_timeout\_%' AND b.option_name = CONCAT( '_site_transient_timeout_', SUBSTRING( a.option_name, 17 ) ) AND b.option_value < 1433110465 ---- converted to ---- DELETE a, b FROM wp_options a, wp_options b WHERE a.option_name LIKE '\_site\_transient\_%' AND a.option_name NOT LIKE '\_site\_transient\_timeout\_%' AND b.option_name = CONCAT( '_site_transient_timeout_', SUBSTRING( a.option_name, 17 ) ) AND b.option_value < 1433110465 ----> ERROR: syntax error at or near "a" LINE 1: DELETE a, b FROM wp_options a, wp_options b ^ --------------------- Since PostgreSQL does not support multi-table DELETE statements, significant rewriting must be done. Since I could not think of a good generic way to perform this rewriting, recognize this statement specifically and provide an alternative version. Signed-off-by: Kevin Locke --- pg4wp/driver_pgsql.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pg4wp/driver_pgsql.php b/pg4wp/driver_pgsql.php index a77571c..d8b32fa 100644 --- a/pg4wp/driver_pgsql.php +++ b/pg4wp/driver_pgsql.php @@ -375,6 +375,18 @@ "(SELECT o1.option_id FROM $wpdb->options AS o1, $wpdb->options AS o2 " . "WHERE o1.option_name = o2.option_name " . "AND o1.option_id < o2.option_id)"; + // Rewrite _transient_timeout multi-table delete query + elseif( 0 === strpos( $sql, 'DELETE a, b FROM wp_options a, wp_options b')) + { + $where = substr( $sql, strpos($sql, 'WHERE ') + 6); + $where = rtrim( $where, " \t\n\r;"); + // Fix string/number comparison by adding check and cast + $where = str_replace( 'AND b.option_value', 'AND b.option_value ~ \'^[0-9]+$\' AND CAST(b.option_value AS BIGINT)', $where); + // Mirror WHERE clause to delete both sides of self-join. + $where2 = strtr( $where, array('a.' => 'b.', 'b.' => 'a.')); + $sql = 'DELETE FROM wp_options a USING wp_options b WHERE '. + '('.$where.') OR ('.$where2.');'; + } // Akismet sometimes doesn't write 'comment_ID' with 'ID' in capitals where needed ... if( false !== strpos( $sql, $wpdb->comments))