Index: includes/database.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.inc,v retrieving revision 1.62.2.4 diff -u -p -r1.62.2.4 database.inc --- includes/database.inc 12 Jul 2007 06:25:47 -0000 1.62.2.4 +++ includes/database.inc 28 Jul 2007 19:10:53 -0000 @@ -44,6 +44,13 @@ */ /** + * Convenience constants for specifying master or slave servers in a query. + * + */ +define('DB_MASTER', 'master'); +define('DB_SLAVE', 'slave'); + +/** * Append a database prefix to all tables in a query. * * Queries sent to Drupal should wrap all table names in curly brackets. This @@ -99,13 +106,23 @@ function db_prefix_tables($sql) { * @return the name of the previously active database or FALSE if non was found. */ function db_set_active($name = 'default') { - global $db_url, $db_type, $active_db; - static $db_conns; + global $db_url, $db_type, $active_db, $active_db_slave; + static $db_conns, $db_conns_slave; if (!isset($db_conns[$name])) { // Initiate a new connection, using the named DB URL specified. if (is_array($db_url)) { $connect_url = array_key_exists($name, $db_url) ? $db_url[$name] : $db_url['default']; + if (is_array($connect_url)) { + $connect_url_slave = $connect_url['slave']; + $connect_url = $connect_url['master']; + if (is_array($connect_url)) { + $connect_url = $connect_url[mt_rand(0, count($connect_url))]; + } + if (is_array($connect_url_slave)) { + $connect_url_slave = $connect_url_slave[mt_rand(0, count($connect_url_slave))]; + } + } } else { $connect_url = $db_url; @@ -126,11 +143,18 @@ function db_set_active($name = 'default' } $db_conns[$name] = db_connect($connect_url); + if (isset($connect_url_slave)) { + $db_conns_slave[$name] = db_connect($connect_url_slave); + } + else { + $db_conns_slave[$name] = $db_conns[$name]; + } } $previous_db = $active_db; // Set the active connection. $active_db = $db_conns[$name]; + $active_db_slave = $db_conns_slave[$name]; return array_search($previous_db, $db_conns); } @@ -183,21 +207,32 @@ define('DB_QUERY_REGEXP', '/(%d|%s|%%|%f * * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, * and TRUE values to decimal 1. - * + * @param $replication_type + * This parameter is only available if the query arguments are passed as a + * single array. If set to DB_SLAVE, the query will be run against a slave + * server if available. If no slave server is configured, it has no effect. + * * @return * A database query result resource, or FALSE if the query was not * executed correctly. */ function db_query($query) { - $args = func_get_args(); - array_shift($args); + $replication_type = DB_MASTER; + $function_args = func_get_args(); + array_shift($function_args); $query = db_prefix_tables($query); - if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax - $args = $args[0]; + if (isset($function_args[0]) and is_array($function_args[0])) { // 'All arguments in one array' syntax. + $args = $function_args[0]; + if (isset($function_args[1])) { // Determine if this query is safe to run against a slave server. + $replication_type = $function_args[1]; + } + } + else { + $args = $function_args; } _db_query_callback($args, TRUE); $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); - return _db_query($query); + return _db_query($query, 0, $replication_type); } /** Index: includes/database.mysql.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.mysql.inc,v retrieving revision 1.66.2.1 diff -u -p -r1.66.2.1 database.mysql.inc --- includes/database.mysql.inc 22 Jan 2007 02:20:50 -0000 1.66.2.1 +++ includes/database.mysql.inc 28 Jul 2007 19:10:53 -0000 @@ -142,15 +142,15 @@ function db_connect($url) { /** * Helper function for db_query(). */ -function _db_query($query, $debug = 0) { - global $active_db, $queries; +function _db_query($query, $debug = 0, $replication_type = DB_MASTER) { + global $active_db, $active_db_slave, $queries; if (variable_get('dev_query', 0)) { list($usec, $sec) = explode(' ', microtime()); $timer = (float)$usec + (float)$sec; } - $result = mysql_query($query, $active_db); + $result = mysql_query($query, ($replication_type == DB_SLAVE) ? $active_db_slave : $active_db); if (variable_get('dev_query', 0)) { $bt = debug_backtrace(); @@ -158,7 +158,7 @@ function _db_query($query, $debug = 0) { list($usec, $sec) = explode(' ', microtime()); $stop = (float)$usec + (float)$sec; $diff = $stop - $timer; - $queries[] = array($query, $diff); + $queries[] = array($query, $diff, $replication_type); } if ($debug) { @@ -296,6 +296,10 @@ function db_affected_rows() { * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, * and TRUE values to decimal 1. * + * @param $replication_type + * This parameter is only available if the query arguments are passed as a + * single array. If set to DB_SLAVE, the query will be run against a slave + * server if available. If no slave server is configured, it has no effect. * @param $from * The first result row to return. * @param $count @@ -305,19 +309,26 @@ function db_affected_rows() { * correctly. */ function db_query_range($query) { - $args = func_get_args(); - $count = array_pop($args); - $from = array_pop($args); - array_shift($args); - + $replication_type = FALSE; + $function_args = func_get_args(); + $count = array_pop($function_args); + $from = array_pop($function_args); + array_shift($function_args); $query = db_prefix_tables($query); - if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax - $args = $args[0]; + if (isset($function_args[0]) and is_array($function_args[0])) { // 'All arguments in one array' syntax. + $args = $function_args[0]; + if (isset($function_args[1])) { // Determine if this query is safe to run against a slave server. + $replication_type = $function_args[1]; + } + } + else { + $args = $function_args; } + _db_query_callback($args, TRUE); $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); $query .= ' LIMIT '. (int)$from .', '. (int)$count; - return _db_query($query); + return _db_query($query, 0, $replication_type); } /** Index: includes/database.mysqli.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.mysqli.inc,v retrieving revision 1.32 diff -u -p -r1.32 database.mysqli.inc --- includes/database.mysqli.inc 27 Dec 2006 22:50:09 -0000 1.32 +++ includes/database.mysqli.inc 28 Jul 2007 19:10:53 -0000 @@ -121,15 +121,15 @@ function db_connect($url) { /** * Helper function for db_query(). */ -function _db_query($query, $debug = 0) { - global $active_db, $queries; +function _db_query($query, $debug = 0, $replication_type = DB_MASTER) { + global $active_db, $active_db_slave, $queries; if (variable_get('dev_query', 0)) { list($usec, $sec) = explode(' ', microtime()); $timer = (float)$usec + (float)$sec; } - $result = mysqli_query($active_db, $query); + $result = mysqli_query(($replication_type == DB_SLAVE) ? $active_db_slave : $active_db, $query); if (variable_get('dev_query', 0)) { $bt = debug_backtrace(); @@ -137,7 +137,7 @@ function _db_query($query, $debug = 0) { list($usec, $sec) = explode(' ', microtime()); $stop = (float)$usec + (float)$sec; $diff = $stop - $timer; - $queries[] = array($query, $diff); + $queries[] = array($query, $diff, $replication_type); } if ($debug) { @@ -285,19 +285,25 @@ function db_affected_rows() { * correctly. */ function db_query_range($query) { - $args = func_get_args(); - $count = array_pop($args); - $from = array_pop($args); - array_shift($args); - + $replication_type = DB_MASTER; + $function_args = func_get_args(); + $count = array_pop($function_args); + $from = array_pop($function_args); + array_shift($function_args); $query = db_prefix_tables($query); - if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax - $args = $args[0]; + if (isset($function_args[0]) and is_array($function_args[0])) { // 'All arguments in one array' syntax. + $args = $function_args[0]; + if (isset($function_args[1])) { // Determine if this query is safe to run against a slave server. + $replication_type = $function_args[1]; + } + } + else { + $args = $function_args; } _db_query_callback($args, TRUE); $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); $query .= ' LIMIT '. (int)$from .', '. (int)$count; - return _db_query($query); + return _db_query($query, 0, replication_type); } /** Index: includes/database.pgsql.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.pgsql.inc,v retrieving revision 1.43 diff -u -p -r1.43 database.pgsql.inc --- includes/database.pgsql.inc 27 Dec 2006 22:13:56 -0000 1.43 +++ includes/database.pgsql.inc 28 Jul 2007 19:10:53 -0000 @@ -114,15 +114,15 @@ function db_connect($url) { /** * Helper function for db_query(). */ -function _db_query($query, $debug = 0) { - global $active_db, $last_result, $queries; +function _db_query($query, $debug = 0, $replication_type = DB_MASTER) { + global $active_db, $active_db_slave, $last_result, $queries; if (variable_get('dev_query', 0)) { list($usec, $sec) = explode(' ', microtime()); $timer = (float)$usec + (float)$sec; } - $last_result = pg_query($active_db, $query); + $last_result = pg_query(($replication_type == DB_SLAVE) ? $active_db_slave : $active_db, $query); if (variable_get('dev_query', 0)) { $bt = debug_backtrace(); @@ -130,7 +130,7 @@ function _db_query($query, $debug = 0) { list($usec, $sec) = explode(' ', microtime()); $stop = (float)$usec + (float)$sec; $diff = $stop - $timer; - $queries[] = array($query, $diff); + $queries[] = array($query, $diff, $replication_type); } if ($debug) { @@ -266,6 +266,10 @@ function db_affected_rows() { * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, * and TRUE values to decimal 1. * + * @param $replication_type + * This parameter is only available if the query arguments are passed as a + * single array. If set to DB_SLAVE, the query will be run against a slave + * server if available. If no slave server is configured, it has no effect. * @param $from * The first result row to return. * @param $count @@ -275,19 +279,25 @@ function db_affected_rows() { * correctly. */ function db_query_range($query) { - $args = func_get_args(); - $count = array_pop($args); - $from = array_pop($args); - array_shift($args); - + $replication_type = DB_MASTER; + $function_args = func_get_args(); + $count = array_pop($function_args); + $from = array_pop($function_args); + array_shift($function_args); $query = db_prefix_tables($query); - if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax - $args = $args[0]; + if (isset($function_args[0]) and is_array($function_args[0])) { // 'All arguments in one array' syntax. + $args = $function_args[0]; + if (isset($function_args[1])) { // Determine if this query is safe to run against a slave server. + $replication_type = $function_args[1]; + } + } + else { + $args = $function_args; } _db_query_callback($args, TRUE); $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); $query .= ' LIMIT '. (int)$count .' OFFSET '. (int)$from; - return _db_query($query); + return _db_query($query, 0, $replication_type); } /** Index: includes/pager.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/pager.inc,v retrieving revision 1.59 diff -u -p -r1.59 pager.inc --- includes/pager.inc 15 Oct 2006 19:57:05 -0000 1.59 +++ includes/pager.inc 28 Jul 2007 19:10:53 -0000 @@ -42,6 +42,10 @@ * the count query) using printf() syntax. Instead of a variable number of * query arguments, you may also pass a single array containing the query * arguments. + * @param $replication_type + * This parameter is only available if the query arguments are passed as a + * single array. If set to DB_SLAVE, the query will be run against a slave + * server if available. If no slave server is configured, it has no effect. * @return * A database query result resource, or FALSE if the query was not executed * correctly. @@ -50,14 +54,21 @@ */ function pager_query($query, $limit = 10, $element = 0, $count_query = NULL) { global $pager_page_array, $pager_total, $pager_total_items; + + $replication_type = DB_MASTER; + $page = isset($_GET['page']) ? $_GET['page'] : ''; - - // Substitute in query arguments. - $args = func_get_args(); - $args = array_slice($args, 4); - // Alternative syntax for '...' - if (isset($args[0]) && is_array($args[0])) { - $args = $args[0]; + + $function_args = func_get_args(); + $function_args = array_slice($function_args, 4); + if (isset($function_args[0]) and is_array($function_args[0])) { // 'All arguments in one array' syntax. + $args = $function_args[0]; + if (isset($function_args[1])) { // Determine if this query is safe to run against a slave server. + $replication_type = $function_args[1]; + } + } + else { + $args = $function_args; } // Construct a count query if none was given. @@ -72,7 +83,7 @@ function pager_query($query, $limit = 10 $pager_total_items[$element] = db_result(db_query($count_query, $args)); $pager_total[$element] = ceil($pager_total_items[$element] / $limit); $pager_page_array[$element] = max(0, min((int)$pager_page_array[$element], ((int)$pager_total[$element]) - 1)); - return db_query_range($query, $args, $pager_page_array[$element] * $limit, $limit); + return db_query_range($query, $args, $replication_type, $pager_page_array[$element] * $limit, $limit); } /** Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.776.2.19 diff -u -p -r1.776.2.19 node.module --- modules/node/node.module 26 Jul 2007 19:16:46 -0000 1.776.2.19 +++ modules/node/node.module 28 Jul 2007 19:10:54 -0000 @@ -2418,7 +2418,7 @@ function node_page_default($arg = NULL) return MENU_NOT_FOUND; } - $result = pager_query(db_rewrite_sql('SELECT n.nid, n.sticky, n.created FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC'), variable_get('default_nodes_main', 10)); + $result = pager_query(db_rewrite_sql('SELECT n.nid, n.sticky, n.created FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC'), variable_get('default_nodes_main', 10), 0, NULL, array(), DB_SLAVE); if (db_num_rows($result)) { $feed_url = url('rss.xml', NULL, NULL, TRUE); @@ -2432,7 +2432,7 @@ function node_page_default($arg = NULL) } else { // Check for existence of admin account. - $admin = db_result(db_query('SELECT uid FROM {users} WHERE uid = 1')); + $admin = db_result(db_query('SELECT uid FROM {users} WHERE uid = 1', array(), DB_SLAVE)); $default_message = t('
Please follow these steps to set up and start using your website:
'); $default_message .= '