From 31b40f71bb71b36d80ea153b5b011530c93ffc07 Mon Sep 17 00:00:00 2001 From: Vincent Milum Jr Date: Fri, 15 Feb 2019 08:16:14 -0800 Subject: [PATCH] Fix for SYSTEM VERSIONED tables #14514, #14515, and #14516 (#14536) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #14514 Fixes #14515 Possible fix for #14516 #14514 Tables which enable the new MariaDB 10.3 versioning show up as "SYSTEM VERSIONED" instead of "BASE TABLE" inside of information schema. This patch now checks for both, so these new table types don't incorrectly display as views. #14515 MariaDB 10.3 also supports INVISIBLE columns, which is optionally paired with SYSTEM VERSIONED tabled (or implemented separately). This patch helps handle this new column attribute. #14516 This patch cannot be fully tested and verified with current MariaDB builds. Version 10.3.9 (currently unreleased) corrects an issue with column information for SYSTEM VERSIONED columns that this patch relies on. https://jira.mariadb.org/browse/MDEV-16804 - the reason for checking with preg_match instead of adding to the list is because there are now combined "extra" information for columns, such as INVISIBLE columns. Just matching entire strings also has a bug with these other "extra" parameters. Signed-off-by: Vincent Milum Jr Signed-off-by: MaurĂ­cio Meneghini Fauth (cherry picked from commit 3f6e360a4ed89b3c0cff649b626f646d49401567) Signed-off-by: MaurĂ­cio Meneghini Fauth --- libraries/classes/DatabaseInterface.php | 4 ++-- libraries/classes/Dbi/DbiMysqli.php | 9 +++++++++ libraries/classes/InsertEdit.php | 5 +---- .../classes/Navigation/Nodes/NodeDatabase.php | 16 ++++++++-------- libraries/classes/Rte/Triggers.php | 2 +- libraries/classes/Sql.php | 5 +++++ libraries/classes/Util.php | 4 ++-- libraries/dbi/dbi_dummy.inc.php | 6 +++--- 8 files changed, 31 insertions(+), 20 deletions(-) diff --git a/libraries/classes/DatabaseInterface.php b/libraries/classes/DatabaseInterface.php index 78172e4618..eb7ed791ed 100644 --- a/libraries/classes/DatabaseInterface.php +++ b/libraries/classes/DatabaseInterface.php @@ -470,9 +470,9 @@ class DatabaseInterface if ($table_type) { if ($table_type == 'view') { - $sql_where_table .= " AND t.`TABLE_TYPE` != 'BASE TABLE'"; + $sql_where_table .= " AND t.`TABLE_TYPE` NOT IN ('BASE TABLE', 'SYSTEM VERSIONED')"; } elseif ($table_type == 'table') { - $sql_where_table .= " AND t.`TABLE_TYPE` = 'BASE TABLE'"; + $sql_where_table .= " AND t.`TABLE_TYPE` IN ('BASE TABLE', 'SYSTEM VERSIONED')"; } } return $sql_where_table; diff --git a/libraries/classes/Dbi/DbiMysqli.php b/libraries/classes/Dbi/DbiMysqli.php index 3833f846a4..24c5bfda68 100644 --- a/libraries/classes/Dbi/DbiMysqli.php +++ b/libraries/classes/Dbi/DbiMysqli.php @@ -520,6 +520,9 @@ class DbiMysqli implements DbiExtension */ public function fieldLen($result, $i) { + if ($i >= $this->numFields($result)) { + return false; + } return mysqli_fetch_field_direct($result, $i)->length; } @@ -533,6 +536,9 @@ class DbiMysqli implements DbiExtension */ public function fieldName($result, $i) { + if ($i >= $this->numFields($result)) { + return false; + } return mysqli_fetch_field_direct($result, $i)->name; } @@ -546,6 +552,9 @@ class DbiMysqli implements DbiExtension */ public function fieldFlags($result, $i) { + if ($i >= $this->numFields($result)) { + return false; + } $f = mysqli_fetch_field_direct($result, $i); $type = $f->type; $charsetnr = $f->charsetnr; diff --git a/libraries/classes/InsertEdit.php b/libraries/classes/InsertEdit.php index d68caeeda7..8157ca5609 100644 --- a/libraries/classes/InsertEdit.php +++ b/libraries/classes/InsertEdit.php @@ -1627,10 +1627,7 @@ class InsertEdit $readOnly ); - $virtual = array( - 'VIRTUAL', 'PERSISTENT', 'VIRTUAL GENERATED', 'STORED GENERATED' - ); - if (in_array($column['Extra'], $virtual)) { + if (preg_match('/(VIRTUAL|PERSISTENT|GENERATED)/', $column['Extra'])) { $html_output .= ''; } diff --git a/libraries/classes/Navigation/Nodes/NodeDatabase.php b/libraries/classes/Navigation/Nodes/NodeDatabase.php index b0a21c2735..246000c49c 100644 --- a/libraries/classes/Navigation/Nodes/NodeDatabase.php +++ b/libraries/classes/Navigation/Nodes/NodeDatabase.php @@ -111,9 +111,9 @@ class NodeDatabase extends Node { $db = $this->real_name; if ($which == 'tables') { - $condition = '='; + $condition = 'IN'; } else { - $condition = '!='; + $condition = 'NOT IN'; } if (! $GLOBALS['cfg']['Server']['DisableIS']) { @@ -121,7 +121,7 @@ class NodeDatabase extends Node $query = "SELECT COUNT(*) "; $query .= "FROM `INFORMATION_SCHEMA`.`TABLES` "; $query .= "WHERE `TABLE_SCHEMA`='$db' "; - $query .= "AND `TABLE_TYPE`" . $condition . "'BASE TABLE' "; + $query .= "AND `TABLE_TYPE`" . $condition . "('BASE TABLE', 'SYSTEM VERSIONED') "; if (! empty($searchClause)) { $query .= "AND " . $this->_getWhereClauseForSearch( $searchClause, @@ -133,7 +133,7 @@ class NodeDatabase extends Node } else { $query = "SHOW FULL TABLES FROM "; $query .= Util::backquote($db); - $query .= " WHERE `Table_type`" . $condition . "'BASE TABLE' "; + $query .= " WHERE `Table_type`" . $condition . "('BASE TABLE', 'SYSTEM VERSIONED') "; if (!empty($searchClause)) { $query .= "AND " . $this->_getWhereClauseForSearch( $searchClause, @@ -446,9 +446,9 @@ class NodeDatabase extends Node private function _getTablesOrViews($which, $pos, $searchClause) { if ($which == 'tables') { - $condition = '='; + $condition = 'IN'; } else { - $condition = '!='; + $condition = 'NOT IN'; } $maxItems = $GLOBALS['cfg']['MaxNavigationItems']; $retval = array(); @@ -458,7 +458,7 @@ class NodeDatabase extends Node $query = "SELECT `TABLE_NAME` AS `name` "; $query .= "FROM `INFORMATION_SCHEMA`.`TABLES` "; $query .= "WHERE `TABLE_SCHEMA`='$escdDb' "; - $query .= "AND `TABLE_TYPE`" . $condition . "'BASE TABLE' "; + $query .= "AND `TABLE_TYPE`" . $condition . "('BASE TABLE', 'SYSTEM VERSIONED') "; if (! empty($searchClause)) { $query .= "AND `TABLE_NAME` LIKE '%"; $query .= $GLOBALS['dbi']->escapeString($searchClause); @@ -470,7 +470,7 @@ class NodeDatabase extends Node } else { $query = " SHOW FULL TABLES FROM "; $query .= Util::backquote($db); - $query .= " WHERE `Table_type`" . $condition . "'BASE TABLE' "; + $query .= " WHERE `Table_type`" . $condition . "('BASE TABLE', 'SYSTEM VERSIONED') "; if (!empty($searchClause)) { $query .= "AND " . Util::backquote( "Tables_in_" . $db diff --git a/libraries/classes/Rte/Triggers.php b/libraries/classes/Rte/Triggers.php index 1f0d273b08..c79d3ecab8 100644 --- a/libraries/classes/Rte/Triggers.php +++ b/libraries/classes/Rte/Triggers.php @@ -325,7 +325,7 @@ class Triggers } $query = "SELECT `TABLE_NAME` FROM `INFORMATION_SCHEMA`.`TABLES` "; $query .= "WHERE `TABLE_SCHEMA`='" . $GLOBALS['dbi']->escapeString($db) . "' "; - $query .= "AND `TABLE_TYPE`='BASE TABLE'"; + $query .= "AND `TABLE_TYPE` IN ('BASE TABLE', 'SYSTEM VERSIONED')"; $tables = $GLOBALS['dbi']->fetchResult($query); // Create the output diff --git a/libraries/classes/Sql.php b/libraries/classes/Sql.php index 4f43ce144c..331edf7233 100644 --- a/libraries/classes/Sql.php +++ b/libraries/classes/Sql.php @@ -170,6 +170,7 @@ class Sql */ private function resultSetContainsUniqueKey($db, $table, array $fields_meta) { + $columns = $GLOBALS['dbi']->getColumns($db, $table); $resultSetColumnNames = array(); foreach ($fields_meta as $oneMeta) { $resultSetColumnNames[] = $oneMeta->name; @@ -181,6 +182,10 @@ class Sql foreach ($indexColumns as $indexColumnName => $dummy) { if (in_array($indexColumnName, $resultSetColumnNames)) { $numberFound++; + } else if (!in_array($indexColumnName, $columns)) { + $numberFound++; + } else if (strpos($columns[$indexColumnName]['Extra'], 'INVISIBLE') !== false) { + $numberFound++; } } if ($numberFound == count($indexColumns)) { diff --git a/libraries/classes/Util.php b/libraries/classes/Util.php index af23753d99..dd3aee5e95 100644 --- a/libraries/classes/Util.php +++ b/libraries/classes/Util.php @@ -4469,9 +4469,9 @@ class Util if (Core::isValid($_REQUEST['tbl_type'], array('table', 'view'))) { $tblGroupSql .= $whereAdded ? " AND" : " WHERE"; if ($_REQUEST['tbl_type'] == 'view') { - $tblGroupSql .= " `Table_type` != 'BASE TABLE'"; + $tblGroupSql .= " `Table_type` NOT IN ('BASE TABLE', 'SYSTEM VERSIONED')"; } else { - $tblGroupSql .= " `Table_type` = 'BASE TABLE'"; + $tblGroupSql .= " `Table_type` IN ('BASE TABLE', 'SYSTEM VERSIONED')"; } } $db_info_result = $GLOBALS['dbi']->query( diff --git a/libraries/dbi/dbi_dummy.inc.php b/libraries/dbi/dbi_dummy.inc.php index 0d29c989f3..d1e656bd9d 100644 --- a/libraries/dbi/dbi_dummy.inc.php +++ b/libraries/dbi/dbi_dummy.inc.php @@ -260,7 +260,7 @@ $GLOBALS['dummy_queries'] = array( ), array( 'query' => 'SELECT `TABLE_NAME` FROM `INFORMATION_SCHEMA`.`TABLES`' - . ' WHERE `TABLE_SCHEMA`=\'pma_test\' AND `TABLE_TYPE`=\'BASE TABLE\'', + . ' WHERE `TABLE_SCHEMA`=\'pma_test\' AND `TABLE_TYPE` IN (\'BASE TABLE\', \'SYSTEM VERSIONED\')', 'result' => array(), ), array( @@ -706,7 +706,7 @@ $GLOBALS['dummy_queries'] = array( ), ), array( - 'query' => "SHOW FULL TABLES FROM `default` WHERE `Table_type`='BASE TABLE'", + 'query' => "SHOW FULL TABLES FROM `default` WHERE `Table_type`IN('BASE TABLE', 'SYSTEM VERSIONED')", 'result' => array( array("test1", "BASE TABLE"), array("test2", "BASE TABLE"), @@ -714,7 +714,7 @@ $GLOBALS['dummy_queries'] = array( ), array( 'query' => "SHOW FULL TABLES FROM `default` " - . "WHERE `Table_type`!='BASE TABLE'", + . "WHERE `Table_type`NOT IN('BASE TABLE', 'SYSTEM VERSIONED')", 'result' => array(), ), array(