Skip to content
This repository has been archived by the owner on Mar 11, 2018. It is now read-only.

Fix for bug preventing 4.6.1 update. See Issue 117. #121

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 3 additions & 25 deletions wp-content/db.php
Original file line number Diff line number Diff line change
@@ -1,28 +1,9 @@
<?php
/*
Added Development Environment/localhost check to return localhost URL
inspired by http://codex.wordpress.org/Running_a_Development_Copy_of_WordPress
Author: @khbites
*/

add_filter ( 'pre_option_home', 'test_localhosts' );
add_filter ( 'pre_option_siteurl', 'test_localhosts' );
function test_localhosts( ) {
/* DB URL is set with SetEnv in Apache https://github.com/mhoofman/wordpress-heroku#linux-or-manual-apache-config */

if (preg_match('/localhost/',$_ENV['DATABASE_URL'])) {
preg_match('/(.*)\/wp-.*\/(\w*\.php)+$/', $_SERVER['REQUEST_URI'], $path);
return ("http://" . $_SERVER['HTTP_HOST'] . $path[1]);
}

else return false; // act as normal; will pull main site info from db
}

/*
Plugin Name: PostgreSQL for WordPress (PG4WP)
Plugin URI: http://www.hawkix.net
Description: PG4WP is a special 'plugin' enabling WordPress to use a PostgreSQL database.
Version: 1.3.1
Version: 1.3.1+
Author: Hawk__
Author URI: http://www.hawkix.net
License: GPLv2 or newer.
Expand All @@ -37,14 +18,11 @@ function test_localhosts( ) {
define( 'PG4WP_DEBUG', false);
// If you just want to log queries that generate errors, leave PG4WP_DEBUG to "false"
// and set this to true
define( 'PG4WP_LOG_ERRORS', false);
define( 'PG4WP_LOG_ERRORS', true);

// If you want to allow insecure configuration (from the author point of view) to work with PG4WP,
// change this to true
define( 'PG4WP_INSECURE', true);

// Not entirely sure why this needs to be set, but it seems to be required since wp version 4
define('WP_USE_EXT_MYSQL', true);
define( 'PG4WP_INSECURE', false);

// This defines the directory where PG4WP files are loaded from
// 2 places checked : wp-content and wp-content/plugins
Expand Down
4 changes: 3 additions & 1 deletion wp-content/pg4wp/core.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@
'<?php' => '',
'?>' => '',
);
// Ensure class uses the replaced mysql_ functions rather than mysqli_
define( 'WP_USE_EXT_MYSQL', true);
eval( str_replace( array_keys($replaces), array_values($replaces), file_get_contents(ABSPATH.'/wp-includes/wp-db.php')));

// Create wpdb object if not already done
if (! isset($wpdb))
if (! isset($wpdb) && defined('DB_USER'))
$wpdb = new wpdb2( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
4 changes: 2 additions & 2 deletions wp-content/pg4wp/db.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Plugin Name: PostgreSQL for WordPress (PG4WP)
Plugin URI: http://www.hawkix.net
Description: PG4WP is a special 'plugin' enabling WordPress to use a PostgreSQL database.
Version: 1.3.1
Version: 1.3.1+
Author: Hawk__
Author URI: http://www.hawkix.net
License: GPLv2 or newer.
Expand All @@ -18,7 +18,7 @@
define( 'PG4WP_DEBUG', false);
// If you just want to log queries that generate errors, leave PG4WP_DEBUG to "false"
// and set this to true
define( 'PG4WP_LOG_ERRORS', false);
define( 'PG4WP_LOG_ERRORS', true);

// If you want to allow insecure configuration (from the author point of view) to work with PG4WP,
// change this to true
Expand Down
121 changes: 105 additions & 16 deletions wp-content/pg4wp/driver_pgsql.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
$GLOBALS['pg4wp_last_insert'] = '';
$GLOBALS['pg4wp_connstr'] = '';
$GLOBALS['pg4wp_conn'] = false;


function wpsql_ping($conn)
{ return pg_ping($conn); }
function wpsql_num_rows($result)
{ return pg_num_rows($result); }
function wpsql_numrows($result)
Expand Down Expand Up @@ -61,7 +63,6 @@ function wpsql_result($result, $i, $fieldname)
{ return pg_fetch_result($result, $i, $fieldname); }
****/

