1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-27 18:02:13 +03:00

new version of help

This commit is contained in:
unknown
2003-05-29 17:47:31 -04:00
parent f440077bd0
commit 69e084af1e
13 changed files with 1672 additions and 950 deletions

View File

@ -26,74 +26,155 @@ struct st_find_field
static struct st_find_field init_used_fields[]=
{
{ "help_topic", "name", 0},
{ "help_topic","description", 0},
{ "help_topic","example", 0},
{ "help_topic", "help_topic_id", 0},
{ "help_category","name", 0},
{ "help_category","help_category_id", 0},
{ "help_relation","help_topic_id", 0},
{ "help_relation","help_category_id", 0}
{ "help_topic", "help_topic_id", 0},
{ "help_topic", "name", 0},
{ "help_topic", "help_category_id", 0},
{ "help_topic", "description", 0},
{ "help_topic", "example", 0},
{ "help_category", "help_category_id", 0},
{ "help_category", "parent_category_id", 0},
{ "help_category", "name", 0},
{ "help_keyword", "help_keyword_id", 0},
{ "help_keyword", "name", 0},
{ "help_relation", "help_topic_id", 0},
{ "help_relation", "help_keyword_id", 0}
};
enum enum_used_fields
{
help_topic_name=0, help_topic_description, help_topic_example,
help_topic_help_topic_id,
help_category_name, help_category_help_category_id,
help_relation_help_topic_id, help_relation_help_category_id
help_topic_help_topic_id= 0,
help_topic_name,
help_topic_help_category_id,
help_topic_description,
help_topic_example,
help_category_help_category_id,
help_category_parent_category_id,
help_category_name,
help_keyword_help_keyword_id,
help_keyword_name,
help_relation_help_topic_id,
help_relation_help_keyword_id
};
/*
Fill local used field structure with pointer to fields */
Fill st_find_field structure with pointers to fields
SYNOPSIS
init_fields()
thd Thread handler
tables list of all tables for fields
find_fields array of structures
count size of previous array
RETURN VALUES
0 all ok
1 one of the fileds didn't finded
*/
static bool init_fields(THD *thd, TABLE_LIST *tables,
struct st_find_field *find_field,
uint count)
struct st_find_field *find_fields, uint count)
{
for (; count-- ; find_field++)
DBUG_ENTER("init_fields");
for (; count-- ; find_fields++)
{
TABLE_LIST *not_used;
/* We have to use 'new' here as field will be re_linked on free */
Item_field *field= new Item_field("mysql", find_field->table_name,
find_field->field_name);
if (!(find_field->field= find_field_in_tables(thd, field, tables,
&not_used,
TRUE)))
return 1;
Item_field *field= new Item_field("mysql", find_fields->table_name,
find_fields->field_name);
if (!(find_fields->field= find_field_in_tables(thd, field, tables,
&not_used, TRUE)))
DBUG_RETURN(1);
}
return 0;
DBUG_RETURN(0);
}
/*
#define help_charset &my_charset_latin1
Returns variants of found topic for help (if it is just single topic,
returns description and example, or else returns only names..)
SYNOPSIS
memorize_variant_topic()
thd Thread handler
topics Table of topics
count number of alredy found topics
find_fields Filled array of information for work with fields
RETURN VALUES
names array of names of found topics (out)
name name of found topic (out)
description description of found topic (out)
example example for found topic (out)
NOTE
Field 'names' is set only if more than one topic is found.
Fields 'name', 'description', 'example' are set only if
found exactly one topic.
*/
void memorize_variant_topic(THD *thd, TABLE *topics, int count,
struct st_find_field *find_fields,
List<String> *names,
String *name, String *description, String *example)
{
DBUG_ENTER("memorize_variant_topic");
MEM_ROOT *mem_root= &thd->mem_root;
if (count==0)
{
get_field(mem_root,find_fields[help_topic_name].field, name);
get_field(mem_root,find_fields[help_topic_description].field, description);
get_field(mem_root,find_fields[help_topic_example].field, example);
}
else
{
if (count==1)
names->push_back(name);
String *new_name= new String;
get_field(mem_root,find_fields[help_topic_name].field,new_name);
names->push_back(new_name);
}
DBUG_VOID_RETURN;
}
/*
Look for topics by mask
SYNOPSIS
search_topics()
thd Thread handler
topics Table of topic
select Function to test for if matching help topic.
Normally 'help_topic.name like 'bit%'
pfname Pointer to Field structure for field "name"
names List of founded topic's names (out)
name Name of founded topic (out),
Only set if founded exactly one topic)
description Description of founded topic (out)
Only set if founded exactly one topic.
example Example for founded topic (out)
Only if founded exactly one topic.
thd Thread handler
topics Table of topics
find_fields Filled array of info for fields
select Function to test for matching help topic.
Normally 'help_topic.name like 'bit%'
RETURN VALUES
# number of topics founded
# number of topics found
names array of names of found topics (out)
name name of found topic (out)
description description of found topic (out)
example example for found topic (out)
NOTE
Field 'names' is set only if more than one topic was found.
Fields 'name', 'description', 'example' are set only if
exactly one topic was found.
*/
int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_field,
SQL_SELECT *select, List<char> *names,
char **name, char **description, char **example)
int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_fields,
SQL_SELECT *select, List<String> *names,
String *name, String *description, String *example)
{
DBUG_ENTER("search_functions");
DBUG_ENTER("search_topics");
int count= 0;
READ_RECORD read_record_info;
@ -102,139 +183,93 @@ int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_field,
{
if (!select->cond->val_int()) // Dosn't match like
continue;
char *lname= get_field(&thd->mem_root, find_field[help_topic_name].field);
memorize_variant_topic(thd,topics,count,find_fields,
names,name,description,example);
count++;
if (count > 2)
{
names->push_back(lname);
}
else if (count == 1)
{
*description= get_field(&thd->mem_root,
find_field[help_topic_description].field);
*example= get_field(&thd->mem_root,
find_field[help_topic_example].field);
*name= lname;
}
else
{
names->push_back(*name);
names->push_back(lname);
*name= 0;
*description= 0;
*example= 0;
}
}
end_read_record(&read_record_info);
DBUG_RETURN(count);
}
/*
Look for categories by mask
Look for keyword by mask
SYNOPSIS
search_categories()
thd THD for init_read_record
categories Table of categories
select Function to test for if matching help topic.
Normally 'help_topic.name like 'bit%'
names List of founded topic's names (out)
res_id Primary index of founded category (only if
founded exactly one category)
search_keyword()
thd Thread handler
keywords Table of keywords
find_fields Filled array of info for fields
select Function to test for matching keyword.
Normally 'help_keyword.name like 'bit%'
key_id help_keyword_if of found topics (out)
RETURN VALUES
# Number of categories founded
0 didn't find any topics matching the mask
1 found exactly one topic matching the mask
2 found more then one topic matching the mask
*/
int search_categories(THD *thd, TABLE *categories,
struct st_find_field *find_fields,
SQL_SELECT *select, List<char> *names, int16 *res_id)
int search_keyword(THD *thd, TABLE *keywords, struct st_find_field *find_fields,
SQL_SELECT *select, int *key_id)
{
Field *pfname= find_fields[help_category_name].field;
DBUG_ENTER("search_categories");
DBUG_ENTER("search_keyword");
int count= 0;
READ_RECORD read_record_info;
init_read_record(&read_record_info, thd, categories, select,1,0);
while (!read_record_info.read_record(&read_record_info))
READ_RECORD read_record_info;
init_read_record(&read_record_info, thd, keywords, select,1,0);
while (!read_record_info.read_record(&read_record_info) && count<2)
{
if (select && !select->cond->val_int())
if (!select->cond->val_int()) // Dosn't match like
continue;
char *lname= get_field(&thd->mem_root,pfname);
if (++count == 1 && res_id)
{
Field *pcat_id= find_fields[help_category_help_category_id].field;
*res_id= (int16) pcat_id->val_int();
}
names->push_back(lname);
*key_id= find_fields[help_keyword_help_keyword_id].field->val_int();
count++;
}
end_read_record(&read_record_info);
DBUG_RETURN(count);
}
/*
Send to client rows in format:
column1 : <name>
column2 : <is_it_category>
Look for all topics with keyword
SYNOPSIS
send_variant_2_list()
protocol Protocol for sending
names List of names
cat Value of the column <is_it_category>
get_topics_for_keyword()
thd Thread handler
topics Table of topics
relations Table of m:m relation "topic/keyword"
find_fields Filled array of info for fields
key_id Primary index to use to find for keyword
RETURN VALUES
-1 Writing fail
0 Data was successefully send
# number of topics found
names array of name of found topics (out)
name name of found topic (out)
description description of found topic (out)
example example for found topic (out)
NOTE
Field 'names' is set only if more than one topic was found.
Fields 'name', 'description', 'example' are set only if
exactly one topic was found.
*/
int send_variant_2_list(Protocol *protocol, List<char> *names,
const char *cat)
int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
struct st_find_field *find_fields, int16 key_id,
List<String> *names,
String *name, String *description, String *example)
{
DBUG_ENTER("send_names");
List_iterator<char> it(*names);
const char *cur_name;
while ((cur_name= it++))
{
protocol->prepare_for_resend();
protocol->store(cur_name, system_charset_info);
protocol->store(cat, system_charset_info);
if (protocol->write())
DBUG_RETURN(-1);
}
DBUG_RETURN(0);
}
/*
Look for all topics of category
SYNOPSIS
get_all_topics_for_category()
thd Thread handler
topics Table of topics
relations Table of m:m relation "topic/category"
cat_id Primary index looked for category
res List of founded topic's names (out)
RETURN VALUES
-1 corrupt database
0 succesefull
*/
int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations,
struct st_find_field *find_fields,
int16 cat_id, List<char> *res)
{
char buff[8]; // Max int length
DBUG_ENTER("get_all_topics_for_category");
char buff[8]; // Max int length
int count= 0;
int iindex_topic, iindex_relations;
Field *rtopic_id, *rcat_id;
Field *rtopic_id, *rkey_id;
DBUG_ENTER("get_topics_for_keyword");
if ((iindex_topic= find_type((char*) "PRIMARY",
&topics->keynames, 1+2)-1)<0 ||
@ -245,37 +280,156 @@ int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations,
DBUG_RETURN(-1);
}
rtopic_id= find_fields[help_relation_help_topic_id].field;
rcat_id= find_fields[help_relation_help_category_id].field;
rkey_id= find_fields[help_relation_help_keyword_id].field;
topics->file->index_init(iindex_topic);
relations->file->index_init(iindex_relations);
rcat_id->store((longlong) cat_id);
rcat_id->get_key_image(buff, rcat_id->pack_length(), help_charset,
rkey_id->store((longlong) key_id);
rkey_id->get_key_image(buff, rkey_id->pack_length(), rkey_id->charset(),
Field::itRAW);
int key_res= relations->file->index_read(relations->record[0],
(byte *)buff, rcat_id->pack_length(),
(byte *)buff, rkey_id->pack_length(),
HA_READ_KEY_EXACT);
for ( ; !key_res && cat_id == (int16) rcat_id->val_int() ;
for ( ;
!key_res && key_id == (int16) rkey_id->val_int() ;
key_res= relations->file->index_next(relations->record[0]))
{
char topic_id_buff[8];
longlong topic_id= rtopic_id->val_int();
Field *field= find_fields[help_topic_help_topic_id].field;
field->store((longlong) topic_id);
field->get_key_image(topic_id_buff, field->pack_length(), help_charset,
field->get_key_image(topic_id_buff, field->pack_length(), field->charset(),
Field::itRAW);
if (!topics->file->index_read(topics->record[0], (byte *)topic_id_buff,
field->pack_length(),
HA_READ_KEY_EXACT))
res->push_back(get_field(&thd->mem_root,
find_fields[help_topic_name].field));
field->pack_length(), HA_READ_KEY_EXACT))
{
memorize_variant_topic(thd,topics,count,find_fields,
names,name,description,example);
count++;
}
}
DBUG_RETURN(0);
DBUG_RETURN(count);
}
/*
Look for topics with keyword by mask
SYNOPSIS
search_topics_by_keyword()
thd Thread handler
keywords Table of keywords
topics Table of topics
relations Table of m:m relation "topic/keyword"
find_fields Filled array of info for fields
select Function to test for if matching help keyword.
Normally 'help_keyword.name like 'bit%'
RETURN VALUES
# number of topics found
names array of name of found topics (out)
name name of found topic (out)
description description of found topic (out)
example example for found topic (out)
NOTE
Field 'names' is set only if more than one topic was found.
Fields 'name', 'description', 'example' are set only if
exactly one topic was found.
*/
int search_topics_by_keyword(THD *thd,
TABLE *keywords, TABLE *topics, TABLE *relations,
struct st_find_field *find_fields,
SQL_SELECT *select, List<String> *names,
String *name, String *description, String *example)
{
int key_id;
return search_keyword(thd,keywords,find_fields,select,&key_id)!=1
? 0 : get_topics_for_keyword(thd,topics,relations,find_fields,key_id,
names,name,description,example);
}
/*
Look for categories by mask
SYNOPSIS
search_categories()
thd THD for init_read_record
categories Table of categories
find_fields Filled array of info for fields
select Function to test for if matching help topic.
Normally 'help_vategory.name like 'bit%'
names List of found categories names (out)
res_id Primary index of found category (only if
found exactly one category)
RETURN VALUES
# Number of categories found
*/
int search_categories(THD *thd, TABLE *categories,
struct st_find_field *find_fields,
SQL_SELECT *select, List<String> *names, int16 *res_id)
{
Field *pfname= find_fields[help_category_name].field;
Field *pcat_id= find_fields[help_category_help_category_id].field;
int count= 0;
READ_RECORD read_record_info;
DBUG_ENTER("search_categories");
init_read_record(&read_record_info, thd, categories, select,1,0);
while (!read_record_info.read_record(&read_record_info))
{
if (select && !select->cond->val_int())
continue;
String *lname= new String;
get_field(&thd->mem_root,pfname,lname);
if (++count == 1 && res_id)
*res_id= (int16) pcat_id->val_int();
names->push_back(lname);
}
end_read_record(&read_record_info);
DBUG_RETURN(count);
}
/*
Look for all topics or subcategories of category
SYNOPSIS
get_all_items_for_category()
thd Thread handler
items Table of items
pfname Field "name" in items
select "where" part of query..
res list of finded names
*/
void get_all_items_for_category(THD *thd, TABLE *items, Field *pfname,
SQL_SELECT *select, List<String> *res)
{
DBUG_ENTER("get_all_items_for_category");
READ_RECORD read_record_info;
init_read_record(&read_record_info, thd, items, select,1,0);
while (!read_record_info.read_record(&read_record_info))
{
if (!select->cond->val_int())
continue;
String *name= new String();
get_field(&thd->mem_root,pfname,name);
res->push_back(name);
}
end_read_record(&read_record_info);
DBUG_VOID_RETURN;
}
/*
Send to client answer for help request
@ -284,17 +438,16 @@ int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations,
send_answer_1()
protocol - protocol for sending
s1 - value of column "Name"
s2 - value of column "Category"
s3 - value of column "Description"
s4 - value of column "Example"
s2 - value of column "Description"
s3 - value of column "Example"
IMPLEMENTATION
Format used:
+----------+---------+------------+------------+
|Name: |Category |Description |Example |
+----------+---------+------------+------------+
|String(64)|String(1)|String(1000)|String(1000)|
+----------+---------+------------+------------+
+----------+------------+------------+
|name |description |example |
+----------+------------+------------+
|String(64)|String(1000)|String(1000)|
+----------+------------+------------+
with exactly one row!
RETURN VALUES
@ -303,24 +456,21 @@ int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations,
0 Successeful send
*/
int send_answer_1(Protocol *protocol, const char *s1, const char *s2,
const char *s3, const char *s4)
int send_answer_1(Protocol *protocol, String *s1, String *s2, String *s3)
{
DBUG_ENTER("send_answer_1");
List<Item> field_list;
field_list.push_back(new Item_empty_string("Name",64));
field_list.push_back(new Item_empty_string("Category",1));
field_list.push_back(new Item_empty_string("Description",1000));
field_list.push_back(new Item_empty_string("Example",1000));
field_list.push_back(new Item_empty_string("name",64));
field_list.push_back(new Item_empty_string("description",1000));
field_list.push_back(new Item_empty_string("example",1000));
if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
protocol->prepare_for_resend();
protocol->store(s1, system_charset_info);
protocol->store(s2, system_charset_info);
protocol->store(s3, system_charset_info);
protocol->store(s4, system_charset_info);
protocol->store(s1);
protocol->store(s2);
protocol->store(s3);
if (protocol->write())
DBUG_RETURN(-1);
DBUG_RETURN(0);
@ -332,28 +482,151 @@ int send_answer_1(Protocol *protocol, const char *s1, const char *s2,
SYNOPSIS
send_header_2()
protocol - protocol for sending
protocol - protocol for sending
is_it_category - need column 'source_category_name'
IMPLEMENTATION
+----------+---------+
|Name: |Category |
+----------+---------+
|String(64)|String(1)|
+----------+---------+
+- -+
|+-------------------- | +----------+--------------+
||source_category_name | |name |is_it_category|
|+-------------------- | +----------+--------------+
||String(64) | |String(64)|String(1) |
|+-------------------- | +----------+--------------+
+- -+
RETURN VALUES
result of protocol->send_fields
*/
int send_header_2(Protocol *protocol)
int send_header_2(Protocol *protocol, bool for_category)
{
DBUG_ENTER("send_header2");
DBUG_ENTER("send_header_2");
List<Item> field_list;
field_list.push_back(new Item_empty_string("Name",64));
field_list.push_back(new Item_empty_string("Category",1));
if (for_category)
field_list.push_back(new Item_empty_string("source_category_name",64));
field_list.push_back(new Item_empty_string("name",64));
field_list.push_back(new Item_empty_string("is_it_category",1));
DBUG_RETURN(protocol->send_fields(&field_list,1));
}
/*
strcmp for using in qsort
SYNOPSIS
strptrcmp()
ptr1 (const void*)&str1
ptr2 (const void*)&str2
RETURN VALUES
same as strcmp
*/
int string_ptr_cmp(const void* ptr1, const void* ptr2)
{
String *str1= *(String**)ptr1;
String *str2= *(String**)ptr2;
return strcmp(str1->c_ptr(),str2->c_ptr());
}
/*
Send to client rows in format:
column1 : <name>
column2 : <is_it_category>
SYNOPSIS
send_variant_2_list()
protocol Protocol for sending
names List of names
cat Value of the column <is_it_category>
source_name name of category for all items..
RETURN VALUES
-1 Writing fail
0 Data was successefully send
*/
int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol,
List<String> *names,
const char *cat, String *source_name)
{
DBUG_ENTER("send_variant_2_list");
String **pointers= (String**)alloc_root(mem_root,
sizeof(String*)*names->elements);
String **pos= pointers;
List_iterator<String> it(*names);
String *cur_name;
while (*pos++= it++);
qsort(pointers,names->elements,sizeof(String*),string_ptr_cmp);
String **end= pointers + names->elements;
for (String **pos= pointers; pos!=end; pos++)
{
protocol->prepare_for_resend();
if (source_name)
protocol->store(source_name);
protocol->store(*pos);
protocol->store(cat,1,&my_charset_latin1);
if (protocol->write())
DBUG_RETURN(-1);
}
DBUG_RETURN(0);
}
/*
Prepare simple SQL_SELECT table.* WHERE <Item>
SYNOPSIS
prepare_simple_select()
thd Thread handler
cond WHERE part of select
tables list of tables, used in WHERE
table goal table
error code of error (out)
RETURN VALUES
# created SQL_SELECT
*/
SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, TABLE_LIST *tables,
TABLE *table, int *error)
{
cond->fix_fields(thd, tables, &cond); // can never fail
SQL_SELECT *res= make_select(table,0,0,cond,error);
return (*error || (res && res->check_quick(0, HA_POS_ERROR))) ? 0 : res;
}
/*
Prepare simple SQL_SELECT table.* WHERE table.name LIKE mask
SYNOPSIS
prepare_select_for_name()
thd Thread handler
mask mask for compare with name
mlen length of mask
tables list of tables, used in WHERE
table goal table
pfname field "name" in table
error code of error (out)
RETURN VALUES
# created SQL_SELECT
*/
SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen,
TABLE_LIST *tables, TABLE *table,
Field *pfname, int *error)
{
Item *cond= new Item_func_like(new Item_field(pfname),
new Item_string(mask,mlen,pfname->charset()),
(char*) "\\");
return prepare_simple_select(thd,cond,tables,table,error);
}
/*
Server-side function 'help'
@ -371,12 +644,13 @@ int send_header_2(Protocol *protocol)
int mysqld_help(THD *thd, const char *mask)
{
Protocol *protocol= thd->protocol;
SQL_SELECT *select= 0, *select_cat= 0;
Item *cond_topic, *cond_cat;
SQL_SELECT *select_topics_by_name= 0, *select_keyword_by_name= 0,
*select_cat_by_name= 0, *select_topics_by_cat= 0, *select_cat_by_cat= 0,
*select_root_cats= 0;
st_find_field used_fields[array_elements(init_used_fields)];
DBUG_ENTER("mysqld_help");
TABLE_LIST tables[3];
TABLE_LIST tables[4];
bzero((gptr)tables,sizeof(tables));
tables[0].alias= tables[0].real_name= (char*) "help_topic";
tables[0].lock_type= TL_READ;
@ -389,11 +663,17 @@ int mysqld_help(THD *thd, const char *mask)
tables[2].alias= tables[2].real_name= (char*) "help_relation";
tables[2].lock_type= TL_READ;
tables[2].db= (char*) "mysql";
tables[2].next= 0;
tables[2].next= &tables[3];
tables[3].alias= tables[3].real_name= (char*) "help_keyword";
tables[3].lock_type= TL_READ;
tables[3].db= (char*) "mysql";
tables[3].next= 0;
List<char> function_list, categories_list;
char *name, *description, *example;
List<String> topics_list, categories_list, subcategories_list;
String name, description, example;
int res, count_topics, count_categories, error;
uint mlen= strlen(mask);
MEM_ROOT *mem_root= &thd->mem_root;
if (open_and_lock_tables(thd, tables))
{
@ -409,111 +689,101 @@ int mysqld_help(THD *thd, const char *mask)
goto end;
}
/* TODO: Find out why these are needed (should not be) */
tables[0].table->file->init_table_handle_for_HANDLER();
tables[1].table->file->init_table_handle_for_HANDLER();
tables[2].table->file->init_table_handle_for_HANDLER();
for (int i=0; i<sizeof(tables)/sizeof(TABLE_LIST); i++)
tables[i].table->file->init_table_handle_for_HANDLER();
cond_topic= new Item_func_like(new Item_field(used_fields[help_topic_name].
field),
new Item_string(mask, strlen(mask),
help_charset),
(char*) "\\");
cond_topic->fix_fields(thd, tables, &cond_topic); // can never fail
select= make_select(tables[0].table,0,0,cond_topic,&error);
if (error || (select && select->check_quick(0, HA_POS_ERROR)))
{
res= -1;
goto end;
}
cond_cat= new Item_func_like(new Item_field(used_fields[help_category_name].
field),
new Item_string(mask, strlen(mask),
help_charset),
(char*) "\\");
cond_cat->fix_fields(thd, tables, &cond_topic); // can never fail
select_cat= make_select(tables[1].table,0,0,cond_cat,&error);
if (error || (select_cat && select_cat->check_quick(0, HA_POS_ERROR)))
if (!(select_topics_by_name=
prepare_select_for_name(thd,mask,mlen,tables,tables[0].table,
used_fields[help_topic_name].field,&error)) ||
!(select_cat_by_name=
prepare_select_for_name(thd,mask,mlen,tables,tables[1].table,
used_fields[help_category_name].field,&error))||
!(select_keyword_by_name=
prepare_select_for_name(thd,mask,mlen,tables,tables[3].table,
used_fields[help_keyword_name].field,&error)))
{
res= -1;
goto end;
}
res= 1;
count_topics= search_topics(thd,tables[0].table, used_fields, select,
&function_list, &name, &description, &example);
count_topics= search_topics(thd,tables[0].table,used_fields,
select_topics_by_name,&topics_list,
&name, &description, &example);
if (count_topics == 0)
count_topics= search_topics_by_keyword(thd,tables[3].table,tables[0].table,
tables[2].table,used_fields,
select_keyword_by_name,&topics_list,
&name,&description,&example);
if (count_topics == 0)
{
int16 category_id;
Item *cond=
new Item_func_like(new
Item_field(used_fields[help_category_name].field),
new Item_string(mask, strlen(mask),
help_charset),
(char*) "\\");
(void) cond->fix_fields(thd, tables, &cond); // can never fail
Field *cat_cat_id= used_fields[help_category_parent_category_id].field;
count_categories= search_categories(thd, tables[1].table, used_fields,
select_cat, &categories_list,
&category_id);
if (count_categories == 1)
select_cat_by_name,
&categories_list,&category_id);
if (!count_categories)
{
if (get_all_topics_for_category(thd,tables[0].table,
tables[2].table, used_fields,
category_id, &function_list))
if (send_header_2(protocol,false))
goto end;
}
else if (count_categories > 1)
{
if (send_header_2(protocol,false) ||
send_variant_2_list(mem_root,protocol,&categories_list,"Y",0))
goto end;
}
else
{
Field *topic_cat_id= used_fields[help_topic_help_category_id].field;
Item *cond_topic_by_cat= new Item_func_equal(new Item_field(topic_cat_id),
new Item_int(category_id));
Item *cond_cat_by_cat= new Item_func_equal(new Item_field(cat_cat_id),
new Item_int(category_id));
if (!(select_topics_by_cat= prepare_simple_select(thd,cond_topic_by_cat,
tables,tables[0].table,
&error)) ||
!(select_cat_by_cat= prepare_simple_select(thd,cond_cat_by_cat,tables,
tables[1].table,&error)))
{
res= -1;
goto end;
}
List_iterator<char> it(function_list);
char *cur_topic;
char buff[1024];
String example(buff, sizeof(buff), help_charset);
example.length(0);
while ((cur_topic= it++))
{
example.append(cur_topic);
example.append("\n",1);
}
if ((send_answer_1(protocol, categories_list.head(),
"Y","",example.ptr())))
goto end;
}
else
{
if (send_header_2(protocol))
goto end;
if (count_categories == 0)
search_categories(thd,tables[1].table, used_fields, (SQL_SELECT *) 0,
&categories_list, 0);
if (send_variant_2_list(protocol,&categories_list,"Y"))
get_all_items_for_category(thd,tables[0].table,
used_fields[help_topic_name].field,
select_topics_by_cat,&topics_list);
get_all_items_for_category(thd,tables[1].table,
used_fields[help_category_name].field,
select_cat_by_cat,&subcategories_list);
String *cat= categories_list.head();
if (send_header_2(protocol, true) ||
send_variant_2_list(mem_root,protocol,&topics_list, "N",cat) ||
send_variant_2_list(mem_root,protocol,&subcategories_list,"Y",cat))
goto end;
}
}
else if (count_topics == 1)
{
if (send_answer_1(protocol,name,"N",description, example))
if (send_answer_1(protocol,&name,&description,&example))
goto end;
}
else
{
/* First send header and functions */
if (send_header_2(protocol) ||
send_variant_2_list(protocol, &function_list, "N"))
if (send_header_2(protocol, false) ||
send_variant_2_list(mem_root,protocol, &topics_list, "N", 0))
goto end;
search_categories(thd, tables[1].table, used_fields, select_cat,
&categories_list, 0);
search_categories(thd, tables[1].table, used_fields,
select_cat_by_name,&categories_list, 0);
/* Then send categories */
if (send_variant_2_list(protocol, &categories_list, "Y"))
if (send_variant_2_list(mem_root,protocol, &categories_list, "Y", 0))
goto end;
}
res= 0;
send_eof(thd);
end:
delete select;
delete select_cat;
DBUG_RETURN(res);
}