add rewrite logic for SHOW TABLE STATUS and a catch for calls to information_schema
This commit is contained in:
@@ -12,7 +12,7 @@ spl_autoload_register(function ($className) {
|
|||||||
function createSQLRewriter(string $sql): AbstractSQLRewriter
|
function createSQLRewriter(string $sql): AbstractSQLRewriter
|
||||||
{
|
{
|
||||||
$sql = trim($sql);
|
$sql = trim($sql);
|
||||||
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)) {
|
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|SHOW TABLE STATUS)\b/i', $sql, $matches)) {
|
||||||
// Convert to a format suitable for class names (e.g., "SHOW TABLES" becomes "ShowTables")
|
// Convert to a format suitable for class names (e.g., "SHOW TABLES" becomes "ShowTables")
|
||||||
$type = str_replace(' ', '', ucwords(str_replace('_', ' ', strtolower($matches[1]))));
|
$type = str_replace(' ', '', ucwords(str_replace('_', ' ', strtolower($matches[1]))));
|
||||||
$className = $type . 'SQLRewriter';
|
$className = $type . 'SQLRewriter';
|
||||||
|
@@ -31,6 +31,16 @@ class SelectSQLRewriter extends AbstractSQLRewriter
|
|||||||
$sql = preg_replace('/SELECT\s+.*?\s+FROM\s+/is', 'SELECT COUNT(*) FROM ', $sql, 1);
|
$sql = preg_replace('/SELECT\s+.*?\s+FROM\s+/is', 'SELECT COUNT(*) FROM ', $sql, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(false !== strpos($sql, 'information_schema')) {
|
||||||
|
// WP Site Health rewrites
|
||||||
|
if (false !== strpos($sql, "SELECT TABLE_NAME AS 'table', TABLE_ROWS AS 'rows', SUM(data_length + index_length)")) {
|
||||||
|
$sql = $this->postgresTableSizeRewrite();
|
||||||
|
return $sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception("Unsupported call to information_schema, this probably won't work correctly and needs to be specifically handled, open a github issue with the SQL");
|
||||||
|
}
|
||||||
|
|
||||||
$sql = $this->ensureOrderByInSelect($sql);
|
$sql = $this->ensureOrderByInSelect($sql);
|
||||||
|
|
||||||
// Convert CONVERT to CAST
|
// Convert CONVERT to CAST
|
||||||
@@ -347,4 +357,29 @@ class SelectSQLRewriter extends AbstractSQLRewriter
|
|||||||
return $sql;
|
return $sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This method is specifically to handle should_suggest_persistent_object_cache in wp site health
|
||||||
|
protected function postgresTableSizeRewrite()
|
||||||
|
{
|
||||||
|
|
||||||
|
$sql = <<<SQL
|
||||||
|
SELECT
|
||||||
|
C.relname AS "table",
|
||||||
|
S.n_live_tup AS "rows",
|
||||||
|
pg_total_relation_size(C.oid) AS "bytes"
|
||||||
|
FROM
|
||||||
|
pg_class C
|
||||||
|
LEFT JOIN
|
||||||
|
pg_namespace N ON (N.oid = C.relnamespace)
|
||||||
|
INNER JOIN
|
||||||
|
pg_stat_user_tables S ON (S.relid = C.oid)
|
||||||
|
WHERE
|
||||||
|
N.nspname = 'public' AND
|
||||||
|
C.relname IN ('wp_comments','wp_options','wp_posts','wp_terms','wp_users')
|
||||||
|
GROUP BY
|
||||||
|
C.relname, pg_total_relation_size(C.oid), S.n_live_tup;
|
||||||
|
SQL;
|
||||||
|
|
||||||
|
return $sql;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
54
pg4wp/rewriters/ShowTableStatusSQLRewriter.php
Normal file
54
pg4wp/rewriters/ShowTableStatusSQLRewriter.php
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class ShowTableStatusSQLRewriter extends AbstractSQLRewriter
|
||||||
|
{
|
||||||
|
public function rewrite(): string
|
||||||
|
{
|
||||||
|
$sql = $this->original();
|
||||||
|
return $this->generatePostgresShowTableStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a PostgreSQL-compatible SQL query to mimic MySQL's "SHOW TABLE STATUS".
|
||||||
|
*
|
||||||
|
* @return string The generated SQL query
|
||||||
|
*/
|
||||||
|
public function generatePostgresShowTableStatus($schema = "public")
|
||||||
|
{
|
||||||
|
$sql = <<<SQL
|
||||||
|
SELECT
|
||||||
|
'Postgres' AS Engine,
|
||||||
|
cls.relname AS TableName,
|
||||||
|
NULL AS Version,
|
||||||
|
NULL AS Row_format,
|
||||||
|
cls.reltuples AS Rows,
|
||||||
|
NULL AS Avg_row_length,
|
||||||
|
pg_relation_size(cls.oid) AS Data_length,
|
||||||
|
NULL AS Max_data_length,
|
||||||
|
pg_indexes_size(cls.oid) AS Index_length,
|
||||||
|
NULL AS Data_free,
|
||||||
|
NULL AS Auto_increment,
|
||||||
|
NULL AS Create_time,
|
||||||
|
NULL AS Update_time,
|
||||||
|
NULL AS Check_time,
|
||||||
|
'UTF8' AS Table_collation,
|
||||||
|
NULL AS Checksum,
|
||||||
|
NULL AS Create_options,
|
||||||
|
obj_description(cls.oid) AS Comment
|
||||||
|
FROM
|
||||||
|
pg_class cls
|
||||||
|
JOIN
|
||||||
|
pg_namespace nsp ON cls.relnamespace = nsp.oid
|
||||||
|
WHERE
|
||||||
|
cls.relkind = 'r'
|
||||||
|
AND nsp.nspname NOT LIKE 'pg_%' -- Ignore schemas with names starting with pg_
|
||||||
|
AND nsp.nspname != 'information_schema' -- Ignore the information_schema
|
||||||
|
AND nsp.nspname = $schema -- Select only tables in the 'myschema' schema
|
||||||
|
ORDER BY
|
||||||
|
cls.relname ASC;
|
||||||
|
SQL;
|
||||||
|
|
||||||
|
return $sql;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user