diff options
author | unknown <monty@mashka.mysql.fi> | 2003-02-12 21:55:37 +0200 |
---|---|---|
committer | unknown <monty@mashka.mysql.fi> | 2003-02-12 21:55:37 +0200 |
commit | fcb61f5917ee69bba91bd6a926db2eab4ac3eeb5 (patch) | |
tree | 3ac37e452f15c8f05e9d1f338a6050281f838048 /sql/sql_help.cc | |
parent | 363fd89b92de2fc58e7910f7a27684308656ebda (diff) | |
download | mariadb-git-fcb61f5917ee69bba91bd6a926db2eab4ac3eeb5.tar.gz |
Fixed a lot of wrong memory references as reported by valgrind
Portability fixes
Added new client function: mysql_get_server_version()
New server help code (From Victor Vagin)
Fixed wrong usage of binary()
Disabled RTREE usage for now.
BitKeeper/etc/ignore:
added scripts/fill_help_tables.sql
client/mysql.cc:
Some fixes when using 'help'
cmd-line-utils/libedit/compat.h:
Portability fix
cmd-line-utils/libedit/fgetln.c:
Portability fix
include/mysql.h:
Added new client function: mysql_get_server_version()
libmysql/libmysql.c:
Added new client function: mysql_get_server_version()
libmysqld/libmysqld.c:
Fixed prototype
mysql-test/install_test_db.sh:
Added creation of help tables
mysql-test/r/connect.result:
Added help tables
mysql-test/r/myisam.result:
Test of RTREE index
mysql-test/r/type_ranges.result:
updated results
mysql-test/t/myisam.test:
Test of RTREE index
mysql-test/t/type_ranges.test:
Updated test
mysys/charset.c:
Indentation change
mysys/my_symlink.c:
Removed compiler warning
scripts/fill_help_tables.sh:
Update for new help tables
sql/field.cc:
Indentation changes
sql/filesort.cc:
Optimized character set usage
sql/item_cmpfunc.cc:
Fix wrong usage of binary()
sql/item_cmpfunc.h:
Fix wrong usage of binary()
sql/item_func.cc:
Fix wrong usage of binary()
sql/item_func.h:
Fix wrong usage of binary()
sql/item_strfunc.cc:
Fix wrong usage of binary()
sql/item_sum.cc:
Fix wrong usage of binary()
sql/item_sum.h:
Fix wrong usage of binary()
sql/key.cc:
Indentation change
sql/lex.h:
HELP -> HELP_SYM
sql/mysql_priv.h:
Make get_field() more general
sql/password.c:
Indentation change + variable initialisation moved
sql/sql_acl.cc:
Make get_field() more general
sql/sql_base.cc:
Added comments + assertion for double call to mysql_lock_tables
sql/sql_cache.cc:
Indentation changes
sql/sql_class.h:
Added need_strxnfrm to SORT_FIELD to be able to optimise character set handling in filesort
sql/sql_derived.cc:
Renamed variables
sql/sql_help.cc:
New help functions (from Victor Vagin)
sql/sql_lex.cc:
Removed variables that doesn't have to be initialized for each query
sql/sql_lex.h:
Removed not used variable (olap)
sql/sql_parse.cc:
Fixed (not fatal) access of unitialized memory
Indentation / code cleanup
sql/sql_prepare.cc:
Indentaion cleanup
sql/sql_table.cc:
Disabled RTREE until 5.0
sql/sql_udf.cc:
Make get_field() more general
sql/sql_yacc.yy:
Removed access to uninitialized memory
Always set offset_limit and select_limit when using LIMIT (removed warnings)
Allow usage of 'help week'
sql/table.cc:
Make get_field() more general
More comments
sql/table.h:
Fixded type of TABLE_LIST->derived
sql/time.cc:
Stricter date / datetime handling (to be able to handle timestamps with days and microseconds)
strings/ctype-bin.c:
Added cha
Diffstat (limited to 'sql/sql_help.cc')
-rw-r--r-- | sql/sql_help.cc | 647 |
1 files changed, 378 insertions, 269 deletions
diff --git a/sql/sql_help.cc b/sql/sql_help.cc index e4c44428242..24ea2e9734e 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -15,288 +15,294 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "mysql_priv.h" -#include "sql_select.h" // For select_describe -#include "sql_acl.h" -/*************************************************************************** -** Get help on string -***************************************************************************/ +struct st_find_field +{ + const char *table_name, *field_name; + Field *field; +}; -#define help_charset &my_charset_latin1 +/* Used fields */ + +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} +}; + +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 +}; -MI_INFO *open_help_file(THD *thd, const char *name) +/* + Fill local used field structure with pointer to fields */ + +static bool init_fields(THD *thd, TABLE_LIST *tables, + struct st_find_field *find_field, + uint count) { - char path[FN_REFLEN]; - (void) sprintf(path,"%s/mysql_help/%s",mysql_data_home,name); - MI_INFO *res= 0; - if (!(res= mi_open(path,O_RDONLY,HA_OPEN_WAIT_IF_LOCKED))) + for (; count-- ; find_field++) { - send_error(thd,ER_CORRUPT_HELP_DB); - return 0; + 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, + ¬_used, + TRUE))) + return 1; } - mi_extra(res,HA_EXTRA_WAIT_LOCK,0); - return res; + return 0; } -#define size_hf_func_id 4 /* func_id int unsigned, */ -#define size_hf_name 64 /* name varchar(64), */ -#define size_hf_url 128 /* url varchar(128), */ -#define size_hf_description sizeof(char*) /* description text, */ -#define size_hf_example sizeof(char*) /* example text, */ -#define size_hf_min_args 16 /* min_args tinyint, */ -#define size_hf_max_args 16 /* max_args tinyint, */ -#define size_hf_date_created 8 /* date_created datetime, */ -#define size_hf_last_modified 8 /* last_modified timestamp, */ - -#define offset_hf_func_id 1 -#define offset_hf_name (offset_hf_func_id+size_hf_func_id) -#define offset_hf_url (offset_hf_name+size_hf_name) -#define offset_hf_description (offset_hf_url+size_hf_url) -#define offset_hf_example (offset_hf_description+size_hf_description) -#define offset_hf_min_args (offset_hf_example+size_hf_example) -#define offset_hf_max_args (offset_hf_min_args+size_hf_min_args) -#define offset_hf_date_created (offset_hf_max_args+size_hf_max_args) -#define offset_hf_last_modified (offset_hf_date_created+size_hf_date_created) - -#define HELP_LEAF_SIZE (offset_hf_last_modified+size_hf_last_modified) - -class help_leaf{ -public: - char record[HELP_LEAF_SIZE]; - - inline const char *get_name() - { - return &record[offset_hf_name]; - } - inline const char *get_description() - { - return *((char**)&record[199/*offset_hf_description*/]); - } - - inline const char *get_example() - { - return *((char**)&record[209/*offset_hf_example*/]); - } - - void prepare_fields() - { - const char *name= get_name(); - const char *c= name + size_hf_name - 1; - while (*c==' ') c--; - int len= c-name+1; - ((char*)name)[len]= '\0'; - } -}; +#define help_charset &my_charset_latin1 -int search_functions(MI_INFO *file_leafs, const char *mask, - List<String> *names, - String **name, String **description, String **example) +/* + 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. + RETURN VALUES + # number of topics founded +*/ + +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) { DBUG_ENTER("search_functions"); int count= 0; - - if (mi_scan_init(file_leafs)) - DBUG_RETURN(-1); - - help_leaf leaf; - - while (!mi_scan(file_leafs,(byte*)&leaf)) + + READ_RECORD read_record_info; + init_read_record(&read_record_info, thd, topics, select,1,0); + while (!read_record_info.read_record(&read_record_info)) { - leaf.prepare_fields(); - - const char *lname= leaf.get_name(); - if (wild_case_compare(help_charset,lname,mask)) + if (!select->cond->val_int()) // Dosn't match like continue; - count++; - if (count>2) + char *lname= get_field(&thd->mem_root, find_field[help_topic_name].field); + count++; + if (count > 2) { - String *s= new String(lname,help_charset); - if (!s->copy()) - names->push_back(s); + names->push_back(lname); } - else if (count==1) + else if (count == 1) { - *description= new String(leaf.get_description(),help_charset); - *example= new String(leaf.get_example(),help_charset); - *name= new String(lname,help_charset); - (*description)->copy(); - (*example)->copy(); - (*name)->copy(); + *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); - delete *description; - delete *example; + names->push_back(lname); *name= 0; *description= 0; *example= 0; - - String *s= new String(lname,help_charset); - if (!s->copy()) - names->push_back(s); } } - + end_read_record(&read_record_info); DBUG_RETURN(count); } -#define size_hc_cat_id 2 /* cat_id smallint, */ -#define size_hc_name 64 /* name varchar(64), */ -#define size_hc_url 128 /* url varchar(128), */ -#define size_hc_date_created 8 /* date_created datetime, */ -#define size_hc_last_modified 8 /* last_modified timestamp, */ - -#define offset_hc_cat_id 0 -#define offset_hc_name (offset_hc_cat_id+size_hc_cat_id) -#define offset_hc_url (offset_hc_name+size_hc_name) -#define offset_hc_date_created (offset_hc_url+size_hc_url) -#define offset_hc_last_modified (offset_hc_date_created+size_hc_date_created) - -#define HELP_CATEGORY_SIZE (offset_hc_last_modified+size_hc_last_modified) - -class help_category{ -public: - char record[HELP_CATEGORY_SIZE]; - - inline int16 get_cat_id() - { - return sint2korr(&record[offset_hc_cat_id]); - } - - inline const char *get_name() - { - return &record[offset_hc_name]; - } - - void prepare_fields() - { - const char *name= get_name(); - const char *c= name + size_hc_name - 1; - while (*c==' ') c--; - int len= c-name+1; - ((char*)name)[len]= '\0'; - } -}; - -int search_categories(THD *thd, - const char *mask, List<String> *names, int16 *res_id) +/* + Look for categories 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) + + RETURN VALUES + # Number of categories founded +*/ + +int search_categories(THD *thd, TABLE *categories, + struct st_find_field *find_fields, + SQL_SELECT *select, List<char> *names, int16 *res_id) { + Field *pfname= find_fields[help_category_name].field; DBUG_ENTER("search_categories"); int count= 0; - - MI_INFO *file_categories= 0; - if (!(file_categories= open_help_file(thd,"function_category_name"))) - DBUG_RETURN(-1); - - if (mi_scan_init(file_categories)) + + 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)) { - mi_close(file_categories); - DBUG_RETURN(-1); + if (select && !select->cond->val_int()) + 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); } + end_read_record(&read_record_info); + + DBUG_RETURN(count); +} - help_category category; +/* + Send to client rows in format: + column1 : <name> + column2 : <is_it_category> - while (!mi_scan(file_categories,(byte*)&category)) - { - category.prepare_fields(); + SYNOPSIS + send_variant_2_list() + protocol Protocol for sending + names List of names + cat Value of the column <is_it_category> - const char *lname= category.get_name(); - if (mask && wild_case_compare(help_charset,lname,mask)) - continue; - count++; + RETURN VALUES + -1 Writing fail + 0 Data was successefully send +*/ - if (count==1 && res_id) - *res_id= category.get_cat_id(); - - String *s= new String(lname,help_charset); - if (!s->copy()) - names->push_back(s); - } - - mi_close(file_categories); - DBUG_RETURN(count); -} - -int send_variant_2_list(Protocol *protocol, List<String> *names, - my_bool is_category) +int send_variant_2_list(Protocol *protocol, List<char> *names, + const char *cat) { DBUG_ENTER("send_names"); - - List_iterator<String> it(*names); - String *cur_name; - while ((cur_name = it++)) + + List_iterator<char> it(*names); + const char *cur_name; + while ((cur_name= it++)) { protocol->prepare_for_resend(); - protocol->store(cur_name->ptr()); - protocol->store(is_category ? "Y" : "N"); + protocol->store(cur_name); + protocol->store(cat); if (protocol->write()) DBUG_RETURN(-1); } DBUG_RETURN(0); } -#define size_hcn_cat_id 2 /* cat_id smallint, */ -#define size_hcn_func_id 4 /* func_id int, */ - -#define offset_hcn_cat_id 1 -#define offset_hcn_func_id (offset_hcn_cat_id+size_hcn_cat_id) - -#define HELP_CATEGORY_NAME_SIZE (offset_hcn_func_id + size_hcn_func_id) -class help_category_leaf{ -public: - char record[HELP_CATEGORY_NAME_SIZE]; +/* + Look for all topics of category - inline int16 get_cat_id() - { - return sint2korr(&record[offset_hcn_cat_id]); - } + 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) - inline int get_func_id() - { - return sint3korr(&record[offset_hcn_func_id]); - } -}; + RETURN VALUES + -1 corrupt database + 0 succesefull +*/ -int get_all_names_for_category(THD *thd,MI_INFO *file_leafs, - int16 cat_id, List<String> *res) +int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations, + struct st_find_field *find_fields, + int16 cat_id, List<char> *res) { - DBUG_ENTER("get_all_names_for_category"); - - MI_INFO *file_names_categories= 0; - if (!(file_names_categories= open_help_file(thd,"function_category"))) - DBUG_RETURN(1); - - help_category_leaf cat_leaf; - help_leaf leaf; - int key_res= mi_rkey(file_names_categories, (byte*)&cat_leaf, 0, - (const byte*)&cat_id,2,HA_READ_KEY_EXACT); - - while (!key_res && cat_leaf.get_cat_id()==cat_id) + char buff[8]; // Max int length + DBUG_ENTER("get_all_topics_for_category"); + + int iindex_topic, iindex_relations; + Field *rtopic_id, *rcat_id; + + if ((iindex_topic= find_type((char*) "PRIMARY", + &topics->keynames, 1+2)-1)<0 || + (iindex_relations= find_type((char*) "PRIMARY", + &relations->keynames, 1+2)-1)<0) { - int leaf_id= cat_leaf.get_func_id(); - - if (!mi_rkey(file_leafs, (byte*)&leaf, 0, - (const byte*)&leaf_id,4,HA_READ_KEY_EXACT)) - { - leaf.prepare_fields(); - String *s= new String(leaf.get_name(),help_charset); - if (!s->copy()) - res->push_back(s); - } - - key_res= mi_rnext(file_names_categories, (byte*)&cat_leaf, 0); + send_error(thd,ER_CORRUPT_HELP_DB); + DBUG_RETURN(-1); + } + rtopic_id= find_fields[help_relation_help_topic_id].field; + rcat_id= find_fields[help_relation_help_category_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, + Field::itRAW); + int key_res= relations->file->index_read(relations->record[0], + buff, rcat_id->pack_length(), + HA_READ_KEY_EXACT); + + for ( ; !key_res && cat_id == (int16) rcat_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::itRAW); + + if (!topics->file->index_read(topics->record[0], topic_id_buff, + field->pack_length(), + HA_READ_KEY_EXACT)) + res->push_back(get_field(&thd->mem_root, + find_fields[help_topic_name].field)); } - - mi_close(file_names_categories); - DBUG_RETURN(0); } + +/* + Send to client answer for help request + + SYNOPSIS + 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" + + IMPLEMENTATION + Format used: + +----------+---------+------------+------------+ + |Name: |Category |Description |Example | + +----------+---------+------------+------------+ + |String(64)|String(1)|String(1000)|String(1000)| + +----------+---------+------------+------------+ + with exactly one row! + + RETURN VALUES + 1 Writing of head failed + -1 Writing of row failed + 0 Successeful send +*/ + int send_answer_1(Protocol *protocol, const char *s1, const char *s2, const char *s3, const char *s4) { @@ -306,10 +312,10 @@ int send_answer_1(Protocol *protocol, const char *s1, const char *s2, 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)); - + if (protocol->send_fields(&field_list,1)) DBUG_RETURN(1); - + protocol->prepare_for_resend(); protocol->store(s1); protocol->store(s2); @@ -317,11 +323,28 @@ int send_answer_1(Protocol *protocol, const char *s1, const char *s2, protocol->store(s4); if (protocol->write()) DBUG_RETURN(-1); - DBUG_RETURN(0); } +/* + Send to client help header + + SYNOPSIS + send_header_2() + protocol - protocol for sending + + IMPLEMENTATION + +----------+---------+ + |Name: |Category | + +----------+---------+ + |String(64)|String(1)| + +----------+---------+ + + RETURN VALUES + result of protocol->send_fields +*/ + int send_header_2(Protocol *protocol) { DBUG_ENTER("send_header2"); @@ -332,79 +355,165 @@ int send_header_2(Protocol *protocol) } +/* + Server-side function 'help' + + SYNOPSIS + mysqld_help() + thd Thread handler + + RETURN VALUES + 0 Success + 1 Error and send_error already commited + -1 error && send_error should be issued (normal case) +*/ + int mysqld_help(THD *thd, const char *mask) { Protocol *protocol= thd->protocol; + SQL_SELECT *select= 0, *select_cat= 0; + Item *cond_topic, *cond_cat; + st_find_field used_fields[array_elements(init_used_fields)]; DBUG_ENTER("mysqld_help"); + + TABLE_LIST tables[3]; + bzero((gptr)tables,sizeof(tables)); + tables[0].alias= tables[0].real_name= (char*) "help_topic"; + tables[0].lock_type= TL_READ; + tables[0].db= (char*) "mysql"; + tables[0].next= &tables[1]; + tables[1].alias= tables[1].real_name= (char*) "help_category"; + tables[1].lock_type= TL_READ; + tables[1].db= (char*) "mysql"; + tables[1].next= &tables[2]; + 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; + + List<char> function_list, categories_list; + char *name, *description, *example; + int res, count_topics, count_categories, error; + + if (open_and_lock_tables(thd, tables)) + { + res= -1; + goto end; + } + /* Init tables and fields to be usable from items */ + setup_tables(tables); + memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields)); + if (init_fields(thd, tables, used_fields, array_elements(used_fields))) + { + res= -1; + 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(); + + 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; + } - MI_INFO *file_leafs= 0; - if (!(file_leafs= open_help_file(thd,"function"))) - DBUG_RETURN(1); - - List<String> function_list, categories_list; - String *name, *description, *example; - int res; - - int count= search_functions(file_leafs, mask, - &function_list,&name,&description,&example); - if (count < 0) + 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))) { - res= 1; + res= -1; goto end; } - else if (count==0) + + res= 1; + count_topics= search_topics(thd,tables[0].table, used_fields, select, + &function_list, &name, &description, &example); + if (count_topics == 0) { int16 category_id; - count= search_categories(thd, mask, &categories_list, &category_id); - if (count<0) + 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 + + count_categories= search_categories(thd, tables[1].table, used_fields, + select_cat, &categories_list, + &category_id); + if (count_categories == 1) { - res= 1; - goto end; - } - else if (count==1) - { - if ((res= get_all_names_for_category(thd, file_leafs, - category_id,&function_list))) + if (get_all_topics_for_category(thd,tables[0].table, + tables[2].table, used_fields, + category_id, &function_list)) + { + res= -1; goto end; - List_iterator<String> it(function_list); - String *cur_leaf, example; - while ((cur_leaf = it++)) + } + 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_leaf); + example.append(cur_topic); example.append("\n",1); } - if ((res= send_answer_1(protocol, categories_list.head()->ptr(), - "Y","",example.ptr()))) + if ((send_answer_1(protocol, categories_list.head(), + "Y","",example.ptr()))) goto end; } else { - if ((res= send_header_2(protocol)) || - (count==0 && - (search_categories(thd, 0, &categories_list, 0)<0 && - ((res= 1)))) || - (res= send_variant_2_list(protocol,&categories_list,true))) + 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")) goto end; } } - else if (count==1) + else if (count_topics == 1) { - if ((res= send_answer_1(protocol,name->ptr(),"N", - description->ptr(), example->ptr()))) + if (send_answer_1(protocol,name,"N",description, example)) goto end; } - else if ((res= send_header_2(protocol)) || - (res= send_variant_2_list(protocol,&function_list,false)) || - (search_categories(thd, mask, &categories_list, 0)<0 && - ((res=1))) || - (res= send_variant_2_list(protocol,&categories_list,true))) + else { - goto end; + /* First send header and functions */ + if (send_header_2(protocol) || + send_variant_2_list(protocol, &function_list, "N")) + goto end; + search_categories(thd, tables[1].table, used_fields, select_cat, + &categories_list, 0); + /* Then send categories */ + if (send_variant_2_list(protocol, &categories_list, "Y")) + goto end; } - + res= 0; + send_eof(thd); - end: - mi_close(file_leafs); + delete select; + delete select_cat; DBUG_RETURN(res); } |