diff options
author | unknown <vva@eagle.mysql.r18.ru> | 2003-05-29 17:47:31 -0400 |
---|---|---|
committer | unknown <vva@eagle.mysql.r18.ru> | 2003-05-29 17:47:31 -0400 |
commit | 69e084af1eedff2dda70fcf073dd4fa349718b69 (patch) | |
tree | a9f85257a75430a22735e52666cbf25e605ea2bb | |
parent | f440077bd03869f48ff278bc2b73fab7a30e282b (diff) | |
download | mariadb-git-69e084af1eedff2dda70fcf073dd4fa349718b69.tar.gz |
new version of help
-rw-r--r-- | client/mysql.cc | 83 | ||||
-rw-r--r-- | mysql-test/install_test_db.sh | 210 | ||||
-rw-r--r-- | mysql-test/r/connect.result | 3 | ||||
-rw-r--r-- | mysql-test/r/help.result | 254 | ||||
-rw-r--r-- | mysql-test/t/help.test | 111 | ||||
-rw-r--r-- | scripts/Makefile.am | 20 | ||||
-rw-r--r-- | scripts/fill_help_tables.sh | 560 | ||||
-rw-r--r-- | scripts/mysql_create_system_tables.sh | 311 | ||||
-rw-r--r-- | scripts/mysql_install_db.sh | 220 | ||||
-rw-r--r-- | sql/mysql_priv.h | 1 | ||||
-rw-r--r-- | sql/protocol.h | 2 | ||||
-rw-r--r-- | sql/sql_help.cc | 782 | ||||
-rw-r--r-- | sql/table.cc | 27 |
13 files changed, 1653 insertions, 931 deletions
diff --git a/client/mysql.cc b/client/mysql.cc index aa9dcca92db..1bfadb37eb2 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1457,6 +1457,16 @@ int mysql_store_result_for_lazy(MYSQL_RES **result) return 0; } +static void print_help_item(MYSQL_ROW *cur, int num_name, int num_cat, char *last_char) +{ + char ccat= (*cur)[num_cat][0]; + if (*last_char != ccat) + { + put_info(ccat == 'Y' ? "categories :" : "topics :", INFO_INFO); + *last_char= ccat; + } + tee_fprintf(PAGER, " %s\n", (*cur)[num_name]); +} static int com_server_help(String *buffer __attribute__((unused)), char *line __attribute__((unused)), char *help_arg) @@ -1465,14 +1475,15 @@ static int com_server_help(String *buffer __attribute__((unused)), const char *server_cmd= buffer->ptr(); char cmd_buf[100]; MYSQL_RES *result; + MYSQL_FIELD *fields; int error; - + if (help_arg[0] != '\'') { (void) strxnmov(cmd_buf, sizeof(cmd_buf), "help '", help_arg, "'", NullS); server_cmd= cmd_buf; } - + if (!status.batch) { old_buffer= *buffer; @@ -1482,15 +1493,16 @@ static int com_server_help(String *buffer __attribute__((unused)), if (!connected && reconnect()) return 1; - if ((error= mysql_real_query_for_lazy(server_cmd,strlen(server_cmd)))) - return error; - if ((error= mysql_store_result_for_lazy(&result))) + if ((error= mysql_real_query_for_lazy(server_cmd,strlen(server_cmd))) || + (error= mysql_store_result_for_lazy(&result))) return error; if (result) { - ulonglong num_rows= mysql_num_rows(result); - if (num_rows == 1) + unsigned int num_fields= mysql_num_fields(result); + my_ulonglong num_rows= mysql_num_rows(result); + fields= mysql_fetch_fields(result); + if (num_fields==3 && num_rows==1) { if (!(cur= mysql_fetch_row(result))) { @@ -1499,46 +1511,45 @@ static int com_server_help(String *buffer __attribute__((unused)), } init_pager(); - if (cur[1][0] == 'Y') - { - tee_fprintf(PAGER, "Help topic \'%s\'\n", cur[0]); - tee_fprintf(PAGER, "%s\n", cur[2]); - tee_fprintf(PAGER, "For help on specific function please type 'help <function>'\nwhere function is one of next:\n%s\n", cur[3]); - } - else - { - tee_fprintf(PAGER, "Name: \'%s\'\n\n", cur[0]); - tee_fprintf(PAGER, "Description:\n%s\n\n", cur[2]); - if (cur[3]) - tee_fprintf(PAGER, "Examples:\n%s\n", cur[3]); - } + tee_fprintf(PAGER, "Name: \'%s\'\n", cur[0]); + tee_fprintf(PAGER, "Description:\n%s", cur[1]); + if (cur[2] && *((char*)cur[2])) + tee_fprintf(PAGER, "Examples:\n%s", cur[2]); + tee_fprintf(PAGER, "\n"); end_pager(); } - else if (num_rows > 1) + else if (num_fields >= 2 && num_rows) { - put_info("Many help items for your request exist", INFO_INFO); - put_info("For more specific request please type 'help <item>' where item is one of next:", INFO_INFO); - init_pager(); - char last_char= '_'; - while ((cur= mysql_fetch_row(result))) + char last_char; + + int num_name, num_cat; + if (num_fields == 2) { - if (cur[1][0]!=last_char) - { - put_info("-------------------------------------------", INFO_INFO); - put_info(cur[1][0] == 'Y' ? - "categories:" : "functions:", INFO_INFO); - put_info("-------------------------------------------", INFO_INFO); - } - last_char= cur[1][0]; - tee_fprintf(PAGER, "%s\n", cur[0]); + put_info("Many help items for your request exist", INFO_INFO); + put_info("For more specific request please type 'help <item>' where item is one of next", INFO_INFO); + num_name= 0; + num_cat= 1; + last_char= '_'; } + else if ((cur= mysql_fetch_row(result))) + { + tee_fprintf(PAGER, "You asked help about help category: \"%s\"\n", cur[0]); + put_info("For a more information type 'help <item>' where item is one of the following", INFO_INFO); + num_name= 1; + num_cat= 2; + print_help_item(&cur,1,2,&last_char); + } + + while ((cur= mysql_fetch_row(result))) + print_help_item(&cur,num_name,num_cat,&last_char); tee_fprintf(PAGER, "\n"); end_pager(); } else { - put_info("\nNothing found\n", INFO_INFO); + put_info("\nNothing found", INFO_INFO); + put_info("Please try to run 'help contents' for list of all accessible topics\n", INFO_INFO); } } diff --git a/mysql-test/install_test_db.sh b/mysql-test/install_test_db.sh index fc3e00d8501..ca6d393e3b4 100644 --- a/mysql-test/install_test_db.sh +++ b/mysql-test/install_test_db.sh @@ -11,10 +11,12 @@ if [ x$1 = x"-bin" ]; then bindir=../bin BINARY_DIST=1 fix_bin=mysql-test + scriptdir=../bin else execdir=../sql bindir=../client fix_bin=. + scriptdir=../scripts fi vardir=var @@ -60,217 +62,11 @@ basedir=. EXTRA_ARG="--language=../sql/share/english/" fi -# Initialize variables -c_d="" i_d="" -c_h="" i_h="" -c_u="" i_u="" -c_f="" i_f="" -c_t="" c_c="" -c_hl="" c_hl="" -c_hc="" c_hc="" -c_clr="" c_clr="" - -# Check for old tables -if test ! -f $mdata/db.frm -then - # mysqld --bootstrap wants one command/line - c_d="$c_d CREATE TABLE db (" - c_d="$c_d Host char(60) DEFAULT '' NOT NULL," - c_d="$c_d Db char(64) DEFAULT '' NOT NULL," - c_d="$c_d User char(16) DEFAULT '' NOT NULL," - c_d="$c_d Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d References_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d PRIMARY KEY Host (Host,Db,User)," - c_d="$c_d KEY User (User)" - c_d="$c_d )" - c_d="$c_d comment='Database privileges';" - - i_d="INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); - INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');" -fi - -if test ! -f $mdata/host.frm -then - c_h="$c_h CREATE TABLE host (" - c_h="$c_h Host char(60) DEFAULT '' NOT NULL," - c_h="$c_h Db char(64) DEFAULT '' NOT NULL," - c_h="$c_h Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h References_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h PRIMARY KEY Host (Host,Db)" - c_h="$c_h )" - c_h="$c_h comment='Host privileges; Merged with database privileges';" -fi - -if test ! -f $mdata/user.frm -then - c_u="$c_u CREATE TABLE user (" - c_u="$c_u Host char(60) binary DEFAULT '' NOT NULL," - c_u="$c_u User char(16) binary DEFAULT '' NOT NULL," - c_u="$c_u Password char(45) binary DEFAULT '' NOT NULL," - c_u="$c_u Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Process_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u File_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u References_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Super_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL," - c_u="$c_u ssl_cipher BLOB NOT NULL," - c_u="$c_u x509_issuer BLOB NOT NULL," - c_u="$c_u x509_subject BLOB NOT NULL," - c_u="$c_u max_questions int(11) unsigned DEFAULT 0 NOT NULL," - c_u="$c_u max_updates int(11) unsigned DEFAULT 0 NOT NULL," - c_u="$c_u max_connections int(11) unsigned DEFAULT 0 NOT NULL," - c_u="$c_u PRIMARY KEY Host (Host,User)" - c_u="$c_u )" - c_u="$c_u comment='Users and global privileges';" - - i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - REPLACE INTO user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - INSERT INTO user (host,user) values ('localhost',''); - INSERT INTO user (host,user) values ('$hostname','');" -fi - -if test ! -f $mdata/func.frm -then - c_f="$c_f CREATE TABLE func (" - c_f="$c_f name char(64) DEFAULT '' NOT NULL," - c_f="$c_f ret tinyint(1) DEFAULT '0' NOT NULL," - c_f="$c_f dl char(128) DEFAULT '' NOT NULL," - c_f="$c_f type enum ('function','aggregate') NOT NULL," - c_f="$c_f PRIMARY KEY (name)" - c_f="$c_f )" - c_f="$c_f comment='User defined functions';" -fi - -if test ! -f $mdata/tables_priv.frm -then - c_t="$c_t CREATE TABLE tables_priv (" - c_t="$c_t Host char(60) DEFAULT '' NOT NULL," - c_t="$c_t Db char(64) DEFAULT '' NOT NULL," - c_t="$c_t User char(16) DEFAULT '' NOT NULL," - c_t="$c_t Table_name char(60) DEFAULT '' NOT NULL," - c_t="$c_t Grantor char(77) DEFAULT '' NOT NULL," - c_t="$c_t Timestamp timestamp(14)," - c_t="$c_t Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL," - c_t="$c_t Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL," - c_t="$c_t PRIMARY KEY (Host,Db,User,Table_name)," - c_t="$c_t KEY Grantor (Grantor)" - c_t="$c_t )" - c_t="$c_t comment='Table privileges';" -fi - -if test ! -f $mdata/columns_priv.frm -then - c_c="$c_c CREATE TABLE columns_priv (" - c_c="$c_c Host char(60) DEFAULT '' NOT NULL," - c_c="$c_c Db char(64) DEFAULT '' NOT NULL," - c_c="$c_c User char(16) DEFAULT '' NOT NULL," - c_c="$c_c Table_name char(64) DEFAULT '' NOT NULL," - c_c="$c_c Column_name char(64) DEFAULT '' NOT NULL," - c_c="$c_c Timestamp timestamp(14)," - c_c="$c_c Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL," - c_c="$c_c PRIMARY KEY (Host,Db,User,Table_name,Column_name)" - c_c="$c_c )" - c_c="$c_c comment='Column privileges';" -fi - -if test ! -f $mdata/help_topic.frm -then - c_hl="$c_hl CREATE TABLE help_topic (" - c_hl="$c_hl help_topic_id int unsigned not null auto_increment," - c_hl="$c_hl name varchar(64) not null," - c_hl="$c_hl description text not null," - c_hl="$c_hl example text not null," - c_hl="$c_hl url varchar(128) not null," - c_hl="$c_hl primary key (help_topic_id)," - c_hl="$c_hl unique index (name)" - c_hl="$c_hl )" - c_hl="$c_hl comment='help topics';" -fi - -if test ! -f $mdata/help_category.frm -then - c_clr="$c_clr CREATE TABLE help_category (" - c_clr="$c_clr help_category_id smallint unsigned not null auto_increment," - c_clr="$c_clr name varchar(64) not null," - c_clr="$c_clr url varchar(128) not null," - c_clr="$c_clr primary key (help_category_id)," - c_clr="$c_clr unique index (name)" - c_clr="$c_clr )" - c_clr="$c_clr comment='help topics-categories relation';" -fi - -if test ! -f $mdata/help_relation.frm -then - c_hc="$c_hc CREATE TABLE help_relation (" - c_hc="$c_hc help_topic_id int unsigned not null references help_topic," - c_hc="$c_hc help_category_id smallint unsigned not null references help_category," - c_hc="$c_hc primary key (help_category_id, help_topic_id)," - c_hc="$c_hc )" - c_hc="$c_hc comment='categories of help topics';" -fi - mysqld_boot=" $execdir/mysqld --no-defaults --bootstrap --skip-grant-tables \ --basedir=$basedir --datadir=$ldata --skip-innodb --skip-bdb $EXTRA_ARG" echo "running $mysqld_boot" -if $mysqld_boot << END_OF_DATA -use mysql; -$c_d -$i_d - -$c_h -$i_h - -$c_u -$i_u - -$c_f -$i_f - -$c_t -$c_c - -$c_hl -$c_hc -$c_clr -END_OF_DATA +if $scriptdir/mysql_create_system_tables test $mdata $hostname | $mysqld_boot then exit 0 else diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result index b7243ac5d0b..a80ddc24d05 100644 --- a/mysql-test/r/connect.result +++ b/mysql-test/r/connect.result @@ -4,6 +4,7 @@ columns_priv db func help_category +help_keyword help_relation help_topic host @@ -19,6 +20,7 @@ columns_priv db func help_category +help_keyword help_relation help_topic host @@ -34,6 +36,7 @@ columns_priv db func help_category +help_keyword help_relation help_topic host diff --git a/mysql-test/r/help.result b/mysql-test/r/help.result index 4da4a84d4ad..d22539b2bcb 100644 --- a/mysql-test/r/help.result +++ b/mysql-test/r/help.result @@ -1,123 +1,243 @@ -truncate mysql.help_topic; -truncate mysql.help_category; -truncate mysql.help_relation; -insert into mysql.help_topic(name,description,example)values('impossible_function_1','description of \n impossible_function1','example of \n impossible_function1'); -SELECT @topic1_id:=LAST_INSERT_ID(); -@topic1_id:=LAST_INSERT_ID() +insert into mysql.help_category(help_category_id,name)values(1,'impossible_category_1'); +select @category1_id:= 1; +@category1_id:= 1 1 -insert into mysql.help_topic(name,description,example)values('impossible_function_2','description of \n impossible_function2','example of \n impossible_function2'); -SELECT @topic2_id:=LAST_INSERT_ID(); -@topic2_id:=LAST_INSERT_ID() +insert into mysql.help_category(help_category_id,name)values(2,'impossible_category_2'); +select @category2_id:= 2; +@category2_id:= 2 2 -insert into mysql.help_topic(name,description,example)values('impossible_function_3','description of \n impossible_function3','example of \n impossible_function3'); -SELECT @topic3_id:=LAST_INSERT_ID(); -@topic3_id:=LAST_INSERT_ID() +insert into mysql.help_category(help_category_id,name,parent_category_id)values(3,'impossible_category_3',@category2_id); +select @category3_id:= 3; +@category3_id:= 3 3 -insert into mysql.help_category(name)values('impossible_category_1'); -SELECT @category1_id:=LAST_INSERT_ID(); -@category1_id:=LAST_INSERT_ID() +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(1,'impossible_function_1',@category1_id,'description of \n impossible_function1\n','example of \n impossible_function1'); +select @topic1_id:= 1; +@topic1_id:= 1 1 -insert into mysql.help_category(name)values('impossible_category_2'); -SELECT @category2_id:=LAST_INSERT_ID(); -@category2_id:=LAST_INSERT_ID() +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(2,'impossible_function_2',@category1_id,'description of \n impossible_function2\n','example of \n impossible_function2'); +select @topic2_id:= 2; +@topic2_id:= 2 2 -insert into mysql.help_relation(help_category_id,help_topic_id)values(@category1_id,@topic1_id); -insert into mysql.help_relation(help_category_id,help_topic_id)values(@category1_id,@topic2_id); -insert into mysql.help_relation(help_category_id,help_topic_id)values(@category2_id,@topic2_id); -insert into mysql.help_relation(help_category_id,help_topic_id)values(@category2_id,@topic3_id); +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(3,'impossible_function_3',@category2_id,'description of \n impossible_function3\n','example of \n impossible_function3'); +select @topic3_id:= 3; +@topic3_id:= 3 +3 +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(4,'impossible_function_4',@category2_id,'description of \n impossible_function4\n','example of \n impossible_function4'); +select @topic4_id:= 4; +@topic4_id:= 4 +4 +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(5,'impossible_function_7',@category3_id,'description of \n impossible_function5\n','example of \n impossible_function7'); +select @topic5_id:= 5; +@topic5_id:= 5 +5 +insert into mysql.help_keyword(help_keyword_id,name)values(1,'impossible_function_1'); +select @keyword1_id:= 1; +@keyword1_id:= 1 +1 +insert into mysql.help_keyword(help_keyword_id,name)values(2,'impossible_function_5'); +select @keyword2_id:= 2; +@keyword2_id:= 2 +2 +insert into mysql.help_keyword(help_keyword_id,name)values(3,'impossible_function_6'); +select @keyword3_id:= 3; +@keyword3_id:= 3 +3 +insert into mysql.help_relation(help_keyword_id,help_topic_id)values(@keyword1_id,@topic2_id); +insert into mysql.help_relation(help_keyword_id,help_topic_id)values(@keyword2_id,@topic1_id); +insert into mysql.help_relation(help_keyword_id,help_topic_id)values(@keyword3_id,@topic3_id); +insert into mysql.help_relation(help_keyword_id,help_topic_id)values(@keyword3_id,@topic4_id); help 'function_of_my_dream'; -Name Category -impossible_category_1 Y -impossible_category_2 Y +name is_it_category help '%possible_f%'; -Name Category +name is_it_category impossible_function_1 N impossible_function_2 N impossible_function_3 N +impossible_function_4 N +impossible_function_7 N help 'impossible_func%'; -Name Category +name is_it_category impossible_function_1 N impossible_function_2 N impossible_function_3 N +impossible_function_4 N +impossible_function_7 N help 'impossible_category%'; -Name Category +name is_it_category impossible_category_1 Y impossible_category_2 Y +impossible_category_3 Y help 'impossible_%'; -Name Category +name is_it_category impossible_function_1 N impossible_function_2 N impossible_function_3 N +impossible_function_4 N +impossible_function_7 N impossible_category_1 Y impossible_category_2 Y +impossible_category_3 Y +help '%function_1'; +name description example +impossible_function_1 description of + impossible_function1 + example of + impossible_function1 help '%function_2'; -Name Category Description Example -impossible_function_2 N description of - impossible_function2 example of +name description example +impossible_function_2 description of + impossible_function2 + example of impossible_function2 +help '%function_3'; +name description example +impossible_function_3 description of + impossible_function3 + example of + impossible_function3 +help '%function_4'; +name description example +impossible_function_4 description of + impossible_function4 + example of + impossible_function4 +help '%function_5'; +name description example +impossible_function_1 description of + impossible_function1 + example of + impossible_function1 +help '%function_6'; +name is_it_category +impossible_function_3 N +impossible_function_4 N +help '%function_7'; +name description example +impossible_function_7 description of + impossible_function5 + example of + impossible_function7 help '%category_2'; -Name Category Description Example -impossible_category_2 Y impossible_function_2 -impossible_function_3 - +source_category_name name is_it_category +impossible_category_2 impossible_function_3 N +impossible_category_2 impossible_function_4 N +impossible_category_2 impossible_category_3 Y help 'impossible_function_1'; -Name Category Description Example -impossible_function_1 N description of - impossible_function1 example of +name description example +impossible_function_1 description of + impossible_function1 + example of impossible_function1 help 'impossible_category_1'; -Name Category Description Example -impossible_category_1 Y impossible_function_1 -impossible_function_2 - +source_category_name name is_it_category +impossible_category_1 impossible_function_1 N +impossible_category_1 impossible_function_2 N +alter table mysql.help_relation type=innodb; +alter table mysql.help_keyword type=innodb; alter table mysql.help_topic type=innodb; alter table mysql.help_category type=innodb; -alter table mysql.help_relation type=innodb; help 'function_of_my_dream'; -Name Category -impossible_category_1 Y -impossible_category_2 Y -help '%ble_f%'; -Name Category +name is_it_category +help '%possible_f%'; +name is_it_category impossible_function_1 N impossible_function_2 N impossible_function_3 N +impossible_function_4 N +impossible_function_7 N help 'impossible_func%'; -Name Category +name is_it_category impossible_function_1 N impossible_function_2 N impossible_function_3 N +impossible_function_4 N +impossible_function_7 N help 'impossible_category%'; -Name Category +name is_it_category impossible_category_1 Y impossible_category_2 Y +impossible_category_3 Y help 'impossible_%'; -Name Category +name is_it_category impossible_function_1 N impossible_function_2 N impossible_function_3 N +impossible_function_4 N +impossible_function_7 N impossible_category_1 Y impossible_category_2 Y +impossible_category_3 Y +help '%function_1'; +name description example +impossible_function_1 description of + impossible_function1 + example of + impossible_function1 help '%function_2'; -Name Category Description Example -impossible_function_2 N description of - impossible_function2 example of +name description example +impossible_function_2 description of + impossible_function2 + example of impossible_function2 +help '%function_3'; +name description example +impossible_function_3 description of + impossible_function3 + example of + impossible_function3 +help '%function_4'; +name description example +impossible_function_4 description of + impossible_function4 + example of + impossible_function4 +help '%function_5'; +name description example +impossible_function_1 description of + impossible_function1 + example of + impossible_function1 +help '%function_6'; +name is_it_category +impossible_function_3 N +impossible_function_4 N +help '%function_7'; +name description example +impossible_function_7 description of + impossible_function5 + example of + impossible_function7 help '%category_2'; -Name Category Description Example -impossible_category_2 Y impossible_function_2 -impossible_function_3 - +source_category_name name is_it_category +impossible_category_2 impossible_function_3 N +impossible_category_2 impossible_function_4 N +impossible_category_2 impossible_category_3 Y help 'impossible_function_1'; -Name Category Description Example -impossible_function_1 N description of - impossible_function1 example of +name description example +impossible_function_1 description of + impossible_function1 + example of impossible_function1 help 'impossible_category_1'; -Name Category Description Example -impossible_category_1 Y impossible_function_1 -impossible_function_2 - +source_category_name name is_it_category +impossible_category_1 impossible_function_1 N +impossible_category_1 impossible_function_2 N +alter table mysql.help_relation type=myisam; +alter table mysql.help_keyword type=myisam; alter table mysql.help_topic type=myisam; alter table mysql.help_category type=myisam; -alter table mysql.help_relation type=myisam; +delete from mysql.help_topic where help_topic_id=@topic1_id; +delete from mysql.help_topic where help_topic_id=@topic2_id; +delete from mysql.help_topic where help_topic_id=@topic3_id; +delete from mysql.help_topic where help_topic_id=@topic4_id; +delete from mysql.help_topic where help_topic_id=@topic5_id; +delete from mysql.help_category where help_category_id=@category3_id; +delete from mysql.help_category where help_category_id=@category2_id; +delete from mysql.help_category where help_category_id=@category1_id; +delete from mysql.help_keyword where help_keyword_id=@keyword1_id; +delete from mysql.help_keyword where help_keyword_id=@keyword2_id; +delete from mysql.help_keyword where help_keyword_id=@keyword3_id; +delete from mysql.help_relation where help_keyword_id=@keyword1_id and help_topic_id=@topic2_id; +delete from mysql.help_relation where help_keyword_id=@keyword2_id and help_topic_id=@topic1_id; +delete from mysql.help_relation where help_keyword_id=@keyword3_id and help_topic_id=@topic3_id; +delete from mysql.help_relation where help_keyword_id=@keyword3_id and help_topic_id=@topic4_id; diff --git a/mysql-test/t/help.test b/mysql-test/t/help.test index c36b670c6b3..82312340336 100644 --- a/mysql-test/t/help.test +++ b/mysql-test/t/help.test @@ -1,50 +1,115 @@ -- source include/have_innodb.inc -truncate mysql.help_topic; -truncate mysql.help_category; -truncate mysql.help_relation; - -insert into mysql.help_topic(name,description,example)values('impossible_function_1','description of \n impossible_function1','example of \n impossible_function1'); -SELECT @topic1_id:=LAST_INSERT_ID(); -insert into mysql.help_topic(name,description,example)values('impossible_function_2','description of \n impossible_function2','example of \n impossible_function2'); -SELECT @topic2_id:=LAST_INSERT_ID(); -insert into mysql.help_topic(name,description,example)values('impossible_function_3','description of \n impossible_function3','example of \n impossible_function3'); -SELECT @topic3_id:=LAST_INSERT_ID(); - -insert into mysql.help_category(name)values('impossible_category_1'); -SELECT @category1_id:=LAST_INSERT_ID(); -insert into mysql.help_category(name)values('impossible_category_2'); -SELECT @category2_id:=LAST_INSERT_ID(); - -insert into mysql.help_relation(help_category_id,help_topic_id)values(@category1_id,@topic1_id); -insert into mysql.help_relation(help_category_id,help_topic_id)values(@category1_id,@topic2_id); -insert into mysql.help_relation(help_category_id,help_topic_id)values(@category2_id,@topic2_id); -insert into mysql.help_relation(help_category_id,help_topic_id)values(@category2_id,@topic3_id); +# category: topic: keyword: +# +# impossible_category_1 +# impossible_function_1 +# impossible_function_5 +# impossible_function_2 +# impossible_function_1 +# impossible_category_2 +# impossible_function_3 +# impossible_function_6 +# impossible_function_4 +# impossible_function_6 +# impossible_category_3 +# impossible_function_7 +insert into mysql.help_category(help_category_id,name)values(1,'impossible_category_1'); +select @category1_id:= 1; +insert into mysql.help_category(help_category_id,name)values(2,'impossible_category_2'); +select @category2_id:= 2; +insert into mysql.help_category(help_category_id,name,parent_category_id)values(3,'impossible_category_3',@category2_id); +select @category3_id:= 3; + +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(1,'impossible_function_1',@category1_id,'description of \n impossible_function1\n','example of \n impossible_function1'); +select @topic1_id:= 1; +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(2,'impossible_function_2',@category1_id,'description of \n impossible_function2\n','example of \n impossible_function2'); +select @topic2_id:= 2; +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(3,'impossible_function_3',@category2_id,'description of \n impossible_function3\n','example of \n impossible_function3'); +select @topic3_id:= 3; +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(4,'impossible_function_4',@category2_id,'description of \n impossible_function4\n','example of \n impossible_function4'); +select @topic4_id:= 4; +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(5,'impossible_function_7',@category3_id,'description of \n impossible_function5\n','example of \n impossible_function7'); +select @topic5_id:= 5; + +insert into mysql.help_keyword(help_keyword_id,name)values(1,'impossible_function_1'); +select @keyword1_id:= 1; +insert into mysql.help_keyword(help_keyword_id,name)values(2,'impossible_function_5'); +select @keyword2_id:= 2; +insert into mysql.help_keyword(help_keyword_id,name)values(3,'impossible_function_6'); +select @keyword3_id:= 3; + +insert into mysql.help_relation(help_keyword_id,help_topic_id)values(@keyword1_id,@topic2_id); +insert into mysql.help_relation(help_keyword_id,help_topic_id)values(@keyword2_id,@topic1_id); +insert into mysql.help_relation(help_keyword_id,help_topic_id)values(@keyword3_id,@topic3_id); +insert into mysql.help_relation(help_keyword_id,help_topic_id)values(@keyword3_id,@topic4_id); + +############## help 'function_of_my_dream'; help '%possible_f%'; help 'impossible_func%'; help 'impossible_category%'; help 'impossible_%'; + +help '%function_1'; help '%function_2'; +help '%function_3'; +help '%function_4'; +help '%function_5'; +help '%function_6'; +help '%function_7'; + help '%category_2'; help 'impossible_function_1'; help 'impossible_category_1'; +############## +alter table mysql.help_relation type=innodb; +alter table mysql.help_keyword type=innodb; alter table mysql.help_topic type=innodb; alter table mysql.help_category type=innodb; -alter table mysql.help_relation type=innodb; +############## help 'function_of_my_dream'; -help '%ble_f%'; +help '%possible_f%'; help 'impossible_func%'; help 'impossible_category%'; help 'impossible_%'; + +help '%function_1'; help '%function_2'; +help '%function_3'; +help '%function_4'; +help '%function_5'; +help '%function_6'; +help '%function_7'; + help '%category_2'; help 'impossible_function_1'; help 'impossible_category_1'; +############## +alter table mysql.help_relation type=myisam; +alter table mysql.help_keyword type=myisam; alter table mysql.help_topic type=myisam; alter table mysql.help_category type=myisam; -alter table mysql.help_relation type=myisam; + +delete from mysql.help_topic where help_topic_id=@topic1_id; +delete from mysql.help_topic where help_topic_id=@topic2_id; +delete from mysql.help_topic where help_topic_id=@topic3_id; +delete from mysql.help_topic where help_topic_id=@topic4_id; +delete from mysql.help_topic where help_topic_id=@topic5_id; + +delete from mysql.help_category where help_category_id=@category3_id; +delete from mysql.help_category where help_category_id=@category2_id; +delete from mysql.help_category where help_category_id=@category1_id; + +delete from mysql.help_keyword where help_keyword_id=@keyword1_id; +delete from mysql.help_keyword where help_keyword_id=@keyword2_id; +delete from mysql.help_keyword where help_keyword_id=@keyword3_id; + +delete from mysql.help_relation where help_keyword_id=@keyword1_id and help_topic_id=@topic2_id; +delete from mysql.help_relation where help_keyword_id=@keyword2_id and help_topic_id=@topic1_id; +delete from mysql.help_relation where help_keyword_id=@keyword3_id and help_topic_id=@topic3_id; +delete from mysql.help_relation where help_keyword_id=@keyword3_id and help_topic_id=@topic4_id; diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 88f561e0e6d..1134226bfaf 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -32,7 +32,9 @@ bin_SCRIPTS = @server_scripts@ \ mysqldumpslow \ mysql_explain_log \ mysql_tableinfo \ - mysqld_multi + mysqld_multi \ + fill_help_tables \ + mysql_create_system_tables EXTRA_SCRIPTS = make_binary_distribution.sh \ make_win_src_distribution.sh \ @@ -54,14 +56,13 @@ EXTRA_SCRIPTS = make_binary_distribution.sh \ mysqld_multi.sh \ mysql_tableinfo.sh \ mysqld_safe.sh \ - fill_help_tables.sh + fill_help_tables.sh \ + mysql_create_system_tables.sh EXTRA_DIST = $(EXTRA_SCRIPTS) \ mysqlaccess.conf \ mysqlbug -pkgdata_DATA = fill_help_tables.sql - # mysqlbug should be distributed built so that people can report build # failures with it. CLEANFILES = @server_scripts@ \ @@ -81,7 +82,7 @@ CLEANFILES = @server_scripts@ \ mysqldumpslow \ mysqld_multi \ fill_help_tables \ - fill_help_tables.sql + mysql_create_system_tables SUPERCLEANFILES = mysqlbug @@ -137,12 +138,5 @@ SUFFIXES = .sh # Don't update the files from bitkeeper %::SCCS/s.% -all: fill_help_tables.sql make_win_src_distribution make_binary_distribution - -# The following rule is here to ensure that build will continue -# even if we don't have perl installed. In this case the help tables -# will be empty +all: make_win_src_distribution make_binary_distribution -fill_help_tables.sql: fill_help_tables ../Docs/manual.texi - -./fill_help_tables < ../Docs/manual.texi > fill_help_tables.sql - echo "" >> fill_help_tables.sql diff --git a/scripts/fill_help_tables.sh b/scripts/fill_help_tables.sh index e21b0ff2bb0..b8cf4ccb3a7 100644 --- a/scripts/fill_help_tables.sh +++ b/scripts/fill_help_tables.sh @@ -1,31 +1,178 @@ #!@PERL@ # -# Usage: fill_help_tables <manual.texi> -# Example: ./fill_help_tables < ../Docs/manual.texi > fill_help_tables.sql +# Copyright (C) 2003 MySQL AB +# For a more info consult the file COPYRIGHT distributed with this file. # # This script generates the SQL statements required by mysql_install_db to # fill up the tables for the server-side online function help, which can be # invoked with "help <function>" from the MySQL client. # +# Usage: +# fill_help_tables OPTIONS < manual.texi > fill_help_tables.sql +# +# --help display this helpscreen and exit +# --verbose print information about help completeness to STDERR +# --lexems=path path to file with lexems. it is used with verbose option. +# default value is ../sql/lex.h +# Examples: +# ./fill_help_tables --help +# ./fill_help_tables --verbose < manual.texi > fill_help_tables.sql +# ./fill_help_tables < manual.texi > fill_help_tables.sql +# # Please note, that you first need to update Docs/manual.texi with the # manual file from the separate "mysqldoc" BitKeeper-Tree! The manual.texi # included in the source tree is just an empty stub file - the full manual # is now maintained in a separate tree. # +# extra tags in manual.texi: +# +# @c help_category <category_name>[@<parent_category_name>] +# +# @c description_for_help_topic <topic_name> <keyword1> <keyword2> +# .... +# @c end_description_for_help_topic +# +# @c example_for_help_topic <topic_name> +# @example +# .... +# @example +# +# # Original version by Victor Vagin <vva@mysql.com> # -my $cat_name= ""; -my $func_name= ""; -my $text= ""; -my $example= ""; +use strict; +use Getopt::Long; + +my $insert_portion_size= 25; +my $error_prefix= "help parsing error:"; + +my $path_to_lex_file= "../sql/lex.h"; +my $verbose_option= 0; +my $help_option= 0; + +GetOptions( + "help",\$help_option, + "verbose",\$verbose_option, + "lexems=s",\$path_to_lex_file +); + +if ($help_option ne 0) +{ + print <<_HELP; + +This script generates the SQL statements required by mysql_install_db to +fill up the tables for the server-side online function help, which can be +invoked with "help <function>" from the MySQL client. + +Usage: + fill_help_tables OPTIONS < manual.texi > fill_help_tables.sql + + --help display this helpscreen and exit + --verbose print information about help completeness to STDERR + --lexems=path path to file with lexems. it is used with verbose option. + default value is ../sql/lex.h + +Examples: + ./fill_help_tables --help + ./fill_help_tables --verbose < manual.texi > fill_help_tables.sql + ./fill_help_tables < manual.texi > fill_help_tables.sql + +_HELP + exit; +} -local $mode= ""; +my $current_category= ""; +my $current_parent_category= ""; +my $next_example_for_topic= ""; + +my %topics; +my %categories; +my %keywords; + +$categories{Contents}->{__parent_category__}= ""; + +sub add_topic_to_category +{ + my ($topic_name)= @_; + + $categories{$current_category}->{$topic_name}= $topics{$topic_name}; + my $category= $categories{$current_category}; + + if (exists($category->{__parent_category__})) + { + my $old_parent= $category->{__parent_category__}; + if ($old_parent ne $current_parent_category) + { + print STDERR "$error_prefix wrong parent for $current_category\n"; + } + } + + if ($current_parent_category ne "") + { + $category->{__parent_category__}= $current_parent_category; + } + + if (exists($topics{$topic_name}->{category})) + { + my $old_category= $topics{$topic_name}->{category}; + if ($old_category ne $category) + { + print STDERR "$error_prefix wrong category for $topic_name\n"; + } + } + + $topics{$topic_name}->{category}= $category; +} + +sub add_example +{ + my ($topic_name,$example)= @_; + + $topic_name=~ tr/a-z/A-Z/; + + if (exists($topics{$topic_name}->{example})) + { + print STDERR "$error_prefix double example for $topic_name\n"; + } + + $topics{$topic_name}->{example}= $example; + add_topic_to_category($topic_name); +} + +sub add_description +{ + my ($topic_name,$description)= @_; + + $topic_name=~ tr/a-z/A-Z/; + + if (exists($topics{$topic_name}->{description})) + { + print STDERR "$error_prefix double description for $topic_name\n"; + } + $topics{$topic_name}->{description}= $description; + add_topic_to_category($topic_name); +} + +sub add_keyword +{ + my ($topic_name,$keyword)= @_; + + $topic_name=~ tr/a-z/A-Z/; + $keyword=~ tr/a-z/A-Z/; + + push(@{$topics{$topic_name}->{keywords}},$keyword); + if (exists($keywords{$keyword}->{$topic_name})) + { + print STDERR "$error_prefix double keyword $keyword for $topic_name\n"; + } + $keywords{$keyword}->{$topic_name}= $topics{$topic_name}; +} sub prepare_name { my ($a)= @_; - + $a =~ s/(\@itemize \@bullet)/ /g; $a =~ s/(\@end itemize)/ /g; $a =~ s/(\@end multitable)/ /g; @@ -46,41 +193,57 @@ sub prepare_name $a =~ s/\`/\`\`/g; $a =~ s/\@table \@code/ /g; - $a =~ s/\(\)//g; - - $a =~ s/((\w|\s)+)\(([\+-=><\/%*!<>\s]+)\)/$3/gxs; #$a =~ s/((\w|\s)+)\(([\+-=><\/%*!<>\s]+)\)/$3 $1/gxs; - $a =~ s/([\+-=><\/%*!<>\s]+)\(((\w|\s)+)\)/$1/gxs;#$a =~ s/([\+-=><\/%*!<>\s]+)\(((\w|\s)+)\)/$1 $2/gxs; + $a =~ s/\"/\\\"/g; + + $a =~ s/((\w|\s)+)\(([\+-=><\/%*!<>\s]+)\)/$3/gxs; + $a =~ s/([\+-=><\/%*!<>\s]+)\(((\w|\s)+)\)/$1/gxs; $a =~ s/((\w|\s)+)\((.+)\)/$1/gxs; - + return $a; } -sub prepare_text +sub prepare_description { my ($a)= @_; - $a =~ s/(\@itemize \@bullet)/ /g; - $a =~ s/(\@end itemize)/ /g; + $a =~ s/(\@itemize \@bullet\n)//g; + $a =~ s/(\@c help_keyword (.*?)\n)//g; + $a =~ s/(\@end itemize\n)//g; + $a =~ s/(\@end example\n)//g; + $a =~ s/(\@example\n)//g; + $a =~ s/(\@{)/{/g; + $a =~ s/(\@})/}/g; $a =~ s/(\@end multitable)/ /g; $a =~ s/(\@end table)/ /g; - $a =~ s/(\@cindex(.*?)\n)/ /g; + $a =~ s/(\@cindex(.*?)\n)//g; + $a =~ s/(\@findex(.*?)\n)//g; + $a =~ s/(\@table(.*?)\n)//g; $a =~ s/(\@multitable \@columnfractions(.*?)\n)/ /g; $a =~ s/(\@node(.*?)\n)/ /g; $a =~ s/(\@tab)/\t/g; $a =~ s/\@itemx/ /g; - $a =~ s/\@item/ /g; + $a =~ s/(\@item\n(\s*?))(\S)/ --- $3/g; + $a =~ s/(\@item)/ /g; + $a =~ s/(\@tindex\s(.*?)\n)//g; + $a =~ s/(\@c\s(.*?)\n)//g; $a =~ s/\@code\{((.|\n)+?)\}/$1/go; $a =~ s/\@strong\{(.+?)\}/$1/go; $a =~ s/\@samp\{(.+?)\}/$1/go; $a =~ s/\@emph\{((.|\n)+?)\}/\/$1\//go; $a =~ s/\@xref\{((.|\n)+?)\}/See also : [$1]/go; $a =~ s/\@ref\{((.|\n)+?)\}/[$1]/go; - $a =~ s/\'/\'\'/g; + $a =~ s/\@w\{((.|\n)+?)\}/$1/go; + $a =~ s/\@strong\{((.|\n)+?)\}/\n!!!!\n$1\n!!!!\n/go; + $a =~ s/\@file\{((.|\n)+?)\}/\*$1/go; $a =~ s/\\/\\\\/g; - $a =~ s/\`/\`\`/g; - $a =~ s/(\n*?)$//g; + $a =~ s/\n\n$/\n/g; + $a =~ s/\n\n$/\n/g; + $a =~ s/\n\n$/\n/g; + $a =~ s/\n\n$/\n/g; + $a =~ s/\n\n$/\n/g; $a =~ s/\n/\\n/g; + $a =~ s/\"/\\\"/g; $a =~ s/\@table \@code/ /g; @@ -91,148 +254,291 @@ sub prepare_example { my ($a)= @_; - $a =~ s/\'/\'\'/g; + $a =~ s/(^\@c for_help_topic(.*?)\n)//g; + $a =~ s/\\/\\\\/g; - $a =~ s/\`/\`\`/g; + $a =~ s/(\@{)/{/g; + $a =~ s/(\@})/}/g; + $a =~ s/(\@\@)/\@/g; $a =~ s/(\n*?)$//g; $a =~ s/\n/\\n/g; - + $a =~ s/\"/\\\"/g; + return $a; } -sub flush_all +sub parse_example { - my ($mode) = @_; - - if ($mode eq ""){return;} - - $func_name= prepare_name($func_name); - $text= prepare_text($text); - $example= prepare_example($example); - - if ($func_name ne "" && $text ne "" && !($func_name =~ /[abcdefghikjlmnopqrstuvwxyz]/)){ - print "INSERT IGNORE INTO help_topic (name,description,example) VALUES ("; - print "'$func_name',"; - print "'$text',"; - print "'$example'"; - print ");\n"; - print "INSERT IGNORE INTO help_relation (help_category_id,help_topic_id) VALUES (\@cur_category,LAST_INSERT_ID());\n"; + return if (!($_=~/\@example/)); + return if ($next_example_for_topic eq ""); + + my $topic_name= $next_example_for_topic; + $next_example_for_topic= ""; + my $text= ""; + + while (<>) + { + last if ($_=~/\@end example/); + $text .= $_; } + + $text= prepare_example($text); - $func_name= ""; - $text= ""; - $example= ""; - $mode= ""; + add_example($topic_name,$text) if ($topic_name ne ""); } -sub new_category +sub parse_example_for_topic { - my ($category)= @_; - - $category= prepare_text($category); - - print "INSERT IGNORE INTO help_category (name) VALUES (\'$category\');\n"; - print "SET \@cur_category=LAST_INSERT_ID();\n"; + my ($for_topic)= m|\@c example_for_help_topic (.+?)$|; + return if ($for_topic eq ""); + + $next_example_for_topic= $for_topic; } -#print "INSERT IGNORE INTO db (Host,DB,User,Select_priv) VALUES ('%','mysql_help','','Y');\n"; -#print "CREATE DATABASE mysql_help;\n"; +sub parse_description +{ + my ($topic_description)= m|\@c description_for_help_topic (.+?)$|; + return if ($topic_description eq ""); + + my ($topic_name,$topic_keywords)= split(/ /,$topic_description); + + if ($topic_name eq "" || $topic_keywords eq "") + { + $topic_name= $topic_description; + } + else + { + my $keyword; + foreach $keyword (split(/ /,$topic_keywords)) + { + add_keyword($topic_name,$keyword) if ($keyword ne ""); + } + } + + my $text= ""; + + while (<>) + { + last if ($_=~/\@c end_description_for_help_topic/); + $text .= $_; + } + + $text= prepare_description($text); + add_description($topic_name,$text); +} -print "USE mysql;\n"; +sub parse_category +{ + my ($c_name,$pc_name)= m|\@c help_category (.+?)\@(.+?)$|; -print "DROP TABLE IF EXISTS help_topic;\n"; -print "CREATE TABLE help_topic ("; -print " help_topic_id int unsigned not null auto_increment,"; -print " name varchar(64) not null,"; -print " description text not null,"; -print " example text not null,"; -print " url varchar(128) not null,"; -print " primary key (help_topic_id),"; -print " unique index(name)"; -print ") type=myisam;\n\n"; + if ($pc_name ne "") + { + $current_category= prepare_name($c_name); + $current_parent_category= prepare_name($pc_name); + } + else + { + my ($c_name)=m|\@c help_category (.+?)$|; + return if ($c_name eq ""); -print "DROP TABLE IF EXISTS help_category;\n"; -print "CREATE TABLE help_category ("; -print " help_category_id smallint unsigned not null auto_increment,"; -print " name varchar(64) not null,"; -print " url varchar(128) not null,"; -print " primary key (help_category_id),"; -print " unique index (name)"; -print ") type=myisam;\n\n"; + $current_category= prepare_name($c_name); + $current_parent_category= "Contents" + } +} -print "DROP TABLE IF EXISTS help_relation;\n"; -print "CREATE TABLE help_relation ("; -print" help_topic_id int unsigned not null references help_topic,"; -print" help_category_id smallint unsigned not null references help_category,"; -print" primary key (help_category_id, help_topic_id),"; -print ") type=myisam;\n\n"; +# parse manual: -print "SET \@cur_category=null;\n\n"; +while (<>) +{ + parse_example_for_topic (); + parse_example (); + parse_description (); + parse_category (); +} -my $in_section_6_3= 0; +# test results of parsing: -for(<>) +sub print_bad_names { - if ($_=~/\@section Functions for Use in \@code{SELECT} and \@code{WHERE} Clauses/ && - !$in_section_6_3){ - $in_section_6_3= 1; - next; + my($names,$prompt)= @_; + if (scalar(@{$names})) + { + print STDERR "\n-------------- $prompt : \n\n"; + my $name; + foreach $name (@{$names}) + { + print STDERR "$name\n"; + } + print STDERR "\n"; } +} - if ($_=~/\@section/ && $in_section_6_3){ - $in_section_6_3= 0; - next; +sub print_verbose_errors +{ + my($name_of_log_file)= @_; + + my @without_help; + my @description_with_at; + my @example_with_at; + my @without_description; + my @without_example; + + print STDERR "\n-------------- parameters of help completeness : \n\n"; + + my $count_lex= 0; + if (!open (TLEX,"<$path_to_lex_file")) + { + print STDERR "Error opening lex file \"$path_to_lex_file\" $!\n"; } + else + { + for (<TLEX>) + { + my ($a,$lex,$b)=m|(.+?)\"(.+?)\"(.+?)$|; + next if ($lex eq ""); + $count_lex++; + next if (exists($topics{$lex}) || exists($keywords{$lex})); + push(@without_help,$lex); + } + close(TLEX); + print STDERR "number of lexems in \"$path_to_lex_file\" - $count_lex\n"; + } + + my $name; + my @topic_names= keys(%topics); + foreach $name (@topic_names) + { + my $topic= $topics{$name}; + push(@description_with_at,$name) if ($topic->{description}=~/\@/); + push(@example_with_at,$name) if ($topic->{example}=~/\@/); + push(@without_description,$name) if (!exists($topic->{description})); + push(@without_example,$name) if (!exists($topic->{example})); + } + + my $count_categories= scalar(keys(%categories)); + print STDERR "number of help categories - ",$count_categories,"\n"; + my $count_topics= scalar(@topic_names); + print STDERR "number of help topics - ",$count_topics,"\n"; + my $count_keywords= scalar(keys(%keywords)); + print STDERR "number of help keywords - ",$count_keywords,"\n"; + + my $count_without_help= scalar(@without_help); + print_bad_names(\@without_help,"lexems without help (". + $count_without_help." ~ ". + (int (($count_without_help/$count_lex)*100)). + "%)"); + print_bad_names(\@description_with_at, + " topics below have symbol \'@\' in their descriptions.\n". + "it's probably the litter from 'texi' tags (script needs fixing)"); + print_bad_names(\@example_with_at, + " topics below have symbol \'@\' in their examples.\n". + "it's probably the litter from 'texi' tags (script needs fixing)"); + print_bad_names(\@without_description,"topics without description"); + + my $count_without_example= scalar(@without_example); + print_bad_names(\@without_example,"topics without example (". + $count_without_example." ~ ". + (int (($count_without_example/$count_topics)*100)). + "%)"); +} - if (!$in_section_6_3) { next; } +print_verbose_errors if ($verbose_option ne 0); - my $c_name= ""; +# output result - ($c_name)=m|\@c for_mysql_help,(.+?)$|; - if (!($c_name eq "") && ! ($c_name =~ m/$cat_name/i)){ - ($cat_name)= $c_name; - new_category($cat_name); - next; +sub print_insert_header +{ + my($count,$header)= @_; + + if ($count % $insert_portion_size ne 0) { + print ","; + } else { + print ";\n" if ($count ne 0); + print "$header"; } +} - ($c_name)=m|\@subsubsection (.+?)$|; - if (!($c_name eq "") && ! ($c_name =~ m/$cat_name/i)){ - ($cat_name)= $c_name; - new_category($cat_name); - next; - } +print "delete from help_topic;\n"; +print "delete from help_category;\n"; +print "delete from help_keyword;\n"; +print "delete from help_relation;\n\n"; - ($c_name)=m|\@subsection (.+?)$|; - if (!($c_name eq "") && ! ($c_name =~ m/$cat_name/i)){ - ($cat_name)= $c_name; - new_category($cat_name); - next; +my @category_names= keys(%categories); +if (scalar(@category_names)) +{ + my $cat_name; + my $count= 0; + foreach $cat_name (@category_names) + { + $categories{$cat_name}->{__id__}= $count; + $count++; } - ($f_name)=m|\@findex (.+?)$|; - if (!($f_name eq "")){ - flush_all($mode); - ($func_name)= ($f_name); - $mode= "text"; - next; + my $header= "insert into help_category ". + "(help_category_id,name,parent_category_id) values "; + $count= 0; + foreach $cat_name (@category_names) + { + print_insert_header($count,$header); + my $parent_cat_name= $categories{$cat_name}->{__parent_category__}; + my $parent_cat_id= $parent_cat_name eq "" + ? "-1" : $categories{$parent_cat_name}->{__id__}; + print "($count,\"$cat_name\",$parent_cat_id)"; + $count++; } + printf ";\n\n"; +} - if ($_=~/\@example/ && ($mode eq "text")){ - $mode= "example"; - next; +my @topic_names= keys(%topics); +if (scalar(@topic_names)) +{ + my $header= "insert into help_topic ". + "(help_topic_id,help_category_id,name,description,example) values "; + my $topic_name; + my $count= 0; + foreach $topic_name (@topic_names) + { + print_insert_header($count,$header); + my $topic= $topics{$topic_name}; + print "($count,"; + print "$topic->{category}->{__id__},"; + print "\"$topic_name\","; + print "\"$topic->{description}\","; + print "\"$topic->{example}\")"; + $topics{$topic_name}->{__id__}= $count; + $count++; } + printf ";\n\n"; +} - if ($_=~/\@end example/ && ($mode eq "example")){ - flush_all($mode); - next; +my @keywords_names= keys(%keywords); +if (scalar(@keywords_names)) +{ + my $header= "insert into help_keyword (help_keyword_id,name) values "; + my $keyword_name; + my $count= 0; + foreach $keyword_name (@keywords_names) + { + print_insert_header($count,$header); + print "($count,\"$keyword_name\")"; + $count++; } - - if ($mode eq "text") { $text .= $_; } - if ($mode eq "example") { $example .= $_; } + printf ";\n\n"; + + $header= "insert into help_relation ". + "(help_topic_id,help_keyword_id) values "; + $count= 0; + my $count_keyword= 0; + foreach $keyword_name (@keywords_names) + { + my $topic_name; + foreach $topic_name (keys(%{$keywords{$keyword_name}})) + { + print_insert_header($count,$header); + print "($topics{$topic_name}->{__id__},$count_keyword)"; + $count++; + } + $count_keyword++; + } + printf ";\n\n"; } - - -print "DELETE help_category "; -print "FROM help_category "; -print "LEFT JOIN help_relation ON help_category.help_category_id=help_relation.help_category_id "; -print "WHERE help_relation.help_category_id is null;" diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh new file mode 100644 index 00000000000..c54394305cd --- /dev/null +++ b/scripts/mysql_create_system_tables.sh @@ -0,0 +1,311 @@ +#!/bin/sh + +# Copyright (C) 1997-2002 MySQL AB +# For a more info consult the file COPYRIGHT distributed with this file + +# This script writes on stdout SQL commands to generate all not +# existing MySQL system tables. It also replaces the help tables with +# new context from the manual (from fill_help_tables.sql). + +# $1 - "test" or "real" or "verbose" variant of database +# $2 - path to mysql-database directory +# $3 - hostname +# $4 - windows option + +if test x$1 = x"" ; +then + echo " +This script writes on stdout SQL commands to generate all not +existing MySQL system tables. It also replaces the help tables with +new context from the manual (from fill_help_tables.sql). + +Usage: + mysql_create_system_tables {help|real|verbose} <path to mysql-database directory> <hostname> <windows option> +"; + exit; +fi + +mdata=$2 +hostname=$3 +windows=$4 + +# Initialize variables +c_d="" i_d="" +c_h="" i_h="" +c_u="" i_u="" +c_f="" i_f="" +c_t="" c_c="" +c_ht="" +c_hc="" +c_hr="" +c_hk="" +i_ht="" + +# Check for old tables +if test ! -f $mdata/db.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing db table" 1>&2; + fi + + # mysqld --bootstrap wants one command/line + c_d="$c_d CREATE TABLE db (" + c_d="$c_d Host char(60) binary DEFAULT '' NOT NULL," + c_d="$c_d Db char(64) binary DEFAULT '' NOT NULL," + c_d="$c_d User char(16) binary DEFAULT '' NOT NULL," + c_d="$c_d Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d References_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d PRIMARY KEY Host (Host,Db,User)," + c_d="$c_d KEY User (User)" + c_d="$c_d )" + c_d="$c_d comment='Database privileges';" + + i_d="INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); + INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');" +fi + +if test ! -f $mdata/host.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing host table" 1>&2; + fi + + c_h="$c_h CREATE TABLE host (" + c_h="$c_h Host char(60) binary DEFAULT '' NOT NULL," + c_h="$c_h Db char(64) binary DEFAULT '' NOT NULL," + c_h="$c_h Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h References_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h PRIMARY KEY Host (Host,Db)" + c_h="$c_h )" + c_h="$c_h comment='Host privileges; Merged with database privileges';" +fi + +if test ! -f $mdata/user.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing user table" 1>&2; + fi + + c_u="$c_u CREATE TABLE user (" + c_u="$c_u Host char(60) binary DEFAULT '' NOT NULL," + c_u="$c_u User char(16) binary DEFAULT '' NOT NULL," + c_u="$c_u Password char(45) binary DEFAULT '' NOT NULL," + c_u="$c_u Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Process_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u File_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u References_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Super_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL," + c_u="$c_u ssl_cipher BLOB NOT NULL," + c_u="$c_u x509_issuer BLOB NOT NULL," + c_u="$c_u x509_subject BLOB NOT NULL," + c_u="$c_u max_questions int(11) unsigned DEFAULT 0 NOT NULL," + c_u="$c_u max_updates int(11) unsigned DEFAULT 0 NOT NULL," + c_u="$c_u max_connections int(11) unsigned DEFAULT 0 NOT NULL," + c_u="$c_u PRIMARY KEY Host (Host,User)" + c_u="$c_u )" + c_u="$c_u comment='Users and global privileges';" + + if test x$1 = x"test" + then + i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + REPLACE INTO user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + INSERT INTO user (host,user) values ('localhost',''); + INSERT INTO user (host,user) values ('$hostname','');" + else + i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + REPLACE INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + INSERT INTO user (host,user) values ('localhost','');" + if test "$windows" -eq 0 + then + i_u="$i_u + INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + REPLACE INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + INSERT INTO user (host,user) values ('$hostname','');" + fi + fi +fi + +if test ! -f $mdata/func.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing func table" 1>&2; + fi + + c_f="$c_f CREATE TABLE func (" + c_f="$c_f name char(64) binary DEFAULT '' NOT NULL," + c_f="$c_f ret tinyint(1) DEFAULT '0' NOT NULL," + c_f="$c_f dl char(128) DEFAULT '' NOT NULL," + c_f="$c_f type enum ('function','aggregate') NOT NULL," + c_f="$c_f PRIMARY KEY (name)" + c_f="$c_f )" + c_f="$c_f comment='User defined functions';" +fi + +if test ! -f $mdata/tables_priv.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing tables_priv table" 1>&2; + fi + + c_t="$c_t CREATE TABLE tables_priv (" + c_t="$c_t Host char(60) binary DEFAULT '' NOT NULL," + c_t="$c_t Db char(64) binary DEFAULT '' NOT NULL," + c_t="$c_t User char(16) binary DEFAULT '' NOT NULL," + c_t="$c_t Table_name char(60) binary DEFAULT '' NOT NULL," + c_t="$c_t Grantor char(77) DEFAULT '' NOT NULL," + c_t="$c_t Timestamp timestamp(14)," + c_t="$c_t Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL," + c_t="$c_t Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL," + c_t="$c_t PRIMARY KEY (Host,Db,User,Table_name)," + c_t="$c_t KEY Grantor (Grantor)" + c_t="$c_t )" + c_t="$c_t comment='Table privileges';" +fi + +if test ! -f $mdata/columns_priv.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing columns_priv table" 1>&2; + fi + + c_c="$c_c CREATE TABLE columns_priv (" + c_c="$c_c Host char(60) binary DEFAULT '' NOT NULL," + c_c="$c_c Db char(64) binary DEFAULT '' NOT NULL," + c_c="$c_c User char(16) binary DEFAULT '' NOT NULL," + c_c="$c_c Table_name char(64) binary DEFAULT '' NOT NULL," + c_c="$c_c Column_name char(64) binary DEFAULT '' NOT NULL," + c_c="$c_c Timestamp timestamp(14)," + c_c="$c_c Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL," + c_c="$c_c PRIMARY KEY (Host,Db,User,Table_name,Column_name)" + c_c="$c_c )" + c_c="$c_c comment='Column privileges';" +fi + +if test ! -f $mdata/help_topic.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing help_topic table" 1>&2; + fi + + c_ht="$c_ht CREATE TABLE help_topic (" + c_ht="$c_ht help_topic_id int unsigned not null," + c_ht="$c_ht name varchar(64) not null," + c_ht="$c_ht help_category_id smallint unsigned not null," + c_ht="$c_ht description text not null," + c_ht="$c_ht example text not null," + c_ht="$c_ht url varchar(128) not null," + c_ht="$c_ht primary key (help_topic_id)," + c_ht="$c_ht unique index (name)" + c_ht="$c_ht )" + c_ht="$c_ht comment='help topics';" +fi + +old_categories="yes" + +if test ! -f $mdata/help_category.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing help_category table" 1>&2; + fi + + c_hc="$c_hc CREATE TABLE help_category (" + c_hc="$c_hc help_category_id smallint unsigned not null," + c_hc="$c_hc name varchar(64) not null," + c_hc="$c_hc parent_category_id smallint unsigned null," + c_hc="$c_hc url varchar(128) not null," + c_hc="$c_hc primary key (help_category_id)," + c_hc="$c_hc unique index (name)" + c_hc="$c_hc )" + c_hc="$c_hc comment='help categories';" +fi + +if test ! -f $mdata/help_keyword.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing help_keyword table" 1>&2; + fi + + c_hk="$c_hk CREATE TABLE help_keyword (" + c_hk="$c_hk help_keyword_id int unsigned not null," + c_hk="$c_hk name varchar(64) not null," + c_hk="$c_hk primary key (help_keyword_id)," + c_hk="$c_hk unique index (name)" + c_hk="$c_hk )" + c_hk="$c_hk comment='help keywords';" +fi + +if test ! -f $mdata/help_relation.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing help_relation table" 1>&2; + fi + + c_hr="$c_hr CREATE TABLE help_relation (" + c_hr="$c_hr help_topic_id int unsigned not null references help_topic," + c_hr="$c_hr help_keyword_id int unsigned not null references help_keyword," + c_hr="$c_hr primary key (help_keyword_id, help_topic_id)" + c_hr="$c_hr )" + c_hr="$c_hr comment='keyword-topic relation';" +fi + +cat << END_OF_DATA +use mysql; +$c_d +$i_d + +$c_h +$i_h + +$c_u +$i_u + +$c_f +$i_f + +$c_t +$c_c + +$c_ht +$c_hc +$c_hr +$c_hk +END_OF_DATA + diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 15bc834e850..96e33d3e7c5 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -87,7 +87,7 @@ if test -z "$basedir" then basedir=@prefix@ bindir=@bindir@ - execdir=@libexecdir@ + execdir=@libexecdir@ pkgdatadir=@pkgdatadir@ else bindir="$basedir/bin" @@ -100,24 +100,24 @@ else else execdir="$basedir/bin" fi - - # find fill_help_tables.sh - for i in $basedir/support-files $basedir/share $basedir/share/mysql $basedir/scripts @pkgdatadir@ - do - if test -f $i/fill_help_tables.sql - then - pkgdatadir=$i - fi - done fi +# find fill_help_tables.sh +for i in $basedir/support-files $basedir/share $basedir/share/mysql $basedir/scripts `pwd` @pkgdatadir@ +do + if test -f $i/fill_help_tables.sql + then + pkgdatadir=$i + fi +done + if test -f $pkgdatadir/fill_help_tables.sql then fill_help_tables=$pkgdatadir/fill_help_tables.sql else if test $verbose -eq 1 then - echo "Could not find help file 'fill_help_tables.sql'". + echo "Could not find help file 'fill_help_tables.sql' ;$pkgdatadir; ;$basedir;". fi fi @@ -172,205 +172,21 @@ fi chown $user $ldata $ldata/mysql $ldata/test; fi -# Initialize variables -c_d="" i_d="" -c_h="" i_h="" -c_u="" i_u="" -c_f="" i_f="" -c_t="" c_c="" - -# Check for old tables if test ! -f $mdata/db.frm then - if test $verbose -eq 1 ; then - echo "Preparing db table" - fi - # mysqld --bootstrap wants one command/line - c_d="$c_d CREATE TABLE db (" - c_d="$c_d Host char(60) binary DEFAULT '' NOT NULL," - c_d="$c_d Db char(64) binary DEFAULT '' NOT NULL," - c_d="$c_d User char(16) binary DEFAULT '' NOT NULL," - c_d="$c_d Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d References_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d PRIMARY KEY Host (Host,Db,User)," - c_d="$c_d KEY User (User)" - c_d="$c_d )" - c_d="$c_d comment='Database privileges';" - - i_d="INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); - INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');" -fi - -if test ! -f $mdata/host.frm -then - if test $verbose -eq 1 ; then - echo "Preparing host table" - fi - - c_h="$c_h CREATE TABLE host (" - c_h="$c_h Host char(60) binary DEFAULT '' NOT NULL," - c_h="$c_h Db char(64) binary DEFAULT '' NOT NULL," - c_h="$c_h Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h References_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h PRIMARY KEY Host (Host,Db)" - c_h="$c_h )" - c_h="$c_h comment='Host privileges; Merged with database privileges';" + c_d="yes" fi -if test ! -f $mdata/user.frm +if test $verbose -eq 1 then - if test $verbose -eq 1 ; then - echo "Preparing user table" - fi - - c_u="$c_u CREATE TABLE user (" - c_u="$c_u Host char(60) binary DEFAULT '' NOT NULL," - c_u="$c_u User char(16) binary DEFAULT '' NOT NULL," - c_u="$c_u Password char(45) binary DEFAULT '' NOT NULL," - c_u="$c_u Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Process_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u File_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u References_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Super_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL," - c_u="$c_u ssl_cipher BLOB NOT NULL," - c_u="$c_u x509_issuer BLOB NOT NULL," - c_u="$c_u x509_subject BLOB NOT NULL," - c_u="$c_u max_questions int(11) unsigned DEFAULT 0 NOT NULL," - c_u="$c_u max_updates int(11) unsigned DEFAULT 0 NOT NULL," - c_u="$c_u max_connections int(11) unsigned DEFAULT 0 NOT NULL," - c_u="$c_u PRIMARY KEY Host (Host,User)" - c_u="$c_u )" - c_u="$c_u comment='Users and global privileges';" - - i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - - REPLACE INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - - INSERT INTO user (host,user) values ('localhost',''); -" - - if test "$windows" -eq 0 - then - i_u="$i_u INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - - REPLACE INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - - INSERT INTO user (host,user) values ('$hostname','');" - fi -fi - -if test ! -f $mdata/func.frm -then - if test $verbose -eq 1 ; then - echo "Preparing func table" - fi - - c_f="$c_f CREATE TABLE func (" - c_f="$c_f name char(64) binary DEFAULT '' NOT NULL," - c_f="$c_f ret tinyint(1) DEFAULT '0' NOT NULL," - c_f="$c_f dl char(128) DEFAULT '' NOT NULL," - c_f="$c_f type enum ('function','aggregate') NOT NULL," - c_f="$c_f PRIMARY KEY (name)" - c_f="$c_f )" - c_f="$c_f comment='User defined functions';" -fi - -if test ! -f $mdata/tables_priv.frm -then - if test $verbose -eq 1 ; then - echo "Preparing tables_priv table" - fi - - c_t="$c_t CREATE TABLE tables_priv (" - c_t="$c_t Host char(60) binary DEFAULT '' NOT NULL," - c_t="$c_t Db char(64) binary DEFAULT '' NOT NULL," - c_t="$c_t User char(16) binary DEFAULT '' NOT NULL," - c_t="$c_t Table_name char(60) binary DEFAULT '' NOT NULL," - c_t="$c_t Grantor char(77) DEFAULT '' NOT NULL," - c_t="$c_t Timestamp timestamp(14)," - c_t="$c_t Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL," - c_t="$c_t Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL," - c_t="$c_t PRIMARY KEY (Host,Db,User,Table_name)," - c_t="$c_t KEY Grantor (Grantor)" - c_t="$c_t )" - c_t="$c_t comment='Table privileges';" -fi - -if test ! -f $mdata/columns_priv.frm -then - if test $verbose -eq 1 ; then - echo "Preparing columns_priv table" - fi - - c_c="$c_c CREATE TABLE columns_priv (" - c_c="$c_c Host char(60) binary DEFAULT '' NOT NULL," - c_c="$c_c Db char(64) binary DEFAULT '' NOT NULL," - c_c="$c_c User char(16) binary DEFAULT '' NOT NULL," - c_c="$c_c Table_name char(64) binary DEFAULT '' NOT NULL," - c_c="$c_c Column_name char(64) binary DEFAULT '' NOT NULL," - c_c="$c_c Timestamp timestamp(14)," - c_c="$c_c Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL," - c_c="$c_c PRIMARY KEY (Host,Db,User,Table_name,Column_name)" - c_c="$c_c )" - c_c="$c_c comment='Column privileges';" + create_option="verbose" +else + create_option="real" fi -echo "Installing privilege tables" +echo "Installing all prepared tables" if ( - cat << END_OF_DATA -use mysql; -$c_d -$i_d - -$c_h -$i_h - -$c_u -$i_u - -$c_f -$i_f - -$c_t -$c_c -END_OF_DATA + mysql_create_system_tables $create_option $mdata $hostname $windows if test -n "$fill_help_tables" then cat $fill_help_tables diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 712c8853a20..a59f1d4b81a 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -877,6 +877,7 @@ bool check_db_name(char *db); bool check_column_name(const char *name); bool check_table_name(const char *name, uint length); char *get_field(MEM_ROOT *mem, Field *field); +bool get_field(MEM_ROOT *mem, Field *field, class String *res); int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr); /* from hostname.cc */ diff --git a/sql/protocol.h b/sql/protocol.h index 2110f1877c2..ffd61b3e848 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -60,6 +60,8 @@ public: { return store_longlong((longlong) from, 0); } inline bool store(ulonglong from) { return store_longlong((longlong) from, 1); } + inline bool store(String *str) + { return store(str->c_ptr(),str->length(),str->charset()); } virtual bool prepare_for_send(List<Item> *item_list) { diff --git a/sql/sql_help.cc b/sql/sql_help.cc index 36c7ef87b17..a9b89a728d2 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -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, - ¬_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, + ¬_used, TRUE))) + DBUG_RETURN(1); } - return 0; + DBUG_RETURN(0); } +/* + + 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) -#define help_charset &my_charset_latin1 + 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 -*/ - -int send_variant_2_list(Protocol *protocol, List<char> *names, - const char *cat) -{ - 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); -} + # number of topics found + names array of name of found topics (out) -/* - Look for all topics of category + name name of found topic (out) + description description of found topic (out) + example example for found topic (out) - 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 + 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 get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations, - struct st_find_field *find_fields, - int16 cat_id, List<char> *res) +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) { - 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)) - { - res= -1; + if (send_header_2(protocol,false)) 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()))) + } + 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 + else { - if (send_header_2(protocol)) + 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; - 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); } diff --git a/sql/table.cc b/sql/table.cc index 3aed75c7ac6..908d6807450 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1161,6 +1161,33 @@ rename_file_ext(const char * from,const char * to,const char * ext) /* + Allocate string field in MEM_ROOT and return it as String + + SYNOPSIS + get_field() + mem MEM_ROOT for allocating + field Field for retrieving of string + res result String + + RETURN VALUES + true string is empty + false all ok +*/ + +bool get_field(MEM_ROOT *mem, Field *field, String *res) +{ + char buff[MAX_FIELD_WIDTH]; + String str(buff,sizeof(buff),&my_charset_bin); + field->val_str(&str,&str); + uint length=str.length(); + if (!length) + return true; + char *to= strmake_root(mem, str.ptr(), length); + res->set(to,length,((Field_str*)field)->charset()); + return false; +} + +/* Allocate string field in MEM_ROOT and return it as NULL-terminated string SYNOPSIS |