home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / phpMyAdmin / libraries / database_interface.lib.php < prev    next >
Encoding:
PHP Script  |  2008-06-23  |  48.7 KB  |  1,301 lines

  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4.  * Common Option Constants For DBI Functions
  5.  *
  6.  * @version $Id: database_interface.lib.php 11326 2008-06-17 21:32:48Z lem9 $
  7.  */
  8. if (! defined('PHPMYADMIN')) {
  9.     exit;
  10. }
  11.  
  12. /**
  13.  *
  14.  */
  15. // PMA_DBI_try_query()
  16. define('PMA_DBI_QUERY_STORE',       1);  // Force STORE_RESULT method, ignored by classic MySQL.
  17. define('PMA_DBI_QUERY_UNBUFFERED',  2);  // Do not read whole query
  18. // PMA_DBI_get_variable()
  19. define('PMA_DBI_GETVAR_SESSION', 1);
  20. define('PMA_DBI_GETVAR_GLOBAL', 2);
  21.  
  22. /**
  23.  * Loads the mysql extensions if it is not loaded yet
  24.  *
  25.  * @param   string  $extension  mysql extension to load
  26.  */
  27. function PMA_DBI_checkAndLoadMysqlExtension($extension = 'mysql') {
  28.     if (! function_exists($extension . '_connect')) {
  29.         PMA_dl($extension);
  30.         // check whether mysql is available
  31.         if (! function_exists($extension . '_connect')) {
  32.             return false;
  33.         }
  34.     }
  35.  
  36.     return true;
  37. }
  38.  
  39.  
  40. /**
  41.  * check for requested extension
  42.  */
  43. if (! PMA_DBI_checkAndLoadMysqlExtension($GLOBALS['cfg']['Server']['extension'])) {
  44.  
  45.     // if it fails try alternative extension ...
  46.     // and display an error ...
  47.  
  48.     /**
  49.      * @todo 2.7.1: add different messages for alternativ extension
  50.      * and complete fail (no alternativ extension too)
  51.      */
  52.     $GLOBALS['PMA_errors'][] =
  53.         sprintf(PMA_sanitize($GLOBALS['strCantLoad']),
  54.             $GLOBALS['cfg']['Server']['extension'])
  55.         .' - <a href="./Documentation.html#faqmysql" target="documentation">'
  56.         .$GLOBALS['strDocu'] . '</a>';
  57.  
  58.     if ($GLOBALS['cfg']['Server']['extension'] === 'mysql') {
  59.         $alternativ_extension = 'mysqli';
  60.     } else {
  61.         $alternativ_extension = 'mysql';
  62.     }
  63.  
  64.     if (! PMA_DBI_checkAndLoadMysqlExtension($alternativ_extension)) {
  65.         // if alternativ fails too ...
  66.         PMA_fatalError(
  67.             sprintf($GLOBALS['strCantLoad'],
  68.                 $GLOBALS['cfg']['Server']['extension'])
  69.             . ' - [a@./Documentation.html#faqmysql@documentation]'
  70.             . $GLOBALS['strDocu'] . '[/a]');
  71.     }
  72.  
  73.     $GLOBALS['cfg']['Server']['extension'] = $alternativ_extension;
  74.     unset($alternativ_extension);
  75. }
  76.  
  77. /**
  78.  * Including The DBI Plugin
  79.  */
  80. require_once './libraries/dbi/' . $GLOBALS['cfg']['Server']['extension'] . '.dbi.lib.php';
  81.  
  82. /**
  83.  * Common Functions
  84.  */
  85. function PMA_DBI_query($query, $link = null, $options = 0) {
  86.     $res = PMA_DBI_try_query($query, $link, $options)
  87.         or PMA_mysqlDie(PMA_DBI_getError($link), $query);
  88.     return $res;
  89. }
  90.  
  91. /**
  92.  * converts charset of a mysql message, usally coming from mysql_error(),
  93.  * into PMA charset, usally UTF-8
  94.  * uses language to charset mapping from mysql/share/errmsg.txt
  95.  * and charset names to ISO charset from information_schema.CHARACTER_SETS
  96.  *
  97.  * @uses    $GLOBALS['cfg']['IconvExtraParams']
  98.  * @uses    $GLOBALS['charset']     as target charset
  99.  * @uses    PMA_DBI_fetch_value()   to get server_language
  100.  * @uses    preg_match()            to filter server_language
  101.  * @uses    in_array()
  102.  * @uses    function_exists()       to check for a convert function
  103.  * @uses    iconv()                 to convert message
  104.  * @uses    libiconv()              to convert message
  105.  * @uses    recode_string()         to convert message
  106.  * @uses    mb_convert_encoding()   to convert message
  107.  * @param   string  $message
  108.  * @return  string  $message
  109.  */
  110. function PMA_DBI_convert_message($message) {
  111.     // latin always last!
  112.     $encodings = array(
  113.         'japanese'      => 'EUC-JP', //'ujis',
  114.         'japanese-sjis' => 'Shift-JIS', //'sjis',
  115.         'korean'        => 'EUC-KR', //'euckr',
  116.         'russian'       => 'KOI8-R', //'koi8r',
  117.         'ukrainian'     => 'KOI8-U', //'koi8u',
  118.         'greek'         => 'ISO-8859-7', //'greek',
  119.         'serbian'       => 'CP1250', //'cp1250',
  120.         'estonian'      => 'ISO-8859-13', //'latin7',
  121.         'slovak'        => 'ISO-8859-2', //'latin2',
  122.         'czech'         => 'ISO-8859-2', //'latin2',
  123.         'hungarian'     => 'ISO-8859-2', //'latin2',
  124.         'polish'        => 'ISO-8859-2', //'latin2',
  125.         'romanian'      => 'ISO-8859-2', //'latin2',
  126.         'spanish'       => 'CP1252', //'latin1',
  127.         'swedish'       => 'CP1252', //'latin1',
  128.         'italian'       => 'CP1252', //'latin1',
  129.         'norwegian-ny'  => 'CP1252', //'latin1',
  130.         'norwegian'     => 'CP1252', //'latin1',
  131.         'portuguese'    => 'CP1252', //'latin1',
  132.         'danish'        => 'CP1252', //'latin1',
  133.         'dutch'         => 'CP1252', //'latin1',
  134.         'english'       => 'CP1252', //'latin1',
  135.         'french'        => 'CP1252', //'latin1',
  136.         'german'        => 'CP1252', //'latin1',
  137.     );
  138.  
  139.     if ($server_language = PMA_DBI_fetch_value('SHOW VARIABLES LIKE \'language\';', 0, 1)) {
  140.         $found = array();
  141.         if (preg_match('&(?:\\\|\\/)([^\\\\\/]*)(?:\\\|\\/)$&i', $server_language, $found)) {
  142.             $server_language = $found[1];
  143.         }
  144.     }
  145.  
  146.     if (! empty($server_language) && isset($encodings[$server_language])) {
  147.         if (function_exists('iconv')) {
  148.             if ((@stristr(PHP_OS, 'AIX')) && (@strcasecmp(ICONV_IMPL, 'unknown') == 0) && (@strcasecmp(ICONV_VERSION, 'unknown') == 0)) {
  149.                 require_once './libraries/iconv_wrapper.lib.php';
  150.                 $message = PMA_aix_iconv_wrapper($encodings[$server_language],
  151.                     $GLOBALS['charset'] . $GLOBALS['cfg']['IconvExtraParams'], $message);
  152.             } else {
  153.                 $message = iconv($encodings[$server_language],
  154.                     $GLOBALS['charset'] . $GLOBALS['cfg']['IconvExtraParams'], $message);
  155.             }
  156.         } elseif (function_exists('recode_string')) {
  157.             $message = recode_string($encodings[$server_language] . '..'  . $GLOBALS['charset'],
  158.                 $message);
  159.         } elseif (function_exists('libiconv')) {
  160.             $message = libiconv($encodings[$server_language], $GLOBALS['charset'], $message);
  161.         } elseif (function_exists('mb_convert_encoding')) {
  162.             // do not try unsupported charsets
  163.             if (! in_array($server_language, array('ukrainian', 'greek', 'serbian'))) {
  164.                 $message = mb_convert_encoding($message, $GLOBALS['charset'],
  165.                     $encodings[$server_language]);
  166.             }
  167.         }
  168.     } else {
  169.         /**
  170.          * @todo lang not found, try all, what TODO ?
  171.          */
  172.     }
  173.  
  174.     return $message;
  175. }
  176.  
  177. /**
  178.  * returns array with table names for given db
  179.  *
  180.  * @param   string  $database   name of database
  181.  * @param   mixed   $link       mysql link resource|object
  182.  * @return  array   tables names
  183.  */
  184. function PMA_DBI_get_tables($database, $link = null)
  185. {
  186.     return PMA_DBI_fetch_result('SHOW TABLES FROM ' . PMA_backquote($database) . ';',
  187.         null, 0, $link, PMA_DBI_QUERY_STORE);
  188. }
  189.  
  190. /**
  191.  * returns array of all tables in given db or dbs
  192.  * this function expects unquoted names:
  193.  * RIGHT: my_database
  194.  * WRONG: `my_database`
  195.  * WRONG: my\_database
  196.  * if $tbl_is_group is true, $table is used as filter for table names
  197.  * if $tbl_is_group is 'comment, $table is used as filter for table comments
  198.  *
  199.  * <code>
  200.  * PMA_DBI_get_tables_full('my_database');
  201.  * PMA_DBI_get_tables_full('my_database', 'my_table'));
  202.  * PMA_DBI_get_tables_full('my_database', 'my_tables_', true));
  203.  * PMA_DBI_get_tables_full('my_database', 'my_tables_', 'comment'));
  204.  * </code>
  205.  *
  206.  * @uses    PMA_MYSQL_INT_VERSION
  207.  * @uses    PMA_DBI_fetch_result()
  208.  * @uses    PMA_escape_mysql_wildcards()
  209.  * @uses    PMA_backquote()
  210.  * @uses    is_array()
  211.  * @uses    addslashes()
  212.  * @uses    strpos()
  213.  * @uses    strtoupper()
  214.  * @param   string          $databases      database
  215.  * @param   string          $table          table
  216.  * @param   boolean|string  $tbl_is_group   $table is a table group
  217.  * @param   resource        $link           mysql link
  218.  * @param   integer         $limit_offset   zero-based offset for the count 
  219.  * @param   boolean|integer $limit_count    number of tables to return 
  220.  * @return  array           list of tables in given db(s)
  221.  */
  222. function PMA_DBI_get_tables_full($database, $table = false,
  223.     $tbl_is_group = false, $link = null, $limit_offset = 0, $limit_count = false)
  224. {
  225.     if (true === $limit_count) {
  226.         $limit_count = $GLOBALS['cfg']['MaxTableList'];
  227.     }
  228.     // prepare and check parameters
  229.     if (! is_array($database)) {
  230.         $databases = array($database);
  231.     } else {
  232.         $databases = $database;
  233.     }
  234.  
  235.     $tables = array();
  236.  
  237.     if (PMA_MYSQL_INT_VERSION >= 50002) {
  238.         // get table information from information_schema
  239.         if ($table) {
  240.             if (true === $tbl_is_group) {
  241.                 $sql_where_table = 'AND `TABLE_NAME` LIKE \''
  242.                     . PMA_escape_mysql_wildcards(addslashes($table)) . '%\'';
  243.             } elseif ('comment' === $tbl_is_group) {
  244.                 $sql_where_table = 'AND `TABLE_COMMENT` LIKE \''
  245.                     . PMA_escape_mysql_wildcards(addslashes($table)) . '%\'';
  246.             } else {
  247.                 $sql_where_table = 'AND `TABLE_NAME` = \'' . addslashes($table) . '\'';
  248.             }
  249.         } else {
  250.             $sql_where_table = '';
  251.         }
  252.  
  253.         // for PMA bc:
  254.         // `SCHEMA_FIELD_NAME` AS `SHOW_TABLE_STATUS_FIELD_NAME`
  255.         //
  256.         // on non-Windows servers,
  257.         // added BINARY in the WHERE clause to force a case sensitive
  258.         // comparison (if we are looking for the db Aa we don't want
  259.         // to find the db aa)
  260.         $this_databases = array_map('PMA_sqlAddslashes', $databases);
  261.  
  262.         $sql = '
  263.              SELECT *,
  264.                     `TABLE_SCHEMA`       AS `Db`,
  265.                     `TABLE_NAME`         AS `Name`,
  266.                     `ENGINE`             AS `Engine`,
  267.                     `ENGINE`             AS `Type`,
  268.                     `VERSION`            AS `Version`,
  269.                     `ROW_FORMAT`         AS `Row_format`,
  270.                     `TABLE_ROWS`         AS `Rows`,
  271.                     `AVG_ROW_LENGTH`     AS `Avg_row_length`,
  272.                     `DATA_LENGTH`        AS `Data_length`,
  273.                     `MAX_DATA_LENGTH`    AS `Max_data_length`,
  274.                     `INDEX_LENGTH`       AS `Index_length`,
  275.                     `DATA_FREE`          AS `Data_free`,
  276.                     `AUTO_INCREMENT`     AS `Auto_increment`,
  277.                     `CREATE_TIME`        AS `Create_time`,
  278.                     `UPDATE_TIME`        AS `Update_time`,
  279.                     `CHECK_TIME`         AS `Check_time`,
  280.                     `TABLE_COLLATION`    AS `Collation`,
  281.                     `CHECKSUM`           AS `Checksum`,
  282.                     `CREATE_OPTIONS`     AS `Create_options`,
  283.                     `TABLE_COMMENT`      AS `Comment`
  284.                FROM `information_schema`.`TABLES`
  285.               WHERE ' . (PMA_IS_WINDOWS ? '' : 'BINARY') . ' `TABLE_SCHEMA` IN (\'' . implode("', '", $this_databases) . '\')
  286.                 ' . $sql_where_table;
  287.  
  288.         if ($limit_count) {
  289.             $sql .= ' LIMIT ' . $limit_count . ' OFFSET ' . $limit_offset;
  290.         }
  291.         $tables = PMA_DBI_fetch_result($sql, array('TABLE_SCHEMA', 'TABLE_NAME'),
  292.             null, $link);
  293.         unset($sql_where_table, $sql);
  294.     }
  295.     // If permissions are wrong on even one database directory,
  296.     // information_schema does not return any table info for any database
  297.     // this is why we fall back to SHOW TABLE STATUS even for MySQL >= 50002
  298.     if (PMA_MYSQL_INT_VERSION < 50002 || empty($tables)) {
  299.         foreach ($databases as $each_database) {
  300.             if (true === $tbl_is_group) {
  301.                 $sql = 'SHOW TABLE STATUS FROM '
  302.                     . PMA_backquote($each_database)
  303.                     .' LIKE \'' . PMA_escape_mysql_wildcards(addslashes($table)) . '%\'';
  304.             } else {
  305.                 $sql = 'SHOW TABLE STATUS FROM '
  306.                     . PMA_backquote($each_database) . ';';
  307.             }
  308.             $each_tables = PMA_DBI_fetch_result($sql, 'Name', null, $link);
  309.             if ($limit_count) {
  310.                 $each_tables = array_slice($each_tables, $limit_offset, $limit_count);
  311.             }
  312.  
  313.             foreach ($each_tables as $table_name => $each_table) {
  314.                 if ('comment' === $tbl_is_group
  315.                   && 0 === strpos($each_table['Comment'], $table))
  316.                 {
  317.                     // remove table from list
  318.                     unset($each_tables[$table_name]);
  319.                     continue;
  320.                 }
  321.  
  322.                 if (! isset($each_tables[$table_name]['Type'])
  323.                   && isset($each_tables[$table_name]['Engine'])) {
  324.                     // pma BC, same parts of PMA still uses 'Type'
  325.                     $each_tables[$table_name]['Type']
  326.                         =& $each_tables[$table_name]['Engine'];
  327.                 } elseif (! isset($each_tables[$table_name]['Engine'])
  328.                   && isset($each_tables[$table_name]['Type'])) {
  329.                     // old MySQL reports Type, newer MySQL reports Engine
  330.                     $each_tables[$table_name]['Engine']
  331.                         =& $each_tables[$table_name]['Type'];
  332.                 }
  333.  
  334.                 // MySQL forward compatibility
  335.                 // so pma could use this array as if every server is of version >5.0
  336.                 $each_tables[$table_name]['TABLE_SCHEMA']      = $each_database;
  337.                 $each_tables[$table_name]['TABLE_NAME']        =& $each_tables[$table_name]['Name'];
  338.                 $each_tables[$table_name]['ENGINE']            =& $each_tables[$table_name]['Engine'];
  339.                 $each_tables[$table_name]['VERSION']           =& $each_tables[$table_name]['Version'];
  340.                 $each_tables[$table_name]['ROW_FORMAT']        =& $each_tables[$table_name]['Row_format'];
  341.                 $each_tables[$table_name]['TABLE_ROWS']        =& $each_tables[$table_name]['Rows'];
  342.                 $each_tables[$table_name]['AVG_ROW_LENGTH']    =& $each_tables[$table_name]['Avg_row_length'];
  343.                 $each_tables[$table_name]['DATA_LENGTH']       =& $each_tables[$table_name]['Data_length'];
  344.                 $each_tables[$table_name]['MAX_DATA_LENGTH']   =& $each_tables[$table_name]['Max_data_length'];
  345.                 $each_tables[$table_name]['INDEX_LENGTH']      =& $each_tables[$table_name]['Index_length'];
  346.                 $each_tables[$table_name]['DATA_FREE']         =& $each_tables[$table_name]['Data_free'];
  347.                 $each_tables[$table_name]['AUTO_INCREMENT']    =& $each_tables[$table_name]['Auto_increment'];
  348.                 $each_tables[$table_name]['CREATE_TIME']       =& $each_tables[$table_name]['Create_time'];
  349.                 $each_tables[$table_name]['UPDATE_TIME']       =& $each_tables[$table_name]['Update_time'];
  350.                 $each_tables[$table_name]['CHECK_TIME']        =& $each_tables[$table_name]['Check_time'];
  351.                 $each_tables[$table_name]['TABLE_COLLATION']   =& $each_tables[$table_name]['Collation'];
  352.                 $each_tables[$table_name]['CHECKSUM']          =& $each_tables[$table_name]['Checksum'];
  353.                 $each_tables[$table_name]['CREATE_OPTIONS']    =& $each_tables[$table_name]['Create_options'];
  354.                 $each_tables[$table_name]['TABLE_COMMENT']     =& $each_tables[$table_name]['Comment'];
  355.  
  356.                 if (strtoupper($each_tables[$table_name]['Comment']) === 'VIEW') {
  357.                     $each_tables[$table_name]['TABLE_TYPE'] = 'VIEW';
  358.                 } else {
  359.                     /**
  360.                      * @todo difference between 'TEMPORARY' and 'BASE TABLE' but how to detect?
  361.                      */
  362.                     $each_tables[$table_name]['TABLE_TYPE'] = 'BASE TABLE';
  363.                 }
  364.             }
  365.  
  366.             $tables[$each_database] = $each_tables;
  367.         }
  368.     }
  369.  
  370.     if ($GLOBALS['cfg']['NaturalOrder']) {
  371.         foreach ($tables as $key => $val) {
  372.             uksort($tables[$key], 'strnatcasecmp');
  373.         }
  374.     }
  375.  
  376.     if (! is_array($database)) {
  377.         if (isset($tables[$database])) {
  378.             return $tables[$database];
  379.         } elseif (isset($tables[strtolower($database)])) {
  380.             // on windows with lower_case_table_names = 1
  381.             // MySQL returns
  382.             // with SHOW DATABASES or information_schema.SCHEMATA: `Test`
  383.             // but information_schema.TABLES gives `test`
  384.             // bug #1436171
  385.             // http://sf.net/support/tracker.php?aid=1436171
  386.             return $tables[strtolower($database)];
  387.         } else {
  388.             return $tables;
  389.         }
  390.     } else {
  391.         return $tables;
  392.     }
  393. }
  394.  
  395. /**
  396.  * returns array with databases containing extended infos about them
  397.  *
  398.  * @todo    move into PMA_List_Database?
  399.  * @param   string      $databases      database
  400.  * @param   boolean     $force_stats    retrieve stats also for MySQL < 5
  401.  * @param   resource    $link           mysql link
  402.  * @param   string      $sort_by        collumn to order by
  403.  * @param   string      $sort_order     ASC or DESC
  404.  * @param   integer     $limit_offset   starting offset for LIMIT
  405.  * @param   bool|int    $limit_count    row count for LIMIT or true for $GLOBALS['cfg']['MaxDbList']
  406.  * @return  array       $databases
  407.  */
  408. function PMA_DBI_get_databases_full($database = null, $force_stats = false,
  409.     $link = null, $sort_by = 'SCHEMA_NAME', $sort_order = 'ASC',
  410.     $limit_offset = 0, $limit_count = false)
  411. {
  412.     $sort_order = strtoupper($sort_order);
  413.  
  414.     if (true === $limit_count) {
  415.         $limit_count = $GLOBALS['cfg']['MaxDbList'];
  416.     }
  417.  
  418.     // initialize to avoid errors when there are no databases
  419.     $databases = array();
  420.  
  421.     $apply_limit_and_order_manual = true;
  422.  
  423.     if (PMA_MYSQL_INT_VERSION >= 50002) {
  424.         /**
  425.          * if $GLOBALS['cfg']['NaturalOrder'] is enabled, we cannot use LIMIT
  426.          * cause MySQL does not support natural ordering, we have to do it afterward
  427.          */
  428.         if ($GLOBALS['cfg']['NaturalOrder']) {
  429.             $limit = '';
  430.         } else {
  431.             if ($limit_count) {
  432.                 $limit = ' LIMIT ' . $limit_count . ' OFFSET ' . $limit_offset;
  433.             }
  434.  
  435.             $apply_limit_and_order_manual = false;
  436.         }
  437.  
  438.         // get table information from information_schema
  439.         if ($database) {
  440.             $sql_where_schema = 'WHERE `SCHEMA_NAME` LIKE \''
  441.                 . addslashes($database) . '\'';
  442.         } else {
  443.             $sql_where_schema = '';
  444.         }
  445.  
  446.         // for PMA bc:
  447.         // `SCHEMA_FIELD_NAME` AS `SHOW_TABLE_STATUS_FIELD_NAME`
  448.         $sql = '
  449.              SELECT `information_schema`.`SCHEMATA`.*';
  450.         if ($force_stats) {
  451.             $sql .= ',
  452.                     COUNT(`information_schema`.`TABLES`.`TABLE_SCHEMA`)
  453.                         AS `SCHEMA_TABLES`,
  454.                     SUM(`information_schema`.`TABLES`.`TABLE_ROWS`)
  455.                         AS `SCHEMA_TABLE_ROWS`,
  456.                     SUM(`information_schema`.`TABLES`.`DATA_LENGTH`)
  457.                         AS `SCHEMA_DATA_LENGTH`,
  458.                     SUM(`information_schema`.`TABLES`.`MAX_DATA_LENGTH`)
  459.                         AS `SCHEMA_MAX_DATA_LENGTH`,
  460.                     SUM(`information_schema`.`TABLES`.`INDEX_LENGTH`)
  461.                         AS `SCHEMA_INDEX_LENGTH`,
  462.                     SUM(`information_schema`.`TABLES`.`DATA_LENGTH`
  463.                       + `information_schema`.`TABLES`.`INDEX_LENGTH`)
  464.                         AS `SCHEMA_LENGTH`,
  465.                     SUM(`information_schema`.`TABLES`.`DATA_FREE`)
  466.                         AS `SCHEMA_DATA_FREE`';
  467.         }
  468.         $sql .= '
  469.                FROM `information_schema`.`SCHEMATA`';
  470.         if ($force_stats) {
  471.             $sql .= '
  472.           LEFT JOIN `information_schema`.`TABLES`
  473.                  ON BINARY `information_schema`.`TABLES`.`TABLE_SCHEMA`
  474.                   = BINARY `information_schema`.`SCHEMATA`.`SCHEMA_NAME`';
  475.         }
  476.         $sql .= '
  477.               ' . $sql_where_schema . '
  478.            GROUP BY BINARY `information_schema`.`SCHEMATA`.`SCHEMA_NAME`
  479.            ORDER BY BINARY ' . PMA_backquote($sort_by) . ' ' . $sort_order
  480.            . $limit;
  481.         $databases = PMA_DBI_fetch_result($sql, 'SCHEMA_NAME', null, $link);
  482.  
  483.         $mysql_error = PMA_DBI_getError($link);
  484.         if (! count($databases) && $GLOBALS['errno']) {
  485.             PMA_mysqlDie($mysql_error, $sql);
  486.         }
  487.  
  488.         // display only databases also in official database list
  489.         // f.e. to apply hide_db and only_db
  490.         $drops = array_diff(array_keys($databases), $GLOBALS['PMA_List_Database']->items);
  491.         if (count($drops)) {
  492.             foreach ($drops as $drop) {
  493.                 unset($databases[$drop]);
  494.             }
  495.             unset($drop);
  496.         }
  497.         unset($sql_where_schema, $sql, $drops);
  498.     } else {
  499.         foreach ($GLOBALS['PMA_List_Database']->items as $database_name) {
  500.             // MySQL forward compatibility
  501.             // so pma could use this array as if every server is of version >5.0
  502.             $databases[$database_name]['SCHEMA_NAME']      = $database_name;
  503.  
  504.             if ($force_stats) {
  505.                 require_once 'mysql_charsets.lib.php';
  506.  
  507.                 $databases[$database_name]['DEFAULT_COLLATION_NAME']
  508.                     = PMA_getDbCollation($database_name);
  509.  
  510.                 // get additonal info about tables
  511.                 $databases[$database_name]['SCHEMA_TABLES']          = 0;
  512.                 $databases[$database_name]['SCHEMA_TABLE_ROWS']      = 0;
  513.                 $databases[$database_name]['SCHEMA_DATA_LENGTH']     = 0;
  514.                 $databases[$database_name]['SCHEMA_MAX_DATA_LENGTH'] = 0;
  515.                 $databases[$database_name]['SCHEMA_INDEX_LENGTH']    = 0;
  516.                 $databases[$database_name]['SCHEMA_LENGTH']          = 0;
  517.                 $databases[$database_name]['SCHEMA_DATA_FREE']       = 0;
  518.  
  519.                 $res = PMA_DBI_query('SHOW TABLE STATUS FROM ' . PMA_backquote($database_name) . ';');
  520.                 while ($row = PMA_DBI_fetch_assoc($res)) {
  521.                     $databases[$database_name]['SCHEMA_TABLES']++;
  522.                     $databases[$database_name]['SCHEMA_TABLE_ROWS']
  523.                         += $row['Rows'];
  524.                     $databases[$database_name]['SCHEMA_DATA_LENGTH']
  525.                         += $row['Data_length'];
  526.                     $databases[$database_name]['SCHEMA_MAX_DATA_LENGTH']
  527.                         += $row['Max_data_length'];
  528.                     $databases[$database_name]['SCHEMA_INDEX_LENGTH']
  529.                         += $row['Index_length'];
  530.                     $databases[$database_name]['SCHEMA_DATA_FREE']
  531.                         += $row['Data_free'];
  532.                     $databases[$database_name]['SCHEMA_LENGTH']
  533.                         += $row['Data_length'] + $row['Index_length'];
  534.                 }
  535.                 PMA_DBI_free_result($res);
  536.                 unset($res);
  537.             }
  538.         }
  539.     }
  540.  
  541.     /**
  542.      * apply limit and order manually now
  543.      * (caused by older MySQL < 5 or $GLOBALS['cfg']['NaturalOrder'])
  544.      */
  545.     if ($apply_limit_and_order_manual) {
  546.  
  547.         /**
  548.          * first apply ordering
  549.          */
  550.         if ($GLOBALS['cfg']['NaturalOrder']) {
  551.             $sorter = 'strnatcasecmp';
  552.         } else {
  553.             $sorter = 'strcasecmp';
  554.         }
  555.  
  556.         // produces f.e.:
  557.         // return -1 * strnatcasecmp($a["SCHEMA_TABLES"], $b["SCHEMA_TABLES"])
  558.         $sort_function = '
  559.             return ' . ($sort_order == 'ASC' ? 1 : -1) . ' * ' . $sorter . '($a["' . $sort_by . '"], $b["' . $sort_by . '"]);
  560.         ';
  561.  
  562.         usort($databases, create_function('$a, $b', $sort_function));
  563.  
  564.         /**
  565.          * now apply limit
  566.          */
  567.         if ($limit_count) {
  568.             $databases = array_slice($databases, $limit_offset, $limit_count);
  569.         }
  570.     }
  571.  
  572.     return $databases;
  573. }
  574.  
  575. /**
  576.  * returns detailed array with all columns for given table in database,
  577.  * or all tables/databases
  578.  *
  579.  * @param   string  $database   name of database
  580.  * @param   string  $table      name of table to retrieve columns from
  581.  * @param   string  $column     name of specific column
  582.  * @param   mixed   $link       mysql link resource
  583.  */
  584. function PMA_DBI_get_columns_full($database = null, $table = null,
  585.     $column = null, $link = null)
  586. {
  587.     $columns = array();
  588.  
  589.     if (PMA_MYSQL_INT_VERSION >= 50002) {
  590.         $sql_wheres = array();
  591.         $array_keys = array();
  592.  
  593.         // get columns information from information_schema
  594.         if (null !== $database) {
  595.             $sql_wheres[] = '`TABLE_SCHEMA` = \'' . addslashes($database) . '\' ';
  596.         } else {
  597.             $array_keys[] = 'TABLE_SCHEMA';
  598.         }
  599.         if (null !== $table) {
  600.             $sql_wheres[] = '`TABLE_NAME` = \'' . addslashes($table) . '\' ';
  601.         } else {
  602.             $array_keys[] = 'TABLE_NAME';
  603.         }
  604.         if (null !== $column) {
  605.             $sql_wheres[] = '`COLUMN_NAME` = \'' . addslashes($column) . '\' ';
  606.         } else {
  607.             $array_keys[] = 'COLUMN_NAME';
  608.         }
  609.  
  610.         // for PMA bc:
  611.         // `[SCHEMA_FIELD_NAME]` AS `[SHOW_FULL_COLUMNS_FIELD_NAME]`
  612.         $sql = '
  613.              SELECT *,
  614.                     `COLUMN_NAME`       AS `Field`,
  615.                     `COLUMN_TYPE`       AS `Type`,
  616.                     `COLLATION_NAME`    AS `Collation`,
  617.                     `IS_NULLABLE`       AS `Null`,
  618.                     `COLUMN_KEY`        AS `Key`,
  619.                     `COLUMN_DEFAULT`    AS `Default`,
  620.                     `EXTRA`             AS `Extra`,
  621.                     `PRIVILEGES`        AS `Privileges`,
  622.                     `COLUMN_COMMENT`    AS `Comment`
  623.                FROM `information_schema`.`COLUMNS`';
  624.         if (count($sql_wheres)) {
  625.             $sql .= "\n" . ' WHERE ' . implode(' AND ', $sql_wheres);
  626.         }
  627.  
  628.         $columns = PMA_DBI_fetch_result($sql, $array_keys, null, $link);
  629.         unset($sql_wheres, $sql);
  630.     } else {
  631.         if (null === $database) {
  632.             foreach ($GLOBALS['PMA_List_Database']->items as $database) {
  633.                 $columns[$database] = PMA_DBI_get_columns_full($database, null,
  634.                     null, $link);
  635.             }
  636.             return $columns;
  637.         } elseif (null === $table) {
  638.             $tables = PMA_DBI_get_tables($database);
  639.             foreach ($tables as $table) {
  640.                 $columns[$table] = PMA_DBI_get_columns_full(
  641.                     $database, $table, null, $link);
  642.             }
  643.             return $columns;
  644.         }
  645.  
  646.         $sql = 'SHOW FULL COLUMNS FROM '
  647.             . PMA_backquote($database) . '.' . PMA_backquote($table);
  648.         if (null !== $column) {
  649.             $sql .= " LIKE '" . $column . "'";
  650.         }
  651.  
  652.         $columns = PMA_DBI_fetch_result($sql, 'Field', null, $link);
  653.  
  654.         $ordinal_position = 1;
  655.         foreach ($columns as $column_name => $each_column) {
  656.  
  657.             // MySQL forward compatibility
  658.             // so pma could use this array as if every server is of version >5.0
  659.             $columns[$column_name]['COLUMN_NAME']                 =& $columns[$column_name]['Field'];
  660.             $columns[$column_name]['COLUMN_TYPE']                 =& $columns[$column_name]['Type'];
  661.             $columns[$column_name]['COLLATION_NAME']              =& $columns[$column_name]['Collation'];
  662.             $columns[$column_name]['IS_NULLABLE']                 =& $columns[$column_name]['Null'];
  663.             $columns[$column_name]['COLUMN_KEY']                  =& $columns[$column_name]['Key'];
  664.             $columns[$column_name]['COLUMN_DEFAULT']              =& $columns[$column_name]['Default'];
  665.             $columns[$column_name]['EXTRA']                       =& $columns[$column_name]['Extra'];
  666.             $columns[$column_name]['PRIVILEGES']                  =& $columns[$column_name]['Privileges'];
  667.             $columns[$column_name]['COLUMN_COMMENT']              =& $columns[$column_name]['Comment'];
  668.  
  669.             $columns[$column_name]['TABLE_CATALOG']               = null;
  670.             $columns[$column_name]['TABLE_SCHEMA']                = $database;
  671.             $columns[$column_name]['TABLE_NAME']                  = $table;
  672.             $columns[$column_name]['ORDINAL_POSITION']            = $ordinal_position;
  673.             $columns[$column_name]['DATA_TYPE']                   =
  674.                 substr($columns[$column_name]['COLUMN_TYPE'], 0,
  675.                     strpos($columns[$column_name]['COLUMN_TYPE'], '('));
  676.             /**
  677.              * @todo guess CHARACTER_MAXIMUM_LENGTH from COLUMN_TYPE
  678.              */
  679.             $columns[$column_name]['CHARACTER_MAXIMUM_LENGTH']    = null;
  680.             /**
  681.              * @todo guess CHARACTER_OCTET_LENGTH from CHARACTER_MAXIMUM_LENGTH
  682.              */
  683.             $columns[$column_name]['CHARACTER_OCTET_LENGTH']      = null;
  684.             $columns[$column_name]['NUMERIC_PRECISION']           = null;
  685.             $columns[$column_name]['NUMERIC_SCALE']               = null;
  686.             $columns[$column_name]['CHARACTER_SET_NAME']          =
  687.                 substr($columns[$column_name]['COLLATION_NAME'], 0,
  688.                     strpos($columns[$column_name]['COLLATION_NAME'], '_'));
  689.  
  690.             $ordinal_position++;
  691.         }
  692.  
  693.         if (null !== $column) {
  694.             reset($columns);
  695.             $columns = current($columns);
  696.         }
  697.     }
  698.  
  699.     return $columns;
  700. }
  701.  
  702. /**
  703.  * @todo should only return columns names, for more info use PMA_DBI_get_columns_full()
  704.  *
  705.  * @deprecated by PMA_DBI_get_columns() or PMA_DBI_get_columns_full()
  706.  * @param   string  $database   name of database
  707.  * @param   string  $table      name of table to retrieve columns from
  708.  * @param   mixed   $link       mysql link resource
  709.  * @return  array   column info
  710.  */
  711. function PMA_DBI_get_fields($database, $table, $link = null)
  712. {
  713.     // here we use a try_query because when coming from
  714.     // tbl_create + tbl_properties.inc.php, the table does not exist
  715.     $fields = PMA_DBI_fetch_result(
  716.         'SHOW FULL COLUMNS
  717.         FROM ' . PMA_backquote($database) . '.' . PMA_backquote($table),
  718.         null, null, $link);
  719.     if (! is_array($fields) || count($fields) < 1) {
  720.         return false;
  721.     }
  722.     return $fields;
  723. }
  724.  
  725. /**
  726.  * array PMA_DBI_get_columns(string $database, string $table, bool $full = false, mysql db link $link = null)
  727.  *
  728.  * @param   string  $database   name of database
  729.  * @param   string  $table      name of table to retrieve columns from
  730.  * @param   boolean $full       wether to return full info or only column names
  731.  * @param   mixed   $link       mysql link resource
  732.  * @return  array   column names
  733.  */
  734. function PMA_DBI_get_columns($database, $table, $full = false, $link = null)
  735. {
  736.     $fields = PMA_DBI_fetch_result(
  737.         'SHOW ' . ($full ? 'FULL' : '') . ' COLUMNS
  738.         FROM ' . PMA_backquote($database) . '.' . PMA_backquote($table),
  739.         'Field', ($full ? null : 'Field'), $link);
  740.     if (! is_array($fields) || count($fields) < 1) {
  741.         return false;
  742.     }
  743.     return $fields;
  744. }
  745.  
  746. /**
  747.  * returns value of given mysql server variable
  748.  *
  749.  * @param   string  $var    mysql server variable name
  750.  * @param   int     $type   PMA_DBI_GETVAR_SESSION|PMA_DBI_GETVAR_GLOBAL
  751.  * @param   mixed   $link   mysql link resource|object
  752.  * @return  mixed   value for mysql server variable
  753.  */
  754. function PMA_DBI_get_variable($var, $type = PMA_DBI_GETVAR_SESSION, $link = null)
  755. {
  756.     if ($link === null) {
  757.         if (isset($GLOBALS['userlink'])) {
  758.             $link = $GLOBALS['userlink'];
  759.         } else {
  760.             return false;
  761.         }
  762.     }
  763.     if (PMA_MYSQL_INT_VERSION < 40002) {
  764.         $type = 0;
  765.     }
  766.     switch ($type) {
  767.         case PMA_DBI_GETVAR_SESSION:
  768.             $modifier = ' SESSION';
  769.             break;
  770.         case PMA_DBI_GETVAR_GLOBAL:
  771.             $modifier = ' GLOBAL';
  772.             break;
  773.         default:
  774.             $modifier = '';
  775.     }
  776.     return PMA_DBI_fetch_value(
  777.         'SHOW' . $modifier . ' VARIABLES LIKE \'' . $var . '\';', 0, 1, $link);
  778. }
  779.  
  780. /**
  781.  * @uses    ./libraries/charset_conversion.lib.php
  782.  * @uses    PMA_DBI_QUERY_STORE
  783.  * @uses    PMA_REMOVED_NON_UTF_8
  784.  * @uses    PMA_MYSQL_INT_VERSION
  785.  * @uses    PMA_MYSQL_STR_VERSION
  786.  * @uses    PMA_DBI_GETVAR_SESSION
  787.  * @uses    PMA_DBI_fetch_value()
  788.  * @uses    PMA_DBI_query()
  789.  * @uses    PMA_DBI_get_variable()
  790.  * @uses    $GLOBALS['collation_connection']
  791.  * @uses    $GLOBALS['charset_connection']
  792.  * @uses    $GLOBALS['available_languages']
  793.  * @uses    $GLOBALS['mysql_charset_map']
  794.  * @uses    $GLOBALS['charset']
  795.  * @uses    $GLOBALS['lang']
  796.  * @uses    $GLOBALS['cfg']['Lang']
  797.  * @uses    $GLOBALS['cfg']['ColumnTypes']
  798.  * @uses    defined()
  799.  * @uses    explode()
  800.  * @uses    sprintf()
  801.  * @uses    intval()
  802.  * @uses    define()
  803.  * @uses    defined()
  804.  * @uses    substr()
  805.  * @uses    count()
  806.  * @param   mixed   $link   mysql link resource|object
  807.  * @param   boolean $is_controluser
  808.  */
  809. function PMA_DBI_postConnect($link, $is_controluser = false)
  810. {
  811.     if (!defined('PMA_MYSQL_INT_VERSION')) {
  812.         $mysql_version = PMA_DBI_fetch_value(
  813.             'SELECT VERSION()', 0, 0, $link, PMA_DBI_QUERY_STORE);
  814.         if ($mysql_version) {
  815.             $match = explode('.', $mysql_version);
  816.             define('PMA_MYSQL_INT_VERSION',
  817.                 (int) sprintf('%d%02d%02d', $match[0], $match[1],
  818.                         intval($match[2])));
  819.             define('PMA_MYSQL_STR_VERSION', $mysql_version);
  820.             unset($mysql_version, $match);
  821.         } else {
  822.             define('PMA_MYSQL_INT_VERSION', 32332);
  823.             define('PMA_MYSQL_STR_VERSION', '3.23.32');
  824.         }
  825.     }
  826.  
  827.     if (!defined('PMA_ENGINE_KEYWORD')) {
  828.         if (PMA_MYSQL_INT_VERSION >= 40102) {
  829.             define('PMA_ENGINE_KEYWORD','ENGINE');
  830.         } else {
  831.             define('PMA_ENGINE_KEYWORD','TYPE');
  832.         }
  833.     }
  834.  
  835.     if (PMA_MYSQL_INT_VERSION >= 40100) {
  836.  
  837.         // If $lang is defined and we are on MySQL >= 4.1.x,
  838.         // we auto-switch the lang to its UTF-8 version (if it exists and user
  839.         // didn't force language)
  840.         if (!empty($GLOBALS['lang'])
  841.           && (substr($GLOBALS['lang'], -5) != 'utf-8')
  842.           && !isset($GLOBALS['cfg']['Lang'])) {
  843.             $lang_utf_8_version =
  844.                 substr($GLOBALS['lang'], 0, strpos($GLOBALS['lang'], '-'))
  845.                 . '-utf-8';
  846.             if (!empty($GLOBALS['available_languages'][$lang_utf_8_version])) {
  847.                 $GLOBALS['lang'] = $lang_utf_8_version;
  848.                 $GLOBALS['charset'] = 'utf-8';
  849.                 define('PMA_LANG_RELOAD', 1);
  850.             }
  851.         }
  852.  
  853.         // and we remove the non-UTF-8 choices to avoid confusion
  854.         // (unless there is a forced language)
  855.         if (!defined('PMA_REMOVED_NON_UTF_8') && ! isset($GLOBALS['cfg']['Lang'])) {
  856.             foreach ($GLOBALS['available_languages'] as $each_lang => $dummy) {
  857.                 if (substr($each_lang, -5) != 'utf-8') {
  858.                     unset($GLOBALS['available_languages'][$each_lang]);
  859.                 }
  860.             }
  861.             define('PMA_REMOVED_NON_UTF_8', 1);
  862.         }
  863.  
  864.         $mysql_charset = $GLOBALS['mysql_charset_map'][$GLOBALS['charset']];
  865.         if ($is_controluser
  866.           || empty($GLOBALS['collation_connection'])
  867.           || (strpos($GLOBALS['collation_connection'], '_')
  868.                 ? substr($GLOBALS['collation_connection'], 0, strpos($GLOBALS['collation_connection'], '_'))
  869.                 : $GLOBALS['collation_connection']) == $mysql_charset) {
  870.  
  871.             PMA_DBI_query('SET NAMES ' . $mysql_charset . ';', $link,
  872.                 PMA_DBI_QUERY_STORE);
  873.         } else {
  874.             PMA_DBI_query('SET CHARACTER SET ' . $mysql_charset . ';', $link,
  875.                 PMA_DBI_QUERY_STORE);
  876.         }
  877.         if (!empty($GLOBALS['collation_connection'])) {
  878.             PMA_DBI_query('SET collation_connection = \'' . $GLOBALS['collation_connection'] . '\';',
  879.                 $link, PMA_DBI_QUERY_STORE);
  880.         }
  881.         if (!$is_controluser) {
  882.             $GLOBALS['collation_connection'] = PMA_DBI_get_variable('collation_connection',
  883.                 PMA_DBI_GETVAR_SESSION, $link);
  884.             $GLOBALS['charset_connection']   = PMA_DBI_get_variable('character_set_connection',
  885.                 PMA_DBI_GETVAR_SESSION, $link);
  886.         }
  887.  
  888.         // Add some field types to the list, this needs to be done once per session!
  889.         if (!in_array('BINARY', $GLOBALS['cfg']['ColumnTypes'])) {
  890.             $GLOBALS['cfg']['ColumnTypes'][] = 'BINARY';
  891.         }
  892.         if (!in_array('VARBINARY', $GLOBALS['cfg']['ColumnTypes'])) {
  893.             $GLOBALS['cfg']['ColumnTypes'][] = 'VARBINARY';
  894.         }
  895.     } else {
  896.         require_once './libraries/charset_conversion.lib.php';
  897.     }
  898. }
  899.  
  900. /**
  901.  * returns a single value from the given result or query,
  902.  * if the query or the result has more than one row or field
  903.  * the first field of the first row is returned
  904.  *
  905.  * <code>
  906.  * $sql = 'SELECT `name` FROM `user` WHERE `id` = 123';
  907.  * $user_name = PMA_DBI_fetch_value($sql);
  908.  * // produces
  909.  * // $user_name = 'John Doe'
  910.  * </code>
  911.  *
  912.  * @uses    is_string()
  913.  * @uses    is_int()
  914.  * @uses    PMA_DBI_try_query()
  915.  * @uses    PMA_DBI_num_rows()
  916.  * @uses    PMA_DBI_fetch_row()
  917.  * @uses    PMA_DBI_fetch_assoc()
  918.  * @uses    PMA_DBI_free_result()
  919.  * @param   string|mysql_result $result query or mysql result
  920.  * @param   integer             $row_number row to fetch the value from,
  921.  *                                      starting at 0, with 0 beeing default
  922.  * @param   integer|string      $field  field to fetch the value from,
  923.  *                                      starting at 0, with 0 beeing default
  924.  * @param   resource            $link   mysql link
  925.  * @param   mixed               $options
  926.  * @return  mixed               value of first field in first row from result
  927.  *                              or false if not found
  928.  */
  929. function PMA_DBI_fetch_value($result, $row_number = 0, $field = 0, $link = null, $options = 0) {
  930.     $value = false;
  931.  
  932.     if (is_string($result)) {
  933.         $result = PMA_DBI_try_query($result, $link, $options | PMA_DBI_QUERY_STORE);
  934.     }
  935.  
  936.     // return false if result is empty or false
  937.     // or requested row is larger than rows in result
  938.     if (PMA_DBI_num_rows($result) < ($row_number + 1)) {
  939.         return $value;
  940.     }
  941.  
  942.     // if $field is an integer use non associative mysql fetch function
  943.     if (is_int($field)) {
  944.         $fetch_function = 'PMA_DBI_fetch_row';
  945.     } else {
  946.         $fetch_function = 'PMA_DBI_fetch_assoc';
  947.     }
  948.  
  949.     // get requested row
  950.     for ($i = 0; $i <= $row_number; $i++) {
  951.         $row = $fetch_function($result);
  952.     }
  953.     PMA_DBI_free_result($result);
  954.  
  955.     // return requested field
  956.     if (isset($row[$field])) {
  957.         $value = $row[$field];
  958.     }
  959.     unset($row);
  960.  
  961.     return $value;
  962. }
  963.  
  964. /**
  965.  * returns only the first row from the result
  966.  *
  967.  * <code>
  968.  * $sql = 'SELECT * FROM `user` WHERE `id` = 123';
  969.  * $user = PMA_DBI_fetch_single_row($sql);
  970.  * // produces
  971.  * // $user = array('id' => 123, 'name' => 'John Doe')
  972.  * </code>
  973.  *
  974.  * @uses    is_string()
  975.  * @uses    PMA_DBI_try_query()
  976.  * @uses    PMA_DBI_num_rows()
  977.  * @uses    PMA_DBI_fetch_row()
  978.  * @uses    PMA_DBI_fetch_assoc()
  979.  * @uses    PMA_DBI_fetch_array()
  980.  * @uses    PMA_DBI_free_result()
  981.  * @param   string|mysql_result $result query or mysql result
  982.  * @param   string              $type   NUM|ASSOC|BOTH
  983.  *                                      returned array should either numeric
  984.  *                                      associativ or booth
  985.  * @param   resource            $link   mysql link
  986.  * @param   mixed               $options
  987.  * @return  array|boolean       first row from result
  988.  *                              or false if result is empty
  989.  */
  990. function PMA_DBI_fetch_single_row($result, $type = 'ASSOC', $link = null, $options = 0) {
  991.     if (is_string($result)) {
  992.         $result = PMA_DBI_try_query($result, $link, $options | PMA_DBI_QUERY_STORE);
  993.     }
  994.  
  995.     // return null if result is empty or false
  996.     if (! PMA_DBI_num_rows($result)) {
  997.         return false;
  998.     }
  999.  
  1000.     switch ($type) {
  1001.         case 'NUM' :
  1002.             $fetch_function = 'PMA_DBI_fetch_row';
  1003.             break;
  1004.         case 'ASSOC' :
  1005.             $fetch_function = 'PMA_DBI_fetch_assoc';
  1006.             break;
  1007.         case 'BOTH' :
  1008.         default :
  1009.             $fetch_function = 'PMA_DBI_fetch_array';
  1010.             break;
  1011.     }
  1012.  
  1013.     $row = $fetch_function($result);
  1014.     PMA_DBI_free_result($result);
  1015.     return $row;
  1016. }
  1017.  
  1018. /**
  1019.  * returns all rows in the resultset in one array
  1020.  *
  1021.  * <code>
  1022.  * $sql = 'SELECT * FROM `user`';
  1023.  * $users = PMA_DBI_fetch_result($sql);
  1024.  * // produces
  1025.  * // $users[] = array('id' => 123, 'name' => 'John Doe')
  1026.  *
  1027.  * $sql = 'SELECT `id`, `name` FROM `user`';
  1028.  * $users = PMA_DBI_fetch_result($sql, 'id');
  1029.  * // produces
  1030.  * // $users['123'] = array('id' => 123, 'name' => 'John Doe')
  1031.  *
  1032.  * $sql = 'SELECT `id`, `name` FROM `user`';
  1033.  * $users = PMA_DBI_fetch_result($sql, 0);
  1034.  * // produces
  1035.  * // $users['123'] = array(0 => 123, 1 => 'John Doe')
  1036.  *
  1037.  * $sql = 'SELECT `id`, `name` FROM `user`';
  1038.  * $users = PMA_DBI_fetch_result($sql, 'id', 'name');
  1039.  * // or
  1040.  * $users = PMA_DBI_fetch_result($sql, 0, 1);
  1041.  * // produces
  1042.  * // $users['123'] = 'John Doe'
  1043.  *
  1044.  * $sql = 'SELECT `name` FROM `user`';
  1045.  * $users = PMA_DBI_fetch_result($sql);
  1046.  * // produces
  1047.  * // $users[] = 'John Doe'
  1048.  * </code>
  1049.  *
  1050.  * @uses    is_string()
  1051.  * @uses    is_int()
  1052.  * @uses    PMA_DBI_try_query()
  1053.  * @uses    PMA_DBI_num_rows()
  1054.  * @uses    PMA_DBI_num_fields()
  1055.  * @uses    PMA_DBI_fetch_row()
  1056.  * @uses    PMA_DBI_fetch_assoc()
  1057.  * @uses    PMA_DBI_free_result()
  1058.  * @param   string|mysql_result $result query or mysql result
  1059.  * @param   string|integer      $key    field-name or offset
  1060.  *                                      used as key for array
  1061.  * @param   string|integer      $value  value-name or offset
  1062.  *                                      used as value for array
  1063.  * @param   resource            $link   mysql link
  1064.  * @param   mixed               $options
  1065.  * @return  array               resultrows or values indexed by $key
  1066.  */
  1067. function PMA_DBI_fetch_result($result, $key = null, $value = null,
  1068.     $link = null, $options = 0)
  1069. {
  1070.     $resultrows = array();
  1071.  
  1072.     if (is_string($result)) {
  1073.         $result = PMA_DBI_try_query($result, $link, $options);
  1074.     }
  1075.  
  1076.     // return empty array if result is empty or false
  1077.     if (! $result) {
  1078.         return $resultrows;
  1079.     }
  1080.  
  1081.     $fetch_function = 'PMA_DBI_fetch_assoc';
  1082.  
  1083.     // no nested array if only one field is in result
  1084.     if (null === $key && 1 === PMA_DBI_num_fields($result)) {
  1085.         $value = 0;
  1086.         $fetch_function = 'PMA_DBI_fetch_row';
  1087.     }
  1088.  
  1089.     // if $key is an integer use non associative mysql fetch function
  1090.     if (is_int($key)) {
  1091.         $fetch_function = 'PMA_DBI_fetch_row';
  1092.     }
  1093.  
  1094.     if (null === $key && null === $value) {
  1095.         while ($row = $fetch_function($result)) {
  1096.             $resultrows[] = $row;
  1097.         }
  1098.     } elseif (null === $key) {
  1099.         while ($row = $fetch_function($result)) {
  1100.             $resultrows[] = $row[$value];
  1101.         }
  1102.     } elseif (null === $value) {
  1103.         if (is_array($key)) {
  1104.             while ($row = $fetch_function($result)) {
  1105.                 $result_target =& $resultrows;
  1106.                 foreach ($key as $key_index) {
  1107.                     if (! isset($result_target[$row[$key_index]])) {
  1108.                         $result_target[$row[$key_index]] = array();
  1109.                     }
  1110.                     $result_target =& $result_target[$row[$key_index]];
  1111.                 }
  1112.                 $result_target = $row;
  1113.             }
  1114.         } else {
  1115.             while ($row = $fetch_function($result)) {
  1116.                 $resultrows[$row[$key]] = $row;
  1117.             }
  1118.         }
  1119.     } else {
  1120.         if (is_array($key)) {
  1121.             while ($row = $fetch_function($result)) {
  1122.                 $result_target =& $resultrows;
  1123.                 foreach ($key as $key_index) {
  1124.                     if (! isset($result_target[$row[$key_index]])) {
  1125.                         $result_target[$row[$key_index]] = array();
  1126.                     }
  1127.                     $result_target =& $result_target[$row[$key_index]];
  1128.                 }
  1129.                 $result_target = $row[$value];
  1130.             }
  1131.         } else {
  1132.             while ($row = $fetch_function($result)) {
  1133.                 $resultrows[$row[$key]] = $row[$value];
  1134.             }
  1135.         }
  1136.     }
  1137.  
  1138.     PMA_DBI_free_result($result);
  1139.     return $resultrows;
  1140. }
  1141.  
  1142. /**
  1143.  * return default table engine for given database
  1144.  *
  1145.  * @return  string  default table engine
  1146.  */
  1147. function PMA_DBI_get_default_engine()
  1148. {
  1149.     if (PMA_MYSQL_INT_VERSION > 50002) {
  1150.         return PMA_DBI_fetch_value('SHOW VARIABLES LIKE \'storage_engine\';', 0, 1);
  1151.     } else {
  1152.         return PMA_DBI_fetch_value('SHOW VARIABLES LIKE \'table_type\';', 0, 1);
  1153.     }
  1154. }
  1155.  
  1156. /**
  1157.  * Get supported SQL compatibility modes
  1158.  *
  1159.  * @return  array   supported SQL compatibility modes
  1160.  */
  1161. function PMA_DBI_getCompatibilities()
  1162. {
  1163.     if (PMA_MYSQL_INT_VERSION < 40100) {
  1164.         return array();
  1165.     }
  1166.     $compats = array('NONE');
  1167.     if (PMA_MYSQL_INT_VERSION >= 40101) {
  1168.         $compats[] = 'ANSI';
  1169.         $compats[] = 'DB2';
  1170.         $compats[] = 'MAXDB';
  1171.         $compats[] = 'MYSQL323';
  1172.         $compats[] = 'MYSQL40';
  1173.         $compats[] = 'MSSQL';
  1174.         $compats[] = 'ORACLE';
  1175.         // removed; in MySQL 5.0.33, this produces exports that
  1176.         // can't be read by POSTGRESQL (see our bug #1596328)
  1177.         //$compats[] = 'POSTGRESQL';
  1178.         if (PMA_MYSQL_INT_VERSION >= 50002) {
  1179.             $compats[] = 'TRADITIONAL';
  1180.         }
  1181.     }
  1182.     return $compats;
  1183. }
  1184.  
  1185. /**
  1186.  * returns warnings for last query
  1187.  *
  1188.  * @uses    $GLOBALS['userlink']
  1189.  * @uses    PMA_DBI_fetch_result()
  1190.  * @param   resource mysql link  $link   mysql link resource
  1191.  * @return  array   warnings
  1192.  */
  1193. function PMA_DBI_get_warnings($link = null)
  1194. {
  1195.     if (PMA_MYSQL_INT_VERSION < 40100) {
  1196.         return array();
  1197.     }
  1198.  
  1199.     if (empty($link)) {
  1200.         if (isset($GLOBALS['userlink'])) {
  1201.             $link = $GLOBALS['userlink'];
  1202.         } else {
  1203.             return array();
  1204.         }
  1205.     }
  1206.  
  1207.     return PMA_DBI_fetch_result('SHOW WARNINGS', null, null, $link);
  1208. }
  1209.  
  1210. /**
  1211.  * returns true (int > 0) if current user is superuser
  1212.  * otherwise 0
  1213.  *
  1214.  * @return integer  $is_superuser
  1215.  */
  1216. function PMA_isSuperuser() {
  1217.     return PMA_DBI_try_query('SELECT COUNT(*) FROM mysql.user',
  1218.         $GLOBALS['userlink'], PMA_DBI_QUERY_STORE);
  1219. }
  1220.  
  1221.  
  1222. /**
  1223.  * returns an array of PROCEDURE or FUNCTION names for a db
  1224.  *
  1225.  * @uses    PMA_DBI_free_result()
  1226.  * @param   string              $db     db name
  1227.  * @param   string              $which  PROCEDURE | FUNCTION
  1228.  * @param   resource            $link   mysql link
  1229.  *
  1230.  * @return  array   the procedure names or function names
  1231.  */
  1232. function PMA_DBI_get_procedures_or_functions($db, $which, $link = null) {
  1233.  
  1234.     $shows = PMA_DBI_fetch_result('SHOW ' . $which . ' STATUS;', null, null, $link);
  1235.     $result = array();
  1236.     foreach ($shows as $one_show) {
  1237.         if ($one_show['Db'] == $db && $one_show['Type'] == $which) {
  1238.             $result[] = $one_show['Name'];
  1239.         }
  1240.     }
  1241.     return($result);
  1242. }
  1243.  
  1244. /**
  1245.  * returns the definition of a specific PROCEDURE or FUNCTION
  1246.  *
  1247.  * @uses    PMA_DBI_fetch_value()
  1248.  * @param   string              $db     db name
  1249.  * @param   string              $which  PROCEDURE | FUNCTION
  1250.  * @param   string              $proc_or_function_name  the procedure name or function name
  1251.  * @param   resource            $link   mysql link
  1252.  *
  1253.  * @return  string              the procedure's or function's definition
  1254.  */
  1255. function PMA_DBI_get_procedure_or_function_def($db, $which, $proc_or_function_name, $link = null) {
  1256.  
  1257.     $returned_field = array('PROCEDURE' => 'Create Procedure', 'FUNCTION' => 'Create Function');
  1258.     $query = 'SHOW CREATE ' . $which . ' ' . PMA_backquote($db) . '.' . PMA_backquote($proc_or_function_name);
  1259.     return(PMA_DBI_fetch_value($query, 0, $returned_field[$which]));
  1260. }
  1261.  
  1262. /**
  1263.  * returns details about the TRIGGERs of a specific table
  1264.  *
  1265.  * @uses    PMA_DBI_fetch_result()
  1266.  * @param   string              $db     db name
  1267.  * @param   string              $table  table name
  1268.  *
  1269.  * @return  array               information about triggers (may be empty)
  1270.  */
  1271. function PMA_DBI_get_triggers($db, $table) {
  1272.  
  1273.     $result = array();
  1274.  
  1275.     // available in INFORMATION_SCHEMA since MySQL 5.0.10
  1276.     // Note: in http://dev.mysql.com/doc/refman/5.0/en/faqs-triggers.html
  1277.     // their example uses WHERE TRIGGER_SCHEMA='dbname' so let's use this
  1278.     // instead of WHERE EVENT_OBJECT_SCHEMA='dbname'
  1279.     if (PMA_MYSQL_INT_VERSION >= 50010) {
  1280.         $triggers = PMA_DBI_fetch_result("SELECT TRIGGER_SCHEMA, TRIGGER_NAME, EVENT_MANIPULATION, ACTION_TIMING, ACTION_STATEMENT, EVENT_OBJECT_SCHEMA, EVENT_OBJECT_TABLE FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA= '" . PMA_sqlAddslashes($db,true) . "' and EVENT_OBJECT_TABLE = '" . PMA_sqlAddslashes($table, true) . "';");
  1281.  
  1282.         if ($triggers) {
  1283.             $delimiter = '//';
  1284.             foreach ($triggers as $trigger) {
  1285.                 $one_result = array();
  1286.                 $one_result['name'] = $trigger['TRIGGER_NAME'];
  1287.                 $one_result['action_timing'] = $trigger['ACTION_TIMING'];
  1288.                 $one_result['event_manipulation'] = $trigger['EVENT_MANIPULATION'];
  1289.  
  1290.                 $one_result['full_trigger_name'] = PMA_backquote($trigger['TRIGGER_SCHEMA']) . '.' . PMA_backquote($trigger['TRIGGER_NAME']);
  1291.                 $one_result['drop'] = 'DROP TRIGGER IF EXISTS ' . $one_result['full_trigger_name'];
  1292.                 $one_result['create'] = 'CREATE TRIGGER ' . $one_result['full_trigger_name'] . ' ' . $trigger['ACTION_TIMING']. ' ' . $trigger['EVENT_MANIPULATION'] . ' ON ' . PMA_backquote($trigger['EVENT_OBJECT_SCHEMA']) . '.' . PMA_backquote($trigger['EVENT_OBJECT_TABLE']) . "\n" . ' FOR EACH ROW ' . $trigger['ACTION_STATEMENT'] . "\n" . $delimiter . "\n";
  1293.  
  1294.                 $result[] = $one_result;
  1295.             }
  1296.         }
  1297.     }
  1298.     return($result);
  1299. }
  1300. ?>
  1301.