1196 | 1203 | * |
1197 | 1204 | * The following placeholders can be used in the query string: |
1198 | 1205 | * %d (integer) |
1199 | 1206 | * %f (float) |
1200 | 1207 | * %s (string) |
1201 | 1208 | * |
1202 | 1209 | * All placeholders MUST be left unquoted in the query string. A corresponding argument MUST be passed for each placeholder. |
1203 | 1210 | * |
1204 | 1211 | * Literal percentage signs (%) in the query string must be written as %%. Percentage wildcards (for example, |
1205 | 1212 | * to use in LIKE syntax) must be passed via a substitution argument containing the complete LIKE string, these |
1206 | 1213 | * cannot be inserted directly in the query string. Also see {@see esc_like()}. |
1207 | 1214 | * |
1208 | 1215 | * This method DOES NOT support sign, padding, alignment, width or precision specifiers. |
1209 | 1216 | * This method DOES NOT support argument numbering or swapping. |
1210 | 1217 | * |
1212 | 1219 | * of the two is not supported. |
1213 | 1220 | * |
1214 | 1221 | * Examples: |
1215 | 1222 | * $wpdb->prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d OR `other_field` LIKE %s", array( 'foo', 1337, '%bar' ) ); |
1216 | 1223 | * $wpdb->prepare( "SELECT DATE_FORMAT(`field`, '%%c') FROM `table` WHERE `column` = %s", 'foo' ); |
1217 | 1224 | * |
1218 | 1225 | * @link https://secure.php.net/sprintf Description of syntax. |
1219 | 1226 | * @since 2.3.0 |
1220 | 1227 | * |
1221 | 1228 | * @param string $query Query statement with sprintf()-like placeholders |
1222 | 1229 | * @param array|mixed $args The array of variables to substitute into the query's placeholders if being called with an array of arguments, |
1223 | 1230 | * or the first variable to substitute into the query's placeholders if being called with individual arguments. |
1224 | 1231 | * @param mixed $args,... further variables to substitute into the query's placeholders if being called wih individual arguments. |
1225 | 1232 | * @return string|void Sanitized query string, if there is a query to prepare. |
1226 | 1233 | */ |
1775 | 1782 | |
1776 | 1783 | // MySQL server has gone away, try to reconnect. |
1777 | 1784 | $mysql_errno = 0; |
1778 | 1785 | if ( ! empty( $this->dbh ) ) { |
1779 | 1786 | if ( $this->use_mysqli ) { |
1780 | 1787 | if ( $this->dbh instanceof mysqli ) { |
1781 | 1788 | $mysql_errno = mysqli_errno( $this->dbh ); |
1782 | 1789 | } else { |
1783 | 1790 | // $dbh is defined, but isn't a real connection. |
1784 | 1791 | // Something has gone horribly wrong, let's try a reconnect. |
1785 | 1792 | $mysql_errno = 2006; |
1786 | 1793 | } |
1787 | 1794 | } else { |
1788 | 1795 | if ( is_resource( $this->dbh ) ) { |
1789 | 1796 | $mysql_errno = mysql_errno( $this->dbh ); |
1790 | 1797 | } else { |
1791 | 1798 | $mysql_errno = 2006; |
1792 | 1799 | } |
1793 | 1800 | } |
1794 | 1801 | } |
1795 | 1802 | |
1796 | 1803 | if ( empty( $this->dbh ) || 2006 == $mysql_errno ) { |
1797 | 1804 | if ( $this->check_connection() ) { |
1834 | 1841 | } else { |
1835 | 1842 | $this->rows_affected = mysql_affected_rows( $this->dbh ); |
1836 | 1843 | } |
1837 | 1844 | // Take note of the insert_id |
1838 | 1845 | if ( preg_match( '/^\s*(insert|replace)\s/i', $query ) ) { |
1839 | 1846 | if ( $this->use_mysqli ) { |
1840 | 1847 | $this->insert_id = mysqli_insert_id( $this->dbh ); |
1841 | 1848 | } else { |
1842 | 1849 | $this->insert_id = mysql_insert_id( $this->dbh ); |
1843 | 1850 | } |
1844 | 1851 | } |
1845 | 1852 | // Return number of rows affected |
1846 | 1853 | $return_val = $this->rows_affected; |
1847 | 1854 | } else { |
1848 | 1855 | $num_rows = 0; |
1849 | | if ( $this->use_mysqli && $this->result instanceof mysqli_result ) { |
| 1856 | if ( $this->use_mysqli && $this->result instanceof mysqli_stmt ) { |
| 1857 | $db_row = array(); |
| 1858 | $mysqli_stmt_bind_result_args = array( $this->result ); |
| 1859 | |
| 1860 | foreach ( mysqli_fetch_fields( mysqli_stmt_result_metadata( $this->result ) ) as $field ) { |
| 1861 | $db_row[ $field->name ] = null; |
| 1862 | $mysqli_stmt_bind_result_args[] = &$db_row[ $field->name ]; |
| 1863 | } |
| 1864 | call_user_func_array( 'mysqli_stmt_bind_result', $mysqli_stmt_bind_result_args ); |
| 1865 | |
| 1866 | while ( mysqli_stmt_fetch( $this->result ) ) { |
| 1867 | // Copy values out, as $db_row fields are bound to the current result set. |
| 1868 | $row = new stdClass(); |
| 1869 | foreach ( $db_row as $field => $value ) { |
| 1870 | $row->{$field} = $value; |
| 1871 | } |
| 1872 | $this->last_result[$num_rows] = $row; |
| 1873 | $num_rows++; |
| 1874 | } |
| 1875 | } elseif ( $this->use_mysqli && $this->result instanceof mysqli_result ) { |
1850 | 1876 | while ( $row = mysqli_fetch_object( $this->result ) ) { |
1851 | 1877 | $this->last_result[$num_rows] = $row; |
1852 | 1878 | $num_rows++; |
1853 | 1879 | } |
1854 | 1880 | } elseif ( is_resource( $this->result ) ) { |
1855 | 1881 | while ( $row = mysql_fetch_object( $this->result ) ) { |
1856 | 1882 | $this->last_result[$num_rows] = $row; |
1857 | 1883 | $num_rows++; |
1858 | 1884 | } |
1859 | 1885 | } |
1860 | 1886 | |
1861 | 1887 | // Log number of rows the query returned |
1862 | 1888 | // and return number of rows selected |
1863 | 1889 | $this->num_rows = $num_rows; |
1864 | 1890 | $return_val = $num_rows; |
1865 | 1891 | } |
1866 | 1892 | |
1867 | 1893 | return $return_val; |
1868 | 1894 | } |
1869 | 1895 | |
1870 | 1896 | /** |
1871 | 1897 | * Internal function to perform the mysql_query() call. |
1872 | 1898 | * |
1873 | 1899 | * @since 3.9.0 |
1874 | 1900 | * |
1875 | 1901 | * @see wpdb::query() |
1876 | 1902 | * |
1877 | 1903 | * @param string $query The query to run. |
1878 | 1904 | */ |
1884 | | if ( ! empty( $this->dbh ) && $this->use_mysqli ) { |
| 1910 | if ( ! empty( $this->dbh ) && $this->use_mysqli && $prepared_query_data !== false ) { |
| 1911 | |
| 1912 | $prepared_value_types = ''; |
| 1913 | $prepared_values = array(); |
| 1914 | foreach ( $prepared_query_data as $v ) { |
| 1915 | if ( ! is_array( $v ) || ! isset( $v['type'] ) ) { |
| 1916 | $v = array( 'type' => 's', 'value' => $v ); |
| 1917 | } |
| 1918 | if ( isset( $this->valid_mysqli_prepare_placeholders[ $v['type'] ] ) ) { |
| 1919 | $prepared_value_types .= $v['type']; |
| 1920 | } else { |
| 1921 | $prepared_value_types .= 's'; |
| 1922 | } |
| 1923 | |
| 1924 | $prepared_values[] = $v['value']; |
| 1925 | } |
| 1926 | |
| 1927 | $prepared_query = mysqli_prepare( $this->dbh, $query ); |
| 1928 | if ( ! $prepared_query ) { |
| 1929 | |
| 1930 | // TODO: Handling of a invalid query |
| 1931 | $this->result = false; |
| 1932 | return false; |
| 1933 | } |
| 1934 | |
| 1935 | if ( $prepared_query->param_count != count( $prepared_query_data ) ) { |
| 1936 | // Inform the developer they passed an invalid query (or args) |
| 1937 | throw new Exception( "Invalid query, incorrect parameter count" ); |
| 1938 | } |
| 1939 | |
| 1940 | $mysqli_stmt_bind_param_args = array( |
| 1941 | $prepared_query, |
| 1942 | $prepared_value_types |
| 1943 | // ... args by ref: |
| 1944 | ); |
| 1945 | foreach ( $prepared_values as $i => $v ) { |
| 1946 | $mysqli_stmt_bind_param_args[] = & $prepared_values[$i]; |
| 1947 | } |
| 1948 | call_user_func_array( 'mysqli_stmt_bind_param', $mysqli_stmt_bind_param_args ); |
| 1949 | |
| 1950 | mysqli_stmt_execute( $prepared_query ); |
| 1951 | $this->result = $prepared_query; |
| 1952 | |
| 1953 | } elseif ( ! empty( $this->dbh ) && $this->use_mysqli ) { |
| 1955 | |
| 1956 | } elseif ( ! empty( $this->dbh ) && $prepared_query_data !== false ) { |
| 1957 | // TODO: TESTING NEEDED |
| 1958 | // TODO: Use a weak prepare (printf) to handle it when MySQLi isn't available. |
| 1959 | $prepared_value_types = array(); |
| 1960 | $prepared_values = array(); |
| 1961 | foreach ( $prepared_query_data as $v ) { |
| 1962 | if ( ! is_array( $v ) || ! isset( $v['type'] ) ) { |
| 1963 | $v = array( 'type' => 's', 'value' => $v ); |
| 1964 | } |
| 1965 | if ( isset( $this->valid_mysqli_prepare_placeholders[ $v['type'] ] ) ) { |
| 1966 | $prepared_value_types[] = $this->valid_mysqli_prepare_placeholders[ $v['type'] ]; |
| 1967 | } else { |
| 1968 | $prepared_value_types[] = '%s'; |
| 1969 | } |
| 1970 | $prepared_values[] = $v['value']; |
| 1971 | } |
| 1972 | |
| 1973 | // TODO: this attempts to prevent issues when ? is present in a non-placeholder context, which shouldn't happen (but might) |
| 1974 | if ( count( $prepared_values ) !== substr_count( $query, '?' ) ) { |
| 1975 | // Inform the developer they passed an invalid query (or args) |
| 1976 | throw new Exception( "Invalid query, incorrect parameter count" ); |
| 1977 | } |
| 1978 | |
| 1979 | // TODO PHP 5.2 compat |
| 1980 | // NOTE: $_query used to record non-prepare'd query with SAVEQUERIES |
| 1981 | $_query = preg_replace_callback( '/\?/', function() use( $prepared_value_types ) { |
| 1982 | static $i = 0; |
| 1983 | return $prepared_value_types[ $i++ ]; |
| 1984 | }, $query ); |
| 1985 | |
| 1986 | $_query = $this->prepare( $_query, $prepared_values ); |
| 1987 | $this->result = mysql_query( $_query, $this->dbh ); |
| 1988 | |
1886 | 1989 | } elseif ( ! empty( $this->dbh ) ) { |
1887 | 1990 | $this->result = mysql_query( $query, $this->dbh ); |
1888 | 1991 | } |
1889 | 1992 | $this->num_queries++; |
1890 | 1993 | |
1891 | 1994 | if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) { |
1892 | 1995 | $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() ); |
1893 | 1996 | } |
1894 | 1997 | } |
1895 | 1998 | |
1896 | 1999 | /** |
1897 | 2000 | * Insert a row into a table. |
1898 | 2001 | * |
1899 | 2002 | * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 'bar' ) ) |
1900 | 2003 | * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) ) |
1964 | 2067 | * @param string $type Optional. What type of operation is this? INSERT or REPLACE. Defaults to INSERT. |
1965 | 2068 | * @return int|false The number of rows affected, or false on error. |
1966 | 2069 | */ |
1967 | 2070 | function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT' ) { |
1968 | 2071 | $this->insert_id = 0; |
1969 | 2072 | |
1970 | 2073 | if ( ! in_array( strtoupper( $type ), array( 'REPLACE', 'INSERT' ) ) ) { |
1971 | 2074 | return false; |
1972 | 2075 | } |
1973 | 2076 | |
1974 | 2077 | $data = $this->process_fields( $table, $data, $format ); |
1975 | 2078 | if ( false === $data ) { |
1976 | 2079 | return false; |
1977 | 2080 | } |
1978 | 2081 | |
1997 | 2107 | } |
1998 | 2108 | |
1999 | 2109 | /** |
2000 | 2110 | * Update a row in the table |
2001 | 2111 | * |
2002 | 2112 | * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 'bar' ), array( 'ID' => 1 ) ) |
2003 | 2113 | * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) ) |
2004 | 2114 | * |
2005 | 2115 | * @since 2.5.0 |
2006 | 2116 | * @see wpdb::prepare() |
2007 | 2117 | * @see wpdb::$field_types |
2008 | 2118 | * @see wp_set_wpdb_vars() |
2009 | 2119 | * |
2010 | 2120 | * @param string $table Table name |
2011 | 2121 | * @param array $data Data to update (in column => value pairs). |
2028 | 2138 | */ |
2029 | 2139 | public function update( $table, $data, $where, $format = null, $where_format = null ) { |
2030 | 2140 | if ( ! is_array( $data ) || ! is_array( $where ) ) { |
2031 | 2141 | return false; |
2032 | 2142 | } |
2033 | 2143 | |
2034 | 2144 | $data = $this->process_fields( $table, $data, $format ); |
2035 | 2145 | if ( false === $data ) { |
2036 | 2146 | return false; |
2037 | 2147 | } |
2038 | 2148 | $where = $this->process_fields( $table, $where, $where_format ); |
2039 | 2149 | if ( false === $where ) { |
2040 | 2150 | return false; |
2041 | 2151 | } |
2042 | 2152 | |
2089 | 2214 | * If string, that format will be used for all of the items in $where. |
2090 | 2215 | * A format is one of '%d', '%f', '%s' (integer, float, string). |
2091 | 2216 | * If omitted, all values in $where will be treated as strings unless otherwise specified in wpdb::$field_types. |
2092 | 2217 | * @return int|false The number of rows updated, or false on error. |
2093 | 2218 | */ |
2094 | 2219 | public function delete( $table, $where, $where_format = null ) { |
2095 | 2220 | if ( ! is_array( $where ) ) { |
2096 | 2221 | return false; |
2097 | 2222 | } |
2098 | 2223 | |
2099 | 2224 | $where = $this->process_fields( $table, $where, $where_format ); |
2100 | 2225 | if ( false === $where ) { |
2101 | 2226 | return false; |
2102 | 2227 | } |
2103 | 2228 | |
2121 | 2256 | } |
2122 | 2257 | |
2123 | 2258 | /** |
2124 | 2259 | * Processes arrays of field/value pairs and field formats. |
2125 | 2260 | * |
2126 | 2261 | * This is a helper method for wpdb's CRUD methods, which take field/value |
2127 | 2262 | * pairs for inserts, updates, and where clauses. This method first pairs |
2128 | 2263 | * each value with a format. Then it determines the charset of that field, |
2129 | 2264 | * using that to determine if any invalid text would be stripped. If text is |
2130 | 2265 | * stripped, then field processing is rejected and the query fails. |
2131 | 2266 | * |
2132 | 2267 | * @since 4.2.0 |
2133 | 2268 | * |
2134 | 2269 | * @param string $table Table name. |
2135 | 2270 | * @param array $data Field/value pair. |
2260 | 2395 | |
2261 | 2396 | /** |
2262 | 2397 | * Retrieve one variable from the database. |
2263 | 2398 | * |
2264 | 2399 | * Executes a SQL query and returns the value from the SQL result. |
2265 | 2400 | * 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. |
2266 | 2401 | * If $query is null, this function returns the value in the specified column and row from the previous SQL result. |
2267 | 2402 | * |
2268 | 2403 | * @since 0.71 |
2269 | 2404 | * |
2270 | 2405 | * @param string|null $query Optional. SQL query. Defaults to null, use the result from the previous query. |
2271 | 2406 | * @param int $x Optional. Column of value to return. Indexed from 0. |
2272 | 2407 | * @param int $y Optional. Row of value to return. Indexed from 0. |
2273 | 2408 | * @return string|null Database query result (as string), or null on failure |
2274 | 2409 | */ |
2284 | 2430 | } |
2285 | 2431 | |
2286 | 2432 | // Extract var out of cached results based x,y vals |
2287 | 2433 | if ( !empty( $this->last_result[$y] ) ) { |
2288 | 2434 | $values = array_values( get_object_vars( $this->last_result[$y] ) ); |
2289 | 2435 | } |
2290 | 2436 | |
2291 | 2437 | // If there is a value return it else return null |
2292 | 2438 | return ( isset( $values[$x] ) && $values[$x] !== '' ) ? $values[$x] : null; |
2293 | 2439 | } |
2294 | 2440 | |
2295 | 2441 | /** |
2296 | 2442 | * Retrieve one row from the database. |
2297 | 2443 | * |
2298 | 2444 | * Executes a SQL query and returns the row from the SQL result. |
2299 | 2445 | * |
2300 | 2446 | * @since 0.71 |
2301 | 2447 | * |
2302 | 2448 | * @param string|null $query SQL query. |
2303 | 2449 | * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to |
2304 | 2450 | * an stdClass object, an associative array, or a numeric array, respectively. Default OBJECT. |
2305 | 2451 | * @param int $y Optional. Row to return. Indexed from 0. |
2306 | 2452 | * @return array|object|null|void Database query result in format specified by $output or null on failure |
2307 | 2453 | */ |
2317 | 2475 | } else { |
2318 | 2476 | return null; |
2319 | 2477 | } |
2320 | 2478 | |
2321 | 2479 | if ( !isset( $this->last_result[$y] ) ) |
2322 | 2480 | return null; |
2323 | 2481 | |
2324 | 2482 | if ( $output == OBJECT ) { |
2325 | 2483 | return $this->last_result[$y] ? $this->last_result[$y] : null; |
2326 | 2484 | } elseif ( $output == ARRAY_A ) { |
2327 | 2485 | return $this->last_result[$y] ? get_object_vars( $this->last_result[$y] ) : null; |
2328 | 2486 | } elseif ( $output == ARRAY_N ) { |
2329 | 2487 | return $this->last_result[$y] ? array_values( get_object_vars( $this->last_result[$y] ) ) : null; |
2330 | 2488 | } elseif ( strtoupper( $output ) === OBJECT ) { |
2331 | 2489 | // Back compat for OBJECT being previously case insensitive. |
2336 | 2494 | } |
2337 | 2495 | |
2338 | 2496 | /** |
2339 | 2497 | * Retrieve one column from the database. |
2340 | 2498 | * |
2341 | 2499 | * Executes a SQL query and returns the column from the SQL result. |
2342 | 2500 | * If the SQL result contains more than one column, this function returns the column specified. |
2343 | 2501 | * If $query is null, this function returns the specified column from the previous SQL result. |
2344 | 2502 | * |
2345 | 2503 | * @since 0.71 |
2346 | 2504 | * |
2347 | 2505 | * @param string|null $query Optional. SQL query. Defaults to previous query. |
2348 | 2506 | * @param int $x Optional. Column to return. Indexed from 0. |
2349 | 2507 | * @return array Database query result. Array indexed from 0 by SQL result row number. |
2350 | 2508 | */ |
2358 | 2522 | } |
2359 | 2523 | |
2360 | 2524 | $new_array = array(); |
2361 | 2525 | // Extract the column values |
2362 | 2526 | for ( $i = 0, $j = count( $this->last_result ); $i < $j; $i++ ) { |
2363 | 2527 | $new_array[$i] = $this->get_var( null, $x, $i ); |
2364 | 2528 | } |
2365 | 2529 | return $new_array; |
2366 | 2530 | } |
2367 | 2531 | |
2368 | 2532 | /** |
2369 | 2533 | * Retrieve an entire SQL result set from the database (i.e., many rows) |
2370 | 2534 | * |
2371 | 2535 | * Executes a SQL query and returns the entire SQL result. |
2372 | 2536 | * |
2373 | 2537 | * @since 0.71 |
2374 | 2538 | * |
2375 | 2539 | * @param string $query SQL query. |
2376 | 2540 | * @param string $output Optional. Any of ARRAY_A | ARRAY_N | OBJECT | OBJECT_K constants. |
2377 | 2541 | * With one of the first three, return an array of rows indexed from 0 by SQL result row number. |
2378 | 2542 | * Each row is an associative array (column => value, ...), a numerically indexed array (0 => value, ...), or an object. ( ->column = value ), respectively. |
2379 | 2543 | * With OBJECT_K, return an associative array of row objects keyed by the value of each row's first column's value. |
2380 | 2544 | * Duplicate keys are discarded. |
2381 | 2545 | * @return array|object|null Database query results |
2382 | 2546 | */ |
2392 | 2562 | } else { |
2393 | 2563 | return null; |
2394 | 2564 | } |
2395 | 2565 | |
2396 | 2566 | $new_array = array(); |
2397 | 2567 | if ( $output == OBJECT ) { |
2398 | 2568 | // Return an integer-keyed array of row objects |
2399 | 2569 | return $this->last_result; |
2400 | 2570 | } elseif ( $output == OBJECT_K ) { |
2401 | 2571 | // Return an array of row objects with keys from column 1 |
2402 | 2572 | // (Duplicates are discarded) |
2403 | 2573 | foreach ( $this->last_result as $row ) { |
2404 | 2574 | $var_by_ref = get_object_vars( $row ); |
2405 | 2575 | $key = array_shift( $var_by_ref ); |
2406 | 2576 | if ( ! isset( $new_array[ $key ] ) ) |