WordPress.org

Make WordPress Core

Ticket #2862: wpdb_BuildSql.diff

File wpdb_BuildSql.diff, 7.0 KB (added by DevaSatyam, 8 years ago)

patch file

  • wp-includes/wp-db.php

     
    8383                else 
    8484                        return mysql_real_escape_string( $string, $this->dbh ); 
    8585        } 
     86         
     87        /** 
     88 *  Builds a properly formatted and escaped SQL statement using an SQL template and a list of arguments. 
     89 * 
     90 *  The function scans the template for query marks ? which are placeholders for the arguments 
     91 *  Query marks are to be followed by format descriptors. 
     92 * 
     93 *  The first argument, the template, is mandatory.  If the template contains no query marks 
     94 *  and no argument is given, the function does nothing. 
     95 * 
     96 *  Placeholders have the following format and are not case sensitive: 
     97 * 
     98 *  <b>?[nn][m]t</b> 
     99 * 
     100 *  Where: 
     101 * 
     102 *  <b>?</b> Begining of placeholder for argument 
     103 * 
     104 *  <b>nn - <i>position</i></b> number of the argument to be replaced. 
     105 *      Argument 0 is the template itself and is not valid. 
     106 *      The first argument after the SQL template is number 1 
     107 *              If no number is given, arguments are taken sequentially. 
     108 *              Numbered replacements do not move the sequential argument pointer. 
     109 *              Arguments beyond the actual number present are considered null 
     110 * 
     111 *  <b>m - <i>modifier</i></b> [optional] indicates what to do if the argument is null 
     112 *  - m: mandatory, if the argument contains null, it will give a fatal error. 
     113 *  - z: null, if the argument is 0 or an empty string, it will be replaced by null 
     114 * 
     115 *  <b>t - <i>data type</i></b> the placeholder will be replaced by the argument as follows 
     116 *  - s: string, if not null, it will be escaped and enclosed in quotes 
     117 *  - i: integer, the integer value (intval() function) of the argument 
     118 *  - f: float, the floating point value (floatval() function) of the argument 
     119 *  - d: date, the argument will be assumed to represent a timestamp and it will be converted to yyyy-mm-dd and quoted 
     120 *  - b: boolean, anything evaluated to false will be 0, otherwise 1 
     121 *  - t: table prefix, the value of the global variable <i>$table_prefix</i>, escaped and unquoted 
     122 *       It takes no argument from the argument list 
     123 * 
     124 *  Example: 
     125 *  <code> 
     126 *  echo BuildSql('Insert into ?ttable (?s,?ns,?mi,?d,?ni,?i)','Something','',5,time(),0,null); 
     127 *  </code> 
     128 *  will return: 
     129 *  <pre> 
     130 *  Insert into wp_table ('Something',null,5,'2006-05-15',null,0) 
     131 *  </pre> 
     132 * 
     133 *  Note that placeholders do not need to be quoted, if quotes are required (strings or dates) they will be provided 
     134 * 
     135 *  @param string $query Template of SQL statement 
     136 * 
     137 * 
     138 *  @param mixed $value,... Values to be replaced into placeholders, sequentially unless stated otherwise 
     139 * 
     140 *  @return string properly formated and escaped SQL statement 
     141 * 
     142 *  The function will call bail if an unknown formatting character is found. 
     143 *  Unused arguments will produce warnings. 
     144 *  Missing arguments will be assumed null and will trigger a fatal error 
     145 *    if the placeholder has the mandatory modifier m. 
     146 *  There is no provision to put a literal ? into the SQL statement since the ? is not a valid SQL operator, 
     147 *    the only valid place for query marks are in literal string constants, which can be passed to this 
     148 *    function in an argument 
     149 */ 
    86150 
     151        function BuildSql($query) { 
     152                global $table_prefix; 
     153 
     154                $num_args = func_num_args();  // number of arguments available 
     155                $args_used = (1 << $num_args) -2; // bit mask to check if arguments are used 
     156            /*                      +---------Anything up to first query mark 
     157                                    |      +------ query mark, start of placeholder 
     158                                    |      |    +---- position of argument 
     159                                    |      |    |     +----- modifier 
     160                                    |      |    |     |       +--- data type 
     161                                                                |      |    |     |       |                     */ 
     162                if (preg_match_all('|([^\?]*)(\?(\d?\d)?([mn]?)([sifdbt])?)*|i',$query,$matches,PREG_SET_ORDER)) { 
     163                        $arg_pointer = 1; // sequential pointer to arguments 
     164                        $s = '';  // output SQL statement 
     165                        foreach($matches as $match) { 
     166                                $NullIfEmpty = false; 
     167                                $s .= $match[1];    //concatenate everything up to question mark 
     168                                $type = strtolower($match[5]);  // read datatype 
     169         
     170                                // read the value of the argument 
     171                                if ($type =='t') { 
     172                                        $value = $table_prefix;         // t is a special case, it takes no argument from the list 
     173                                        $n = 0; 
     174                                } elseif (intval($match[3])) {  // if there is a nn position modifier, read it  
     175                                                                                                // (null evaluates to 0, which is an invalid position anyhow) 
     176                                        $n = intval($match[3]); 
     177                                } else {                                                // else, read the next sequential argument an increment the argument pointer 
     178                                        $n = $arg_pointer++; 
     179                                } 
     180                                if ($n) {               // if there was an argument to be read (notice t does not ask for an argument) 
     181                                        $args_used &= ~ (1 << $n);   // some bitwise magic to unset the bit position representing the argument 
     182                                        if ($n >= $num_args) $value = null;   // if argument requeste beyond those available, assume it null 
     183                                        else $value = func_get_arg($n);      // otherwise, read it 
     184                                } 
     185         
     186                                switch ($match[4]) {  // read modifier 
     187                                        case 'm':                       // mandatory? 
     188                                        case 'M': 
     189                                                if (is_null($value)) $this->bail("<p>Missing value for argument $n near: ... ${match[0]} ...</p>"); 
     190                                                break; 
     191                                        case 'n':               // null if empty? 
     192                                        case 'N': 
     193                                                $NullIfEmpty = true;  // set flag 
     194                                                break; 
     195                                } 
     196                                switch($type) { // now we process $value according to datatype and $NullIfEmpty flag 
     197                                case 's': 
     198                                        case 'S': 
     199                                                if ($NullIfEmpty and strlen($value) == 0) { 
     200                                                        $s .='null'; 
     201                                                } else { 
     202                                                $s .= "'" . $this->escape($value) . "'";   
     203                                                } 
     204                                        break; 
     205                                case 'i': 
     206                                        case 'I': 
     207                                                if ($NullIfEmpty and $value == 0) { 
     208                                                        $s .='null'; 
     209                                                } else { 
     210                                                $s .= intval($value); 
     211                                                } 
     212                                        break; 
     213                                case 'f': 
     214                                        case 'F': 
     215                                                if ($NullIfEmpty and $value == 0) { 
     216                                                        $s .='null'; 
     217                                                } else { 
     218                                                $s .= floatval($value); 
     219                                                } 
     220                                        break; 
     221                                        case 'd': 
     222                                        case 'D': 
     223                                                if ($NullIfEmpty and empty($value)) { 
     224                                                        $s .='null'; 
     225                                                } else { 
     226                                                        $s .= "'" . date('Y-m-d', $value) . "'"; 
     227                                                } 
     228                                                break; 
     229                                        case 'b': 
     230                                        case 'B':  // booleans cannot be null 
     231                                                $s .= intval($value!=false); 
     232                                                break; 
     233                                        case 't': 
     234                                        case 'T': 
     235                                                $s .=  $this->escape($value); 
     236                                                break; 
     237                                        case null: 
     238                                                break; 
     239                                default: 
     240                                                $this->bail('<p>Unknown formatting character in BuildSql: ' . $match[0] . " en SQL <br />[$query]</p>"); 
     241                                } 
     242         
     243                        } 
     244                } 
     245                // if all arguments used, $args_used will be zero 
     246                if ($args_used) { 
     247                        for($i=1;$i<$num_args;$i++) { 
     248                                $args_used >>=1; // bitmaks is shift right 
     249                                // if right most bit still 1, it means it has not been used. 
     250                                if ($args_used & 1) $this->bail("Argument $i not used"); 
     251                        } 
     252                } 
     253         
     254                return $s; 
     255        } 
     256 
    87257        // ================================================================== 
    88258        //      Print SQL/DB error. 
    89259