summaryrefslogtreecommitdiff
path: root/sql/sql_help.cc
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2003-02-12 21:55:37 +0200
committerunknown <monty@mashka.mysql.fi>2003-02-12 21:55:37 +0200
commitfcb61f5917ee69bba91bd6a926db2eab4ac3eeb5 (patch)
tree3ac37e452f15c8f05e9d1f338a6050281f838048 /sql/sql_help.cc
parent363fd89b92de2fc58e7910f7a27684308656ebda (diff)
downloadmariadb-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.cc647
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,
+ &not_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);
}