From a9edb3a57211a7a641eb7276c558af2c930af268 Mon Sep 17 00:00:00 2001 From: Kevin Locke Date: Sat, 6 Jun 2015 20:33:15 -0600 Subject: [PATCH] [nextgen-gallery] Check ORDER BY in SELECT DISTINCT MySQL supports ordering by columns which do not appear in the field list for a SELECT DISTINCT statement while PostgreSQL does not. This results in errors such as: Error running : SELECT DISTINCT pid , GROUP_CONCAT(CONCAT_WS('@@', meta_key, meta_value)) AS `extras` FROM `wp_ngg_pictures` LEFT OUTER JOIN `wp_postmeta` ON `wp_postmeta`.`post_id` = `extras_post_id` WHERE (`exclude` = 0) AND (`galleryid` IN (2)) GROUP BY wp_ngg_pictures.pid ORDER BY `sortorder` ASC ---- converted to ---- SELECT DISTINCT pid , string_agg(CONCAT_WS('@@', meta_key, meta_value), ',') AS extras FROM wp_ngg_pictures LEFT OUTER JOIN wp_postmeta ON wp_postmeta.post_id = extras_post_id WHERE (exclude = 0) AND (galleryid IN (2)) GROUP BY wp_ngg_pictures.pid ORDER BY sortorder ASC ----> ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list LINE 1: ...yid IN (2)) GROUP BY wp_ngg_pictures.pid ORDER BY sortorder ... ^ To avoid this error, ensure that the field listed in the ORDER BY statement also appears in the SELECT statement. To support GROUP BY statements, ensure that it is aggregated using MIN() to mimic the MySQL behavior. Signed-off-by: Kevin Locke --- pg4wp/driver_pgsql.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pg4wp/driver_pgsql.php b/pg4wp/driver_pgsql.php index 46ba043..2a232bb 100644 --- a/pg4wp/driver_pgsql.php +++ b/pg4wp/driver_pgsql.php @@ -227,6 +227,24 @@ $sql = preg_replace( $pattern, 'SELECT COUNT($1) $2', $sql); } + // Ensure that ORDER BY column appears in SELECT DISTINCT fields + $pattern = '/^SELECT DISTINCT.*ORDER BY\s+(\S+)/'; + if( preg_match( $pattern, $sql, $matches) && + strpos( $sql, $matches[1]) > strpos( $sql, 'ORDER BY') && + false === strpos( $sql, '*')) + { + if( false !== strpos( $sql, 'GROUP BY')) + { + $pattern = '/ FROM /'; + $sql = preg_replace( $pattern, ', MIN('.$matches[1].') AS '.$matches[1].' FROM ', $sql, 1); + } + else + { + $pattern = '/ FROM /'; + $sql = preg_replace( $pattern, ', '.$matches[1].' FROM ', $sql, 1); + } + } + // Convert CONVERT to CAST $pattern = '/CONVERT\(([^()]*(\(((?>[^()]+)|(?-2))*\))?[^()]*),\s*([^\s]+)\)/x'; $sql = preg_replace( $pattern, 'CAST($1 AS $4)', $sql);