// This is a fake connection except during installation
function wpsql_connect($dbserver, $dbuser, $dbpass)
{
$GLOBALS['pg4wp_connstr'] = '';
Expand All @@ -77,19 +78,19 @@ function wpsql_connect($dbserver, $dbuser, $dbpass)
elseif( !PG4WP_INSECURE)
wp_die( 'Connecting to your PostgreSQL database without a password is considered insecure.
<br />If you want to do it anyway, please set "PG4WP_INSECURE" to true in your "db.php" file.' );

// While installing, we test the connection to 'template1' (as we don't know the effective dbname yet)
if( defined('WP_INSTALLING') && WP_INSTALLING)
return wpsql_select_db(DB_NAME); // Heroku Postgres 9.1 does not allow connection to 'template1'

return 1;

// PostgreSQL must connect to a specific database (unlike MySQL)
// Guess at one here and reconnect as required in wpsql_select_db
$dbname = defined('DB_NAME') && DB_NAME ? DB_NAME : 'template1';
return pg_connect( $GLOBALS['pg4wp_connstr'].' dbname='.$dbname);
}

// The effective connection happens here
function wpsql_select_db($dbname, $connection_id = 0)
{
$pg_connstr = $GLOBALS['pg4wp_connstr'].' dbname='.$dbname;

// Note: pg_connect returns existing connection for same connstr
$GLOBALS['pg4wp_conn'] = pg_connect($pg_connstr);

if( $GLOBALS['pg4wp_conn'])
Expand Down Expand Up @@ -183,7 +184,9 @@ function wpsql_insert_id($lnk = NULL)
elseif( PG4WP_DEBUG || PG4WP_ERROR_LOG)
{
$log = '['.microtime(true)."] wpsql_insert_id() was called with '$table' and '$ins_field'".
" and generated an error. The latest INSERT query was :\n'$lastq'\n";
" and returned the error:\n".pg_last_error().
"\nFor the query:\n".$sql.
"\nThe latest INSERT query was :\n'$lastq'\n";
error_log( $log, 3, PG4WP_LOG.'pg4wp_errors.log');
}
}
Expand All @@ -195,6 +198,7 @@ function wpsql_insert_id($lnk = NULL)

function pg4wp_rewrite( $sql)
{
// Note: Can be called from constructor before $wpdb is set
global $wpdb;

$logto = 'queries';
Expand Down Expand Up @@ -226,9 +230,34 @@ function pg4wp_rewrite( $sql)
$pattern = '/SELECT\s+([^\s]+)\s+(FROM.+)/';
$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);

// Handle CAST( ... AS CHAR)
$sql = preg_replace( '/CAST\((.+) AS CHAR\)/', 'CAST($1 AS TEXT)', $sql);

// Handle CAST( ... AS SIGNED)
$sql = preg_replace( '/CAST\((.+) AS SIGNED\)/', 'CAST($1 AS INTEGER)', $sql);

// Handle COUNT(*)...ORDER BY...
$sql = preg_replace( '/COUNT(.+)ORDER BY.+/s', 'COUNT$1', $sql);
Expand All @@ -249,6 +278,9 @@ function pg4wp_rewrite( $sql)

$pattern = '/DATE_ADD[ ]*\(([^,]+),([^\)]+)\)/';
$sql = preg_replace( $pattern, '($1 + $2)', $sql);

$pattern = '/GROUP_CONCAT\(([^()]*(\(((?>[^()]+)|(?-2))*\))?[^()]*)\)/x';
$sql = preg_replace( $pattern, "string_agg($1, ',')", $sql);

// UNIX_TIMESTAMP in MYSQL returns an integer
$pattern = '/UNIX_TIMESTAMP\(([^\)]+)\)/';
Expand All @@ -270,8 +302,15 @@ function pg4wp_rewrite( $sql)
// MySQL 'IF' conversion - Note : NULLIF doesn't need to be corrected
$pattern = '/ (?<!NULL)IF[ ]*\(([^,]+),([^,]+),([^\)]+)\)/';
$sql = preg_replace( $pattern, ' CASE WHEN $1 THEN $2 ELSE $3 END', $sql);

// Act like MySQL default configuration, where sql_mode is ""
$pattern = '/@@SESSION.sql_mode/';
$sql = preg_replace( $pattern, "''", $sql);

$sql = str_replace('GROUP BY '.$wpdb->prefix.'posts.ID', '' , $sql);
if( isset($wpdb))
{
$sql = str_replace('GROUP BY '.$wpdb->prefix.'posts.ID', '' , $sql);
}
$sql = str_replace("!= ''", '<> 0', $sql);

// MySQL 'LIKE' is case insensitive by default, whereas PostgreSQL 'LIKE' is
Expand All @@ -285,9 +324,28 @@ function pg4wp_rewrite( $sql)
$sql = str_replace( 'post_date_gmt > 1970', 'post_date_gmt > to_timestamp (\'1970\')', $sql);

// Akismet sometimes doesn't write 'comment_ID' with 'ID' in capitals where needed ...
if( false !== strpos( $sql, $wpdb->comments))
if( isset($wpdb) && false !== strpos( $sql, $wpdb->comments))
$sql = str_replace(' comment_id ', ' comment_ID ', $sql);


// MySQL allows integers to be used as boolean expressions
// where 0 is false and all other values are true.
//
// Although this could occur anywhere with any number, so far it
// has only been observed as top-level expressions in the WHERE
// clause and only with 0. For performance, limit current
// replacements to that.
$pattern_after_where = '(?:\s*$|\s+(GROUP|HAVING|ORDER|LIMIT|PROCEDURE|INTO|FOR|LOCK))';
$pattern = '/(WHERE\s+)0(\s+AND|\s+OR|' . $pattern_after_where . ')/';
$sql = preg_replace( $pattern, '$1false$2', $sql);

$pattern = '/(AND\s+|OR\s+)0(' . $pattern_after_where . ')/';
$sql = preg_replace( $pattern, '$1false$2', $sql);

// MySQL supports strings as names, PostgreSQL needs identifiers.
// Limit to after closing parenthesis to reduce false-positives
// Currently only an issue for nextgen-gallery plugin
$pattern = '/\) AS \'([^\']+)\'/';
$sql = preg_replace( $pattern, ') AS "$1"', $sql);
} // SELECT
elseif( 0 === strpos($sql, 'UPDATE'))
{
Expand All @@ -299,9 +357,12 @@ function pg4wp_rewrite( $sql)
$pattern = '/[ ]*`([^` ]+)`[ ]*=/';
$sql = preg_replace( $pattern, ' $1 =', $sql);

// Those are used when we need to set the date to now() in gmt time
$sql = str_replace( "'0000-00-00 00:00:00'", 'now() AT TIME ZONE \'gmt\'', $sql);

// For correct ID quoting
$pattern = '/[ ]*([^ ]*ID[^ ]*)[ ]*=/';
$sql = preg_replace( $pattern, ' "$1" =', $sql);
$pattern = '/(,|\s)[ ]*([^ \']*ID[^ \']*)[ ]*=/';
$sql = preg_replace( $pattern, '$1 "$2" =', $sql);

// This will avoid modifications to anything following ' SET '
list($sql,$end) = explode( ' SET ', $sql, 2);
Expand Down Expand Up @@ -348,6 +409,13 @@ function pg4wp_rewrite( $sql)
$sql = 'DELETE FROM '.$table.' WHERE '.$matches[2].' = '.$matches[3].';'.$sql;
}
}
elseif( 0 === strpos($sql, 'INSERT IGNORE'))
{
// Note: Requires PostgreSQL 9.0 and USAGE privilege.
// Could do query-specific rewrite using SELECT without FROM
// as in http://stackoverflow.com/a/13342031
$sql = 'DO $$BEGIN INSERT'.substr($sql, 13).'; EXCEPTION WHEN unique_violation THEN END;$$;';
}

