Migrate install rewriting to new rewriters
This commit is contained in:
@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
// This is required by class-wpdb so we must load it first
|
||||
require_once ABSPATH . '/wp-includes/version.php';
|
||||
require_once ABSPATH . '/wp-includes/cache.php';
|
||||
require_once ABSPATH . '/wp-includes/l10n.php';
|
||||
|
||||
@ -20,14 +21,6 @@ if (!function_exists('wpsql_is_resource')) {
|
||||
}
|
||||
}
|
||||
|
||||
// Logs are put in the pg4wp directory
|
||||
define( 'PG4WP_LOG', PG4WP_ROOT.'/logs/');
|
||||
// Check if the logs directory is needed and exists or create it if possible
|
||||
if( (PG4WP_DEBUG || PG4WP_LOG_ERRORS) &&
|
||||
!file_exists( PG4WP_LOG) &&
|
||||
is_writable(dirname( PG4WP_LOG)))
|
||||
mkdir( PG4WP_LOG);
|
||||
|
||||
// Load the driver defined in 'db.php'
|
||||
require_once(PG4WP_ROOT . '/driver_' . DB_DRIVER . '.php');
|
||||
|
||||
|
34
pg4wp/db.php
34
pg4wp/db.php
@ -1,11 +1,11 @@
|
||||
<?php
|
||||
/*
|
||||
Plugin Name: PostgreSQL for WordPress (PG4WP)
|
||||
Plugin URI: https://github.com/PostgreSQL-For-Wordpress/postgresql-for-wordpress
|
||||
Description: PG4WP is a special plugin enabling WordPress to use a PostgreSQL database.
|
||||
Version: v2.2
|
||||
Author: PostgreSQL-For-Wordpress
|
||||
Author URI: https://github.com/PostgreSQL-For-Wordpress
|
||||
Plugin URI: http://www.hawkix.net
|
||||
Description: PG4WP is a special 'plugin' enabling WordPress to use a PostgreSQL database.
|
||||
Version: 1.3.1+
|
||||
Author: Hawk__
|
||||
Author URI: http://www.hawkix.net
|
||||
License: GPLv2 or newer.
|
||||
*/
|
||||
|
||||
@ -36,16 +36,28 @@ if(!defined('PG4WP_ROOT')) {
|
||||
|
||||
// This defines the directory where PG4WP files are loaded from
|
||||
// 3 places checked : wp-content, wp-content/plugins and the base directory
|
||||
if(file_exists(ABSPATH . '/wp-content/pg4wp')) {
|
||||
define('PG4WP_ROOT', ABSPATH . '/wp-content/pg4wp');
|
||||
} elseif(file_exists(ABSPATH . '/wp-content/plugins/pg4wp')) {
|
||||
define('PG4WP_ROOT', ABSPATH . '/wp-content/plugins/pg4wp');
|
||||
} elseif(file_exists(ABSPATH . '/pg4wp')) {
|
||||
define('PG4WP_ROOT', ABSPATH . '/pg4wp');
|
||||
if(file_exists(ABSPATH . 'wp-content/pg4wp')) {
|
||||
define('PG4WP_ROOT', ABSPATH . 'wp-content/pg4wp');
|
||||
} elseif(file_exists(ABSPATH . 'wp-content/plugins/pg4wp')) {
|
||||
define('PG4WP_ROOT', ABSPATH . 'wp-content/plugins/pg4wp');
|
||||
} elseif(file_exists(ABSPATH . 'pg4wp')) {
|
||||
define('PG4WP_ROOT', ABSPATH . 'pg4wp');
|
||||
} else {
|
||||
die('PG4WP file directory not found');
|
||||
}
|
||||
|
||||
// Logs are put in the pg4wp directory
|
||||
if (!defined('PG4WP_LOG'))
|
||||
{
|
||||
define('PG4WP_LOG', PG4WP_ROOT . '/logs/');
|
||||
}
|
||||
// Check if the logs directory is needed and exists or create it if possible
|
||||
if((PG4WP_DEBUG || PG4WP_LOG_ERRORS) &&
|
||||
!file_exists(PG4WP_LOG) &&
|
||||
is_writable(dirname(PG4WP_LOG))) {
|
||||
mkdir(PG4WP_LOG);
|
||||
}
|
||||
|
||||
// Here happens all the magic
|
||||
require_once(PG4WP_ROOT . '/core.php');
|
||||
} // Protection against multiple loading
|
||||
|
@ -1,297 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @package PostgreSQL_For_Wordpress
|
||||
* @version $Id$
|
||||
* @author Hawk__, www.hawkix.net
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file registers functions used only when installing or upgrading WordPress
|
||||
*/
|
||||
|
||||
// List of types translations (the key is the mysql one, the value is the text to use instead)
|
||||
$GLOBALS['pg4wp_ttr'] = array(
|
||||
'bigint(20)' => 'bigint',
|
||||
'bigint(10)' => 'int',
|
||||
'int(11)' => 'int',
|
||||
'tinytext' => 'text',
|
||||
'mediumtext' => 'text',
|
||||
'longtext' => 'text',
|
||||
'unsigned' => '',
|
||||
'gmt datetime NOT NULL default \'0000-00-00 00:00:00\'' => 'gmt timestamp NOT NULL DEFAULT timezone(\'gmt\'::text, now())',
|
||||
'default \'0000-00-00 00:00:00\'' => 'DEFAULT now()',
|
||||
'\'0000-00-00 00:00:00\'' => 'now()',
|
||||
'datetime' => 'timestamp',
|
||||
'DEFAULT CHARACTER SET utf8' => '',
|
||||
|
||||
// WP 2.7.1 compatibility
|
||||
'int(4)' => 'smallint',
|
||||
|
||||
// For WPMU (starting with WP 3.2)
|
||||
'tinyint(2)' => 'smallint',
|
||||
'tinyint(1)' => 'smallint',
|
||||
"enum('0','1')" => 'smallint',
|
||||
'COLLATE utf8_general_ci' => '',
|
||||
|
||||
// For flash-album-gallery plugin
|
||||
'tinyint' => 'smallint',
|
||||
);
|
||||
|
||||
function pg4wp_installing( $sql, &$logto)
|
||||
{
|
||||
global $wpdb;
|
||||
|
||||
// Emulate SHOW commands
|
||||
if( 0 === strpos( $sql, 'SHOW') || 0 === strpos( $sql, 'show'))
|
||||
{
|
||||
// SHOW VARIABLES LIKE emulation for sql_mode
|
||||
// Used by nextgen-gallery plugin
|
||||
if( 0 === strpos( $sql, "SHOW VARIABLES LIKE 'sql_mode'"))
|
||||
{
|
||||
// Act like MySQL default configuration, where sql_mode is ""
|
||||
$sql = 'SELECT \'sql_mode\' AS "Variable_name", \'\' AS "Value";';
|
||||
}
|
||||
// SHOW COLUMNS emulation
|
||||
elseif( preg_match('/SHOW\s+(FULL\s+)?COLUMNS\s+(?:FROM\s+|IN\s+)`?(\w+)`?(?:\s+LIKE\s+(.+)|\s+WHERE\s+(.+))?/i', $sql, $matches))
|
||||
{
|
||||
$logto = 'SHOWCOLUMN';
|
||||
$full = $matches[1];
|
||||
$table = $matches[2];
|
||||
$like = isset($matches[3]) ? $matches[3] : FALSE;
|
||||
$where = isset($matches[4]) ? $matches[4] : FALSE;
|
||||
// Wrap as sub-query to emulate WHERE behavior
|
||||
$sql = ($where ? 'SELECT * FROM (' : '').
|
||||
'SELECT column_name as "Field",
|
||||
data_type as "Type",'.($full ? '
|
||||
NULL as "Collation",' : '').'
|
||||
is_nullable as "Null",
|
||||
\'\' as "Key",
|
||||
column_default as "Default",
|
||||
\'\' as "Extra"'.($full ? ',
|
||||
\'select,insert,update,references\' as "Privileges",
|
||||
\'\' as "Comment"' : '').'
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = \''.$table.'\''.($like ? '
|
||||
AND column_name LIKE '.$like : '').($where ? ') AS columns
|
||||
WHERE '.$where : '').';';
|
||||
}
|
||||
// SHOW INDEX emulation
|
||||
elseif( 0 === strpos( $sql, 'SHOW INDEX'))
|
||||
{
|
||||
$logto = 'SHOWINDEX';
|
||||
$pattern = '/SHOW INDEX FROM\s+(\w+)/';
|
||||
preg_match( $pattern, $sql, $matches);
|
||||
$table = $matches[1];
|
||||
// Note: Row order must be in column index position order
|
||||
$sql = 'SELECT bc.relname AS "Table",
|
||||
CASE WHEN i.indisunique THEN \'0\' ELSE \'1\' END AS "Non_unique",
|
||||
CASE WHEN i.indisprimary THEN \'PRIMARY\' WHEN bc.relname LIKE \'%usermeta\' AND ic.relname = \'umeta_key\'
|
||||
THEN \'meta_key\' ELSE REPLACE( ic.relname, \''.$table.'_\', \'\') END AS "Key_name",
|
||||
a.attname AS "Column_name",
|
||||
NULL AS "Sub_part"
|
||||
FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a
|
||||
WHERE bc.oid = i.indrelid
|
||||
AND ic.oid = i.indexrelid
|
||||
AND (i.indkey[0] = a.attnum OR i.indkey[1] = a.attnum OR i.indkey[2] = a.attnum OR i.indkey[3] = a.attnum OR i.indkey[4] = a.attnum OR i.indkey[5] = a.attnum OR i.indkey[6] = a.attnum OR i.indkey[7] = a.attnum)
|
||||
AND a.attrelid = bc.oid
|
||||
AND bc.relname = \''.$table.'\'
|
||||
ORDER BY "Key_name", CASE a.attnum
|
||||
WHEN i.indkey[0] THEN 0
|
||||
WHEN i.indkey[1] THEN 1
|
||||
WHEN i.indkey[2] THEN 2
|
||||
WHEN i.indkey[3] THEN 3
|
||||
WHEN i.indkey[4] THEN 4
|
||||
WHEN i.indkey[5] THEN 5
|
||||
WHEN i.indkey[6] THEN 6
|
||||
WHEN i.indkey[7] THEN 7
|
||||
END;';
|
||||
}
|
||||
// SHOW TABLES emulation
|
||||
elseif( preg_match('/SHOW\s+(FULL\s+)?TABLES\s+(?:LIKE\s+(.+)|WHERE\s+(.+))?/i', $sql, $matches))
|
||||
{
|
||||
$logto = 'SHOWTABLES';
|
||||
$full = $matches[1];
|
||||
$like = $matches[2];
|
||||
$where = $matches[3];
|
||||
// Wrap as sub-query to emulate WHERE behavior
|
||||
$sql = ($where ? 'SELECT * FROM (' : '').
|
||||
'SELECT table_name as "Tables_in_'.$wpdb->dbname.'"'.($full ? ',
|
||||
table_type AS "Table_type"' : '').'
|
||||
FROM information_schema.tables'.($like ? '
|
||||
WHERE table_name LIKE '.$like : '').($where ? ') AS tables
|
||||
WHERE '.$where : '').';';
|
||||
}
|
||||
}
|
||||
// Table alteration
|
||||
elseif( 0 === strpos( $sql, 'ALTER TABLE'))
|
||||
{
|
||||
$logto = 'ALTER';
|
||||
$pattern = '/ALTER TABLE\s+(\w+)\s+CHANGE COLUMN\s+([^\s]+)\s+([^\s]+)\s+([^ ]+)( unsigned|)\s*(NOT NULL|)\s*(default (.+)|)/';
|
||||
if( 1 === preg_match( $pattern, $sql, $matches))
|
||||
{
|
||||
$table = $matches[1];
|
||||
$col = $matches[2];
|
||||
$newname = $matches[3];
|
||||
$type = strtolower($matches[4]);
|
||||
if( isset($GLOBALS['pg4wp_ttr'][$type]))
|
||||
$type = $GLOBALS['pg4wp_ttr'][$type];
|
||||
$unsigned = $matches[5];
|
||||
$notnull = $matches[6];
|
||||
$default = $matches[7];
|
||||
$defval = $matches[8];
|
||||
if( isset($GLOBALS['pg4wp_ttr'][$defval]))
|
||||
$defval = $GLOBALS['pg4wp_ttr'][$defval];
|
||||
$newq = "ALTER TABLE $table ALTER COLUMN $col TYPE $type";
|
||||
if( !empty($notnull))
|
||||
$newq .= ", ALTER COLUMN $col SET NOT NULL";
|
||||
if( !empty($default))
|
||||
$newq .= ", ALTER COLUMN $col SET DEFAULT $defval";
|
||||
if( $col != $newname)
|
||||
$newq .= ";ALTER TABLE $table RENAME COLUMN $col TO $newcol;";
|
||||
$sql = $newq;
|
||||
}
|
||||
$pattern = '/ALTER TABLE\s+(\w+)\s+ALTER COLUMN\s+/';
|
||||
if( 1 === preg_match( $pattern, $sql))
|
||||
{
|
||||
// Translate default values
|
||||
$sql = str_replace(
|
||||
array_keys($GLOBALS['pg4wp_ttr']), array_values($GLOBALS['pg4wp_ttr']), $sql);
|
||||
}
|
||||
$pattern = '/ALTER TABLE\s+(\w+)\s+ADD COLUMN\s+([^\s]+)\s+([^ ]+)( unsigned|)\s+(NOT NULL|)\s*(default (.+)|)/';
|
||||
if( 1 === preg_match( $pattern, $sql, $matches))
|
||||
{
|
||||
$table = $matches[1];
|
||||
$col = $matches[2];
|
||||
$type = strtolower($matches[3]);
|
||||
if( isset($GLOBALS['pg4wp_ttr'][$type]))
|
||||
$type = $GLOBALS['pg4wp_ttr'][$type];
|
||||
$unsigned = $matches[4];
|
||||
$notnull = $matches[5];
|
||||
$default = $matches[6];
|
||||
$defval = $matches[7];
|
||||
if( isset($GLOBALS['pg4wp_ttr'][$defval]))
|
||||
$defval = $GLOBALS['pg4wp_ttr'][$defval];
|
||||
$newq = "ALTER TABLE $table ADD COLUMN $col $type";
|
||||
if( !empty($default))
|
||||
$newq .= " DEFAULT $defval";
|
||||
if( !empty($notnull))
|
||||
$newq .= " NOT NULL";
|
||||
$sql = $newq;
|
||||
}
|
||||
$pattern = '/ALTER TABLE\s+(\w+)\s+ADD (UNIQUE |)KEY\s+([^\s]+)\s+\(((?:[^\(\)]+|\([^\(\)]+\))+)\)/';
|
||||
if( 1 === preg_match( $pattern, $sql, $matches))
|
||||
{
|
||||
$table = $matches[1];
|
||||
$unique = $matches[2];
|
||||
$index = $matches[3];
|
||||
$columns = $matches[4];
|
||||
|
||||
// Remove prefix indexing
|
||||
// Rarely used and apparently unnecessary for current uses
|
||||
$columns = preg_replace( '/\([^\)]*\)/', '', $columns);
|
||||
|
||||
// Workaround for index name duplicate
|
||||
$index = $table.'_'.$index;
|
||||
$sql = "CREATE {$unique}INDEX $index ON $table ($columns)";
|
||||
}
|
||||
$pattern = '/ALTER TABLE\s+(\w+)\s+DROP INDEX\s+([^\s]+)/';
|
||||
if( 1 === preg_match( $pattern, $sql, $matches))
|
||||
{
|
||||
$table = $matches[1];
|
||||
$index = $matches[2];
|
||||
$sql = "DROP INDEX ${table}_${index}";
|
||||
}
|
||||
$pattern = '/ALTER TABLE\s+(\w+)\s+DROP PRIMARY KEY/';
|
||||
if( 1 === preg_match( $pattern, $sql, $matches))
|
||||
{
|
||||
$table = $matches[1];
|
||||
$sql = "ALTER TABLE ${table} DROP CONSTRAINT ${table}_pkey";
|
||||
}
|
||||
}
|
||||
// Table description
|
||||
elseif( 0 === strpos( $sql, 'DESCRIBE'))
|
||||
{
|
||||
$logto = 'DESCRIBE';
|
||||
preg_match( '/DESCRIBE\s+(\w+)/', $sql, $matches);
|
||||
$table_name = $matches[1];
|
||||
$sql = "SELECT pg_attribute.attname AS \"Field\",
|
||||
CASE pg_type.typname
|
||||
WHEN 'int2' THEN 'int(4)'
|
||||
WHEN 'int4' THEN 'int(11)'
|
||||
WHEN 'int8' THEN 'bigint(20) unsigned'
|
||||
WHEN 'varchar' THEN 'varchar(' || pg_attribute.atttypmod-4 || ')'
|
||||
WHEN 'timestamp' THEN 'datetime'
|
||||
WHEN 'text' THEN 'longtext'
|
||||
ELSE pg_type.typname
|
||||
END AS \"Type\",
|
||||
CASE WHEN pg_attribute.attnotnull THEN ''
|
||||
ELSE 'YES'
|
||||
END AS \"Null\",
|
||||
CASE pg_type.typname
|
||||
WHEN 'varchar' THEN substring(pg_get_expr(pg_attrdef.adbin, pg_attrdef.adrelid) FROM '^''(.*)''.*$')
|
||||
WHEN 'timestamp' THEN CASE WHEN pg_get_expr(pg_attrdef.adbin, pg_attrdef.adrelid) LIKE '%now()%' THEN '0000-00-00 00:00:00' ELSE pg_get_expr(pg_attrdef.adbin, pg_attrdef.adrelid) END
|
||||
ELSE pg_get_expr(pg_attrdef.adbin, pg_attrdef.adrelid)
|
||||
END AS \"Default\"
|
||||
FROM pg_class
|
||||
INNER JOIN pg_attribute
|
||||
ON (pg_class.oid=pg_attribute.attrelid)
|
||||
INNER JOIN pg_type
|
||||
ON (pg_attribute.atttypid=pg_type.oid)
|
||||
LEFT JOIN pg_attrdef
|
||||
ON (pg_class.oid=pg_attrdef.adrelid AND pg_attribute.attnum=pg_attrdef.adnum)
|
||||
WHERE pg_class.relname='$table_name' AND pg_attribute.attnum>=1 AND NOT pg_attribute.attisdropped;";
|
||||
} // DESCRIBE
|
||||
// Fix table creations
|
||||
elseif( 0 === strpos($sql, 'CREATE TABLE'))
|
||||
{
|
||||
$logto = 'CREATE';
|
||||
$sql = str_replace( 'CREATE TABLE IF NOT EXISTS ', 'CREATE TABLE ', $sql);
|
||||
$pattern = '/CREATE TABLE [`]?(\w+)[`]?/';
|
||||
preg_match($pattern, $sql, $matches);
|
||||
$table = $matches[1];
|
||||
|
||||
// Remove trailing spaces
|
||||
$sql = trim( $sql).';';
|
||||
|
||||
// Translate types and some other replacements
|
||||
$sql = str_replace(
|
||||
array_keys($GLOBALS['pg4wp_ttr']), array_values($GLOBALS['pg4wp_ttr']), $sql);
|
||||
|
||||
// Fix auto_increment by adding a sequence
|
||||
$pattern = '/int[ ]+NOT NULL auto_increment/';
|
||||
preg_match($pattern, $sql, $matches);
|
||||
if($matches)
|
||||
{
|
||||
$seq = $table . '_seq';
|
||||
$sql = str_replace( 'NOT NULL auto_increment', "NOT NULL DEFAULT nextval('$seq'::text)", $sql);
|
||||
$sql .= "\nCREATE SEQUENCE $seq;";
|
||||
}
|
||||
|
||||
// Support for INDEX creation
|
||||
$pattern = '/,\s+(UNIQUE |)KEY\s+([^\s]+)\s+\(((?:[\w]+(?:\([\d]+\))?[,]?)*)\)/';
|
||||
if( preg_match_all( $pattern, $sql, $matches, PREG_SET_ORDER))
|
||||
foreach( $matches as $match)
|
||||
{
|
||||
$unique = $match[1];
|
||||
$index = $match[2];
|
||||
$columns = $match[3];
|
||||
$columns = preg_replace( '/\(\d+\)/', '', $columns);
|
||||
// Workaround for index name duplicate
|
||||
$index = $table.'_'.$index;
|
||||
$sql .= "\nCREATE {$unique}INDEX $index ON $table ($columns);";
|
||||
}
|
||||
// Now remove handled indexes
|
||||
$sql = preg_replace( $pattern, '', $sql);
|
||||
}// CREATE TABLE
|
||||
elseif( 0 === strpos($sql, 'DROP TABLE'))
|
||||
{
|
||||
$logto = 'DROPTABLE';
|
||||
$pattern = '/DROP TABLE.+ [`]?(\w+)[`]?$/';
|
||||
preg_match($pattern, $sql, $matches);
|
||||
$table = $matches[1];
|
||||
$seq = $table . '_seq';
|
||||
$sql .= ";\nDROP SEQUENCE IF EXISTS $seq;";
|
||||
}// DROP TABLE
|
||||
|
||||
return $sql;
|
||||
}
|
@ -12,7 +12,7 @@ spl_autoload_register(function ($className) {
|
||||
function createSQLRewriter(string $sql): AbstractSQLRewriter
|
||||
{
|
||||
$sql = trim($sql);
|
||||
if (preg_match('/^(SELECT|INSERT|UPDATE|DELETE|SHOW TABLES|OPTIMIZE TABLE|SET NAMES|SHOW FULL COLUMNS)\b/i', $sql, $matches)) {
|
||||
if (preg_match('/^(SELECT|INSERT|UPDATE|DELETE|DESCRIBE|ALTER TABLE|CREATE TABLE|DROP TABLE|SHOW INDEX|SHOW VARIABLES|SHOW TABLES|OPTIMIZE TABLE|SET NAMES|SHOW FULL COLUMNS)\b/i', $sql, $matches)) {
|
||||
// Convert to a format suitable for class names (e.g., "SHOW TABLES" becomes "ShowTables")
|
||||
$type = str_replace(' ', '', ucwords(str_replace('_', ' ', strtolower($matches[1]))));
|
||||
$className = $type . 'SQLRewriter';
|
||||
@ -61,7 +61,6 @@ function pg4wp_rewrite($sql)
|
||||
default:
|
||||
}
|
||||
|
||||
$sql = loadInstallFunctions($sql, $logto);
|
||||
$sql = correctMetaValue($sql);
|
||||
$sql = handleInterval($sql);
|
||||
$sql = cleanAndCapitalize($sql);
|
||||
@ -107,24 +106,6 @@ function pg4wp_rewrite($sql)
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load upgrade and install functions as required.
|
||||
*
|
||||
* @param string $sql SQL query string
|
||||
* @param string $logto Logging type
|
||||
* @return string Modified SQL query string
|
||||
*/
|
||||
function loadInstallFunctions($sql, &$logto)
|
||||
{
|
||||
$begin = strtoupper(substr($sql, 0, 3));
|
||||
$search = array('SHO', 'ALT', 'DES', 'CRE', 'DRO');
|
||||
if (in_array($begin, $search)) {
|
||||
require_once(PG4WP_ROOT . '/driver_pgsql_install.php');
|
||||
$sql = pg4wp_installing($sql, $logto);
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the meta_value field for WP 2.9.1 and add type cast.
|
||||
*
|
||||
|
126
pg4wp/rewriters/AlterTableSQLRewriter.php
Normal file
126
pg4wp/rewriters/AlterTableSQLRewriter.php
Normal file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
class AlterTableSQLRewriter extends AbstractSQLRewriter
|
||||
{
|
||||
public function rewrite(): string
|
||||
{
|
||||
// List of types translations (the key is the mysql one, the value is the text to use instead)
|
||||
$typeTranslations = array(
|
||||
'bigint(20)' => 'bigint',
|
||||
'bigint(10)' => 'int',
|
||||
'int(11)' => 'int',
|
||||
'tinytext' => 'text',
|
||||
'mediumtext' => 'text',
|
||||
'longtext' => 'text',
|
||||
'unsigned' => '',
|
||||
'gmt datetime NOT NULL default \'0000-00-00 00:00:00\'' => 'gmt timestamp NOT NULL DEFAULT timezone(\'gmt\'::text, now())',
|
||||
'default \'0000-00-00 00:00:00\'' => 'DEFAULT now()',
|
||||
'\'0000-00-00 00:00:00\'' => 'now()',
|
||||
'datetime' => 'timestamp',
|
||||
'DEFAULT CHARACTER SET utf8' => '',
|
||||
|
||||
// WP 2.7.1 compatibility
|
||||
'int(4)' => 'smallint',
|
||||
|
||||
// For WPMU (starting with WP 3.2)
|
||||
'tinyint(2)' => 'smallint',
|
||||
'tinyint(1)' => 'smallint',
|
||||
"enum('0','1')" => 'smallint',
|
||||
'COLLATE utf8_general_ci' => '',
|
||||
|
||||
// For flash-album-gallery plugin
|
||||
'tinyint' => 'smallint',
|
||||
);
|
||||
$pattern = '/ALTER TABLE\s+(\w+)\s+CHANGE COLUMN\s+([^\s]+)\s+([^\s]+)\s+([^ ]+)( unsigned|)\s*(NOT NULL|)\s*(default (.+)|)/';
|
||||
if(1 === preg_match($pattern, $sql, $matches)) {
|
||||
$table = $matches[1];
|
||||
$col = $matches[2];
|
||||
$newname = $matches[3];
|
||||
$type = strtolower($matches[4]);
|
||||
if(isset($typeTranslations[$type])) {
|
||||
$type = $typeTranslations[$type];
|
||||
}
|
||||
$unsigned = $matches[5];
|
||||
$notnull = $matches[6];
|
||||
$default = $matches[7];
|
||||
$defval = $matches[8];
|
||||
if(isset($typeTranslations[$defval])) {
|
||||
$defval = $typeTranslations[$defval];
|
||||
}
|
||||
$newq = "ALTER TABLE $table ALTER COLUMN $col TYPE $type";
|
||||
if(!empty($notnull)) {
|
||||
$newq .= ", ALTER COLUMN $col SET NOT NULL";
|
||||
}
|
||||
if(!empty($default)) {
|
||||
$newq .= ", ALTER COLUMN $col SET DEFAULT $defval";
|
||||
}
|
||||
if($col != $newname) {
|
||||
$newq .= ";ALTER TABLE $table RENAME COLUMN $col TO $newcol;";
|
||||
}
|
||||
$sql = $newq;
|
||||
}
|
||||
$pattern = '/ALTER TABLE\s+(\w+)\s+ALTER COLUMN\s+/';
|
||||
if(1 === preg_match($pattern, $sql)) {
|
||||
// Translate default values
|
||||
$sql = str_replace(
|
||||
array_keys($typeTranslations),
|
||||
array_values($typeTranslations),
|
||||
$sql
|
||||
);
|
||||
}
|
||||
$pattern = '/ALTER TABLE\s+(\w+)\s+ADD COLUMN\s+([^\s]+)\s+([^ ]+)( unsigned|)\s+(NOT NULL|)\s*(default (.+)|)/';
|
||||
if(1 === preg_match($pattern, $sql, $matches)) {
|
||||
$table = $matches[1];
|
||||
$col = $matches[2];
|
||||
$type = strtolower($matches[3]);
|
||||
if(isset($typeTranslations[$type])) {
|
||||
$type = $typeTranslations[$type];
|
||||
}
|
||||
$unsigned = $matches[4];
|
||||
$notnull = $matches[5];
|
||||
$default = $matches[6];
|
||||
$defval = $matches[7];
|
||||
if(isset($typeTranslations[$defval])) {
|
||||
$defval = $typeTranslations[$defval];
|
||||
}
|
||||
$newq = "ALTER TABLE $table ADD COLUMN $col $type";
|
||||
if(!empty($default)) {
|
||||
$newq .= " DEFAULT $defval";
|
||||
}
|
||||
if(!empty($notnull)) {
|
||||
$newq .= " NOT NULL";
|
||||
}
|
||||
$sql = $newq;
|
||||
}
|
||||
$pattern = '/ALTER TABLE\s+(\w+)\s+ADD (UNIQUE |)KEY\s+([^\s]+)\s+\(((?:[^\(\)]+|\([^\(\)]+\))+)\)/';
|
||||
if(1 === preg_match($pattern, $sql, $matches)) {
|
||||
$table = $matches[1];
|
||||
$unique = $matches[2];
|
||||
$index = $matches[3];
|
||||
$columns = $matches[4];
|
||||
|
||||
// Remove prefix indexing
|
||||
// Rarely used and apparently unnecessary for current uses
|
||||
$columns = preg_replace('/\([^\)]*\)/', '', $columns);
|
||||
|
||||
// Workaround for index name duplicate
|
||||
$index = $table . '_' . $index;
|
||||
$sql = "CREATE {$unique}INDEX $index ON $table ($columns)";
|
||||
}
|
||||
$pattern = '/ALTER TABLE\s+(\w+)\s+DROP INDEX\s+([^\s]+)/';
|
||||
if(1 === preg_match($pattern, $sql, $matches)) {
|
||||
$table = $matches[1];
|
||||
$index = $matches[2];
|
||||
$sql = "DROP INDEX ${table}_${index}";
|
||||
}
|
||||
$pattern = '/ALTER TABLE\s+(\w+)\s+DROP PRIMARY KEY/';
|
||||
if(1 === preg_match($pattern, $sql, $matches)) {
|
||||
$table = $matches[1];
|
||||
$sql = "ALTER TABLE ${table} DROP CONSTRAINT ${table}_pkey";
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
}
|
||||
|
||||
|
80
pg4wp/rewriters/CreateTableSQLRewriter.php
Normal file
80
pg4wp/rewriters/CreateTableSQLRewriter.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
class CreateTableSQLRewriter extends AbstractSQLRewriter
|
||||
{
|
||||
public function rewrite(): string
|
||||
{
|
||||
// List of types translations (the key is the mysql one, the value is the text to use instead)
|
||||
$typeTranslations = array(
|
||||
'bigint(20)' => 'bigint',
|
||||
'bigint(10)' => 'int',
|
||||
'int(11)' => 'int',
|
||||
'tinytext' => 'text',
|
||||
'mediumtext' => 'text',
|
||||
'longtext' => 'text',
|
||||
'unsigned' => '',
|
||||
'gmt datetime NOT NULL default \'0000-00-00 00:00:00\'' => 'gmt timestamp NOT NULL DEFAULT timezone(\'gmt\'::text, now())',
|
||||
'default \'0000-00-00 00:00:00\'' => 'DEFAULT now()',
|
||||
'\'0000-00-00 00:00:00\'' => 'now()',
|
||||
'datetime' => 'timestamp',
|
||||
'DEFAULT CHARACTER SET utf8mb4' => '',
|
||||
'DEFAULT CHARACTER SET utf8' => '',
|
||||
|
||||
// WP 2.7.1 compatibility
|
||||
'int(4)' => 'smallint',
|
||||
|
||||
// For WPMU (starting with WP 3.2)
|
||||
'tinyint(2)' => 'smallint',
|
||||
'tinyint(1)' => 'smallint',
|
||||
"enum('0','1')" => 'smallint',
|
||||
'COLLATE utf8mb4_unicode_520_ci' => '',
|
||||
'COLLATE utf8_general_ci' => '',
|
||||
|
||||
// For flash-album-gallery plugin
|
||||
'tinyint' => 'smallint',
|
||||
);
|
||||
|
||||
$sql = $this->original();
|
||||
$sql = str_replace('CREATE TABLE IF NOT EXISTS ', 'CREATE TABLE ', $sql);
|
||||
$pattern = '/CREATE TABLE [`]?(\w+)[`]?/';
|
||||
preg_match($pattern, $sql, $matches);
|
||||
$table = $matches[1];
|
||||
|
||||
// Remove trailing spaces
|
||||
$sql = trim($sql) . ';';
|
||||
|
||||
// Translate types and some other replacements
|
||||
$sql = str_replace(
|
||||
array_keys($typeTranslations),
|
||||
array_values($typeTranslations),
|
||||
$sql
|
||||
);
|
||||
|
||||
// Fix auto_increment by adding a sequence
|
||||
$pattern = '/int[ ]+NOT NULL auto_increment/';
|
||||
preg_match($pattern, $sql, $matches);
|
||||
if($matches) {
|
||||
$seq = $table . '_seq';
|
||||
$sql = str_replace('NOT NULL auto_increment', "NOT NULL DEFAULT nextval('$seq'::text)", $sql);
|
||||
$sql .= "\nCREATE SEQUENCE $seq;";
|
||||
}
|
||||
|
||||
// Support for INDEX creation
|
||||
$pattern = '/,\s+(UNIQUE |)KEY\s+([^\s]+)\s+\(((?:[\w]+(?:\([\d]+\))?[,]?)*)\)/';
|
||||
if(preg_match_all($pattern, $sql, $matches, PREG_SET_ORDER)) {
|
||||
foreach($matches as $match) {
|
||||
$unique = $match[1];
|
||||
$index = $match[2];
|
||||
$columns = $match[3];
|
||||
$columns = preg_replace('/\(\d+\)/', '', $columns);
|
||||
// Workaround for index name duplicate
|
||||
$index = $table . '_' . $index;
|
||||
$sql .= "\nCREATE {$unique}INDEX $index ON $table ($columns);";
|
||||
}
|
||||
}
|
||||
// Now remove handled indexes
|
||||
$sql = preg_replace($pattern, '', $sql);
|
||||
|
||||
return $sql;
|
||||
}
|
||||
}
|
78
pg4wp/rewriters/DescribeSQLRewriter.php
Normal file
78
pg4wp/rewriters/DescribeSQLRewriter.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
class DescribeSQLRewriter extends AbstractSQLRewriter
|
||||
{
|
||||
public function rewrite(): string
|
||||
{
|
||||
$sql = $this->original();
|
||||
$table = $this->extractTableName($sql);
|
||||
return $this->generatePostgresDescribeTable($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts table name from a "DESCRIBE" SQL statement.
|
||||
*
|
||||
* @param string $sql The SQL statement
|
||||
* @return string|null The table name if found, or null otherwise
|
||||
*/
|
||||
protected function extractTableName($sql) {
|
||||
$pattern = "/DESCRIBE ['\"`]?([^'\"`]+)['\"`]?/i";
|
||||
if (preg_match($pattern, $sql, $matches)) {
|
||||
return $matches[1];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a PostgreSQL-compatible SQL query to mimic MySQL's "DESCRIBE".
|
||||
*
|
||||
* @param string $tableName The table name
|
||||
* @return string The generated SQL query
|
||||
*/
|
||||
function generatePostgresDescribeTable($tableName) {
|
||||
$sql = <<<SQL
|
||||
SELECT
|
||||
f.attnum AS number,
|
||||
f.attname AS name,
|
||||
f.attnum,
|
||||
f.attnotnull AS notnull,
|
||||
pg_catalog.format_type(f.atttypid,f.atttypmod) AS type,
|
||||
CASE
|
||||
WHEN p.contype = 'p' THEN 't'
|
||||
ELSE 'f'
|
||||
END AS primarykey,
|
||||
CASE
|
||||
WHEN p.contype = 'u' THEN 't'
|
||||
ELSE 'f'
|
||||
END AS uniquekey,
|
||||
CASE
|
||||
WHEN p.contype = 'f' THEN g.relname
|
||||
END AS foreignkey,
|
||||
CASE
|
||||
WHEN p.contype = 'f' THEN p.confkey
|
||||
END AS foreignkey_fieldnum,
|
||||
CASE
|
||||
WHEN p.contype = 'f' THEN g.relname
|
||||
END AS foreignkey,
|
||||
CASE
|
||||
WHEN p.contype = 'f' THEN p.conkey
|
||||
END AS foreignkey_connnum,
|
||||
CASE
|
||||
WHEN f.atthasdef = 't' THEN pg_get_expr(d.adbin, d.adrelid)
|
||||
END AS default
|
||||
FROM pg_attribute f
|
||||
JOIN pg_class c ON c.oid = f.attrelid
|
||||
JOIN pg_type t ON t.oid = f.atttypid
|
||||
LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum
|
||||
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY (p.conkey)
|
||||
LEFT JOIN pg_class AS g ON p.confrelid = g.oid
|
||||
WHERE c.relkind = 'r'::char
|
||||
AND n.nspname = 'public'
|
||||
AND c.relname = '$tableName'
|
||||
AND f.attnum > 0 ORDER BY number
|
||||
SQL;
|
||||
|
||||
return $sql;
|
||||
}
|
||||
}
|
17
pg4wp/rewriters/DropTableSQLRewriter.php
Normal file
17
pg4wp/rewriters/DropTableSQLRewriter.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
class DropTableSQLRewriter extends AbstractSQLRewriter
|
||||
{
|
||||
public function rewrite(): string
|
||||
{
|
||||
$sql = $this->original();
|
||||
|
||||
$pattern = '/DROP TABLE.+ [`]?(\w+)[`]?$/';
|
||||
preg_match($pattern, $sql, $matches);
|
||||
$table = $matches[1];
|
||||
$seq = $table . '_seq';
|
||||
$sql .= ";\nDROP SEQUENCE IF EXISTS $seq;";
|
||||
|
||||
return $sql;
|
||||
}
|
||||
}
|
60
pg4wp/rewriters/ShowIndexSQLRewriter.php
Normal file
60
pg4wp/rewriters/ShowIndexSQLRewriter.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
class ShowIndexSQLRewriter extends AbstractSQLRewriter
|
||||
{
|
||||
public function rewrite(): string
|
||||
{
|
||||
$sql = $this->original();
|
||||
$table = $this->extractTableNameFromShowIndex($sql);
|
||||
return $this->generatePostgresShowIndexFrom($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts table name from a "SHOW FULL COLUMNS" SQL statement.
|
||||
*
|
||||
* @param string $sql The SQL statement
|
||||
* @return string|null The table name if found, or null otherwise
|
||||
*/
|
||||
protected function extractVariableName($sql) {
|
||||
$pattern = "/SHOW INDEX FROM ['\"`]?([^'\"`]+)['\"`]?/i";
|
||||
if (preg_match($pattern, $sql, $matches)) {
|
||||
return $matches[1];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a PostgreSQL-compatible SQL query to mimic MySQL's "SHOW INDEX FROM".
|
||||
*
|
||||
* @param string $tableName The table name
|
||||
* @return string The generated SQL query
|
||||
*/
|
||||
function generatePostgresShowIndexFrom($tableName) {
|
||||
$sql = <<<SQL
|
||||
SELECT bc.relname AS "Table",
|
||||
CASE WHEN i.indisunique THEN '0' ELSE '1' END AS "Non_unique",
|
||||
CASE WHEN i.indisprimary THEN 'PRIMARY' WHEN bc.relname LIKE '%usermeta' AND ic.relname = 'umeta_key'
|
||||
THEN 'meta_key' ELSE REPLACE( ic.relname, '' . $table . '_', '') END AS "Key_name",
|
||||
a.attname AS "Column_name",
|
||||
NULL AS "Sub_part"
|
||||
FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a
|
||||
WHERE bc.oid = i.indrelid
|
||||
AND ic.oid = i.indexrelid
|
||||
AND (i.indkey[0] = a.attnum OR i.indkey[1] = a.attnum OR i.indkey[2] = a.attnum OR i.indkey[3] = a.attnum OR i.indkey[4] = a.attnum OR i.indkey[5] = a.attnum OR i.indkey[6] = a.attnum OR i.indkey[7] = a.attnum)
|
||||
AND a.attrelid = bc.oid
|
||||
AND bc.relname = '' . $tableName . ''
|
||||
ORDER BY "Key_name", CASE a.attnum
|
||||
WHEN i.indkey[0] THEN 0
|
||||
WHEN i.indkey[1] THEN 1
|
||||
WHEN i.indkey[2] THEN 2
|
||||
WHEN i.indkey[3] THEN 3
|
||||
WHEN i.indkey[4] THEN 4
|
||||
WHEN i.indkey[5] THEN 5
|
||||
WHEN i.indkey[6] THEN 6
|
||||
WHEN i.indkey[7] THEN 7
|
||||
END
|
||||
SQL;
|
||||
|
||||
return $sql;
|
||||
}
|
||||
}
|
41
pg4wp/rewriters/ShowVariablesSQLRewriter.php
Normal file
41
pg4wp/rewriters/ShowVariablesSQLRewriter.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
class ShowVariablesSQLRewriter extends AbstractSQLRewriter
|
||||
{
|
||||
public function rewrite(): string
|
||||
{
|
||||
$sql = $this->original();
|
||||
$table = $this->extractVariableName($sql);
|
||||
return $this->generatePostgres($sql, $variableName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts table name from a "SHOW FULL COLUMNS" SQL statement.
|
||||
*
|
||||
* @param string $sql The SQL statement
|
||||
* @return string|null The table name if found, or null otherwise
|
||||
*/
|
||||
protected function extractVariableName($sql) {
|
||||
$pattern = "/SHOW VARIABLES LIKE ['\"`]?([^'\"`]+)['\"`]?/i";
|
||||
if (preg_match($pattern, $sql, $matches)) {
|
||||
return $matches[1];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a PostgreSQL-compatible SQL query to mimic MySQL's "SHOW VARIABLES".
|
||||
*
|
||||
* @param string $tableName The table name
|
||||
* @return string The generated SQL query
|
||||
*/
|
||||
function generatePostgres($sql, $variableName) {
|
||||
if ($variableName == "sql_mode") {
|
||||
// Act like MySQL default configuration, where sql_mode is ""
|
||||
return "SELECT '$variableName' AS \"Variable_name\", '' AS \"Value\";";
|
||||
}
|
||||
|
||||
// return untransformed sql
|
||||
return $sql;
|
||||
}
|
||||
}
|
47
wp-includes/version.php
Normal file
47
wp-includes/version.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* WordPress Version
|
||||
*
|
||||
* Contains version information for the current WordPress release.
|
||||
*
|
||||
* @package WordPress
|
||||
* @since 1.2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* The WordPress version string.
|
||||
*
|
||||
* Holds the current version number for WordPress core. Used to bust caches
|
||||
* and to enable development mode for scripts when running from the /src directory.
|
||||
*
|
||||
* @global string $wp_version
|
||||
*/
|
||||
$wp_version = '6.3.2';
|
||||
|
||||
/**
|
||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||
*
|
||||
* @global int $wp_db_version
|
||||
*/
|
||||
$wp_db_version = 55853;
|
||||
|
||||
/**
|
||||
* Holds the TinyMCE version.
|
||||
*
|
||||
* @global string $tinymce_version
|
||||
*/
|
||||
$tinymce_version = '49110-20201110';
|
||||
|
||||
/**
|
||||
* Holds the required PHP version.
|
||||
*
|
||||
* @global string $required_php_version
|
||||
*/
|
||||
$required_php_version = '7.0.0';
|
||||
|
||||
/**
|
||||
* Holds the required MySQL version.
|
||||
*
|
||||
* @global string $required_mysql_version
|
||||
*/
|
||||
$required_mysql_version = '5.0';
|
Reference in New Issue
Block a user