Make WordPress Core

Ticket #10918: 10918-2.patch

File 10918-2.patch, 251.8 KB (added by azaozz, 15 years ago)
  • wp-admin/setup-config.php

     
    9191        <li>Database username</li>
    9292        <li>Database password</li>
    9393        <li>Database host</li>
     94        <li>Database type</li>
    9495        <li>Table prefix (if you want to run more than one WordPress in a single database) </li>
    9596</ol>
    9697<p><strong>If for any reason this automatic file creation doesn't work, don't worry. All this does is fill in the database information to a configuration file. You may also simply open <code>wp-config-sample.php</code> in a text editor, fill in your information, and save it as <code>wp-config.php</code>. </strong></p>
     
    114115                <tr>
    115116                        <th scope="row"><label for="uname">User Name</label></th>
    116117                        <td><input name="uname" id="uname" type="text" size="25" value="username" /></td>
    117                         <td>Your MySQL username</td>
     118                        <td>Your database username</td>
    118119                </tr>
    119120                <tr>
    120121                        <th scope="row"><label for="pwd">Password</label></th>
    121122                        <td><input name="pwd" id="pwd" type="text" size="25" value="password" /></td>
    122                         <td>...and MySQL password.</td>
     123                        <td>...and database password.</td>
    123124                </tr>
    124125                <tr>
    125126                        <th scope="row"><label for="dbhost">Database Host</label></th>
    126127                        <td><input name="dbhost" id="dbhost" type="text" size="25" value="localhost" /></td>
    127                         <td>99% chance you won't need to change this value.</td>
     128                        <td>DB host, 99% chance you won't need to change this value.</td><?php
     129
     130                $folders = array();
     131                if ( is_dir(ABSPATH . 'wp-includes/wp-db/') ) {
     132                        $dir = ABSPATH . 'wp-includes/wp-db/';
     133                        $handle = dir($dir);
     134                        while ( $filename = $handle->read() ) {
     135                                $restricted = array('.', '..', '.svn');
     136                                $path = realpath($dir.$filename);
     137                                if ( is_dir($path) && !in_array($filename, $restricted) ) {
     138                                        if ( $path !== '/' ) {
     139                                                $path .= '/';
     140                                        }
     141                                        if ( is_readable($path) ) {
     142                                                $folders[] = $filename;
     143                                        }
     144                                }
     145                        }
     146                }
     147                if ( empty($folders) ) { ?>
     148
     149                        <input name="dbtype" id="dbtype" type="hidden" value="mysql" /><?php
     150                } else { ?>
     151
    128152                </tr>
    129153                <tr>
     154                        <th scope="row"><label for="dbtype">Database Type</label></th>
     155                        <td>
     156                                <select name="dbtype" id="dbtype"><?php
     157
     158                                foreach ( $folders as $folder ) {
     159                                        // mysql as default
     160                                        if ( $folder == 'mysql' ) {
     161                                                echo "<option value=\"$folder\">MySQL</option>\n";
     162                                        } elseif ( $folder == 'sqlsrv' ) {
     163                                                echo "<option value=\"$folder\">SQL Server using MS PHP driver (SQLSRV; PHP5 &amp; Win req.)</option>\n";
     164                                        } elseif ( $folder == 'mssql' ) {
     165                                                echo "<option value=\"$folder\">SQL Server using PHP native driver (MSSQL)</option>\n";
     166                                        } else {
     167                                                echo "<option value=\"$folder\">$folder</option>\n";
     168                                        }
     169                                } ?>
     170
     171                                </select>
     172                                <td>The DB Type.</td><?php
     173                        } ?>
     174
     175                </tr>
     176                <tr>
    130177                        <th scope="row"><label for="prefix">Table Prefix</label></th>
    131178                        <td><input name="prefix" id="prefix" type="text" id="prefix" value="wp_" size="25" /></td>
    132179                        <td>If you want to run multiple WordPress installations in a single database, change this.</td>
     
    142189        $uname   = trim($_POST['uname']);
    143190        $passwrd = trim($_POST['pwd']);
    144191        $dbhost  = trim($_POST['dbhost']);
     192        $dbtype  = trim($_POST['dbtype']);
    145193        $prefix  = trim($_POST['prefix']);
    146194        if (empty($prefix)) $prefix = 'wp_';
    147195
     
    153201        define('DB_USER', $uname);
    154202        define('DB_PASSWORD', $passwrd);
    155203        define('DB_HOST', $dbhost);
     204        define('DB_TYPE', $dbtype);
    156205        /**#@-*/
    157206
    158207        // We'll fail here if the values are no good.
     
    174223                        case "define('DB_HOST'":
    175224                                $configFile[$line_num] = str_replace("localhost", $dbhost, $line);
    176225                                break;
     226                        case "define('DB_TYPE'":
     227                                $configFile[$line_num] = str_replace('mysql', $dbtype, $line);
     228                                break;
    177229                        case '$table_prefix  =':
    178230                                $configFile[$line_num] = str_replace('wp_', $prefix, $line);
    179231                                break;
  • wp-config-sample.php

     
    11<?php
    2 /** 
     2/**
    33 * The base configurations of the WordPress.
    44 *
    55 * This file has the following configurations: MySQL settings, Table Prefix,
     
    1818/** The name of the database for WordPress */
    1919define('DB_NAME', 'putyourdbnamehere');
    2020
    21 /** MySQL database username */
     21/** Database username */
    2222define('DB_USER', 'usernamehere');
    2323
    24 /** MySQL database password */
     24/** Database password */
    2525define('DB_PASSWORD', 'yourpasswordhere');
    2626
    27 /** MySQL hostname */
     27/** Database hostname */
    2828define('DB_HOST', 'localhost');
    2929
     30/** Database Type. Defaults to mysql */
     31define('DB_TYPE', 'mysql');
     32
    3033/** Database Charset to use in creating database tables. */
    3134define('DB_CHARSET', 'utf8');
    3235
  • wp-includes/wp-db.php

     
    11<?php
    2 /**
    3  * WordPress DB Class
    4  *
    5  * Original code from {@link http://php.justinvincent.com Justin Vincent (justin@visunet.ie)}
    6  *
    7  * @package WordPress
    8  * @subpackage Database
    9  * @since 0.71
    10  */
     2// help maintain backwards compatibility.
     3if ( !defined('DB_TYPE') ) {
     4        define('DB_TYPE', 'mysql');
     5}
    116
    12 /**
    13  * @since 0.71
    14  */
    15 define('EZSQL_VERSION', 'WP1.25');
     7require_once(dirname(__FILE__) . '/wp-db/' . DB_TYPE . '/' . DB_TYPE . '.php');
    168
    17 /**
    18  * @since 0.71
    19  */
    20 define('OBJECT', 'OBJECT', true);
    21 
    22 /**
    23  * @since {@internal Version Unknown}}
    24  */
    25 define('OBJECT_K', 'OBJECT_K', false);
    26 
    27 /**
    28  * @since 0.71
    29  */
    30 define('ARRAY_A', 'ARRAY_A', false);
    31 
    32 /**
    33  * @since 0.71
    34  */
    35 define('ARRAY_N', 'ARRAY_N', false);
    36 
    37 /**
    38  * WordPress Database Access Abstraction Object
    39  *
    40  * It is possible to replace this class with your own
    41  * by setting the $wpdb global variable in wp-content/db.php
    42  * file with your class. You can name it wpdb also, since
    43  * this file will not be included, if the other file is
    44  * available.
    45  *
    46  * @link http://codex.wordpress.org/Function_Reference/wpdb_Class
    47  *
    48  * @package WordPress
    49  * @subpackage Database
    50  * @since 0.71
    51  * @final
    52  */
    53 class wpdb {
    54 
     9if ( !isset($wpdb) ) {
    5510        /**
    56          * Whether to show SQL/DB errors
    57          *
    58          * @since 0.71
    59          * @access private
    60          * @var bool
    61          */
    62         var $show_errors = false;
    63 
    64         /**
    65          * Whether to suppress errors during the DB bootstrapping.
    66          *
    67          * @access private
    68          * @since {@internal Version Unknown}}
    69          * @var bool
    70          */
    71         var $suppress_errors = false;
    72 
    73         /**
    74          * The last error during query.
    75          *
    76          * @since {@internal Version Unknown}}
    77          * @var string
    78          */
    79         var $last_error = '';
    80 
    81         /**
    82          * Amount of queries made
    83          *
    84          * @since 1.2.0
    85          * @access private
    86          * @var int
    87          */
    88         var $num_queries = 0;
    89 
    90         /**
    91          * Saved result of the last query made
    92          *
    93          * @since 1.2.0
    94          * @access private
    95          * @var array
    96          */
    97         var $last_query;
    98 
    99         /**
    100          * Saved info on the table column
    101          *
    102          * @since 1.2.0
    103          * @access private
    104          * @var array
    105          */
    106         var $col_info;
    107 
    108         /**
    109          * Saved queries that were executed
    110          *
    111          * @since 1.5.0
    112          * @access private
    113          * @var array
    114          */
    115         var $queries;
    116 
    117         /**
    118          * WordPress table prefix
    119          *
    120          * You can set this to have multiple WordPress installations
    121          * in a single database. The second reason is for possible
    122          * security precautions.
    123          *
    124          * @since 0.71
    125          * @access private
    126          * @var string
    127          */
    128         var $prefix = '';
    129 
    130         /**
    131          * Whether the database queries are ready to start executing.
    132          *
    133          * @since 2.5.0
    134          * @access private
    135          * @var bool
    136          */
    137         var $ready = false;
    138 
    139         /**
    140          * WordPress Posts table
    141          *
    142          * @since 1.5.0
    143          * @access public
    144          * @var string
    145          */
    146         var $posts;
    147 
    148         /**
    149          * WordPress Users table
    150          *
    151          * @since 1.5.0
    152          * @access public
    153          * @var string
    154          */
    155         var $users;
    156 
    157         /**
    158          * WordPress Categories table
    159          *
    160          * @since 1.5.0
    161          * @access public
    162          * @var string
    163          */
    164         var $categories;
    165 
    166         /**
    167          * WordPress Post to Category table
    168          *
    169          * @since 1.5.0
    170          * @access public
    171          * @var string
    172          */
    173         var $post2cat;
    174 
    175         /**
    176          * WordPress Comments table
    177          *
    178          * @since 1.5.0
    179          * @access public
    180          * @var string
    181          */
    182         var $comments;
    183 
    184         /**
    185          * WordPress Links table
    186          *
    187          * @since 1.5.0
    188          * @access public
    189          * @var string
    190          */
    191         var $links;
    192 
    193         /**
    194          * WordPress Options table
    195          *
    196          * @since 1.5.0
    197          * @access public
    198          * @var string
    199          */
    200         var $options;
    201 
    202         /**
    203          * WordPress Post Metadata table
    204          *
    205          * @since {@internal Version Unknown}}
    206          * @access public
    207          * @var string
    208          */
    209         var $postmeta;
    210 
    211         /**
    212          * WordPress Comment Metadata table
    213          *
    214          * @since 2.9
    215          * @access public
    216          * @var string
    217          */
    218         var $commentmeta;
    219 
    220         /**
    221          * WordPress User Metadata table
    222          *
    223          * @since 2.3.0
    224          * @access public
    225          * @var string
    226          */
    227         var $usermeta;
    228 
    229         /**
    230          * WordPress Terms table
    231          *
    232          * @since 2.3.0
    233          * @access public
    234          * @var string
    235          */
    236         var $terms;
    237 
    238         /**
    239          * WordPress Term Taxonomy table
    240          *
    241          * @since 2.3.0
    242          * @access public
    243          * @var string
    244          */
    245         var $term_taxonomy;
    246 
    247         /**
    248          * WordPress Term Relationships table
    249          *
    250          * @since 2.3.0
    251          * @access public
    252          * @var string
    253          */
    254         var $term_relationships;
    255 
    256         /**
    257          * List of WordPress tables
    258          *
    259          * @since {@internal Version Unknown}}
    260          * @access private
    261          * @var array
    262          */
    263         var $tables = array('users', 'usermeta', 'posts', 'categories', 'post2cat', 'comments', 'links', 'link2cat', 'options',
    264                         'postmeta', 'terms', 'term_taxonomy', 'term_relationships', 'commentmeta');
    265 
    266         /**
    267          * List of deprecated WordPress tables
    268          *
    269          * @since 2.9.0
    270          * @access private
    271          * @var array
    272          */
    273         var $old_tables = array('categories', 'post2cat', 'link2cat');
    274 
    275 
    276         /**
    277          * Format specifiers for DB columns. Columns not listed here default to %s.  Initialized in wp-settings.php.
    278          *
    279          * Keys are colmn names, values are format types: 'ID' => '%d'
    280          *
    281          * @since 2.8.0
    282          * @see wpdb:prepare()
    283          * @see wpdb:insert()
    284          * @see wpdb:update()
    285          * @access public
    286          * @war array
    287          */
    288         var $field_types = array();
    289 
    290         /**
    291          * Database table columns charset
    292          *
    293          * @since 2.2.0
    294          * @access public
    295          * @var string
    296          */
    297         var $charset;
    298 
    299         /**
    300          * Database table columns collate
    301          *
    302          * @since 2.2.0
    303          * @access public
    304          * @var string
    305          */
    306         var $collate;
    307 
    308         /**
    309          * Whether to use mysql_real_escape_string
    310          *
    311          * @since 2.8.0
    312          * @access public
    313          * @var bool
    314          */
    315         var $real_escape = false;
    316 
    317         /**
    318          * Database Username
    319          *
    320          * @since 2.9.0
    321          * @access private
    322          * @var string
    323          */
    324         var $dbuser;
    325 
    326         /**
    327          * Connects to the database server and selects a database
    328          *
    329          * PHP4 compatibility layer for calling the PHP5 constructor.
    330          *
    331          * @uses wpdb::__construct() Passes parameters and returns result
    332          * @since 0.71
    333          *
    334          * @param string $dbuser MySQL database user
    335          * @param string $dbpassword MySQL database password
    336          * @param string $dbname MySQL database name
    337          * @param string $dbhost MySQL database host
    338          */
    339         function wpdb($dbuser, $dbpassword, $dbname, $dbhost) {
    340                 return $this->__construct($dbuser, $dbpassword, $dbname, $dbhost);
    341         }
    342 
    343         /**
    344          * Connects to the database server and selects a database
    345          *
    346          * PHP5 style constructor for compatibility with PHP5. Does
    347          * the actual setting up of the class properties and connection
    348          * to the database.
    349          *
    350          * @since 2.0.8
    351          *
    352          * @param string $dbuser MySQL database user
    353          * @param string $dbpassword MySQL database password
    354          * @param string $dbname MySQL database name
    355          * @param string $dbhost MySQL database host
    356          */
    357         function __construct($dbuser, $dbpassword, $dbname, $dbhost) {
    358                 register_shutdown_function(array(&$this, "__destruct"));
    359 
    360                 if ( defined('WP_DEBUG') and WP_DEBUG == true )
    361                         $this->show_errors();
    362 
    363                 if ( defined('DB_CHARSET') )
    364                         $this->charset = DB_CHARSET;
    365 
    366                 if ( defined('DB_COLLATE') )
    367                         $this->collate = DB_COLLATE;
    368 
    369                 $this->dbuser = $dbuser;
    370 
    371                 $this->dbh = @mysql_connect($dbhost, $dbuser, $dbpassword, true);
    372                 if (!$this->dbh) {
    373                         $this->bail(sprintf(/*WP_I18N_DB_CONN_ERROR*/"
    374 <h1>Error establishing a database connection</h1>
    375 <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>
    376 <ul>
    377         <li>Are you sure you have the correct username and password?</li>
    378         <li>Are you sure that you have typed the correct hostname?</li>
    379         <li>Are you sure that the database server is running?</li>
    380 </ul>
    381 <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>
    382 "/*/WP_I18N_DB_CONN_ERROR*/, $dbhost), 'db_connect_fail');
    383                         return;
    384                 }
    385 
    386                 $this->ready = true;
    387 
    388                 if ( $this->has_cap( 'collation' ) ) {
    389                         if ( !empty($this->charset) ) {
    390                                 if ( function_exists('mysql_set_charset') ) {
    391                                         mysql_set_charset($this->charset, $this->dbh);
    392                                         $this->real_escape = true;
    393                                 } else {
    394                                         $collation_query = "SET NAMES '{$this->charset}'";
    395                                         if ( !empty($this->collate) )
    396                                                 $collation_query .= " COLLATE '{$this->collate}'";
    397                                         $this->query($collation_query);
    398                                 }
    399                         }
    400                 }
    401 
    402                 $this->select($dbname);
    403         }
    404 
    405         /**
    406          * PHP5 style destructor and will run when database object is destroyed.
    407          *
    408          * @since 2.0.8
    409          *
    410          * @return bool Always true
    411          */
    412         function __destruct() {
    413                 return true;
    414         }
    415 
    416         /**
    417          * Sets the table prefix for the WordPress tables.
    418          *
    419          * Also allows for the CUSTOM_USER_TABLE and CUSTOM_USER_META_TABLE to
    420          * override the WordPress users and usersmeta tables that would otherwise be determined by the $prefix.
    421          *
    422          * @since 2.5.0
    423          *
    424          * @param string $prefix Alphanumeric name for the new prefix.
    425          * @return string|WP_Error Old prefix or WP_Error on error
    426          */
    427         function set_prefix($prefix) {
    428 
    429                 if ( preg_match('|[^a-z0-9_]|i', $prefix) )
    430                         return new WP_Error('invalid_db_prefix', /*WP_I18N_DB_BAD_PREFIX*/'Invalid database prefix'/*/WP_I18N_DB_BAD_PREFIX*/);
    431 
    432                 $old_prefix = $this->prefix;
    433                 $this->prefix = $prefix;
    434 
    435                 foreach ( (array) $this->tables as $table )
    436                         $this->$table = $this->prefix . $table;
    437 
    438                 if ( defined('CUSTOM_USER_TABLE') )
    439                         $this->users = CUSTOM_USER_TABLE;
    440 
    441                 if ( defined('CUSTOM_USER_META_TABLE') )
    442                         $this->usermeta = CUSTOM_USER_META_TABLE;
    443 
    444                 return $old_prefix;
    445         }
    446 
    447         /**
    448          * Selects a database using the current database connection.
    449          *
    450          * The database name will be changed based on the current database
    451          * connection. On failure, the execution will bail and display an DB error.
    452          *
    453          * @since 0.71
    454          *
    455          * @param string $db MySQL database name
    456          * @return null Always null.
    457          */
    458         function select($db) {
    459                 if (!@mysql_select_db($db, $this->dbh)) {
    460                         $this->ready = false;
    461                         $this->bail(sprintf(/*WP_I18N_DB_SELECT_DB*/'
    462 <h1>Can&#8217;t select database</h1>
    463 <p>We were able to connect to the database server (which means your username and password is okay) but not able to select the <code>%1$s</code> database.</p>
    464 <ul>
    465 <li>Are you sure it exists?</li>
    466 <li>Does the user <code>%2$s</code> have permission to use the <code>%1$s</code> database?</li>
    467 <li>On some systems the name of your database is prefixed with your username, so it would be like <code>username_%1$s</code>. Could that be the problem?</li>
    468 </ul>
    469 <p>If you don\'t know how to setup a database you should <strong>contact your host</strong>. If all else fails you may find help at the <a href="http://wordpress.org/support/">WordPress Support Forums</a>.</p>'/*/WP_I18N_DB_SELECT_DB*/, $db, $this->dbuser), 'db_select_fail');
    470                         return;
    471                 }
    472         }
    473 
    474         function _weak_escape($string) {
    475                 return addslashes($string);
    476         }
    477 
    478         function _real_escape($string) {
    479                 if ( $this->dbh && $this->real_escape )
    480                         return mysql_real_escape_string( $string, $this->dbh );
    481                 else
    482                         return addslashes( $string );
    483         }
    484 
    485         function _escape($data) {
    486                 if ( is_array($data) ) {
    487                         foreach ( (array) $data as $k => $v ) {
    488                                 if ( is_array($v) )
    489                                         $data[$k] = $this->_escape( $v );
    490                                 else
    491                                         $data[$k] = $this->_real_escape( $v );
    492                         }
    493                 } else {
    494                         $data = $this->_real_escape( $data );
    495                 }
    496 
    497                 return $data;
    498         }
    499 
    500         /**
    501          * Escapes content for insertion into the database using addslashes(), for security
    502          *
    503          * @since 0.71
    504          *
    505          * @param string|array $data
    506          * @return string query safe string
    507          */
    508         function escape($data) {
    509                 if ( is_array($data) ) {
    510                         foreach ( (array) $data as $k => $v ) {
    511                                 if ( is_array($v) )
    512                                         $data[$k] = $this->escape( $v );
    513                                 else
    514                                         $data[$k] = $this->_weak_escape( $v );
    515                         }
    516                 } else {
    517                         $data = $this->_weak_escape( $data );
    518                 }
    519 
    520                 return $data;
    521         }
    522 
    523         /**
    524          * Escapes content by reference for insertion into the database, for security
    525          *
    526          * @since 2.3.0
    527          *
    528          * @param string $s
    529          */
    530         function escape_by_ref(&$string) {
    531                 $string = $this->_real_escape( $string );
    532         }
    533 
    534         /**
    535          * Prepares a SQL query for safe execution.  Uses sprintf()-like syntax.
    536          *
    537          * This function only supports a small subset of the sprintf syntax; it only supports %d (decimal number), %s (string).
    538          * Does not support sign, padding, alignment, width or precision specifiers.
    539          * Does not support argument numbering/swapping.
    540          *
    541          * May be called like {@link http://php.net/sprintf sprintf()} or like {@link http://php.net/vsprintf vsprintf()}.
    542          *
    543          * Both %d and %s should be left unquoted in the query string.
    544          *
    545          * <code>
    546          * wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", "foo", 1337 )
    547          * </code>
    548          *
    549          * @link http://php.net/sprintf Description of syntax.
    550          * @since 2.3.0
    551          *
    552          * @param string $query Query statement with sprintf()-like placeholders
    553          * @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()}.
    554          * @param mixed $args,... further variables to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}.
    555          * @return null|string Sanitized query string
    556          */
    557         function prepare($query = null) { // ( $query, *$args )
    558                 if ( is_null( $query ) )
    559                         return;
    560                 $args = func_get_args();
    561                 array_shift($args);
    562                 // If args were passed as an array (as in vsprintf), move them up
    563                 if ( isset($args[0]) && is_array($args[0]) )
    564                         $args = $args[0];
    565                 $query = str_replace("'%s'", '%s', $query); // in case someone mistakenly already singlequoted it
    566                 $query = str_replace('"%s"', '%s', $query); // doublequote unquoting
    567                 $query = str_replace('%s', "'%s'", $query); // quote the strings
    568                 array_walk($args, array(&$this, 'escape_by_ref'));
    569                 return @vsprintf($query, $args);
    570         }
    571 
    572         /**
    573          * Print SQL/DB error.
    574          *
    575          * @since 0.71
    576          * @global array $EZSQL_ERROR Stores error information of query and error string
    577          *
    578          * @param string $str The error to display
    579          * @return bool False if the showing of errors is disabled.
    580          */
    581         function print_error($str = '') {
    582                 global $EZSQL_ERROR;
    583 
    584                 if (!$str) $str = mysql_error($this->dbh);
    585                 $EZSQL_ERROR[] = array ('query' => $this->last_query, 'error_str' => $str);
    586 
    587                 if ( $this->suppress_errors )
    588                         return false;
    589 
    590                 if ( $caller = $this->get_caller() )
    591                         $error_str = sprintf(/*WP_I18N_DB_QUERY_ERROR_FULL*/'WordPress database error %1$s for query %2$s made by %3$s'/*/WP_I18N_DB_QUERY_ERROR_FULL*/, $str, $this->last_query, $caller);
    592                 else
    593                         $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);
    594 
    595                 $log_error = true;
    596                 if ( ! function_exists('error_log') )
    597                         $log_error = false;
    598 
    599                 $log_file = @ini_get('error_log');
    600                 if ( !empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file) )
    601                         $log_error = false;
    602 
    603                 if ( $log_error )
    604                         @error_log($error_str, 0);
    605 
    606                 // Is error output turned on or not..
    607                 if ( !$this->show_errors )
    608                         return false;
    609 
    610                 $str = htmlspecialchars($str, ENT_QUOTES);
    611                 $query = htmlspecialchars($this->last_query, ENT_QUOTES);
    612 
    613                 // If there is an error then take note of it
    614                 print "<div id='error'>
    615                 <p class='wpdberror'><strong>WordPress database error:</strong> [$str]<br />
    616                 <code>$query</code></p>
    617                 </div>";
    618         }
    619 
    620         /**
    621          * Enables showing of database errors.
    622          *
    623          * This function should be used only to enable showing of errors.
    624          * wpdb::hide_errors() should be used instead for hiding of errors. However,
    625          * this function can be used to enable and disable showing of database
    626          * errors.
    627          *
    628          * @since 0.71
    629          *
    630          * @param bool $show Whether to show or hide errors
    631          * @return bool Old value for showing errors.
    632          */
    633         function show_errors( $show = true ) {
    634                 $errors = $this->show_errors;
    635                 $this->show_errors = $show;
    636                 return $errors;
    637         }
    638 
    639         /**
    640          * Disables showing of database errors.
    641          *
    642          * @since 0.71
    643          *
    644          * @return bool Whether showing of errors was active or not
    645          */
    646         function hide_errors() {
    647                 $show = $this->show_errors;
    648                 $this->show_errors = false;
    649                 return $show;
    650         }
    651 
    652         /**
    653          * Whether to suppress database errors.
    654          *
    655          * @param unknown_type $suppress
    656          * @return unknown
    657          */
    658         function suppress_errors( $suppress = true ) {
    659                 $errors = $this->suppress_errors;
    660                 $this->suppress_errors = $suppress;
    661                 return $errors;
    662         }
    663 
    664         /**
    665          * Kill cached query results.
    666          *
    667          * @since 0.71
    668          */
    669         function flush() {
    670                 $this->last_result = array();
    671                 $this->col_info = null;
    672                 $this->last_query = null;
    673         }
    674 
    675         /**
    676          * Perform a MySQL database query, using current database connection.
    677          *
    678          * More information can be found on the codex page.
    679          *
    680          * @since 0.71
    681          *
    682          * @param string $query
    683          * @return int|false Number of rows affected/selected or false on error
    684          */
    685         function query($query) {
    686                 if ( ! $this->ready )
    687                         return false;
    688 
    689                 // filter the query, if filters are available
    690                 // NOTE: some queries are made before the plugins have been loaded, and thus cannot be filtered with this method
    691                 if ( function_exists('apply_filters') )
    692                         $query = apply_filters('query', $query);
    693 
    694                 // initialise return
    695                 $return_val = 0;
    696                 $this->flush();
    697 
    698                 // Log how the function was called
    699                 $this->func_call = "\$db->query(\"$query\")";
    700 
    701                 // Keep track of the last query for debug..
    702                 $this->last_query = $query;
    703 
    704                 // Perform the query via std mysql_query function..
    705                 if ( defined('SAVEQUERIES') && SAVEQUERIES )
    706                         $this->timer_start();
    707 
    708                 $this->result = @mysql_query($query, $this->dbh);
    709                 ++$this->num_queries;
    710 
    711                 if ( defined('SAVEQUERIES') && SAVEQUERIES )
    712                         $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
    713 
    714                 // If there is an error then take note of it..
    715                 if ( $this->last_error = mysql_error($this->dbh) ) {
    716                         $this->print_error();
    717                         return false;
    718                 }
    719 
    720                 if ( preg_match("/^\\s*(insert|delete|update|replace|alter) /i",$query) ) {
    721                         $this->rows_affected = mysql_affected_rows($this->dbh);
    722                         // Take note of the insert_id
    723                         if ( preg_match("/^\\s*(insert|replace) /i",$query) ) {
    724                                 $this->insert_id = mysql_insert_id($this->dbh);
    725                         }
    726                         // Return number of rows affected
    727                         $return_val = $this->rows_affected;
    728                 } else {
    729                         $i = 0;
    730                         while ($i < @mysql_num_fields($this->result)) {
    731                                 $this->col_info[$i] = @mysql_fetch_field($this->result);
    732                                 $i++;
    733                         }
    734                         $num_rows = 0;
    735                         while ( $row = @mysql_fetch_object($this->result) ) {
    736                                 $this->last_result[$num_rows] = $row;
    737                                 $num_rows++;
    738                         }
    739 
    740                         @mysql_free_result($this->result);
    741 
    742                         // Log number of rows the query returned
    743                         $this->num_rows = $num_rows;
    744 
    745                         // Return number of rows selected
    746                         $return_val = $this->num_rows;
    747                 }
    748 
    749                 return $return_val;
    750         }
    751 
    752         /**
    753          * Insert a row into a table.
    754          *
    755          * <code>
    756          * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
    757          * </code>
    758          *
    759          * @since 2.5.0
    760          * @see wpdb::prepare()
    761          *
    762          * @param string $table table name
    763          * @param array $data Data to insert (in column => value pairs).  Both $data columns and $data values should be "raw" (neither should be SQL escaped).
    764          * @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.
    765          * @return int|false The number of rows inserted, or false on error.
    766          */
    767         function insert($table, $data, $format = null) {
    768                 $formats = $format = (array) $format;
    769                 $fields = array_keys($data);
    770                 $formatted_fields = array();
    771                 foreach ( $fields as $field ) {
    772                         if ( !empty($format) )
    773                                 $form = ( $form = array_shift($formats) ) ? $form : $format[0];
    774                         elseif ( isset($this->field_types[$field]) )
    775                                 $form = $this->field_types[$field];
    776                         else
    777                                 $form = '%s';
    778                         $formatted_fields[] = $form;
    779                 }
    780                 $sql = "INSERT INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES ('" . implode( "','", $formatted_fields ) . "')";
    781                 return $this->query( $this->prepare( $sql, $data) );
    782         }
    783 
    784 
    785         /**
    786          * Update a row in the table
    787          *
    788          * <code>
    789          * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) )
    790          * </code>
    791          *
    792          * @since 2.5.0
    793          * @see wpdb::prepare()
    794          *
    795          * @param string $table table name
    796          * @param array $data Data to update (in column => value pairs).  Both $data columns and $data values should be "raw" (neither should be SQL escaped).
    797          * @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".
    798          * @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.
    799          * @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.
    800          * @return int|false The number of rows updated, or false on error.
    801          */
    802         function update($table, $data, $where, $format = null, $where_format = null) {
    803                 if ( !is_array( $where ) )
    804                         return false;
    805 
    806                 $formats = $format = (array) $format;
    807                 $bits = $wheres = array();
    808                 foreach ( (array) array_keys($data) as $field ) {
    809                         if ( !empty($format) )
    810                                 $form = ( $form = array_shift($formats) ) ? $form : $format[0];
    811                         elseif ( isset($this->field_types[$field]) )
    812                                 $form = $this->field_types[$field];
    813                         else
    814                                 $form = '%s';
    815                         $bits[] = "`$field` = {$form}";
    816                 }
    817 
    818                 $where_formats = $where_format = (array) $where_format;
    819                 foreach ( (array) array_keys($where) as $field ) {
    820                         if ( !empty($where_format) )
    821                                 $form = ( $form = array_shift($where_formats) ) ? $form : $where_format[0];
    822                         elseif ( isset($this->field_types[$field]) )
    823                                 $form = $this->field_types[$field];
    824                         else
    825                                 $form = '%s';
    826                         $wheres[] = "`$field` = {$form}";
    827                 }
    828 
    829                 $sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres );
    830                 return $this->query( $this->prepare( $sql, array_merge(array_values($data), array_values($where))) );
    831         }
    832 
    833         /**
    834          * Retrieve one variable from the database.
    835          *
    836          * Executes a SQL query and returns the value from the SQL result.
    837          * If the SQL result contains more than one column and/or more than one row, this function returns the value in the column and row specified.
    838          * If $query is null, this function returns the value in the specified column and row from the previous SQL result.
    839          *
    840          * @since 0.71
    841          *
    842          * @param string|null $query SQL query.  If null, use the result from the previous query.
    843          * @param int $x (optional) Column of value to return.  Indexed from 0.
    844          * @param int $y (optional) Row of value to return.  Indexed from 0.
    845          * @return string Database query result
    846          */
    847         function get_var($query=null, $x = 0, $y = 0) {
    848                 $this->func_call = "\$db->get_var(\"$query\",$x,$y)";
    849                 if ( $query )
    850                         $this->query($query);
    851 
    852                 // Extract var out of cached results based x,y vals
    853                 if ( !empty( $this->last_result[$y] ) ) {
    854                         $values = array_values(get_object_vars($this->last_result[$y]));
    855                 }
    856 
    857                 // If there is a value return it else return null
    858                 return (isset($values[$x]) && $values[$x]!=='') ? $values[$x] : null;
    859         }
    860 
    861         /**
    862          * Retrieve one row from the database.
    863          *
    864          * Executes a SQL query and returns the row from the SQL result.
    865          *
    866          * @since 0.71
    867          *
    868          * @param string|null $query SQL query.
    869          * @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.
    870          * @param int $y (optional) Row to return.  Indexed from 0.
    871          * @return mixed Database query result in format specifed by $output
    872          */
    873         function get_row($query = null, $output = OBJECT, $y = 0) {
    874                 $this->func_call = "\$db->get_row(\"$query\",$output,$y)";
    875                 if ( $query )
    876                         $this->query($query);
    877                 else
    878                         return null;
    879 
    880                 if ( !isset($this->last_result[$y]) )
    881                         return null;
    882 
    883                 if ( $output == OBJECT ) {
    884                         return $this->last_result[$y] ? $this->last_result[$y] : null;
    885                 } elseif ( $output == ARRAY_A ) {
    886                         return $this->last_result[$y] ? get_object_vars($this->last_result[$y]) : null;
    887                 } elseif ( $output == ARRAY_N ) {
    888                         return $this->last_result[$y] ? array_values(get_object_vars($this->last_result[$y])) : null;
    889                 } else {
    890                         $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*/);
    891                 }
    892         }
    893 
    894         /**
    895          * Retrieve one column from the database.
    896          *
    897          * Executes a SQL query and returns the column from the SQL result.
    898          * If the SQL result contains more than one column, this function returns the column specified.
    899          * If $query is null, this function returns the specified column from the previous SQL result.
    900          *
    901          * @since 0.71
    902          *
    903          * @param string|null $query SQL query.  If null, use the result from the previous query.
    904          * @param int $x Column to return.  Indexed from 0.
    905          * @return array Database query result.  Array indexed from 0 by SQL result row number.
    906          */
    907         function get_col($query = null , $x = 0) {
    908                 if ( $query )
    909                         $this->query($query);
    910 
    911                 $new_array = array();
    912                 // Extract the column values
    913                 for ( $i=0; $i < count($this->last_result); $i++ ) {
    914                         $new_array[$i] = $this->get_var(null, $x, $i);
    915                 }
    916                 return $new_array;
    917         }
    918 
    919         /**
    920          * Retrieve an entire SQL result set from the database (i.e., many rows)
    921          *
    922          * Executes a SQL query and returns the entire SQL result.
    923          *
    924          * @since 0.71
    925          *
    926          * @param string $query SQL query.
    927          * @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.
    928          * @return mixed Database query results
    929          */
    930         function get_results($query = null, $output = OBJECT) {
    931                 $this->func_call = "\$db->get_results(\"$query\", $output)";
    932 
    933                 if ( $query )
    934                         $this->query($query);
    935                 else
    936                         return null;
    937 
    938                 if ( $output == OBJECT ) {
    939                         // Return an integer-keyed array of row objects
    940                         return $this->last_result;
    941                 } elseif ( $output == OBJECT_K ) {
    942                         // Return an array of row objects with keys from column 1
    943                         // (Duplicates are discarded)
    944                         foreach ( $this->last_result as $row ) {
    945                                 $key = array_shift( get_object_vars( $row ) );
    946                                 if ( !isset( $new_array[ $key ] ) )
    947                                         $new_array[ $key ] = $row;
    948                         }
    949                         return $new_array;
    950                 } elseif ( $output == ARRAY_A || $output == ARRAY_N ) {
    951                         // Return an integer-keyed array of...
    952                         if ( $this->last_result ) {
    953                                 $i = 0;
    954                                 foreach( (array) $this->last_result as $row ) {
    955                                         if ( $output == ARRAY_N ) {
    956                                                 // ...integer-keyed row arrays
    957                                                 $new_array[$i] = array_values( get_object_vars( $row ) );
    958                                         } else {
    959                                                 // ...column name-keyed row arrays
    960                                                 $new_array[$i] = get_object_vars( $row );
    961                                         }
    962                                         ++$i;
    963                                 }
    964                                 return $new_array;
    965                         }
    966                 }
    967         }
    968 
    969         /**
    970          * Retrieve column metadata from the last query.
    971          *
    972          * @since 0.71
    973          *
    974          * @param string $info_type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill
    975          * @param int $col_offset 0: col name. 1: which table the col's in. 2: col's max length. 3: if the col is numeric. 4: col's type
    976          * @return mixed Column Results
    977          */
    978         function get_col_info($info_type = 'name', $col_offset = -1) {
    979                 if ( $this->col_info ) {
    980                         if ( $col_offset == -1 ) {
    981                                 $i = 0;
    982                                 foreach( (array) $this->col_info as $col ) {
    983                                         $new_array[$i] = $col->{$info_type};
    984                                         $i++;
    985                                 }
    986                                 return $new_array;
    987                         } else {
    988                                 return $this->col_info[$col_offset]->{$info_type};
    989                         }
    990                 }
    991         }
    992 
    993         /**
    994          * Starts the timer, for debugging purposes.
    995          *
    996          * @since 1.5.0
    997          *
    998          * @return true
    999          */
    1000         function timer_start() {
    1001                 $mtime = microtime();
    1002                 $mtime = explode(' ', $mtime);
    1003                 $this->time_start = $mtime[1] + $mtime[0];
    1004                 return true;
    1005         }
    1006 
    1007         /**
    1008          * Stops the debugging timer.
    1009          *
    1010          * @since 1.5.0
    1011          *
    1012          * @return int Total time spent on the query, in milliseconds
    1013          */
    1014         function timer_stop() {
    1015                 $mtime = microtime();
    1016                 $mtime = explode(' ', $mtime);
    1017                 $time_end = $mtime[1] + $mtime[0];
    1018                 $time_total = $time_end - $this->time_start;
    1019                 return $time_total;
    1020         }
    1021 
    1022         /**
    1023          * Wraps errors in a nice header and footer and dies.
    1024          *
    1025          * Will not die if wpdb::$show_errors is true
    1026          *
    1027          * @since 1.5.0
    1028          *
    1029          * @param string $message The Error message
    1030          * @param string $error_code (optional) A Computer readable string to identify the error.
    1031          * @return false|void
    1032          */
    1033         function bail($message, $error_code = '500') {
    1034                 if ( !$this->show_errors ) {
    1035                         if ( class_exists('WP_Error') )
    1036                                 $this->error = new WP_Error($error_code, $message);
    1037                         else
    1038                                 $this->error = $message;
    1039                         return false;
    1040                 }
    1041                 wp_die($message);
    1042         }
    1043 
    1044         /**
    1045          * Whether or not MySQL database is at least the required minimum version.
    1046          *
    1047          * @since 2.5.0
    1048          * @uses $wp_version
    1049          *
    1050          * @return WP_Error
    1051          */
    1052         function check_database_version()
    1053         {
    1054                 global $wp_version;
    1055                 // Make sure the server has MySQL 4.0
    1056                 if ( version_compare($this->db_version(), '4.0.0', '<') )
    1057                         return new WP_Error('database_version',sprintf(__('<strong>ERROR</strong>: WordPress %s requires MySQL 4.0.0 or higher'), $wp_version));
    1058         }
    1059 
    1060         /**
    1061          * Whether of not the database supports collation.
    1062          *
    1063          * Called when WordPress is generating the table scheme.
    1064          *
    1065          * @since 2.5.0
    1066          *
    1067          * @return bool True if collation is supported, false if version does not
    1068          */
    1069         function supports_collation() {
    1070                 return $this->has_cap( 'collation' );
    1071         }
    1072 
    1073         /**
    1074          * Generic function to determine if a database supports a particular feature
    1075          * @param string $db_cap the feature
    1076          * @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.
    1077          * @return bool
    1078          */
    1079         function has_cap( $db_cap ) {
    1080                 $version = $this->db_version();
    1081 
    1082                 switch ( strtolower( $db_cap ) ) :
    1083                 case 'collation' :    // @since 2.5.0
    1084                 case 'group_concat' : // @since 2.7
    1085                 case 'subqueries' :   // @since 2.7
    1086                         return version_compare($version, '4.1', '>=');
    1087                         break;
    1088                 endswitch;
    1089 
    1090                 return false;
    1091         }
    1092 
    1093         /**
    1094          * Retrieve the name of the function that called wpdb.
    1095          *
    1096          * Requires PHP 4.3 and searches up the list of functions until it reaches
    1097          * the one that would most logically had called this method.
    1098          *
    1099          * @since 2.5.0
    1100          *
    1101          * @return string The name of the calling function
    1102          */
    1103         function get_caller() {
    1104                 // requires PHP 4.3+
    1105                 if ( !is_callable('debug_backtrace') )
    1106                         return '';
    1107 
    1108                 $bt = debug_backtrace();
    1109                 $caller = array();
    1110 
    1111                 $bt = array_reverse( $bt );
    1112                 foreach ( (array) $bt as $call ) {
    1113                         if ( @$call['class'] == __CLASS__ )
    1114                                 continue;
    1115                         $function = $call['function'];
    1116                         if ( isset( $call['class'] ) )
    1117                                 $function = $call['class'] . "->$function";
    1118                         $caller[] = $function;
    1119                 }
    1120                 $caller = join( ', ', $caller );
    1121 
    1122                 return $caller;
    1123         }
    1124 
    1125         /**
    1126          * The database version number
    1127          * @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.
    1128          * @return false|string false on failure, version number on success
    1129          */
    1130         function db_version() {
    1131                 return preg_replace('/[^0-9.].*/', '', mysql_get_server_info( $this->dbh ));
    1132         }
    1133 }
    1134 
    1135 if ( ! isset($wpdb) ) {
    1136         /**
    1137          * WordPress Database Object, if it isn't set already in wp-content/db.php
    1138          * @global object $wpdb Creates a new wpdb object based on wp-config.php Constants for the database
    1139          * @since 0.71
    1140          */
     11        * WordPress Database Object, if it isn't set already in wp-content/db.php
     12        * @global object $wpdb Creates a new wpdb object based on wp-config.php Constants for the database
     13        * @since 0.71
     14        */
    114115        $wpdb = new wpdb(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
    114216}
    1143 ?>
  • wp-includes/wp-db/mssql/mssql.php

     
     1<?php
     2/**
     3 * WordPress DB Class
     4 *
     5 * Original code from {@link http://php.justinvincent.com Justin Vincent (justin@visunet.ie)}
     6 *
     7 * Modifications for MSSQL by A.Garcia and A.Gentile
     8 *
     9 * @package WordPress
     10 * @subpackage Database
     11 * @since 0.71
     12 */
     13
     14/**
     15 * @since 0.71
     16 */
     17define('EZSQL_VERSION', 'WP1.25');
     18
     19/**
     20 * @since 0.71
     21 */
     22define('OBJECT', 'OBJECT', true);
     23
     24/**
     25 * @since {@internal Version Unknown}}
     26 */
     27define('OBJECT_K', 'OBJECT_K', false);
     28
     29/**
     30 * @since 0.71
     31 */
     32define('ARRAY_A', 'ARRAY_A', false);
     33
     34/**
     35 * @since 0.71
     36 */
     37define('ARRAY_N', 'ARRAY_N', false);
     38
     39require_once 'translations/translations.php';
     40
     41/**
     42 * WordPress Database Access Abstraction Object
     43 *
     44 * It is possible to replace this class with your own
     45 * by setting the $wpdb global variable in wp-content/db.php
     46 * file with your class. You can name it wpdb also, since
     47 * this file will not be included, if the other file is
     48 * available.
     49 *
     50 * @link http://codex.wordpress.org/Function_Reference/wpdb_Class
     51 *
     52 * @package WordPress
     53 * @subpackage Database
     54 * @since 0.71
     55 * @final
     56 */
     57class wpdb extends SQL_Translations {
     58
     59        /**
     60         * Whether to show SQL/DB errors
     61         *
     62         * @since 0.71
     63         * @access private
     64         * @var bool
     65         */
     66        var $show_errors = true;
     67
     68        /**
     69         * Whether to suppress errors during the DB bootstrapping.
     70         *
     71         * @access private
     72         * @since {@internal Version Unknown}}
     73         * @var bool
     74         */
     75        var $suppress_errors = false;
     76
     77        /**
     78         * The last error during query.
     79         *
     80         * @since {@internal Version Unknown}}
     81         * @var string
     82         */
     83        var $last_error = '';
     84
     85        /**
     86         * Amount of queries made
     87         *
     88         * @since 1.2.0
     89         * @access private
     90         * @var int
     91         */
     92        var $num_queries = 0;
     93
     94        /**
     95         * Saved result of the last query made
     96         *
     97         * @since 1.2.0
     98         * @access private
     99         * @var array
     100         */
     101        var $last_query;
     102
     103        /**
     104         * Saved result of the last translated query made
     105         *
     106         * @since 1.2.0
     107         * @access private
     108         * @var array
     109         */
     110        var $previous_query;
     111
     112        /**
     113         * Saved info on the table column
     114         *
     115         * @since 1.2.0
     116         * @access private
     117         * @var array
     118         */
     119        var $col_info;
     120
     121        /**
     122         * Saved queries that were executed
     123         *
     124         * @since 1.5.0
     125         * @access private
     126         * @var array
     127         */
     128        var $queries;
     129
     130        /**
     131         * WordPress table prefix
     132         *
     133         * You can set this to have multiple WordPress installations
     134         * in a single database. The second reason is for possible
     135         * security precautions.
     136         *
     137         * @since 0.71
     138         * @access private
     139         * @var string
     140         */
     141        var $prefix = '';
     142
     143        /**
     144         * Whether the database queries are ready to start executing.
     145         *
     146         * @since 2.5.0
     147         * @access private
     148         * @var bool
     149         */
     150        var $ready = false;
     151
     152        /**
     153         * WordPress Posts table
     154         *
     155         * @since 1.5.0
     156         * @access public
     157         * @var string
     158         */
     159        var $posts;
     160
     161        /**
     162         * WordPress Users table
     163         *
     164         * @since 1.5.0
     165         * @access public
     166         * @var string
     167         */
     168        var $users;
     169
     170        /**
     171         * WordPress Categories table
     172         *
     173         * @since 1.5.0
     174         * @access public
     175         * @var string
     176         */
     177        var $categories;
     178
     179        /**
     180         * WordPress Post to Category table
     181         *
     182         * @since 1.5.0
     183         * @access public
     184         * @var string
     185         */
     186        var $post2cat;
     187
     188        /**
     189         * WordPress Comments table
     190         *
     191         * @since 1.5.0
     192         * @access public
     193         * @var string
     194         */
     195        var $comments;
     196
     197        /**
     198         * WordPress Links table
     199         *
     200         * @since 1.5.0
     201         * @access public
     202         * @var string
     203         */
     204        var $links;
     205
     206        /**
     207         * WordPress Options table
     208         *
     209         * @since 1.5.0
     210         * @access public
     211         * @var string
     212         */
     213        var $options;
     214
     215        /**
     216         * WordPress Post Metadata table
     217         *
     218         * @since {@internal Version Unknown}}
     219         * @access public
     220         * @var string
     221         */
     222        var $postmeta;
     223
     224        /**
     225         * WordPress User Metadata table
     226         *
     227         * @since 2.3.0
     228         * @access public
     229         * @var string
     230         */
     231        var $usermeta;
     232
     233        /**
     234         * WordPress Terms table
     235         *
     236         * @since 2.3.0
     237         * @access public
     238         * @var string
     239         */
     240        var $terms;
     241
     242        /**
     243         * WordPress Term Taxonomy table
     244         *
     245         * @since 2.3.0
     246         * @access public
     247         * @var string
     248         */
     249        var $term_taxonomy;
     250
     251        /**
     252         * WordPress Term Relationships table
     253         *
     254         * @since 2.3.0
     255         * @access public
     256         * @var string
     257         */
     258        var $term_relationships;
     259
     260        /**
     261         * List of WordPress tables
     262         *
     263         * @since {@internal Version Unknown}}
     264         * @access private
     265         * @var array
     266         */
     267        var $tables = array('users', 'usermeta', 'posts', 'categories', 'post2cat', 'comments', 'links', 'link2cat', 'options',
     268                        'postmeta', 'terms', 'term_taxonomy', 'term_relationships');
     269
     270        /**
     271         * Format specifiers for DB columns. Columns not listed here default to %s.  Initialized in wp-settings.php.
     272         *
     273         * Keys are colmn names, values are format types: 'ID' => '%d'
     274         *
     275         * @since 2.8.0
     276         * @see wpdb:prepare()
     277         * @see wpdb:insert()
     278         * @see wpdb:update()
     279         * @access public
     280         * @war array
     281         */
     282        var $field_types = array();
     283
     284        /**
     285         * Database table columns charset
     286         *
     287         * @since 2.2.0
     288         * @access public
     289         * @var string
     290         */
     291        var $charset;
     292
     293        /**
     294         * Database table columns collate
     295         *
     296         * @since 2.2.0
     297         * @access public
     298         * @var string
     299         */
     300        var $collate;
     301
     302        /**
     303         * Whether to use mysql_real_escape_string
     304         *
     305         * @since 2.8.0
     306         * @access public
     307         * @var bool
     308         */
     309        var $real_escape = false;
     310
     311        /**
     312        * Database type
     313        * @access public
     314        * @var string
     315        */
     316        var $db_type;
     317
     318        /**
     319         * Connects to the database server and selects a database
     320         *
     321         * PHP4 compatibility layer for calling the PHP5 constructor.
     322         *
     323         * @uses wpdb::__construct() Passes parameters and returns result
     324         * @since 0.71
     325         *
     326         * @param string $dbtype database type
     327         * @param string $dbuser database user
     328         * @param string $dbpassword database password
     329         * @param string $dbname database name
     330         * @param string $dbhost database host
     331         */
     332        function wpdb($dbuser, $dbpassword, $dbname, $dbhost) {
     333                return $this->__construct($dbuser, $dbpassword, $dbname, $dbhost);
     334        }
     335
     336        /**
     337         * Connects to the database server and selects a database
     338         *
     339         * PHP5 style constructor for compatibility with PHP5. Does
     340         * the actual setting up of the class properties and connection
     341         * to the database.
     342         *
     343         * @since 2.0.8
     344         *
     345         * @param string $dbtype database type
     346         * @param string $dbuser database user
     347         * @param string $dbpassword database password
     348         * @param string $dbname database name
     349         * @param string $dbhost database host
     350         */
     351        function __construct($dbuser, $dbpassword, $dbname, $dbhost) {
     352                register_shutdown_function(array(&$this, "__destruct"));
     353
     354                if ( defined('WP_DEBUG') and WP_DEBUG == true ) {
     355                        $this->show_errors();
     356                }
     357
     358                if ( defined('DB_CHARSET') ) {
     359                        $this->charset = DB_CHARSET;
     360                }
     361
     362                if ( defined('DB_COLLATE') ) {
     363                        $this->collate = DB_COLLATE;
     364                }
     365                parent::__construct();
     366
     367                $this->db_type = DB_TYPE;
     368
     369                // Make sure the version is the same for your ntwdblib.dll.
     370                // The TDS library and the ntwdblib.dll can't be speaking two different protocols.
     371                putenv("TDSVER=70");
     372
     373                // Set text limit sizes to max BEFORE connection is made
     374                ini_set('mssql.textlimit', 2147483647);
     375                ini_set('mssql.textsize', 2147483647);
     376
     377                if (get_magic_quotes_gpc()) {
     378                        $dbhost = trim(str_replace("\\\\", "\\", $dbhost));
     379                }
     380
     381                $this->dbh = mssql_connect($dbhost, $dbuser, $dbpassword);
     382                mssql_min_error_severity(0);
     383                mssql_min_message_severity(17);
     384
     385                if (!$this->dbh) {
     386                        $this->bail(sprintf(/*WP_I18N_DB_CONN_ERROR*/"
     387        <h1>Error establishing a database connection</h1>
     388        <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>
     389        <ul>
     390        <li>Are you sure you have the correct username and password?</li>
     391        <li>Are you sure that you have typed the correct hostname?</li>
     392        <li>Are you sure that the database server is running?</li>
     393        </ul>
     394        <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>
     395        "/*/WP_I18N_DB_CONN_ERROR*/, $dbhost));
     396                        return;
     397                }
     398
     399                $this->ready = true;
     400
     401                // Make sure textsize fields are set to max.
     402                @mssql_query('SET TEXTSIZE 2147483647');
     403                /* SET NAMES doesn't translate
     404                if ( $this->supports_collation() ) {
     405                        $collation_query = '';
     406                        if ( !empty($this->charset) ) {
     407                                $collation_query = "SET NAMES '{$this->charset}'";
     408                                if (!empty($this->collate) )
     409                                        $collation_query .= " COLLATE '{$this->collate}'";
     410                        }
     411
     412                        if ( !empty($collation_query) )
     413                                $this->query($collation_query);
     414
     415                }
     416                */
     417                $this->select($dbname);
     418        }
     419
     420        /**
     421         * PHP5 style destructor and will run when database object is destroyed.
     422         *
     423         * @since 2.0.8
     424         *
     425         * @return bool Always true
     426         */
     427        function __destruct() {
     428                return true;
     429        }
     430
     431        /**
     432         * Sets the table prefix for the WordPress tables.
     433         *
     434         * Also allows for the CUSTOM_USER_TABLE and CUSTOM_USER_META_TABLE to
     435         * override the WordPress users and usersmeta tables that would otherwise be determined by the $prefix.
     436         *
     437         * @since 2.5.0
     438         *
     439         * @param string $prefix Alphanumeric name for the new prefix.
     440         * @return string|WP_Error Old prefix or WP_Error on error
     441         */
     442        function set_prefix($prefix) {
     443
     444                if ( preg_match('|[^a-z0-9_]|i', $prefix) ) {
     445                        return new WP_Error('invalid_db_prefix', /*WP_I18N_DB_BAD_PREFIX*/'Invalid database prefix'/*/WP_I18N_DB_BAD_PREFIX*/);
     446                }
     447
     448                $old_prefix = $this->prefix;
     449                $this->prefix = $prefix;
     450
     451                foreach ( (array) $this->tables as $table ) {
     452                        $this->$table = $this->prefix . $table;
     453                }
     454
     455                if ( defined('CUSTOM_USER_TABLE') ) {
     456                        $this->users = CUSTOM_USER_TABLE;
     457                }
     458
     459                if ( defined('CUSTOM_USER_META_TABLE') ) {
     460                        $this->usermeta = CUSTOM_USER_META_TABLE;
     461                }
     462
     463                return $old_prefix;
     464        }
     465
     466        /**
     467         * Selects a database using the current database connection.
     468         *
     469         * The database name will be changed based on the current database
     470         * connection. On failure, the execution will bail and display an DB error.
     471         *
     472         * @since 0.71
     473         *
     474         * @param string $db database name
     475         * @return null Always null.
     476         */
     477        function select($db) {
     478                $result = false;
     479                $result = mssql_select_db($db, $this->dbh);
     480
     481                if (!$result) {
     482                        $this->ready = false;
     483                        $this->bail(sprintf(/*WP_I18N_DB_SELECT_DB*/'
     484        <h1>Can&#8217;t select database</h1>
     485        <p>We were able to connect to the database server (which means your username and password is okay) but not able to select the <code>%1$s</code> database.</p>
     486        <ul>
     487        <li>Are you sure it exists?</li>
     488        <li>Does the user <code>%2$s</code> have permission to use the <code>%1$s</code> database?</li>
     489        <li>On some systems the name of your database is prefixed with your username, so it would be like username_wordpress. Could that be the problem?</li>
     490        </ul>
     491        <p>If you don\'t know how to setup a database you should <strong>contact your host</strong>. If all else fails you may find help at the <a href="http://wordpress.org/support/">WordPress Support Forums</a>.</p>'/*/WP_I18N_DB_SELECT_DB*/, $db, DB_USER));
     492                        return;
     493                }
     494        }
     495
     496        /**
     497         * Escapes content for insertion into the database, for security
     498         *
     499         * @since 0.71
     500         *
     501         * @param string $string
     502         * @return string query safe string
     503         */
     504        function escape($string) {
     505                return str_replace("'", "''", $string);
     506        }
     507
     508        /**
     509         * Escapes content by reference for insertion into the database, for security
     510         *
     511         * @since 2.3.0
     512         *
     513         * @param string $s
     514         */
     515        function escape_by_ref(&$s) {
     516                $s = $this->escape($s);
     517        }
     518
     519        /**
     520         * Prepares a SQL query for safe use, using sprintf() syntax.
     521         *
     522         * @link http://php.net/sprintf See for syntax to use for query string.
     523         * @since 2.3.0
     524         *
     525         * @param null|string $args If string, first parameter must be query statement
     526         * @param mixed $args,... If additional parameters, they will be set inserted into the query.
     527         * @return null|string Sanitized query string
     528         */
     529        function prepare($query = null) {
     530                if ( is_null( $query ) ) {
     531                        return;
     532                }
     533                $this->prepare_args = func_get_args();
     534                array_shift($this->prepare_args);
     535                // If args were passed as an array (as in vsprintf), move them up
     536                if ( isset($this->prepare_args[0]) && is_array($this->prepare_args[0]) ) {
     537                        $this->prepare_args = $this->prepare_args[0];
     538                }
     539                $flag = '--PREPARE';
     540                foreach($this->prepare_args as $key => $arg){
     541                        if ($key !== 0 && is_serialized($arg)) {
     542                                $flag = '--SERIALIZED';
     543                        }
     544                }
     545                $query = str_replace("'%s'", '%s', $query); // in case someone mistakenly already singlequoted it
     546                $query = str_replace('"%s"', '%s', $query); // doublequote unquoting
     547                $query = str_replace('%s', "'%s'", $query); // quote the strings
     548                array_walk($this->prepare_args, array(&$this, 'escape_by_ref'));
     549                return @vsprintf($query, $this->prepare_args).$flag;
     550        }
     551
     552        /**
     553         * Print SQL/DB error.
     554         *
     555         * @since 0.71
     556         * @global array $EZSQL_ERROR Stores error information of query and error string
     557         *
     558         * @param string $str The error to display
     559         * @return bool False if the showing of errors is disabled.
     560         */
     561        function print_error($str = '') {
     562                global $EZSQL_ERROR;
     563
     564                if (!$str) {
     565                        $str = mssql_get_last_message();
     566                }
     567                $EZSQL_ERROR[] = array ('query' => $this->last_query, 'error_str' => $str);
     568
     569                if ( $this->suppress_errors )
     570                        return false;
     571
     572                if ( $caller = $this->get_caller() )
     573                        $error_str = sprintf(/*WP_I18N_DB_QUERY_ERROR_FULL*/'WordPress database error %1$s for query %2$s made by %3$s'/*/WP_I18N_DB_QUERY_ERROR_FULL*/, $str, $this->last_query, $caller);
     574                else
     575                        $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);
     576
     577                $log_error = true;
     578                if ( ! function_exists('error_log') )
     579                        $log_error = false;
     580
     581                $log_file = @ini_get('error_log');
     582                if ( !empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file) )
     583                        $log_error = false;
     584
     585                if ( $log_error )
     586                        @error_log($error_str, 0);
     587
     588                // Is error output turned on or not..
     589                if ( !$this->show_errors )
     590                        return false;
     591
     592                $str = htmlspecialchars($str, ENT_QUOTES);
     593                $query = htmlspecialchars($this->last_query, ENT_QUOTES);
     594
     595                // If there is an error then take note of it
     596                print "<div id='error'>
     597                <p class='wpdberror'><strong>WordPress database error:</strong> [$str]<br />
     598                <code>$query</code></p>
     599                </div>";
     600        }
     601
     602        /**
     603         * Enables showing of database errors.
     604         *
     605         * This function should be used only to enable showing of errors.
     606         * wpdb::hide_errors() should be used instead for hiding of errors. However,
     607         * this function can be used to enable and disable showing of database
     608         * errors.
     609         *
     610         * @since 0.71
     611         *
     612         * @param bool $show Whether to show or hide errors
     613         * @return bool Old value for showing errors.
     614         */
     615        function show_errors( $show = true ) {
     616                $errors = $this->show_errors;
     617                $this->show_errors = $show;
     618                return $errors;
     619        }
     620
     621        /**
     622         * Disables showing of database errors.
     623         *
     624         * @since 0.71
     625         *
     626         * @return bool Whether showing of errors was active or not
     627         */
     628        function hide_errors() {
     629                $show = $this->show_errors;
     630                $this->show_errors = false;
     631                return $show;
     632        }
     633
     634        /**
     635         * Whether to suppress database errors.
     636         *
     637         * @param unknown_type $suppress
     638         * @return unknown
     639         */
     640        function suppress_errors( $suppress = true ) {
     641                $errors = $this->suppress_errors;
     642                $this->suppress_errors = $suppress;
     643                return $errors;
     644        }
     645
     646        /**
     647         * Kill cached query results.
     648         *
     649         * @since 0.71
     650         */
     651        function flush() {
     652                $this->last_result = array();
     653                $this->col_info = null;
     654                $this->last_query = null;
     655        }
     656
     657        /**
     658         * Perform a MSSQL database query, using current database connection.
     659         *
     660         * More information can be found on the codex page.
     661         *
     662         * @since 0.71
     663         *
     664         * @param string $query
     665         * @param bool $translate Should we translate the query?
     666         * @return int|false Number of rows affected/selected or false on error
     667         */
     668        function query($query, $translate = true) {
     669
     670                if ( ! $this->ready ) {
     671                        return false;
     672                }
     673
     674                // filter the query, if filters are available
     675                // NOTE: some queries are made before the plugins have been loaded, and thus cannot be filtered with this method
     676                if ( function_exists('apply_filters') ) {
     677                        $query = apply_filters('query', $query);
     678                }
     679
     680                // initialise return
     681                $return_val = 0;
     682                $this->flush();
     683
     684                // Log how the function was called
     685                $this->func_call = "\$db->query(\"$query\")";
     686
     687                // Keep track of the last query for debug..
     688                $this->last_query = $query;
     689
     690                // Make Necessary Translations
     691                if ($translate === true) {
     692                        $query = $this->translate($query);
     693                        $this->previous_query = $query;
     694                }
     695               
     696                if ($this->preceeding_query !== false) {
     697                        if (is_array($this->preceeding_query)) {
     698                                foreach ($this->preceeding_query as $p_query) {
     699                                        @mssql_query($sub_query);
     700                                }
     701                        } else {
     702                                @mssql_query($this->preceeding_query);
     703                        }
     704                        $this->preceeding_query = false;
     705                }
     706               
     707                // Check if array of queries (this happens for INSERTS with multiple VALUES blocks)
     708                if (is_array($query)) {
     709                        foreach ($query as $sub_query) {
     710                                $this->_pre_query();
     711                                $this->result = @mssql_query($sub_query);
     712                                $return_val = $this->_post_query($sub_query);
     713                        }
     714                } else {
     715                        $this->_pre_query();
     716                        $this->result = @mssql_query(($query);
     717                        $return_val = $this->_post_query($query);
     718                }
     719               
     720                if ($this->following_query !== false) {
     721                        if (is_array($this->following_query)) {
     722                                foreach ($this->following_query as $f_query) {
     723                                        @mssql_query($f_query);
     724                                }
     725                        } else {
     726                                @mssql_query($this->following_query);
     727                        }
     728                        $this->following_query = false;
     729                }
     730
     731                return $return_val;
     732        }
     733       
     734        function _pre_query() {
     735                if ( defined('SAVEQUERIES') && SAVEQUERIES ) {
     736                        $this->timer_start();
     737                }
     738        }
     739       
     740        function _post_query($query) {
     741                ++$this->num_queries;
     742                // If there is an error then take note of it..
     743                if ( $this->result == FALSE && $this->last_error = mssql_get_last_message() ) {
     744                        //var_dump($query);
     745                        //var_dump($this->translation_changes);
     746                        $this->print_error();
     747                        return false;
     748                }
     749
     750                if ( defined('SAVEQUERIES') && SAVEQUERIES ) {
     751                        $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
     752                }
     753
     754                if ( preg_match("/^\\s*(insert|delete|update|replace) /i",$query) ) {
     755
     756                        $this->rows_affected = mssql_rows_affected($this->dbh);
     757                        // Take note of the insert_id
     758                        if ( preg_match("/^\\s*(insert|replace) /i",$query) ) {
     759                                $result = @mssql_fetch_object(@mssql_query("SELECT SCOPE_IDENTITY() AS ID"));
     760                                $this->insert_id = $result->ID;
     761                        }
     762
     763                        $return_val = $this->rows_affected;
     764                } else {
     765
     766                        $i = 0;
     767                        while ($i < @mssql_num_fields($this->result)) {
     768                                $field = @mssql_fetch_field($this->result, $i);
     769                                $new_field = new stdClass();
     770                                $new_field->name = $field->name;
     771                                $new_field->table = $field->column_source;
     772                                $new_field->def = null;
     773                                $new_field->max_length = $field->max_length;
     774                                $new_field->not_null = true;
     775                                $new_field->primary_key = null;
     776                                $new_field->unique_key = null;
     777                                $new_field->multiple_key = null;
     778                                $new_field->numeric = $field->numeric;
     779                                $new_field->blob = null;
     780                                $new_field->type = $field->type;
     781                                if(isset($field->unsigned)) {
     782                                        $new_field->unsigned = $field->unsigned;
     783                                } else {
     784                                        $new_field->unsigned = null;
     785                                }
     786                                $new_field->zerofill = null;
     787                                $this->col_info[$i] = $new_field;
     788                                $i++;
     789                        }
     790                        $num_rows = 0;
     791                        while ( $row = @mssql_fetch_object($this->result) ) {
     792                                $this->last_result[$num_rows] = $row;
     793                                $num_rows++;
     794                        }
     795                        $this->last_result = $this->fix_results($this->last_result);
     796
     797                        @mssql_free_result($this->result);
     798
     799                        // Log number of rows the query returned
     800                        $this->num_rows = $num_rows;
     801
     802                        // Return number of rows selected
     803                        $return_val = $this->num_rows;
     804                }
     805
     806                return $return_val;
     807        }
     808
     809        /**
     810         * Insert a row into a table.
     811         *
     812         * <code>
     813         * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
     814         * </code>
     815         *
     816         * @since 2.5.0
     817         * @see wpdb::prepare()
     818         *
     819         * @param string $table table name
     820         * @param array $data Data to insert (in column => value pairs).  Both $data columns and $data values should be "raw" (neither should be SQL escaped).
     821         * @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.
     822         * @return int|false The number of rows inserted, or false on error.
     823         */
     824        function insert($table, $data, $format = null) {
     825                $formats = $format = (array) $format;
     826                $fields = array_keys($data);
     827                $formatted_fields = array();
     828                foreach ( $fields as $field ) {
     829                        if ( !empty($format) )
     830                                $form = ( $form = array_shift($formats) ) ? $form : $format[0];
     831                        elseif ( isset($this->field_types[$field]) )
     832                                $form = $this->field_types[$field];
     833                        else
     834                                $form = '%s';
     835                        $formatted_fields[] = $form;
     836                }
     837                $sql = "INSERT INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES ('" . implode( "','", $formatted_fields ) . "')";
     838                return $this->query( $this->prepare( $sql, $data) );
     839        }
     840
     841        /**
     842         * Update a row in the table
     843         *
     844         * <code>
     845         * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) )
     846         * </code>
     847         *
     848         * @since 2.5.0
     849         * @see wpdb::prepare()
     850         *
     851         * @param string $table table name
     852         * @param array $data Data to update (in column => value pairs).  Both $data columns and $data values should be "raw" (neither should be SQL escaped).
     853         * @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".
     854         * @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.
     855         * @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.
     856         * @return int|false The number of rows updated, or false on error.
     857         */
     858        function update($table, $data, $where, $format = null, $where_format = null) {
     859                if ( !is_array( $where ) )
     860                        return false;
     861
     862                $formats = $format = (array) $format;
     863                $bits = $wheres = array();
     864                foreach ( (array) array_keys($data) as $field ) {
     865                        if ( !empty($format) )
     866                                $form = ( $form = array_shift($formats) ) ? $form : $format[0];
     867                        elseif ( isset($this->field_types[$field]) )
     868                                $form = $this->field_types[$field];
     869                        else
     870                                $form = '%s';
     871                        $bits[] = "`$field` = {$form}";
     872                }
     873
     874                $where_formats = $where_format = (array) $where_format;
     875                foreach ( (array) array_keys($where) as $field ) {
     876                        if ( !empty($where_format) )
     877                                $form = ( $form = array_shift($where_formats) ) ? $form : $where_format[0];
     878                        elseif ( isset($this->field_types[$field]) )
     879                                $form = $this->field_types[$field];
     880                        else
     881                                $form = '%s';
     882                        $wheres[] = "`$field` = {$form}";
     883                }
     884
     885                $sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres );
     886                return $this->query( $this->prepare( $sql, array_merge(array_values($data), array_values($where))) );
     887        }
     888
     889        /**
     890         * Retrieve one variable from the database.
     891         *
     892         * This combines the functionality of wpdb::get_row() and wpdb::get_col(),
     893         * so both the column and row can be picked.
     894         *
     895         * It is possible to use this function without executing more queries. If
     896         * you already made a query, you can set the $query to 'null' value and just
     897         * retrieve either the column and row of the last query result.
     898         *
     899         * @since 0.71
     900         *
     901         * @param string $query Can be null as well, for caching
     902         * @param int $x Column num to return
     903         * @param int $y Row num to return
     904         * @return mixed Database query results
     905         */
     906        function get_var($query=null, $x = 0, $y = 0) {
     907                $this->func_call = "\$db->get_var(\"$query\",$x,$y)";
     908                if ( $query )
     909                        $this->query($query);
     910
     911                // Extract var out of cached results based x,y vals
     912                if ( !empty( $this->last_result[$y] ) ) {
     913                        $values = array_values(get_object_vars($this->last_result[$y]));
     914                }
     915
     916                // If there is a value return it else return null
     917                return (isset($values[$x]) && $values[$x]!=='') ? $values[$x] : null;
     918        }
     919
     920        /**
     921         * Retrieve one row from the database.
     922         *
     923         * @since 0.71
     924         *
     925         * @param string $query SQL query
     926         * @param string $output ARRAY_A | ARRAY_N | OBJECT
     927         * @param int $y Row num to return
     928         * @return mixed Database query results
     929         */
     930        function get_row($query = null, $output = OBJECT, $y = 0) {
     931                $this->func_call = "\$db->get_row(\"$query\",$output,$y)";
     932                if ( $query )
     933                        $this->query($query);
     934                else
     935                        return null;
     936
     937                if ( !isset($this->last_result[$y]) )
     938                        return null;
     939
     940                if ( $output == OBJECT ) {
     941                        return $this->last_result[$y] ? $this->last_result[$y] : null;
     942                } elseif ( $output == ARRAY_A ) {
     943                        return $this->last_result[$y] ? get_object_vars($this->last_result[$y]) : null;
     944                } elseif ( $output == ARRAY_N ) {
     945                        return $this->last_result[$y] ? array_values(get_object_vars($this->last_result[$y])) : null;
     946                } else {
     947                        $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*/);
     948                }
     949        }
     950
     951        /**
     952         * Retrieve one column from the database.
     953         *
     954         * @since 0.71
     955         *
     956         * @param string $query Can be null as well, for caching
     957         * @param int $x Col num to return. Starts from 0.
     958         * @return array Column results
     959         */
     960        function get_col($query = null , $x = 0) {
     961                if ( $query )
     962                        $this->query($query);
     963
     964                $new_array = array();
     965                // Extract the column values
     966                for ( $i=0; $i < count($this->last_result); $i++ ) {
     967                        $new_array[$i] = $this->get_var(null, $x, $i);
     968                }
     969                return $new_array;
     970        }
     971
     972        /**
     973         * Retrieve an entire result set from the database.
     974         *
     975         * @since 0.71
     976         *
     977         * @param string|null $query Can also be null to pull from the cache
     978         * @param string $output ARRAY_A | ARRAY_N | OBJECT_K | OBJECT
     979         * @return mixed Database query results
     980         */
     981        function get_results($query = null, $output = OBJECT) {
     982                $this->func_call = "\$db->get_results(\"$query\", $output)";
     983
     984                if ( $query )
     985                        $this->query($query);
     986                else
     987                        return null;
     988
     989                if ( $output == OBJECT ) {
     990                        // Return an integer-keyed array of row objects
     991                        return $this->last_result;
     992                } elseif ( $output == OBJECT_K ) {
     993                        // Return an array of row objects with keys from column 1
     994                        // (Duplicates are discarded)
     995                        foreach ( $this->last_result as $row ) {
     996                                $key = array_shift( get_object_vars( $row ) );
     997                                if ( !isset( $new_array[ $key ] ) )
     998                                        $new_array[ $key ] = $row;
     999                        }
     1000                        return $new_array;
     1001                } elseif ( $output == ARRAY_A || $output == ARRAY_N ) {
     1002                        // Return an integer-keyed array of...
     1003                        if ( $this->last_result ) {
     1004                                $i = 0;
     1005                                foreach( (array) $this->last_result as $row ) {
     1006                                        if ( $output == ARRAY_N ) {
     1007                                                // ...integer-keyed row arrays
     1008                                                $new_array[$i] = array_values( get_object_vars( $row ) );
     1009                                        } else {
     1010                                                // ...column name-keyed row arrays
     1011                                                $new_array[$i] = get_object_vars( $row );
     1012                                        }
     1013                                        ++$i;
     1014                                }
     1015                                return $new_array;
     1016                        }
     1017                }
     1018        }
     1019
     1020        /**
     1021         * Retrieve column metadata from the last query.
     1022         *
     1023         * @since 0.71
     1024         *
     1025         * @param string $info_type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill
     1026         * @param int $col_offset 0: col name. 1: which table the col's in. 2: col's max length. 3: if the col is numeric. 4: col's type
     1027         * @return mixed Column Results
     1028         */
     1029        function get_col_info($info_type = 'name', $col_offset = -1) {
     1030                if ( $this->col_info ) {
     1031                        if ( $col_offset == -1 ) {
     1032                                $i = 0;
     1033                                foreach( (array) $this->col_info as $col ) {
     1034                                        $new_array[$i] = $col->{$info_type};
     1035                                        $i++;
     1036                                }
     1037                                return $new_array;
     1038                        } else {
     1039                                return $this->col_info[$col_offset]->{$info_type};
     1040                        }
     1041                }
     1042        }
     1043
     1044        /**
     1045         * Starts the timer, for debugging purposes.
     1046         *
     1047         * @since 1.5.0
     1048         *
     1049         * @return bool Always returns true
     1050         */
     1051        function timer_start() {
     1052                $mtime = microtime();
     1053                $mtime = explode(' ', $mtime);
     1054                $this->time_start = $mtime[1] + $mtime[0];
     1055                return true;
     1056        }
     1057
     1058        /**
     1059         * Stops the debugging timer.
     1060         *
     1061         * @since 1.5.0
     1062         *
     1063         * @return int Total time spent on the query, in milliseconds
     1064         */
     1065        function timer_stop() {
     1066                $mtime = microtime();
     1067                $mtime = explode(' ', $mtime);
     1068                $time_end = $mtime[1] + $mtime[0];
     1069                $time_total = $time_end - $this->time_start;
     1070                return $time_total;
     1071        }
     1072
     1073        /**
     1074         * Wraps fatal errors in a nice header and footer and dies.
     1075         *
     1076         * @since 1.5.0
     1077         *
     1078         * @param string $message
     1079         * @return unknown
     1080         */
     1081        function bail($message) {
     1082                if ( !$this->show_errors ) {
     1083                        if ( class_exists('WP_Error') )
     1084                                $this->error = new WP_Error('500', $message);
     1085                        else
     1086                                $this->error = $message;
     1087                        return false;
     1088                }
     1089                wp_die($message);
     1090        }
     1091
     1092        /**
     1093         * Whether or not MySQL database is minimal required version.
     1094         *
     1095         * @since 2.5.0
     1096         * @uses $wp_version
     1097         *
     1098         * @return WP_Error
     1099         */
     1100        function check_database_version()
     1101        {
     1102                global $wp_version;
     1103                // Base on database type
     1104                //
     1105                if ($this->db_type == "mysql") {
     1106                        // Make sure the server has MySQL 4.0
     1107                        $mysql_version = preg_replace('|[^0-9\.]|', '', @mysql_get_server_info($this->dbh));
     1108                        if ( version_compare($mysql_version, '4.0.0', '<') )
     1109                                return new WP_Error('database_version',sprintf(__('<strong>ERROR</strong>: WordPress %s requires MySQL 4.0.0 or higher'), $wp_version));
     1110                }
     1111        }
     1112
     1113        /**
     1114         * Whether of not the database version supports collation.
     1115         *
     1116         * Called when WordPress is generating the table scheme.
     1117         *
     1118         * @since 2.5.0
     1119         *
     1120         * @return bool True if collation is supported, false if version does not
     1121         */
     1122        function supports_collation()
     1123        {
     1124                return false;
     1125        }
     1126
     1127        /**
     1128         * Retrieve the name of the function that called wpdb.
     1129         *
     1130         * Requires PHP 4.3 and searches up the list of functions until it reaches
     1131         * the one that would most logically had called this method.
     1132         *
     1133         * @since 2.5.0
     1134         *
     1135         * @return string The name of the calling function
     1136         */
     1137        function get_caller() {
     1138                // requires PHP 4.3+
     1139                if ( !is_callable('debug_backtrace') )
     1140                        return '';
     1141
     1142                $bt = debug_backtrace();
     1143                $caller = array();
     1144
     1145                $bt = array_reverse( $bt );
     1146                foreach ( (array) $bt as $call ) {
     1147                        if ( @$call['class'] == __CLASS__ )
     1148                                continue;
     1149                        $function = $call['function'];
     1150                        if ( isset( $call['class'] ) )
     1151                                $function = $call['class'] . "->$function";
     1152                        $caller[] = $function;
     1153                }
     1154                $caller = join( ', ', $caller );
     1155
     1156                return $caller;
     1157        }
     1158
     1159        function show_tables()
     1160        {
     1161                $tables = $this->get_col("Select Table_name as \"Table name\"
     1162        From Information_schema.Tables
     1163        Where Table_type = 'BASE TABLE' and Objectproperty
     1164        (Object_id(Table_name), 'IsMsShipped') = 0");
     1165                foreach ($tables as $table) {
     1166                        echo "Table: ".$table."<br/>";
     1167                        $rows = $this->get_col("SELECT COUNT (*) FROM {$table}");
     1168                        foreach ($rows as $row) {
     1169                                echo "Rows: ".$row."<br/>";
     1170                        }
     1171                }
     1172        }
     1173}
     1174 No newline at end of file
  • wp-includes/wp-db/mssql/translations/fields_map.php

    Property changes on: wp-includes\wp-db\mssql\mssql.php
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
     1<?php
     2/**
     3 * Fields mapping
     4 *
     5 * Some column types from MySQL
     6 * don't have an exact equivalent for SQL Server
     7 * That is why we need to know what column types they were
     8 * originally to make the translations.
     9 *
     10 * @category MSSQL
     11 * @package MySQL_Translations
     12 * @author A.Garcia & A.Gentile
     13 * */
     14class Fields_map
     15{
     16    var $fields_map = array();
     17    var $filepath = '';
     18
     19        /**
     20     * php4 style call to constructor.
     21     *
     22     * @since 2.7.1
     23     *
     24     */
     25    function Fields_map()
     26    {
     27                return $this->__construct();
     28    }
     29       
     30        /**
     31         * Set filepath
     32         *
     33         * PHP5 style constructor for compatibility with PHP5.
     34         *
     35         * @since 2.7.1
     36         */
     37        function __construct()
     38        {
     39                $this->filepath = dirname(dirname(dirname(dirname(dirname(__FILE__))))) . '/wp-content/fields_map.parsed_types.php';
     40        }
     41
     42    /**
     43     * Get array of fields by type from fields_map property
     44     *
     45     * @since 2.8
     46     * @param $type
     47     * @param $table
     48     *
     49     * @return array
     50     */
     51    function by_type($type, $table = null)
     52    {
     53        $ret = array();
     54        foreach ( $this->fields_map as $tables => $fields ) {
     55            if ( is_array($fields) ) {
     56                foreach ( $fields as $field_name => $field_meta ) {
     57                    if ( $field_meta['type'] == $type ) {
     58                        if ( is_null($table) || $tables == $table ) {
     59                            $ret[] = $field_name;
     60                        }
     61                    }
     62                }
     63            }
     64        }
     65        return $ret;
     66    }
     67
     68    /**
     69     * Get array of tables from fields_map property
     70     *
     71     * @since 2.8
     72     *
     73     * @return array
     74     */
     75    function get_tables()
     76    {
     77        $ret = array();
     78        foreach ( $this->fields_map as $tables => $fields ) {
     79            $ret[] = $tables;
     80        }
     81        return $ret;
     82    }
     83
     84    /**
     85     * Given a query find the column types
     86     *
     87     * @since 2.8
     88     * @param $qry
     89     *
     90     * @return array
     91     */
     92    function extract_column_types($qry)
     93    {
     94        //table name
     95        $matches = array();
     96                if ( preg_match('/(?:CREATE|ALTER) TABLE (.*) \(/i', $qry, $matches) ) {
     97                        $table_name = $matches[1];
     98                } else {
     99                        $table_name = '';
     100                }
     101
     102
     103                $fields_and_indexes = substr( $qry, strpos($qry, '(') + 1, strrpos($qry, ')') - (strpos($qry, '(') + 1) );
     104                $just_fields = trim( substr( $fields_and_indexes, 0, $this->index_pos($fields_and_indexes) ) );
     105
     106                $field_lines = explode(',', $just_fields);
     107                $field_types = array();
     108                foreach ( $field_lines as $field_line ) {
     109                        if ( !empty($field_line) ) {
     110                                $field_line = trim($field_line);
     111                                $words = explode(' ', $field_line, 3);
     112                                $first_word = $words[0];
     113                                $field_type = $this->type_translations($words[1]);
     114                                if ( $field_type !== false ) {
     115                                        $field_types[$first_word] = array('type'=>$field_type);
     116                                }
     117                        }
     118                }
     119
     120                //get primary key
     121                $just_indexes = trim( substr( $fields_and_indexes, $this->index_pos($fields_and_indexes) ) );
     122                $matches = array();
     123                $has_primary_key = preg_match('/PRIMARY KEY *\((.*?)[,|\)]/i', $just_indexes, $matches);
     124                if ( $has_primary_key ) {
     125                        $primary_key = trim($matches[1]);
     126                        $field_types[$primary_key] = array('type' => 'primary_id');
     127                }
     128                ksort($field_types);
     129
     130                return array($table_name => $field_types);
     131    }
     132
     133    /**
     134     * According to the column types in MySQL
     135     *
     136     * @since 2.8
     137     * @param $field_type
     138     *
     139     * @return array
     140     */
     141    function type_translations($field_type)
     142    {
     143        //false means not translate this field.
     144        $translations = array(
     145                        array('pattern' => '/varchar(.*)/', 'trans' => false),
     146                        array('pattern' => '/.*text.*/',    'trans' => 'text'),
     147                        array('pattern' => '/.*datetime.*/','trans' => 'date'),
     148                        array('pattern' => '/int(.*)/',     'trans' => 'int'),
     149                );
     150
     151                $res = '';
     152                while ( ($res === '') && ($trans = array_shift($translations)) ) {
     153                        if ( preg_match($trans['pattern'],$field_type) ) {
     154                                $res = $trans['trans'];
     155                        }
     156                }
     157         
     158                if ( $res === '' ) {
     159                        $res = $field_type;
     160                }
     161                return $res; 
     162    }
     163
     164
     165    /**
     166     * Get array of tables from fields_map property
     167     *
     168     * @since 2.8
     169     * @param $fields_and_indexes
     170     *
     171     * @return array
     172     */
     173    function index_pos($fields_and_indexes)
     174    {
     175        $reserved_words = array('PRIMARY KEY', 'UNIQUE');
     176                $res = false;
     177                while ( ($res === false) && ($reserved_word = array_shift($reserved_words)) ){
     178                        $res = stripos($fields_and_indexes,$reserved_word);
     179                }
     180       
     181                return $res;
     182    }
     183
     184    /**
     185     * Update fields may given a CREATE | ALTER query
     186     *
     187     * @since 2.8
     188     * @param $qry
     189     *
     190     * @return array
     191     */
     192    function update_for($qry)
     193    {
     194        $this->read();
     195                $this->fields_map = array_merge($this->fields_map, $this->extract_column_types($qry));
     196                file_put_contents($this->filepath, '<?php return ' . var_export($this->fields_map, true) . "\n ?>");
     197                return $this->fields_map;
     198    }
     199
     200    /**
     201     * Get the fields_map from memory or from the file.
     202     *
     203     * @since 2.8
     204     *
     205     * @return array
     206     */
     207    function read()
     208    {
     209                if ( empty($this->fields_map) ) {
     210                        if ( file_exists($this->filepath) ) {
     211                                $this->fields_map = require($this->filepath);
     212                        } else {
     213                                $this->fields_map = array();
     214                        }
     215                }
     216                return $this->fields_map;
     217    }
     218
     219}
  • wp-includes/wp-db/mssql/translations/translations.php

    Property changes on: wp-includes\wp-db\mssql\translations\fields_map.php
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
     1<?php
     2require_once(dirname(__FILE__) . '/fields_map.php');
     3
     4/**
     5 * SQL Dialect Translations
     6 *
     7 * @category MSSQL
     8 * @package MySQL_Translations
     9 * @author A.Garcia & A.Gentile
     10 * */
     11class SQL_Translations
     12{
     13    /**
     14     * Field Mapping
     15     *
     16     * @since 2.7.1
     17     * @access private
     18     * @var array
     19     */
     20    var $fields_map = null;
     21
     22    /**
     23     * Was this query prepared?
     24     *
     25     * @since 2.7.1
     26     * @access private
     27     * @var bool
     28     */
     29    var $prepared = false;
     30
     31    /**
     32     * Update query?
     33     *
     34     * @since 2.7.1
     35     * @access private
     36     * @var bool
     37     */
     38    var $update_query = false;
     39
     40    /**
     41     * Insert query?
     42     *
     43     * @since 2.7.1
     44     * @access private
     45     * @var bool
     46     */
     47    var $insert_query = false;
     48
     49    /**
     50     * Prepare arguments
     51     *
     52     * @since 2.7.1
     53     * @access private
     54     * @var array
     55     */
     56    var $prepare_args = array();
     57
     58    /**
     59     * Update Data
     60     *
     61     * @since 2.7.1
     62     * @access private
     63     * @var array
     64     */
     65    var $update_data = array();
     66
     67    /**
     68     * Update Data
     69     *
     70     * @since 2.7.1
     71     * @access private
     72     * @var array
     73     */
     74    var $translation_changes = array();
     75       
     76        /**
     77     * Azure
     78         * Are we dealing with a SQL Azure DB?
     79     *
     80     * @since 2.7.1
     81     * @access public
     82     * @var bool
     83     */
     84    var $azure = false;
     85       
     86        /**
     87         * Preceeding query
     88         * Sometimes we need to issue a query
     89         * before the original query
     90         *
     91         * @since 2.8.5
     92         * @access public
     93         * @var mixed
     94         */
     95        var $preceeding_query = false;
     96       
     97        /**
     98         * Following query
     99         * Sometimes we need to issue a query
     100         * right after the original query
     101         *
     102         * @since 2.8.5
     103         * @access public
     104         * @var mixed
     105         */
     106        var $following_query = false;
     107       
     108    /**
     109     * php4 style call to constructor.
     110     *
     111     * @since 2.7.1
     112     *
     113     */
     114    function SQL_Translations()
     115    {
     116                return $this->__construct();
     117    }
     118       
     119        /**
     120         * Assign fields_map as a new Fields_map object
     121         *
     122         * PHP5 style constructor for compatibility with PHP5.
     123         *
     124         * @since 2.7.1
     125         */
     126        function __construct()
     127        {
     128                $this->fields_map = new Fields_map();
     129        }
     130
     131    /**
     132     * MySQL > MSSQL Query Translation
     133     * Processes smaller translation sub-functions
     134     *
     135     * @since 2.7.1
     136     *
     137     * @param string $query Query coming in
     138     *
     139     * @return string Translated Query
     140     */
     141    function translate($query)
     142    {
     143                $this->insert_query = false;
     144                $this->preceeding_query = false;
     145                $this->following_query = false;
     146               
     147                if ( stripos($query, 'INSERT') === 0 ) {
     148            $this->insert_query = true;
     149                }
     150               
     151        // Was this query prepared?
     152        if ( strripos($query, '--PREPARE') !== FALSE ) {
     153            $query = str_replace('--PREPARE', '', $query);
     154            $this->prepared = TRUE;
     155        } else {
     156            $this->prepared = FALSE;
     157        }
     158
     159        // Update Query?
     160        if ( strripos($query, '--UPDATE') !== FALSE ) {
     161            $query = str_replace('--UPDATE', '', $query);
     162            $this->update_query = TRUE;
     163        } else {
     164            $this->update_query = FALSE;
     165        }
     166
     167        // Do we have serialized arguments?
     168        if ( strripos($query, '--SERIALIZED') !== FALSE ) {
     169            $query = str_replace('--SERIALIZED', '', $query);
     170            $query = $this->translate_general($query);
     171            return $query;
     172        }
     173
     174        $query = trim($query);
     175
     176        $sub_funcs = array(
     177            'translate_general',
     178            'translate_date_add',
     179            'translate_if_stmt',
     180            'translate_sqlcalcrows',
     181            'translate_limit',
     182            'translate_now_datetime',
     183            'translate_distinct_orderby',
     184            'translate_sort_casting',
     185            'translate_column_type',
     186            'translate_remove_groupby',
     187            'translate_insert_nulltime',
     188            'translate_incompat_data_type',
     189            'translate_create_queries',
     190        );
     191
     192        // Perform translations and record query changes.
     193        $this->translation_changes = array();
     194        foreach ( $sub_funcs as $sub_func ) {
     195            $old_query = $query;
     196            $query = $this->$sub_func($query);
     197            if ( $old_query !== $query ) {
     198                $this->translation_changes[] = $sub_func;
     199                $this->translation_changes[] = $query;
     200                $this->translation_changes[] = $old_query;
     201            }
     202        }
     203        if ( $this->insert_query ) {
     204            $query = $this->split_insert_values($query);
     205        }
     206        if ( $this->prepared && $this->insert_query ) {
     207            if ( is_array($query) ) {
     208                foreach ($query as $k => $v) {
     209                    $query[$k] = $this->verify_insert($v);
     210                }
     211            } else {
     212                $query = $this->verify_insert($query);
     213            }
     214        }
     215
     216        if ( $this->update_query ) {
     217            $query = $this->verify_update($query);
     218        }
     219
     220        return $query;
     221    }
     222
     223    /**
     224     * More generalized information gathering queries
     225     *
     226     * @since 2.7.1
     227     *
     228     * @param string $query Query coming in
     229     *
     230     * @return string Translated Query
     231     */
     232    function translate_general($query)
     233    {
     234        // SERVER VERSION
     235        if ( stripos($query, 'SELECT VERSION()' ) === 0 ) {
     236            $query = substr_replace($query, 'SELECT @@VERSION', 0, 16);
     237        }
     238        // SQL_MODE NO EQUIV
     239        if ( stripos($query, "SHOW VARIABLES LIKE 'sql_mode'" ) === 0 ) {
     240            $query = '';
     241        }
     242        // LAST INSERT ID
     243        if ( stripos($query, 'LAST_INSERT_ID()') > 0 ) {
     244            $start_pos = stripos($query, 'LAST_INSERT_ID()');
     245            $query = substr_replace($query, '@@IDENTITY', $start_pos, 16);
     246        }
     247        // SHOW TABLES
     248        if ( strtolower($query) === 'show tables;' ) {
     249            $query = str_ireplace('show tables', "select name from SYSOBJECTS where TYPE = 'U' order by NAME", $query);
     250        }
     251        if ( stripos($query, 'show tables like ') === 0 ) {
     252            $end_pos = strlen($query);
     253            $param = substr($query, 17, $end_pos - 17);
     254            $query = 'SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE ' . $param;
     255        }
     256        // SET NAMES doesn't exist in T-SQL
     257        if ( strtolower($query) == "set names 'utf8'" ) {
     258            $query = "";
     259        }
     260        // SHOW COLUMNS
     261        if ( stripos($query, 'SHOW COLUMNS FROM ') === 0 ) {
     262            $end_pos = strlen($query);
     263            $param = substr($query, 18, $end_pos - 18);
     264            $param = "'". trim($param, "'") . "'";
     265            $query = 'SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ' . $param;
     266        }
     267               
     268                // SHOW INDEXES - issue with sql azure trying to fix....sys.sysindexes is coming back as invalid onject name
     269                if ( stripos($query, 'SHOW INDEXES FROM ') === 0 ) {
     270                        return $query;
     271                        $table = substr($query, 18);
     272                        $query = "SELECT sys.sysindexes.name AS IndexName
     273                                          FROM sysobjects
     274                                       JOIN sys.key_constraints ON parent_object_id = sys.sysobjects.id
     275                                       JOIN sys.sysindexes ON sys.sysindexes.id = sys.sysobjects.id and sys.key_constraints.unique_index_id = sys.sysindexes.indid
     276                                       JOIN sys.index_columns ON sys.index_columns.object_id = sys.sysindexes.id  and sys.index_columns.index_id = sys.sysindexes.indid
     277                                       JOIN sys.syscolumns ON sys.syscolumns.id = sys.sysindexes.id AND sys.index_columns.column_id = sys.syscolumns.colid
     278                                          WHERE sys.sysobjects.type = 'u'       
     279                                           AND sys.sysobjects.name = '{$table}'";
     280                }
     281               
     282        // USE INDEX
     283        if ( stripos($query, 'USE INDEX (') !== FALSE ) {
     284            $start_pos = stripos($query, 'USE INDEX (');
     285            $end_pos = $this->get_matching_paren($query, $start_pos + 11);
     286            $params = substr($query, $start_pos + 11, $end_pos - ($start_pos + 11));
     287            $params = explode(',', $params);
     288            foreach ( $params as $k => $v ) {
     289                $params[$k] = trim($v);
     290                foreach ( $this->fields_map->read() as $table => $fields ) {
     291                    if ( is_array($fields) ) {
     292                        foreach ( $fields as $field_name => $field_meta ) {
     293                            if ( $field_name == $params[$k] ) {
     294                                $params[$k] = $table . '_' . $params[$k];
     295                            }
     296                        }
     297                    }
     298                }
     299            }
     300            $params = implode(',', $params);
     301            $query = substr_replace($query, 'WITH (INDEX(' . $params . '))', $start_pos, ($end_pos + 1) - $start_pos);
     302        }
     303               
     304                // DESCRIBE - this is pretty darn close to mysql equiv, however it will need to have a flag to modify the result set
     305                // this and SHOW INDEX FROM are used in WP upgrading. The problem is that WP will see the different data types and try
     306                // to alter the table thinking an upgrade is necessary. So the result set from this query needs to be modified using
     307                // the field_mapping to revert column types back to their mysql equiv to fool WP.
     308                if ( stripos($query, 'DESCRIBE ') === 0 ) {
     309                        return $query;
     310                        $table = substr($query, 9);
     311                        $query = $this->describe($table);
     312                }
     313
     314        // DROP TABLES
     315        if ( stripos($query, 'DROP TABLE IF EXISTS ') === 0 ) {
     316            $table = substr($query, 21, strlen($query) - 21);
     317            $query = 'DROP TABLE ' . $table;
     318        } elseif ( stripos($query, 'DROP TABLE ') === 0 ) {
     319            $table = substr($query, 11, strlen($query) - 11);
     320            $query = 'DROP TABLE ' . $table;
     321        }
     322
     323        // TICKS
     324        $query = str_replace('`', '', $query);
     325
     326        // Computed
     327        // This is done as the SQLSRV driver doesn't seem to set a property value for computed
     328        // selected columns, thus WP doesn't have anything to work with.
     329        $query = str_replace('SELECT COUNT(*)', 'SELECT COUNT(*) as Computed', $query);
     330               
     331                // Turn on IDENTITY_INSERT for Importing inserts that are trying to explicitly set
     332                // and IDENTITY column
     333                if ( $this->insert_query ) {
     334                        if ( stristr($query, 'INTO ' . $this->prefix . 'posts') !== FALSE ) {
     335                                $strlen = strlen($this->prefix . 'posts');
     336                                $start_pos = stripos($query, $this->prefix . 'posts') + $strlen;
     337                                $start_pos = stripos($query, '(', $start_pos);
     338                                $end_pos = $this->get_matching_paren($query, $start_pos + 1);
     339                                $params = substr($query, $start_pos + 1, $end_pos - ($start_pos + 1));
     340                                $params = explode(',', $params);
     341                                $found = false;
     342                                foreach ( $params as $k => $v ) {
     343                                        if ( strtolower($v) === 'id' ) {
     344                                                $found = true;
     345                                        }       
     346                                }
     347                                if ( $found ) {
     348                                        $this->preceeding_query = "SET IDENTITY_INSERT {$this->prefix}posts ON";
     349                                        $this->following_query = "SET IDENTITY_INSERT {$this->prefix}posts OFF";
     350                                }
     351                        }
     352                }
     353
     354        return $query;
     355    }
     356
     357
     358    /**
     359     * Changes for DATE_ADD and INTERVAL
     360     *
     361     * @since 2.7.1
     362     *
     363     * @param string $query Query coming in
     364     *
     365     * @return string Translated Query
     366     */
     367    function translate_date_add($query)
     368    {
     369        $query = preg_replace('/date_add\((.*?),.*?([0-9]+?) (.*?)\)/i', 'DATEADD(\3,\2,\1)', $query);
     370        $query = preg_replace('/date_sub\((.*?),.*?([0-9]+?) (.*?)\)/i', 'DATEADD(\3,-\2,\1)', $query);
     371
     372        return $query;
     373    }
     374
     375
     376    /**
     377     * Removing Unnecessary IF statement that T-SQL doesn't play nice with
     378     *
     379     * @since 2.7.1
     380     *
     381     * @param string $query Query coming in
     382     *
     383     * @return string Translated Query
     384     */
     385    function translate_if_stmt($query)
     386    {
     387        if ( stripos( $query, 'IF (DATEADD(') > 0 ) {
     388            $start_pos = stripos($query, 'DATEADD(');
     389            $end_pos = $this->get_matching_paren($query, $start_pos + 8);
     390            $stmt = substr($query, $start_pos, ($end_pos - $start_pos)) . ') >= getdate() THEN 1 ELSE 0 END)';
     391
     392            $start_pos = stripos($query, 'IF (');
     393            $end_pos = $this->get_matching_paren($query, ($start_pos+6))+1;
     394            $query = substr_replace($query, '(CASE WHEN ' . $stmt, $start_pos, ($end_pos - $start_pos));
     395        }
     396        return $query;
     397    }
     398
     399    /**
     400     * SQL_CALC_FOUND_ROWS does not exist in T-SQL
     401     *
     402     * @since 2.7.1
     403     *
     404     * @param string $query Query coming in
     405     *
     406     * @return string Translated Query
     407     */
     408    function translate_sqlcalcrows($query)
     409    {
     410        if ( stripos($query, 'SQL_CALC_FOUND_ROWS') > 0 ) {
     411            $sql_calc_pos = stripos($query, 'SQL_CALC_FOUND_ROWS');
     412            $from_pos = stripos($query, 'FROM');
     413            $query = substr_replace($query,'* ', $sql_calc_pos, ($from_pos - $sql_calc_pos));
     414        }
     415        // catch the next query.
     416        if ( stripos($query, 'FOUND_ROWS()') > 0 ) {
     417            $from_pos = stripos($this->previous_query, 'FROM');
     418            $where_pos = stripos($this->previous_query, 'WHERE');
     419            $from_str = trim(substr($this->previous_query, $from_pos, ($where_pos - $from_pos)));
     420            $order_by_pos = stripos($this->previous_query, 'ORDER BY');
     421            $where_str = trim(substr($this->previous_query, $where_pos, ($order_by_pos - $where_pos)));
     422            $query = str_ireplace('FOUND_ROWS()', 'COUNT(1) ' . $from_str . ' ' . $where_str, $query);
     423        }
     424        return $query;
     425    }
     426
     427    /**
     428     * Changing LIMIT to TOP...mimicking offset
     429     *
     430     * @since 2.7.1
     431     *
     432     * @param string $query Query coming in
     433     *
     434     * @return string Translated Query
     435     */
     436    function translate_limit($query)
     437    {
     438        if ( ( stripos($query,'SELECT') !== 0 && stripos($query,'SELECT') !== FALSE )
     439            && ( stripos($query,'UPDATE') !== 0  && stripos($query,'UPDATE') !== FALSE ) ) {
     440            return $query;
     441        }
     442        $pattern = '/LIMIT\s*(\d+)((\s*,?\s*)(\d+)*)$/is';
     443        $matched = preg_match($pattern, $query, $limit_matches);
     444        if ( $matched == 0 ) {
     445            return $query;
     446        }
     447        // Remove the LIMIT statement
     448        $true_offset = false;
     449        $query = preg_replace($pattern, '', $query);
     450        if ( stripos($query,'DELETE') === 0 ) {
     451            return $query;
     452        }
     453        // Check for true offset
     454        if ( count($limit_matches) == 5 && $limit_matches[1] != '0' ) {
     455            $true_offset = true;
     456            if ( stripos($query, 'SELECT DISTINCT') === 0 ) {
     457                $start = 15;
     458                $start_type = 'SELECT DISTINCT';
     459            } elseif ( stripos($query, 'SELECT') === 0 ) {
     460                $start = 6;
     461                $start_type = 'SELECT';
     462            } elseif ( stripos($query, 'DELETE') === 0 ) {
     463                $start = 6;
     464                $start_type = 'DELETE';
     465            }
     466            // Grab any ORDER BY fields
     467            $arr = array();
     468            if ( stripos($query, 'ORDER') > 0 ) {
     469                $order_pos = stripos($query, 'ORDER');
     470                if ( stripos($query, 'BY', $order_pos) > $order_pos ) {
     471                    $true_offset = true;
     472                    $order_by_pos = stripos($query, 'BY', $order_pos) + 2;
     473                    $fields = substr($query, $order_by_pos, strlen($query) - $order_by_pos);
     474                    $query = substr_replace($query, '', $order_pos, strlen($query) - $order_pos);
     475                    $fields = explode(',', $fields);
     476                    foreach ( $fields as $field ) {
     477                        $field = trim($field);
     478                        if ( stripos($field, 'DESC') > 0 ) {
     479                            $pos = stripos($field, 'DESC');
     480                            $field = trim(substr_replace($field, '', $pos, ($pos + 4) - $pos));
     481                            $arr[] = array('field' => $field, 'ord' => 'DESC');
     482                        } elseif ( stripos($field, 'ASC') > 0 ) {
     483                            $pos = stripos($field, 'ASC');
     484                            $field = trim(substr_replace($field, '', $pos, ($pos + 3) - $pos));
     485                            $arr[] = array('field' => $field, 'ord' => 'ASC');
     486                        } else {
     487                            $arr[] = array('field' => $field, 'ord' => '');
     488                        }
     489                    }
     490                }
     491            }
     492            // Get table name from 'FROM' section.
     493            $from_pos = stripos($query, 'FROM', $start);
     494            $end_from = stripos($query, ' ', $from_pos + 5);
     495            $table = substr($query, $from_pos + 5, $end_from - ($from_pos + 5));
     496            $sarr = explode( ',', trim( substr($query, $start, ($from_pos - $start)) ) );
     497            $tables = $this->fields_map->get_tables();
     498            if ( !in_array($table, $tables) ) {
     499                // We can't continue without the primary key
     500                $true_offset = false;
     501            }
     502            if ( $true_offset ) {
     503                $primary_key = $this->fields_map->by_type('primary_id', $table);
     504                $sarr[] = "ROW_NUMBER() OVER(ORDER BY " . $primary_key[0] . ") AS RowNum";
     505                $str = implode(', ', $sarr);
     506                $query = substr_replace($query, $str . ' ', $start + 1, $from_pos - ($start + 1));
     507            }
     508
     509        } elseif ( count($limit_matches) == 5 && $limit_matches[1] == '0' ) {
     510            $limit_matches[1] = $limit_matches[4];
     511            $true_offset = false;
     512        }
     513
     514        // Rewrite the query.
     515        if ( $true_offset === false ) {
     516            if ( stripos($query, 'DISTINCT') > 0 ) {
     517                $query = str_ireplace('DISTINCT', 'DISTINCT TOP ' . $limit_matches[1] . ' ', $query);
     518            } else {
     519                $query = str_ireplace('DELETE ', 'DELETE TOP ' . $limit_matches[1] . ' ', $query);
     520                $query = str_ireplace('SELECT ', 'SELECT TOP ' . $limit_matches[1] . ' ', $query);
     521            }
     522        } else {
     523            $limit_matches[1] = (int) $limit_matches[1];
     524            $limit_matches[4] = (int) $limit_matches[4];
     525            $q = '';
     526            foreach ( $arr as $order_by_field ) {
     527                $q .= $order_by_field['field'].' '.$order_by_field['ord'].', ';
     528            }
     529            $q = ' ORDER BY ' . rtrim($q, ', ');
     530            if ( stripos($query, 'DISTINCT') > 0 ) {
     531                $query = 'SELECT *
     532                FROM (
     533                    '. $query . '
     534                    ) AS DerivTable
     535                WHERE DerivTable.RowNum BETWEEN ' . $limit_matches[1] . ' AND ' . ($limit_matches[1] + $limit_matches[4]) . $q;
     536            } else {
     537                $query = 'SELECT *
     538                FROM (
     539                    '. $query . '
     540                    ) AS DerivTable
     541                WHERE DerivTable.RowNum BETWEEN ' . $limit_matches[1] . ' AND ' . ($limit_matches[1] + $limit_matches[4]) . $q;
     542            }
     543        }
     544        return $query;
     545    }
     546
     547
     548    /**
     549     * Replace From UnixTime and now()
     550     *
     551     * @since 2.7.1
     552     *
     553     * @param string $query Query coming in
     554     *
     555     * @return string Translated Query
     556     */
     557    function translate_now_datetime($query)
     558    {
     559        $replacement = 'getdate()';
     560        $query = preg_replace('/(from_unixtime|unix_timestamp)\s*\(([^\)]*)\)/i', $replacement, $query);
     561        $query = str_ireplace('NOW()', $replacement, $query);
     562
     563        // REPLACE dayofmonth which doesn't exist in T-SQL
     564        $check = $query;
     565        $query = preg_replace('/dayofmonth\((.*?)\)/i', 'DATEPART(DD,\1)',$query);
     566        if ( $check !== $query ) {
     567            $as_array = $this->get_as_fields($query);
     568            if ( empty($as_array) ) {
     569                $query = str_ireplace('FROM', 'as dom FROM', $query);
     570            }
     571        }
     572        return $query;
     573    }
     574
     575    /**
     576     * Order By within a Select Distinct needs to have an field for every alias
     577     *
     578     * @since 2.7.1
     579     *
     580     * @param string $query Query coming in
     581     *
     582     * @return string Translated Query
     583     */
     584    function translate_distinct_orderby($query)
     585    {
     586        if ( stripos($query, 'DISTINCT') > 0 ) {
     587            if ( stripos($query, 'ORDER') > 0 ) {
     588                $order_pos = stripos($query, 'ORDER');
     589                if ( stripos($query, 'BY', $order_pos) > $order_pos ) {
     590                    $fields = $this->get_as_fields($query);
     591                    $ob = stripos($query, 'BY', $order_pos);
     592                    if ( stripos($query, ' ASC', $ob) > 0 ) {
     593                        $ord = stripos($query, ' ASC', $ob);
     594                    }
     595                    if ( stripos($query, ' DESC', $ob) > 0 ) {
     596                        $ord = stripos($query, ' DESC', $ob);
     597                    }
     598                    $str = 'BY ';
     599                    $str .= implode(', ',$fields);
     600
     601                    $query = substr_replace($query, $str, $ob, ($ord-$ob));
     602                }
     603            }
     604        }
     605        return $query;
     606    }
     607
     608
     609    /**
     610     * To sort text fields they need to be first cast as varchar
     611     *
     612     * @since 2.7.1
     613     *
     614     * @param string $query Query coming in
     615     *
     616     * @return string Translated Query
     617     */
     618    function translate_sort_casting($query)
     619    {
     620        if ( in_array('translate_limit', $this->translation_changes) ) {
     621            return $query;
     622        }
     623        if ( stripos($query, 'ORDER') > 0 ) {
     624            $order_pos = stripos($query, 'ORDER');
     625            if ( stripos($query, 'BY', $order_pos) == ($order_pos + 6)) {
     626                $ob = stripos($query, 'BY', $order_pos);
     627                if ( stripos($query,' ASC', $ob) > 0 ) {
     628                    $ord = stripos($query, ' ASC', $ob);
     629                }
     630                if ( stripos($query,' DESC', $ob) > 0 ) {
     631                    $ord = stripos($query, ' DESC', $ob);
     632                }
     633
     634                $params = substr($query, ($ob + 3), ($ord - ($ob + 3)));
     635                $params = preg_split('/[\s,]+/', $params);
     636                $p = array();
     637                foreach ( $params as $value ) {
     638                    $value = str_replace(',', '', $value);
     639                    if ( !empty($value) ) {
     640                        $p[] = $value;
     641                    }
     642                }
     643                $str = '';
     644
     645                foreach ($p as $v ) {
     646                    $match = false;
     647                    foreach( $this->fields_map->read() as $table => $table_fields ) {
     648                        if ( is_array($table_fields) ) {
     649                            foreach ( $table_fields as $field => $field_meta) {
     650                                if ( $field_meta['type'] == 'text' ) {
     651                                    if ( $v == $table . '.' . $field || $v == $field ) {
     652                                        $match = true;
     653                                    }
     654                                }
     655                            }
     656                        }
     657                    }
     658                    if ( $match ) {
     659                        $str .= 'cast(' . $v . ' as varchar(255)), ';
     660                    } else {
     661                        $str .= $v . ', ';
     662                    }
     663                }
     664                $str = rtrim($str, ', ');
     665                $query = substr_replace( $query, $str, ($ob + 3), ($ord - ($ob + 3)) );
     666            }
     667        }
     668        return $query;
     669    }
     670
     671    /**
     672     * Meta key fix. \_%  to  [_]%
     673     *
     674     * @since 2.7.1
     675     *
     676     * @param string $query Query coming in
     677     *
     678     * @return string Translated Query
     679     */
     680    function translate_column_type($query)
     681    {
     682        if ( stripos($query, "LIKE '\_%'") > 0 ) {
     683            $start_pos = stripos($query, "LIKE '\_%'");
     684            $end_pos = $start_pos + 10;
     685            $str = "LIKE '[_]%'";
     686            $query = substr_replace($query, $str, $start_pos, ($end_pos - $start_pos));
     687        }
     688        return $query;
     689    }
     690
     691
     692    /**
     693     * Remove group by stmt in certain queries as T-SQL will
     694     * want all column names to execute query properly
     695     *
     696     * FIXES: Column 'wp_posts.post_author' is invalid in the select list because
     697     * it is not contained in either an aggregate function or the GROUP BY clause.
     698     *
     699     * @since 2.7.1
     700     *
     701     * @param string $query Query coming in
     702     *
     703     * @return string Translated Query
     704     */
     705    function translate_remove_groupby($query)
     706    {
     707        $query = str_ireplace("GROUP BY {$this->prefix}posts.ID ", ' ', $query);
     708        // Fixed query for archives widgets.
     709        $query = str_ireplace(
     710            'GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date DESC',
     711            'GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY month DESC, year DESC',
     712            $query
     713        );
     714        return $query;
     715    }
     716
     717
     718    /**
     719     * When INSERTING 0000-00-00 00:00:00 or '' for datetime SQL Server says wtf
     720     * because it's null value begins at 1900-01-01...so lets change this to current time.
     721     *
     722     * @since 2.7.1
     723     *
     724     * @param string $query Query coming in
     725     *
     726     * @return string Translated Query
     727     */
     728    function translate_insert_nulltime($query)
     729    {
     730        if ( stripos($query, 'INSERT') === 0 ) {
     731            // Lets grab the fields to be inserted into and their position
     732            // based on the csv.
     733            $first_paren = stripos($query, '(', 11) + 1;
     734            $last_paren = $this->get_matching_paren($query, $first_paren);
     735            $fields = explode(',',substr($query, $first_paren, ($last_paren - $first_paren)));
     736            $date_fields = array();
     737            $date_fields_map = $this->fields_map->by_type('date');
     738            foreach ( $fields as $key => $field ) {
     739                $field = trim($field);
     740
     741                if ( in_array($field, $date_fields_map) ) {
     742                    $date_fields[] = array('pos' => $key, 'field' => $field);
     743                }
     744            }
     745            // we have date fields to check
     746            if ( count($date_fields) > 0 ) {
     747                // we need to get the values
     748                $values_pos = stripos($query, 'VALUES');
     749                $first_paren = stripos($query, '(', $values_pos);
     750                $last_paren = $this->get_matching_paren($query, ($first_paren + 1));
     751                $values = explode(',',substr($query, ($first_paren+1), ($last_paren-($first_paren+1))));
     752                foreach ( $date_fields as $df ) {
     753                    $v = trim($values[$df['pos']]);
     754                    $quote = ( stripos($v, "'0000-00-00 00:00:00'") === 0 || $v === "''" ) ? "'" : '';
     755                    if ( stripos($v, '0000-00-00 00:00:00') === 0
     756                        || stripos($v, "'0000-00-00 00:00:00'") === 0
     757                        || $v === "''" ) {
     758                        if ( stripos($df['field'], 'gmt') > 0 ) {
     759                            $v = $quote.gmdate('Y-m-d H:i:s').$quote;
     760                        } else {
     761                            $v = $quote.date('Y-m-d H:i:s').$quote;
     762                        }
     763                    }
     764                    $values[$df['pos']] = $v;
     765                }
     766                $str = implode(',', $values);
     767                $query = substr_replace($query, $str, ($first_paren+1), ($last_paren-($first_paren+1)));
     768            }
     769        }
     770        return $query;
     771    }
     772
     773    /**
     774     * The data types text and varchar are incompatible in the equal to operator.
     775     * TODO: Have a check for the appropriate table of the field to
     776     * prevent plugin collision.
     777     *
     778     * @since 2.7.1
     779     *
     780     * @param string $query Query coming in
     781     *
     782     * @return string Translated Query
     783     */
     784    function translate_incompat_data_type($query)
     785    {
     786        // Lets check to make sure this is a SELECT query.
     787        if ( stripos($query, 'SELECT') === 0 ) {
     788            $operators = array(
     789                '='  => 'LIKE',
     790                '!=' => 'NOT LIKE',
     791                '<>' => 'NOT LIKE'
     792            );
     793
     794            foreach ( $this->fields_map->read() as $table => $table_fields ) {
     795                if ( is_array($table_fields) ) {
     796                    foreach ( $table_fields as $field => $field_meta ) {
     797                        if ( $field_meta['type'] == 'text' ) {
     798                            foreach ( $operators as $oper => $val ) {
     799                                $query = str_ireplace(
     800                                    $table . '.' . $field . ' ' . $oper,
     801                                    $table . '.' . $field . ' ' . $val,
     802                                    $query
     803                                );
     804                                $query = str_ireplace($field . ' ' . $oper, $field . ' ' . $val, $query);
     805                            }
     806                        }
     807                    }
     808                }
     809            }
     810        }
     811        return $query;
     812    }
     813
     814    /**
     815     * General create/alter query translations
     816     *
     817     * @since 2.7.1
     818     *
     819     * @param string $query Query coming in
     820     *
     821     * @return string Translated Query
     822     */
     823    function translate_create_queries($query)
     824    {
     825        if ( stripos($query, 'CREATE') !== 0 && stripos($query, 'ALTER') !== 0 ) {
     826            return $query;
     827        }
     828                // deal with alters in a bit
     829                if (stripos($query, 'ALTER') === 0) {
     830                        return $query;
     831                }
     832               
     833                // fix enum as it doesn't exist in T-SQL
     834                if ( stripos($query, 'enum(') !== false ) {
     835                        $enums = array_reverse($this->stripos_all($query, 'enum('));
     836                        foreach ( $enums as $start_pos ) {
     837                                $end = $this->get_matching_paren($query, $start_pos + 5);
     838                                // get values inside enum
     839                                $values = substr($query, $start_pos + 5, ($end - ($start_pos + 5)));
     840                                $values = explode(',', $values);
     841                                $all_int = true;
     842                                foreach ( $values as $value ) {
     843                                        $val = trim(str_replace("'", '', $value));
     844                                        if ( !is_numeric($val) || (int) $val != $val ) {
     845                                                $all_int = false;
     846                                        }
     847                                }
     848                                // if enum of ints create an appropriate int column otherwise create a varchar
     849                                if ( $all_int ) {
     850                                        $query = substr_replace($query, 'smallint', $start_pos, ($end + 1) - $start_pos);
     851                                } else {
     852                                        $query = substr_replace($query, 'varchar(255)', $start_pos, ($end + 1) - $start_pos);
     853                                }
     854                        }
     855                }
     856               
     857                // remove IF NOT EXISTS as that doesn't exist in T-SQL
     858                $query = str_ireplace(' IF NOT EXISTS', '', $query);
     859       
     860                //save array to file_maps
     861                $this->fields_map->update_for($query);
     862
     863                // change auto increment to indentity
     864        $start_positions = array_reverse($this->stripos_all($query, 'auto_increment'));
     865        if ( stripos($query, 'auto_increment') > 0 ) {
     866            foreach ($start_positions as $start_pos) {
     867                $query = substr_replace($query, 'IDENTITY(1,1)', $start_pos, 14);
     868            }
     869        }
     870        if ( stripos($query, 'AFTER') > 0 ) {
     871            $start_pos = stripos($query, 'AFTER');
     872            $query = substr($query, 0, $start_pos);
     873        }
     874        // replacement of certain data types and functions
     875        $fields = array(
     876            'int (',
     877            'int(',
     878            'index (',
     879            'index(',
     880        );
     881
     882        foreach ( $fields as $field ) {
     883            // reverse so that when we make changes it wont effect the next change.
     884            $start_positions = array_reverse($this->stripos_all($query, $field));
     885            foreach ( $start_positions as $start_pos ) {
     886                $first_paren = stripos($query, '(', $start_pos);
     887                $end_pos = $this->get_matching_paren($query, $first_paren + 1) + 1;
     888                if ( $field == 'index(' || $field == 'index (' ) {
     889                    $query = substr_replace($query, '', $start_pos, $end_pos - $start_pos);
     890                } else {
     891                    $query = substr_replace($query, rtrim(rtrim($field,'('), ' '), $start_pos, ($end_pos - $start_pos));
     892                }
     893            }
     894        }
     895
     896        $query = str_ireplace("'0000-00-00 00:00:00'", 'getdate()', $query);
     897
     898        // strip unsigned
     899        $query = str_ireplace("unsigned ", '', $query);
     900
     901        // strip collation, engine type, etc from end of query
     902        $pos = stripos($query, '(', stripos($query, 'TABLE '));
     903        $end = $this->get_matching_paren($query, $pos + 1);
     904        $query = substr_replace($query, ');', $end);
     905
     906        $query = str_ireplace("DEFAULT CHARACTER SET utf8", '', $query);
     907        $query = str_ireplace(" CHARACTER SET utf8", '', $query);
     908               
     909                // add collation
     910                $ac_types = array('tinytext', 'longtext', 'mediumtext', 'varchar');
     911                foreach ( $ac_types as $ac_type ) {
     912                        $start_positions = array_reverse($this->stripos_all($query, $ac_type));
     913                        foreach ( $start_positions as $start_pos ) {
     914                                if ($ac_type == 'varchar') {
     915                                        $end = $this->get_matching_paren($query, $start_pos + (strlen($ac_type) + 1));
     916                                        $sub = substr($query, $end + 2, 7);
     917                                        $end_pos = $end + 1;
     918                                } else {
     919                                        $query = substr_replace($query, 'TEXT', $start_pos, strlen($ac_type));
     920                                        $sub = substr($query, $start_pos + 5, 7);
     921                                        $end_pos = $start_pos + 4;
     922                                }
     923                                if ( $sub !== 'COLLATE' ) {
     924                                        $query = $this->add_collation($query, $end_pos);
     925                                }
     926                        }
     927                }
     928
     929        $keys = array();
     930        $table_pos = stripos($query, ' TABLE ') + 6;
     931        $table = substr($query, $table_pos, stripos($query, '(', $table_pos) - $table_pos);
     932        $table = trim($table);
     933               
     934                $reserved_words = array('public');
     935                // get column names to check for reserved words to encapsulate with [ ]
     936                foreach ( $this->fields_map->read() as $table_name => $table_fields ) {
     937            if ( $table_name == $table && is_array($table_fields) ) {
     938                foreach ( $table_fields as $field => $field_meta ) {
     939                    if ( in_array($field, $reserved_words) ) {
     940                                                $query = str_ireplace($field, "[{$field}]", $query);
     941                                        }
     942                }
     943            }
     944        }
     945
     946        // get primary key constraints
     947        if ( stripos($query, 'PRIMARY KEY') > 0) {
     948            $start_positions = $this->stripos_all($query, 'PRIMARY KEY');
     949            foreach ( $start_positions as $start_pos ) {
     950                $start = stripos($query, '(', $start_pos);
     951                $end_paren = $this->get_matching_paren($query, $start + 1);
     952                $field = explode(',', substr($query, $start + 1, $end_paren - ($start + 1)));
     953                                foreach ( $field as $k => $v ) {
     954                                        if ( stripos($v, '(') !== false ) {
     955                                                $field[$k] = preg_replace('/\(.*\)/', '', $v);
     956                                        }
     957                                }
     958                $keys[] = array('type' => 'PRIMARY KEY', 'pos' => $start_pos, 'field' => $field);
     959            }
     960        }
     961        // get unique key constraints
     962        if ( stripos($query, 'UNIQUE KEY') > 0 ) {
     963            $start_positions = $this->stripos_all($query, 'UNIQUE KEY');
     964            foreach ($start_positions as $start_pos) {
     965                $start = stripos($query, '(', $start_pos);
     966                $end_paren = $this->get_matching_paren($query, $start + 1);
     967                $field = explode(',', substr($query, $start + 1, $end_paren - ($start + 1)));
     968                                foreach ( $field as $k => $v ) {
     969                                        if ( stripos($v, '(') !== false ) {
     970                                                $field[$k] = preg_replace('/\(.*\)/', '', $v);
     971                                        }
     972                                }
     973                $keys[] = array('type' => 'UNIQUE KEY', 'pos' => $start_pos, 'field' => $field);
     974            }
     975        }
     976        // get key constraints
     977        if ( stripos($query, 'KEY') > 0) {
     978            $start_positions = $this->stripos_all($query, 'KEY');
     979            foreach ( $start_positions as $start_pos ) {
     980                if ( substr($query, $start_pos - 7, 6) !== 'UNIQUE'
     981                    && substr($query, $start_pos - 8, 7) !== 'PRIMARY'
     982                    && (substr($query, $start_pos - 1, 1) == ' ' || substr($query, $start_pos - 1, 1) == "\n") ) {
     983                    $start = stripos($query, '(', $start_pos);
     984                    $end_paren = $this->get_matching_paren($query, $start + 1);
     985                    $field = explode(',', substr($query, $start + 1, $end_paren - ($start + 1)));
     986                                        foreach ( $field as $k => $v ) {
     987                                                if ( stripos($v, '(') !== false ) {
     988                                                        $field[$k] = preg_replace('/\(.*\)/', '', $v);
     989                                                }
     990                                        }
     991                    $keys[] = array('type' => 'KEY', 'pos' => $start_pos, 'field' => $field);
     992                }
     993            }
     994        }
     995
     996        $count = count($keys);
     997        $add_primary = false;
     998        $key_str = '';
     999        $lowest_start_pos = false;
     1000        $unwanted = array(
     1001            'slug',
     1002            'name',
     1003            'term_id',
     1004            'taxonomy',
     1005            'term_taxonomy_id',
     1006            'comment_approved',
     1007            'comment_post_ID',
     1008            'comment_approved',
     1009            'link_visible',
     1010            'post_id',
     1011            'meta_key',
     1012            'post_type',
     1013            'post_status',
     1014            'post_date',
     1015            'ID',
     1016            'post_name',
     1017            'post_parent',
     1018            'user_login',
     1019            'user_nicename',
     1020            'user_id',
     1021        );
     1022        for ( $i = 0; $i < $count; $i++ ) {
     1023            if ( $keys[$i]['pos'] < $lowest_start_pos || $lowest_start_pos === false ) {
     1024                $lowest_start_pos = $keys[$i]['pos'];
     1025            }
     1026            if ( $keys[$i]['type'] == 'PRIMARY KEY' ) {
     1027                $add_primary = true;
     1028            }
     1029            switch ( $keys[$i]['type'] ) {
     1030                case 'PRIMARY KEY':
     1031                                        $str = "CONSTRAINT [" . $table . "_" . implode('_', $keys[$i]['field']) . "] PRIMARY KEY CLUSTERED (" . implode(',', $keys[$i]['field']) . ") WITH (IGNORE_DUP_KEY = OFF)";
     1032                                        if (!$this->azure ) {
     1033                                                $str .= " ON [PRIMARY]";
     1034                                        }
     1035                break;
     1036                case 'UNIQUE KEY':
     1037                    $check = true;
     1038                    foreach ( $keys[$i]['field'] as $field ) {
     1039                        if ( in_array($field, $unwanted) ) {
     1040                            $check = false;
     1041                        }
     1042                    }
     1043                    if ( $check ) {
     1044                        $str = "CONSTRAINT [" . $table . "_" . implode('_', $keys[$i]['field']) . "] UNIQUE NONCLUSTERED (" . implode(',', $keys[$i]['field']) . ")";
     1045                    } else {
     1046                        $str = '';
     1047                    }
     1048                break;
     1049                                case 'KEY':
     1050                                        // CREATE NONCLUSTERED INDEX index_name ON table(col1,col2)
     1051                                        $check = true;
     1052                                        $str = '';
     1053                    foreach ( $keys[$i]['field'] as $field ) {
     1054                        if ( in_array($field, $unwanted) ) {
     1055                            $check = false;
     1056                        }
     1057                    }
     1058                    if ( $check ) {
     1059                                                if ( !is_array($this->following_query) && $this->following_query === false ) {
     1060                                                        $this->following_query = array();
     1061                                                } elseif (!is_array($this->following_query)) {
     1062                                                        $this->following_query = array($this->following_query);
     1063                                                }
     1064                                                $this->following_query[] = "CREATE NONCLUSTERED INDEX " .
     1065                                                $table . "_" . implode('_', $keys[$i]['field']) .
     1066                                                " ON ".$table."(".implode(',', $keys[$i]['field']).")";
     1067                    }
     1068                                break;
     1069            }
     1070            if ( $i !== $count - 1 && $str !== '' ) {
     1071                $str .= ',';
     1072            }
     1073            $key_str .= $str . "\n";
     1074        }
     1075        if ( $key_str !== '' ) {
     1076            if ( $add_primary && !$this->azure ) {
     1077                $query = substr_replace($query, $key_str . ") ON [PRIMARY];", $lowest_start_pos);
     1078            } else {
     1079                $query = substr_replace($query, $key_str . ");", $lowest_start_pos);
     1080            }
     1081        }
     1082
     1083        return $query;
     1084    }
     1085
     1086    /**
     1087     * Given a first parenthesis ( ...will find its matching closing paren )
     1088     *
     1089     * @since 2.7.1
     1090     *
     1091     * @param string $str given string
     1092     * @param int $start_pos position of where desired starting paren begins+1
     1093     *
     1094     * @return int position of matching ending parenthesis
     1095     */
     1096    function get_matching_paren($str, $start_pos)
     1097    {
     1098        $count = strlen($str);
     1099        $bracket = 1;
     1100        for ( $i = $start_pos; $i < $count; $i++ ) {
     1101            if ( $str[$i] == '(' ) {
     1102                $bracket++;
     1103            } elseif ( $str[$i] == ')' ) {
     1104                $bracket--;
     1105            }
     1106            if ( $bracket == 0 ) {
     1107                return $i;
     1108            }
     1109        }
     1110    }
     1111
     1112    /**
     1113     * Get the Aliases in a query
     1114     * E.G. Field1 AS yyear, Field2 AS mmonth
     1115     * will return array with yyear and mmonth
     1116     *
     1117     * @since 2.7.1
     1118     *
     1119     * @param string $str a query
     1120     *
     1121     * @return array array of aliases in a query
     1122     */
     1123    function get_as_fields($query)
     1124    {
     1125        $arr = array();
     1126        $tok = preg_split('/[\s,]+/', $query);
     1127        $count = count($tok);
     1128        for ( $i = 0; $i < $count; $i++ ) {
     1129            if ( strtolower($tok[$i]) === 'as' ) {
     1130                $arr[] = $tok[($i + 1)];
     1131            }
     1132        }
     1133        return $arr;
     1134    }
     1135
     1136    /**
     1137    * Fix for SQL Server returning null values with one space.
     1138    * Fix for SQL Server returning datetime fields with milliseconds.
     1139    * Fix for SQL Server returning integer fields as integer (mysql returns as string)
     1140    *
     1141    * @since 2.7.1
     1142    *
     1143    * @param array $result_set result set array of an executed query
     1144    *
     1145    * @return array result set array with modified fields
     1146    */
     1147    function fix_results($result_set)
     1148    {
     1149        // If empty bail early.
     1150        if ( is_null($result_set)) {
     1151            return false;
     1152        }
     1153        if ( is_array($result_set) && empty($result_set) ) {
     1154            return array();
     1155        }
     1156        $map_fields = $this->fields_map->by_type('date');
     1157        $fields = array_keys(get_object_vars(current($result_set)));
     1158        foreach ( $result_set as $key => $result ) {
     1159            // Remove milliseconds
     1160            foreach ( $map_fields as $date_field ) {
     1161                if ( isset($result->$date_field) ) {
     1162                    // date_format is a PHP5 function. sqlsrv is only PHP5 compat
     1163                    // the result set for datetime columns is a PHP DateTime object, to extract
     1164                    // the string we need to use date_format().
     1165                                        if ( is_object($result->$date_field) ) {
     1166                                                $result_set[$key]->$date_field = date_format($result->$date_field, 'Y-m-d H:i:s');
     1167                                        }
     1168                }
     1169            }
     1170            // Check for null values being returned as space and change integers to strings (to mimic mysql results)
     1171            foreach ( $fields as $field ) {
     1172                if ( $field == 'crdate' || $field == 'refdate' ) {
     1173                    $result_set[$key]->$field = date_format($result->$field, 'Y-m-d H:i:s');
     1174                }
     1175                if ( $result->$field === ' ' ) {
     1176                    $result->$field = '';
     1177                }
     1178                if ( is_int($result->$field) ) {
     1179                    $result->$field = (string) $result->$field;
     1180                }
     1181            }
     1182        }
     1183        return $result_set;
     1184    }
     1185
     1186    /**
     1187     * Check to see if an INSERT query has multiple VALUES blocks. If so we need create
     1188     * seperate queries for each.
     1189     * @since 2.7.1
     1190     *
     1191     * @param string $query Query coming in
     1192     *
     1193     * @return array array of insert queries
     1194     */
     1195    function split_insert_values($query)
     1196    {
     1197        $arr = array();
     1198        if ( stripos($query, 'INSERT') === 0 ) {
     1199            $first = substr($query, 0, (stripos($query, 'VALUES') + 7));
     1200            $values = substr($query, (stripos($query, 'VALUES') + 7));
     1201            $arr = preg_split('/\),\s+\(/', $values);
     1202            foreach ( $arr as $k => $v ) {
     1203                                if ( substr($v, -1) !== ')' ) {
     1204                                        $v = $v . ')';
     1205                                }
     1206                               
     1207                                if ( substr($v, 0, 1) !== '(' ) {
     1208                                        $v = '(' . $v;
     1209                                }
     1210                               
     1211                $arr[$k] = $first . $v;
     1212            }
     1213        }
     1214        if ( count($arr) < 2 ) {
     1215            return $query;
     1216        }
     1217        return $arr;
     1218    }
     1219
     1220    /**
     1221     * Check query to make sure translations weren't made to INSERT query values
     1222     * If so replace translation with original data.
     1223     * E.G. INSERT INTO wp_posts (wp_title) VALUES ('SELECT * FROM wp_posts LIMIT 1');
     1224     * The translations may change the value data to SELECT TOP 1 FROM wp_posts...in this case
     1225     * we don't want that to happen.
     1226     *
     1227     * @since 2.7.1
     1228     *
     1229     * @param string $query Query coming in
     1230     *
     1231     * @return string Verified Query
     1232     */
     1233    function verify_insert($query)
     1234    {
     1235        $values_pos = stripos($query, 'VALUES');
     1236        $first_paren = stripos($query, '(', $values_pos);
     1237        $last_paren = $this->get_matching_paren($query, $first_paren + 1);
     1238        $values = explode(',', substr($query, ($first_paren + 1), ($last_paren-($first_paren + 1))));
     1239        if ( count($this->prepare_args) !== count($values) ) {
     1240            return $query;
     1241        }
     1242        $i = 0;
     1243        foreach ( $values as $k => $value ) {
     1244            $value = trim($value);
     1245            foreach ( $this->prepare_args as $r => $arg ) {
     1246                if ( $k == $i && $arg !== $value ) {
     1247                    if ( $arg !== '' && $arg !== '0000-00-00 00:00:00' ) {
     1248                        $values[$k] = "'" . $arg . "'";
     1249                    }
     1250                }
     1251                $i++;
     1252            }
     1253        }
     1254        $str = implode(',', $values);
     1255        $query = substr_replace($query, $str, ($first_paren + 1), ($last_paren - ($first_paren + 1)));
     1256        return $query;
     1257    }
     1258
     1259    /**
     1260     * Check query to make sure translations weren't made to UPDATE query values
     1261     * If so replace translation with original data.
     1262     * E.G. UPDATE wp_posts SET post_title = 'SELECT * FROM wp_posts LIMIT 1' WHERE post_id = 1;
     1263     * The translations may change the value data to SELECT TOP 1 FROM wp_posts...in this case
     1264     * we don't want that to happen
     1265     *
     1266     * @since 2.7.1
     1267     *
     1268     * @param string $query Query coming in
     1269     *
     1270     * @return string Verified Query
     1271     */
     1272    function verify_update($query)
     1273    {
     1274        $values = array();
     1275        $keys = array_keys($this->update_data);
     1276
     1277        $start = stripos($query, 'SET') + 3;
     1278        $end = strripos($query, 'WHERE');
     1279        $sub = substr($query, $start, $end - $start);
     1280        $arr = explode(', ', $sub);
     1281        foreach ( $arr as $k => $v ) {
     1282            $v = trim($v);
     1283            $st = stripos($v, ' =');
     1284            $sv = substr($v, 0, $st);
     1285            if ( in_array($sv, $keys) ) {
     1286                $sp = substr($v, $st + 4, -1);
     1287                $values[] = str_replace("'", "''", $sp);
     1288            }
     1289        }
     1290        $update_data = array_values($this->update_data);
     1291        if ( count($update_data) == count($values) ) {
     1292            foreach ( $update_data as $key => $val ) {
     1293                if ( $update_data[$key] !== $values[$key] ) {
     1294                    $values[$key] = str_replace("''", "'", $update_data[$key]);
     1295                }
     1296            }
     1297
     1298            foreach ( $values as $y => $vt ) {
     1299                $values[$y] = $keys[$y] . " = '" . $vt . "'";
     1300            }
     1301            $str = implode(', ', $values) . ' ';
     1302            $query = substr_replace($query, $str, ($start+1), ($end-($start+1)));
     1303        }
     1304        return $query;
     1305    }
     1306
     1307    /**
     1308     * Add collation for a field definition within a CREATE/ALTER query
     1309     *
     1310     * @since 2.8
     1311     * @param $type
     1312     *
     1313     * @return string
     1314     */
     1315    function add_collation($query, $pos)
     1316    {
     1317        $query = substr_replace($query, ' COLLATE Latin1_General_BIN', $pos, 0);
     1318        return $query;
     1319    }
     1320       
     1321    /**
     1322     * Describe wrapper
     1323     *
     1324     * @since 2.8.5
     1325     * @param $table
     1326     *
     1327     * @return string
     1328     */
     1329        function describe($table)
     1330        {
     1331                $sql = "SELECT
     1332                        c.name AS Field
     1333                        ,t.name + t.length_string AS Type
     1334                        ,CASE c.is_nullable WHEN 1 THEN 'YES' ELSE 'NO' END AS [Null]
     1335                        ,CASE
     1336                                WHEN EXISTS (SELECT * FROM sys.key_constraints AS kc
     1337                                                           INNER JOIN sys.index_columns AS ic ON kc.unique_index_id = ic.index_id AND kc.parent_object_id = ic.object_id
     1338                                                           WHERE kc.type = 'PK' AND ic.column_id = c.column_id AND c.object_id = ic.object_id)
     1339                                                           THEN 'PRI'
     1340                                WHEN EXISTS (SELECT * FROM sys.key_constraints AS kc
     1341                                                           INNER JOIN sys.index_columns AS ic ON kc.unique_index_id = ic.index_id AND kc.parent_object_id = ic.object_id
     1342                                                           WHERE kc.type <> 'PK' AND ic.column_id = c.column_id AND c.object_id = ic.object_id)
     1343                                                           THEN 'UNI'
     1344                                ELSE ''
     1345                        END AS [Key]
     1346                        ,ISNULL((
     1347                                SELECT TOP(1)
     1348                                        dc.definition
     1349                                FROM sys.default_constraints AS dc
     1350                                WHERE dc.parent_column_id = c.column_id AND c.object_id = dc.parent_object_id)
     1351                        ,'') AS [Default]
     1352                        ,CASE
     1353                                WHEN EXISTS (
     1354                                        SELECT
     1355                                                *
     1356                                        FROM sys.identity_columns AS ic
     1357                                        WHERE ic.column_id = c.column_id AND c.object_id = ic.object_id)
     1358                                                THEN 'auto_increment'
     1359                                ELSE ''
     1360                        END AS Extra
     1361                FROM sys.columns AS c
     1362                CROSS APPLY (
     1363                        SELECT
     1364                                t.name AS n1
     1365                                ,CASE
     1366                                        -- Types with length
     1367                                        WHEN c.max_length > 0 AND t.name IN ('varchar', 'char', 'varbinary', 'binary') THEN '(' + CAST(c.max_length AS VARCHAR) + ')'
     1368                                        WHEN c.max_length > 0 AND t.name IN ('nvarchar', 'nchar') THEN '(' + CAST(c.max_length/2 AS VARCHAR) + ')'
     1369                                        WHEN c.max_length < 0 AND t.name IN ('nvarchar', 'varchar', 'varbinary') THEN '(max)'
     1370                                        -- Types with precision & scale
     1371                                        WHEN t.name IN ('decimal', 'numeric') THEN '(' + CAST(c.precision AS VARCHAR) + ',' + CAST(c.scale AS VARCHAR) + ')'
     1372                                        -- Types with only precision
     1373                                        WHEN t.name IN ('float') THEN '(' + CAST(c.precision AS VARCHAR) + ')'
     1374                                        -- Types with only scale
     1375                                        WHEN t.name IN ('datetime2', 'time', 'datetimeoffset') THEN '(' + CAST(c.scale AS VARCHAR) + ')'
     1376                                        -- The rest take no arguments
     1377                                        ELSE ''
     1378                                END AS length_string
     1379                                ,*
     1380                        FROM sys.types AS t
     1381                        WHERE t.system_type_id = c.system_type_id AND t.system_type_id = t.user_type_id
     1382                ) AS t
     1383                WHERE object_id = OBJECT_ID('{$table}');";
     1384                return $sql;
     1385        }
     1386
     1387    /**
     1388     * Get all occurrences(positions) of a string within a string
     1389     *
     1390     * @since 2.8
     1391     * @param $type
     1392     *
     1393     * @return array
     1394     */
     1395    function stripos_all($haystack, $needle, $offset = 0)
     1396    {
     1397                $arr = array();
     1398                while ( $offset !== false ) {
     1399                        $pos = stripos($haystack, $needle, $offset);
     1400                        if ( $pos !== false ) {
     1401                                $arr[] = $pos;
     1402                                $pos = $pos + strlen($needle);
     1403                        }
     1404                        $offset = $pos;
     1405                }
     1406        return $arr;
     1407    }
     1408}
     1409
     1410if ( !function_exists('str_ireplace') ) {
     1411    /**
     1412     * PHP 4 Compatible str_ireplace function
     1413     * found in php.net comments
     1414     *
     1415     * @since 2.7.1
     1416     *
     1417     * @param string $search what needs to be replaced
     1418     * @param string $replace replacing value
     1419     * @param string $subject string to perform replace on
     1420     *
     1421     * @return string the string with replacements
     1422     */
     1423    function str_ireplace($search, $replace, $subject)
     1424    {
     1425        $token = chr(1);
     1426        $haystack = strtolower($subject);
     1427        $needle = strtolower($search);
     1428        while ( $pos = strpos($haystack, $needle) !== FALSE ) {
     1429            $subject = substr_replace($subject, $token, $pos, strlen($search));
     1430            $haystack = substr_replace($haystack, $token, $pos, strlen($search));
     1431        }
     1432        return str_replace($token, $replace, $subject);
     1433    }
     1434}
     1435
     1436if ( !function_exists('stripos') ) {
     1437    /**
     1438     * PHP 4 Compatible stripos function
     1439     * found in php.net comments
     1440     *
     1441     * @since 2.7.1
     1442     *
     1443     * @param string $str the string to search in
     1444     * @param string $needle what we are looking for
     1445     * @param int $offset starting position
     1446     *
     1447     * @return int position of needle if found. FALSE if not found.
     1448     */
     1449    function stripos($str, $needle, $offset = 0)
     1450    {
     1451        return strpos(strtolower($str), strtolower($needle), $offset);
     1452    }
     1453}
     1454
     1455if ( !function_exists('strripos') ) {
     1456    /**
     1457     * PHP 4 Compatible strripos function
     1458     * found in php.net comments
     1459     *
     1460     * @since 2.7.1
     1461     *
     1462     * @param string $haystack the string to search in
     1463     * @param string $needle what we are looking for
     1464     *
     1465     * @return int position of needle if found. FALSE if not found.
     1466     */
     1467    function strripos($haystack, $needle, $offset = 0)
     1468    {
     1469        if ( !is_string($needle) ) {
     1470            $needle = chr(intval($needle));
     1471        }
     1472        if ( $offset < 0 ) {
     1473            $temp_cut = strrev(substr($haystack, 0, abs($offset)));
     1474        } else {
     1475            $temp_cut = strrev(substr($haystack, 0, max((strlen($haystack) - $offset ), 0)));
     1476        }
     1477        if ( stripos($temp_cut, strrev($needle)) === false ) {
     1478            return false;
     1479        } else {
     1480            $found = stripos($temp_cut, strrev($needle));
     1481        }
     1482        $pos = ( strlen($haystack) - ($found + $offset + strlen($needle)) );
     1483        return $pos;
     1484    }
     1485}
  • wp-includes/wp-db/mysql/mysql.php

    Property changes on: wp-includes\wp-db\mssql\translations\translations.php
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
     1<?php
     2/**
     3 * WordPress DB Class
     4 *
     5 * Original code from {@link http://php.justinvincent.com Justin Vincent (justin@visunet.ie)}
     6 *
     7 * @package WordPress
     8 * @subpackage Database
     9 * @since 0.71
     10 */
     11
     12/**
     13 * @since 0.71
     14 */
     15define('EZSQL_VERSION', 'WP1.25');
     16
     17/**
     18 * @since 0.71
     19 */
     20define('OBJECT', 'OBJECT', true);
     21
     22/**
     23 * @since {@internal Version Unknown}}
     24 */
     25define('OBJECT_K', 'OBJECT_K', false);
     26
     27/**
     28 * @since 0.71
     29 */
     30define('ARRAY_A', 'ARRAY_A', false);
     31
     32/**
     33 * @since 0.71
     34 */
     35define('ARRAY_N', 'ARRAY_N', false);
     36
     37/**
     38 * WordPress Database Access Abstraction Object
     39 *
     40 * It is possible to replace this class with your own
     41 * by setting the $wpdb global variable in wp-content/db.php
     42 * file with your class. You can name it wpdb also, since
     43 * this file will not be included, if the other file is
     44 * available.
     45 *
     46 * @link http://codex.wordpress.org/Function_Reference/wpdb_Class
     47 *
     48 * @package WordPress
     49 * @subpackage Database
     50 * @since 0.71
     51 * @final
     52 */
     53class wpdb {
     54
     55        /**
     56         * Whether to show SQL/DB errors
     57         *
     58         * @since 0.71
     59         * @access private
     60         * @var bool
     61         */
     62        var $show_errors = false;
     63
     64        /**
     65         * Whether to suppress errors during the DB bootstrapping.
     66         *
     67         * @access private
     68         * @since {@internal Version Unknown}}
     69         * @var bool
     70         */
     71        var $suppress_errors = false;
     72
     73        /**
     74         * The last error during query.
     75         *
     76         * @since {@internal Version Unknown}}
     77         * @var string
     78         */
     79        var $last_error = '';
     80
     81        /**
     82         * Amount of queries made
     83         *
     84         * @since 1.2.0
     85         * @access private
     86         * @var int
     87         */
     88        var $num_queries = 0;
     89
     90        /**
     91         * Saved result of the last query made
     92         *
     93         * @since 1.2.0
     94         * @access private
     95         * @var array
     96         */
     97        var $last_query;
     98
     99        /**
     100         * Saved info on the table column
     101         *
     102         * @since 1.2.0
     103         * @access private
     104         * @var array
     105         */
     106        var $col_info;
     107
     108        /**
     109         * Saved queries that were executed
     110         *
     111         * @since 1.5.0
     112         * @access private
     113         * @var array
     114         */
     115        var $queries;
     116
     117        /**
     118         * WordPress table prefix
     119         *
     120         * You can set this to have multiple WordPress installations
     121         * in a single database. The second reason is for possible
     122         * security precautions.
     123         *
     124         * @since 0.71
     125         * @access private
     126         * @var string
     127         */
     128        var $prefix = '';
     129
     130        /**
     131         * Whether the database queries are ready to start executing.
     132         *
     133         * @since 2.5.0
     134         * @access private
     135         * @var bool
     136         */
     137        var $ready = false;
     138
     139        /**
     140         * WordPress Posts table
     141         *
     142         * @since 1.5.0
     143         * @access public
     144         * @var string
     145         */
     146        var $posts;
     147
     148        /**
     149         * WordPress Users table
     150         *
     151         * @since 1.5.0
     152         * @access public
     153         * @var string
     154         */
     155        var $users;
     156
     157        /**
     158         * WordPress Categories table
     159         *
     160         * @since 1.5.0
     161         * @access public
     162         * @var string
     163         */
     164        var $categories;
     165
     166        /**
     167         * WordPress Post to Category table
     168         *
     169         * @since 1.5.0
     170         * @access public
     171         * @var string
     172         */
     173        var $post2cat;
     174
     175        /**
     176         * WordPress Comments table
     177         *
     178         * @since 1.5.0
     179         * @access public
     180         * @var string
     181         */
     182        var $comments;
     183
     184        /**
     185         * WordPress Links table
     186         *
     187         * @since 1.5.0
     188         * @access public
     189         * @var string
     190         */
     191        var $links;
     192
     193        /**
     194         * WordPress Options table
     195         *
     196         * @since 1.5.0
     197         * @access public
     198         * @var string
     199         */
     200        var $options;
     201
     202        /**
     203         * WordPress Post Metadata table
     204         *
     205         * @since {@internal Version Unknown}}
     206         * @access public
     207         * @var string
     208         */
     209        var $postmeta;
     210
     211        /**
     212         * WordPress Comment Metadata table
     213         *
     214         * @since 2.9
     215         * @access public
     216         * @var string
     217         */
     218        var $commentmeta;
     219
     220        /**
     221         * WordPress User Metadata table
     222         *
     223         * @since 2.3.0
     224         * @access public
     225         * @var string
     226         */
     227        var $usermeta;
     228
     229        /**
     230         * WordPress Terms table
     231         *
     232         * @since 2.3.0
     233         * @access public
     234         * @var string
     235         */
     236        var $terms;
     237
     238        /**
     239         * WordPress Term Taxonomy table
     240         *
     241         * @since 2.3.0
     242         * @access public
     243         * @var string
     244         */
     245        var $term_taxonomy;
     246
     247        /**
     248         * WordPress Term Relationships table
     249         *
     250         * @since 2.3.0
     251         * @access public
     252         * @var string
     253         */
     254        var $term_relationships;
     255
     256        /**
     257         * List of WordPress tables
     258         *
     259         * @since {@internal Version Unknown}}
     260         * @access private
     261         * @var array
     262         */
     263        var $tables = array('users', 'usermeta', 'posts', 'categories', 'post2cat', 'comments', 'links', 'link2cat', 'options',
     264                        'postmeta', 'terms', 'term_taxonomy', 'term_relationships', 'commentmeta');
     265
     266        /**
     267         * List of deprecated WordPress tables
     268         *
     269         * @since 2.9.0
     270         * @access private
     271         * @var array
     272         */
     273        var $old_tables = array('categories', 'post2cat', 'link2cat');
     274
     275
     276        /**
     277         * Format specifiers for DB columns. Columns not listed here default to %s.  Initialized in wp-settings.php.
     278         *
     279         * Keys are colmn names, values are format types: 'ID' => '%d'
     280         *
     281         * @since 2.8.0
     282         * @see wpdb:prepare()
     283         * @see wpdb:insert()
     284         * @see wpdb:update()
     285         * @access public
     286         * @war array
     287         */
     288        var $field_types = array();
     289
     290        /**
     291         * Database table columns charset
     292         *
     293         * @since 2.2.0
     294         * @access public
     295         * @var string
     296         */
     297        var $charset;
     298
     299        /**
     300         * Database table columns collate
     301         *
     302         * @since 2.2.0
     303         * @access public
     304         * @var string
     305         */
     306        var $collate;
     307
     308        /**
     309         * Whether to use mysql_real_escape_string
     310         *
     311         * @since 2.8.0
     312         * @access public
     313         * @var bool
     314         */
     315        var $real_escape = false;
     316
     317        /**
     318         * Database Username
     319         *
     320         * @since 2.9.0
     321         * @access private
     322         * @var string
     323         */
     324        var $dbuser;
     325
     326        /**
     327         * Connects to the database server and selects a database
     328         *
     329         * PHP4 compatibility layer for calling the PHP5 constructor.
     330         *
     331         * @uses wpdb::__construct() Passes parameters and returns result
     332         * @since 0.71
     333         *
     334         * @param string $dbuser MySQL database user
     335         * @param string $dbpassword MySQL database password
     336         * @param string $dbname MySQL database name
     337         * @param string $dbhost MySQL database host
     338         */
     339        function wpdb($dbuser, $dbpassword, $dbname, $dbhost) {
     340                return $this->__construct($dbuser, $dbpassword, $dbname, $dbhost);
     341        }
     342
     343        /**
     344         * Connects to the database server and selects a database
     345         *
     346         * PHP5 style constructor for compatibility with PHP5. Does
     347         * the actual setting up of the class properties and connection
     348         * to the database.
     349         *
     350         * @since 2.0.8
     351         *
     352         * @param string $dbuser MySQL database user
     353         * @param string $dbpassword MySQL database password
     354         * @param string $dbname MySQL database name
     355         * @param string $dbhost MySQL database host
     356         */
     357        function __construct($dbuser, $dbpassword, $dbname, $dbhost) {
     358                register_shutdown_function(array(&$this, "__destruct"));
     359
     360                if ( defined('WP_DEBUG') and WP_DEBUG == true )
     361                        $this->show_errors();
     362
     363                if ( defined('DB_CHARSET') )
     364                        $this->charset = DB_CHARSET;
     365
     366                if ( defined('DB_COLLATE') )
     367                        $this->collate = DB_COLLATE;
     368
     369                $this->dbuser = $dbuser;
     370
     371                $this->dbh = @mysql_connect($dbhost, $dbuser, $dbpassword, true);
     372                if (!$this->dbh) {
     373                        $this->bail(sprintf(/*WP_I18N_DB_CONN_ERROR*/"
     374<h1>Error establishing a database connection</h1>
     375<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>
     376<ul>
     377        <li>Are you sure you have the correct username and password?</li>
     378        <li>Are you sure that you have typed the correct hostname?</li>
     379        <li>Are you sure that the database server is running?</li>
     380</ul>
     381<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>
     382"/*/WP_I18N_DB_CONN_ERROR*/, $dbhost), 'db_connect_fail');
     383                        return;
     384                }
     385
     386                $this->ready = true;
     387
     388                if ( $this->has_cap( 'collation' ) ) {
     389                        if ( !empty($this->charset) ) {
     390                                if ( function_exists('mysql_set_charset') ) {
     391                                        mysql_set_charset($this->charset, $this->dbh);
     392                                        $this->real_escape = true;
     393                                } else {
     394                                        $collation_query = "SET NAMES '{$this->charset}'";
     395                                        if ( !empty($this->collate) )
     396                                                $collation_query .= " COLLATE '{$this->collate}'";
     397                                        $this->query($collation_query);
     398                                }
     399                        }
     400                }
     401
     402                $this->select($dbname);
     403        }
     404
     405        /**
     406         * PHP5 style destructor and will run when database object is destroyed.
     407         *
     408         * @since 2.0.8
     409         *
     410         * @return bool Always true
     411         */
     412        function __destruct() {
     413                return true;
     414        }
     415
     416        /**
     417         * Sets the table prefix for the WordPress tables.
     418         *
     419         * Also allows for the CUSTOM_USER_TABLE and CUSTOM_USER_META_TABLE to
     420         * override the WordPress users and usersmeta tables that would otherwise be determined by the $prefix.
     421         *
     422         * @since 2.5.0
     423         *
     424         * @param string $prefix Alphanumeric name for the new prefix.
     425         * @return string|WP_Error Old prefix or WP_Error on error
     426         */
     427        function set_prefix($prefix) {
     428
     429                if ( preg_match('|[^a-z0-9_]|i', $prefix) )
     430                        return new WP_Error('invalid_db_prefix', /*WP_I18N_DB_BAD_PREFIX*/'Invalid database prefix'/*/WP_I18N_DB_BAD_PREFIX*/);
     431
     432                $old_prefix = $this->prefix;
     433                $this->prefix = $prefix;
     434
     435                foreach ( (array) $this->tables as $table )
     436                        $this->$table = $this->prefix . $table;
     437
     438                if ( defined('CUSTOM_USER_TABLE') )
     439                        $this->users = CUSTOM_USER_TABLE;
     440
     441                if ( defined('CUSTOM_USER_META_TABLE') )
     442                        $this->usermeta = CUSTOM_USER_META_TABLE;
     443
     444                return $old_prefix;
     445        }
     446
     447        /**
     448         * Selects a database using the current database connection.
     449         *
     450         * The database name will be changed based on the current database
     451         * connection. On failure, the execution will bail and display an DB error.
     452         *
     453         * @since 0.71
     454         *
     455         * @param string $db MySQL database name
     456         * @return null Always null.
     457         */
     458        function select($db) {
     459                if (!@mysql_select_db($db, $this->dbh)) {
     460                        $this->ready = false;
     461                        $this->bail(sprintf(/*WP_I18N_DB_SELECT_DB*/'
     462<h1>Can&#8217;t select database</h1>
     463<p>We were able to connect to the database server (which means your username and password is okay) but not able to select the <code>%1$s</code> database.</p>
     464<ul>
     465<li>Are you sure it exists?</li>
     466<li>Does the user <code>%2$s</code> have permission to use the <code>%1$s</code> database?</li>
     467<li>On some systems the name of your database is prefixed with your username, so it would be like <code>username_%1$s</code>. Could that be the problem?</li>
     468</ul>
     469<p>If you don\'t know how to setup a database you should <strong>contact your host</strong>. If all else fails you may find help at the <a href="http://wordpress.org/support/">WordPress Support Forums</a>.</p>'/*/WP_I18N_DB_SELECT_DB*/, $db, $this->dbuser), 'db_select_fail');
     470                        return;
     471                }
     472        }
     473
     474        function _weak_escape($string) {
     475                return addslashes($string);
     476        }
     477
     478        function _real_escape($string) {
     479                if ( $this->dbh && $this->real_escape )
     480                        return mysql_real_escape_string( $string, $this->dbh );
     481                else
     482                        return addslashes( $string );
     483        }
     484
     485        function _escape($data) {
     486                if ( is_array($data) ) {
     487                        foreach ( (array) $data as $k => $v ) {
     488                                if ( is_array($v) )
     489                                        $data[$k] = $this->_escape( $v );
     490                                else
     491                                        $data[$k] = $this->_real_escape( $v );
     492                        }
     493                } else {
     494                        $data = $this->_real_escape( $data );
     495                }
     496
     497                return $data;
     498        }
     499
     500        /**
     501         * Escapes content for insertion into the database using addslashes(), for security
     502         *
     503         * @since 0.71
     504         *
     505         * @param string|array $data
     506         * @return string query safe string
     507         */
     508        function escape($data) {
     509                if ( is_array($data) ) {
     510                        foreach ( (array) $data as $k => $v ) {
     511                                if ( is_array($v) )
     512                                        $data[$k] = $this->escape( $v );
     513                                else
     514                                        $data[$k] = $this->_weak_escape( $v );
     515                        }
     516                } else {
     517                        $data = $this->_weak_escape( $data );
     518                }
     519
     520                return $data;
     521        }
     522
     523        /**
     524         * Escapes content by reference for insertion into the database, for security
     525         *
     526         * @since 2.3.0
     527         *
     528         * @param string $s
     529         */
     530        function escape_by_ref(&$string) {
     531                $string = $this->_real_escape( $string );
     532        }
     533
     534        /**
     535         * Prepares a SQL query for safe execution.  Uses sprintf()-like syntax.
     536         *
     537         * This function only supports a small subset of the sprintf syntax; it only supports %d (decimal number), %s (string).
     538         * Does not support sign, padding, alignment, width or precision specifiers.
     539         * Does not support argument numbering/swapping.
     540         *
     541         * May be called like {@link http://php.net/sprintf sprintf()} or like {@link http://php.net/vsprintf vsprintf()}.
     542         *
     543         * Both %d and %s should be left unquoted in the query string.
     544         *
     545         * <code>
     546         * wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", "foo", 1337 )
     547         * </code>
     548         *
     549         * @link http://php.net/sprintf Description of syntax.
     550         * @since 2.3.0
     551         *
     552         * @param string $query Query statement with sprintf()-like placeholders
     553         * @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()}.
     554         * @param mixed $args,... further variables to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}.
     555         * @return null|string Sanitized query string
     556         */
     557        function prepare($query = null) { // ( $query, *$args )
     558                if ( is_null( $query ) )
     559                        return;
     560                $args = func_get_args();
     561                array_shift($args);
     562                // If args were passed as an array (as in vsprintf), move them up
     563                if ( isset($args[0]) && is_array($args[0]) )
     564                        $args = $args[0];
     565                $query = str_replace("'%s'", '%s', $query); // in case someone mistakenly already singlequoted it
     566                $query = str_replace('"%s"', '%s', $query); // doublequote unquoting
     567                $query = str_replace('%s', "'%s'", $query); // quote the strings
     568                array_walk($args, array(&$this, 'escape_by_ref'));
     569                return @vsprintf($query, $args);
     570        }
     571
     572        /**
     573         * Print SQL/DB error.
     574         *
     575         * @since 0.71
     576         * @global array $EZSQL_ERROR Stores error information of query and error string
     577         *
     578         * @param string $str The error to display
     579         * @return bool False if the showing of errors is disabled.
     580         */
     581        function print_error($str = '') {
     582                global $EZSQL_ERROR;
     583
     584                if (!$str) $str = mysql_error($this->dbh);
     585                $EZSQL_ERROR[] = array ('query' => $this->last_query, 'error_str' => $str);
     586
     587                if ( $this->suppress_errors )
     588                        return false;
     589
     590                if ( $caller = $this->get_caller() )
     591                        $error_str = sprintf(/*WP_I18N_DB_QUERY_ERROR_FULL*/'WordPress database error %1$s for query %2$s made by %3$s'/*/WP_I18N_DB_QUERY_ERROR_FULL*/, $str, $this->last_query, $caller);
     592                else
     593                        $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);
     594
     595                $log_error = true;
     596                if ( ! function_exists('error_log') )
     597                        $log_error = false;
     598
     599                $log_file = @ini_get('error_log');
     600                if ( !empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file) )
     601                        $log_error = false;
     602
     603                if ( $log_error )
     604                        @error_log($error_str, 0);
     605
     606                // Is error output turned on or not..
     607                if ( !$this->show_errors )
     608                        return false;
     609
     610                $str = htmlspecialchars($str, ENT_QUOTES);
     611                $query = htmlspecialchars($this->last_query, ENT_QUOTES);
     612
     613                // If there is an error then take note of it
     614                print "<div id='error'>
     615                <p class='wpdberror'><strong>WordPress database error:</strong> [$str]<br />
     616                <code>$query</code></p>
     617                </div>";
     618        }
     619
     620        /**
     621         * Enables showing of database errors.
     622         *
     623         * This function should be used only to enable showing of errors.
     624         * wpdb::hide_errors() should be used instead for hiding of errors. However,
     625         * this function can be used to enable and disable showing of database
     626         * errors.
     627         *
     628         * @since 0.71
     629         *
     630         * @param bool $show Whether to show or hide errors
     631         * @return bool Old value for showing errors.
     632         */
     633        function show_errors( $show = true ) {
     634                $errors = $this->show_errors;
     635                $this->show_errors = $show;
     636                return $errors;
     637        }
     638
     639        /**
     640         * Disables showing of database errors.
     641         *
     642         * @since 0.71
     643         *
     644         * @return bool Whether showing of errors was active or not
     645         */
     646        function hide_errors() {
     647                $show = $this->show_errors;
     648                $this->show_errors = false;
     649                return $show;
     650        }
     651
     652        /**
     653         * Whether to suppress database errors.
     654         *
     655         * @param unknown_type $suppress
     656         * @return unknown
     657         */
     658        function suppress_errors( $suppress = true ) {
     659                $errors = $this->suppress_errors;
     660                $this->suppress_errors = $suppress;
     661                return $errors;
     662        }
     663
     664        /**
     665         * Kill cached query results.
     666         *
     667         * @since 0.71
     668         */
     669        function flush() {
     670                $this->last_result = array();
     671                $this->col_info = null;
     672                $this->last_query = null;
     673        }
     674
     675        /**
     676         * Perform a MySQL database query, using current database connection.
     677         *
     678         * More information can be found on the codex page.
     679         *
     680         * @since 0.71
     681         *
     682         * @param string $query
     683         * @return int|false Number of rows affected/selected or false on error
     684         */
     685        function query($query) {
     686                if ( ! $this->ready )
     687                        return false;
     688
     689                // filter the query, if filters are available
     690                // NOTE: some queries are made before the plugins have been loaded, and thus cannot be filtered with this method
     691                if ( function_exists('apply_filters') )
     692                        $query = apply_filters('query', $query);
     693
     694                // initialise return
     695                $return_val = 0;
     696                $this->flush();
     697
     698                // Log how the function was called
     699                $this->func_call = "\$db->query(\"$query\")";
     700
     701                // Keep track of the last query for debug..
     702                $this->last_query = $query;
     703
     704                // Perform the query via std mysql_query function..
     705                if ( defined('SAVEQUERIES') && SAVEQUERIES )
     706                        $this->timer_start();
     707
     708                $this->result = @mysql_query($query, $this->dbh);
     709                ++$this->num_queries;
     710
     711                if ( defined('SAVEQUERIES') && SAVEQUERIES )
     712                        $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
     713
     714                // If there is an error then take note of it..
     715                if ( $this->last_error = mysql_error($this->dbh) ) {
     716                        $this->print_error();
     717                        return false;
     718                }
     719
     720                if ( preg_match("/^\\s*(insert|delete|update|replace|alter) /i",$query) ) {
     721                        $this->rows_affected = mysql_affected_rows($this->dbh);
     722                        // Take note of the insert_id
     723                        if ( preg_match("/^\\s*(insert|replace) /i",$query) ) {
     724                                $this->insert_id = mysql_insert_id($this->dbh);
     725                        }
     726                        // Return number of rows affected
     727                        $return_val = $this->rows_affected;
     728                } else {
     729                        $i = 0;
     730                        while ($i < @mysql_num_fields($this->result)) {
     731                                $this->col_info[$i] = @mysql_fetch_field($this->result);
     732                                $i++;
     733                        }
     734                        $num_rows = 0;
     735                        while ( $row = @mysql_fetch_object($this->result) ) {
     736                                $this->last_result[$num_rows] = $row;
     737                                $num_rows++;
     738                        }
     739
     740                        @mysql_free_result($this->result);
     741
     742                        // Log number of rows the query returned
     743                        $this->num_rows = $num_rows;
     744
     745                        // Return number of rows selected
     746                        $return_val = $this->num_rows;
     747                }
     748
     749                return $return_val;
     750        }
     751
     752        /**
     753         * Insert a row into a table.
     754         *
     755         * <code>
     756         * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
     757         * </code>
     758         *
     759         * @since 2.5.0
     760         * @see wpdb::prepare()
     761         *
     762         * @param string $table table name
     763         * @param array $data Data to insert (in column => value pairs).  Both $data columns and $data values should be "raw" (neither should be SQL escaped).
     764         * @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.
     765         * @return int|false The number of rows inserted, or false on error.
     766         */
     767        function insert($table, $data, $format = null) {
     768                $formats = $format = (array) $format;
     769                $fields = array_keys($data);
     770                $formatted_fields = array();
     771                foreach ( $fields as $field ) {
     772                        if ( !empty($format) )
     773                                $form = ( $form = array_shift($formats) ) ? $form : $format[0];
     774                        elseif ( isset($this->field_types[$field]) )
     775                                $form = $this->field_types[$field];
     776                        else
     777                                $form = '%s';
     778                        $formatted_fields[] = $form;
     779                }
     780                $sql = "INSERT INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES ('" . implode( "','", $formatted_fields ) . "')";
     781                return $this->query( $this->prepare( $sql, $data) );
     782        }
     783
     784
     785        /**
     786         * Update a row in the table
     787         *
     788         * <code>
     789         * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) )
     790         * </code>
     791         *
     792         * @since 2.5.0
     793         * @see wpdb::prepare()
     794         *
     795         * @param string $table table name
     796         * @param array $data Data to update (in column => value pairs).  Both $data columns and $data values should be "raw" (neither should be SQL escaped).
     797         * @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".
     798         * @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.
     799         * @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.
     800         * @return int|false The number of rows updated, or false on error.
     801         */
     802        function update($table, $data, $where, $format = null, $where_format = null) {
     803                if ( !is_array( $where ) )
     804                        return false;
     805
     806                $formats = $format = (array) $format;
     807                $bits = $wheres = array();
     808                foreach ( (array) array_keys($data) as $field ) {
     809                        if ( !empty($format) )
     810                                $form = ( $form = array_shift($formats) ) ? $form : $format[0];
     811                        elseif ( isset($this->field_types[$field]) )
     812                                $form = $this->field_types[$field];
     813                        else
     814                                $form = '%s';
     815                        $bits[] = "`$field` = {$form}";
     816                }
     817
     818                $where_formats = $where_format = (array) $where_format;
     819                foreach ( (array) array_keys($where) as $field ) {
     820                        if ( !empty($where_format) )
     821                                $form = ( $form = array_shift($where_formats) ) ? $form : $where_format[0];
     822                        elseif ( isset($this->field_types[$field]) )
     823                                $form = $this->field_types[$field];
     824                        else
     825                                $form = '%s';
     826                        $wheres[] = "`$field` = {$form}";
     827                }
     828
     829                $sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres );
     830                return $this->query( $this->prepare( $sql, array_merge(array_values($data), array_values($where))) );
     831        }
     832
     833        /**
     834         * Retrieve one variable from the database.
     835         *
     836         * Executes a SQL query and returns the value from the SQL result.
     837         * If the SQL result contains more than one column and/or more than one row, this function returns the value in the column and row specified.
     838         * If $query is null, this function returns the value in the specified column and row from the previous SQL result.
     839         *
     840         * @since 0.71
     841         *
     842         * @param string|null $query SQL query.  If null, use the result from the previous query.
     843         * @param int $x (optional) Column of value to return.  Indexed from 0.
     844         * @param int $y (optional) Row of value to return.  Indexed from 0.
     845         * @return string Database query result
     846         */
     847        function get_var($query=null, $x = 0, $y = 0) {
     848                $this->func_call = "\$db->get_var(\"$query\",$x,$y)";
     849                if ( $query )
     850                        $this->query($query);
     851
     852                // Extract var out of cached results based x,y vals
     853                if ( !empty( $this->last_result[$y] ) ) {
     854                        $values = array_values(get_object_vars($this->last_result[$y]));
     855                }
     856
     857                // If there is a value return it else return null
     858                return (isset($values[$x]) && $values[$x]!=='') ? $values[$x] : null;
     859        }
     860
     861        /**
     862         * Retrieve one row from the database.
     863         *
     864         * Executes a SQL query and returns the row from the SQL result.
     865         *
     866         * @since 0.71
     867         *
     868         * @param string|null $query SQL query.
     869         * @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.
     870         * @param int $y (optional) Row to return.  Indexed from 0.
     871         * @return mixed Database query result in format specifed by $output
     872         */
     873        function get_row($query = null, $output = OBJECT, $y = 0) {
     874                $this->func_call = "\$db->get_row(\"$query\",$output,$y)";
     875                if ( $query )
     876                        $this->query($query);
     877                else
     878                        return null;
     879
     880                if ( !isset($this->last_result[$y]) )
     881                        return null;
     882
     883                if ( $output == OBJECT ) {
     884                        return $this->last_result[$y] ? $this->last_result[$y] : null;
     885                } elseif ( $output == ARRAY_A ) {
     886                        return $this->last_result[$y] ? get_object_vars($this->last_result[$y]) : null;
     887                } elseif ( $output == ARRAY_N ) {
     888                        return $this->last_result[$y] ? array_values(get_object_vars($this->last_result[$y])) : null;
     889                } else {
     890                        $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*/);
     891                }
     892        }
     893
     894        /**
     895         * Retrieve one column from the database.
     896         *
     897         * Executes a SQL query and returns the column from the SQL result.
     898         * If the SQL result contains more than one column, this function returns the column specified.
     899         * If $query is null, this function returns the specified column from the previous SQL result.
     900         *
     901         * @since 0.71
     902         *
     903         * @param string|null $query SQL query.  If null, use the result from the previous query.
     904         * @param int $x Column to return.  Indexed from 0.
     905         * @return array Database query result.  Array indexed from 0 by SQL result row number.
     906         */
     907        function get_col($query = null , $x = 0) {
     908                if ( $query )
     909                        $this->query($query);
     910
     911                $new_array = array();
     912                // Extract the column values
     913                for ( $i=0; $i < count($this->last_result); $i++ ) {
     914                        $new_array[$i] = $this->get_var(null, $x, $i);
     915                }
     916                return $new_array;
     917        }
     918
     919        /**
     920         * Retrieve an entire SQL result set from the database (i.e., many rows)
     921         *
     922         * Executes a SQL query and returns the entire SQL result.
     923         *
     924         * @since 0.71
     925         *
     926         * @param string $query SQL query.
     927         * @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.
     928         * @return mixed Database query results
     929         */
     930        function get_results($query = null, $output = OBJECT) {
     931                $this->func_call = "\$db->get_results(\"$query\", $output)";
     932
     933                if ( $query )
     934                        $this->query($query);
     935                else
     936                        return null;
     937
     938                if ( $output == OBJECT ) {
     939                        // Return an integer-keyed array of row objects
     940                        return $this->last_result;
     941                } elseif ( $output == OBJECT_K ) {
     942                        // Return an array of row objects with keys from column 1
     943                        // (Duplicates are discarded)
     944                        foreach ( $this->last_result as $row ) {
     945                                $key = array_shift( get_object_vars( $row ) );
     946                                if ( !isset( $new_array[ $key ] ) )
     947                                        $new_array[ $key ] = $row;
     948                        }
     949                        return $new_array;
     950                } elseif ( $output == ARRAY_A || $output == ARRAY_N ) {
     951                        // Return an integer-keyed array of...
     952                        if ( $this->last_result ) {
     953                                $i = 0;
     954                                foreach( (array) $this->last_result as $row ) {
     955                                        if ( $output == ARRAY_N ) {
     956                                                // ...integer-keyed row arrays
     957                                                $new_array[$i] = array_values( get_object_vars( $row ) );
     958                                        } else {
     959                                                // ...column name-keyed row arrays
     960                                                $new_array[$i] = get_object_vars( $row );
     961                                        }
     962                                        ++$i;
     963                                }
     964                                return $new_array;
     965                        }
     966                }
     967        }
     968
     969        /**
     970         * Retrieve column metadata from the last query.
     971         *
     972         * @since 0.71
     973         *
     974         * @param string $info_type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill
     975         * @param int $col_offset 0: col name. 1: which table the col's in. 2: col's max length. 3: if the col is numeric. 4: col's type
     976         * @return mixed Column Results
     977         */
     978        function get_col_info($info_type = 'name', $col_offset = -1) {
     979                if ( $this->col_info ) {
     980                        if ( $col_offset == -1 ) {
     981                                $i = 0;
     982                                foreach( (array) $this->col_info as $col ) {
     983                                        $new_array[$i] = $col->{$info_type};
     984                                        $i++;
     985                                }
     986                                return $new_array;
     987                        } else {
     988                                return $this->col_info[$col_offset]->{$info_type};
     989                        }
     990                }
     991        }
     992
     993        /**
     994         * Starts the timer, for debugging purposes.
     995         *
     996         * @since 1.5.0
     997         *
     998         * @return true
     999         */
     1000        function timer_start() {
     1001                $mtime = microtime();
     1002                $mtime = explode(' ', $mtime);
     1003                $this->time_start = $mtime[1] + $mtime[0];
     1004                return true;
     1005        }
     1006
     1007        /**
     1008         * Stops the debugging timer.
     1009         *
     1010         * @since 1.5.0
     1011         *
     1012         * @return int Total time spent on the query, in milliseconds
     1013         */
     1014        function timer_stop() {
     1015                $mtime = microtime();
     1016                $mtime = explode(' ', $mtime);
     1017                $time_end = $mtime[1] + $mtime[0];
     1018                $time_total = $time_end - $this->time_start;
     1019                return $time_total;
     1020        }
     1021
     1022        /**
     1023         * Wraps errors in a nice header and footer and dies.
     1024         *
     1025         * Will not die if wpdb::$show_errors is true
     1026         *
     1027         * @since 1.5.0
     1028         *
     1029         * @param string $message The Error message
     1030         * @param string $error_code (optional) A Computer readable string to identify the error.
     1031         * @return false|void
     1032         */
     1033        function bail($message, $error_code = '500') {
     1034                if ( !$this->show_errors ) {
     1035                        if ( class_exists('WP_Error') )
     1036                                $this->error = new WP_Error($error_code, $message);
     1037                        else
     1038                                $this->error = $message;
     1039                        return false;
     1040                }
     1041                wp_die($message);
     1042        }
     1043
     1044        /**
     1045         * Whether or not MySQL database is at least the required minimum version.
     1046         *
     1047         * @since 2.5.0
     1048         * @uses $wp_version
     1049         *
     1050         * @return WP_Error
     1051         */
     1052        function check_database_version()
     1053        {
     1054                global $wp_version;
     1055                // Make sure the server has MySQL 4.0
     1056                if ( version_compare($this->db_version(), '4.0.0', '<') )
     1057                        return new WP_Error('database_version',sprintf(__('<strong>ERROR</strong>: WordPress %s requires MySQL 4.0.0 or higher'), $wp_version));
     1058        }
     1059
     1060        /**
     1061         * Whether of not the database supports collation.
     1062         *
     1063         * Called when WordPress is generating the table scheme.
     1064         *
     1065         * @since 2.5.0
     1066         *
     1067         * @return bool True if collation is supported, false if version does not
     1068         */
     1069        function supports_collation() {
     1070                return $this->has_cap( 'collation' );
     1071        }
     1072
     1073        /**
     1074         * Generic function to determine if a database supports a particular feature
     1075         * @param string $db_cap the feature
     1076         * @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.
     1077         * @return bool
     1078         */
     1079        function has_cap( $db_cap ) {
     1080                $version = $this->db_version();
     1081
     1082                switch ( strtolower( $db_cap ) ) :
     1083                case 'collation' :    // @since 2.5.0
     1084                case 'group_concat' : // @since 2.7
     1085                case 'subqueries' :   // @since 2.7
     1086                        return version_compare($version, '4.1', '>=');
     1087                        break;
     1088                endswitch;
     1089
     1090                return false;
     1091        }
     1092
     1093        /**
     1094         * Retrieve the name of the function that called wpdb.
     1095         *
     1096         * Requires PHP 4.3 and searches up the list of functions until it reaches
     1097         * the one that would most logically had called this method.
     1098         *
     1099         * @since 2.5.0
     1100         *
     1101         * @return string The name of the calling function
     1102         */
     1103        function get_caller() {
     1104                // requires PHP 4.3+
     1105                if ( !is_callable('debug_backtrace') )
     1106                        return '';
     1107
     1108                $bt = debug_backtrace();
     1109                $caller = array();
     1110
     1111                $bt = array_reverse( $bt );
     1112                foreach ( (array) $bt as $call ) {
     1113                        if ( @$call['class'] == __CLASS__ )
     1114                                continue;
     1115                        $function = $call['function'];
     1116                        if ( isset( $call['class'] ) )
     1117                                $function = $call['class'] . "->$function";
     1118                        $caller[] = $function;
     1119                }
     1120                $caller = join( ', ', $caller );
     1121
     1122                return $caller;
     1123        }
     1124
     1125        /**
     1126         * The database version number
     1127         * @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.
     1128         * @return false|string false on failure, version number on success
     1129         */
     1130        function db_version() {
     1131                return preg_replace('/[^0-9.].*/', '', mysql_get_server_info( $this->dbh ));
     1132        }
     1133}
     1134
  • wp-includes/wp-db/mysql/translations/translations.php

    Property changes on: wp-includes\wp-db\mysql\mysql.php
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
     1<?php
     2// Necessary SQL Dialect Translations
     3class Translations
     4{
     5        // No Translation Necessary
     6        function translate($query)
     7        {
     8                return $query;
     9        }
     10}
  • wp-includes/wp-db/sqlsrv/sqlsrv.php

    Property changes on: wp-includes\wp-db\mysql\translations\translations.php
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
     1<?php
     2/**
     3 * WordPress DB Class
     4 *
     5 * Original code from {@link http://php.justinvincent.com Justin Vincent (justin@visunet.ie)}
     6 *
     7 * Modifications for SQLSRV (Microsoft PHP SQL Server driver) by A.Garcia and A.Gentile
     8 *
     9 * @package WordPress
     10 * @subpackage Database
     11 * @since 0.71
     </