diff options
author | Christian Foellmann <foellmann@foe-services.de> | 2014-12-23 14:48:13 +0300 |
---|---|---|
committer | Christian Foellmann <foellmann@foe-services.de> | 2014-12-23 14:48:13 +0300 |
commit | 2bfb20e57418ebf396149782be9f98e868fe8608 (patch) | |
tree | a5ec4011410970603d3f462a535a5a359057fa77 /libraries/relation.lib.php | |
parent | 20f1bf77c8281efc675a14e0f6bf52f657dabd9a (diff) |
UPDATE 4.3.34.3.3
Diffstat (limited to 'libraries/relation.lib.php')
-rw-r--r-- | libraries/relation.lib.php | 713 |
1 files changed, 528 insertions, 185 deletions
diff --git a/libraries/relation.lib.php b/libraries/relation.lib.php index 349eb49f8f..f4c5987e26 100644 --- a/libraries/relation.lib.php +++ b/libraries/relation.lib.php @@ -88,10 +88,7 @@ function PMA_getRelationsParamDiagnostic($cfgRelation) $messages = array(); $messages['error'] = '<font color="red"><strong>' . __('not OK') - . '</strong></font>' - . ' [ <a href="%s" target="documentation">' - . __('Documentation') - . '</a> ]'; + . '</strong></font>'; $messages['ok'] = '<font color="green"><strong>' . _pgettext('Correctly working', 'OK') @@ -101,12 +98,16 @@ function PMA_getRelationsParamDiagnostic($cfgRelation) $messages['disabled'] = '<font color="red">' . __('Disabled') . '</font>'; if (false === $GLOBALS['cfg']['Server']['pmadb']) { - $retval .= 'PMA Database ... ' - . sprintf($messages['error'], 'pmadb') + $retval .= __('Configuration of pmadb… ') + . $messages['error'] + . PMA_Util::showDocu('setup', 'linked-tables') . '<br />' . "\n" . __('General relation features') . ' <font color="green">' . __('Disabled') . '</font>' . "\n"; + if (! empty($GLOBALS['db']) && $GLOBALS['cfg']['ZeroConf']) { + $retval .= PMA_getHtmlFixPMATables(); + } } else { $retval .= '<table>' . "\n"; $retval .= PMA_getDiagMessageForParameter( @@ -150,7 +151,7 @@ function PMA_getRelationsParamDiagnostic($cfgRelation) 'pdf_pages' ); $retval .= PMA_getDiagMessageForFeature( - __('Creation of PDFs'), + __('Designer and creation of PDFs'), 'pdfwork', $messages ); @@ -172,8 +173,12 @@ function PMA_getRelationsParamDiagnostic($cfgRelation) $messages ); if ($cfgRelation['commwork'] && ! $cfgRelation['mimework']) { - $retval .= '<tr><td colspan=2 class="left">'; - $retval .= __('Please see the documentation on how to update your column_comments table.'); + $retval .= '<tr><td colspan=2 class="left error">'; + $retval .= __( + 'Please see the documentation on how to' + . ' update your column_info table. ' + ); + $retval .= PMA_Util::showDocu('config', 'cfg_Servers_column_info'); $retval .= '</td></tr>'; } $retval .= PMA_getDiagMessageForParameter( @@ -199,17 +204,6 @@ function PMA_getRelationsParamDiagnostic($cfgRelation) $messages ); $retval .= PMA_getDiagMessageForParameter( - 'designer_coords', - isset($cfgRelation['designer_coords']), - $messages, - 'designer_coords' - ); - $retval .= PMA_getDiagMessageForFeature( - __('Designer'), - 'designerwork', - $messages - ); - $retval .= PMA_getDiagMessageForParameter( 'recent', isset($cfgRelation['recent']), $messages, @@ -292,35 +286,53 @@ function PMA_getRelationsParamDiagnostic($cfgRelation) 'savedsearcheswork', $messages ); - $retval .= '</table>' . "\n"; - - $retval .= '<p>' . __('Quick steps to setup advanced features:') . '</p>'; - $retval .= '<ul>'; - $retval .= '<li>'; - $retval .= __( - 'Create the needed tables with the ' - . '<code>examples/create_tables.sql</code>.' - ); - $retval .= ' ' . PMA_Util::showDocu('setup', 'linked-tables'); - $retval .= '</li>'; - $retval .= '<li>'; - $retval .= __('Create a pma user and give access to these tables.'); - $retval .= ' ' . PMA_Util::showDocu('config', 'cfg_Servers_controluser'); - $retval .= '</li>'; - $retval .= '<li>'; - $retval .= __( - 'Enable advanced features in configuration file ' - . '(<code>config.inc.php</code>), for example by ' - . 'starting from <code>config.sample.inc.php</code>.' + $retval .= PMA_getDiagMessageForParameter( + 'central_columns', + isset($cfgRelation['central_columns']), + $messages, + 'central_columns' ); - $retval .= ' ' . PMA_Util::showDocu('setup', 'quick-install'); - $retval .= '</li>'; - $retval .= '<li>'; - $retval .= __( - 'Re-login to phpMyAdmin to load the updated configuration file.' + $retval .= PMA_getDiagMessageForFeature( + __('Managing Central list of columns'), + 'central_columnswork', + $messages ); - $retval .= '</li>'; - $retval .= '</ul>'; + $retval .= '</table>' . "\n"; + + if (! $cfgRelation['allworks']) { + + $retval .= '<p>' . __('Quick steps to setup advanced features:') + . '</p>'; + $retval .= '<ul>'; + $retval .= '<li>'; + $retval .= sprintf( + __( + 'Create the needed tables with the ' + . '<code>%screate_tables.sql</code>.' + ), + htmlspecialchars(EXAMPLES_DIR) + ); + $retval .= ' ' . PMA_Util::showDocu('setup', 'linked-tables'); + $retval .= '</li>'; + $retval .= '<li>'; + $retval .= __('Create a pma user and give access to these tables.'); + $retval .= ' ' . PMA_Util::showDocu('config', 'cfg_Servers_controluser'); + $retval .= '</li>'; + $retval .= '<li>'; + $retval .= __( + 'Enable advanced features in configuration file ' + . '(<code>config.inc.php</code>), for example by ' + . 'starting from <code>config.sample.inc.php</code>.' + ); + $retval .= ' ' . PMA_Util::showDocu('setup', 'quick-install'); + $retval .= '</li>'; + $retval .= '<li>'; + $retval .= __( + 'Re-login to phpMyAdmin to load the updated configuration file.' + ); + $retval .= '</li>'; + $retval .= '</ul>'; + } } return $retval; @@ -340,7 +352,9 @@ function PMA_getDiagMessageForFeature($feature_name, $relation_parameter, $messages, $skip_line = true ) { $retval = ' <tr><td colspan=2 class="right">' . $feature_name . ': '; - if ($GLOBALS['cfgRelation'][$relation_parameter]) { + if (isset($GLOBALS['cfgRelation'][$relation_parameter]) + && $GLOBALS['cfgRelation'][$relation_parameter] + ) { $retval .= $messages['enabled']; } else { $retval .= $messages['disabled']; @@ -402,27 +416,28 @@ function PMA_checkRelationsParam() $cfgRelation['recentwork'] = false; $cfgRelation['uiprefswork'] = false; $cfgRelation['trackingwork'] = false; - $cfgRelation['designerwork'] = false; $cfgRelation['userconfigwork'] = false; $cfgRelation['menuswork'] = false; $cfgRelation['navwork'] = false; $cfgRelation['allworks'] = false; $cfgRelation['savedsearcheswork'] = false; + $cfgRelation['central_columnswork'] = false; $cfgRelation['user'] = null; $cfgRelation['db'] = null; if ($GLOBALS['server'] == 0 || empty($GLOBALS['cfg']['Server']['pmadb']) - || ! $GLOBALS['dbi']->selectDb($GLOBALS['cfg']['Server']['pmadb'], $GLOBALS['controllink']) + || ! $GLOBALS['dbi']->selectDb( + $GLOBALS['cfg']['Server']['pmadb'], $GLOBALS['controllink'] + ) ) { // No server selected -> no bookmark table // we return the array with the falses in it, - // to avoid some 'Unitialized string offset' errors later + // to avoid some 'Uninitialized string offset' errors later $GLOBALS['cfg']['Server']['pmadb'] = false; return $cfgRelation; } - $cfgRelation['user'] = $GLOBALS['cfg']['Server']['user']; $cfgRelation['db'] = $GLOBALS['cfg']['Server']['pmadb']; @@ -454,8 +469,6 @@ function PMA_checkRelationsParam() $cfgRelation['table_info'] = $curr_table[0]; } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['table_coords']) { $cfgRelation['table_coords'] = $curr_table[0]; - } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['designer_coords']) { - $cfgRelation['designer_coords'] = $curr_table[0]; } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['column_info']) { $cfgRelation['column_info'] = $curr_table[0]; } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['pdf_pages']) { @@ -478,6 +491,8 @@ function PMA_checkRelationsParam() $cfgRelation['navigationhiding'] = $curr_table[0]; } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['savedsearches']) { $cfgRelation['savedsearches'] = $curr_table[0]; + } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['central_columns']) { + $cfgRelation['central_columns'] = $curr_table[0]; } } // end while $GLOBALS['dbi']->freeResult($tab_rs); @@ -495,7 +510,9 @@ function PMA_checkRelationsParam() if (isset($cfgRelation['column_info'])) { $cfgRelation['commwork'] = true; - $cfgRelation['mimework'] = true; + // phpMyAdmin 4.3+ + // Check for input transformations upgrade. + $cfgRelation['mimework'] = PMA_tryUpgradeTransformations(); } if (isset($cfgRelation['history'])) { @@ -518,12 +535,6 @@ function PMA_checkRelationsParam() $cfgRelation['userconfigwork'] = true; } - // we do not absolutely need that the internal relations or the PDF - // schema feature be activated - if (isset($cfgRelation['designer_coords'])) { - $cfgRelation['designerwork'] = true; - } - if (isset($cfgRelation['bookmark'])) { $cfgRelation['bookmarkwork'] = true; } @@ -540,12 +551,16 @@ function PMA_checkRelationsParam() $cfgRelation['savedsearcheswork'] = true; } + if (isset($cfgRelation['central_columns'])) { + $cfgRelation['central_columnswork'] = true; + } + if ($cfgRelation['relwork'] && $cfgRelation['displaywork'] && $cfgRelation['pdfwork'] && $cfgRelation['commwork'] && $cfgRelation['mimework'] && $cfgRelation['historywork'] && $cfgRelation['recentwork'] && $cfgRelation['uiprefswork'] && $cfgRelation['trackingwork'] && $cfgRelation['userconfigwork'] - && $cfgRelation['bookmarkwork'] && $cfgRelation['designerwork'] + && $cfgRelation['bookmarkwork'] && $cfgRelation['central_columnswork'] && $cfgRelation['menuswork'] && $cfgRelation['navwork'] && $cfgRelation['savedsearcheswork'] ) { @@ -556,6 +571,69 @@ function PMA_checkRelationsParam() } // end of the 'PMA_getRelationsParam()' function /** + * Check whether column_info table input transformation + * upgrade is required and try to upgrade silently + * + * @return bool false if upgrade failed + * + * @access public + */ +function PMA_tryUpgradeTransformations() +{ + // From 4.3, new input oriented transformation feature was introduced. + // Check whether column_info table has input transformation columns + $new_cols = array( + "input_transformation", + "input_transformation_options" + ); + $query = 'SHOW COLUMNS FROM ' + . PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb']) + . '.' . PMA_Util::backquote($GLOBALS['cfg']['Server']['column_info']) + . ' WHERE Field IN (\'' . implode('\', \'', $new_cols) . '\')'; + $result = PMA_queryAsControlUser( + $query, false, PMA_DatabaseInterface::QUERY_STORE + ); + if ($result) { + $rows = $GLOBALS['dbi']->numRows($result); + $GLOBALS['dbi']->freeResult($result); + // input transformations are present + // no need to upgrade + if ($rows === 2) { + return true; + // try silent upgrade without disturbing the user + } else { + // read upgrade query file + $query = @file_get_contents(EXAMPLES_DIR . 'upgrade_column_info_4_3_0+.sql'); + // replace database name from query to with set in config.inc.php + $query = str_replace( + '`phpmyadmin`', + PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb']), + $query + ); + // replace pma__column_info table name from query + // to with set in config.inc.php + $query = str_replace( + '`pma__column_info`', + PMA_Util::backquote($GLOBALS['cfg']['Server']['column_info']), + $query + ); + $GLOBALS['dbi']->tryMultiQuery($query, $GLOBALS['controllink']); + // skips result sets of query as we are not interested in it + while ($GLOBALS['dbi']->moreResults($GLOBALS['controllink']) + && $GLOBALS['dbi']->nextResult($GLOBALS['controllink']) + ) { + } + $error = $GLOBALS['dbi']->getError($GLOBALS['controllink']); + // return true if no error exists otherwise false + return empty($error); + } + } + // some failure, either in upgrading or something else + // make some noise, time to wake up user. + return false; +} + +/** * Gets all Relations to foreign tables for a given table or * optionally a given column in a table * @@ -583,7 +661,7 @@ function PMA_getForeigners($db, $table, $column = '', $source = 'both') . '.' . PMA_Util::backquote($cfgRelation['relation']) . ' WHERE `master_db` = \'' . PMA_Util::sqlAddSlashes($db) . '\' AND `master_table` = \'' . PMA_Util::sqlAddSlashes($table) . '\' '; - if (strlen($column)) { + if (/*overload*/mb_strlen($column)) { $rel_query .= ' AND `master_field` = ' . '\'' . PMA_Util::sqlAddSlashes($column) . '\''; } @@ -592,61 +670,26 @@ function PMA_getForeigners($db, $table, $column = '', $source = 'both') ); } - if (($source == 'both' || $source == 'foreign') && strlen($table)) { + if (($source == 'both' || $source == 'foreign') && /*overload*/mb_strlen($table) + ) { $showCreateTableQuery = 'SHOW CREATE TABLE ' . PMA_Util::backquote($db) . '.' . PMA_Util::backquote($table); $show_create_table = $GLOBALS['dbi']->fetchValue( $showCreateTableQuery, 0, 1 ); - $analyzed_sql = PMA_SQP_analyze(PMA_SQP_parse($show_create_table)); - - foreach ($analyzed_sql[0]['foreign_keys'] as $one_key) { - // The analyzer may return more than one column name in the - // index list or the ref_index_list; if this happens, - // the current logic just discards the whole index; having - // more than one index field is currently unsupported (see FAQ 3.6) - if (count($one_key['index_list']) == 1) { - foreach ($one_key['index_list'] as $i => $field) { - // If a foreign key is defined in the 'internal' source (pmadb) - // and as a native foreign key, we won't get it twice - // if $source='both' because we use $field as key - - // The parser looks for a CONSTRAINT clause just before - // the FOREIGN KEY clause. It finds it (as output from - // SHOW CREATE TABLE) in MySQL 4.0.13, but not in older - // versions like 3.23.58. - // In those cases, the FOREIGN KEY parsing will put numbers - // like -1, 0, 1... instead of the constraint number. - - if (isset($one_key['constraint'])) { - $foreign[$field]['constraint'] = $one_key['constraint']; - } - - if (isset($one_key['ref_db_name'])) { - $foreign[$field]['foreign_db'] = $one_key['ref_db_name']; - } else { - $foreign[$field]['foreign_db'] = $db; - } - $foreign[$field]['foreign_table'] = $one_key['ref_table_name']; - $foreign[$field]['foreign_field'] - = $one_key['ref_index_list'][$i]; - if (isset($one_key['on_delete'])) { - $foreign[$field]['on_delete'] = $one_key['on_delete']; - } - if (isset($one_key['on_update'])) { - $foreign[$field]['on_update'] = $one_key['on_update']; - } - } - } + if ($show_create_table) { + $analyzed_sql = PMA_SQP_analyze(PMA_SQP_parse($show_create_table)); + $foreign['foreign_keys_data'] = $analyzed_sql[0]['foreign_keys']; } } /** * Emulating relations for some information_schema and data_dictionary tables */ - $isInformationSchema = strtolower($db) == 'information_schema'; - $is_data_dictionary = PMA_DRIZZLE && strtolower($db) == 'data_dictionary'; + $isInformationSchema = /*overload*/mb_strtolower($db) == 'information_schema'; + $is_data_dictionary = PMA_DRIZZLE + && /*overload*/mb_strtolower($db) == 'data_dictionary'; if (($isInformationSchema || $is_data_dictionary) && ($source == 'internal' || $source == 'both') ) { @@ -659,8 +702,9 @@ function PMA_getForeigners($db, $table, $column = '', $source = 'both') } if (isset($GLOBALS[$relations_key][$table])) { foreach ($GLOBALS[$relations_key][$table] as $field => $relations) { - if ((! strlen($column) || $column == $field) - && (! isset($foreign[$field]) || ! strlen($foreign[$field])) + if ((! /*overload*/mb_strlen($column) || $column == $field) + && (! isset($foreign[$field]) + || ! /*overload*/mb_strlen($foreign[$field])) ) { $foreign[$field] = $relations; } @@ -843,7 +887,7 @@ function PMA_setDbComment($db, $comment = '') return false; } - if (strlen($comment)) { + if (/*overload*/mb_strlen($comment)) { $upd_query = 'INSERT INTO ' . PMA_Util::backquote($cfgRelation['db']) . '.' . PMA_Util::backquote($cfgRelation['column_info']) @@ -885,9 +929,10 @@ function PMA_setDbComment($db, $comment = '') */ function PMA_setHistory($db, $table, $username, $sqlquery) { + $maxCharactersInDisplayedSQL = $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']; // Prevent to run this automatically on Footer class destroying in testsuite if (defined('TESTSUITE') - || strlen($sqlquery) > $GLOBALS['cfg']['MaxCharactersInDisplayedSQL'] + || /*overload*/mb_strlen($sqlquery) > $maxCharactersInDisplayedSQL ) { return; } @@ -898,13 +943,7 @@ function PMA_setHistory($db, $table, $username, $sqlquery) $_SESSION['sql_history'] = array(); } - $key = md5($sqlquery . $db . $table); - - if (isset($_SESSION['sql_history'][$key])) { - unset($_SESSION['sql_history'][$key]); - } - - $_SESSION['sql_history'][$key] = array( + $_SESSION['sql_history'][] = array( 'db' => $db, 'table' => $table, 'sqlquery' => $sqlquery, @@ -935,6 +974,9 @@ function PMA_setHistory($db, $table, $username, $sqlquery) NOW(), \'' . PMA_Util::sqlAddSlashes($sqlquery) . '\')' ); + + PMA_purgeHistory($username); + } // end of 'PMA_setHistory()' function /** @@ -950,22 +992,26 @@ function PMA_getHistory($username) { $cfgRelation = PMA_getRelationsParam(); + if (! $cfgRelation['historywork']) { + return false; + } + /** * if db-based history is disabled but there exists a session-based * history, use it */ - if (! $GLOBALS['cfg']['QueryHistoryDB'] && isset($_SESSION['sql_history'])) { + if (! $GLOBALS['cfg']['QueryHistoryDB']) { + if (isset($_SESSION['sql_history'])) { return array_reverse($_SESSION['sql_history']); - } - - if (! $cfgRelation['historywork']) { + } return false; } $hist_query = ' SELECT `db`, `table`, - `sqlquery` + `sqlquery`, + `timevalue` FROM ' . PMA_Util::backquote($cfgRelation['db']) . '.' . PMA_Util::backquote($cfgRelation['history']) . ' WHERE `username` = \'' . PMA_Util::sqlAddSlashes($username) . '\' @@ -1007,7 +1053,9 @@ function PMA_purgeHistory($username) ORDER BY `timevalue` DESC LIMIT ' . $GLOBALS['cfg']['QueryHistoryMax'] . ', 1'; - if ($max_time = $GLOBALS['dbi']->fetchValue($search_query, 0, 0, $GLOBALS['controllink'])) { + if ($max_time = $GLOBALS['dbi']->fetchValue( + $search_query, 0, 0, $GLOBALS['controllink'] + )) { PMA_queryAsControlUser( 'DELETE FROM ' . PMA_Util::backquote($cfgRelation['db']) . '.' @@ -1052,14 +1100,16 @@ function PMA_buildForeignDropdown($foreign, $data, $mode) } foreach ($foreign as $key => $value) { - if ($GLOBALS['PMA_String']->strlen($value) <= $GLOBALS['cfg']['LimitChars'] + if (/*overload*/mb_strlen($value) <= $GLOBALS['cfg']['LimitChars'] ) { $vtitle = ''; $value = htmlspecialchars($value); } else { $vtitle = htmlspecialchars($value); $value = htmlspecialchars( - substr($value, 0, $GLOBALS['cfg']['LimitChars']) . '...' + /*overload*/mb_substr( + $value, 0, $GLOBALS['cfg']['LimitChars'] + ) . '...' ); } @@ -1171,11 +1221,11 @@ function PMA_foreignDropdown($disp_row, $foreign_field, $foreign_display, $data, /** * Gets foreign keys in preparation for a drop-down selector * - * @param array $foreigners array of the foreign keys - * @param string $field the foreign field name - * @param bool $override_total whether to override the total - * @param string $foreign_filter a possible filter - * @param string $foreign_limit a possible LIMIT clause + * @param array|boolean $foreigners array of the foreign keys + * @param string $field the foreign field name + * @param bool $override_total whether to override the total + * @param string $foreign_filter a possible filter + * @param string $foreign_limit a possible LIMIT clause * * @return array data about the foreign keys * @@ -1188,11 +1238,18 @@ function PMA_getForeignData( // we always show the foreign field in the drop-down; if a display // field is defined, we show it besides the foreign field $foreign_link = false; - if ($foreigners && isset($foreigners[$field])) { - $foreigner = $foreigners[$field]; - $foreign_db = $foreigner['foreign_db']; - $foreign_table = $foreigner['foreign_table']; - $foreign_field = $foreigner['foreign_field']; + do { + if (! $foreigners) { + break; + } + $foreigner = PMA_searchColumnInForeigners($foreigners, $field); + if ($foreigner != false) { + $foreign_db = $foreigner['foreign_db']; + $foreign_table = $foreigner['foreign_table']; + $foreign_field = $foreigner['foreign_field']; + } else { + break; + } // Count number of rows in the foreign table. Currently we do // not use a drop-down if more than ForeignKeyMaxLimit rows in the @@ -1234,18 +1291,15 @@ function PMA_getForeignData( $f_query_limit = isset($foreign_limit) ? $foreign_limit : ''; if (!empty($foreign_filter)) { - $res = $GLOBALS['dbi']->query( + $the_total = $GLOBALS['dbi']->fetchValue( 'SELECT COUNT(*)' . $f_query_from . $f_query_filter ); - if ($res) { - $the_total = $GLOBALS['dbi']->fetchValue($res); - @$GLOBALS['dbi']->freeResult($res); - } else { + if ($the_total === false) { $the_total = 0; } } - $disp = $GLOBALS['dbi']->query( + $disp = $GLOBALS['dbi']->tryQuery( $f_query_main . $f_query_from . $f_query_filter . $f_query_order . $f_query_limit ); @@ -1259,12 +1313,18 @@ function PMA_getForeignData( $disp_row[] = $single_disp_row; } @$GLOBALS['dbi']->freeResult($disp); + } else { + // Either no data in the foreign table or + // user does not have select permission to foreign table/field + // Show an input field with a 'Browse foreign values' link + $disp_row = null; + $foreign_link = true; } } else { $disp_row = null; $foreign_link = true; } - } // end if $foreigners + } while (false); $foreignData = array(); $foreignData['foreign_link'] = $foreign_link; @@ -1289,16 +1349,18 @@ function PMA_getForeignData( function PMA_getRelatives($all_tables, $master) { $fromclause = ''; + $left_joins = array(); $emerg = ''; + $ignore_internal_relations = false; // The list of tables that we still couldn't connect $remaining_tables = $all_tables; unset($remaining_tables[$master]); - // The list of allready connected tables + // The list of already connected tables $known_tables = array(); $known_tables[$master] = $master; $run = 0; - while (count($remaining_tables) > 0) { + while ($GLOBALS['cfgRelation']['relwork'] && count($remaining_tables) > 0) { // Whether to go from master to foreign or vice versa if ($run % 2 == 0) { $from = 'master'; @@ -1322,14 +1384,18 @@ function PMA_getRelatives($all_tables, $master) while ($row = $GLOBALS['dbi']->fetchAssoc($relations)) { $found_table = $row[$to . '_table']; if (isset($remaining_tables[$found_table])) { - $fromclause - .= "\n" . ' LEFT JOIN ' - . PMA_Util::backquote($GLOBALS['db']) . '.' - . PMA_Util::backquote($row[$to . '_table']) . ' ON ' - . PMA_Util::backquote($row[$from . '_table']) . '.' + $left_join_with = PMA_Util::backquote($GLOBALS['db']) . '.' + . PMA_Util::backquote($row[$to . '_table']); + $on_condition = PMA_Util::backquote($row[$from . '_table']) . '.' . PMA_Util::backquote($row[$from . '_field']) . ' = ' . PMA_Util::backquote($row[$to . '_table']) . '.' - . PMA_Util::backquote($row[$to . '_field']) . ' '; + . PMA_Util::backquote($row[$to . '_field']); + + $left_joins[$left_join_with] = array( + 'left_join_with' => $left_join_with, + 'on_condition' => array($on_condition) + ); + $known_tables[$found_table] = $found_table; unset($remaining_tables[$found_table]); } @@ -1342,6 +1408,55 @@ function PMA_getRelatives($all_tables, $master) } } } // end while + + // Generate 'LEFT JOIN's for InnoDB foreign keys. + $remaining_tables = $all_tables; + foreach ($remaining_tables as $one_table) { + $foreigners = PMA_getForeigners($GLOBALS['db'], $one_table, '', 'foreign'); + foreach ($foreigners['foreign_keys_data'] as $one_key) { + if (in_array($one_key['ref_table_name'], $all_tables) + && ! isset($one_key['ref_db_name']) + && ($one_key['ref_table_name'] == $master + || $one_key['ref_table_name'] == $one_table) + ) { + $left_join_with = PMA_Util::backquote($GLOBALS['db']) . '.' + . PMA_Util::backquote($one_table); + if (! isset($left_joins[$left_join_with])) { + $left_joins[$left_join_with] = array( + 'left_join_with' =>$left_join_with, + 'on_condition' => array() + ); + } + + foreach ($one_key['ref_index_list'] as $key => $one_column) { + $on_condition = PMA_Util::backquote($one_key['ref_table_name']) + . '.' . PMA_Util::backquote($one_column) . ' = ' + . PMA_Util::backquote($one_table) . '.' + . PMA_Util::backquote($one_key['index_list'][$key]); + + if (! in_array($on_condition, $left_joins[$left_join_with]['on_condition'])) { + $left_joins[$left_join_with]['on_condition'][] + = $on_condition; + } + } + $ignore_internal_relations = true; + unset($remaining_tables[$one_table]); + } + } + } + + if ($ignore_internal_relations) { + $emerg = ''; + } + + // Build the 'FROM' clause. + foreach ($left_joins as $one_join) { + $fromclause .= "\n" . ' LEFT JOIN ' + . $one_join['left_join_with'] + . ' ON ' + . implode(' AND ', $one_join['on_condition']); + } + $fromclause = $emerg . $fromclause; return $fromclause; } // end of the "PMA_getRelatives()" function @@ -1495,15 +1610,6 @@ function PMA_REL_renameTable($source_db, $target_db, $source_table, $target_tabl 'db_name', 'table_name' ); } - - if ($GLOBALS['cfgRelation']['designerwork']) { - PMA_REL_renameSingleTable( - 'designer_coords', - $source_db, $target_db, - $source_table, $target_table, - 'db_name', 'table_name' - ); - } } /** @@ -1536,6 +1642,7 @@ function PMA_REL_createPage($newpage, $cfgRelation, $db) /** * Get child table references for a table column. + * This works only if 'DisableIS' is false. An empty array is returned otherwise. * * @param string $db name of master table db. * @param string $table name of master table. @@ -1543,26 +1650,26 @@ function PMA_REL_createPage($newpage, $cfgRelation, $db) * * @return array $child_references */ -function PMA_getChildReferences($db, $table, $column) +function PMA_getChildReferences($db, $table, $column = '') { $child_references = array(); - $i=0; - $rel_query = 'SELECT `column_name`,' - . ' `table_name`,' - . '`table_schema`' - . ' FROM `information_schema`.`key_column_usage`' - . ' WHERE `referenced_column_name` = \'' - . PMA_Util::sqlAddSlashes($column) . '\'' - . ' AND `referenced_table_name` = \'' - . PMA_Util::sqlAddSlashes($table) . '\'' - . ' AND `referenced_table_schema` = \'' - . PMA_Util::sqlAddSlashes($db) . '\''; - - $result = $GLOBALS['dbi']->tryQuery($rel_query, $GLOBALS['controllink']); - if ($result == true) { - while (($row = $GLOBALS['dbi']->fetchAssoc($result))) { - $child_references[$i++] = $row; + if (! $GLOBALS['cfg']['Server']['DisableIS']) { + $rel_query = "SELECT `column_name`, `table_name`," + . " `table_schema`, `referenced_column_name`" + . " FROM `information_schema`.`key_column_usage`" + . " WHERE `referenced_table_name` = '" + . PMA_Util::sqlAddSlashes($table) . "'" + . " AND `referenced_table_schema` = '" + . PMA_Util::sqlAddSlashes($db) . "'"; + if ($column) { + $rel_query .= " AND `referenced_column_name` = '" + . PMA_Util::sqlAddSlashes($column) . "'"; } + + $child_references = $GLOBALS['dbi']->fetchResult( + $rel_query, array('referenced_column_name', null), + null, $GLOBALS['controllink'] + ); } return $child_references; } @@ -1570,24 +1677,47 @@ function PMA_getChildReferences($db, $table, $column) /** * Check child table references and foreign key for a table column. * - * @param string $db name of master table db. - * @param string $table name of master table. - * @param string $column name of master table column. + * @param string $db name of master table db. + * @param string $table name of master table. + * @param string $column name of master table column. + * @param array $foreigners_full foreiners array for the whole table. + * @param array $child_references_full child references for the whole table. * * @return array $column_status telling about references if foreign key. */ -function PMA_checkChildForeignReferences($db, $table, $column) -{ +function PMA_checkChildForeignReferences( + $db, $table, $column, $foreigners_full = null, $child_references_full = null +) { $column_status = array(); $column_status['isEditable'] = false; $column_status['isReferenced'] = false; $column_status['isForeignKey'] = false; $column_status['references'] = array(); - $foreigners = PMA_getForeigners($db, $table, $column); - $child_references = PMA_getChildReferences($db, $table, $column); + + $foreigners = array(); + if ($foreigners_full !== null) { + if (isset($foreigners_full[$column])) { + $foreigners[$column] = $foreigners_full[$column]; + } + if (isset($foreigners_full['foreign_keys_data'])) { + $foreigners['foreign_keys_data'] = $foreigners_full['foreign_keys_data']; + } + } else { + $foreigners = PMA_getForeigners($db, $table, $column, 'foreign'); + } + $foreigner = PMA_searchColumnInForeigners($foreigners, $column); + + $child_references = array(); + if ($child_references_full !== null) { + if (isset($child_references_full[$column])) { + $child_references = $child_references_full[$column]; + } + } else { + $child_references = PMA_getChildReferences($db, $table, $column); + } if (sizeof($child_references, 0) > 0 - || (! empty($foreigners[$column]) && sizeof($foreigners[$column], 0) > 0) + || $foreigner ) { if (sizeof($child_references, 0) > 0) { $column_status['isReferenced'] = true; @@ -1600,7 +1730,7 @@ function PMA_checkChildForeignReferences($db, $table, $column) } } - if (!empty($foreigners[$column]) && sizeof($foreigners[$column], 0) > 0) { + if ($foreigner) { $column_status['isForeignKey'] = true; } } else { @@ -1609,4 +1739,217 @@ function PMA_checkChildForeignReferences($db, $table, $column) return $column_status; } + +/** + * Search a table column in foreign data. + * + * @param array $foreigners Table Foreign data + * @param string $column Column name + * + * @return bool|array + */ +function PMA_searchColumnInForeigners($foreigners, $column) +{ + if (isset($foreigners[$column])) { + return $foreigners[$column]; + } else { + $foreigner = array(); + foreach ($foreigners['foreign_keys_data'] as $key => $one_key) { + $column_index = array_search($column, $one_key['index_list']); + if ($column_index !== false) { + $foreigner['foreign_field'] + = $one_key['ref_index_list'][$column_index]; + $foreigner['foreign_db'] = isset($one_key['ref_db_name']) + ? $one_key['ref_db_name'] + : $GLOBALS['db']; + $foreigner['foreign_table'] = $one_key['ref_table_name']; + $foreigner['constraint'] = $one_key['constraint']; + + return $foreigner; + } + } + } + + return false; +} + +/** + * Searches a DB for the existence of PMA tables. + * + * @param string $db Database + * @param array $tables Default table names + * + * @return bool + */ +function PMA_searchPMATablesInDb($db, $tables) +{ + $tab_rs = $GLOBALS['dbi']->getTables($db); + + if ($tab_rs === false) { + return false; + } + + foreach ($tab_rs as $curr_table) { + if (in_array($curr_table, $tables)) { + $tables = array_diff($tables, array($curr_table)); + } + } + + if (count($tables) != 0) { + return false; + } + + return true; +} + +/** + * Returns default PMA table names and their create queries. + * + * @return array table name, create query + */ +function PMA_getDefaultPMATableNames() +{ + $pma_tables = array(); + if (PMA_DRIZZLE) { + $create_tables_file = file_get_contents( + EXAMPLES_DIR. 'create_tables_drizzle.sql' + ); + } else { + $create_tables_file = file_get_contents( + EXAMPLES_DIR. 'create_tables.sql' + ); + } + + $queries = explode(';', $create_tables_file); + + foreach ($queries as $query) { + if (preg_match( + '/CREATE TABLE IF NOT EXISTS `(.*)` \(/', + $query, + $table + ) + ) { + $pma_tables[$table[1]] = $query . ';'; + } + } + + return $pma_tables; +} + +/** + * Creates PMA tables in the given db, updates if already exists. + * + * @param string $db Database + * + * @return void + */ +function PMA_fixPMATables($db) +{ + $default_tables = PMA_getDefaultPMATableNames(); + $GLOBALS['dbi']->selectDb($db); + + foreach ($default_tables as $table => $create_query) { + $GLOBALS['dbi']->tryQuery($create_query); + + if ($error = $GLOBALS['dbi']->getError()) { + $GLOBALS['message'] = $error; + break; + } + + if ($table == 'pma__bookmark') { + $GLOBALS['cfg']['Server']['bookmarktable'] = $table; + } elseif ($table == 'pma__relation') { + $GLOBALS['cfg']['Server']['relation'] = $table; + } elseif ($table == 'pma__table_info') { + $GLOBALS['cfg']['Server']['table_info'] = $table; + } elseif ($table == 'pma__table_coords') { + $GLOBALS['cfg']['Server']['table_coords'] = $table; + } elseif ($table == 'pma__column_info') { + $GLOBALS['cfg']['Server']['column_info'] = $table; + } elseif ($table == 'pma__pdf_pages') { + $GLOBALS['cfg']['Server']['pdf_pages'] = $table; + } elseif ($table == 'pma__history') { + $GLOBALS['cfg']['Server']['history'] = $table; + } elseif ($table == 'pma__recent') { + $GLOBALS['cfg']['Server']['recent'] = $table; + } elseif ($table == 'pma__table_uiprefs') { + $GLOBALS['cfg']['Server']['table_uiprefs'] = $table; + } elseif ($table == 'pma__tracking') { + $GLOBALS['cfg']['Server']['tracking'] = $table; + } elseif ($table == 'pma__userconfig') { + $GLOBALS['cfg']['Server']['userconfig'] = $table; + } elseif ($table == 'pma__users') { + $GLOBALS['cfg']['Server']['users'] = $table; + } elseif ($table == 'pma__usergroups') { + $GLOBALS['cfg']['Server']['usergroups'] = $table; + } elseif ($table == 'pma__navigationhiding') { + $GLOBALS['cfg']['Server']['navigationhiding'] = $table; + } elseif ($table == 'pma__savedsearches') { + $GLOBALS['cfg']['Server']['savedsearches'] = $table; + } elseif ($table == 'pma__central_columns') { + $GLOBALS['cfg']['Server']['central_columns'] = $table; + } else if ($table == 'pma__designer_coords') { + $GLOBALS['cfg']['Server']['designer_coords'] = $table; + } + } + $GLOBALS['cfg']['Server']['pmadb'] = $db; + $_SESSION['relation'][$GLOBALS['server']] = PMA_checkRelationsParam(); +} + +/** + * Get Html for PMA tables fixing anchor. + * + * @return string Html + */ +function PMA_getHtmlFixPMATables() +{ + $retval = ''; + + $url_query = PMA_URL_getCommon(array('db' => $GLOBALS['db'])); + $url_query .= '&goto=db_operations.php&fix_pmadb=1'; + $message = PMA_Message::notice( + __( + '%sCreate%s the phpMyAdmin configuration storage in the ' + . 'current database.' + ) + ); + $message->addParam( + '<a href="' . $GLOBALS['cfg']['PmaAbsoluteUri'] + . 'chk_rel.php' . $url_query . '">', + false + ); + $message->addParam('</a>', false); + + $retval .= $message->getDisplay(); + + return $retval; +} + +/** + * Gets the relations info and status, depending on the condition + * + * @param boolean $condition whether to look for foreigners or not + * @param string $db database name + * @param string $table table name + * + * @return array ($res_rel, $have_rel) + */ +function PMA_getRelationsAndStatus($condition, $db, $table) +{ + if ($condition) { + // Find which tables are related with the current one and write it in + // an array + $res_rel = PMA_getForeigners($db, $table); + + if (count($res_rel) > 0) { + $have_rel = true; + } else { + $have_rel = false; + } + } else { + $have_rel = false; + $res_rel = array(); + } // end if + return(array($res_rel, $have_rel)); +} ?> |