[ Index ] |
PHP Cross Reference of phpBB 3.0 Beta 3 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * @package search 5 * @version $Id: fulltext_mysql.php,v 1.30 2006/10/14 14:56:44 acydburn Exp $ 6 * @copyright (c) 2005 phpBB Group 7 * @license http://opensource.org/licenses/gpl-license.php GNU Public License 8 * 9 */ 10 11 /** 12 */ 13 if (!defined('IN_PHPBB')) 14 { 15 exit; 16 } 17 18 /** 19 * @ignore 20 */ 21 include_once($phpbb_root_path . 'includes/search/search.' . $phpEx); 22 23 /** 24 * fulltext_mysql 25 * Fulltext search for MySQL 26 * @package search 27 */ 28 class fulltext_mysql extends search_backend 29 { 30 var $stats = array(); 31 var $word_length = array(); 32 var $split_words = array(); 33 var $search_query; 34 var $common_words = array(); 35 36 function fulltext_mysql(&$error) 37 { 38 global $config; 39 40 $this->word_length = array('min' => $config['fulltext_mysql_min_word_len'], 'max' => $config['fulltext_mysql_max_word_len']); 41 42 $error = false; 43 } 44 45 /** 46 * Checks for correct MySQL version and stores min/max word length in the config 47 */ 48 function init() 49 { 50 global $db, $user; 51 52 if (strpos($db->sql_layer, 'mysql') === false) 53 { 54 return $user->lang['FULLTEXT_MYSQL_INCOMPATIBLE_VERSION']; 55 } 56 57 $result = $db->sql_query('SELECT VERSION() AS mysql_version'); 58 $version = $db->sql_fetchfield('mysql_version'); 59 $db->sql_freeresult($result); 60 61 if (!preg_match('#^4|5|6#s', $version)) 62 { 63 return $user->lang['FULLTEXT_MYSQL_INCOMPATIBLE_VERSION']; 64 } 65 66 $result = $db->sql_query('SHOW TABLE STATUS LIKE \'' . POSTS_TABLE . '\''); 67 $info = $db->sql_fetchrow($result); 68 $db->sql_freeresult($result); 69 70 $engine = ''; 71 if (isset($info['Engine'])) 72 { 73 $engine = $info['Engine']; 74 } 75 else if (isset($info['Type'])) 76 { 77 $engine = $info['Type']; 78 } 79 80 if ($engine != 'MyISAM') 81 { 82 return $user->lang['FULLTEXT_MYSQL_NOT_MYISAM']; 83 } 84 85 $sql = 'SHOW VARIABLES 86 LIKE \'ft\_%\''; 87 $result = $db->sql_query($sql); 88 89 $mysql_info = array(); 90 while ($row = $db->sql_fetchrow($result)) 91 { 92 $mysql_info[$row['Variable_name']] = $row['Value']; 93 } 94 $db->sql_freeresult($result); 95 96 set_config('fulltext_mysql_max_word_len', $mysql_info['ft_max_word_len']); 97 set_config('fulltext_mysql_min_word_len', $mysql_info['ft_min_word_len']); 98 99 return false; 100 } 101 102 /** 103 * Splits keywords entered by a user into an array of words stored in $this->split_words 104 * Stores the tidied search query in $this->search_query 105 * 106 * @param string $keywords Contains the keyword as entered by the user 107 * @param string $terms is either 'all' or 'any' 108 * @return false if no valid keywords were found and otherwise true 109 */ 110 function split_keywords(&$keywords, $terms) 111 { 112 global $config; 113 114 $this->get_ignore_words(); 115 $this->get_synonyms(); 116 117 if ($terms == 'all') 118 { 119 $match = array('#\sand\s#i', '#\sor\s#i', '#\snot\s#i', '#\+#', '#-#', '#\|#'); 120 $replace = array(' +', ' |', ' -', ' +', ' -', ' |'); 121 122 $keywords = preg_replace($match, $replace, $keywords); 123 } 124 125 $match = array(); 126 // New lines, carriage returns 127 $match[] = "#[\n\r]+#"; 128 // NCRs like etc. 129 $match[] = '#(&|&)[\#a-z0-9]+?;#i'; 130 131 // Filter out as above 132 $keywords = preg_replace($match, ' ', trim($keywords)); 133 134 // Split words 135 $split_keywords = preg_replace('#([^\w\'*])#', '$1$1', str_replace('\'\'', '\' \'', trim($keywords))); 136 $matches = array(); 137 preg_match_all('#(?:[^\w*]|^)([+\-|]?(?:[\w*]+\'?)*[\w*])(?:[^\w*]|$)#', $split_keywords, $matches); 138 $this->split_words = $matches[1]; 139 140 if (sizeof($this->ignore_words)) 141 { 142 $this->common_words = array_intersect($this->split_words, $this->ignore_words); 143 $this->split_words = array_diff($this->split_words, $this->ignore_words); 144 } 145 146 if (sizeof($this->replace_synonym)) 147 { 148 $this->split_words = str_replace($this->replace_synonym, $this->match_synonym, $this->split_words); 149 } 150 151 foreach ($this->split_words as $i => $word) 152 { 153 $clean_word = preg_replace('#^[+\-|]#', '', $word); 154 155 // check word length 156 $clean_len = utf8_strlen(str_replace('*', '', $clean_word)); 157 if (($clean_len < $config['fulltext_mysql_min_word_len']) || ($clean_len > $config['fulltext_mysql_max_word_len'])) 158 { 159 $this->common_words[] = $word; 160 unset($this->split_words[$i]); 161 } 162 } 163 164 $this->search_query = implode(' ', $this->split_words); 165 166 if (sizeof($this->split_words)) 167 { 168 $this->split_words = array_values($this->split_words); 169 sort($this->split_words); 170 return true; 171 } 172 return false; 173 } 174 175 /** 176 * Turns text into an array of words 177 */ 178 function split_message($text) 179 { 180 global $config; 181 182 $this->get_ignore_words(); 183 $this->get_synonyms(); 184 185 // Split words 186 $text = preg_replace('#([^\w\'*])#', '$1$1', str_replace('\'\'', '\' \'', trim($text))); 187 $matches = array(); 188 preg_match_all('#(?:[^\w*]|^)([+\-|]?(?:[\w*]+\'?)*[\w*])(?:[^\w*]|$)#', $text, $matches); 189 $text = $matches[1]; 190 191 if (sizeof($this->ignore_words)) 192 { 193 $text = array_diff($text, $this->ignore_words); 194 } 195 196 if (sizeof($this->replace_synonym)) 197 { 198 $text = str_replace($this->replace_synonym, $this->match_synonym, $text); 199 } 200 201 // remove too short or too long words 202 $text = array_values($text); 203 for ($i = 0, $n = sizeof($text); $i < $n; $i++) 204 { 205 $text[$i] = trim($text[$i]); 206 if (utf8_strlen($text[$i]) < $config['fulltext_mysql_min_word_len'] || utf8_strlen($text[$i]) > $config['fulltext_mysql_max_word_len']) 207 { 208 unset($text[$i]); 209 } 210 } 211 212 return array_values($text); 213 } 214 215 /** 216 * Performs a search on keywords depending on display specific params. 217 * 218 * @param array $id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered 219 * @param int $start indicates the first index of the page 220 * @param int $per_page number of ids each page is supposed to contain 221 * @return total number of results 222 */ 223 function keyword_search($type, &$fields, &$terms, &$sort_by_sql, &$sort_key, &$sort_dir, &$sort_days, &$ex_fid_ary, &$m_approve_fid_ary, &$topic_id, &$author_ary, &$id_ary, $start, $per_page) 224 { 225 global $config, $db; 226 227 // No keywords? No posts. 228 if (!sizeof($this->split_words)) 229 { 230 return false; 231 } 232 233 // generate a search_key from all the options to identify the results 234 $search_key = md5(implode('#', array( 235 implode(',', $this->split_words), 236 $type, 237 $fields, 238 $terms, 239 $sort_days, 240 $sort_key, 241 $topic_id, 242 implode(',', $ex_fid_ary), 243 implode(',', $m_approve_fid_ary), 244 implode(',', $author_ary) 245 ))); 246 247 // try reading the results from cache 248 $result_count = 0; 249 if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE) 250 { 251 return $result_count; 252 } 253 254 $id_ary = array(); 255 256 $join_topic = ($type == 'posts') ? false : true; 257 258 // Build sql strings for sorting 259 $sql_sort = $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC'); 260 $sql_sort_table = $sql_sort_join = ''; 261 262 switch ($sql_sort[0]) 263 { 264 case 'u': 265 $sql_sort_table = USERS_TABLE . ' u, '; 266 $sql_sort_join = ($type == 'posts') ? ' AND u.user_id = p.poster_id ' : ' AND u.user_id = t.topic_poster '; 267 break; 268 269 case 't': 270 $join_topic = true; 271 break; 272 273 case 'f': 274 $sql_sort_table = FORUMS_TABLE . ' f, '; 275 $sql_sort_join = ' AND f.forum_id = p.forum_id '; 276 break; 277 } 278 279 // Build some display specific sql strings 280 switch ($fields) 281 { 282 case 'titleonly': 283 $sql_match = 'p.post_subject'; 284 $sql_match_where = ' AND p.post_id = t.topic_first_post_id'; 285 $join_topic = true; 286 break; 287 288 case 'msgonly': 289 $sql_match = 'p.post_text'; 290 $sql_match_where = ''; 291 break; 292 293 case 'firstpost': 294 $sql_match = 'p.post_subject, p.post_text'; 295 $sql_match_where = ' AND p.post_id = t.topic_first_post_id'; 296 $join_topic = true; 297 break; 298 299 default: 300 $sql_match = 'p.post_subject, p.post_text'; 301 $sql_match_where = ''; 302 break; 303 } 304 305 if (!sizeof($m_approve_fid_ary)) 306 { 307 $m_approve_fid_sql = ' AND p.post_approved = 1'; 308 } 309 else if ($m_approve_fid_ary === array(-1)) 310 { 311 $m_approve_fid_sql = ''; 312 } 313 else 314 { 315 $m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')'; 316 } 317 318 $sql_select = (!$result_count) ? 'SQL_CALC_FOUND_ROWS ' : ''; 319 $sql_select = ($type == 'posts') ? $sql_select . 'p.post_id' : 'DISTINCT ' . $sql_select . 't.topic_id'; 320 $sql_from = ($join_topic) ? TOPICS_TABLE . ' t, ' : ''; 321 $field = ($type == 'posts') ? 'post_id' : 'topic_id'; 322 $sql_author = (sizeof($author_ary) == 1) ? ' = ' . $author_ary[0] : 'IN (' . implode(', ', $author_ary) . ')'; 323 324 $sql_where_options = $sql_sort_join; 325 $sql_where_options .= ($topic_id) ? ' AND p.topic_id = ' . $topic_id : ''; 326 $sql_where_options .= ($join_topic) ? ' AND t.topic_id = p.topic_id' : ''; 327 $sql_where_options .= (sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; 328 $sql_where_options .= $m_approve_fid_sql; 329 $sql_where_options .= (sizeof($author_ary)) ? ' AND p.poster_id ' . $sql_author : ''; 330 $sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; 331 $sql_where_options .= $sql_match_where; 332 333 // split the words into words that have to be included or must not be included and optional words 334 $words = $any_words = array(); 335 if ($terms == 'all') 336 { 337 foreach ($this->split_words as $id => $word) 338 { 339 if ((strpos($word, '+') === 0) || (strpos($word, '-') === 0)) 340 { 341 $words[] = $word; 342 } 343 else if (strpos($word, '|') === 0) 344 { 345 $any_words[] = substr($word, 1); 346 } 347 else 348 { 349 $words[] = '+' . $word; 350 } 351 } 352 } 353 else 354 { 355 foreach ($this->split_words as $id => $word) 356 { 357 if ((strpos($word, '+') === 0) || (strpos($word, '-') === 0) || (strpos($word, '|') === 0)) 358 { 359 $words[] = substr($word, 1); 360 } 361 else 362 { 363 $words[] = $word; 364 } 365 } 366 } 367 368 // Get the ids for the current result block 369 $any_words = (sizeof($any_words)) ? ' +(' . implode(' ', $any_words) . ')' : ''; 370 371 $sql = "SELECT $sql_select 372 FROM $sql_from$sql_sort_table" . POSTS_TABLE . " p 373 WHERE MATCH ($sql_match) AGAINST ('" . $db->sql_escape(implode(' ', $words)) . $any_words . "' IN BOOLEAN MODE) 374 $sql_where_options 375 ORDER BY $sql_sort"; 376 $result = $db->sql_query_limit($sql, $config['search_block_size'], $start); 377 378 while ($row = $db->sql_fetchrow($result)) 379 { 380 $id_ary[] = $row[$field]; 381 } 382 $db->sql_freeresult($result); 383 384 $id_ary = array_unique($id_ary); 385 386 if (!sizeof($id_ary)) 387 { 388 return false; 389 } 390 391 // if the total result count is not cached yet, retrieve it from the db 392 if (!$result_count) 393 { 394 $sql = 'SELECT FOUND_ROWS() as result_count'; 395 $result = $db->sql_query($sql); 396 $result_count = (int) $db->sql_fetchfield('result_count'); 397 $db->sql_freeresult($result); 398 399 if (!$result_count) 400 { 401 return false; 402 } 403 } 404 405 // store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page 406 $this->save_ids($search_key, implode(' ', $this->split_words), $author_ary, $result_count, $id_ary, $start, $sort_dir); 407 $id_ary = array_slice($id_ary, 0, (int) $per_page); 408 409 return $result_count; 410 } 411 412 /** 413 * Performs a search on an author's posts without caring about message contents. Depends on display specific params 414 * 415 * @param array $id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered 416 * @param int $start indicates the first index of the page 417 * @param int $per_page number of ids each page is supposed to contain 418 * @return total number of results 419 */ 420 function author_search($type, &$sort_by_sql, &$sort_key, &$sort_dir, &$sort_days, &$ex_fid_ary, &$m_approve_fid_ary, &$topic_id, &$author_ary, &$id_ary, $start, $per_page) 421 { 422 global $config, $db; 423 424 // No author? No posts. 425 if (!sizeof($author_ary)) 426 { 427 return 0; 428 } 429 430 // generate a search_key from all the options to identify the results 431 $search_key = md5(implode('#', array( 432 '', 433 $type, 434 '', 435 '', 436 $sort_days, 437 $sort_key, 438 $topic_id, 439 implode(',', $ex_fid_ary), 440 implode(',', $m_approve_fid_ary), 441 implode(',', $author_ary) 442 ))); 443 444 // try reading the results from cache 445 $result_count = 0; 446 if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE) 447 { 448 return $result_count; 449 } 450 451 $id_ary = array(); 452 453 // Create some display specific sql strings 454 $sql_author = $db->sql_in_set('p.poster_id', $author_ary); 455 $sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; 456 $sql_topic_id = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : ''; 457 $sql_time = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; 458 459 // Build sql strings for sorting 460 $sql_sort = $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC'); 461 $sql_sort_table = $sql_sort_join = ''; 462 switch ($sql_sort[0]) 463 { 464 case 'u': 465 $sql_sort_table = USERS_TABLE . ' u, '; 466 $sql_sort_join = ($type == 'posts') ? ' AND u.user_id = p.poster_id ' : ' AND u.user_id = t.topic_poster '; 467 break; 468 469 case 't': 470 $sql_sort_table = ($type == 'posts') ? TOPICS_TABLE . ' t, ' : ''; 471 $sql_sort_join = ($type == 'posts') ? ' AND t.topic_id = p.topic_id ' : ''; 472 break; 473 474 case 'f': 475 $sql_sort_table = FORUMS_TABLE . ' f, '; 476 $sql_sort_join = ' AND f.forum_id = p.forum_id '; 477 break; 478 } 479 480 if (!sizeof($m_approve_fid_ary)) 481 { 482 $m_approve_fid_sql = ' AND p.post_approved = 1'; 483 } 484 else if ($m_approve_fid_ary == array(-1)) 485 { 486 $m_approve_fid_sql = ''; 487 } 488 else 489 { 490 $m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')'; 491 } 492 493 // If the cache was completely empty count the results 494 $calc_results = ($result_count) ? '' : 'SQL_CALC_FOUND_ROWS '; 495 496 // Build the query for really selecting the post_ids 497 if ($type == 'posts') 498 { 499 $sql = "SELECT {$calc_results}p.post_id 500 FROM " . $sql_sort_table . POSTS_TABLE . " p 501 WHERE $sql_author 502 $sql_topic_id 503 $m_approve_fid_sql 504 $sql_fora 505 $sql_sort_join 506 $sql_time 507 ORDER BY $sql_sort"; 508 $field = 'post_id'; 509 } 510 else 511 { 512 $sql = "SELECT {$calc_results}t.topic_id 513 FROM " . $sql_sort_table . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p 514 WHERE $sql_author 515 $sql_topic_id 516 $m_approve_fid_sql 517 $sql_fora 518 AND t.topic_id = p.topic_id 519 $sql_sort_join 520 $sql_time 521 GROUP BY t.topic_id 522 ORDER BY $sql_sort"; 523 $field = 'topic_id'; 524 } 525 526 // Only read one block of posts from the db and then cache it 527 $result = $db->sql_query_limit($sql, $config['search_block_size'], $start); 528 529 while ($row = $db->sql_fetchrow($result)) 530 { 531 $id_ary[] = $row[$field]; 532 } 533 $db->sql_freeresult($result); 534 535 // retrieve the total result count if needed 536 if (!$result_count) 537 { 538 $sql = 'SELECT FOUND_ROWS() as result_count'; 539 $result = $db->sql_query($sql); 540 $result_count = (int) $db->sql_fetchfield('result_count'); 541 $db->sql_freeresult($result); 542 543 if (!$result_count) 544 { 545 return false; 546 } 547 } 548 549 if (sizeof($id_ary)) 550 { 551 $this->save_ids($search_key, '', $author_ary, $result_count, $id_ary, $start, $sort_dir); 552 $id_ary = array_slice($id_ary, 0, $per_page); 553 554 return $result_count; 555 } 556 return false; 557 } 558 559 /** 560 * Destroys cached search results, that contained one of the new words in a post so the results won't be outdated. 561 * 562 * @param string $mode contains the post mode: edit, post, reply, quote ... 563 */ 564 function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id) 565 { 566 global $db; 567 568 // Split old and new post/subject to obtain array of words 569 $split_text = $this->split_message($message); 570 $split_title = ($subject) ? $this->split_message($subject) : array(); 571 572 $words = array(); 573 if ($mode == 'edit') 574 { 575 $old_text = array(); 576 $old_title = array(); 577 578 $sql = 'SELECT post_text, post_subject 579 FROM ' . POSTS_TABLE . " 580 WHERE post_id = $post_id"; 581 $result = $db->sql_query($sql); 582 583 if ($row = $db->sql_fetchrow($result)) 584 { 585 $old_text = $this->split_message($row['post_text']); 586 $old_title = $this->split_message($row['post_subject']); 587 } 588 $db->sql_freeresult($result); 589 590 $words = array_unique(array_merge( 591 array_diff($split_text, $old_text), 592 array_diff($split_title, $old_title), 593 array_diff($old_text, $split_text), 594 array_diff($old_title, $split_title) 595 )); 596 unset($old_title); 597 unset($old_text); 598 } 599 else 600 { 601 $words = array_unique(array_merge($split_text, $split_title)); 602 } 603 unset($split_text); 604 unset($split_title); 605 606 // destroy cached search results containing any of the words removed or added 607 $this->destroy_cache($words, array($poster_id)); 608 609 unset($words); 610 } 611 612 /** 613 * Destroy cached results, that might be outdated after deleting a post 614 */ 615 function index_remove($post_ids, $author_ids, $forum_ids) 616 { 617 $this->destroy_cache(array(), $author_ids); 618 } 619 620 /** 621 * Destroy old cache entries 622 */ 623 function tidy() 624 { 625 global $db, $config; 626 627 // destroy too old cached search results 628 $this->destroy_cache(array()); 629 630 set_config('search_last_gc', time(), true); 631 } 632 633 /** 634 * Create fulltext index 635 */ 636 function create_index($acp_module, $u_action) 637 { 638 global $db; 639 640 // Make sure we can actually use MySQL with fulltext indexes 641 if ($error = $this->init()) 642 { 643 return $error; 644 } 645 646 if (empty($this->stats)) 647 { 648 $this->get_stats(); 649 } 650 651 if (!isset($this->stats['post_subject'])) 652 { 653 $db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ADD FULLTEXT (post_subject)'); 654 } 655 656 if (!isset($this->stats['post_text'])) 657 { 658 $db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ADD FULLTEXT (post_text)'); 659 } 660 661 $db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); 662 663 return false; 664 } 665 666 /** 667 * Drop fulltext index 668 */ 669 function delete_index($acp_module, $u_action) 670 { 671 global $db; 672 673 // Make sure we can actually use MySQL with fulltext indexes 674 if ($error = $this->init()) 675 { 676 return $error; 677 } 678 679 if (empty($this->stats)) 680 { 681 $this->get_stats(); 682 } 683 684 if (isset($this->stats['post_subject'])) 685 { 686 $db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' DROP INDEX post_subject'); 687 } 688 689 if (isset($this->stats['post_text'])) 690 { 691 $db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' DROP INDEX post_text'); 692 } 693 694 $db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); 695 696 return false; 697 } 698 699 /** 700 * Returns true if both FULLTEXT indexes exist 701 */ 702 function index_created() 703 { 704 if (empty($this->stats)) 705 { 706 $this->get_stats(); 707 } 708 709 return (isset($this->stats['post_text']) && isset($this->stats['post_subject'])) ? true : false; 710 } 711 712 /** 713 * Returns an associative array containing information about the indexes 714 */ 715 function index_stats() 716 { 717 global $user; 718 719 if (empty($this->stats)) 720 { 721 $this->get_stats(); 722 } 723 724 return array( 725 $user->lang['FULLTEXT_MYSQL_TOTAL_POSTS'] => ($this->index_created()) ? $this->stats['total_posts'] : 0, 726 $user->lang['FULLTEXT_MYSQL_TEXT_CARDINALITY'] => isset($this->stats['post_text']['Cardinality']) ? $this->stats['post_text']['Cardinality'] : 0, 727 $user->lang['FULLTEXT_MYSQL_SUBJECT_CARDINALITY'] => isset($this->stats['post_subject']['Cardinality']) ? $this->stats['post_subject']['Cardinality'] : 0, 728 ); 729 } 730 731 function get_stats() 732 { 733 global $db; 734 735 if (strpos($db->sql_layer, 'mysql') === false) 736 { 737 $this->stats = array(); 738 return; 739 } 740 741 $sql = 'SHOW INDEX 742 FROM ' . POSTS_TABLE; 743 $result = $db->sql_query($sql); 744 745 while ($row = $db->sql_fetchrow($result)) 746 { 747 // deal with older MySQL versions which didn't use Index_type 748 $index_type = (isset($row['Index_type'])) ? $row['Index_type'] : $row['Comment']; 749 750 if ($index_type == 'FULLTEXT') 751 { 752 if ($row['Column_name'] == 'post_text') 753 { 754 $this->stats['post_text'] = $row; 755 } 756 else if ($row['Column_name'] == 'post_subject') 757 { 758 $this->stats['post_subject'] = $row; 759 } 760 } 761 } 762 $db->sql_freeresult($result); 763 764 $sql = 'SELECT COUNT(post_id) as total_posts 765 FROM ' . POSTS_TABLE; 766 $result = $db->sql_query($sql); 767 $this->stats['total_posts'] = (int) $db->sql_fetchfield('total_posts'); 768 $db->sql_freeresult($result); 769 } 770 } 771 772 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 22 00:35:05 2006 | Cross-referenced by PHPXref 0.6 |