? drupal-512962-D6.patch Index: includes/menu.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/menu.inc,v retrieving revision 1.255.2.32 diff -u -p -r1.255.2.32 menu.inc --- includes/menu.inc 6 Oct 2009 11:59:05 -0000 1.255.2.32 +++ includes/menu.inc 9 Jan 2010 00:25:59 -0000 @@ -579,7 +579,7 @@ function _menu_translate(&$router_item, $router_item['href'] = implode('/', $link_map); $router_item['options'] = array(); _menu_check_access($router_item, $map); - + // For performance, don't localize an item the user can't access. if ($router_item['access']) { _menu_item_localize($router_item, $map); @@ -1880,7 +1880,7 @@ function _menu_delete_item($item, $force * - plid The mlid of the parent. * - router_path The path of the relevant router item. * @return - * The mlid of the saved menu link, or FALSE if the menu link could not be + * The mlid of the saved menu link, or FALSE if the menu link could not be * saved. */ function menu_link_save(&$item) { @@ -2342,8 +2342,24 @@ function _menu_router_build($callbacks) watchdog('php', 'Menu router rebuild failed - some paths may not work correctly.', array(), WATCHDOG_ERROR); return array(); } - // Delete the existing router since we have some data to replace it. - db_query('DELETE FROM {menu_router}'); + + // Prep for multi-insert + $data = array(); + $chunks = 0; + $loop_counter = 0; + if (stristr($db_type, 'pgsql')) { + // Set Max Packet size to 16MB if using postgreSQL. + $max_packet = 16777216; + } + else { + // Get maximum packet size for mysql + $max_packet = db_result(db_query("SHOW VARIABLES WHERE Variable_name = 'max_allowed_packet'")); + // default to 1/2 MB + $max_packet = $max_packet > 524288 ? $max_packet : 524288; + // Assume 50 Kb is max size of each insert + $max_chunk = $max_packet/51200; + } + // Apply inheritance rules. foreach ($menu as $path => $v) { $item = &$menu[$path]; @@ -2425,22 +2441,83 @@ function _menu_router_build($callbacks) } $title_arguments = $item['title arguments'] ? serialize($item['title arguments']) : ''; - db_query("INSERT INTO {menu_router} - (path, load_functions, to_arg_functions, access_callback, - access_arguments, page_callback, page_arguments, fit, - number_parts, tab_parent, tab_root, - title, title_callback, title_arguments, - type, block_callback, description, position, weight, file) - VALUES ('%s', '%s', '%s', '%s', - '%s', '%s', '%s', %d, - %d, '%s', '%s', - '%s', '%s', '%s', - %d, '%s', '%s', '%s', %d, '%s')", - $path, $item['load_functions'], $item['to_arg_functions'], $item['access callback'], - serialize($item['access arguments']), $item['page callback'], serialize($item['page arguments']), $item['_fit'], - $item['_number_parts'], $item['tab_parent'], $item['tab_root'], - $item['title'], $item['title callback'], $title_arguments, - $item['type'], $item['block callback'], $item['description'], $item['position'], $item['weight'], $item['include file']); + + $data[$chunks][] = $path; + $data[$chunks][] = $item['load_functions']; + $data[$chunks][] = $item['to_arg_functions']; + $data[$chunks][] = $item['access callback']; + $data[$chunks][] = serialize($item['access arguments']); + $data[$chunks][] = $item['page callback']; + $data[$chunks][] = serialize($item['page arguments']); + $data[$chunks][] = $item['_fit']; + $data[$chunks][] = $item['_number_parts']; + $data[$chunks][] = $item['tab_parent']; + $data[$chunks][] = $item['tab_root']; + $data[$chunks][] = $item['title']; + $data[$chunks][] = $item['title callback']; + $data[$chunks][] = $title_arguments; + $data[$chunks][] = $item['type']; + $data[$chunks][] = $item['block callback']; + $data[$chunks][] = $item['description']; + $data[$chunks][] = $item['position']; + $data[$chunks][] = $item['weight']; + $data[$chunks][] = $item['include file']; + + $loop_counter++; + if ($loop_counter > $max_chunk) { + $chunks++; + $loop_counter = 0; + } + } + + // Delete the existing router since we have some data to replace it. + db_query('DELETE FROM {menu_router}'); + // Run the multi insert + foreach ($data as $values) { + _db_insert_multi('menu_router', array( + 'path', + 'load_functions', + 'to_arg_functions', + 'access_callback', + 'access_arguments', + 'page_callback', + 'page_arguments', + 'fit', + 'number_parts', + 'tab_parent', + 'tab_root', + 'title', + 'title_callback', + 'title_arguments', + 'type', + 'block_callback', + 'description', + 'position', + 'weight', + 'file', + ), + array( + "'%s'", + "'%s'", + "'%s'", + "'%s'", + "'%s'", + "'%s'", + "'%s'", + "%d", + "%d", + "'%s'", + "'%s'", + "'%s'", + "'%s'", + "'%s'", + "%d", + "'%s'", + "'%s'", + "'%s'", + "%d", + "'%s'", + ), $values); } // Sort the masks so they are in order of descending fit, and store them. $masks = array_keys($masks); @@ -2451,6 +2528,50 @@ function _menu_router_build($callbacks) } /** + * Insert many records into the database. + * + * NOTE Be aware of the MySQL's max_packet_size variable. + * + * @param $table + * The name of the table. + * @param $fields + * array of field names to be updated + * @param $placeholders + * array of db_query placeholders; like %d or '%s' + * @param $values + * array of values you wish to be inserted. If you have 3 fields then the + * array should be structured like + * array($field_1_value_A, $field_2_value_A, $field_3_value_A, + * $field_1_value_B, $field_2_value_B, $field_3_value_B); + * @param $suppress + * bool. TRUE to suppress db_query errors + * @return + * returns db_query() result. + */ +function _db_insert_multi($table, $fields, $placeholders, $data, $suppress = FALSE) { + // Get the number of rows that will be inserted + $rows = count($data)/count($fields); + // Build the values placeholders string. + $values = '(' . implode(', ', $placeholders) . ')'; + // Create what goes in the IN () + $v = $values; + // Add the rest of the place holders + for ($i = 1; $i < $rows; $i++) { + $v .= ', ' . $values; + } + // Build the fields part of this query + $fields = implode(', ', $fields); + $query = "INSERT INTO {" . $table . "} ($fields) VALUES $v"; + // Run the query + if ($suppress) { + return @db_query($query, $data); + } + else { + return db_query($query, $data); + } +} + +/** * Returns TRUE if a path is external (e.g. http://example.com). */ function menu_path_is_external($path) {