WordPress.org

Make WordPress Core

Ticket #11799: 11799.2.patch

File 11799.2.patch, 44.5 KB (added by hakre, 8 years ago)

First one - rev 4; Fix: get_var / hakre; Fix: Comment / Denis; Fix: Query $type was not case insensitive. Fixed.

  • wp-includes/wp-db.php

     
    6464        /**
    6565         * Whether to suppress errors during the DB bootstrapping.
    6666         *
     67         *
     68         * @since 2.5
    6769         * @access private
    68          * @since {@internal Version Unknown}}
    6970         * @var bool
    7071         */
    7172        var $suppress_errors = false;
     
    7374        /**
    7475         * The last error during query.
    7576         *
    76          * @since {@internal Version Unknown}}
    77          * @var string
     77         * FIXME (hakre) access violations on multiple locations in core
     78         * @see get_last_error()
     79         *
     80         * @since  2.5
     81         * @access private
     82         * @var    string
    7883         */
    7984        var $last_error = '';
    8085
    8186        /**
    8287         * Amount of queries made
    8388         *
    84          * @since 1.2.0
     89         * @since  1.2.0
    8590         * @access private
    86          * @var int
     91         * @var    int
    8792         */
    8893        var $num_queries = 0;
    8994
    9095        /**
     96         * Amount of rows returned by last query operation
     97         *
     98         * @since  1.2
     99         * @access private
     100         * @var    int
     101         */
     102        var $num_rows = 0;
     103
     104        /**
     105         * Number of affected rows by last query operation
     106         *
     107         * @since  0.71
     108         * @access private
     109         * @var    integer
     110         */
     111        var $rows_affected = 0;
     112
     113
     114        /**
    91115         * Saved result of the last query made
    92116         *
    93117         * @since 1.2.0
     
    97121        var $last_query;
    98122
    99123        /**
     124         * Saved resultset of the last query made
     125         *
     126         * @todo (hakre) get version number
     127         *
     128         * @since  {@internal Version Unknown}
     129         * @access private
     130         * @var    array (null if unintialized)
     131         */
     132        var $last_result;
     133
     134
     135        /**
    100136         * Saved info on the table column
    101137         *
    102138         * @since 1.2.0
     
    135171         * @var bool
    136172         */
    137173        var $ready = false;
    138         var $blogid = 0;
    139         var $siteid = 0;
    140         var $blogs;
    141         var $signups;
    142         var $site;
    143         var $sitemeta;
    144         var $sitecategories;
    145         var $global_tables = array('blogs', 'signups', 'site', 'sitemeta', 'users', 'usermeta', 'sitecategories', 'registration_log', 'blog_versions');
    146174
    147175        /**
    148176         * WordPress Posts table
     
    264292        /**
    265293         * List of WordPress tables
    266294         *
     295         * @todo (hakre) get revision number
     296         *
    267297         * @since {@internal Version Unknown}}
    268298         * @access private
    269299         * @var array
    270300         */
    271         var $tables = array('posts', 'categories', 'post2cat', 'comments', 'links', 'link2cat', 'options',
     301        var $tables = array('users', 'usermeta', 'posts', 'categories', 'post2cat', 'comments', 'links', 'link2cat', 'options',
    272302                        'postmeta', 'terms', 'term_taxonomy', 'term_relationships', 'commentmeta');
    273303
    274304        /**
     
    280310         */
    281311        var $old_tables = array('categories', 'post2cat', 'link2cat');
    282312
    283 
    284313        /**
    285314         * Format specifiers for DB columns. Columns not listed here default to %s.  Initialized in wp-settings.php.
    286315         *
     
    345374         * @param string $dbhost MySQL database host
    346375         */
    347376        function wpdb($dbuser, $dbpassword, $dbname, $dbhost) {
    348                 if( defined( "WP_USE_MULTIPLE_DB" ) && CONSTANT( "WP_USE_MULTIPLE_DB" ) == true )
    349                         $this->db_connect();
    350377                return $this->__construct($dbuser, $dbpassword, $dbname, $dbhost);
    351378        }
    352379
     
    365392         * @param string $dbhost MySQL database host
    366393         */
    367394        function __construct($dbuser, $dbpassword, $dbname, $dbhost) {
    368                 register_shutdown_function(array(&$this, "__destruct"));
     395                register_shutdown_function( array( &$this, "__destruct" ) );
    369396
    370397                if ( WP_DEBUG )
    371398                        $this->show_errors();
    372399
    373                 if( is_multisite() ) {
    374                         $this->charset = 'utf8';
    375                         if( defined( 'DB_COLLATE' ) && constant( 'DB_COLLATE' ) != '' ) {
    376                                 $this->collate = constant( 'DB_COLLATE' );
    377                         } else {
    378                                 $this->collate = 'utf8_general_ci';
    379                         }
    380                 }
    381 
    382400                if ( defined('DB_CHARSET') )
    383401                        $this->charset = DB_CHARSET;
    384402
     
    387405
    388406                $this->dbuser = $dbuser;
    389407
    390                 $this->dbh = @mysql_connect($dbhost, $dbuser, $dbpassword, true);
    391                 if (!$this->dbh) {
    392                         $this->bail(sprintf(/*WP_I18N_DB_CONN_ERROR*/"
     408                $this->dbh = @mysql_connect( $dbhost, $dbuser, $dbpassword, true );
     409                if ( !$this->dbh ) {
     410                        $this->bail( sprintf( /*WP_I18N_DB_CONN_ERROR*/"
    393411<h1>Error establishing a database connection</h1>
    394412<p>This either means that the username and password information in your <code>wp-config.php</code> file is incorrect or we can't contact the database server at <code>%s</code>. This could mean your host's database server is down.</p>
    395413<ul>
     
    398416        <li>Are you sure that the database server is running?</li>
    399417</ul>
    400418<p>If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href='http://wordpress.org/support/'>WordPress Support Forums</a>.</p>
    401 "/*/WP_I18N_DB_CONN_ERROR*/, $dbhost), 'db_connect_fail');
     419"/*/WP_I18N_DB_CONN_ERROR*/, $dbhost ), 'db_connect_fail' );
    402420                        return;
    403421                }
    404422
    405423                $this->ready = true;
    406424
    407                 if ( $this->has_cap( 'collation' ) && !empty($this->charset) ) {
    408                         if ( function_exists('mysql_set_charset') ) {
    409                                 mysql_set_charset($this->charset, $this->dbh);
     425                if ( $this->has_cap( 'collation' ) && !empty( $this->charset ) ) {
     426                        if ( function_exists( 'mysql_set_charset' ) ) {
     427                                mysql_set_charset( $this->charset, $this->dbh );
    410428                                $this->real_escape = true;
    411429                        } else {
    412                                 $collation_query = "SET NAMES '{$this->charset}'";
    413                                 if ( !empty($this->collate) )
    414                                         $collation_query .= " COLLATE '{$this->collate}'";
    415                                 $this->query($collation_query);
     430                                $query = $this->prepare( 'SET NAMES %s', $this->charset );
     431                                if ( !empty( $this->collate ) )
     432                                        $query .= $this->prepare( ' COLLATE %s', $this->collate );
     433                                $this->query( $query );
     434                                // @todo (hakre) still addslashes; rest disabled for now (430)) there must be a possibility to switch real_escape on here as well!
    416435                        }
    417436                }
    418437
    419                 $this->select($dbname, $this->dbh);
     438                $this->select( $dbname, $this->dbh );
    420439        }
    421440
    422441        /**
    423442         * PHP5 style destructor and will run when database object is destroyed.
    424443         *
     444         * NOTE:
     445         *
     446         *   In difference to the PHP5 behavior of __destruct, this function will
     447         *   be called when the script shuts down. If the garbage collector will
     448         *   remove this object earlier in PHP5, this function will be called prior to
     449         *   script termination.
     450         *
     451         *   Please see {@link __construct() class constructor} and the
     452         *   {@link register_shutdown_function() register_shutdown_function()}. for
     453         *   more details.
     454         *
     455         * @link http://www.php.net/__destruct
     456         * @link http://www.php.net/register_shutdown_function
     457         *
    425458         * @since 2.0.8
    426459         *
    427          * @return bool Always true
     460         * @return void
    428461         */
    429462        function __destruct() {
    430                 return true;
    431463        }
    432464
    433465        /**
     
    441473         * @param string $prefix Alphanumeric name for the new prefix.
    442474         * @return string|WP_Error Old prefix or WP_Error on error
    443475         */
    444         function set_prefix($prefix) {
     476        function set_prefix( $prefix ) {
    445477
    446                 if ( preg_match('|[^a-z0-9_]|i', $prefix) )
     478                if ( preg_match( '|[^a-z0-9_]|i', $prefix ) )
    447479                        return new WP_Error('invalid_db_prefix', /*WP_I18N_DB_BAD_PREFIX*/'Invalid database prefix'/*/WP_I18N_DB_BAD_PREFIX*/);
    448480
    449                 if( is_multisite() ) {
    450                         $old_prefix = '';
    451                 } else {
    452                         $old_prefix = $prefix;
    453                 }
    454                 if( isset( $this->base_prefix ) )
    455                         $old_prefix = $this->base_prefix;
    456                 $this->base_prefix = $prefix;
    457                 foreach ( $this->global_tables as $table )
    458                         $this->$table = $prefix . $table;
     481                $old_prefix   = $this->prefix;
     482                $this->prefix = $prefix;
    459483
    460                 if ( defined('VHOST') && empty($this->blogid) )
    461                         return $old_prefix;
    462 
    463                 $this->prefix = $this->get_blog_prefix( $this->blogid );
    464 
    465                 foreach ( (array) $this->tables as $table )
     484                foreach ( $this->tables as $table )
    466485                        $this->$table = $this->prefix . $table;
    467486
    468                 if ( defined('CUSTOM_USER_TABLE') )
     487                if ( defined( 'CUSTOM_USER_TABLE' ) )
    469488                        $this->users = CUSTOM_USER_TABLE;
    470489
    471                 if ( defined('CUSTOM_USER_META_TABLE') )
     490                if ( defined( 'CUSTOM_USER_META_TABLE' ) )
    472491                        $this->usermeta = CUSTOM_USER_META_TABLE;
    473492
    474493                return $old_prefix;
    475494        }
    476495
    477         function set_blog_id($blog_id, $site_id = '') {
    478                 if ( !empty($site_id) )
    479                         $this->siteid = $site_id;
    480 
    481                 $old_blog_id = $this->blogid;
    482                 $this->blogid = $blog_id;
    483 
    484                 $this->prefix = $this->get_blog_prefix( $this->blogid );
    485 
    486                 foreach ( $this->tables as $table )
    487                         $this->$table = $this->prefix . $table;
    488 
    489                 return $old_blog_id;
    490         }
    491 
    492         function get_blog_prefix( $blog_id = '' ) {
    493                 if ( $blog_id ) {
    494                         if( defined('MULTISITE') && ( $blog_id == 0 || $blog_id == 1) ) {
    495                                 return $this->prefix;
    496                         } else {
    497                                 return $this->base_prefix . $blog_id . '_';
    498                         }
    499                 } else {
    500                         return $this->base_prefix;
    501                 }
    502         }
    503 
    504496        /**
    505497         * Selects a database using the current database connection.
    506498         *
     
    512504         * @param string $db MySQL database name
    513505         * @return null Always null.
    514506         */
    515         function select($db, &$dbh) {
    516                 if (!@mysql_select_db($db, $dbh)) {
     507        function select($db) {
     508                if (!@mysql_select_db($db, $this->dbh)) {
    517509                        $this->ready = false;
    518510                        $this->bail(sprintf(/*WP_I18N_DB_SELECT_DB*/'
    519511<h1>Can&#8217;t select database</h1>
     
    528520                }
    529521        }
    530522
    531         function _weak_escape($string) {
    532                 return addslashes($string);
    533         }
    534 
    535         function _real_escape($string) {
     523        /**
     524         * real escape
     525         *
     526         * escape via mysql_real_escape_string() or addslashes() 
     527         *
     528         * @since  2.8
     529         * @access private
     530         *
     531         * @param  string $string to escape
     532         * @return string escaped
     533         */
     534        function _real_escape( $string ) {
    536535                if ( $this->dbh && $this->real_escape )
    537536                        return mysql_real_escape_string( $string, $this->dbh );
    538537                else
    539538                        return addslashes( $string );
    540539        }
    541540
    542         function _escape($data) {
    543                 if ( is_array($data) ) {
    544                         foreach ( (array) $data as $k => $v ) {
    545                                 if ( is_array($v) )
    546                                         $data[$k] = $this->_escape( $v );
    547                                 else
    548                                         $data[$k] = $this->_real_escape( $v );
    549                         }
    550                 } else {
    551                         $data = $this->_real_escape( $data );
    552                 }
     541        /**
     542         * escape
     543         *
     544         * escape data, uses {@see _real_escape()} and works
     545         * on arrays as well.
     546         *
     547         * @since  2.8
     548         * @access private
     549         *
     550         * @param  string|array $data to escape
     551         * @return string|array escaped
     552         */
     553        function _escape( $data ) {
     554                if ( is_array( $data ) )
     555                        return array_map( array( &$this, '_escape' ), $data );
    553556
    554                 return $data;
     557                return $this->_real_escape( $data );
    555558        }
    556559
    557560        /**
     
    559562         *
    560563         * @since 0.71
    561564         *
    562          * @param string|array $data
    563          * @return string query safe string
     565         * @param  string|array $data to escape
     566         * @return string|array escaped as query safe string
    564567         */
    565         function escape($data) {
    566                 if ( is_array($data) ) {
    567                         foreach ( (array) $data as $k => $v ) {
    568                                 if ( is_array($v) )
    569                                         $data[$k] = $this->escape( $v );
    570                                 else
    571                                         $data[$k] = $this->_weak_escape( $v );
    572                         }
    573                 } else {
    574                         $data = $this->_weak_escape( $data );
    575                 }
     568        function escape( $data ) {
     569                if ( is_array($data) )
     570                        return array_map( array( &$this, 'escape' ), $data );
    576571
    577                 return $data;
     572                return addslashes( $data );
    578573        }
    579574
    580575        /**
     
    582577         *
    583578         * @since 2.3.0
    584579         *
    585          * @param string $s
     580         * @param  string $string to escape
     581         * @return void
    586582         */
    587         function escape_by_ref(&$string) {
     583        function escape_by_ref( &$string ) {
    588584                $string = $this->_real_escape( $string );
    589585        }
    590586
    591587        /**
    592588         * Prepares a SQL query for safe execution.  Uses sprintf()-like syntax.
    593589         *
     590         * The following directives can be used in the query format string:
     591         *
     592         *   %d (decimal number) 
     593         *   %s (string)
     594         *   %% (literal percentage sign - no argument needed)
     595         *
     596         * Both %d and %s are to be left unquoted in the query string and   
     597         * they need an argument passed for them.
     598         * Literals (%) as parts of the query must be properly written
     599         * as %%.
     600         * 
    594601         * This function only supports a small subset of the sprintf syntax; it only supports %d (decimal number), %s (string).
    595602         * Does not support sign, padding, alignment, width or precision specifiers.
    596603         * Does not support argument numbering/swapping.
     
    601608         *
    602609         * <code>
    603610         * wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", "foo", 1337 )
     611         * wpdb::prepare( "SELECT DATE_FORMAT(`field`, '%%c') FROM `table` WHERE `column` = %s", 'foo' );
    604612         * </code>
    605613         *
    606614         * @link http://php.net/sprintf Description of syntax.
    607615         * @since 2.3.0
    608616         *
    609          * @param string $query Query statement with sprintf()-like placeholders
    610          * @param array|mixed $args The array of variables to substitute into the query's placeholders if being called like {@link http://php.net/vsprintf vsprintf()}, or the first variable to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}.
    611          * @param mixed $args,... further variables to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}.
    612          * @return null|string Sanitized query string
     617         * @param  string $query Query statement with sprintf()-like placeholders
     618         * @param  mixed  $args The array of variables to substitute into the query's placeholders if being called like {@link http://php.net/vsprintf vsprintf()}, or the first variable to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}.
     619         * @param  mixed $args,... further variables to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}.
     620         * @return string|false  Sanitized query string, false on error
    613621         */
    614         function prepare($query = null) { // ( $query, *$args )
     622        function prepare( $query = null ) { // ( $query, *$args )
    615623                if ( is_null( $query ) )
    616                         return;
     624                        return false;
     625
    617626                $args = func_get_args();
    618                 array_shift($args);
    619                 // If args were passed as an array (as in vsprintf), move them up
    620                 if ( isset($args[0]) && is_array($args[0]) )
    621                         $args = $args[0];
    622                 $query = str_replace("'%s'", '%s', $query); // in case someone mistakenly already singlequoted it
    623                 $query = str_replace('"%s"', '%s', $query); // doublequote unquoting
    624                 $query = str_replace('%s', "'%s'", $query); // quote the strings
    625                 array_walk($args, array(&$this, 'escape_by_ref'));
    626                 return @vsprintf($query, $args);
     627                array_shift( $args );
     628
     629                if ( isset( $args[0] ) && is_array( $args[0] ) )
     630                        $args = $args[0]; # re-assign args passed as array like in vsprintf
     631
     632                // @todo (hakre) $query input can be  better sanitzed, tested code available #11608
     633
     634                $quoted = str_replace('%s', "'%s'", $query); # quote the strings
     635                $quoted = str_replace( array( "''%s''", "\"'%'\"" ), "'%s'", $quoted ); # in case someone mistakenly already single/double quoted it
     636                array_walk( $args, array( &$this, 'escape_by_ref' ) );
     637                return @vsprintf( $quoted, $args );
    627638        }
    628639
    629640        /**
     
    635646         * @param string $str The error to display
    636647         * @return bool False if the showing of errors is disabled.
    637648         */
    638         function print_error($str = '') {
     649        function print_error( $str = '' ) {
    639650                global $EZSQL_ERROR;
    640651
    641652                if (!$str) $str = mysql_error($this->dbh);
     
    649660                else
    650661                        $error_str = sprintf(/*WP_I18N_DB_QUERY_ERROR*/'WordPress database error %1$s for query %2$s'/*/WP_I18N_DB_QUERY_ERROR*/, $str, $this->last_query);
    651662
    652                 $log_error = true;
    653                 if ( ! function_exists('error_log') )
    654                         $log_error = false;
     663                trigger_error( $error_str, E_USER_WARNING );
    655664
    656                 $log_file = @ini_get('error_log');
    657                 if ( !empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file) )
    658                         $log_error = false;
     665                if ( function_exists( 'error_log' )
     666                     && !( $log_file = ini_get( 'error_log' ) )
     667                     && ( 'syslog' != $log_file )
     668                     && @is_writable( $log_file ) )
     669                    @error_log( $error_str );
    659670
    660                 if ( $log_error )
    661                         @error_log($error_str, 0);
    662 
    663671                // Is error output turned on or not..
    664672                if ( !$this->show_errors )
    665673                        return false;
    666674
    667                 // If there is an error then take note of it
    668                 if( is_multisite() ) {
    669                         $msg = "WordPress database error: [$str]\n{$this->last_query}\n";
    670                         if( defined( 'ERRORLOGFILE' ) )
    671                                 error_log( $msg, 3, CONSTANT( 'ERRORLOGFILE' ) );
    672                         if( defined( 'DIEONDBERROR' ) )
    673                                 die( $msg );
    674                 } else {
    675                         $str = htmlspecialchars($str, ENT_QUOTES);
    676                         $query = htmlspecialchars($this->last_query, ENT_QUOTES);
    677 
    678                         print "<div id='error'>
    679                         <p class='wpdberror'><strong>WordPress database error:</strong> [$str]<br />
    680                         <code>$query</code></p>
    681                         </div>";
    682                 }
     675                $str   = htmlspecialchars( $str, ENT_QUOTES );
     676                $query = $this->last_query ? sprintf( '<br><code>%s</code>', htmlspecialchars( $this->last_query, ENT_QUOTES ) ) : '';
     677                printf('<div id="error"><p class="wpdberror"><strong>WordPress database error:</strong> [%s]%s</p>', $str, $query);
    683678        }
    684679
    685680        /**
     
    690685         * this function can be used to enable and disable showing of database
    691686         * errors.
    692687         *
    693          * @since 0.71
    694          *
    695          * @param bool $show Whether to show or hide errors
     688         * @since  0.71
     689         * @see    hide_errors()
     690         *
     691         * @param  bool $show Whether to show or hide errors
    696692         * @return bool Old value for showing errors.
    697693         */
    698694        function show_errors( $show = true ) {
     
    703699
    704700        /**
    705701         * Disables showing of database errors.
     702         *
     703         * By default database errors are not shown.
    706704         *
    707          * @since 0.71
     705         * @since  0.71
     706         * @see    show_errors()
    708707         *
    709          * @return bool Whether showing of errors was active or not
     708         * @return bool Old show errors value
    710709         */
    711710        function hide_errors() {
    712711                $show = $this->show_errors;
     
    717716        /**
    718717         * Whether to suppress database errors.
    719718         *
    720          * @param unknown_type $suppress
    721          * @return unknown
     719         * By default database errors are suppressed, with a simple
     720         * call to this function they can be enabled.
     721         *
     722         * @since  2.5
     723         * @see    hide_errors()
     724         * @param  bool $suppress (optional) new value, defaults to true
     725         * @return bool old suppress errors value
    722726         */
    723727        function suppress_errors( $suppress = true ) {
    724728                $errors = $this->suppress_errors;
    725                 $this->suppress_errors = $suppress;
     729                $this->suppress_errors = (bool) $suppress;
    726730                return $errors;
    727731        }
    728732
     
    730734         * Kill cached query results.
    731735         *
    732736         * @since 0.71
     737         *
     738         * @return void
    733739         */
    734740        function flush() {
    735                 $this->last_result = array();
    736                 $this->col_info = null;
    737                 $this->last_query = null;
     741                $this->last_result   = array();
     742                $this->num_rows      = 0;
     743                $this->rows_affected = 0;
     744                $this->col_info      = null;
     745                $this->last_query    = null;
    738746        }
    739747
    740         function db_connect( $query = "SELECT" ) {
    741                 global $db_list, $global_db_list;
    742                 if( is_array( $db_list ) == false )
    743                         return true;
    744 
    745                 if( $this->blogs != '' && preg_match("/(" . $this->blogs . "|" . $this->users . "|" . $this->usermeta . "|" . $this->site . "|" . $this->sitemeta . "|" . $this->sitecategories . ")/i",$query) ) {
    746                         $action = 'global';
    747                         $details = $global_db_list[ mt_rand( 0, count( $global_db_list ) -1 ) ];
    748                         $this->db_global = $details;
    749                 } elseif ( preg_match("/^\\s*(alter table|create|insert|delete|update|replace) /i",$query) ) {
    750                         $action = 'write';
    751                         $details = $db_list[ 'write' ][ mt_rand( 0, count( $db_list[ 'write' ] ) -1 ) ];
    752                         $this->db_write = $details;
    753                 } else {
    754                         $action = '';
    755                         $details = $db_list[ 'read' ][ mt_rand( 0, count( $db_list[ 'read' ] ) -1 ) ];
    756                         $this->db_read = $details;
    757                 }
    758 
    759                 $dbhname = "dbh" . $action;
    760                 $this->$dbhname = @mysql_connect( $details[ 'db_host' ], $details[ 'db_user' ], $details[ 'db_password' ] );
    761                 if (!$this->$dbhname ) {
    762                         $this->bail("
    763 <h1>Error establishing a database connection</h1>
    764 <p>This either means that the username and password information in your <code>wp-config.php</code> file is incorrect or we can't contact the database server at <code>$dbhost</code>. This could mean your host's database server is down.</p>
    765 <ul>
    766         <li>Are you sure you have the correct username and password?</li>
    767         <li>Are you sure that you have typed the correct hostname?</li>
    768         <li>Are you sure that the database server is running?</li>
    769 </ul>
    770 <p>If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href='http://wordpress.org/support/'>WordPress Support Forums</a>.</p>
    771 ");
    772                 }
    773                 $this->select( $details[ 'db_name' ], $this->$dbhname );
    774         }
    775 
    776748        /**
    777749         * Perform a MySQL database query, using current database connection.
    778750         *
     
    780752         *
    781753         * @since 0.71
    782754         *
    783          * @param string $query
     755         * @param  string   $query database query
    784756         * @return int|false Number of rows affected/selected or false on error
    785757         */
    786         function query($query) {
     758        function query( $query ) {
    787759                if ( ! $this->ready )
    788760                        return false;
    789761
    790                 // filter the query, if filters are available
    791                 // NOTE: some queries are made before the plugins have been loaded, and thus cannot be filtered with this method
    792762                if ( function_exists('apply_filters') )
    793763                        $query = apply_filters('query', $query);
    794764
    795                 // initialise return
     765                // init return values and objects state
    796766                $return_val = 0;
    797767                $this->flush();
    798768
     
    802772                // Keep track of the last query for debug..
    803773                $this->last_query = $query;
    804774
    805                 // Perform the query via std mysql_query function..
    806775                if ( defined('SAVEQUERIES') && SAVEQUERIES )
    807776                        $this->timer_start();
    808                
    809                 // use $this->dbh for read ops, and $this->dbhwrite for write ops
    810                 // use $this->dbhglobal for gloal table ops
    811                 unset( $dbh );
    812                 if( defined( "WP_USE_MULTIPLE_DB" ) && CONSTANT( "WP_USE_MULTIPLE_DB" ) == true ) {
    813                         if( $this->blogs != '' && preg_match("/(" . $this->blogs . "|" . $this->users . "|" . $this->usermeta . "|" . $this->site . "|" . $this->sitemeta . "|" . $this->sitecategories . ")/i",$query) ) {
    814                                 if( false == isset( $this->dbhglobal ) ) {
    815                                         $this->db_connect( $query );
    816                                 }
    817                                 $dbh =& $this->dbhglobal;
    818                                 $this->last_db_used = "global";
    819                         } elseif ( preg_match("/^\\s*(alter table|create|insert|delete|update|replace) /i",$query) ) {
    820                                 if( false == isset( $this->dbhwrite ) ) {
    821                                         $this->db_connect( $query );
    822                                 }
    823                                 $dbh =& $this->dbhwrite;
    824                                 $this->last_db_used = "write";
    825                         } else {
    826                                 $dbh =& $this->dbh;
    827                                 $this->last_db_used = "read";
    828                         }
    829                 } else {
    830                         $dbh =& $this->dbh;
    831                         $this->last_db_used = "other/read";
    832                 }
    833777
    834                 $this->result = @mysql_query($query, $dbh);
    835                 ++$this->num_queries;
     778                // Perform the query via std mysql_query function..
     779                $this->result = @mysql_query($query, $this->dbh);
     780                $this->num_queries++;
    836781
    837782                if ( defined('SAVEQUERIES') && SAVEQUERIES )
    838783                        $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
    839784
    840785                // If there is an error then take note of it..
    841                 if ( $this->last_error = mysql_error($dbh) ) {
     786                if ( $this->last_error = mysql_error( $this->dbh ) ) {
    842787                        $this->print_error();
    843788                        return false;
    844789                }
    845790
    846                 if ( preg_match("/^\\s*(insert|delete|update|replace|alter) /i",$query) ) {
    847                         $this->rows_affected = mysql_affected_rows($dbh);
    848                         // Take note of the insert_id
    849                         if ( preg_match("/^\\s*(insert|replace) /i",$query) ) {
    850                                 $this->insert_id = mysql_insert_id($dbh);
    851                         }
    852                         // Return number of rows affected
    853                         $return_val = $this->rows_affected;
    854                 } else {
    855                         $i = 0;
    856                         while ($i < @mysql_num_fields($this->result)) {
    857                                 $this->col_info[$i] = @mysql_fetch_field($this->result);
    858                                 $i++;
    859                         }
    860                         $num_rows = 0;
    861                         while ( $row = @mysql_fetch_object($this->result) ) {
    862                                 $this->last_result[$num_rows] = $row;
    863                                 $num_rows++;
    864                         }
     791                if ( preg_match( '(^\s*([a-z]{2,})\s+)i', $query, $matches ) )
     792                        $type = strtoupper($matches[1]);
     793                else
     794                        $type = '';
    865795
    866                         @mysql_free_result($this->result);
     796                switch( $type ) {
     797                        case 'INSERT':
     798                        case 'REPLACE':
     799                                $this->insert_id = mysql_insert_id( $this->dbh );
     800                        case 'DELETE':
     801                        case 'UPDATE':
     802                        case 'ALTER':
     803                                $this->rows_affected = mysql_affected_rows( $this->dbh );
     804                                $return_val = $this->rows_affected;
     805                                break;
    867806
    868                         // Log number of rows the query returned
    869                         $this->num_rows = $num_rows;
     807                        default:
     808                                $i = 0;
     809                                while ( $i < @mysql_num_fields( $this->result ) )
     810                                        $this->col_info[$i++] = @mysql_fetch_field( $this->result );
    870811
    871                         // Return number of rows selected
    872                         $return_val = $this->num_rows;
     812                                $num_rows = 0;
     813                                while ( $row = @mysql_fetch_assoc( $this->result ) )
     814                                        $this->last_result[$num_rows++] = $row;
     815
     816                                @mysql_free_result( $this->result );
     817                                $this->num_rows = $num_rows;
     818                                $return_val = $num_rows;
    873819                }
    874 
     820               
    875821                return $return_val;
    876822        }
    877823
     
    879825         * Insert a row into a table.
    880826         *
    881827         * <code>
     828         * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ) )
    882829         * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
    883830         * </code>
    884831         *
    885832         * @since 2.5.0
    886          * @see wpdb::prepare()
     833         * @see   prepare()
    887834         *
    888          * @param string $table table name
    889          * @param array $data Data to insert (in column => value pairs).  Both $data columns and $data values should be "raw" (neither should be SQL escaped).
    890          * @param array|string $format (optional) An array of formats to be mapped to each of the value in $data.  If string, that format will be used for all of the values in $data.  A format is one of '%d', '%s' (decimal number, string).  If omitted, all values in $data will be treated as strings.
    891          * @return int|false The number of rows inserted, or false on error.
     835         * @param  string       $table table name
     836         * @param  array        $data  Data to insert (in column => value pairs).  Both $data columns and $data values should be "raw" (neither should be SQL escaped).
     837         * @param  array|string $format (optional) An array of formats to be mapped to each of the value in $data.  If string, that format will be used for all of the values in $data.  A format is one of '%d', '%s' (decimal number, string).  If omitted, all values in $data will be treated as strings.
     838         * @return int|false    The number of rows inserted, or false on error.
    892839         */
    893         function insert($table, $data, $format = null) {
    894                 $formats = $format = (array) $format;
    895                 $fields = array_keys($data);
    896                 $formatted_fields = array();
    897                 foreach ( $fields as $field ) {
    898                         if ( !empty($format) )
    899                                 $form = ( $form = array_shift($formats) ) ? $form : $format[0];
    900                         elseif ( isset($this->field_types[$field]) )
    901                                 $form = $this->field_types[$field];
    902                         else
    903                                 $form = '%s';
    904                         $formatted_fields[] = $form;
    905                 }
    906                 $sql = "INSERT INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES ('" . implode( "','", $formatted_fields ) . "')";
    907                 return $this->query( $this->prepare( $sql, $data) );
     840        function insert( $table, $data, $format = null ) {
     841                if ( !is_array( $data ) )
     842                        return false;
     843
     844                $sql = sprintf(
     845                        'INSERT INTO `%s` SET %s'
     846                        , $table
     847                        , $this->_field_formats( array_keys( $data ), $format, ', ' )
     848                );
     849                $values = array_values( $data );
     850                return $this->query( $this->prepare( $sql, $values ) );
    908851        }
    909852
    910 
    911853        /**
    912854         * Update a row in the table
    913855         *
    914856         * <code>
     857         * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ) )
    915858         * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) )
    916859         * </code>
    917860         *
    918861         * @since 2.5.0
    919          * @see wpdb::prepare()
     862         * @see   prepare()
    920863         *
    921          * @param string $table table name
    922          * @param array $data Data to update (in column => value pairs).  Both $data columns and $data values should be "raw" (neither should be SQL escaped).
    923          * @param array $where A named array of WHERE clauses (in column => value pairs).  Multiple clauses will be joined with ANDs.  Both $where columns and $where values should be "raw".
    924          * @param array|string $format (optional) An array of formats to be mapped to each of the values in $data.  If string, that format will be used for all of the values in $data.  A format is one of '%d', '%s' (decimal number, string).  If omitted, all values in $data will be treated as strings.
     864         * @param string       $table        table name
     865         * @param array        $data        Data to update (in column => value pairs).  Both $data columns and $data values should be "raw" (neither should be SQL escaped).
     866         * @param array        $where        A named array of WHERE clauses (in column => value pairs).  Multiple clauses will be joined with ANDs.  Both $where columns and $where values should be "raw".
     867         * @param array|string $format       (optional) An array of formats to be mapped to each of the values in $data.  If string, that format will be used for all of the values in $data.  A format is one of '%d', '%s' (decimal number, string).  If omitted, all values in $data will be treated as strings.
    925868         * @param array|string $format_where (optional) An array of formats to be mapped to each of the values in $where.  If string, that format will be used for all of  the items in $where.  A format is one of '%d', '%s' (decimal number, string).  If omitted, all values in $where will be treated as strings.
    926          * @return int|false The number of rows updated, or false on error.
     869         * @return int|false   The number of rows updated, or false on error.
    927870         */
    928         function update($table, $data, $where, $format = null, $where_format = null) {
    929                 if ( !is_array( $where ) )
     871        function update( $table, $data, $where, $format = null, $where_format = null ) {
     872                if ( !is_array( $data ) || !is_array( $where ))
    930873                        return false;
    931874
     875                $sql = sprintf(
     876                        'UPDATE `%s` SET %s WHERE %s'
     877                        , $table
     878                        , $this->_field_formats( array_keys( $data  ), $format, ', ' )
     879                        , $this->_field_formats( array_keys( $where ), $where_format, ' AND ' )
     880                );             
     881                $values = array_merge( array_values( $data ), array_values( $where ) );
     882                return $this->query( $this->prepare( $sql, $values ) );
     883        }
     884
     885        /**
     886         * field types
     887         *
     888         * helper function to get the format string for
     889         * multiple fields.
     890         *
     891         * @param array $fields fields name => value based
     892         * @param array $format additional field-format specifier(s), compare to wpdb::update() $format parameter
     893         * @param string $concat concatination string
     894         * @param string $default (optional) default format, is %s, see wpdb::prepare() for format tokens
     895         * @return array string format token string for those fields to be used
     896         * @access private
     897         * @since 3.0
     898         */
     899        function _field_formats( $fields, $format, $concat, $default = '%s' ) {
     900                $result  = array();
    932901                $formats = $format = (array) $format;
    933                 $bits = $wheres = array();
    934                 foreach ( (array) array_keys($data) as $field ) {
    935                         if ( !empty($format) )
    936                                 $form = ( $form = array_shift($formats) ) ? $form : $format[0];
    937                         elseif ( isset($this->field_types[$field]) )
    938                                 $form = $this->field_types[$field];
    939                         else
    940                                 $form = '%s';
    941                         $bits[] = "`$field` = {$form}";
    942                 }
    943902
    944                 $where_formats = $where_format = (array) $where_format;
    945                 foreach ( (array) array_keys($where) as $field ) {
    946                         if ( !empty($where_format) )
    947                                 $form = ( $form = array_shift($where_formats) ) ? $form : $where_format[0];
    948                         elseif ( isset($this->field_types[$field]) )
    949                                 $form = $this->field_types[$field];
    950                         else
    951                                 $form = '%s';
    952                         $wheres[] = "`$field` = {$form}";
     903                foreach ( $fields as $field ) {
     904                        $token = $default;
     905                        if ( count( $format ) )
     906                                $token = ( $token = array_shift($formats) ) ? $token : $format[0];
     907                        elseif ( isset( $this->field_types[$field] ) )
     908                                $token = $this->field_types[$field];
     909
     910                        $result[] = sprintf( '`%s` = %s', $field, $token );
    953911                }
    954912
    955                 $sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres );
    956                 return $this->query( $this->prepare( $sql, array_merge(array_values($data), array_values($where))) );
     913                return implode( $concat, $result );
    957914        }
    958915
    959916        /**
     
    965922         *
    966923         * @since 0.71
    967924         *
    968          * @param string|null $query SQL query.  If null, use the result from the previous query.
    969          * @param int $x (optional) Column of value to return.  Indexed from 0.
    970          * @param int $y (optional) Row of value to return.  Indexed from 0.
    971          * @return string Database query result
     925         * @param string       $query (optional) SQL query. Defaults to NULL the re-use of existing data.
     926         * @param int          $col  (optional) Column of value to return.  Indexed from 0.
     927         * @param int          $row  (optional) Row of value to return.  Indexed from 0.
     928         * @return string|null string value on success, NULL if a value on
    972929         */
    973         function get_var($query=null, $x = 0, $y = 0) {
    974                 $this->func_call = "\$db->get_var(\"$query\",$x,$y)";
     930        function get_var( $query = null, $col = 0, $row = 0 ) {
     931                $this->func_call = "\$db->get_var(\"$query\",$col,$row)";
    975932                if ( $query )
    976                         $this->query($query);
     933                        $this->query( $query );
    977934
    978                 // Extract var out of cached results based x,y vals
    979                 if ( !empty( $this->last_result[$y] ) ) {
    980                         $values = array_values(get_object_vars($this->last_result[$y]));
     935                if ( isset( $this->last_result[$row] )
     936                     && ( $values = array_values( $this->last_result[$row] ) )
     937                     && isset( $values[$col] ) ) {
     938                        return $values[$col];
    981939                }
    982940
    983                 // If there is a value return it else return null
    984                 return (isset($values[$x]) && $values[$x]!=='') ? $values[$x] : null;
     941                return null;
    985942        }
    986943
    987944        /**
     
    993950         *
    994951         * @param string|null $query SQL query.
    995952         * @param string $output (optional) one of ARRAY_A | ARRAY_N | OBJECT constants.  Return an associative array (column => value, ...), a numerically indexed array (0 => value, ...) or an object ( ->column = value ), respectively.
    996          * @param int $y (optional) Row to return.  Indexed from 0.
    997          * @return mixed Database query result in format specifed by $output
     953         * @param int    $row (optional) Row to return.  Indexed from 0.
     954         * @return mixed Database query result in format specifed by $output or NULL
    998955         */
    999         function get_row($query = null, $output = OBJECT, $y = 0) {
    1000                 $this->func_call = "\$db->get_row(\"$query\",$output,$y)";
    1001                 if ( $query )
    1002                         $this->query($query);
    1003                 else
    1004                         return null;
     956        function &get_row( $query = null, $output = OBJECT, $row = 0) {
     957                $this->func_call = "\$db->get_row(\"$query\",$output,$row)";
     958                $retval = null;
    1005959
    1006                 if ( !isset($this->last_result[$y]) )
    1007                         return null;
     960                if ( null !== $query && false === $this->query( $query ) )
     961                        return $retval;
    1008962
    1009                 if ( $output == OBJECT ) {
    1010                         return $this->last_result[$y] ? $this->last_result[$y] : null;
    1011                 } elseif ( $output == ARRAY_A ) {
    1012                         return $this->last_result[$y] ? get_object_vars($this->last_result[$y]) : null;
    1013                 } elseif ( $output == ARRAY_N ) {
    1014                         return $this->last_result[$y] ? array_values(get_object_vars($this->last_result[$y])) : null;
    1015                 } else {
    1016                         $this->print_error(/*WP_I18N_DB_GETROW_ERROR*/" \$db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N"/*/WP_I18N_DB_GETROW_ERROR*/);
     963                $row = absint( $row );
     964
     965                if ( $row >= $this->num_rows )
     966                        return $retval;
     967
     968                $retval = $this->last_result[$row]; # stored as ARRAY_A, {@see query()}
     969
     970                switch ( $output ) {
     971                        case OBJECT:
     972                                $retval = (object) $retval;
     973                        case ARRAY_A:
     974                                break;
     975                        case ARRAY_N:
     976                                $retval = array_values( $retval );
     977                                break;
     978                        default:
     979                                $this->print_error(/*WP_I18N_DB_GETROW_ERROR*/" \$db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N"/*/WP_I18N_DB_GETROW_ERROR*/);     
    1017980                }
     981               
     982                return $retval;
    1018983        }
     984       
     985        /**
     986         * get last database error
     987         *
     988     * @since 3.0
     989     *
     990         * @return string last mysql database error
     991         */
     992        function get_last_error() {
     993                return $this->last_error;
     994        }
     995       
     996        /**
     997         * get number of rows
     998         *
     999         * Retrieve the number of rows of the last querty operation
     1000         *
     1001     * @since 3.0
     1002         * @see   query()
     1003     *
     1004         * @return int number of rows
     1005         */
     1006        function get_num_rows() {
     1007                return $this->num_rows;
     1008        }
    10191009
    10201010        /**
    10211011         * Retrieve one column from the database.
     
    10261016         *
    10271017         * @since 0.71
    10281018         *
    1029          * @param string|null $query SQL query.  If null, use the result from the previous query.
    1030          * @param int $x Column to return.  Indexed from 0.
    1031          * @return array Database query result.  Array indexed from 0 by SQL result row number.
     1019         * @param  string $query (optional) SQL query. If omitted it uses the result from the previous query.
     1020         * @param  int    $col   (optional) Column to return. Indexed from 0, defaults to first column.
     1021         * @return array  Array  Zero-based-row-number-keyed containing the column's value(s)
    10321022         */
    1033         function get_col($query = null , $x = 0) {
     1023        function get_col( $query = null , $col = 0 ) {
    10341024                if ( $query )
    1035                         $this->query($query);
     1025                        $this->query( $query );
    10361026
    10371027                $new_array = array();
    1038                 // Extract the column values
    1039                 for ( $i=0; $i < count($this->last_result); $i++ ) {
    1040                         $new_array[$i] = $this->get_var(null, $x, $i);
    1041                 }
     1028
     1029                // get that column values of all rows
     1030                $count = $this->num_rows;
     1031                for ( $i = 0; $i < $count; $i++ )
     1032                        if ( isset( $this->last_result[$i] )
     1033                         && $values = array_values( $this->last_result[$i] )
     1034                         && isset( $values[$col] ) )
     1035                                $new_array[$i] = $values[$col];
     1036
    10421037                return $new_array;
    10431038        }
    10441039
     
    10461041         * Retrieve an entire SQL result set from the database (i.e., many rows)
    10471042         *
    10481043         * Executes a SQL query and returns the entire SQL result.
     1044         *
     1045         * Return Types:
     1046         *
     1047         *   ARRAY_A  : array of column name-keyed row arrays
     1048         *   ARRAY_N  : array of integer-keyed row arrays
     1049         *   OBJECT   : array of row objects
     1050         *   OBJECT_K : column-1-keyed array of row objects (duplicates are discarded)
    10491051         *
    10501052         * @since 0.71
    10511053         *
    10521054         * @param string $query SQL query.
    10531055         * @param string $output (optional) ane of ARRAY_A | ARRAY_N | OBJECT | OBJECT_K constants.  With one of the first three, return an array of rows indexed from 0 by SQL result row number.  Each row is an associative array (column => value, ...), a numerically indexed array (0 => value, ...), or an object. ( ->column = value ), respectively.  With OBJECT_K, return an associative array of row objects keyed by the value of each row's first column's value.  Duplicate keys are discarded.
    1054          * @return mixed Database query results
     1056         * @return array|object|null Database query results or NULL on error
    10551057         */
    1056         function get_results($query = null, $output = OBJECT) {
     1058        function &get_results( $query = null, $output = OBJECT ) {
    10571059                $this->func_call = "\$db->get_results(\"$query\", $output)";
    1058 
     1060                $retval = null;
     1061               
    10591062                if ( $query )
    1060                         $this->query($query);
     1063                        $this->query( $query );
    10611064                else
    1062                         return null;
     1065                        return $retval;
    10631066
    1064                 if ( $output == OBJECT ) {
    1065                         // Return an integer-keyed array of row objects
    1066                         return $this->last_result;
    1067                 } elseif ( $output == OBJECT_K ) {
    1068                         // Return an array of row objects with keys from column 1
    1069                         // (Duplicates are discarded)
    1070                         foreach ( $this->last_result as $row ) {
    1071                                 $key = array_shift( get_object_vars( $row ) );
    1072                                 if ( !isset( $new_array[ $key ] ) )
    1073                                         $new_array[ $key ] = $row;
    1074                         }
    1075                         return $new_array;
    1076                 } elseif ( $output == ARRAY_A || $output == ARRAY_N ) {
    1077                         // Return an integer-keyed array of...
    1078                         if ( $this->last_result ) {
    1079                                 $i = 0;
    1080                                 foreach( (array) $this->last_result as $row ) {
    1081                                         if ( $output == ARRAY_N ) {
    1082                                                 // ...integer-keyed row arrays
    1083                                                 $new_array[$i] = array_values( get_object_vars( $row ) );
    1084                                         } else {
    1085                                                 // ...column name-keyed row arrays
    1086                                                 $new_array[$i] = get_object_vars( $row );
    1087                                         }
    1088                                         ++$i;
    1089                                 }
    1090                                 return $new_array;
    1091                         }
     1067                $retval = $this->last_result; # Array of database rows, each of type ARRAY_A {@see query()}
     1068
     1069                switch ( $output ) {
     1070                        case OBJECT:   # array of row objects
     1071                                foreach ( $retval as $key => $value )
     1072                                        $retval[$key] = (object) $value;
     1073                                break;
     1074
     1075                        case OBJECT_K: # column-1-keyed array of row objects (duplicates are discarded)
     1076                                $retval = array();
     1077                                foreach ($this->last_result as $value )
     1078                                        if ( !isset( $retval[$key = array_shift( array_values( $value ) )] ) )
     1079                                                $retval[$key] = (object) $value;
     1080                                break;
     1081
     1082                        case ARRAY_N:  # array of integer-keyed row arrays
     1083                                foreach ( $retval as $key=> $value )
     1084                                        $retval[$key] = array_values( $value );
     1085
     1086                        case ARRAY_A:  # array of column name-keyed row arrays
     1087                                break;
     1088
     1089                        default:       # undefined return type
     1090                                $retval = null;
    10921091                }
     1092
     1093                return $retval;
    10931094        }
    10941095
    10951096        /**
     
    11721173         *
    11731174         * @since 2.5.0
    11741175         * @uses $wp_version
     1176         * @uses $required_mysql_version
    11751177         *
    11761178         * @return WP_Error
    11771179         */
     
    11971199        }
    11981200
    11991201        /**
    1200          * Generic function to determine if a database supports a particular feature
    1201          * @param string $db_cap the feature
    1202          * @param false|string|resource $dbh_or_table (not implemented) Which database to test.  False = the currently selected database, string = the database containing the specified table, resource = the database corresponding to the specified mysql resource.
     1202         * has capability
     1203         *
     1204         * Determine if a database supports a particular feature
     1205         *
     1206         * Features are (since version):
     1207     *
     1208     *   'collation'     2.5.0
     1209     *   'group_concat'  2.7
     1210     *   'subqueries'    2.7
     1211     *
     1212         * ADDITIONAL PARAMETER NOTICE
     1213         *
     1214         * there once was a proposed second parameter which has never been
     1215         * implemented. It was describben as "Which database to test" ($dbh_or_table)
     1216         * 
     1217         * It would have had three different types:
     1218         *
     1219         *      false    : currently selected database
     1220         *  string   : database containing this table
     1221         *  resource : database by mysql resource
     1222         * 
     1223         * regarding that third parameter please see {@see db_version()} as well
     1224         *
     1225         * @since  2.7
     1226         * @see    db_version()
     1227         *
     1228         * @param  string $db_cap the feature
    12031229         * @return bool
    12041230         */
    12051231        function has_cap( $db_cap ) {
    1206                 $version = $this->db_version();
     1232                $db_cap = strtolower( $db_cap );
    12071233
    1208                 switch ( strtolower( $db_cap ) ) :
    1209                 case 'collation' :    // @since 2.5.0
    1210                 case 'group_concat' : // @since 2.7
    1211                 case 'subqueries' :   // @since 2.7
    1212                         return version_compare($version, '4.1', '>=');
    1213                         break;
    1214                 endswitch;
    1215 
    1216                 return false;
     1234                switch ( $db_cap ) {
     1235                        case 'collation' :    # @since 2.5.0
     1236                        case 'group_concat' : # @since 2.7
     1237                        case 'subqueries' :   # @since 2.7
     1238                                $version = $this->db_version();
     1239                                return version_compare( $version, '4.1', '>=' );
     1240                        default:
     1241                                return false;
     1242                }
    12171243        }
    12181244
    12191245        /**
     
    12271253         * @return string The name of the calling function
    12281254         */
    12291255        function get_caller() {
    1230                 // requires PHP 4.3+
    1231                 if ( !is_callable('debug_backtrace') )
    1232                         return '';
    1233 
    1234                 $bt = debug_backtrace();
     1256                $trace  = array_reverse( debug_backtrace() );
    12351257                $caller = array();
    12361258
    1237                 $bt = array_reverse( $bt );
    1238                 foreach ( (array) $bt as $call ) {
    1239                         if ( @$call['class'] == __CLASS__ )
    1240                                 continue;
     1259                foreach ( $trace as $call ) {
     1260                        if ( isset( $call['class'] ) &&  __CLASS__ == $call['class'] )
     1261                                continue; # filter out function calls if this object's class
     1262
    12411263                        $function = $call['function'];
     1264
    12421265                        if ( isset( $call['class'] ) )
    12431266                                $function = $call['class'] . "->$function";
     1267
    12441268                        $caller[] = $function;
    12451269                }
    1246                 $caller = join( ', ', $caller );
    12471270
    1248                 return $caller;
     1271                return join( ', ', $caller );
    12491272        }
    12501273
    12511274        /**
    1252          * The database version number
    1253          * @param false|string|resource $dbh_or_table (not implemented) Which database to test.  False = the currently selected database, string = the database containing the specified table, resource = the database corresponding to the specified mysql resource.
     1275         * get database version number
     1276         *
     1277         * ADDITIONAL PARAMETER NOTICE
     1278         *
     1279         * there once was a proposed second parameter which has never been
     1280         * implemented. It was describben as "Which database to test" ($dbh_or_table)
     1281         *
     1282         * It would have had three different types:
     1283         *
     1284         *      false    : currently selected database
     1285         *  string   : database containing this table
     1286         *  resource : database by mysql resource
     1287         *
     1288         * regarding that third parameter please see {@see db_version()} as well
     1289         *
     1290         * @since  2.7
     1291         * @see    has_cap()
     1292         *
    12541293         * @return false|string false on failure, version number on success
    12551294         */
    12561295        function db_version() {
    12571296                return preg_replace('/[^0-9.].*/', '', mysql_get_server_info( $this->dbh ));
    12581297        }
     1298       
     1299        /**
     1300         * get tables
     1301         *
     1302         * get list of a set of tables
     1303         *
     1304         * Sets:
     1305         *
     1306         *   all     : all names
     1307         *   current : active tables
     1308         *   old     : deprecated tables
     1309         *
     1310         * @since  3.0
     1311         *
     1312         * @param  string $set (optional) 'all', 'current' or 'old'. defaults to 'current'
     1313         * @return array  list of old table names (w/o prefix), false on error
     1314         */
     1315        function get_tables( $set = 'current' ) {
     1316                $tables = false;
     1317
     1318                switch ( $set ) {
     1319                        case 'all':
     1320                                $tables = $this->tables;
     1321                                break;
     1322                        case 'current':
     1323                                $tables = array_diff( $this->tables, $this->old_tables );
     1324                                break;
     1325                        case 'old':
     1326                                $tables = $this->old_tables;
     1327                                break;
     1328                }
     1329
     1330                return $tables;
     1331        }
    12591332}
    12601333
    12611334if ( ! isset($wpdb) ) {
     
    12661339         */
    12671340        $wpdb = new wpdb(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
    12681341}
    1269 ?>
     1342?>
     1343 No newline at end of file