/** * Set the content need to be show in message * * @param string $sorted_column_message the message for sorted column * @param string $limit_clause the limit clause of analyzed query * @param integer $total the total number of rows returned by * the SQL query without any * programmatically appended LIMIT clause * @param integer $pos_next the offset for next page * @param string $pre_count the string renders before row count * @param string $after_count the string renders after row count * * @return PMA_Message $message an object of PMA_Message * * @access private * * @see getTable() */ private function _setMessageInformation($sorted_column_message, $limit_clause, $total, $pos_next, $pre_count, $after_count) { $unlim_num_rows = $this->__get('_unlim_num_rows'); // To use in isset() if (isset($unlim_num_rows) && $unlim_num_rows != $total) { $selectstring = ', ' . $unlim_num_rows . ' ' . __('in query'); } else { $selectstring = ''; } if (!empty($limit_clause)) { $limit_data = $this->getCommonFunctions()->analyzeLimitClause($limit_clause); $first_shown_rec = $limit_data['start']; if ($limit_data['length'] < $total) { $last_shown_rec = $limit_data['start'] + $limit_data['length'] - 1; } else { $last_shown_rec = $limit_data['start'] + $total - 1; } } elseif ($_SESSION['tmp_user_values']['max_rows'] == self::ALL_ROWS || $pos_next > $total) { $first_shown_rec = $_SESSION['tmp_user_values']['pos']; $last_shown_rec = $total - 1; } else { $first_shown_rec = $_SESSION['tmp_user_values']['pos']; $last_shown_rec = $pos_next - 1; } if (PMA_Table::isView($this->__get('_db'), $this->__get('_table')) && $total == $GLOBALS['cfg']['MaxExactCountViews']) { $message = PMA_Message::notice(__('This view has at least this number of rows. ' . 'Please refer to %sdocumentation%s.')); $message->addParam('[a@./Documentation.html#cfg_MaxExactCount@_blank]'); $message->addParam('[/a]'); $message_view_warning = $this->getCommonFunctions()->showHint($message); } else { $message_view_warning = false; } $message = PMA_Message::success(__('Showing rows')); $message->addMessage($first_shown_rec); if ($message_view_warning) { $message->addMessage('...', ' - '); $message->addMessage($message_view_warning); $message->addMessage('('); } else { $message->addMessage($last_shown_rec, ' - '); $message->addMessage(' ('); $message->addMessage($pre_count . $this->getCommonFunctions()->formatNumber($total, 0)); $message->addString(__('total')); if (!empty($after_count)) { $message->addMessage($after_count); } $message->addMessage($selectstring, ''); $message->addMessage(', ', ''); } $messagge_qt = PMA_Message::notice(__('Query took %01.4f sec') . ')'); $messagge_qt->addParam($this->__get('_querytime')); $message->addMessage($messagge_qt, ''); if (!is_null($sorted_column_message)) { $message->addMessage($sorted_column_message, ''); } return $message; }
/** * Counts and returns (or displays) the number of records in a table * * Revision 13 July 2001: Patch for limiting dump size from * vinay@sanisoft.com & girish@sanisoft.com * * @param string the current database name * @param string the current table name * @param boolean whether to force an exact count * * @return mixed the number of records if "retain" param is true, * otherwise true * * @access public */ public static function countRecords($db, $table, $force_exact = false, $is_view = null) { if (isset(PMA_Table::$cache[$db][$table]['ExactRows'])) { $row_count = PMA_Table::$cache[$db][$table]['ExactRows']; } else { $row_count = false; if (null === $is_view) { $is_view = PMA_Table::isView($db, $table); } if (!$force_exact) { if (!isset(PMA_Table::$cache[$db][$table]['Rows']) && !$is_view) { PMA_Table::$cache[$db][$table] = PMA_DBI_fetch_single_row('SHOW TABLE STATUS FROM ' . PMA_backquote($db) . ' LIKE \'' . PMA_sqlAddslashes($table, true) . '\''); } $row_count = PMA_Table::$cache[$db][$table]['Rows']; } // for a VIEW, $row_count is always false at this point if (false === $row_count || $row_count < $GLOBALS['cfg']['MaxExactCount']) { if (!$is_view) { $row_count = PMA_DBI_fetch_value('SELECT COUNT(*) FROM ' . PMA_backquote($db) . '.' . PMA_backquote($table)); } else { // For complex views, even trying to get a partial record // count could bring down a server, so we offer an // alternative: setting MaxExactCountViews to 0 will bypass // completely the record counting for views if ($GLOBALS['cfg']['MaxExactCountViews'] == 0) { $row_count = 0; } else { // Counting all rows of a VIEW could be too long, so use // a LIMIT clause. // Use try_query because it can fail (when a VIEW is // based on a table that no longer exists) $result = PMA_DBI_try_query('SELECT 1 FROM ' . PMA_backquote($db) . '.' . PMA_backquote($table) . ' LIMIT ' . $GLOBALS['cfg']['MaxExactCountViews'], null, PMA_DBI_QUERY_STORE); if (!PMA_DBI_getError()) { $row_count = PMA_DBI_num_rows($result); PMA_DBI_free_result($result); } } } PMA_Table::$cache[$db][$table]['ExactRows'] = $row_count; } } return $row_count; }
/** * Set the content that needs to be shown in message * * @param string $sorted_column_message the message for sorted column * @param string $limit_clause the limit clause of analyzed query * @param integer $total the total number of rows returned by * the SQL query without any * programmatically appended LIMIT clause * @param integer $pos_next the offset for next page * @param string $pre_count the string renders before row count * @param string $after_count the string renders after row count * * @return PMA_Message $message an object of PMA_Message * * @access private * * @see getTable() */ private function _setMessageInformation($sorted_column_message, $limit_clause, $total, $pos_next, $pre_count, $after_count) { $unlim_num_rows = $this->__get('unlim_num_rows'); // To use in isset() if (!empty($limit_clause)) { $limit_data = PMA_Util::analyzeLimitClause($limit_clause); $first_shown_rec = $limit_data['start']; if ($limit_data['length'] < $total) { $last_shown_rec = $limit_data['start'] + $limit_data['length'] - 1; } else { $last_shown_rec = $limit_data['start'] + $total - 1; } } elseif ($_SESSION['tmpval']['max_rows'] == self::ALL_ROWS || $pos_next > $total) { $first_shown_rec = $_SESSION['tmpval']['pos']; $last_shown_rec = $total - 1; } else { $first_shown_rec = $_SESSION['tmpval']['pos']; $last_shown_rec = $pos_next - 1; } if (PMA_Table::isView($this->__get('db'), $this->__get('table')) && $total == $GLOBALS['cfg']['MaxExactCountViews']) { $message = PMA_Message::notice(__('This view has at least this number of rows. ' . 'Please refer to %sdocumentation%s.')); $message->addParam('[doc@cfg_MaxExactCount]'); $message->addParam('[/doc]'); $message_view_warning = PMA_Util::showHint($message); } else { $message_view_warning = false; } $message = PMA_Message::success(__('Showing rows %1s - %2s')); $message->addParam($first_shown_rec); if ($message_view_warning) { $message->addParam('... ' . $message_view_warning, false); } else { $message->addParam($last_shown_rec); } $message->addMessage('('); if (!$message_view_warning) { if (isset($unlim_num_rows) && $unlim_num_rows != $total) { $message_total = PMA_Message::notice($pre_count . __('%1$d total, %2$d in query')); $message_total->addParam($total); $message_total->addParam($unlim_num_rows); } else { $message_total = PMA_Message::notice($pre_count . __('%d total')); $message_total->addParam($total); } if (!empty($after_count)) { $message_total->addMessage($after_count); } $message->addMessage($message_total, ''); $message->addMessage(', ', ''); } $message_qt = PMA_Message::notice(__('Query took %01.4f seconds.') . ')'); $message_qt->addParam($this->__get('querytime')); $message->addMessage($message_qt, ''); if (!is_null($sorted_column_message)) { $message->addMessage($sorted_column_message, ''); } return $message; }
/** * Displays a table of results returned by a SQL query. * This function is called by the "sql.php" script. * * @param integer the link id associated to the query which results have * to be displayed * @param array the display mode * @param array the analyzed query * * @uses $_SESSION['tmp_user_values']['pos'] * @global string $db the database name * @global string $table the table name * @global string $goto the URL to go back in case of errors * @global string $sql_query the current SQL query * @global integer $num_rows the total number of rows returned by the * SQL query * @global integer $unlim_num_rows the total number of rows returned by the * SQL query without any programmatically * appended "LIMIT" clause * @global array $fields_meta the list of fields properties * @global integer $fields_cnt the total number of fields returned by * the SQL query * @global array $vertical_display informations used with vertical display * mode * @global array $highlight_columns column names to highlight * @global array $cfgRelation the relation settings * * @access private * * @see PMA_showMessage(), PMA_setDisplayMode(), * PMA_displayTableNavigation(), PMA_displayTableHeaders(), * PMA_displayTableBody(), PMA_displayResultsOperations() */ function PMA_displayTable(&$dt_result, &$the_disp_mode, $analyzed_sql) { global $db, $table, $goto; global $sql_query, $num_rows, $unlim_num_rows, $fields_meta, $fields_cnt; global $vertical_display, $highlight_columns; global $cfgRelation; global $showtable; // why was this called here? (already called from sql.php) //PMA_displayTable_checkConfigParams(); /** * @todo move this to a central place * @todo for other future table types */ $is_innodb = isset($showtable['Type']) && $showtable['Type'] == 'InnoDB'; if ($is_innodb && !isset($analyzed_sql[0]['queryflags']['union']) && !isset($analyzed_sql[0]['table_ref'][1]['table_name']) && (empty($analyzed_sql[0]['where_clause']) || $analyzed_sql[0]['where_clause'] == '1 ')) { // "j u s t b r o w s i n g" $pre_count = '~'; $after_count = PMA_showHint(PMA_sanitize($GLOBALS['strApproximateCount']), true); } else { $pre_count = ''; $after_count = ''; } // 1. ----- Prepares the work ----- // 1.1 Gets the informations about which functionalities should be // displayed $total = ''; $is_display = PMA_setDisplayMode($the_disp_mode, $total); // 1.2 Defines offsets for the next and previous pages if ($is_display['nav_bar'] == '1') { if ($_SESSION['tmp_user_values']['max_rows'] == 'all') { $pos_next = 0; $pos_prev = 0; } else { $pos_next = $_SESSION['tmp_user_values']['pos'] + $_SESSION['tmp_user_values']['max_rows']; $pos_prev = $_SESSION['tmp_user_values']['pos'] - $_SESSION['tmp_user_values']['max_rows']; if ($pos_prev < 0) { $pos_prev = 0; } } } // end if // 1.3 Find the sort expression // we need $sort_expression and $sort_expression_nodirection // even if there are many table references if (!empty($analyzed_sql[0]['order_by_clause'])) { $sort_expression = trim(str_replace(' ', ' ', $analyzed_sql[0]['order_by_clause'])); /** * Get rid of ASC|DESC */ preg_match('@(.*)([[:space:]]*(ASC|DESC))@si', $sort_expression, $matches); $sort_expression_nodirection = isset($matches[1]) ? trim($matches[1]) : $sort_expression; $sort_direction = isset($matches[2]) ? trim($matches[2]) : ''; unset($matches); } else { $sort_expression = $sort_expression_nodirection = $sort_direction = ''; } // 1.4 Prepares display of first and last value of the sorted column if (!empty($sort_expression_nodirection)) { list($sort_table, $sort_column) = explode('.', $sort_expression_nodirection); $sort_table = PMA_unQuote($sort_table); $sort_column = PMA_unQuote($sort_column); // find the sorted column index in row result // (this might be a multi-table query) $sorted_column_index = false; foreach ($fields_meta as $key => $meta) { if ($meta->table == $sort_table && $meta->name == $sort_column) { $sorted_column_index = $key; break; } } if ($sorted_column_index !== false) { // fetch first row of the result set $row = PMA_DBI_fetch_row($dt_result); $column_for_first_row = substr($row[$sorted_column_index], 0, $GLOBALS['cfg']['LimitChars']); // fetch last row of the result set PMA_DBI_data_seek($dt_result, $num_rows - 1); $row = PMA_DBI_fetch_row($dt_result); $column_for_last_row = substr($row[$sorted_column_index], 0, $GLOBALS['cfg']['LimitChars']); // reset to first row for the loop in PMA_displayTableBody() PMA_DBI_data_seek($dt_result, 0); // we could also use here $sort_expression_nodirection $sorted_column_message = ' [' . htmlspecialchars($sort_column) . ': <strong>' . htmlspecialchars($column_for_first_row) . ' - ' . htmlspecialchars($column_for_last_row) . '</strong>]'; unset($row, $column_for_first_row, $column_for_last_row); } unset($sorted_column_index, $sort_table, $sort_column); } // 2. ----- Displays the top of the page ----- // 2.1 Displays a messages with position informations if ($is_display['nav_bar'] == '1' && isset($pos_next)) { if (isset($unlim_num_rows) && $unlim_num_rows != $total) { $selectstring = ', ' . $unlim_num_rows . ' ' . $GLOBALS['strSelectNumRows']; } else { $selectstring = ''; } $last_shown_rec = $_SESSION['tmp_user_values']['max_rows'] == 'all' || $pos_next > $total ? $total - 1 : $pos_next - 1; if (PMA_Table::isView($db, $table) && $total == $GLOBALS['cfg']['MaxExactCountViews']) { $message = PMA_Message::notice('strViewHasAtLeast'); $message->addParam('[a@./Documentation.html#cfg_MaxExactCount@_blank]'); $message->addParam('[/a]'); $message_view_warning = PMA_showHint($message); } else { $message_view_warning = false; } $message = PMA_Message::success('strShowingRecords'); $message->addMessage($_SESSION['tmp_user_values']['pos']); if ($message_view_warning) { $message->addMessage('...', ' - '); $message->addMessage($message_view_warning); $message->addMessage('('); } else { $message->addMessage($last_shown_rec, ' - '); $message->addMessage($pre_count . PMA_formatNumber($total, 0) . $after_count, ' ('); $message->addString('strTotal'); $message->addMessage($selectstring, ''); $message->addMessage(', ', ''); } $messagge_qt = PMA_Message::notice('strQueryTime'); $messagge_qt->addParam($GLOBALS['querytime']); $message->addMessage($messagge_qt, ''); $message->addMessage(')', ''); $message->addMessage(isset($sorted_column_message) ? $sorted_column_message : '', ''); PMA_showMessage($message, $sql_query, 'success'); } elseif (!isset($GLOBALS['printview']) || $GLOBALS['printview'] != '1') { PMA_showMessage($GLOBALS['strSuccess'], $sql_query, 'success'); } // 2.3 Displays the navigation bars if (!strlen($table)) { if (isset($analyzed_sql[0]['query_type']) && $analyzed_sql[0]['query_type'] == 'SELECT') { // table does not always contain a real table name, // for example in MySQL 5.0.x, the query SHOW STATUS // returns STATUS as a table name $table = $fields_meta[0]->table; } else { $table = ''; } } if ($is_display['nav_bar'] == '1') { PMA_displayTableNavigation($pos_next, $pos_prev, $sql_query, 'top_direction_dropdown'); echo "\n"; } elseif (!isset($GLOBALS['printview']) || $GLOBALS['printview'] != '1') { echo "\n" . '<br /><br />' . "\n"; } // 2b ----- Get field references from Database ----- // (see the 'relation' configuration variable) // loic1, 2002-03-02: extended to php3 // initialize map $map = array(); // find tables $target = array(); if (isset($analyzed_sql[0]['table_ref']) && is_array($analyzed_sql[0]['table_ref'])) { foreach ($analyzed_sql[0]['table_ref'] as $table_ref_position => $table_ref) { $target[] = $analyzed_sql[0]['table_ref'][$table_ref_position]['table_true_name']; } } $tabs = '(\'' . join('\',\'', $target) . '\')'; if ($cfgRelation['displaywork']) { if (!strlen($table)) { $exist_rel = false; } else { $exist_rel = PMA_getForeigners($db, $table, '', 'both'); if ($exist_rel) { foreach ($exist_rel as $master_field => $rel) { $display_field = PMA_getDisplayField($rel['foreign_db'], $rel['foreign_table']); $map[$master_field] = array($rel['foreign_table'], $rel['foreign_field'], $display_field, $rel['foreign_db']); } // end while } // end if } // end if } // end if // end 2b // 3. ----- Displays the results table ----- PMA_displayTableHeaders($is_display, $fields_meta, $fields_cnt, $analyzed_sql, $sort_expression, $sort_expression_nodirection, $sort_direction); $url_query = ''; echo '<tbody>' . "\n"; $clause_is_unique = PMA_displayTableBody($dt_result, $is_display, $map, $analyzed_sql); // vertical output case if ($_SESSION['tmp_user_values']['disp_direction'] == 'vertical') { PMA_displayVerticalTable(); } // end if unset($vertical_display); echo '</tbody>' . "\n"; ?> </table> <?php // 4. ----- Displays the link for multi-fields edit and delete if ($is_display['del_lnk'] == 'dr' && $is_display['del_lnk'] != 'kp') { $delete_text = $is_display['del_lnk'] == 'dr' ? $GLOBALS['strDelete'] : $GLOBALS['strKill']; $_url_params = array('db' => $db, 'table' => $table, 'sql_query' => $sql_query, 'goto' => $goto); $uncheckall_url = 'sql.php' . PMA_generate_common_url($_url_params); $_url_params['checkall'] = '1'; $checkall_url = 'sql.php' . PMA_generate_common_url($_url_params); if ($_SESSION['tmp_user_values']['disp_direction'] == 'vertical') { $checkall_params['onclick'] = 'if (setCheckboxes(\'rowsDeleteForm\', true)) return false;'; $uncheckall_params['onclick'] = 'if (setCheckboxes(\'rowsDeleteForm\', false)) return false;'; } else { $checkall_params['onclick'] = 'if (markAllRows(\'rowsDeleteForm\')) return false;'; $uncheckall_params['onclick'] = 'if (unMarkAllRows(\'rowsDeleteForm\')) return false;'; } $checkall_link = PMA_linkOrButton($checkall_url, $GLOBALS['strCheckAll'], $checkall_params, false); $uncheckall_link = PMA_linkOrButton($uncheckall_url, $GLOBALS['strUncheckAll'], $uncheckall_params, false); if ($_SESSION['tmp_user_values']['disp_direction'] != 'vertical') { echo '<img class="selectallarrow" width="38" height="22"' . ' src="' . $GLOBALS['pmaThemeImage'] . 'arrow_' . $GLOBALS['text_dir'] . '.png' . '"' . ' alt="' . $GLOBALS['strWithChecked'] . '" />'; } echo $checkall_link . "\n" . ' / ' . "\n" . $uncheckall_link . "\n" . '<i>' . $GLOBALS['strWithChecked'] . '</i>' . "\n"; PMA_buttonOrImage('submit_mult', 'mult_submit', 'submit_mult_change', $GLOBALS['strChange'], 'b_edit.png'); PMA_buttonOrImage('submit_mult', 'mult_submit', 'submit_mult_delete', $delete_text, 'b_drop.png'); if ($analyzed_sql[0]['querytype'] == 'SELECT') { PMA_buttonOrImage('submit_mult', 'mult_submit', 'submit_mult_export', $GLOBALS['strExport'], 'b_tblexport.png'); } echo "\n"; echo '<input type="hidden" name="sql_query"' . ' value="' . htmlspecialchars($sql_query) . '" />' . "\n"; echo '<input type="hidden" name="url_query"' . ' value="' . $GLOBALS['url_query'] . '" />' . "\n"; echo '<input type="hidden" name="clause_is_unique"' . ' value="' . $clause_is_unique . '" />' . "\n"; echo '</form>' . "\n"; } // 5. ----- Displays the navigation bar at the bottom if required ----- if ($is_display['nav_bar'] == '1') { echo '<br />' . "\n"; PMA_displayTableNavigation($pos_next, $pos_prev, $sql_query, 'bottom_direction_dropdown'); } elseif (!isset($GLOBALS['printview']) || $GLOBALS['printview'] != '1') { echo "\n" . '<br /><br />' . "\n"; } // 6. ----- Displays "Query results operations" if (!isset($GLOBALS['printview']) || $GLOBALS['printview'] != '1') { PMA_displayResultsOperations($the_disp_mode, $analyzed_sql); } }
/** * Function to generate unique condition for specified row. * * @param resource $handle current query result * @param integer $fields_cnt number of fields * @param array $fields_meta meta information about fields * @param array $row current row * @param boolean $force_unique generate condition only on pk or unique * * @access public * * @return array the calculated condition and whether condition is unique */ function PMA_getUniqueCondition($handle, $fields_cnt, $fields_meta, $row, $force_unique = false) { $primary_key = ''; $unique_key = ''; $nonprimary_condition = ''; $preferred_condition = ''; $primary_key_array = array(); $unique_key_array = array(); $nonprimary_condition_array = array(); $condition_array = array(); for ($i = 0; $i < $fields_cnt; ++$i) { $condition = ''; $con_key = ''; $con_val = ''; $field_flags = PMA_DBI_field_flags($handle, $i); $meta = $fields_meta[$i]; // do not use a column alias in a condition if (!isset($meta->orgname) || !strlen($meta->orgname)) { $meta->orgname = $meta->name; if (isset($GLOBALS['analyzed_sql'][0]['select_expr']) && is_array($GLOBALS['analyzed_sql'][0]['select_expr'])) { foreach ($GLOBALS['analyzed_sql'][0]['select_expr'] as $select_expr) { // need (string) === (string) // '' !== 0 but '' == 0 if ((string) $select_expr['alias'] === (string) $meta->name) { $meta->orgname = $select_expr['column']; break; } // end if } // end foreach } } // Do not use a table alias in a condition. // Test case is: // select * from galerie x WHERE //(select count(*) from galerie y where y.datum=x.datum)>1 // // But orgtable is present only with mysqli extension so the // fix is only for mysqli. // Also, do not use the original table name if we are dealing with // a view because this view might be updatable. // (The isView() verification should not be costly in most cases // because there is some caching in the function). if (isset($meta->orgtable) && $meta->table != $meta->orgtable && !PMA_Table::isView($GLOBALS['db'], $meta->table)) { $meta->table = $meta->orgtable; } // to fix the bug where float fields (primary or not) // can't be matched because of the imprecision of // floating comparison, use CONCAT // (also, the syntax "CONCAT(field) IS NULL" // that we need on the next "if" will work) if ($meta->type == 'real') { $con_key = 'CONCAT(' . PMA_backquote($meta->table) . '.' . PMA_backquote($meta->orgname) . ')'; } else { $con_key = PMA_backquote($meta->table) . '.' . PMA_backquote($meta->orgname); } // end if... else... $condition = ' ' . $con_key . ' '; if (!isset($row[$i]) || is_null($row[$i])) { $con_val = 'IS NULL'; } else { // timestamp is numeric on some MySQL 4.1 // for real we use CONCAT above and it should compare to string if ($meta->numeric && $meta->type != 'timestamp' && $meta->type != 'real') { $con_val = '= ' . $row[$i]; } elseif (($meta->type == 'blob' || $meta->type == 'string') && stristr($field_flags, 'BINARY') && !empty($row[$i])) { // do not waste memory building a too big condition if (strlen($row[$i]) < 1000) { // use a CAST if possible, to avoid problems // if the field contains wildcard characters % or _ $con_val = '= CAST(0x' . bin2hex($row[$i]) . ' AS BINARY)'; } else { // this blob won't be part of the final condition $con_val = null; } } elseif (in_array($meta->type, PMA_getGISDatatypes()) && !empty($row[$i])) { // do not build a too big condition if (strlen($row[$i]) < 5000) { $condition .= '=0x' . bin2hex($row[$i]) . ' AND'; } else { $condition = ''; } } elseif ($meta->type == 'bit') { $con_val = "= b'" . PMA_printable_bit_value($row[$i], $meta->length) . "'"; } else { $con_val = '= \'' . PMA_sqlAddSlashes($row[$i], false, true) . '\''; } } if ($con_val != null) { $condition .= $con_val . ' AND'; if ($meta->primary_key > 0) { $primary_key .= $condition; $primary_key_array[$con_key] = $con_val; } elseif ($meta->unique_key > 0) { $unique_key .= $condition; $unique_key_array[$con_key] = $con_val; } $nonprimary_condition .= $condition; $nonprimary_condition_array[$con_key] = $con_val; } } // end for // Correction University of Virginia 19991216: // prefer primary or unique keys for condition, // but use conjunction of all values if no primary key $clause_is_unique = true; if ($primary_key) { $preferred_condition = $primary_key; $condition_array = $primary_key_array; } elseif ($unique_key) { $preferred_condition = $unique_key; $condition_array = $unique_key_array; } elseif (!$force_unique) { $preferred_condition = $nonprimary_condition; $condition_array = $nonprimary_condition_array; $clause_is_unique = false; } $where_clause = trim(preg_replace('|\\s?AND$|', '', $preferred_condition)); return array($where_clause, $clause_is_unique, $condition_array); }
/** * Create tracking version for multiple tables * * @param array $selected list of selected tables * * @return void */ function PMA_createTrackingForMultipleTables($selected) { $tracking_set = PMA_getTrackingSet(); foreach ($selected as $selected_table) { PMA_Tracker::createVersion($GLOBALS['db'], $selected_table, $_REQUEST['version'], $tracking_set, PMA_Table::isView($GLOBALS['db'], $selected_table)); } }
/** * Outputs the content of a table in SQL format * * @param string $db database name * @param string $table table name * @param string $crlf the end of line sequence * @param string $error_url the url to go back in case of error * @param string $sql_query SQL query for obtaining data * * @return bool Whether it succeeded */ public function exportData($db, $table, $crlf, $error_url, $sql_query) { global $current_row, $sql_backquotes; if (isset($GLOBALS['sql_compatibility'])) { $compat = $GLOBALS['sql_compatibility']; } else { $compat = 'NONE'; } $formatted_table_name = isset($GLOBALS['sql_backquotes']) ? PMA_Util::backquoteCompat($table, $compat) : '\'' . $table . '\''; // Do not export data for a VIEW // (For a VIEW, this is called only when exporting a single VIEW) if (PMA_Table::isView($db, $table)) { $head = $this->_possibleCRLF() . $this->_exportComment() . $this->_exportComment('VIEW ' . ' ' . $formatted_table_name) . $this->_exportComment(__('Data') . ': ' . __('None')) . $this->_exportComment() . $this->_possibleCRLF(); if (!PMA_exportOutputHandler($head)) { return false; } return true; } // analyze the query to get the true column names, not the aliases // (this fixes an undefined index, also if Complete inserts // are used, we did not get the true column name in case of aliases) $analyzed_sql = PMA_SQP_analyze(PMA_SQP_parse($sql_query)); $result = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_UNBUFFERED); // a possible error: the table has crashed $tmp_error = PMA_DBI_getError(); if ($tmp_error) { return PMA_exportOutputHandler($this->_exportComment(__('Error reading data:') . ' (' . $tmp_error . ')')); } if ($result != false) { $fields_cnt = PMA_DBI_num_fields($result); // Get field information $fields_meta = PMA_DBI_get_fields_meta($result); $field_flags = array(); for ($j = 0; $j < $fields_cnt; $j++) { $field_flags[$j] = PMA_DBI_field_flags($result, $j); } for ($j = 0; $j < $fields_cnt; $j++) { if (isset($analyzed_sql[0]['select_expr'][$j]['column'])) { $field_set[$j] = PMA_Util::backquoteCompat($analyzed_sql[0]['select_expr'][$j]['column'], $compat, $sql_backquotes); } else { $field_set[$j] = PMA_Util::backquoteCompat($fields_meta[$j]->name, $compat, $sql_backquotes); } } if (isset($GLOBALS['sql_type']) && $GLOBALS['sql_type'] == 'UPDATE') { // update $schema_insert = 'UPDATE '; if (isset($GLOBALS['sql_ignore'])) { $schema_insert .= 'IGNORE '; } // avoid EOL blank $schema_insert .= PMA_Util::backquoteCompat($table, $compat, $sql_backquotes) . ' SET'; } else { // insert or replace if (isset($GLOBALS['sql_type']) && $GLOBALS['sql_type'] == 'REPLACE') { $sql_command = 'REPLACE'; } else { $sql_command = 'INSERT'; } // delayed inserts? if (isset($GLOBALS['sql_delayed'])) { $insert_delayed = ' DELAYED'; } else { $insert_delayed = ''; } // insert ignore? if (isset($GLOBALS['sql_type']) && $GLOBALS['sql_type'] == 'INSERT' && isset($GLOBALS['sql_ignore'])) { $insert_delayed .= ' IGNORE'; } //truncate table before insert if (isset($GLOBALS['sql_truncate']) && $GLOBALS['sql_truncate'] && $sql_command == 'INSERT') { $truncate = 'TRUNCATE TABLE ' . PMA_Util::backquoteCompat($table, $compat, $sql_backquotes) . ";"; $truncatehead = $this->_possibleCRLF() . $this->_exportComment() . $this->_exportComment(__('Truncate table before insert') . ' ' . $formatted_table_name) . $this->_exportComment() . $crlf; PMA_exportOutputHandler($truncatehead); PMA_exportOutputHandler($truncate); } else { $truncate = ''; } // scheme for inserting fields if ($GLOBALS['sql_insert_syntax'] == 'complete' || $GLOBALS['sql_insert_syntax'] == 'both') { $fields = implode(', ', $field_set); $schema_insert = $sql_command . $insert_delayed . ' INTO ' . PMA_Util::backquoteCompat($table, $compat, $sql_backquotes) . ' (' . $fields . ') VALUES'; } else { $schema_insert = $sql_command . $insert_delayed . ' INTO ' . PMA_Util::backquoteCompat($table, $compat, $sql_backquotes) . ' VALUES'; } } //\x08\\x09, not required $search = array("", "\n", "\r", ""); $replace = array('\\0', '\\n', '\\r', '\\Z'); $current_row = 0; $query_size = 0; if (($GLOBALS['sql_insert_syntax'] == 'extended' || $GLOBALS['sql_insert_syntax'] == 'both') && (!isset($GLOBALS['sql_type']) || $GLOBALS['sql_type'] != 'UPDATE')) { $separator = ','; $schema_insert .= $crlf; } else { $separator = ';'; } while ($row = PMA_DBI_fetch_row($result)) { if ($current_row == 0) { $head = $this->_possibleCRLF() . $this->_exportComment() . $this->_exportComment(__('Dumping data for table') . ' ' . $formatted_table_name) . $this->_exportComment() . $crlf; if (!PMA_exportOutputHandler($head)) { return false; } } // We need to SET IDENTITY_INSERT ON for MSSQL if (isset($GLOBALS['sql_compatibility']) && $GLOBALS['sql_compatibility'] == 'MSSQL' && $current_row == 0) { if (!PMA_exportOutputHandler('SET IDENTITY_INSERT ' . PMA_Util::backquoteCompat($table, $compat) . ' ON ;' . $crlf)) { return false; } } $current_row++; for ($j = 0; $j < $fields_cnt; $j++) { // NULL if (!isset($row[$j]) || is_null($row[$j])) { $values[] = 'NULL'; } elseif ($fields_meta[$j]->numeric && $fields_meta[$j]->type != 'timestamp' && !$fields_meta[$j]->blob) { // a number // timestamp is numeric on some MySQL 4.1, BLOBs are // sometimes numeric $values[] = $row[$j]; } elseif (stristr($field_flags[$j], 'BINARY') && $fields_meta[$j]->blob && isset($GLOBALS['sql_hex_for_blob'])) { // a true BLOB // - mysqldump only generates hex data when the --hex-blob // option is used, for fields having the binary attribute // no hex is generated // - a TEXT field returns type blob but a real blob // returns also the 'binary' flag // empty blobs need to be different, but '0' is also empty // :-( if (empty($row[$j]) && $row[$j] != '0') { $values[] = '\'\''; } else { $values[] = '0x' . bin2hex($row[$j]); } } elseif ($fields_meta[$j]->type == 'bit') { // detection of 'bit' works only on mysqli extension $values[] = "b'" . PMA_Util::sqlAddSlashes(PMA_Util::printableBitValue($row[$j], $fields_meta[$j]->length)) . "'"; } else { // something else -> treat as a string $values[] = '\'' . str_replace($search, $replace, PMA_Util::sqlAddSlashes($row[$j])) . '\''; } // end if } // end for // should we make update? if (isset($GLOBALS['sql_type']) && $GLOBALS['sql_type'] == 'UPDATE') { $insert_line = $schema_insert; for ($i = 0; $i < $fields_cnt; $i++) { if (0 == $i) { $insert_line .= ' '; } if ($i > 0) { // avoid EOL blank $insert_line .= ','; } $insert_line .= $field_set[$i] . ' = ' . $values[$i]; } list($tmp_unique_condition, $tmp_clause_is_unique) = PMA_Util::getUniqueCondition($result, $fields_cnt, $fields_meta, $row); $insert_line .= ' WHERE ' . $tmp_unique_condition; unset($tmp_unique_condition, $tmp_clause_is_unique); } else { // Extended inserts case if ($GLOBALS['sql_insert_syntax'] == 'extended' || $GLOBALS['sql_insert_syntax'] == 'both') { if ($current_row == 1) { $insert_line = $schema_insert . '(' . implode(', ', $values) . ')'; } else { $insert_line = '(' . implode(', ', $values) . ')'; $sql_max_size = $GLOBALS['sql_max_query_size']; if (isset($sql_max_size) && $sql_max_size > 0 && $query_size + strlen($insert_line) > $sql_max_size) { if (!PMA_exportOutputHandler(';' . $crlf)) { return false; } $query_size = 0; $current_row = 1; $insert_line = $schema_insert . $insert_line; } } $query_size += strlen($insert_line); // Other inserts case } else { $insert_line = $schema_insert . '(' . implode(', ', $values) . ')'; } } unset($values); if (!PMA_exportOutputHandler(($current_row == 1 ? '' : $separator . $crlf) . $insert_line)) { return false; } } // end while if ($current_row > 0) { if (!PMA_exportOutputHandler(';' . $crlf)) { return false; } } // We need to SET IDENTITY_INSERT OFF for MSSQL if (isset($GLOBALS['sql_compatibility']) && $GLOBALS['sql_compatibility'] == 'MSSQL' && $current_row > 0) { $outputSucceeded = PMA_exportOutputHandler($crlf . 'SET IDENTITY_INSERT ' . PMA_Util::backquoteCompat($table, $compat) . ' OFF;' . $crlf); if (!$outputSucceeded) { return false; } } } // end if ($result != false) PMA_DBI_free_result($result); return true; }
/** * Test for isView * * @return void */ public function testIsView() { $this->assertEquals(false, PMA_Table::isView()); //validate that it is the same as DBI fetchResult $this->assertEquals(true, PMA_Table::isView('PMA', 'PMA_BookMark')); $this->assertEquals(false, PMA_Table::isView('PMA', 'PMA_BookMark_2')); }
} } } elseif ($export_type == 'database') { if (!PMA_exportDBHeader($db)) { break; } if (isset($table_select)) { $tmp_select = implode($table_select, '|'); $tmp_select = '|' . $tmp_select . '|'; } $i = 0; $views = array(); foreach ($tables as $table) { // if this is a view, collect it for later; views must be exported after // the tables if (PMA_Table::isView($db, $table)) { $views[] = $table; continue; } $local_query = 'SELECT * FROM ' . PMA_backquote($db) . '.' . PMA_backquote($table); if (isset($tmp_select) && strpos(' ' . $tmp_select, '|' . $table . '|') || !isset($tmp_select)) { if (isset($GLOBALS[$what . '_structure'])) { if (!PMA_exportStructure($db, $table, $crlf, $err_url, $do_relation, $do_comments, $do_mime, $do_dates)) { break 2; } } if (isset($GLOBALS[$what . '_data'])) { if (!PMA_exportData($db, $table, $crlf, $err_url, $local_query)) { break 2; } }
/** * Counts and returns (or displays) the number of records in a table * * Revision 13 July 2001: Patch for limiting dump size from * vinay@sanisoft.com & girish@sanisoft.com * * @param string the current database name * @param string the current table name * @param boolean whether to retain or to displays the result * @param boolean whether to force an exact count * * @return mixed the number of records if retain is required, true else * * @access public */ function countRecords($db, $table, $ret = false, $force_exact = false) { $row_count = false; if (!$force_exact) { $row_count = PMA_DBI_fetch_value('SHOW TABLE STATUS FROM ' . PMA_backquote($db) . ' LIKE \'' . PMA_sqlAddslashes($table, true) . '\';', 0, 'Rows'); } $tbl_is_view = PMA_Table::isView($db, $table); if (false === $row_count || $row_count < $GLOBALS['cfg']['MaxExactCount']) { if (!$tbl_is_view) { $row_count = PMA_DBI_fetch_value('SELECT COUNT(*) FROM ' . PMA_backquote($db) . '.' . PMA_backquote($table)); // since counting all rows of a view could be too long } else { // try_query because it can fail ( a VIEW was based on // a table that no longer exists) $result = PMA_DBI_try_query('SELECT 1 FROM ' . PMA_backquote($db) . '.' . PMA_backquote($table) . ' LIMIT ' . $GLOBALS['cfg']['MaxExactCount'], null, PMA_DBI_QUERY_STORE); if (!PMA_DBI_getError()) { $row_count = PMA_DBI_num_rows($result); PMA_DBI_free_result($result); } } } if ($ret) { return $row_count; } /** * @deprecated at the moment nowhere is $return = false used */ // Note: as of PMA 2.8.0, we no longer seem to be using // PMA_Table::countRecords() in display mode. echo PMA_formatNumber($row_count, 0); if ($tbl_is_view) { echo ' ' . sprintf($GLOBALS['strViewMaxExactCount'], $GLOBALS['cfg']['MaxExactCount'], '[a@./Documentation.html#cfg_MaxExactCount@_blank]', '[/a]'); } }
/** * Function to send html for column dropdown list * * @return void */ function PMA_sendHtmlForColumnDropdownList() { $response = PMA_Response::getInstance(); $foreignTable = $_REQUEST['foreignTable']; $table_obj = new PMA_Table($foreignTable, $_REQUEST['foreignDb']); // Since views do not have keys defined on them provide the full list of columns if (PMA_Table::isView($_REQUEST['foreignDb'], $foreignTable)) { $columnList = $table_obj->getColumns(false, false); } else { $columnList = $table_obj->getIndexedColumns(false, false); } $columns = array(); foreach ($columnList as $column) { $columns[] = htmlspecialchars($column); } $response->addJSON('columns', $columns); // @todo should be: $server->db($db)->table($table)->primary() $primary = PMA_Index::getPrimary($foreignTable, $_REQUEST['foreignDb']); if (false === $primary) { return; } $primarycols = array_keys($primary->getColumns()); $response->addJSON('primary', $primarycols); }
/** * Outputs export header. It is the first method to be called, so all * the required variables are initialized here. * * @return bool Whether it succeeded */ public function exportHeader() { $this->initSpecificVariables(); global $crlf, $cfg, $db; $table = $this->_getTable(); $tables = $this->_getTables(); $export_struct = isset($GLOBALS['xml_export_functions']) || isset($GLOBALS['xml_export_procedures']) || isset($GLOBALS['xml_export_tables']) || isset($GLOBALS['xml_export_triggers']) || isset($GLOBALS['xml_export_views']); $export_data = isset($GLOBALS['xml_export_contents']) ? true : false; if ($GLOBALS['output_charset_conversion']) { $charset = $GLOBALS['charset_of_file']; } else { $charset = 'utf-8'; } $head = '<?xml version="1.0" encoding="' . $charset . '"?>' . $crlf . '<!--' . $crlf . '- phpMyAdmin XML Dump' . $crlf . '- version ' . PMA_VERSION . $crlf . '- http://www.phpmyadmin.net' . $crlf . '-' . $crlf . '- ' . __('Host:') . ' ' . $cfg['Server']['host']; if (!empty($cfg['Server']['port'])) { $head .= ':' . $cfg['Server']['port']; } $head .= $crlf . '- ' . __('Generation Time:') . ' ' . PMA_Util::localisedDate() . $crlf . '- ' . __('Server version:') . ' ' . PMA_MYSQL_STR_VERSION . $crlf . '- ' . __('PHP Version:') . ' ' . phpversion() . $crlf . '-->' . $crlf . $crlf; $head .= '<pma_xml_export version="1.0"' . ($export_struct ? ' xmlns:pma="http://www.phpmyadmin.net/some_doc_url/"' : '') . '>' . $crlf; if ($export_struct) { if (PMA_DRIZZLE) { $result = $GLOBALS['dbi']->fetchResult("SELECT\n 'utf8' AS DEFAULT_CHARACTER_SET_NAME,\n DEFAULT_COLLATION_NAME\n FROM data_dictionary.SCHEMAS\n WHERE SCHEMA_NAME = '" . PMA_Util::sqlAddSlashes($db) . "'"); } else { $result = $GLOBALS['dbi']->fetchResult('SELECT `DEFAULT_CHARACTER_SET_NAME`, `DEFAULT_COLLATION_NAME`' . ' FROM `information_schema`.`SCHEMATA` WHERE `SCHEMA_NAME`' . ' = \'' . PMA_Util::sqlAddSlashes($db) . '\' LIMIT 1'); } $db_collation = $result[0]['DEFAULT_COLLATION_NAME']; $db_charset = $result[0]['DEFAULT_CHARACTER_SET_NAME']; $head .= ' <!--' . $crlf; $head .= ' - Structure schemas' . $crlf; $head .= ' -->' . $crlf; $head .= ' <pma:structure_schemas>' . $crlf; $head .= ' <pma:database name="' . htmlspecialchars($db) . '" collation="' . $db_collation . '" charset="' . $db_charset . '">' . $crlf; if (count($tables) == 0) { $tables[] = $table; } foreach ($tables as $table) { // Export tables and views $result = $GLOBALS['dbi']->fetchResult('SHOW CREATE TABLE ' . PMA_Util::backquote($db) . '.' . PMA_Util::backquote($table), 0); $tbl = $result[$table][1]; $is_view = PMA_Table::isView($db, $table); if ($is_view) { $type = 'view'; } else { $type = 'table'; } if ($is_view && !isset($GLOBALS['xml_export_views'])) { continue; } if (!$is_view && !isset($GLOBALS['xml_export_tables'])) { continue; } $head .= ' <pma:' . $type . ' name="' . $table . '">' . $crlf; $tbl = " " . htmlspecialchars($tbl); $tbl = str_replace("\n", "\n ", $tbl); $head .= $tbl . ';' . $crlf; $head .= ' </pma:' . $type . '>' . $crlf; if (isset($GLOBALS['xml_export_triggers']) && $GLOBALS['xml_export_triggers']) { // Export triggers $triggers = $GLOBALS['dbi']->getTriggers($db, $table); if ($triggers) { foreach ($triggers as $trigger) { $code = $trigger['create']; $head .= ' <pma:trigger name="' . $trigger['name'] . '">' . $crlf; // Do some formatting $code = substr(rtrim($code), 0, -3); $code = " " . htmlspecialchars($code); $code = str_replace("\n", "\n ", $code); $head .= $code . $crlf; $head .= ' </pma:trigger>' . $crlf; } unset($trigger); unset($triggers); } } } if (isset($GLOBALS['xml_export_functions']) && $GLOBALS['xml_export_functions']) { // Export functions $functions = $GLOBALS['dbi']->getProceduresOrFunctions($db, 'FUNCTION'); if ($functions) { foreach ($functions as $function) { $head .= ' <pma:function name="' . $function . '">' . $crlf; // Do some formatting $sql = $GLOBALS['dbi']->getDefinition($db, 'FUNCTION', $function); $sql = rtrim($sql); $sql = " " . htmlspecialchars($sql); $sql = str_replace("\n", "\n ", $sql); $head .= $sql . $crlf; $head .= ' </pma:function>' . $crlf; } unset($function); unset($functions); } } if (isset($GLOBALS['xml_export_procedures']) && $GLOBALS['xml_export_procedures']) { // Export procedures $procedures = $GLOBALS['dbi']->getProceduresOrFunctions($db, 'PROCEDURE'); if ($procedures) { foreach ($procedures as $procedure) { $head .= ' <pma:procedure name="' . $procedure . '">' . $crlf; // Do some formatting $sql = $GLOBALS['dbi']->getDefinition($db, 'PROCEDURE', $procedure); $sql = rtrim($sql); $sql = " " . htmlspecialchars($sql); $sql = str_replace("\n", "\n ", $sql); $head .= $sql . $crlf; $head .= ' </pma:procedure>' . $crlf; } unset($procedure); unset($procedures); } } unset($result); $head .= ' </pma:database>' . $crlf; $head .= ' </pma:structure_schemas>' . $crlf; if ($export_data) { $head .= $crlf; } } return PMA_exportOutputHandler($head); }
/** * Copies or renames table * * @param string $source_db source database * @param string $source_table source table * @param string $target_db target database * @param string $target_table target table * @param string $what what to be moved or copied (data, dataonly) * @param bool $move whether to move * @param string $mode mode * * @return bool true if success, false otherwise */ public static function moveCopy($source_db, $source_table, $target_db, $target_table, $what, $move, $mode) { global $err_url; // Try moving the tables directly, using native `RENAME` statement. if ($move && $what == 'data') { $tbl = new PMA_Table($source_table, $source_db); if ($tbl->rename($target_table, $target_db)) { $GLOBALS['message'] = $tbl->getLastMessage(); return true; } } // Setting required export settings. $GLOBALS['sql_backquotes'] = 1; $GLOBALS['asfile'] = 1; // Ensuring the target database is valid. if (!$GLOBALS['pma']->databases->exists($source_db, $target_db)) { if (!$GLOBALS['pma']->databases->exists($source_db)) { $GLOBALS['message'] = PMA_Message::rawError(sprintf(__('Source database `%s` was not found!'), htmlspecialchars($source_db))); } if (!$GLOBALS['pma']->databases->exists($target_db)) { $GLOBALS['message'] = PMA_Message::rawError(sprintf(__('Target database `%s` was not found!'), htmlspecialchars($target_db))); } return false; } /** * The full name of source table, quoted. * @var string $source */ $source = PMA_Util::backquote($source_db) . '.' . PMA_Util::backquote($source_table); // If the target database is not specified, the operation is taking // place in the same database. if (!isset($target_db) || !mb_strlen($target_db)) { $target_db = $source_db; } // Selecting the database could avoid some problems with replicated // databases, when moving table from replicated one to not replicated one. $GLOBALS['dbi']->selectDb($target_db); /** * The full name of target table, quoted. * @var string $target */ $target = PMA_Util::backquote($target_db) . '.' . PMA_Util::backquote($target_table); // No table is created when this is a data-only operation. if ($what != 'dataonly') { include_once "libraries/plugin_interface.lib.php"; /** * Instance used for exporting the current structure of the table. * * @var ExportSql */ $export_sql_plugin = PMA_getPlugin("export", "sql", 'libraries/plugins/export/', array('export_type' => 'table', 'single_table' => false)); $no_constraints_comments = true; $GLOBALS['sql_constraints_query'] = ''; // set the value of global sql_auto_increment variable if (isset($_POST['sql_auto_increment'])) { $GLOBALS['sql_auto_increment'] = $_POST['sql_auto_increment']; } /** * The old structure of the table.. * @var string $sql_structure */ $sql_structure = $export_sql_plugin->getTableDef($source_db, $source_table, "\n", $err_url, false, false); unset($no_constraints_comments); // ----------------------------------------------------------------- // Phase 0: Preparing structures used. /** * The destination where the table is moved or copied to. * @var SqlParser\Components\Expression */ $destination = new SqlParser\Components\Expression($target_db, $target_table, ''); // Find server's SQL mode so the builder can generate correct // queries. // One of the options that alters the behaviour is `ANSI_QUOTES`. // This is not availabile for Drizzle. if (!PMA_DRIZZLE) { SqlParser\Context::setMode($GLOBALS['dbi']->fetchValue("SELECT @@sql_mode")); } // ----------------------------------------------------------------- // Phase 1: Dropping existent element of the same name (if exists // and required). if (isset($_REQUEST['drop_if_exists']) && $_REQUEST['drop_if_exists'] == 'true') { /** * Drop statement used for building the query. * @var SqlParser\Statements\DropStatement $statement */ $statement = new SqlParser\Statements\DropStatement(); $tbl = new PMA_Table($target_db, $target_table); $statement->options = new SqlParser\Components\OptionsArray(array($tbl->isView() ? 'VIEW' : 'TABLE', 'IF EXISTS')); $statement->fields = array($destination); // Building the query. $drop_query = $statement->build() . ';'; // Executing it. $GLOBALS['dbi']->query($drop_query); $GLOBALS['sql_query'] .= "\n" . $drop_query; // If an existing table gets deleted, maintain any entries for // the PMA_* tables. $maintain_relations = true; } // ----------------------------------------------------------------- // Phase 2: Generating the new query of this structure. /** * The parser responsible for parsing the old queries. * @var SqlParser\Parser $parser */ $parser = new SqlParser\Parser($sql_structure); if (!empty($parser->statements[0])) { /** * The CREATE statement of this structure. * @var SqlParser\Statements\CreateStatement $statement */ $statement = $parser->statements[0]; // Changing the destination. $statement->name = $destination; // Building back the query. $sql_structure = $statement->build() . ';'; // Executing it. $GLOBALS['dbi']->query($sql_structure); $GLOBALS['sql_query'] .= "\n" . $sql_structure; } // ----------------------------------------------------------------- // Phase 3: Adding constraints. // All constraint names are removed because they must be unique. if (($move || isset($GLOBALS['add_constraints'])) && !empty($GLOBALS['sql_constraints_query'])) { $parser = new SqlParser\Parser($GLOBALS['sql_constraints_query']); /** * The ALTER statement that generates the constraints. * @var SqlParser\Statements\AlterStatement $statement */ $statement = $parser->statements[0]; // Changing the altered table to the destination. $statement->table = $destination; // Removing the name of the constraints. foreach ($statement->altered as $idx => $altered) { // All constraint names are removed because they must be unique. if ($altered->options->has('CONSTRAINT')) { $altered->field = null; } } // Building back the query. $GLOBALS['sql_constraints_query'] = $statement->build() . ';'; // Executing it. if ($mode == 'one_table') { $GLOBALS['dbi']->query($GLOBALS['sql_constraints_query']); } $GLOBALS['sql_query'] .= "\n" . $GLOBALS['sql_constraints_query']; if ($mode == 'one_table') { unset($GLOBALS['sql_constraints_query']); } } // ----------------------------------------------------------------- // Phase 4: Adding indexes. // View phase 3. if (!empty($GLOBALS['sql_indexes'])) { $parser = new SqlParser\Parser($GLOBALS['sql_indexes']); /** * The ALTER statement that generates the indexes. * @var SqlParser\Statements\AlterStatement $statement */ $statement = $parser->statements[0]; // Changing the altered table to the destination. $statement->table = $destination; // Removing the name of the constraints. foreach ($statement->altered as $idx => $altered) { // All constraint names are removed because they must be unique. if ($altered->options->has('CONSTRAINT')) { $altered->field = null; } } // Building back the query. $GLOBALS['sql_indexes'] = $statement->build() . ';'; // Executing it. if ($mode == 'one_table' || $mode == 'db_copy') { $GLOBALS['dbi']->query($GLOBALS['sql_indexes']); } $GLOBALS['sql_query'] .= "\n" . $GLOBALS['sql_indexes']; if ($mode == 'one_table' || $mode == 'db_copy') { unset($GLOBALS['sql_indexes']); } } // ----------------------------------------------------------------- // Phase 5: Adding AUTO_INCREMENT. if (!empty($GLOBALS['sql_auto_increments'])) { if ($mode == 'one_table' || $mode == 'db_copy') { $parser = new SqlParser\Parser($GLOBALS['sql_auto_increments']); /** * The ALTER statement that alters the AUTO_INCREMENT value. * @var SqlParser\Statements\AlterStatement $statement */ $statement = $parser->statements[0]; // Changing the altered table to the destination. $statement->table = $destination; // Building back the query. $GLOBALS['sql_auto_increments'] = $statement->build() . ';'; // Executing it. $GLOBALS['dbi']->query($GLOBALS['sql_auto_increments']); $GLOBALS['sql_query'] .= "\n" . $GLOBALS['sql_auto_increments']; unset($GLOBALS['sql_auto_increments']); } } } else { $GLOBALS['sql_query'] = ''; } $_table = new PMA_Table($target_table, $target_db); // Copy the data unless this is a VIEW if (($what == 'data' || $what == 'dataonly') && !$_table->isView()) { if (!PMA_DRIZZLE) { $sql_set_mode = "SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO'"; $GLOBALS['dbi']->query($sql_set_mode); $GLOBALS['sql_query'] .= "\n\n" . $sql_set_mode . ';'; } $sql_insert_data = 'INSERT INTO ' . $target . ' SELECT * FROM ' . $source; $GLOBALS['dbi']->query($sql_insert_data); $GLOBALS['sql_query'] .= "\n\n" . $sql_insert_data . ';'; } PMA_getRelationsParam(); // Drops old table if the user has requested to move it if ($move) { // This could avoid some problems with replicated databases, when // moving table from replicated one to not replicated one $GLOBALS['dbi']->selectDb($source_db); $_source_table = new PMA_Table($source_table, $source_db); if ($_source_table->isView()) { $sql_drop_query = 'DROP VIEW'; } else { $sql_drop_query = 'DROP TABLE'; } $sql_drop_query .= ' ' . $source; $GLOBALS['dbi']->query($sql_drop_query); // Renable table in configuration storage PMA_REL_renameTable($source_db, $target_db, $source_table, $target_table); $GLOBALS['sql_query'] .= "\n\n" . $sql_drop_query . ';'; // end if ($move) return true; } // we are copying // Create new entries as duplicates from old PMA DBs if ($what == 'dataonly' || isset($maintain_relations)) { return true; } if ($GLOBALS['cfgRelation']['commwork']) { // Get all comments and MIME-Types for current table $comments_copy_rs = PMA_queryAsControlUser('SELECT column_name, comment' . ($GLOBALS['cfgRelation']['mimework'] ? ', mimetype, transformation, transformation_options' : '') . ' FROM ' . PMA_Util::backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_Util::backquote($GLOBALS['cfgRelation']['column_info']) . ' WHERE ' . ' db_name = \'' . PMA_Util::sqlAddSlashes($source_db) . '\'' . ' AND ' . ' table_name = \'' . PMA_Util::sqlAddSlashes($source_table) . '\''); // Write every comment as new copied entry. [MIME] while ($comments_copy_row = $GLOBALS['dbi']->fetchAssoc($comments_copy_rs)) { $new_comment_query = 'REPLACE INTO ' . PMA_Util::backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_Util::backquote($GLOBALS['cfgRelation']['column_info']) . ' (db_name, table_name, column_name, comment' . ($GLOBALS['cfgRelation']['mimework'] ? ', mimetype, transformation, transformation_options' : '') . ') ' . ' VALUES(' . '\'' . PMA_Util::sqlAddSlashes($target_db) . '\',\'' . PMA_Util::sqlAddSlashes($target_table) . '\',\'' . PMA_Util::sqlAddSlashes($comments_copy_row['column_name']) . '\'' . ($GLOBALS['cfgRelation']['mimework'] ? ',\'' . PMA_Util::sqlAddSlashes($comments_copy_row['comment']) . '\',' . '\'' . PMA_Util::sqlAddSlashes($comments_copy_row['mimetype']) . '\',' . '\'' . PMA_Util::sqlAddSlashes($comments_copy_row['transformation']) . '\',' . '\'' . PMA_Util::sqlAddSlashes($comments_copy_row['transformation_options']) . '\'' : '') . ')'; PMA_queryAsControlUser($new_comment_query); } // end while $GLOBALS['dbi']->freeResult($comments_copy_rs); unset($comments_copy_rs); } // duplicating the bookmarks must not be done here, but // just once per db $get_fields = array('display_field'); $where_fields = array('db_name' => $source_db, 'table_name' => $source_table); $new_fields = array('db_name' => $target_db, 'table_name' => $target_table); PMA_Table::duplicateInfo('displaywork', 'table_info', $get_fields, $where_fields, $new_fields); /** * @todo revise this code when we support cross-db relations */ $get_fields = array('master_field', 'foreign_table', 'foreign_field'); $where_fields = array('master_db' => $source_db, 'master_table' => $source_table); $new_fields = array('master_db' => $target_db, 'foreign_db' => $target_db, 'master_table' => $target_table); PMA_Table::duplicateInfo('relwork', 'relation', $get_fields, $where_fields, $new_fields); $get_fields = array('foreign_field', 'master_table', 'master_field'); $where_fields = array('foreign_db' => $source_db, 'foreign_table' => $source_table); $new_fields = array('master_db' => $target_db, 'foreign_db' => $target_db, 'foreign_table' => $target_table); PMA_Table::duplicateInfo('relwork', 'relation', $get_fields, $where_fields, $new_fields); /** * @todo Can't get duplicating PDFs the right way. The * page numbers always get screwed up independently from * duplication because the numbers do not seem to be stored on a * per-database basis. Would the author of pdf support please * have a look at it? * $get_fields = array('page_descr'); $where_fields = array('db_name' => $source_db); $new_fields = array('db_name' => $target_db); $last_id = PMA_Table::duplicateInfo( 'pdfwork', 'pdf_pages', $get_fields, $where_fields, $new_fields ); if (isset($last_id) && $last_id >= 0) { $get_fields = array('x', 'y'); $where_fields = array( 'db_name' => $source_db, 'table_name' => $source_table ); $new_fields = array( 'db_name' => $target_db, 'table_name' => $target_table, 'pdf_page_number' => $last_id ); PMA_Table::duplicateInfo( 'pdfwork', 'table_coords', $get_fields, $where_fields, $new_fields ); } */ return true; }
/** * Builds and executes SQL statements to create the database and tables * as necessary, as well as insert all the data. * * @param string $db_name Name of the database * @param array &$tables Array of tables for the specified database * @param array &$analyses Analyses of the tables * @param array &$additional_sql Additional SQL statements to be executed * @param array $options Associative array of options * * @return void * @access public * * @link http://wiki.phpmyadmin.net/pma/Import */ function PMA_buildSQL($db_name, &$tables, &$analyses = null, &$additional_sql = null, $options = null) { /* Take care of the options */ if (isset($options['db_collation']) && !is_null($options['db_collation'])) { $collation = $options['db_collation']; } else { $collation = "utf8_general_ci"; } if (isset($options['db_charset']) && !is_null($options['db_charset'])) { $charset = $options['db_charset']; } else { $charset = "utf8"; } if (isset($options['create_db'])) { $create_db = $options['create_db']; } else { $create_db = true; } /* Create SQL code to handle the database */ $sql = array(); if ($create_db) { if (PMA_DRIZZLE) { $sql[] = "CREATE DATABASE IF NOT EXISTS " . PMA_Util::backquote($db_name) . " COLLATE " . $collation; } else { $sql[] = "CREATE DATABASE IF NOT EXISTS " . PMA_Util::backquote($db_name) . " DEFAULT CHARACTER SET " . $charset . " COLLATE " . $collation; } } /** * The calling plug-in should include this statement, * if necessary, in the $additional_sql parameter * * $sql[] = "USE " . backquote($db_name); */ /* Execute the SQL statements create above */ $sql_len = count($sql); for ($i = 0; $i < $sql_len; ++$i) { PMA_importRunQuery($sql[$i], $sql[$i]); } /* No longer needed */ unset($sql); /* Run the $additional_sql statements supplied by the caller plug-in */ if ($additional_sql != null) { /* Clean the SQL first */ $additional_sql_len = count($additional_sql); /** * Only match tables for now, because CREATE IF NOT EXISTS * syntax is lacking or nonexisting for views, triggers, * functions, and procedures. * * See: http://bugs.mysql.com/bug.php?id=15287 * * To the best of my knowledge this is still an issue. * * $pattern = 'CREATE (TABLE|VIEW|TRIGGER|FUNCTION|PROCEDURE)'; */ $pattern = '/CREATE [^`]*(TABLE)/'; $replacement = 'CREATE \\1 IF NOT EXISTS'; /* Change CREATE statements to CREATE IF NOT EXISTS to support * inserting into existing structures */ for ($i = 0; $i < $additional_sql_len; ++$i) { $additional_sql[$i] = preg_replace($pattern, $replacement, $additional_sql[$i]); /* Execute the resulting statements */ PMA_importRunQuery($additional_sql[$i], $additional_sql[$i]); } } if ($analyses != null) { $type_array = array(NONE => "NULL", VARCHAR => "varchar", INT => "int", DECIMAL => "decimal", BIGINT => "bigint", GEOMETRY => 'geometry'); /* TODO: Do more checking here to make sure they really are matched */ if (count($tables) != count($analyses)) { exit; } /* Create SQL code to create the tables */ $num_tables = count($tables); for ($i = 0; $i < $num_tables; ++$i) { $num_cols = count($tables[$i][COL_NAMES]); $tempSQLStr = "CREATE TABLE IF NOT EXISTS " . PMA_Util::backquote($db_name) . '.' . PMA_Util::backquote($tables[$i][TBL_NAME]) . " ("; for ($j = 0; $j < $num_cols; ++$j) { $size = $analyses[$i][SIZES][$j]; if ((int) $size == 0) { $size = 10; } $tempSQLStr .= PMA_Util::backquote($tables[$i][COL_NAMES][$j]) . " " . $type_array[$analyses[$i][TYPES][$j]]; if ($analyses[$i][TYPES][$j] != GEOMETRY) { $tempSQLStr .= "(" . $size . ")"; } if ($j != count($tables[$i][COL_NAMES]) - 1) { $tempSQLStr .= ", "; } } $tempSQLStr .= ")" . (PMA_DRIZZLE ? "" : " DEFAULT CHARACTER SET " . $charset) . " COLLATE " . $collation . ";"; /** * Each SQL statement is executed immediately * after it is formed so that we don't have * to store them in a (possibly large) buffer */ PMA_importRunQuery($tempSQLStr, $tempSQLStr); } } /** * Create the SQL statements to insert all the data * * Only one insert query is formed for each table */ $tempSQLStr = ""; $col_count = 0; $num_tables = count($tables); for ($i = 0; $i < $num_tables; ++$i) { $num_cols = count($tables[$i][COL_NAMES]); $num_rows = count($tables[$i][ROWS]); $tempSQLStr = "INSERT INTO " . PMA_Util::backquote($db_name) . '.' . PMA_Util::backquote($tables[$i][TBL_NAME]) . " ("; for ($m = 0; $m < $num_cols; ++$m) { $tempSQLStr .= PMA_Util::backquote($tables[$i][COL_NAMES][$m]); if ($m != $num_cols - 1) { $tempSQLStr .= ", "; } } $tempSQLStr .= ") VALUES "; for ($j = 0; $j < $num_rows; ++$j) { $tempSQLStr .= "("; for ($k = 0; $k < $num_cols; ++$k) { // If fully formatted SQL, no need to enclose // with apostrophes, add slashes etc. if ($analyses != null && isset($analyses[$i][FORMATTEDSQL][$col_count]) && $analyses[$i][FORMATTEDSQL][$col_count] == true) { $tempSQLStr .= (string) $tables[$i][ROWS][$j][$k]; } else { if ($analyses != null) { $is_varchar = $analyses[$i][TYPES][$col_count] === VARCHAR; } else { $is_varchar = !is_numeric($tables[$i][ROWS][$j][$k]); } /* Don't put quotes around NULL fields */ if (!strcmp($tables[$i][ROWS][$j][$k], 'NULL')) { $is_varchar = false; } $tempSQLStr .= $is_varchar ? "'" : ""; $tempSQLStr .= PMA_Util::sqlAddSlashes((string) $tables[$i][ROWS][$j][$k]); $tempSQLStr .= $is_varchar ? "'" : ""; } if ($k != $num_cols - 1) { $tempSQLStr .= ", "; } if ($col_count == $num_cols - 1) { $col_count = 0; } else { $col_count++; } /* Delete the cell after we are done with it */ unset($tables[$i][ROWS][$j][$k]); } $tempSQLStr .= ")"; if ($j != $num_rows - 1) { $tempSQLStr .= ",\n "; } $col_count = 0; /* Delete the row after we are done with it */ unset($tables[$i][ROWS][$j]); } $tempSQLStr .= ";"; /** * Each SQL statement is executed immediately * after it is formed so that we don't have * to store them in a (possibly large) buffer */ PMA_importRunQuery($tempSQLStr, $tempSQLStr); } /* No longer needed */ unset($tempSQLStr); /** * A work in progress */ /* Add the viewable structures from $additional_sql * to $tables so they are also displayed */ $view_pattern = '@VIEW `[^`]+`\\.`([^`]+)@'; $table_pattern = '@CREATE TABLE IF NOT EXISTS `([^`]+)`@'; /* Check a third pattern to make sure its not a "USE `db_name`;" statement */ $regs = array(); $inTables = false; $additional_sql_len = count($additional_sql); for ($i = 0; $i < $additional_sql_len; ++$i) { preg_match($view_pattern, $additional_sql[$i], $regs); if (count($regs) == 0) { preg_match($table_pattern, $additional_sql[$i], $regs); } if (count($regs)) { for ($n = 0; $n < $num_tables; ++$n) { if (!strcmp($regs[1], $tables[$n][TBL_NAME])) { $inTables = true; break; } } if (!$inTables) { $tables[] = array(TBL_NAME => $regs[1]); } } /* Reset the array */ $regs = array(); $inTables = false; } $params = array('db' => (string) $db_name); $db_url = 'db_structure.php' . PMA_URL_getCommon($params); $db_ops_url = 'db_operations.php' . PMA_URL_getCommon($params); $message = '<br /><br />'; $message .= '<strong>' . __('The following structures have either been created or altered. Here you can:') . '</strong><br />'; $message .= '<ul><li>' . __("View a structure's contents by clicking on its name.") . '</li>'; $message .= '<li>' . __('Change any of its settings by clicking the corresponding "Options" link.') . '</li>'; $message .= '<li>' . __('Edit structure by following the "Structure" link.') . '</li>'; $message .= sprintf('<br /><li><a href="%s" title="%s">%s</a> (<a href="%s" title="%s">' . __('Options') . '</a>)</li>', $db_url, sprintf(__('Go to database: %s'), htmlspecialchars(PMA_Util::backquote($db_name))), htmlspecialchars($db_name), $db_ops_url, sprintf(__('Edit settings for %s'), htmlspecialchars(PMA_Util::backquote($db_name)))); $message .= '<ul>'; unset($params); $num_tables = count($tables); for ($i = 0; $i < $num_tables; ++$i) { $params = array('db' => (string) $db_name, 'table' => (string) $tables[$i][TBL_NAME]); $tbl_url = 'sql.php' . PMA_URL_getCommon($params); $tbl_struct_url = 'tbl_structure.php' . PMA_URL_getCommon($params); $tbl_ops_url = 'tbl_operations.php' . PMA_URL_getCommon($params); unset($params); if (!PMA_Table::isView($db_name, $tables[$i][TBL_NAME])) { $message .= sprintf('<li><a href="%s" title="%s">%s</a> (<a href="%s" title="%s">' . __('Structure') . '</a>) (<a href="%s" title="%s">' . __('Options') . '</a>)</li>', $tbl_url, sprintf(__('Go to table: %s'), htmlspecialchars(PMA_Util::backquote($tables[$i][TBL_NAME]))), htmlspecialchars($tables[$i][TBL_NAME]), $tbl_struct_url, sprintf(__('Structure of %s'), htmlspecialchars(PMA_Util::backquote($tables[$i][TBL_NAME]))), $tbl_ops_url, sprintf(__('Edit settings for %s'), htmlspecialchars(PMA_Util::backquote($tables[$i][TBL_NAME])))); } else { $message .= sprintf('<li><a href="%s" title="%s">%s</a></li>', $tbl_url, sprintf(__('Go to view: %s'), htmlspecialchars(PMA_Util::backquote($tables[$i][TBL_NAME]))), htmlspecialchars($tables[$i][TBL_NAME])); } } $message .= '</ul></ul>'; global $import_notice; $import_notice = $message; unset($tables); }
/** * Returns the table tabs as an array * * @return array Data for generating table tabs */ private function _getTableTabs() { $db_is_system_schema = $GLOBALS['dbi']->isSystemSchema($this->_db); $tbl_is_view = PMA_Table::isView($this->_db, $this->_table); $is_superuser = $GLOBALS['dbi']->isSuperuser(); $isCreateOrGrantUser = $GLOBALS['dbi']->isUserType('grant') || $GLOBALS['dbi']->isUserType('create'); $tabs = array(); $tabs['browse']['icon'] = 'b_browse.png'; $tabs['browse']['text'] = __('Browse'); $tabs['browse']['link'] = 'sql.php'; $tabs['browse']['args']['pos'] = 0; $tabs['structure']['icon'] = 'b_props.png'; $tabs['structure']['link'] = 'tbl_structure.php'; $tabs['structure']['text'] = __('Structure'); $tabs['sql']['icon'] = 'b_sql.png'; $tabs['sql']['link'] = 'tbl_sql.php'; $tabs['sql']['text'] = __('SQL'); $tabs['search']['icon'] = 'b_search.png'; $tabs['search']['text'] = __('Search'); $tabs['search']['link'] = 'tbl_select.php'; $tabs['search']['active'] = in_array(basename($GLOBALS['PMA_PHP_SELF']), array('tbl_select.php', 'tbl_zoom_select.php', 'tbl_find_replace.php')); if (!$db_is_system_schema) { $tabs['insert']['icon'] = 'b_insrow.png'; $tabs['insert']['link'] = 'tbl_change.php'; $tabs['insert']['text'] = __('Insert'); } $tabs['export']['icon'] = 'b_tblexport.png'; $tabs['export']['link'] = 'tbl_export.php'; $tabs['export']['args']['single_table'] = 'true'; $tabs['export']['text'] = __('Export'); /** * Don't display "Import" for views and information_schema */ if (!$tbl_is_view && !$db_is_system_schema) { $tabs['import']['icon'] = 'b_tblimport.png'; $tabs['import']['link'] = 'tbl_import.php'; $tabs['import']['text'] = __('Import'); } if (($is_superuser || $isCreateOrGrantUser) && !PMA_DRIZZLE && !$db_is_system_schema) { $tabs['privileges']['link'] = 'server_privileges.php'; $tabs['privileges']['args']['checkprivsdb'] = $this->_db; $tabs['privileges']['args']['checkprivstable'] = $this->_table; // stay on table view $tabs['privileges']['args']['viewing_mode'] = 'table'; $tabs['privileges']['text'] = __('Privileges'); $tabs['privileges']['icon'] = 's_rights.png'; } /** * Don't display "Operations" for views and information_schema */ if (!$tbl_is_view && !$db_is_system_schema) { $tabs['operation']['icon'] = 'b_tblops.png'; $tabs['operation']['link'] = 'tbl_operations.php'; $tabs['operation']['text'] = __('Operations'); } if (PMA_Tracker::isActive()) { $tabs['tracking']['icon'] = 'eye.png'; $tabs['tracking']['text'] = __('Tracking'); $tabs['tracking']['link'] = 'tbl_tracking.php'; } if (!$db_is_system_schema && !PMA_DRIZZLE && PMA_Util::currentUserHasPrivilege('TRIGGER', $this->_db, $this->_table) && !$tbl_is_view) { $tabs['triggers']['link'] = 'tbl_triggers.php'; $tabs['triggers']['text'] = __('Triggers'); $tabs['triggers']['icon'] = 'b_triggers.png'; } /** * Views support a limited number of operations */ if ($tbl_is_view && !$db_is_system_schema) { $tabs['operation']['icon'] = 'b_tblops.png'; $tabs['operation']['link'] = 'view_operations.php'; $tabs['operation']['text'] = __('Operations'); } return $tabs; }
* * @todo replace this by PMA_Table * @global array $GLOBALS['showtable'] * @name $showtable */ $GLOBALS['showtable'] = array(); // PMA_Table::sGetStatusInfo() does caching by default, but here // we force reading of the current table status // if $reread_info is true (for example, coming from tbl_operations.php // and we just changed the table's storage engine) $GLOBALS['showtable'] = PMA_Table::sGetStatusInfo($GLOBALS['db'], $GLOBALS['table'], null, isset($reread_info) && $reread_info ? true : false); // need this test because when we are creating a table, we get 0 rows // from the SHOW TABLE query // and we don't want to mess up the $tbl_storage_engine coming from the form if ($showtable) { if (PMA_Table::isView($GLOBALS['db'], $GLOBALS['table'])) { $tbl_is_view = true; $tbl_storage_engine = __('View'); $show_comment = null; } else { $tbl_is_view = false; $tbl_storage_engine = isset($showtable['Engine']) ? strtoupper($showtable['Engine']) : ''; // a new comment could be coming from tbl_operations.php // and we want to show it in the header if (isset($submitcomment) && isset($comment)) { $show_comment = $comment; } else { $show_comment = isset($showtable['Comment']) ? $showtable['Comment'] : ''; } } $tbl_collation = empty($showtable['Collation']) ? '' : $showtable['Collation'];
/** * Get VIEWs in a particular database * * @param string $db Database name to look in * * @return array $views Set of VIEWs inside the database */ function PMA_DBI_getVirtualTables($db) { $tables_full = PMA_DBI_get_tables_full($db); $views = array(); foreach ($tables_full as $table => $tmp) { if (PMA_Table::isView($db, $table)) { $views[] = $table; } } return $views; }
/** * Function to create the tracking version * * @return void */ function PMA_createTrackingVersion() { $tracking_set = PMA_getTrackingSet(); $versionCreated = PMA_Tracker::createVersion($GLOBALS['db'], $GLOBALS['table'], $_REQUEST['version'], $tracking_set, PMA_Table::isView($GLOBALS['db'], $GLOBALS['table'])); if ($versionCreated) { $msg = PMA_Message::success(sprintf(__('Version %1$s was created, tracking for %2$s is active.'), htmlspecialchars($_REQUEST['version']), htmlspecialchars($GLOBALS['db'] . '.' . $GLOBALS['table']))); $msg->display(); } }
/** * Test for isView * * @return void */ public function testIsView() { $table = new PMA_Table(null, null); $this->assertEquals(false, $table->isView()); //validate that it is the same as DBI fetchResult $table = new PMA_Table('PMA_BookMark', 'PMA'); $this->assertEquals(true, $table->isView()); $table = new PMA_Table('PMA_BookMark_2', 'PMA'); $this->assertEquals(false, $table->isView()); }
/** * Returns Html for show create. * * @param string $db Database name * @param array $db_objects Array containing DB objects * * @return string Html */ function PMA_getHtmlShowCreate($db, $db_objects) { // Main outer container. $html_output = '<div class="show_create_results">' . '<h2>' . __('Showing create queries') . '</h2>'; // Table header. $output_table = '<fieldset>' . '<legend>%s</legend>' . '<table class="show_create">' . '<thead>' . '<tr>' . '<th>%s</th>' . '<th>Create %s</th>' . '</tr>' . '</thead>' . '<tbody>'; // Holds rows html for views. $views = ''; // Holds rows html for tables. $tables = ''; // Handles odd, even classes for rows. // for 'Views' $odd1 = true; // for 'Tables' $odd2 = true; // Iterate through each object. foreach ($db_objects as $key => $object) { // Check if current object is a View or Table. $isView = PMA_Table::isView($db, $object); if ($isView) { $row_class = $odd1 ? 'odd' : 'even'; $create_data = PMA_getShowCreate($db, $object, 'view'); $views .= '<tr class="' . $row_class . '">' . '<td><strong>' . PMA_mimeDefaultFunction($create_data['View']) . '</strong></td>' . '<td>' . PMA_mimeDefaultFunction($create_data['Create View']) . '</td>' . '</tr>'; $odd1 = !$odd1; } else { $row_class = $odd2 ? 'odd' : 'even'; $create_data = PMA_getShowCreate($db, $object, 'table'); $tables .= '<tr class="' . $row_class . '">' . '<td><strong>' . PMA_mimeDefaultFunction($create_data['Table']) . '</strong></td>' . '<td>' . PMA_mimeDefaultFunction($create_data['Create Table']) . '</td>' . '</tr>'; $odd2 = !$odd2; } } // Prepare table header for each type of object. if (!empty($tables)) { $title = __('Tables'); $tables = sprintf($output_table, $title, 'Table', 'Table') . $tables . '</tbody></table></fieldset>'; } if (!empty($views)) { $title = __('Views'); $views = sprintf($output_table, $title, 'View', 'View') . $views . '</tbody></table></fieldset>'; } // Compile the final html. $html_output .= $tables . $views . '</div>'; return $html_output; }
$GLOBALS['pma']->databases->build(); } if (isset($GLOBALS['add_constraints'])) { $GLOBALS['sql_constraints_query_full_db'] = ''; } $tables_full = PMA_DBI_get_tables_full($db); $views = array(); foreach ($tables_full as $each_table => $tmp) { // to be able to rename a db containing views, we // first collect in $views all the views we find and we // will handle them after the tables /** * @todo support a view of a view * @todo support triggers */ if (PMA_Table::isView($db, $each_table)) { $views[] = $each_table; continue; } $back = $sql_query; $sql_query = ''; // value of $what for this table only $this_what = $what; // do not copy the data from a Merge table // note: on the calling FORM, 'data' means 'structure and data' if ($tables_full[$each_table]['Engine'] == 'MRG_MyISAM') { if ($this_what == 'data') { $this_what = 'structure'; } if ($this_what == 'dataonly') { $this_what = 'nocopy';
/** * Get VIEWs in a particular database * * @param string $db Database name to look in * * @return array $views Set of VIEWs inside the database */ public function getVirtualTables($db) { $tables_full = $this->getTablesFull($db); $views = array(); foreach ($tables_full as $table => $tmp) { if (PMA_Table::isView($db, $table)) { $views[] = $table; } } return $views; }
/** * Set a property from UI preferences. * If pmadb and table_uiprefs is set, it will save the UI preferences to * phpMyAdmin database. * Available property: * - PROP_SORTED_COLUMN * - PROP_COLUMN_ORDER * - PROP_COLUMN_VISIB * * @param string $property Property * @param mixed $value Value for the property * @param string $table_create_time Needed for PROP_COLUMN_ORDER and PROP_COLUMN_VISIB * * @return boolean|PMA_Message */ public function setUiProp($property, $value, $table_create_time = null) { if (!isset($this->uiprefs)) { $this->loadUiPrefs(); } // we want to save the create time if the property is PROP_COLUMN_ORDER if (!PMA_Table::isView($this->db_name, $this->name) && ($property == self::PROP_COLUMN_ORDER || $property == self::PROP_COLUMN_VISIB)) { $curr_create_time = self::sGetStatusInfo($this->db_name, $this->name, 'CREATE_TIME'); if (isset($table_create_time) && $table_create_time == $curr_create_time) { $this->uiprefs['CREATE_TIME'] = $curr_create_time; } else { // there is no $table_create_time, or // supplied $table_create_time is older than current create time, // so don't save return PMA_Message::error(sprintf(__('Cannot save UI property "%s". The changes made will not be persistent after you refresh this page. Please check if the table structure has been changed.'), $property)); } } // save the value $this->uiprefs[$property] = $value; // check if pmadb is set if (strlen($GLOBALS['cfg']['Server']['pmadb']) && strlen($GLOBALS['cfg']['Server']['table_uiprefs'])) { return $this->saveUiprefsToDb(); } return true; }
/** * Returns the table tabs as an array * * @return array Data for generating table tabs */ private function _getTableTabs() { $db_is_information_schema = PMA_is_system_schema($this->_db); $tbl_is_view = PMA_Table::isView($this->_db, $this->_table); $table_info_num_rows = PMA_Table::countRecords($this->_db, $this->_table); $tabs = array(); $tabs['browse']['icon'] = 'b_browse.png'; $tabs['browse']['text'] = __('Browse'); $tabs['browse']['link'] = 'sql.php'; $tabs['browse']['args']['pos'] = 0; $tabs['structure']['icon'] = 'b_props.png'; $tabs['structure']['link'] = 'tbl_structure.php'; $tabs['structure']['text'] = __('Structure'); $tabs['sql']['icon'] = 'b_sql.png'; $tabs['sql']['link'] = 'tbl_sql.php'; $tabs['sql']['text'] = __('SQL'); $tabs['search']['icon'] = 'b_search.png'; $tabs['search']['text'] = __('Search'); $tabs['search']['link'] = 'tbl_select.php'; $tabs['search']['active'] = in_array(basename($GLOBALS['PMA_PHP_SELF']), array('tbl_select.php', 'tbl_zoom_select.php')); if (!$db_is_information_schema) { $tabs['insert']['icon'] = 'b_insrow.png'; $tabs['insert']['link'] = 'tbl_change.php'; $tabs['insert']['text'] = __('Insert'); } $tabs['export']['icon'] = 'b_tblexport.png'; $tabs['export']['link'] = 'tbl_export.php'; $tabs['export']['args']['single_table'] = 'true'; $tabs['export']['text'] = __('Export'); /** * Don't display "Import" and "Operations" * for views and information_schema */ if (!$tbl_is_view && !$db_is_information_schema) { $tabs['import']['icon'] = 'b_tblimport.png'; $tabs['import']['link'] = 'tbl_import.php'; $tabs['import']['text'] = __('Import'); $tabs['operation']['icon'] = 'b_tblops.png'; $tabs['operation']['link'] = 'tbl_operations.php'; $tabs['operation']['text'] = __('Operations'); } if (PMA_Tracker::isActive()) { $tabs['tracking']['icon'] = 'eye.png'; $tabs['tracking']['text'] = __('Tracking'); $tabs['tracking']['link'] = 'tbl_tracking.php'; } if (!$db_is_information_schema && !PMA_DRIZZLE && PMA_Util::currentUserHasPrivilege('TRIGGER', $this->_db, $this->_table) && !$tbl_is_view) { $tabs['triggers']['link'] = 'tbl_triggers.php'; $tabs['triggers']['text'] = __('Triggers'); $tabs['triggers']['icon'] = 'b_triggers.png'; } /** * Views support a limited number of operations */ if ($tbl_is_view && !$db_is_information_schema) { $tabs['operation']['icon'] = 'b_tblops.png'; $tabs['operation']['link'] = 'view_operations.php'; $tabs['operation']['text'] = __('Operations'); } return $tabs; }
/** * Displays a table of results returned by a sql query. * This function is called by the "sql.php" script. * * @param integer the link id associated to the query which results have * to be displayed * @param array the display mode * @param array the analyzed query * * @global string $db the database name * @global string $table the table name * @global string $goto the url to go back in case of errors * @global boolean $dontlimitchars whether to limit the number of displayed * characters of text type fields or not * @global string $sql_query the current sql query * @global integer $num_rows the total number of rows returned by the * sql query * @global integer $unlim_num_rows the total number of rows returned by the * sql query without any programmatically * appended "LIMIT" clause * @global integer $pos the current postion of the first record * to be displayed * @global array $fields_meta the list of fields properties * @global integer $fields_cnt the total number of fields returned by * the sql query * @global array $vertical_display informations used with vertical display * mode * @global string $disp_direction the display mode * (horizontal/vertical/horizontalflipped) * @global integer $repeat_cells the number of row to display between two * table headers * @global array $highlight_columns collumn names to highlight * @global array $cfgRelation the relation settings * * @access private * * @see PMA_showMessage(), PMA_setDisplayMode(), * PMA_displayTableNavigation(), PMA_displayTableHeaders(), * PMA_displayTableBody(), PMA_displayResultsOperations() */ function PMA_displayTable(&$dt_result, &$the_disp_mode, $analyzed_sql) { global $db, $table, $goto, $dontlimitchars; global $sql_query, $num_rows, $unlim_num_rows, $pos, $fields_meta, $fields_cnt; global $vertical_display, $disp_direction, $repeat_cells, $highlight_columns; global $cfgRelation; // 1. ----- Prepares the work ----- // 1.1 Gets the informations about which functionnalities should be // displayed $total = ''; $is_display = PMA_setDisplayMode($the_disp_mode, $total); if ($total == '') { unset($total); } // 1.2 Defines offsets for the next and previous pages if ($is_display['nav_bar'] == '1') { if (!isset($pos)) { $pos = 0; } if ($GLOBALS['session_max_rows'] == 'all') { $pos_next = 0; $pos_prev = 0; } else { $pos_next = $pos + $GLOBALS['cfg']['MaxRows']; $pos_prev = $pos - $GLOBALS['cfg']['MaxRows']; if ($pos_prev < 0) { $pos_prev = 0; } } } // end if // 1.3 Urlencodes the query to use in input form fields $encoded_sql_query = urlencode($sql_query); // 2. ----- Displays the top of the page ----- // 2.1 Displays a messages with position informations if ($is_display['nav_bar'] == '1' && isset($pos_next)) { if (isset($unlim_num_rows) && $unlim_num_rows != $total) { $selectstring = ', ' . $unlim_num_rows . ' ' . $GLOBALS['strSelectNumRows']; } else { $selectstring = ''; } $last_shown_rec = $GLOBALS['session_max_rows'] == 'all' || $pos_next > $total ? $total - 1 : $pos_next - 1; PMA_showMessage($GLOBALS['strShowingRecords'] . " {$pos} - {$last_shown_rec} (" . PMA_formatNumber($total, 0) . ' ' . $GLOBALS['strTotal'] . $selectstring . ', ' . sprintf($GLOBALS['strQueryTime'], $GLOBALS['querytime']) . ')'); if (isset($table) && PMA_Table::isView($db, $table) && $total == $GLOBALS['cfg']['MaxExactCount']) { echo '<div class="notice">' . "\n"; echo PMA_sanitize(sprintf($GLOBALS['strViewMaxExactCount'], PMA_formatNumber($GLOBALS['cfg']['MaxExactCount'], 0), '[a@./Documentation.html#cfg_MaxExactCount@_blank]', '[/a]')) . "\n"; echo '</div>' . "\n"; } } elseif (!isset($GLOBALS['printview']) || $GLOBALS['printview'] != '1') { PMA_showMessage($GLOBALS['strSQLQuery']); } // 2.3 Displays the navigation bars if (!isset($table) || strlen(trim($table)) == 0) { if (isset($analyzed_sql[0]['query_type']) && $analyzed_sql[0]['query_type'] == 'SELECT') { // table does not always contain a real table name, // for example in MySQL 5.0.x, the query SHOW STATUS // returns STATUS as a table name $table = $fields_meta[0]->table; } else { $table = ''; } } if (!isset($GLOBALS['printview']) || $GLOBALS['printview'] != '1') { PMA_displayResultsOperations($the_disp_mode, $analyzed_sql); } if ($is_display['nav_bar'] == '1') { PMA_displayTableNavigation($pos_next, $pos_prev, $encoded_sql_query); echo "\n"; } elseif (!isset($GLOBALS['printview']) || $GLOBALS['printview'] != '1') { echo "\n" . '<br /><br />' . "\n"; } // 2b ----- Get field references from Database ----- // (see the 'relation' config variable) // loic1, 2002-03-02: extended to php3 // init map $map = array(); // find tables $target = array(); if (isset($analyzed_sql[0]['table_ref']) && is_array($analyzed_sql[0]['table_ref'])) { foreach ($analyzed_sql[0]['table_ref'] as $table_ref_position => $table_ref) { $target[] = $analyzed_sql[0]['table_ref'][$table_ref_position]['table_true_name']; } } $tabs = '(\'' . join('\',\'', $target) . '\')'; if ($cfgRelation['displaywork']) { if (!isset($table) || !strlen($table)) { $exist_rel = false; } else { $exist_rel = PMA_getForeigners($db, $table, '', 'both'); if ($exist_rel) { foreach ($exist_rel as $master_field => $rel) { $display_field = PMA_getDisplayField($rel['foreign_db'], $rel['foreign_table']); $map[$master_field] = array($rel['foreign_table'], $rel['foreign_field'], $display_field, $rel['foreign_db']); } // end while } // end if } // end if } // end if // end 2b // 3. ----- Displays the results table ----- PMA_displayTableHeaders($is_display, $fields_meta, $fields_cnt, $analyzed_sql); $url_query = ''; echo '<tbody>' . "\n"; PMA_displayTableBody($dt_result, $is_display, $map, $analyzed_sql); echo '</tbody>' . "\n"; // vertical output case if ($disp_direction == 'vertical') { PMA_displayVerticalTable(); } // end if unset($vertical_display); ?> </table> <?php // 4. ----- Displays the link for multi-fields delete if ($is_display['del_lnk'] == 'dr' && $is_display['del_lnk'] != 'kp') { $delete_text = $is_display['del_lnk'] == 'dr' ? $GLOBALS['strDelete'] : $GLOBALS['strKill']; $uncheckall_url = 'sql.php?' . PMA_generate_common_url($db, $table) . '&sql_query=' . urlencode($sql_query) . '&pos=' . $pos . '&session_max_rows=' . $GLOBALS['session_max_rows'] . '&pos=' . $pos . '&disp_direction=' . $disp_direction . '&repeat_cells=' . $repeat_cells . '&goto=' . $goto . '&dontlimitchars=' . $dontlimitchars; $checkall_url = $uncheckall_url . '&checkall=1'; if ($disp_direction == 'vertical') { $checkall_params['onclick'] = 'if (setCheckboxes(\'rowsDeleteForm\', true)) return false;'; $uncheckall_params['onclick'] = 'if (setCheckboxes(\'rowsDeleteForm\', false)) return false;'; } else { $checkall_params['onclick'] = 'if (markAllRows(\'rowsDeleteForm\')) return false;'; $uncheckall_params['onclick'] = 'if (unMarkAllRows(\'rowsDeleteForm\')) return false;'; } $checkall_link = PMA_linkOrButton($checkall_url, $GLOBALS['strCheckAll'], $checkall_params, false); $uncheckall_link = PMA_linkOrButton($uncheckall_url, $GLOBALS['strUncheckAll'], $uncheckall_params, false); if ($disp_direction != 'vertical') { echo '<img class="selectallarrow" width="38" height="22"' . ' src="' . $GLOBALS['pmaThemeImage'] . 'arrow_' . $GLOBALS['text_dir'] . '.png' . '"' . ' alt="' . $GLOBALS['strWithChecked'] . '" />'; } echo $checkall_link . "\n" . ' / ' . "\n" . $uncheckall_link . "\n" . '<i>' . $GLOBALS['strWithChecked'] . '</i>' . "\n"; if ($GLOBALS['cfg']['PropertiesIconic']) { PMA_buttonOrImage('submit_mult', 'mult_submit', 'submit_mult_change', $GLOBALS['strChange'], 'b_edit.png'); PMA_buttonOrImage('submit_mult', 'mult_submit', 'submit_mult_delete', $delete_text, 'b_drop.png'); if ($analyzed_sql[0]['querytype'] == 'SELECT') { PMA_buttonOrImage('submit_mult', 'mult_submit', 'submit_mult_export', $GLOBALS['strExport'], 'b_tblexport.png'); } echo "\n"; } else { echo ' <input type="submit" name="submit_mult"' . ' value="' . htmlspecialchars($GLOBALS['strEdit']) . '"' . ' title="' . $GLOBALS['strEdit'] . '" />' . "\n"; echo ' <input type="submit" name="submit_mult"' . ' value="' . htmlspecialchars($delete_text) . '"' . ' title="' . $delete_text . '" />' . "\n"; if ($analyzed_sql[0]['querytype'] == 'SELECT') { echo ' <input type="submit" name="submit_mult"' . ' value="' . htmlspecialchars($GLOBALS['strExport']) . '"' . ' title="' . $GLOBALS['strExport'] . '" />' . "\n"; } } echo '<input type="hidden" name="sql_query"' . ' value="' . htmlspecialchars($sql_query) . '" />' . "\n"; echo '<input type="hidden" name="pos" value="' . $pos . '" />' . "\n"; echo '<input type="hidden" name="url_query"' . ' value="' . $GLOBALS['url_query'] . '" />' . "\n"; echo '</form>' . "\n"; } // 5. ----- Displays the navigation bar at the bottom if required ----- if ($is_display['nav_bar'] == '1') { echo '<br />' . "\n"; PMA_displayTableNavigation($pos_next, $pos_prev, $encoded_sql_query); } elseif (!isset($GLOBALS['printview']) || $GLOBALS['printview'] != '1') { echo "\n" . '<br /><br />' . "\n"; } }
} } if (!PMA_exportDBFooter($db)) { break; } } else { if (!PMA_exportDBHeader($db)) { break; } // We export just one table if ($limit_to > 0 && $limit_from >= 0) { $add_query = ' LIMIT ' . ($limit_from > 0 ? $limit_from . ', ' : '') . $limit_to; } else { $add_query = ''; } $is_view = PMA_Table::isView($db, $table); if (isset($GLOBALS[$what . '_structure'])) { if (!PMA_exportStructure($db, $table, $crlf, $err_url, $do_relation, $do_comments, $do_mime, $do_dates, $is_view ? 'create_view' : 'create_table', $export_type)) { break; } } // If this is an export of a single view, we have to export data; // for example, a PDF report if (isset($GLOBALS[$what . '_data'])) { if (!empty($sql_query)) { // only preg_replace if needed if (!empty($add_query)) { // remove trailing semicolon before adding a LIMIT $sql_query = preg_replace('%;\\s*$%', '', $sql_query); } $local_query = $sql_query . $add_query;
/** * Counts and returns (or displays) the number of records in a table * * Revision 13 July 2001: Patch for limiting dump size from * vinay@sanisoft.com & girish@sanisoft.com * * @param string the current database name * @param string the current table name * @param boolean whether to retain or to displays the result * @param boolean whether to force an exact count * * @return mixed the number of records if retain is required, true else * * @access public */ function countRecords($db, $table, $ret = false, $force_exact = false) { $row_count = false; if (!$force_exact) { $row_count = PMA_DBI_fetch_value('SHOW TABLE STATUS FROM ' . PMA_backquote($db) . ' LIKE \'' . PMA_sqlAddslashes($table, true) . '\';', 0, 'Rows'); } $tbl_is_view = PMA_Table::isView($db, $table); // for a VIEW, $row_count is always false at this point if (false === $row_count || $row_count < $GLOBALS['cfg']['MaxExactCount']) { if (!$tbl_is_view) { $row_count = PMA_DBI_fetch_value('SELECT COUNT(*) FROM ' . PMA_backquote($db) . '.' . PMA_backquote($table)); } else { // For complex views, even trying to get a partial record // count could bring down a server, so we offer an // alternative: setting MaxExactCountViews to 0 will bypass // completely the record counting for views if ($GLOBALS['cfg']['MaxExactCountViews'] == 0) { $row_count = 0; } else { // Counting all rows of a VIEW could be too long, so use // a LIMIT clause. // Use try_query because it can fail (a VIEW is based on // a table that no longer exists) $result = PMA_DBI_try_query('SELECT 1 FROM ' . PMA_backquote($db) . '.' . PMA_backquote($table) . ' LIMIT ' . $GLOBALS['cfg']['MaxExactCountViews'], null, PMA_DBI_QUERY_STORE); if (!PMA_DBI_getError()) { $row_count = PMA_DBI_num_rows($result); PMA_DBI_free_result($result); } } } } if ($ret) { return $row_count; } /** * @deprecated at the moment nowhere is $return = false used */ // Note: as of PMA 2.8.0, we no longer seem to be using // PMA_Table::countRecords() in display mode. echo PMA_formatNumber($row_count, 0); if ($tbl_is_view) { echo ' ' . sprintf($GLOBALS['strViewMaxExactCount'], $GLOBALS['cfg']['MaxExactCount'], '[a@./Documentation.html#cfg_MaxExactCount@_blank]', '[/a]'); } }
/** * Export at the table level * * @param string $db the database to export * @param string $table the table to export * @param string $whatStrucOrData structure or data or both * @param ExportPlugin $export_plugin the selected export plugin * @param string $crlf end of line character(s) * @param string $err_url the URL in case of error * @param string $export_type the export type * @param bool $do_relation whether to export relation info * @param bool $do_comments whether to add comments * @param bool $do_mime whether to add MIME info * @param bool $do_dates whether to add dates * @param string $allrows whether "dump all rows" was ticked * @param string $limit_to upper limit * @param string $limit_from starting limit * @param string $sql_query query for which exporting is requested * @param array $aliases Alias information for db/table/column * * @return void */ function PMA_exportTable($db, $table, $whatStrucOrData, $export_plugin, $crlf, $err_url, $export_type, $do_relation, $do_comments, $do_mime, $do_dates, $allrows, $limit_to, $limit_from, $sql_query, $aliases) { $db_alias = !empty($aliases[$db]['alias']) ? $aliases[$db]['alias'] : ''; if (!$export_plugin->exportDBHeader($db, $db_alias)) { return; } if (isset($allrows) && $allrows == '0' && $limit_to > 0 && $limit_from >= 0) { $add_query = ' LIMIT ' . ($limit_from > 0 ? $limit_from . ', ' : '') . $limit_to; } else { $add_query = ''; } $_table = new PMA_Table($table, $db); $is_view = $_table->isView(); if ($whatStrucOrData == 'structure' || $whatStrucOrData == 'structure_and_data') { if ($is_view) { if (isset($GLOBALS['sql_create_view'])) { if (!$export_plugin->exportStructure($db, $table, $crlf, $err_url, 'create_view', $export_type, $do_relation, $do_comments, $do_mime, $do_dates, $aliases)) { return; } } } else { if (isset($GLOBALS['sql_create_table'])) { if (!$export_plugin->exportStructure($db, $table, $crlf, $err_url, 'create_table', $export_type, $do_relation, $do_comments, $do_mime, $do_dates, $aliases)) { return; } } } } // If this is an export of a single view, we have to export data; // for example, a PDF report // if it is a merge table, no data is exported $table = new PMA_Table($table, $db); if (($whatStrucOrData == 'data' || $whatStrucOrData == 'structure_and_data') && !$table->isMerge()) { if (!empty($sql_query)) { // only preg_replace if needed if (!empty($add_query)) { // remove trailing semicolon before adding a LIMIT $sql_query = preg_replace('%;\\s*$%', '', $sql_query); } $local_query = $sql_query . $add_query; $GLOBALS['dbi']->selectDb($db); } else { $local_query = 'SELECT * FROM ' . PMA_Util::backquote($db) . '.' . PMA_Util::backquote($table) . $add_query; } if (!$export_plugin->exportData($db, $table, $crlf, $err_url, $local_query, $aliases)) { return; } } // now export the triggers (needs to be done after the data because // triggers can modify already imported tables) if (isset($GLOBALS['sql_create_trigger']) && ($whatStrucOrData == 'structure' || $whatStrucOrData == 'structure_and_data')) { if (!$export_plugin->exportStructure($db, $table, $crlf, $err_url, 'triggers', $export_type, $do_relation, $do_comments, $do_mime, $do_dates, $aliases)) { return; } } if (!$export_plugin->exportDBFooter($db)) { return; } if (isset($GLOBALS['sql_metadata'])) { // Types of metadata to export. // In the future these can be allowed to be selected by the user $metadataTypes = PMA_getMetadataTypesToExport(); $export_plugin->exportMetadata($db, $table, $metadataTypes); } }
/** * return html for tables' detail * * @param array $the_tables tables list * @param string $db database name * @param array $cfg global config * @param array $cfgRelation config from PMA_getRelationsParam * @param int $cell_align_left cell align left * * @return string */ function PMA_getHtmlForTablesDetail($the_tables, $db, $cfg, $cfgRelation, $cell_align_left) { $html = ''; $tables_cnt = count($the_tables); $multi_tables = count($the_tables) > 1; $counter = 0; foreach ($the_tables as $table) { if ($counter + 1 >= $tables_cnt) { $breakstyle = ''; } else { $breakstyle = ' style="page-break-after: always;"'; } $counter++; $html .= '<div' . $breakstyle . '>' . "\n"; $html .= '<h1>' . htmlspecialchars($table) . '</h1>' . "\n"; /** * Gets table informations */ $showtable = PMA_Table::sGetStatusInfo($db, $table); $num_rows = isset($showtable['Rows']) ? $showtable['Rows'] : 0; $show_comment = isset($showtable['Comment']) ? $showtable['Comment'] : ''; $tbl_is_view = PMA_Table::isView($db, $table); /** * Gets fields properties */ $columns = $GLOBALS['dbi']->getColumns($db, $table); // We need this to correctly learn if a TIMESTAMP is NOT NULL, since // SHOW FULL FIELDS or INFORMATION_SCHEMA incorrectly says NULL // and SHOW CREATE TABLE says NOT NULL (tested // in MySQL 4.0.25 and 5.0.21, http://bugs.mysql.com/20910). $show_create_table = $GLOBALS['dbi']->fetchValue('SHOW CREATE TABLE ' . PMA_Util::backquote($db) . '.' . PMA_Util::backquote($table), 0, 1); $analyzed_sql = PMA_SQP_analyze(PMA_SQP_parse($show_create_table)); // Check if we can use Relations // Find which tables are related with the current one and write it in // an array $res_rel = PMA_getForeigners($db, $table); $have_rel = (bool) count($res_rel); /** * Displays the comments of the table if MySQL >= 3.23 */ if (!empty($show_comment)) { $html .= __('Table comments:') . ' ' . htmlspecialchars($show_comment) . '<br /><br />'; } $html .= PMA_getHtmlForTableStructure($have_rel, $tbl_is_view, $columns, $analyzed_sql, $res_rel, $db, $table, $cfgRelation, $cfg, $showtable, $cell_align_left); if ($multi_tables) { unset($num_rows, $show_comment); $html .= '<hr />' . "\n"; } // end if $html .= '</div>' . "\n"; } // end while return $html; }
/** * Copies or renames table * */ public static function moveCopy($source_db, $source_table, $target_db, $target_table, $what, $move, $mode) { global $err_url; /* Try moving table directly */ if ($move && $what == 'data') { $tbl = new PMA_Table($source_table, $source_db); $result = $tbl->rename($target_table, $target_db, PMA_Table::isView($source_db, $source_table)); if ($result) { $GLOBALS['message'] = $tbl->getLastMessage(); return true; } } // set export settings we need $GLOBALS['sql_backquotes'] = 1; $GLOBALS['asfile'] = 1; // Ensure the target is valid if (!$GLOBALS['pma']->databases->exists($source_db, $target_db)) { if (!$GLOBALS['pma']->databases->exists($source_db)) { $GLOBALS['message'] = PMA_Message::rawError('source database `' . htmlspecialchars($source_db) . '` not found'); } if (!$GLOBALS['pma']->databases->exists($target_db)) { $GLOBALS['message'] = PMA_Message::rawError('target database `' . htmlspecialchars($target_db) . '` not found'); } return false; } $source = PMA_backquote($source_db) . '.' . PMA_backquote($source_table); if (!isset($target_db) || !strlen($target_db)) { $target_db = $source_db; } // Doing a select_db could avoid some problems with replicated databases, // when moving table from replicated one to not replicated one PMA_DBI_select_db($target_db); $target = PMA_backquote($target_db) . '.' . PMA_backquote($target_table); // do not create the table if dataonly if ($what != 'dataonly') { require_once './libraries/export/sql.php'; $no_constraints_comments = true; $GLOBALS['sql_constraints_query'] = ''; $sql_structure = PMA_getTableDef($source_db, $source_table, "\n", $err_url, false, false); unset($no_constraints_comments); $parsed_sql = PMA_SQP_parse($sql_structure); $analyzed_sql = PMA_SQP_analyze($parsed_sql); $i = 0; if (empty($analyzed_sql[0]['create_table_fields'])) { // this is not a CREATE TABLE, so find the first VIEW $target_for_view = PMA_backquote($target_db); while (true) { if ($parsed_sql[$i]['type'] == 'alpha_reservedWord' && $parsed_sql[$i]['data'] == 'VIEW') { break; } $i++; } } unset($analyzed_sql); $server_sql_mode = PMA_DBI_fetch_value("SHOW VARIABLES LIKE 'sql_mode'", 0, 1); // ANSI_QUOTES might be a subset of sql_mode, for example // REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI if (false !== strpos($server_sql_mode, 'ANSI_QUOTES')) { $table_delimiter = 'quote_double'; } else { $table_delimiter = 'quote_backtick'; } unset($server_sql_mode); /* Find table name in query and replace it */ while ($parsed_sql[$i]['type'] != $table_delimiter) { $i++; } /* no need to PMA_backquote() */ if (isset($target_for_view)) { // this a view definition; we just found the first db name // that follows DEFINER VIEW // so change it for the new db name $parsed_sql[$i]['data'] = $target_for_view; // then we have to find all references to the source db // and change them to the target db, ensuring we stay into // the $parsed_sql limits $last = $parsed_sql['len'] - 1; $backquoted_source_db = PMA_backquote($source_db); for (++$i; $i <= $last; $i++) { if ($parsed_sql[$i]['type'] == $table_delimiter && $parsed_sql[$i]['data'] == $backquoted_source_db) { $parsed_sql[$i]['data'] = $target_for_view; } } unset($last, $backquoted_source_db); } else { $parsed_sql[$i]['data'] = $target; } /* Generate query back */ $sql_structure = PMA_SQP_formatHtml($parsed_sql, 'query_only'); // If table exists, and 'add drop table' is selected: Drop it! $drop_query = ''; if (isset($GLOBALS['drop_if_exists']) && $GLOBALS['drop_if_exists'] == 'true') { if (PMA_Table::_isView($target_db, $target_table)) { $drop_query = 'DROP VIEW'; } else { $drop_query = 'DROP TABLE'; } $drop_query .= ' IF EXISTS ' . PMA_backquote($target_db) . '.' . PMA_backquote($target_table); PMA_DBI_query($drop_query); $GLOBALS['sql_query'] .= "\n" . $drop_query . ';'; // If an existing table gets deleted, maintain any // entries for the PMA_* tables $maintain_relations = true; } @PMA_DBI_query($sql_structure); $GLOBALS['sql_query'] .= "\n" . $sql_structure . ';'; if (($move || isset($GLOBALS['add_constraints'])) && !empty($GLOBALS['sql_constraints_query'])) { $parsed_sql = PMA_SQP_parse($GLOBALS['sql_constraints_query']); $i = 0; // find the first $table_delimiter, it must be the source table name while ($parsed_sql[$i]['type'] != $table_delimiter) { $i++; // maybe someday we should guard against going over limit //if ($i == $parsed_sql['len']) { // break; //} } // replace it by the target table name, no need to PMA_backquote() $parsed_sql[$i]['data'] = $target; // now we must remove all $table_delimiter that follow a CONSTRAINT // keyword, because a constraint name must be unique in a db $cnt = $parsed_sql['len'] - 1; for ($j = $i; $j < $cnt; $j++) { if ($parsed_sql[$j]['type'] == 'alpha_reservedWord' && strtoupper($parsed_sql[$j]['data']) == 'CONSTRAINT') { if ($parsed_sql[$j + 1]['type'] == $table_delimiter) { $parsed_sql[$j + 1]['data'] = ''; } } } // Generate query back $GLOBALS['sql_constraints_query'] = PMA_SQP_formatHtml($parsed_sql, 'query_only'); if ($mode == 'one_table') { PMA_DBI_query($GLOBALS['sql_constraints_query']); } $GLOBALS['sql_query'] .= "\n" . $GLOBALS['sql_constraints_query']; if ($mode == 'one_table') { unset($GLOBALS['sql_constraints_query']); } } } else { $GLOBALS['sql_query'] = ''; } // Copy the data unless this is a VIEW if (($what == 'data' || $what == 'dataonly') && !PMA_Table::_isView($target_db, $target_table)) { $sql_insert_data = 'INSERT INTO ' . $target . ' SELECT * FROM ' . $source; PMA_DBI_query($sql_insert_data); $GLOBALS['sql_query'] .= "\n\n" . $sql_insert_data . ';'; } $GLOBALS['cfgRelation'] = PMA_getRelationsParam(); // Drops old table if the user has requested to move it if ($move) { // This could avoid some problems with replicated databases, when // moving table from replicated one to not replicated one PMA_DBI_select_db($source_db); if (PMA_Table::_isView($source_db, $source_table)) { $sql_drop_query = 'DROP VIEW'; } else { $sql_drop_query = 'DROP TABLE'; } $sql_drop_query .= ' ' . $source; PMA_DBI_query($sql_drop_query); // Move old entries from PMA-DBs to new table if ($GLOBALS['cfgRelation']['commwork']) { $remove_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['column_info']) . ' SET table_name = \'' . PMA_sqlAddslashes($target_table) . '\', ' . ' db_name = \'' . PMA_sqlAddslashes($target_db) . '\'' . ' WHERE db_name = \'' . PMA_sqlAddslashes($source_db) . '\'' . ' AND table_name = \'' . PMA_sqlAddslashes($source_table) . '\''; PMA_query_as_controluser($remove_query); unset($remove_query); } // updating bookmarks is not possible since only a single table is moved, // and not the whole DB. if ($GLOBALS['cfgRelation']['displaywork']) { $table_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['table_info']) . ' SET db_name = \'' . PMA_sqlAddslashes($target_db) . '\', ' . ' table_name = \'' . PMA_sqlAddslashes($target_table) . '\'' . ' WHERE db_name = \'' . PMA_sqlAddslashes($source_db) . '\'' . ' AND table_name = \'' . PMA_sqlAddslashes($source_table) . '\''; PMA_query_as_controluser($table_query); unset($table_query); } if ($GLOBALS['cfgRelation']['relwork']) { $table_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['relation']) . ' SET foreign_table = \'' . PMA_sqlAddslashes($target_table) . '\',' . ' foreign_db = \'' . PMA_sqlAddslashes($target_db) . '\'' . ' WHERE foreign_db = \'' . PMA_sqlAddslashes($source_db) . '\'' . ' AND foreign_table = \'' . PMA_sqlAddslashes($source_table) . '\''; PMA_query_as_controluser($table_query); unset($table_query); $table_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['relation']) . ' SET master_table = \'' . PMA_sqlAddslashes($target_table) . '\',' . ' master_db = \'' . PMA_sqlAddslashes($target_db) . '\'' . ' WHERE master_db = \'' . PMA_sqlAddslashes($source_db) . '\'' . ' AND master_table = \'' . PMA_sqlAddslashes($source_table) . '\''; PMA_query_as_controluser($table_query); unset($table_query); } /** * @todo Can't get moving PDFs the right way. The page numbers * always get screwed up independently from duplication because the * numbers do not seem to be stored on a per-database basis. Would * the author of pdf support please have a look at it? */ if ($GLOBALS['cfgRelation']['pdfwork']) { $table_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['table_coords']) . ' SET table_name = \'' . PMA_sqlAddslashes($target_table) . '\',' . ' db_name = \'' . PMA_sqlAddslashes($target_db) . '\'' . ' WHERE db_name = \'' . PMA_sqlAddslashes($source_db) . '\'' . ' AND table_name = \'' . PMA_sqlAddslashes($source_table) . '\''; PMA_query_as_controluser($table_query); unset($table_query); /* $pdf_query = 'SELECT pdf_page_number ' . ' FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['table_coords']) . ' WHERE db_name = \'' . PMA_sqlAddslashes($target_db) . '\'' . ' AND table_name = \'' . PMA_sqlAddslashes($target_table) . '\''; $pdf_rs = PMA_query_as_controluser($pdf_query); while ($pdf_copy_row = PMA_DBI_fetch_assoc($pdf_rs)) { $table_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['pdf_pages']) . ' SET db_name = \'' . PMA_sqlAddslashes($target_db) . '\'' . ' WHERE db_name = \'' . PMA_sqlAddslashes($source_db) . '\'' . ' AND page_nr = \'' . PMA_sqlAddslashes($pdf_copy_row['pdf_page_number']) . '\''; $tb_rs = PMA_query_as_controluser($table_query); unset($table_query); unset($tb_rs); } */ } if ($GLOBALS['cfgRelation']['designerwork']) { $table_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['designer_coords']) . ' SET table_name = \'' . PMA_sqlAddslashes($target_table) . '\',' . ' db_name = \'' . PMA_sqlAddslashes($target_db) . '\'' . ' WHERE db_name = \'' . PMA_sqlAddslashes($source_db) . '\'' . ' AND table_name = \'' . PMA_sqlAddslashes($source_table) . '\''; PMA_query_as_controluser($table_query); unset($table_query); } $GLOBALS['sql_query'] .= "\n\n" . $sql_drop_query . ';'; // end if ($move) } else { // we are copying // Create new entries as duplicates from old PMA DBs if ($what != 'dataonly' && !isset($maintain_relations)) { if ($GLOBALS['cfgRelation']['commwork']) { // Get all comments and MIME-Types for current table $comments_copy_query = 'SELECT column_name, ' . PMA_backquote('comment') . ($GLOBALS['cfgRelation']['mimework'] ? ', mimetype, transformation, transformation_options' : '') . ' FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['column_info']) . ' WHERE db_name = \'' . PMA_sqlAddslashes($source_db) . '\' AND table_name = \'' . PMA_sqlAddslashes($source_table) . '\''; $comments_copy_rs = PMA_query_as_controluser($comments_copy_query); // Write every comment as new copied entry. [MIME] while ($comments_copy_row = PMA_DBI_fetch_assoc($comments_copy_rs)) { $new_comment_query = 'REPLACE INTO ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['column_info']) . ' (db_name, table_name, column_name, ' . PMA_backquote('comment') . ($GLOBALS['cfgRelation']['mimework'] ? ', mimetype, transformation, transformation_options' : '') . ') ' . ' VALUES(' . '\'' . PMA_sqlAddslashes($target_db) . '\',' . '\'' . PMA_sqlAddslashes($target_table) . '\',' . '\'' . PMA_sqlAddslashes($comments_copy_row['column_name']) . '\'' . ($GLOBALS['cfgRelation']['mimework'] ? ',\'' . PMA_sqlAddslashes($comments_copy_row['comment']) . '\',' . '\'' . PMA_sqlAddslashes($comments_copy_row['mimetype']) . '\',' . '\'' . PMA_sqlAddslashes($comments_copy_row['transformation']) . '\',' . '\'' . PMA_sqlAddslashes($comments_copy_row['transformation_options']) . '\'' : '') . ')'; PMA_query_as_controluser($new_comment_query); } // end while PMA_DBI_free_result($comments_copy_rs); unset($comments_copy_rs); } // duplicating the bookmarks must not be done here, but // just once per db $get_fields = array('display_field'); $where_fields = array('db_name' => $source_db, 'table_name' => $source_table); $new_fields = array('db_name' => $target_db, 'table_name' => $target_table); PMA_Table::duplicateInfo('displaywork', 'table_info', $get_fields, $where_fields, $new_fields); /** * @todo revise this code when we support cross-db relations */ $get_fields = array('master_field', 'foreign_table', 'foreign_field'); $where_fields = array('master_db' => $source_db, 'master_table' => $source_table); $new_fields = array('master_db' => $target_db, 'foreign_db' => $target_db, 'master_table' => $target_table); PMA_Table::duplicateInfo('relwork', 'relation', $get_fields, $where_fields, $new_fields); $get_fields = array('foreign_field', 'master_table', 'master_field'); $where_fields = array('foreign_db' => $source_db, 'foreign_table' => $source_table); $new_fields = array('master_db' => $target_db, 'foreign_db' => $target_db, 'foreign_table' => $target_table); PMA_Table::duplicateInfo('relwork', 'relation', $get_fields, $where_fields, $new_fields); $get_fields = array('x', 'y', 'v', 'h'); $where_fields = array('db_name' => $source_db, 'table_name' => $source_table); $new_fields = array('db_name' => $target_db, 'table_name' => $target_table); PMA_Table::duplicateInfo('designerwork', 'designer_coords', $get_fields, $where_fields, $new_fields); /** * @todo Can't get duplicating PDFs the right way. The * page numbers always get screwed up independently from * duplication because the numbers do not seem to be stored on a * per-database basis. Would the author of pdf support please * have a look at it? * $get_fields = array('page_descr'); $where_fields = array('db_name' => $source_db); $new_fields = array('db_name' => $target_db); $last_id = PMA_Table::duplicateInfo('pdfwork', 'pdf_pages', $get_fields, $where_fields, $new_fields); if (isset($last_id) && $last_id >= 0) { $get_fields = array('x', 'y'); $where_fields = array('db_name' => $source_db, 'table_name' => $source_table); $new_fields = array('db_name' => $target_db, 'table_name' => $target_table, 'pdf_page_number' => $last_id); PMA_Table::duplicateInfo('pdfwork', 'table_coords', $get_fields, $where_fields, $new_fields); } */ } } return true; }