summaryrefslogtreecommitdiff
path: root/storage/innobase/fts/fts0ast.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/fts/fts0ast.cc')
-rw-r--r--storage/innobase/fts/fts0ast.cc98
1 files changed, 88 insertions, 10 deletions
diff --git a/storage/innobase/fts/fts0ast.cc b/storage/innobase/fts/fts0ast.cc
index c01c43a021f..972f5acf461 100644
--- a/storage/innobase/fts/fts0ast.cc
+++ b/storage/innobase/fts/fts0ast.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -98,9 +98,21 @@ fts_ast_create_node_text(
void* arg, /*!< in: ast state instance */
const char* ptr) /*!< in: ast text string */
{
+ ulint len = strlen(ptr);
+ fts_ast_node_t* node = NULL;
+
+ ut_ad(len >= 2);
+
+ if (len == 2) {
+ ut_ad(ptr[0] == '\"');
+ ut_ad(ptr[1] == '\"');
+ return(NULL);
+ }
+
+ node = fts_ast_node_create();
+
/*!< We ignore the actual quotes "" */
- ulint len = strlen(ptr) - 2;
- fts_ast_node_t* node = fts_ast_node_create();
+ len -= 2;
node->type = FTS_AST_TEXT;
node->text.ptr = static_cast<byte*>(ut_malloc(len + 1));
@@ -381,34 +393,100 @@ fts_ast_node_print(
}
/******************************************************************//**
-Traverse the AST - in-order traversal.
+Traverse the AST - in-order traversal, except for the FTS_IGNORE
+nodes, which will be ignored in the first pass of each level, and
+visited in a second pass after all other nodes in the same level are visited.
@return DB_SUCCESS if all went well */
UNIV_INTERN
-ulint
+dberr_t
fts_ast_visit(
/*==========*/
fts_ast_oper_t oper, /*!< in: current operator */
fts_ast_node_t* node, /*!< in: current root node */
fts_ast_callback visitor, /*!< in: callback function */
- void* arg) /*!< in: arg for callback */
+ void* arg, /*!< in: arg for callback */
+ bool* has_ignore) /*!< out: true, if the operator
+ was ignored during processing,
+ currently we only ignore
+ FTS_IGNORE operator */
{
- ulint error = DB_SUCCESS;
+ dberr_t error = DB_SUCCESS;
+ fts_ast_node_t* oper_node = NULL;
+ fts_ast_node_t* start_node;
+ bool revisit = false;
+ bool will_be_ignored = false;
+
+ start_node = node->list.head;
ut_a(node->type == FTS_AST_LIST
|| node->type == FTS_AST_SUBEXP_LIST);
+ /* In the first pass of the tree, at the leaf level of the
+ tree, FTS_IGNORE operation will be ignored. It will be
+ repeated at the level above the leaf level */
for (node = node->list.head;
- node && error == DB_SUCCESS;
+ node && (error == DB_SUCCESS);
node = node->next) {
if (node->type == FTS_AST_LIST) {
- error = fts_ast_visit(oper, node, visitor, arg);
+ error = fts_ast_visit(oper, node, visitor,
+ arg, &will_be_ignored);
+
+ /* If will_be_ignored is set to true, then
+ we encountered and ignored a FTS_IGNORE operator,
+ and a second pass is needed to process FTS_IGNORE
+ operator */
+ if (will_be_ignored) {
+ revisit = true;
+ }
} else if (node->type == FTS_AST_SUBEXP_LIST) {
error = fts_ast_visit_sub_exp(node, visitor, arg);
} else if (node->type == FTS_AST_OPER) {
oper = node->oper;
+ oper_node = node;
} else {
- visitor(oper, node, arg);
+ if (node->visited) {
+ continue;
+ }
+
+ ut_a(oper == FTS_NONE || !oper_node
+ || oper_node->oper == oper);
+
+ if (oper == FTS_IGNORE) {
+ *has_ignore = true;
+ /* Change the operator to FTS_IGNORE_SKIP,
+ so that it is processed in the second pass */
+ oper_node->oper = FTS_IGNORE_SKIP;
+ continue;
+ }
+
+ if (oper == FTS_IGNORE_SKIP) {
+ /* This must be the second pass, now we process
+ the FTS_IGNORE operator */
+ visitor(FTS_IGNORE, node, arg);
+ } else {
+ visitor(oper, node, arg);
+ }
+
+ node->visited = true;
+ }
+ }
+
+ /* Second pass to process the skipped FTS_IGNORE operation.
+ It is only performed at the level above leaf level */
+ if (revisit) {
+ for (node = start_node;
+ node && error == DB_SUCCESS;
+ node = node->next) {
+
+ if (node->type == FTS_AST_LIST) {
+ /* In this pass, it will process all those
+ operators ignored in the first pass, and those
+ whose operators are set to FTS_IGNORE_SKIP */
+ error = fts_ast_visit(
+ oper, node, visitor, arg,
+ &will_be_ignored);
+ }
}
}