mariadb/mysql-test/suite/innodb_fts/t/fulltext_order_by.test
Aleksey Midenkov e056efdd6c MDEV-25004 Missing row in FTS_DOC_ID_INDEX during DELETE HISTORY
1. In case of system-versioned table add row_end into FTS_DOC_ID index
   in fts_create_common_tables() and innobase_create_key_defs().
   fts_n_uniq() returns 1 or 2 depending on whether the table is
   system-versioned.

   After this patch recreate of FTS_DOC_ID index is required for
   existing system-versioned tables. If you see this message in error
   log or server warnings: "InnoDB: Table db/t1 contains 2 indexes
   inside InnoDB, which is different from the number of indexes 1
   defined in the MariaDB" use this command to fix the table:

      ALTER TABLE db.t1 FORCE;

2. Fix duplicate history for secondary unique index like it was done
   in MDEV-23644 for clustered index (932ec586aa). In case of
   existing history row which conflicts with currently inseted row we
   check in row_ins_scan_sec_index_for_duplicate() whether that row
   was inserted as part of current transaction. In that case we
   indicate with DB_FOREIGN_DUPLICATE_KEY that new history row is not
   needed and should be silently skipped.

3. Some parts of MDEV-21138 (7410ff436e) reverted. Skipping of
   FTS_DOC_ID index for history rows made problems with purge
   system. Now this is fixed differently by p.2.

4. wait_all_purged.inc checks that we didn't affect non-history rows
   so they are deleted and purged correctly.

Additional FTS fixes

  fts_init_get_doc_id(): exclude history rows from max_doc_id
  calculation. fts_init_get_doc_id() callback is used only for crash
  recovery.

  fts_add_doc_by_id(): set max value for row_end field.

  fts_read_stopword(): stopwords table can be system-versioned too. We
  now read stopwords only for current data.

  row_insert_for_mysql(): exclude history rows from doc_id validation.

  row_merge_read_clustered_index(): exclude history_rows from doc_id
  processing.

  fts_load_user_stopword(): for versioned table retrieve row_end field
  and skip history rows. For non-versioned table we retrieve 'value'
  field twice (just for uniformity).

FTS tests for System Versioning now include maybe_versioning.inc which
adds 3 combinations:

'vers'     for debug build sets sysvers_force and
	   sysvers_hide. sysvers_force makes every created table
	   system-versioned, sysvers_hide hides WITH SYSTEM VERSIONING
	   for SHOW CREATE.

	   Note: basic.test, stopword.test and versioning.test do not
	   require debug for 'vers' combination. This is controlled by
	   $modify_create_table in maybe_versioning.inc and these
	   tests run WITH SYSTEM VERSIONING explicitly which allows to
	   test 'vers' combination on non-debug builds.

'vers_trx' like 'vers' sets sysvers_force_trx and sysvers_hide. That
	   tests FTS with trx_id-based System Versioning.

'orig' 	   works like before: no System Versioning is added, no debug is
	   required.

Upgrade/downgrade test for System Versioning is done by
innodb_fts.versioning. It has 2 combinations:

'prepare' makes binaries in std_data (requires old server and OLD_BINDIR).
	  It tests upgrade/downgrade against old server as well.

'upgrade' tests upgrade against binaries in std_data.

Cleanups:

Removed innodb-fts-stopword.test as it duplicates stopword.test
2022-12-27 00:02:02 +03:00

168 lines
5.7 KiB
Text

