Loading Docs/manual.texi +116 −23 Original line number Diff line number Diff line Loading @@ -633,6 +633,7 @@ Examples of Common Queries * example-user-variables:: Using user variables * example-Foreign keys:: Using foreign keys * Searching on two keys:: * Calculating days:: Queries from Twin Project Loading Loading @@ -16551,6 +16552,7 @@ mysql> select 2 > 2; -> 0 @end example @cindex @code{NULL}, testing for null @findex <=> (Equal to) @item <=> Null safe equal: Loading @@ -16559,6 +16561,7 @@ mysql> select 1 <=> 1, NULL <=> NULL, 1 <=> NULL; -> 1 1 0 @end example @cindex @code{NULL}, testing for null @findex IS NULL @findex IS NOT NULL @item IS NULL Loading Loading @@ -16643,6 +16646,7 @@ mysql> select ISNULL(1/0); Note that a comparison of @code{NULL} values using @code{=} will always be false! @cindex @code{NULL}, testing for null @findex COALESCE() @item COALESCE(list) Returns first non-@code{NULL} element in list: Loading Loading @@ -16860,6 +16864,7 @@ make string comparison even more flexible. @subsection Control Flow Functions @table @code @cindex @code{NULL}, testing for null @findex IFNULL() @item IFNULL(expr1,expr2) If @code{expr1} is not @code{NULL}, @code{IFNULL()} returns @code{expr1}, Loading Loading @@ -17136,10 +17141,13 @@ mysql> select SQRT(20); @findex PI() @item PI() Returns the value of PI: Returns the value of PI. The default shown number of decimals is 5, but @strong{MySQL} internally uses the full double precession for PI. @example mysql> select PI(); -> 3.141593 mysql> SELECT PI()+0.000000000000000000; -> 3.141592653589793116 @end example @findex COS() Loading Loading @@ -19268,7 +19276,7 @@ The options work for all table types, if not otherwise indicated: @item @code{PACK_KEYS} @tab Set this to 1 if you want to have a smaller index. This usually makes updates slower and reads faster (MyISAM, ISAM). @item @code{PASSWORD} @tab Encrypt the @code{.frm} file with a password. This option doesn't do anything in the standard @strong{MySQL} version. @item @code{DELAY_KEY_WRITE} @tab Set this to 1 if want to delay key table updates until the table is closed (MyISAM). @item @code{ROW_FORMAT} @tab Defines how the rows should be stored (for the future). @item @code{ROW_FORMAT} @tab Defines how the rows should be stored. Currently you can only use the DYNAMIC and STATIC options for MyISAM tables. @end multitable When you use a @code{MyISAM} table, @strong{MySQL} uses the product of Loading Loading @@ -19461,9 +19469,8 @@ normally do @code{ALTER TABLE} that often this isn't that high on our TODO. @itemize @bullet @item To use @code{ALTER TABLE}, you need @strong{select}, @strong{insert}, @strong{delete}, @strong{update}, @strong{create}, and @strong{drop} privileges on the table. To use @code{ALTER TABLE}, you need @strong{ALTER}, @strong{INSERT}, and @strong{CREATE} privileges on the table. @item @code{IGNORE} is a @strong{MySQL} extension to ANSI SQL92. Loading Loading @@ -19553,7 +19560,7 @@ assigns a default value, as described in @findex DROP INDEX @item @code{DROP INDEX} removes an index. This is a @strong{MySQL} extension to ANSI SQL92. ANSI SQL92. @xref{DROP INDEX}. @item If columns are dropped from a table, the columns are also removed from any Loading Loading @@ -20527,6 +20534,8 @@ or INSERT [LOW_PRIORITY | DELAYED] [IGNORE] or INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] tbl_name SET col_name=expression, col_name=expression, ... or INSERT [LOW_PRIORITY] [IGNORE] [INTO] tbl_name SELECT ... @end example Loading Loading @@ -22289,8 +22298,8 @@ tables to use the slower key cache method to create the index. @strong{NOTE} that this parameter is given in megabytes! @item @code{myisam_max_sort_file_size} The maximum size of the temporary file @strong{MySQL} is allowed to create to while recreating the index (during @code{REPAIR}, @code{ALTER TABLE} The maximum size of the temporary file @strong{MySQL} is allowed to use while recreating the index (during @code{REPAIR}, @code{ALTER TABLE} or @code{LOAD DATA INFILE}. If the file size would be bigger than this, the index will be created through the key cache (which is slower). @strong{NOTE} that this parameter is given in megabytes! Loading Loading @@ -22605,8 +22614,23 @@ combination after it has found the first matching row. @item Not exists @strong{MySQL} was able to do a @code{LEFT JOIN} optimization on the query and will not examine more rows in this table for a row combination after it finds one row that matches the @code{LEFT JOIN} criteria. query and will not examine more rows in this table for the previous row combination after it finds one row that matches the @code{LEFT JOIN} criteria. Here is an example for this: @example SELECT * FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL; @end example Assume that @code{t2.id} is defined with @code{NOT NULL}. In this case @strong{MySQL} will scan @code{t1} and look up the rows in @code{t2} through @code{t1.id}. If @strong{MySQL} finds a matching row in @code{t2}, it knows that @code{t2.id} can never be @code{NULL}, and will not scan through the rest of the rows in @code{t2} that has the same @code{id}. In other words, for each row in @code{t1}, @strong{MySQL} only needs to do a single lookup in @code{t2}, independent of how many matching rows there are in @code{t2}. @item @code{range checked for each record (index map: #)} @strong{MySQL} didn't find a real good index to use. It will, instead, for Loading Loading @@ -22863,6 +22887,9 @@ the @code{FROM} clause. @{DESCRIBE | DESC@} tbl_name @{col_name | wild@} @end example @code{DESCRIBE} is a shortcut for @code{SHOW COLUMNS FROM}. @xref{SHOW DATABASE INFO}. @code{DESCRIBE} provides information about a table's columns. @code{col_name} may be a column name or a string containing the SQL @samp{%} and @samp{_} wild-card characters. Loading Loading @@ -22954,6 +22981,18 @@ are locked by the current thread are automatically unlocked when the thread issues another @code{LOCK TABLES}, or when the connection to the server is closed. The main reasons to use @code{LOCK TABLES} are: @itemize @bullet @item Emulate transactions with not transaction safe tables. @item To get more speed with @code{MyISAM} tables when inserting/updating data over many statements. The main reason this gives more speed is that @strong{MySQL} will not flush the key cache for the locked tables until @code{UNLOCK TABLES} is called. @end itemize If a thread obtains a @code{READ} lock on a table, that thread (and all other threads) can only read from the table. If a thread obtains a @code{WRITE} lock on a table, then only the thread holding the lock can @code{READ} from Loading Loading @@ -24519,7 +24558,7 @@ mysql> ALTER TABLE tbl_name TYPE = MYISAM; @end example @cindex tables, @code{HEAP} @node HEAP, BDB, ISAM, Table types @node HEAP, InnoDB, ISAM, Table types @section HEAP Tables @code{HEAP} tables use a hashed index and are stored in memory. This Loading Loading @@ -24596,7 +24635,7 @@ SUM_OVER_ALL_KEYS(max_length_of_key + sizeof(char*) * 2) @code{sizeof(char*)} is 4 on 32-bit machines and 8 on 64-bit machines. @node InnoDB, , GEMINI, Table types @node InnoDB, BDB, HEAP, Table types @section InnoDB Tables @menu Loading Loading @@ -25897,7 +25936,7 @@ Finland @cindex tables, @code{BDB} @cindex tables, @code{Berkeley DB} @node BDB, GEMINI, HEAP, Table types @node BDB, GEMINI, InnoDB, Table types @section BDB or Berkeley_DB Tables @menu Loading Loading @@ -26183,7 +26222,7 @@ not trivial). @end itemize @cindex GEMINI tables @node GEMINI, InnoDB, BDB, Table types @node GEMINI, , BDB, Table types @section GEMINI Tables @cindex GEMINI tables, overview Loading Loading @@ -28800,6 +28839,7 @@ mysql> SELECT * FROM shop; * example-user-variables:: Using user variables * example-Foreign keys:: Using foreign keys * Searching on two keys:: * Calculating days:: @end menu @node example-Maximum-column, example-Maximum-row, Examples, Examples Loading Loading @@ -29056,7 +29096,7 @@ SELECT s.* FROM persons p, shirts s @findex UNION @cindex searching, two keys @cindex keys, searching on two @node Searching on two keys, , example-Foreign keys, Examples @node Searching on two keys, Calculating days, example-Foreign keys, Examples @subsection Searching on Two Keys @strong{MySQL} doesn't yet optimize when you search on two different Loading Loading @@ -29088,6 +29128,35 @@ DROP TABLE tmp; The above way to solve this query is in effect an @code{UNION} of two queries. @cindex bit_functions, example @findex BIT_OR @findex BIT_COUNT @findex << @node Calculating days, , Searching on two keys, Examples @subsection Calculating visits per day The following shows an idea of how you can use the bit group functions to calculate the number of days per month a user has visited a web page. @example CREATE TABLE t1 (year YEAR(4), month INT(2) UNSIGNED ZEROFILL, day INT(2) UNSIGNED ZEROFILL); INSERT INTO t1 VALUES(2000,1,1),(2000,1,20),(2000,1,30),(2000,2,2),(2000,2,23),(2000,2,23); SELECT year,month,BIT_COUNT(BIT_OR(1<<day)) AS days FROM t1 GROUP BY year,month; Which returns: +------+-------+------+ | year | month | days | +------+-------+------+ | 2000 | 01 | 3 | | 2000 | 02 | 2 | +------+-------+------+ @end example The above calculates how many different days was used for a given year/month combination, with automatic removal of duplicate entries. @cindex modes, batch @cindex batch mode @cindex running, batch mode Loading Loading @@ -30911,10 +30980,13 @@ unless you know what you are doing! @itemize @item Minimal length of word to be indexed is defined by @strong{MySQL} variable @code{ft_min_word_length}. @xref{SHOW VARIABLES}. Change it to the value you prefer, and rebuild your @code{FULLTEXT} indexes (e.g. with @code{OPTIMIZE TABLE}). Minimal length of word to be indexed is defined in @code{myisam/ftdefs.h} file by the line @example #define MIN_WORD_LEN 4 @end example Change it to the value you prefer, recompile @strong{MySQL}, and rebuild your @code{FULLTEXT} indexes. @item The stopword list is defined in @code{myisam/ft_static.c} Loading Loading @@ -30980,6 +31052,9 @@ index operations (querying/dumping/statistics). @itemize @bullet @item Make all operations with @code{FULLTEXT} index @strong{faster}. @item Support for braces @code{()} in boolean full-text search. @item Phrase search, proximity operators @item Boolean search can work without @code{FULLTEXT} index (yes, @strong{very} slow). @item Support for "always-index words". They could be any strings the user wants to treat as words, examples are "C++", "AS/400", "TCP/IP", etc. @item Support for full-text search in @code{MERGE} tables. Loading Loading @@ -52004,7 +52079,19 @@ structure. Don't allow more than a defined number of threads to run MyISAM recover at the same time. @item Change @code{INSERT ... SELECT} to use concurrent inserts. Change @code{INSERT ... SELECT} to optionally use concurrent inserts. @item Implement @code{RENAME DATABASE}. To make this safe for all table handlers, it should work as follows: @itemize @bullet @item Create the new database. @item For every table do a rename of the table to another database, as we do with the @code{RENAME} command. @item Drop the old database. @end itemize @item Return the original field types() when doing @code{SELECT MIN(column) ... GROUP BY}. Loading Loading @@ -52051,6 +52138,8 @@ a concurrent insert at the end of the file if the file is read-locked. @item Remember @code{FOREIGN} key definitions in the @file{.frm} file. @item Cascading @code{DELETE} @item Server side cursors. @item Check if @code{lockd} works with modern Linux kernels; If not, we have Loading @@ -52060,6 +52149,13 @@ give any errors if @code{lockd} works. @item Allow SQL variables in @code{LIMIT}, like in @code{LIMIT @@a,@@b}. @item Allow update of variables in @code{UPDATE} statements. For example: @code{UPDATE TABLE foo SET @@a=a+b,a=@@a, b=@@a+c} @item Change when user variables are updated so that one can use them with @code{GROUP BY}, as in the following example: @code{SELECT id, @@a:=count(*), sum(sum_col)/@@a FROM table_name GROUP BY id}. @item Don't add automatic @code{DEFAULT} values to columns. Give an error when using an @code{INSERT} that doesn't contain a column that doesn't have a @code{DEFAULT}. Loading Loading @@ -52198,9 +52294,6 @@ Change that @code{ALTER TABLE} doesn't abort clients that executes Fix that when columns referenced in an @code{UPDATE} clause contains the old values before the update started. @item Allow update of variables in @code{UPDATE} statements. For example: @code{UPDATE TABLE foo SET @@a=a+b,a=@@a, b=@@a+c} @item @code{myisamchk}, @code{REPAIR} and @code{OPTIMIZE TABLE} should be able to handle cases where the data and/or index files are symbolic links. @item sql/slave.cc +1 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ #define RPL_LOG_NAME (glob_mi.log_file_name[0] ? glob_mi.log_file_name :\ "FIRST") bool slave_running = 0; volatile bool slave_running = 0; pthread_t slave_real_id; MASTER_INFO glob_mi; HASH replicate_do_table, replicate_ignore_table; Loading sql/slave.h +1 −2 Original line number Diff line number Diff line Loading @@ -98,8 +98,7 @@ int init_master_info(MASTER_INFO* mi); void end_master_info(MASTER_INFO* mi); extern bool opt_log_slave_updates ; pthread_handler_decl(handle_slave,arg); extern bool volatile abort_loop, abort_slave; extern bool slave_running; extern bool volatile abort_loop, abort_slave, slave_running; extern uint32 slave_skip_counter; // needed for problems when slave stops and // we want to restart it skipping one or more events in the master log that Loading sql/sql_base.cc +86 −91 Original line number Diff line number Diff line Loading @@ -34,6 +34,8 @@ HASH open_cache; /* Used by mysql_test */ static int open_unireg_entry(THD *thd,TABLE *entry,const char *db, const char *name, const char *alias, bool locked); static bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, const char *table_name, List_iterator<Item> *it); static void free_cache_entry(TABLE *entry); static void mysql_rm_tmp_tables(void); static key_map get_key_map_from_key_list(TABLE *table, Loading Loading @@ -109,71 +111,75 @@ static void check_unused(void) #define check_unused() #endif OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild) int list_open_tables(THD *thd,List<char> *tables, const char *db, const char *wild) { int result = 0; uint col_access=thd->col_access; OPEN_TABLE_LIST **start_list, *open_list; TABLE_LIST table_list; char name[NAME_LEN*2]; DBUG_ENTER("list_open_tables"); VOID(pthread_mutex_lock(&LOCK_open)); bzero((char*) &table_list,sizeof(table_list)); start_list= &open_list; open_list=0; for (uint idx=0 ; result == 0 && idx < open_cache.records; idx++) for (uint idx=0 ; idx < open_cache.records; idx++) { OPEN_TABLE_LIST *table; TABLE *entry=(TABLE*) hash_element(&open_cache,idx); if ((!entry->real_name)) continue; // Shouldn't happen if (wild) if ((!entry->real_name) || strcmp(entry->table_cache_key,db)) continue; if (wild && wild[0] && wild_compare(entry->real_name,wild)) continue; if (db && !(col_access & TABLE_ACLS)) { strxmov(name,entry->table_cache_key,".",entry->real_name,NullS); if (wild_compare(name,wild)) table_list.db= (char*) db; table_list.real_name= entry->real_name;/*real name*/ table_list.grant.privilege=col_access; if (check_grant(thd,TABLE_ACLS,&table_list,1)) continue; } /* need to check if he have't already listed it */ /* Check if user has SELECT privilege for any column in the table */ table_list.db= (char*) entry->table_cache_key; table_list.real_name= entry->real_name; table_list.grant.privilege=0; if (check_table_access(thd,SELECT_ACL | EXTRA_ACL,&table_list)) continue; /* need to check if we haven't already listed it */ for (table= open_list ; table ; table=table->next) { if (!strcmp(table->table,entry->real_name) && !strcmp(table->db,entry->table_cache_key)) List_iterator<char> it(*tables); char *table_name; int check = 0; while (check == 0 && (table_name=it++)) { if (entry->in_use) table->in_use++; if (entry->locked_by_name) table->locked++; break; if (!strcmp(table_name,entry->real_name)) check++; } } if (table) if (check) continue; if (!(*start_list = (OPEN_TABLE_LIST *) sql_alloc(sizeof(OPEN_TABLE_LIST)+entry->key_length))) if (tables->push_back(thd->strdup(entry->real_name))) { open_list=0; // Out of memory result = -1; break; } (*start_list)->table=(strmov((*start_list)->db=(char*) ((*start_list)+1), entry->table_cache_key)+1, entry->real_name); (*start_list)->in_use= entry->in_use ? 1 : 0; (*start_list)->locked= entry->locked_by_name ? 1 : 0; start_list= &(*start_list)->next; } VOID(pthread_mutex_unlock(&LOCK_open)); DBUG_RETURN(open_list); DBUG_RETURN(result); } char* query_table_status(THD *thd,const char *db,const char *table_name) { int cached = 0, in_use = 0; char info[256]; for (uint idx=0 ; idx < open_cache.records; idx++) { TABLE *entry=(TABLE*) hash_element(&open_cache,idx); if (strcmp(entry->table_cache_key,db) || strcmp(entry->real_name,table_name)) continue; cached++; if (entry->in_use) in_use++; } sprintf(info, "cached=%d, in_use=%d", cached, in_use); return thd->strdup(info); } Loading Loading @@ -253,7 +259,7 @@ send_fields(THD *thd,List<Item> &list,uint flag) if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length())) break; /* purecov: inspected */ } send_eof(&thd->net); send_eof(&thd->net,(test_flags & TEST_MIT_THREAD) ? 0: 1); return 0; err: send_error(&thd->net,ER_OUT_OF_RESOURCES); /* purecov: inspected */ Loading Loading @@ -424,34 +430,9 @@ void close_thread_tables(THD *thd, bool locked) DBUG_PRINT("info", ("thd->open_tables=%p", thd->open_tables)); while (thd->open_tables) found_old_table|=close_thread_table(thd, &thd->open_tables); /* Free tables to hold down open files */ while (open_cache.records > table_cache_size && unused_tables) VOID(hash_delete(&open_cache,(byte*) unused_tables)); /* purecov: tested */ check_unused(); if (found_old_table) { /* Tell threads waiting for refresh that something has happened */ VOID(pthread_cond_broadcast(&COND_refresh)); } if (!locked) VOID(pthread_mutex_unlock(&LOCK_open)); /* VOID(pthread_sigmask(SIG_SETMASK,&thd->signals,NULL)); */ DBUG_VOID_RETURN; } /* move one table to free list */ bool close_thread_table(THD *thd, TABLE **table_ptr) for (table=thd->open_tables ; table ; table=next) { DBUG_ENTER("close_thread_table"); bool found_old_table=0; TABLE *table=*table_ptr; *table_ptr=table->next; next=table->next; if (table->version != refresh_version || thd->version != refresh_version || !table->db_stat) { Loading Loading @@ -481,7 +462,21 @@ bool close_thread_table(THD *thd, TABLE **table_ptr) else unused_tables=table->next=table->prev=table; } DBUG_RETURN(found_old_table); } thd->open_tables=0; /* Free tables to hold down open files */ while (open_cache.records > table_cache_size && unused_tables) VOID(hash_delete(&open_cache,(byte*) unused_tables)); /* purecov: tested */ check_unused(); if (found_old_table) { /* Tell threads waiting for refresh that something has happened */ VOID(pthread_cond_broadcast(&COND_refresh)); } if (!locked) VOID(pthread_mutex_unlock(&LOCK_open)); /* VOID(pthread_sigmask(SIG_SETMASK,&thd->signals,NULL)); */ DBUG_VOID_RETURN; } /* Close and delete temporary tables */ Loading Loading @@ -1837,7 +1832,7 @@ static key_map get_key_map_from_key_list(TABLE *table, ** Returns pointer to last inserted field if ok ****************************************************************************/ bool static bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, const char *table_name, List_iterator<Item> *it) { Loading sql/sql_show.cc +17 −13 Original line number Diff line number Diff line Loading @@ -95,34 +95,38 @@ mysqld_show_dbs(THD *thd,const char *wild) ** List all open tables in a database ***************************************************************************/ int mysqld_show_open_tables(THD *thd,const char *wild) int mysqld_show_open_tables(THD *thd,const char *db,const char *wild) { Item_string *field=new Item_string("",0); List<Item> field_list; OPEN_TABLE_LIST *open_list; CONVERT *convert=thd->convert_set; char *end,*table_name; List<char> tables; DBUG_ENTER("mysqld_show_open_tables"); field_list.push_back(new Item_empty_string("Database",NAME_LEN)); field_list.push_back(new Item_empty_string("Table",NAME_LEN)); field_list.push_back(new Item_int("In_use",0, 4)); field_list.push_back(new Item_int("Name_locked",0, 4)); field->name=(char*) thd->alloc(20+(uint) strlen(db)+(wild ? (uint) strlen(wild)+4:0)); end=strxmov(field->name,"Open_tables_in_",db,NullS); if (wild && wild[0]) strxmov(end," (",wild,")",NullS); field->max_length=NAME_LEN; field_list.push_back(field); field_list.push_back(new Item_empty_string("Comment",80)); if (send_fields(thd,field_list,1)) DBUG_RETURN(1); if (!(open_list=list_open_tables(thd,wild))) if (list_open_tables(thd,&tables,db,wild)) DBUG_RETURN(-1); for ( ; open_list ; open_list=open_list->next) List_iterator<char> it(tables); while ((table_name=it++)) { thd->packet.length(0); net_store_data(&thd->packet,convert, open_list->db); net_store_data(&thd->packet,convert, open_list->table); net_store_data(&thd->packet,open_list->in_use); net_store_data(&thd->packet,open_list->locked); net_store_data(&thd->packet,table_name); net_store_data(&thd->packet,query_table_status(thd,db,table_name)); if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length())) DBUG_RETURN(-1); } send_eof(&thd->net); DBUG_RETURN(0); } Loading Loading
Docs/manual.texi +116 −23 Original line number Diff line number Diff line Loading @@ -633,6 +633,7 @@ Examples of Common Queries * example-user-variables:: Using user variables * example-Foreign keys:: Using foreign keys * Searching on two keys:: * Calculating days:: Queries from Twin Project Loading Loading @@ -16551,6 +16552,7 @@ mysql> select 2 > 2; -> 0 @end example @cindex @code{NULL}, testing for null @findex <=> (Equal to) @item <=> Null safe equal: Loading @@ -16559,6 +16561,7 @@ mysql> select 1 <=> 1, NULL <=> NULL, 1 <=> NULL; -> 1 1 0 @end example @cindex @code{NULL}, testing for null @findex IS NULL @findex IS NOT NULL @item IS NULL Loading Loading @@ -16643,6 +16646,7 @@ mysql> select ISNULL(1/0); Note that a comparison of @code{NULL} values using @code{=} will always be false! @cindex @code{NULL}, testing for null @findex COALESCE() @item COALESCE(list) Returns first non-@code{NULL} element in list: Loading Loading @@ -16860,6 +16864,7 @@ make string comparison even more flexible. @subsection Control Flow Functions @table @code @cindex @code{NULL}, testing for null @findex IFNULL() @item IFNULL(expr1,expr2) If @code{expr1} is not @code{NULL}, @code{IFNULL()} returns @code{expr1}, Loading Loading @@ -17136,10 +17141,13 @@ mysql> select SQRT(20); @findex PI() @item PI() Returns the value of PI: Returns the value of PI. The default shown number of decimals is 5, but @strong{MySQL} internally uses the full double precession for PI. @example mysql> select PI(); -> 3.141593 mysql> SELECT PI()+0.000000000000000000; -> 3.141592653589793116 @end example @findex COS() Loading Loading @@ -19268,7 +19276,7 @@ The options work for all table types, if not otherwise indicated: @item @code{PACK_KEYS} @tab Set this to 1 if you want to have a smaller index. This usually makes updates slower and reads faster (MyISAM, ISAM). @item @code{PASSWORD} @tab Encrypt the @code{.frm} file with a password. This option doesn't do anything in the standard @strong{MySQL} version. @item @code{DELAY_KEY_WRITE} @tab Set this to 1 if want to delay key table updates until the table is closed (MyISAM). @item @code{ROW_FORMAT} @tab Defines how the rows should be stored (for the future). @item @code{ROW_FORMAT} @tab Defines how the rows should be stored. Currently you can only use the DYNAMIC and STATIC options for MyISAM tables. @end multitable When you use a @code{MyISAM} table, @strong{MySQL} uses the product of Loading Loading @@ -19461,9 +19469,8 @@ normally do @code{ALTER TABLE} that often this isn't that high on our TODO. @itemize @bullet @item To use @code{ALTER TABLE}, you need @strong{select}, @strong{insert}, @strong{delete}, @strong{update}, @strong{create}, and @strong{drop} privileges on the table. To use @code{ALTER TABLE}, you need @strong{ALTER}, @strong{INSERT}, and @strong{CREATE} privileges on the table. @item @code{IGNORE} is a @strong{MySQL} extension to ANSI SQL92. Loading Loading @@ -19553,7 +19560,7 @@ assigns a default value, as described in @findex DROP INDEX @item @code{DROP INDEX} removes an index. This is a @strong{MySQL} extension to ANSI SQL92. ANSI SQL92. @xref{DROP INDEX}. @item If columns are dropped from a table, the columns are also removed from any Loading Loading @@ -20527,6 +20534,8 @@ or INSERT [LOW_PRIORITY | DELAYED] [IGNORE] or INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] tbl_name SET col_name=expression, col_name=expression, ... or INSERT [LOW_PRIORITY] [IGNORE] [INTO] tbl_name SELECT ... @end example Loading Loading @@ -22289,8 +22298,8 @@ tables to use the slower key cache method to create the index. @strong{NOTE} that this parameter is given in megabytes! @item @code{myisam_max_sort_file_size} The maximum size of the temporary file @strong{MySQL} is allowed to create to while recreating the index (during @code{REPAIR}, @code{ALTER TABLE} The maximum size of the temporary file @strong{MySQL} is allowed to use while recreating the index (during @code{REPAIR}, @code{ALTER TABLE} or @code{LOAD DATA INFILE}. If the file size would be bigger than this, the index will be created through the key cache (which is slower). @strong{NOTE} that this parameter is given in megabytes! Loading Loading @@ -22605,8 +22614,23 @@ combination after it has found the first matching row. @item Not exists @strong{MySQL} was able to do a @code{LEFT JOIN} optimization on the query and will not examine more rows in this table for a row combination after it finds one row that matches the @code{LEFT JOIN} criteria. query and will not examine more rows in this table for the previous row combination after it finds one row that matches the @code{LEFT JOIN} criteria. Here is an example for this: @example SELECT * FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL; @end example Assume that @code{t2.id} is defined with @code{NOT NULL}. In this case @strong{MySQL} will scan @code{t1} and look up the rows in @code{t2} through @code{t1.id}. If @strong{MySQL} finds a matching row in @code{t2}, it knows that @code{t2.id} can never be @code{NULL}, and will not scan through the rest of the rows in @code{t2} that has the same @code{id}. In other words, for each row in @code{t1}, @strong{MySQL} only needs to do a single lookup in @code{t2}, independent of how many matching rows there are in @code{t2}. @item @code{range checked for each record (index map: #)} @strong{MySQL} didn't find a real good index to use. It will, instead, for Loading Loading @@ -22863,6 +22887,9 @@ the @code{FROM} clause. @{DESCRIBE | DESC@} tbl_name @{col_name | wild@} @end example @code{DESCRIBE} is a shortcut for @code{SHOW COLUMNS FROM}. @xref{SHOW DATABASE INFO}. @code{DESCRIBE} provides information about a table's columns. @code{col_name} may be a column name or a string containing the SQL @samp{%} and @samp{_} wild-card characters. Loading Loading @@ -22954,6 +22981,18 @@ are locked by the current thread are automatically unlocked when the thread issues another @code{LOCK TABLES}, or when the connection to the server is closed. The main reasons to use @code{LOCK TABLES} are: @itemize @bullet @item Emulate transactions with not transaction safe tables. @item To get more speed with @code{MyISAM} tables when inserting/updating data over many statements. The main reason this gives more speed is that @strong{MySQL} will not flush the key cache for the locked tables until @code{UNLOCK TABLES} is called. @end itemize If a thread obtains a @code{READ} lock on a table, that thread (and all other threads) can only read from the table. If a thread obtains a @code{WRITE} lock on a table, then only the thread holding the lock can @code{READ} from Loading Loading @@ -24519,7 +24558,7 @@ mysql> ALTER TABLE tbl_name TYPE = MYISAM; @end example @cindex tables, @code{HEAP} @node HEAP, BDB, ISAM, Table types @node HEAP, InnoDB, ISAM, Table types @section HEAP Tables @code{HEAP} tables use a hashed index and are stored in memory. This Loading Loading @@ -24596,7 +24635,7 @@ SUM_OVER_ALL_KEYS(max_length_of_key + sizeof(char*) * 2) @code{sizeof(char*)} is 4 on 32-bit machines and 8 on 64-bit machines. @node InnoDB, , GEMINI, Table types @node InnoDB, BDB, HEAP, Table types @section InnoDB Tables @menu Loading Loading @@ -25897,7 +25936,7 @@ Finland @cindex tables, @code{BDB} @cindex tables, @code{Berkeley DB} @node BDB, GEMINI, HEAP, Table types @node BDB, GEMINI, InnoDB, Table types @section BDB or Berkeley_DB Tables @menu Loading Loading @@ -26183,7 +26222,7 @@ not trivial). @end itemize @cindex GEMINI tables @node GEMINI, InnoDB, BDB, Table types @node GEMINI, , BDB, Table types @section GEMINI Tables @cindex GEMINI tables, overview Loading Loading @@ -28800,6 +28839,7 @@ mysql> SELECT * FROM shop; * example-user-variables:: Using user variables * example-Foreign keys:: Using foreign keys * Searching on two keys:: * Calculating days:: @end menu @node example-Maximum-column, example-Maximum-row, Examples, Examples Loading Loading @@ -29056,7 +29096,7 @@ SELECT s.* FROM persons p, shirts s @findex UNION @cindex searching, two keys @cindex keys, searching on two @node Searching on two keys, , example-Foreign keys, Examples @node Searching on two keys, Calculating days, example-Foreign keys, Examples @subsection Searching on Two Keys @strong{MySQL} doesn't yet optimize when you search on two different Loading Loading @@ -29088,6 +29128,35 @@ DROP TABLE tmp; The above way to solve this query is in effect an @code{UNION} of two queries. @cindex bit_functions, example @findex BIT_OR @findex BIT_COUNT @findex << @node Calculating days, , Searching on two keys, Examples @subsection Calculating visits per day The following shows an idea of how you can use the bit group functions to calculate the number of days per month a user has visited a web page. @example CREATE TABLE t1 (year YEAR(4), month INT(2) UNSIGNED ZEROFILL, day INT(2) UNSIGNED ZEROFILL); INSERT INTO t1 VALUES(2000,1,1),(2000,1,20),(2000,1,30),(2000,2,2),(2000,2,23),(2000,2,23); SELECT year,month,BIT_COUNT(BIT_OR(1<<day)) AS days FROM t1 GROUP BY year,month; Which returns: +------+-------+------+ | year | month | days | +------+-------+------+ | 2000 | 01 | 3 | | 2000 | 02 | 2 | +------+-------+------+ @end example The above calculates how many different days was used for a given year/month combination, with automatic removal of duplicate entries. @cindex modes, batch @cindex batch mode @cindex running, batch mode Loading Loading @@ -30911,10 +30980,13 @@ unless you know what you are doing! @itemize @item Minimal length of word to be indexed is defined by @strong{MySQL} variable @code{ft_min_word_length}. @xref{SHOW VARIABLES}. Change it to the value you prefer, and rebuild your @code{FULLTEXT} indexes (e.g. with @code{OPTIMIZE TABLE}). Minimal length of word to be indexed is defined in @code{myisam/ftdefs.h} file by the line @example #define MIN_WORD_LEN 4 @end example Change it to the value you prefer, recompile @strong{MySQL}, and rebuild your @code{FULLTEXT} indexes. @item The stopword list is defined in @code{myisam/ft_static.c} Loading Loading @@ -30980,6 +31052,9 @@ index operations (querying/dumping/statistics). @itemize @bullet @item Make all operations with @code{FULLTEXT} index @strong{faster}. @item Support for braces @code{()} in boolean full-text search. @item Phrase search, proximity operators @item Boolean search can work without @code{FULLTEXT} index (yes, @strong{very} slow). @item Support for "always-index words". They could be any strings the user wants to treat as words, examples are "C++", "AS/400", "TCP/IP", etc. @item Support for full-text search in @code{MERGE} tables. Loading Loading @@ -52004,7 +52079,19 @@ structure. Don't allow more than a defined number of threads to run MyISAM recover at the same time. @item Change @code{INSERT ... SELECT} to use concurrent inserts. Change @code{INSERT ... SELECT} to optionally use concurrent inserts. @item Implement @code{RENAME DATABASE}. To make this safe for all table handlers, it should work as follows: @itemize @bullet @item Create the new database. @item For every table do a rename of the table to another database, as we do with the @code{RENAME} command. @item Drop the old database. @end itemize @item Return the original field types() when doing @code{SELECT MIN(column) ... GROUP BY}. Loading Loading @@ -52051,6 +52138,8 @@ a concurrent insert at the end of the file if the file is read-locked. @item Remember @code{FOREIGN} key definitions in the @file{.frm} file. @item Cascading @code{DELETE} @item Server side cursors. @item Check if @code{lockd} works with modern Linux kernels; If not, we have Loading @@ -52060,6 +52149,13 @@ give any errors if @code{lockd} works. @item Allow SQL variables in @code{LIMIT}, like in @code{LIMIT @@a,@@b}. @item Allow update of variables in @code{UPDATE} statements. For example: @code{UPDATE TABLE foo SET @@a=a+b,a=@@a, b=@@a+c} @item Change when user variables are updated so that one can use them with @code{GROUP BY}, as in the following example: @code{SELECT id, @@a:=count(*), sum(sum_col)/@@a FROM table_name GROUP BY id}. @item Don't add automatic @code{DEFAULT} values to columns. Give an error when using an @code{INSERT} that doesn't contain a column that doesn't have a @code{DEFAULT}. Loading Loading @@ -52198,9 +52294,6 @@ Change that @code{ALTER TABLE} doesn't abort clients that executes Fix that when columns referenced in an @code{UPDATE} clause contains the old values before the update started. @item Allow update of variables in @code{UPDATE} statements. For example: @code{UPDATE TABLE foo SET @@a=a+b,a=@@a, b=@@a+c} @item @code{myisamchk}, @code{REPAIR} and @code{OPTIMIZE TABLE} should be able to handle cases where the data and/or index files are symbolic links. @item
sql/slave.cc +1 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ #define RPL_LOG_NAME (glob_mi.log_file_name[0] ? glob_mi.log_file_name :\ "FIRST") bool slave_running = 0; volatile bool slave_running = 0; pthread_t slave_real_id; MASTER_INFO glob_mi; HASH replicate_do_table, replicate_ignore_table; Loading
sql/slave.h +1 −2 Original line number Diff line number Diff line Loading @@ -98,8 +98,7 @@ int init_master_info(MASTER_INFO* mi); void end_master_info(MASTER_INFO* mi); extern bool opt_log_slave_updates ; pthread_handler_decl(handle_slave,arg); extern bool volatile abort_loop, abort_slave; extern bool slave_running; extern bool volatile abort_loop, abort_slave, slave_running; extern uint32 slave_skip_counter; // needed for problems when slave stops and // we want to restart it skipping one or more events in the master log that Loading
sql/sql_base.cc +86 −91 Original line number Diff line number Diff line Loading @@ -34,6 +34,8 @@ HASH open_cache; /* Used by mysql_test */ static int open_unireg_entry(THD *thd,TABLE *entry,const char *db, const char *name, const char *alias, bool locked); static bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, const char *table_name, List_iterator<Item> *it); static void free_cache_entry(TABLE *entry); static void mysql_rm_tmp_tables(void); static key_map get_key_map_from_key_list(TABLE *table, Loading Loading @@ -109,71 +111,75 @@ static void check_unused(void) #define check_unused() #endif OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild) int list_open_tables(THD *thd,List<char> *tables, const char *db, const char *wild) { int result = 0; uint col_access=thd->col_access; OPEN_TABLE_LIST **start_list, *open_list; TABLE_LIST table_list; char name[NAME_LEN*2]; DBUG_ENTER("list_open_tables"); VOID(pthread_mutex_lock(&LOCK_open)); bzero((char*) &table_list,sizeof(table_list)); start_list= &open_list; open_list=0; for (uint idx=0 ; result == 0 && idx < open_cache.records; idx++) for (uint idx=0 ; idx < open_cache.records; idx++) { OPEN_TABLE_LIST *table; TABLE *entry=(TABLE*) hash_element(&open_cache,idx); if ((!entry->real_name)) continue; // Shouldn't happen if (wild) if ((!entry->real_name) || strcmp(entry->table_cache_key,db)) continue; if (wild && wild[0] && wild_compare(entry->real_name,wild)) continue; if (db && !(col_access & TABLE_ACLS)) { strxmov(name,entry->table_cache_key,".",entry->real_name,NullS); if (wild_compare(name,wild)) table_list.db= (char*) db; table_list.real_name= entry->real_name;/*real name*/ table_list.grant.privilege=col_access; if (check_grant(thd,TABLE_ACLS,&table_list,1)) continue; } /* need to check if he have't already listed it */ /* Check if user has SELECT privilege for any column in the table */ table_list.db= (char*) entry->table_cache_key; table_list.real_name= entry->real_name; table_list.grant.privilege=0; if (check_table_access(thd,SELECT_ACL | EXTRA_ACL,&table_list)) continue; /* need to check if we haven't already listed it */ for (table= open_list ; table ; table=table->next) { if (!strcmp(table->table,entry->real_name) && !strcmp(table->db,entry->table_cache_key)) List_iterator<char> it(*tables); char *table_name; int check = 0; while (check == 0 && (table_name=it++)) { if (entry->in_use) table->in_use++; if (entry->locked_by_name) table->locked++; break; if (!strcmp(table_name,entry->real_name)) check++; } } if (table) if (check) continue; if (!(*start_list = (OPEN_TABLE_LIST *) sql_alloc(sizeof(OPEN_TABLE_LIST)+entry->key_length))) if (tables->push_back(thd->strdup(entry->real_name))) { open_list=0; // Out of memory result = -1; break; } (*start_list)->table=(strmov((*start_list)->db=(char*) ((*start_list)+1), entry->table_cache_key)+1, entry->real_name); (*start_list)->in_use= entry->in_use ? 1 : 0; (*start_list)->locked= entry->locked_by_name ? 1 : 0; start_list= &(*start_list)->next; } VOID(pthread_mutex_unlock(&LOCK_open)); DBUG_RETURN(open_list); DBUG_RETURN(result); } char* query_table_status(THD *thd,const char *db,const char *table_name) { int cached = 0, in_use = 0; char info[256]; for (uint idx=0 ; idx < open_cache.records; idx++) { TABLE *entry=(TABLE*) hash_element(&open_cache,idx); if (strcmp(entry->table_cache_key,db) || strcmp(entry->real_name,table_name)) continue; cached++; if (entry->in_use) in_use++; } sprintf(info, "cached=%d, in_use=%d", cached, in_use); return thd->strdup(info); } Loading Loading @@ -253,7 +259,7 @@ send_fields(THD *thd,List<Item> &list,uint flag) if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length())) break; /* purecov: inspected */ } send_eof(&thd->net); send_eof(&thd->net,(test_flags & TEST_MIT_THREAD) ? 0: 1); return 0; err: send_error(&thd->net,ER_OUT_OF_RESOURCES); /* purecov: inspected */ Loading Loading @@ -424,34 +430,9 @@ void close_thread_tables(THD *thd, bool locked) DBUG_PRINT("info", ("thd->open_tables=%p", thd->open_tables)); while (thd->open_tables) found_old_table|=close_thread_table(thd, &thd->open_tables); /* Free tables to hold down open files */ while (open_cache.records > table_cache_size && unused_tables) VOID(hash_delete(&open_cache,(byte*) unused_tables)); /* purecov: tested */ check_unused(); if (found_old_table) { /* Tell threads waiting for refresh that something has happened */ VOID(pthread_cond_broadcast(&COND_refresh)); } if (!locked) VOID(pthread_mutex_unlock(&LOCK_open)); /* VOID(pthread_sigmask(SIG_SETMASK,&thd->signals,NULL)); */ DBUG_VOID_RETURN; } /* move one table to free list */ bool close_thread_table(THD *thd, TABLE **table_ptr) for (table=thd->open_tables ; table ; table=next) { DBUG_ENTER("close_thread_table"); bool found_old_table=0; TABLE *table=*table_ptr; *table_ptr=table->next; next=table->next; if (table->version != refresh_version || thd->version != refresh_version || !table->db_stat) { Loading Loading @@ -481,7 +462,21 @@ bool close_thread_table(THD *thd, TABLE **table_ptr) else unused_tables=table->next=table->prev=table; } DBUG_RETURN(found_old_table); } thd->open_tables=0; /* Free tables to hold down open files */ while (open_cache.records > table_cache_size && unused_tables) VOID(hash_delete(&open_cache,(byte*) unused_tables)); /* purecov: tested */ check_unused(); if (found_old_table) { /* Tell threads waiting for refresh that something has happened */ VOID(pthread_cond_broadcast(&COND_refresh)); } if (!locked) VOID(pthread_mutex_unlock(&LOCK_open)); /* VOID(pthread_sigmask(SIG_SETMASK,&thd->signals,NULL)); */ DBUG_VOID_RETURN; } /* Close and delete temporary tables */ Loading Loading @@ -1837,7 +1832,7 @@ static key_map get_key_map_from_key_list(TABLE *table, ** Returns pointer to last inserted field if ok ****************************************************************************/ bool static bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, const char *table_name, List_iterator<Item> *it) { Loading
sql/sql_show.cc +17 −13 Original line number Diff line number Diff line Loading @@ -95,34 +95,38 @@ mysqld_show_dbs(THD *thd,const char *wild) ** List all open tables in a database ***************************************************************************/ int mysqld_show_open_tables(THD *thd,const char *wild) int mysqld_show_open_tables(THD *thd,const char *db,const char *wild) { Item_string *field=new Item_string("",0); List<Item> field_list; OPEN_TABLE_LIST *open_list; CONVERT *convert=thd->convert_set; char *end,*table_name; List<char> tables; DBUG_ENTER("mysqld_show_open_tables"); field_list.push_back(new Item_empty_string("Database",NAME_LEN)); field_list.push_back(new Item_empty_string("Table",NAME_LEN)); field_list.push_back(new Item_int("In_use",0, 4)); field_list.push_back(new Item_int("Name_locked",0, 4)); field->name=(char*) thd->alloc(20+(uint) strlen(db)+(wild ? (uint) strlen(wild)+4:0)); end=strxmov(field->name,"Open_tables_in_",db,NullS); if (wild && wild[0]) strxmov(end," (",wild,")",NullS); field->max_length=NAME_LEN; field_list.push_back(field); field_list.push_back(new Item_empty_string("Comment",80)); if (send_fields(thd,field_list,1)) DBUG_RETURN(1); if (!(open_list=list_open_tables(thd,wild))) if (list_open_tables(thd,&tables,db,wild)) DBUG_RETURN(-1); for ( ; open_list ; open_list=open_list->next) List_iterator<char> it(tables); while ((table_name=it++)) { thd->packet.length(0); net_store_data(&thd->packet,convert, open_list->db); net_store_data(&thd->packet,convert, open_list->table); net_store_data(&thd->packet,open_list->in_use); net_store_data(&thd->packet,open_list->locked); net_store_data(&thd->packet,table_name); net_store_data(&thd->packet,query_table_status(thd,db,table_name)); if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length())) DBUG_RETURN(-1); } send_eof(&thd->net); DBUG_RETURN(0); } Loading