diff --git a/pg4wp/driver_pgsql.php b/pg4wp/driver_pgsql.php index 9a50837..4809e9d 100644 --- a/pg4wp/driver_pgsql.php +++ b/pg4wp/driver_pgsql.php @@ -13,31 +13,10 @@ * This was originally based on usleepless's original 'mysql2pgsql.php' file, many thanks to him */ - // 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()', - 'datetime' => 'timestamp', - 'DEFAULT CHARACTER SET utf8' => '', - - // WP 2.7.1 compatibility - 'int(4)' => 'smallint', - - // ZdMultiLang support hack - 'term_id varchar(5)' => 'term_id int', - 'BIGINT(20)' => 'int', - 'character set utf8' => '', - 'CHARACTER SET utf8' => '', - 'UNSIGNED' => '', // ZdMultilang 1.2.5 - ); - + // Load up upgrade and install functions as required + if( defined( 'WP_INSTALLING') && WP_INSTALLING) + require_once( PG4WP_ROOT.'/driver_pgsql_install.php'); + // Initializing some variables $GLOBALS['pg4wp_result'] = 0; $GLOBALS['pg4wp_numrows'] = '10'; @@ -275,152 +254,8 @@ $logto = 'SHOWTABLES'; $sql = 'SELECT tablename FROM pg_tables WHERE schemaname = \'public\';'; } - // 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]; -$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 ic.relname 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 a.attname;'; - } - // 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 = $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+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]; - // 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_attrdef.adsrc FROM '^\'(.*)\'.*$') - WHEN 'timestamp' THEN CASE WHEN pg_attrdef.adsrc LIKE '%now()%' THEN '0000-00-00 00:00:00' ELSE pg_attrdef.adsrc END - ELSE pg_attrdef.adsrc - 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'; - $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+\(([^\)]+)\)/'; - if( preg_match_all( $pattern, $sql, $matches, PREG_SET_ORDER)) - foreach( $matches as $match) - { - $unique = $match[1]; - $index = $match[2]; - $columns = $match[3]; - // 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( defined('WP_INSTALLING') && WP_INSTALLING) + $sql = pg4wp_installing( $sql, $logto); // Field names with CAPITALS need special handling if( false !== strpos($sql, 'ID')) diff --git a/pg4wp/driver_pgsql_install.php b/pg4wp/driver_pgsql_install.php new file mode 100644 index 0000000..2c02eae --- /dev/null +++ b/pg4wp/driver_pgsql_install.php @@ -0,0 +1,189 @@ + '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()', + 'datetime' => 'timestamp', + 'DEFAULT CHARACTER SET utf8' => '', + + // WP 2.7.1 compatibility + 'int(4)' => 'smallint', + + // ZdMultiLang support hack + 'term_id varchar(5)' => 'term_id int', + 'BIGINT(20)' => 'int', + 'character set utf8' => '', + 'CHARACTER SET utf8' => '', + 'UNSIGNED' => '', // ZdMultilang 1.2.5 + ); + + function pg4wp_installing( $sql, &$logto) + { + global $table_prefix; + + // SHOW INDEX emulation + if( 0 === strpos( $sql, 'SHOW INDEX')) + { + $logto = 'SHOWINDEX'; + $pattern = '/SHOW INDEX FROM\s+(\w+)/'; + preg_match( $pattern, $sql, $matches); + $table = $matches[1]; +$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 ic.relname 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 a.attname;'; + } + // 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 = $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+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]; + // 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_attrdef.adsrc FROM '^\'(.*)\'.*$') + WHEN 'timestamp' THEN CASE WHEN pg_attrdef.adsrc LIKE '%now()%' THEN '0000-00-00 00:00:00' ELSE pg_attrdef.adsrc END + ELSE pg_attrdef.adsrc + 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'; + $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+\(([^\)]+)\)/'; + if( preg_match_all( $pattern, $sql, $matches, PREG_SET_ORDER)) + foreach( $matches as $match) + { + $unique = $match[1]; + $index = $match[2]; + $columns = $match[3]; + // 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 + + return $sql; + } diff --git a/readme.txt b/readme.txt index 506aece..7775b70 100644 --- a/readme.txt +++ b/readme.txt @@ -50,6 +50,8 @@ There is no screenshot for this plugin == Changelog == +* Moved parts required only when installing/upgrading from driver_pgsql.php to a separate file + The file is loaded only when needed so that memory footprint should be a bit smaller * Added UNIX_TIMESTAMP support * Added DAYOFMONTH support (Thanks to Pete Deffendol for noticing the problem) * Upgrading from WP 2.8.6 to WP 2.9.1 works with a minor error