--source include/have_innodb.inc
--source include/maybe_versioning.inc
--disable_warnings
DROP TABLE IF EXISTS t1,t2,t3;
--enable_warnings
CREATE TABLE t1 (
a INT AUTO_INCREMENT PRIMARY KEY,
message CHAR(20),
FULLTEXT(message)
) ENGINE = InnoDB comment = 'original testcase by sroussey@network54.com';
INSERT INTO t1 (message) VALUES ("Testing"),("table"),("testbug"),
("steve"),("is"),("cool"),("steve is cool");
-- disable_result_log
ANALYZE TABLE t1;
-- enable_result_log
# basic MATCH
SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE MATCH (message) AGAINST ('steve');
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve');
SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE);
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE);
# MATCH + ORDER BY (with ft-ranges)
SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE MATCH (message) AGAINST ('steve') ORDER BY a;
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY a;
# MATCH + ORDER BY (with normal ranges) + UNIQUE
SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve') ORDER BY a DESC;
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY a DESC;
# MATCH + ORDER BY + UNIQUE (const_table)
SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve') ORDER BY 1;
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY 1;
# ORDER BY MATCH
# INNODB_FTS: INVESITGATE
SELECT if(a in (4,7),2,1), FORMAT(MATCH (message) AGAINST ('steve'),6) as rel FROM t1 ORDER BY rel;
SELECT if(a in (4,7),2,1), MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) as rel FROM t1 ORDER BY rel;
#
# BUG#6635 - test_if_skip_sort_order() thought it can skip filesort
# for fulltext searches too
#
alter table t1 add key m (message);
-- disable_result_log
ANALYZE TABLE t1;
-- enable_result_log
explain SELECT message FROM t1 WHERE MATCH (message) AGAINST ('steve') ORDER BY message;
SELECT message FROM t1 WHERE MATCH (message) AGAINST ('steve') ORDER BY message desc;
drop table t1;
#
# reused boolean scan bug
#
CREATE TABLE t1 (
a INT AUTO_INCREMENT PRIMARY KEY,
message CHAR(20),
FULLTEXT(message)
) ENGINE = InnoDB;
INSERT INTO t1 (message) VALUES ("testbug"),("testbug foobar");
-- disable_result_log
ANALYZE TABLE t1;
-- enable_result_log
SELECT a, MATCH (message) AGAINST ('t* f*' IN BOOLEAN MODE) as rel FROM t1;
SELECT a, MATCH (message) AGAINST ('t* f*' IN BOOLEAN MODE) as rel FROM t1 ORDER BY rel,a;
drop table t1;
# BUG#11869
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
thread int(11) NOT NULL default '0',
beitrag longtext NOT NULL,
PRIMARY KEY (id),
KEY thread (thread),
FULLTEXT KEY beitrag (beitrag)
) ENGINE =InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=7923 ;
CREATE TABLE t2 (
id int(11) NOT NULL auto_increment,
text varchar(100) NOT NULL default '',
PRIMARY KEY (id),
KEY text (text)
) ENGINE = InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=63 ;
CREATE TABLE t3 (
id int(11) NOT NULL auto_increment,
forum int(11) NOT NULL default '0',
betreff varchar(70) NOT NULL default '',
PRIMARY KEY (id),
KEY forum (forum),
FULLTEXT KEY betreff (betreff)
) ENGINE = InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=996 ;
--error ER_TABLENAME_NOT_ALLOWED_HERE
select a.text, b.id, b.betreff
from
t2 a inner join t3 b on a.id = b.forum inner join
t1 c on b.id = c.thread
where
match(b.betreff) against ('+abc' in boolean mode)
group by a.text, b.id, b.betreff
union
select a.text, b.id, b.betreff
from
t2 a inner join t3 b on a.id = b.forum inner join
t1 c on b.id = c.thread
where
match(c.beitrag) against ('+abc' in boolean mode)
group by
a.text, b.id, b.betreff
order by
match(b.betreff) against ('+abc' in boolean mode) desc;
--error ER_TABLENAME_NOT_ALLOWED_HERE
select a.text, b.id, b.betreff
from
t2 a inner join t3 b on a.id = b.forum inner join
t1 c on b.id = c.thread
where
match(b.betreff) against ('+abc' in boolean mode)
union
select a.text, b.id, b.betreff
from
t2 a inner join t3 b on a.id = b.forum inner join
t1 c on b.id = c.thread
where
match(c.beitrag) against ('+abc' in boolean mode)
order by
match(b.betreff) against ('+abc' in boolean mode) desc;
select a.text, b.id, b.betreff
from
t2 a inner join t3 b on a.id = b.forum inner join
t1 c on b.id = c.thread
where
match(b.betreff) against ('+abc' in boolean mode)
union
select a.text, b.id, b.betreff
from
t2 a inner join t3 b on a.id = b.forum inner join
t1 c on b.id = c.thread
where
match(c.beitrag) against ('+abc' in boolean mode)
order by
match(betreff) against ('+abc' in boolean mode) desc;
# BUG#11869 part2: used table type doesn't support FULLTEXT indexes error
(select b.id, b.betreff from t3 b) union
(select b.id, b.betreff from t3 b)
order by match(betreff) against ('+abc' in boolean mode) desc;
--error ER_FT_MATCHING_KEY_NOT_FOUND
(select b.id, b.betreff from t3 b) union
(select b.id, b.betreff from t3 b)
order by match(betreff) against ('+abc') desc;
select distinct b.id, b.betreff from t3 b
order by match(betreff) against ('+abc' in boolean mode) desc;
select b.id, b.betreff from t3 b group by b.id+1
order by match(betreff) against ('+abc' in boolean mode) desc;
drop table t1,t2,t3;
# End of 4.1 tests