// To avoid Encoding errors when inserting data coming from outside
if( preg_match('/^.{1}/us',$sql,$ar) != 1)
Expand All @@ -365,6 +433,15 @@ function pg4wp_rewrite( $sql)
elseif( 0 === strpos( $sql, 'DELETE' ))
{
$logto = 'DELETE';

// ORDER BY is not supported in DELETE queries, and not required
// when LIMIT is not present
if( false !== strpos( $sql, 'ORDER BY') && false === strpos( $sql, 'LIMIT'))
{
$pattern = '/ORDER BY \S+ (ASC|DESC)?/';
$sql = preg_replace( $pattern, '', $sql);
}

// LIMIT is not allowed in DELETE queries
$sql = str_replace( 'LIMIT 1', '', $sql);
$sql = str_replace( ' REGEXP ', ' ~ ', $sql);
Expand All @@ -375,6 +452,18 @@ function pg4wp_rewrite( $sql)
"(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))
Expand All @@ -399,7 +488,7 @@ function pg4wp_rewrite( $sql)
$sql = "SET NAMES 'utf8'";
}
// Load up upgrade and install functions as required
$begin = substr( $sql, 0, 3);
$begin = strtoupper( substr( $sql, 0, 3));
$search = array( 'SHO', 'ALT', 'DES', 'CRE', 'DRO');
if( in_array($begin, $search))
{
Expand Down Expand Up @@ -455,7 +544,7 @@ function pg4wp_rewrite( $sql)
$pattern = '/INSERT INTO (\w+)\s+\([ a-zA-Z_"]+/';
preg_match($pattern, $sql, $matches);
$GLOBALS['pg4wp_ins_table'] = $matches[1];
$match_list = split(' ', $matches[0]);
$match_list = explode(' ', $matches[0]);
if( $GLOBALS['pg4wp_ins_table'])
{
$GLOBALS['pg4wp_ins_field'] = trim($match_list[3],' () ');
Expand Down
Loading