Commit 27561841 authored by sasha@mysql.sashanet.com's avatar sasha@mysql.sashanet.com

merged latest changes in 3.23

parents 6bedc859 cc35643e
...@@ -633,6 +633,7 @@ Examples of Common Queries ...@@ -633,6 +633,7 @@ Examples of Common Queries
* example-user-variables:: Using user variables * example-user-variables:: Using user variables
* example-Foreign keys:: Using foreign keys * example-Foreign keys:: Using foreign keys
* Searching on two keys:: * Searching on two keys::
* Calculating days::
Queries from Twin Project Queries from Twin Project
...@@ -16551,6 +16552,7 @@ mysql> select 2 > 2; ...@@ -16551,6 +16552,7 @@ mysql> select 2 > 2;
-> 0 -> 0
@end example @end example
@cindex @code{NULL}, testing for null
@findex <=> (Equal to) @findex <=> (Equal to)
@item <=> @item <=>
Null safe equal: Null safe equal:
...@@ -16559,6 +16561,7 @@ mysql> select 1 <=> 1, NULL <=> NULL, 1 <=> NULL; ...@@ -16559,6 +16561,7 @@ mysql> select 1 <=> 1, NULL <=> NULL, 1 <=> NULL;
-> 1 1 0 -> 1 1 0
@end example @end example
@cindex @code{NULL}, testing for null
@findex IS NULL @findex IS NULL
@findex IS NOT NULL @findex IS NOT NULL
@item IS NULL @item IS NULL
...@@ -16643,6 +16646,7 @@ mysql> select ISNULL(1/0); ...@@ -16643,6 +16646,7 @@ mysql> select ISNULL(1/0);
Note that a comparison of @code{NULL} values using @code{=} will always be Note that a comparison of @code{NULL} values using @code{=} will always be
false! false!
@cindex @code{NULL}, testing for null
@findex COALESCE() @findex COALESCE()
@item COALESCE(list) @item COALESCE(list)
Returns first non-@code{NULL} element in list: Returns first non-@code{NULL} element in list:
...@@ -16860,6 +16864,7 @@ make string comparison even more flexible. ...@@ -16860,6 +16864,7 @@ make string comparison even more flexible.
@subsection Control Flow Functions @subsection Control Flow Functions
@table @code @table @code
@cindex @code{NULL}, testing for null
@findex IFNULL() @findex IFNULL()
@item IFNULL(expr1,expr2) @item IFNULL(expr1,expr2)
If @code{expr1} is not @code{NULL}, @code{IFNULL()} returns @code{expr1}, If @code{expr1} is not @code{NULL}, @code{IFNULL()} returns @code{expr1},
...@@ -17136,10 +17141,13 @@ mysql> select SQRT(20); ...@@ -17136,10 +17141,13 @@ mysql> select SQRT(20);
@findex PI() @findex PI()
@item 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 @example
mysql> select PI(); mysql> select PI();
-> 3.141593 -> 3.141593
mysql> SELECT PI()+0.000000000000000000;
-> 3.141592653589793116
@end example @end example
@findex COS() @findex COS()
...@@ -19268,7 +19276,7 @@ The options work for all table types, if not otherwise indicated: ...@@ -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{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{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{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 @end multitable
When you use a @code{MyISAM} table, @strong{MySQL} uses the product of When you use a @code{MyISAM} table, @strong{MySQL} uses the product of
...@@ -19461,9 +19469,8 @@ normally do @code{ALTER TABLE} that often this isn't that high on our TODO. ...@@ -19461,9 +19469,8 @@ normally do @code{ALTER TABLE} that often this isn't that high on our TODO.
@itemize @bullet @itemize @bullet
@item @item
To use @code{ALTER TABLE}, you need @strong{select}, @strong{insert}, To use @code{ALTER TABLE}, you need @strong{ALTER}, @strong{INSERT},
@strong{delete}, @strong{update}, @strong{create}, and @strong{drop} and @strong{CREATE} privileges on the table.
privileges on the table.
@item @item
@code{IGNORE} is a @strong{MySQL} extension to ANSI SQL92. @code{IGNORE} is a @strong{MySQL} extension to ANSI SQL92.
...@@ -19553,7 +19560,7 @@ assigns a default value, as described in ...@@ -19553,7 +19560,7 @@ assigns a default value, as described in
@findex DROP INDEX @findex DROP INDEX
@item @item
@code{DROP INDEX} removes an index. This is a @strong{MySQL} extension to @code{DROP INDEX} removes an index. This is a @strong{MySQL} extension to
ANSI SQL92. ANSI SQL92. @xref{DROP INDEX}.
@item @item
If columns are dropped from a table, the columns are also removed from any If columns are dropped from a table, the columns are also removed from any
...@@ -20527,6 +20534,8 @@ or INSERT [LOW_PRIORITY | DELAYED] [IGNORE] ...@@ -20527,6 +20534,8 @@ or INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
or INSERT [LOW_PRIORITY | DELAYED] [IGNORE] or INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
[INTO] tbl_name [INTO] tbl_name
SET col_name=expression, col_name=expression, ... SET col_name=expression, col_name=expression, ...
or INSERT [LOW_PRIORITY] [IGNORE] [INTO] tbl_name
SELECT ...
@end example @end example
...@@ -22289,8 +22298,8 @@ tables to use the slower key cache method to create the index. ...@@ -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! @strong{NOTE} that this parameter is given in megabytes!
@item @code{myisam_max_sort_file_size} @item @code{myisam_max_sort_file_size}
The maximum size of the temporary file @strong{MySQL} is allowed to create The maximum size of the temporary file @strong{MySQL} is allowed to use
to while recreating the index (during @code{REPAIR}, @code{ALTER TABLE} while recreating the index (during @code{REPAIR}, @code{ALTER TABLE}
or @code{LOAD DATA INFILE}. If the file size would be bigger than this, 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). the index will be created through the key cache (which is slower).
@strong{NOTE} that this parameter is given in megabytes! @strong{NOTE} that this parameter is given in megabytes!
...@@ -22605,8 +22614,23 @@ combination after it has found the first matching row. ...@@ -22605,8 +22614,23 @@ combination after it has found the first matching row.
@item Not exists @item Not exists
@strong{MySQL} was able to do a @code{LEFT JOIN} optimization on the @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 query and will not examine more rows in this table for the previous row
after it finds one row that matches the @code{LEFT JOIN} criteria. 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: #)} @item @code{range checked for each record (index map: #)}
@strong{MySQL} didn't find a real good index to use. It will, instead, for @strong{MySQL} didn't find a real good index to use. It will, instead, for
...@@ -22863,6 +22887,9 @@ the @code{FROM} clause. ...@@ -22863,6 +22887,9 @@ the @code{FROM} clause.
@{DESCRIBE | DESC@} tbl_name @{col_name | wild@} @{DESCRIBE | DESC@} tbl_name @{col_name | wild@}
@end example @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} @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{_} may be a column name or a string containing the SQL @samp{%} and @samp{_}
wild-card characters. wild-card characters.
...@@ -22954,6 +22981,18 @@ are locked by the current thread are automatically unlocked when the ...@@ -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 thread issues another @code{LOCK TABLES}, or when the connection to the
server is closed. 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 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} 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 lock on a table, then only the thread holding the lock can @code{READ} from
...@@ -24519,7 +24558,7 @@ mysql> ALTER TABLE tbl_name TYPE = MYISAM; ...@@ -24519,7 +24558,7 @@ mysql> ALTER TABLE tbl_name TYPE = MYISAM;
@end example @end example
@cindex tables, @code{HEAP} @cindex tables, @code{HEAP}
@node HEAP, BDB, ISAM, Table types @node HEAP, InnoDB, ISAM, Table types
@section HEAP Tables @section HEAP Tables
@code{HEAP} tables use a hashed index and are stored in memory. This @code{HEAP} tables use a hashed index and are stored in memory. This
...@@ -24596,7 +24635,7 @@ SUM_OVER_ALL_KEYS(max_length_of_key + sizeof(char*) * 2) ...@@ -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. @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 @section InnoDB Tables
@menu @menu
...@@ -25897,7 +25936,7 @@ Finland ...@@ -25897,7 +25936,7 @@ Finland
@cindex tables, @code{BDB} @cindex tables, @code{BDB}
@cindex tables, @code{Berkeley DB} @cindex tables, @code{Berkeley DB}
@node BDB, GEMINI, HEAP, Table types @node BDB, GEMINI, InnoDB, Table types
@section BDB or Berkeley_DB Tables @section BDB or Berkeley_DB Tables
@menu @menu
...@@ -26183,7 +26222,7 @@ not trivial). ...@@ -26183,7 +26222,7 @@ not trivial).
@end itemize @end itemize
@cindex GEMINI tables @cindex GEMINI tables
@node GEMINI, InnoDB, BDB, Table types @node GEMINI, , BDB, Table types
@section GEMINI Tables @section GEMINI Tables
@cindex GEMINI tables, overview @cindex GEMINI tables, overview
...@@ -28800,6 +28839,7 @@ mysql> SELECT * FROM shop; ...@@ -28800,6 +28839,7 @@ mysql> SELECT * FROM shop;
* example-user-variables:: Using user variables * example-user-variables:: Using user variables
* example-Foreign keys:: Using foreign keys * example-Foreign keys:: Using foreign keys
* Searching on two keys:: * Searching on two keys::
* Calculating days::
@end menu @end menu
@node example-Maximum-column, example-Maximum-row, Examples, Examples @node example-Maximum-column, example-Maximum-row, Examples, Examples
...@@ -29056,7 +29096,7 @@ SELECT s.* FROM persons p, shirts s ...@@ -29056,7 +29096,7 @@ SELECT s.* FROM persons p, shirts s
@findex UNION @findex UNION
@cindex searching, two keys @cindex searching, two keys
@cindex keys, searching on two @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 @subsection Searching on Two Keys
@strong{MySQL} doesn't yet optimize when you search on two different @strong{MySQL} doesn't yet optimize when you search on two different
...@@ -29088,6 +29128,35 @@ DROP TABLE tmp; ...@@ -29088,6 +29128,35 @@ DROP TABLE tmp;
The above way to solve this query is in effect an @code{UNION} of two queries. 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 modes, batch
@cindex batch mode @cindex batch mode
@cindex running, batch mode @cindex running, batch mode
...@@ -30911,10 +30980,13 @@ unless you know what you are doing! ...@@ -30911,10 +30980,13 @@ unless you know what you are doing!
@itemize @itemize
@item @item
Minimal length of word to be indexed is defined by @strong{MySQL} Minimal length of word to be indexed is defined in
variable @code{ft_min_word_length}. @xref{SHOW VARIABLES}. @code{myisam/ftdefs.h} file by the line
Change it to the value you prefer, and rebuild @example
your @code{FULLTEXT} indexes (e.g. with @code{OPTIMIZE TABLE}). #define MIN_WORD_LEN 4
@end example
Change it to the value you prefer, recompile @strong{MySQL}, and rebuild
your @code{FULLTEXT} indexes.
@item @item
The stopword list is defined in @code{myisam/ft_static.c} The stopword list is defined in @code{myisam/ft_static.c}
...@@ -30980,6 +31052,9 @@ index operations (querying/dumping/statistics). ...@@ -30980,6 +31052,9 @@ index operations (querying/dumping/statistics).
@itemize @bullet @itemize @bullet
@item Make all operations with @code{FULLTEXT} index @strong{faster}. @item Make all operations with @code{FULLTEXT} index @strong{faster}.
@item Support for braces @code{()} in boolean full-text search. @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 @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. 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. @item Support for full-text search in @code{MERGE} tables.
...@@ -52004,7 +52079,19 @@ structure. ...@@ -52004,7 +52079,19 @@ structure.
Don't allow more than a defined number of threads to run MyISAM recover Don't allow more than a defined number of threads to run MyISAM recover
at the same time. at the same time.
@item @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 @item
Return the original field types() when doing @code{SELECT MIN(column) Return the original field types() when doing @code{SELECT MIN(column)
... GROUP BY}. ... GROUP BY}.
...@@ -52051,6 +52138,8 @@ a concurrent insert at the end of the file if the file is read-locked. ...@@ -52051,6 +52138,8 @@ a concurrent insert at the end of the file if the file is read-locked.
@item @item
Remember @code{FOREIGN} key definitions in the @file{.frm} file. Remember @code{FOREIGN} key definitions in the @file{.frm} file.
@item @item
Cascading @code{DELETE}
@item
Server side cursors. Server side cursors.
@item @item
Check if @code{lockd} works with modern Linux kernels; If not, we have Check if @code{lockd} works with modern Linux kernels; If not, we have
...@@ -52060,6 +52149,13 @@ give any errors if @code{lockd} works. ...@@ -52060,6 +52149,13 @@ give any errors if @code{lockd} works.
@item @item
Allow SQL variables in @code{LIMIT}, like in @code{LIMIT @@a,@@b}. Allow SQL variables in @code{LIMIT}, like in @code{LIMIT @@a,@@b}.
@item @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 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 an @code{INSERT} that doesn't contain a column that doesn't have a
@code{DEFAULT}. @code{DEFAULT}.
...@@ -52198,9 +52294,6 @@ Change that @code{ALTER TABLE} doesn't abort clients that executes ...@@ -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 Fix that when columns referenced in an @code{UPDATE} clause contains the old
values before the update started. values before the update started.
@item @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 @code{myisamchk}, @code{REPAIR} and @code{OPTIMIZE TABLE} should be able
to handle cases where the data and/or index files are symbolic links. to handle cases where the data and/or index files are symbolic links.
@item @item
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#define RPL_LOG_NAME (glob_mi.log_file_name[0] ? glob_mi.log_file_name :\ #define RPL_LOG_NAME (glob_mi.log_file_name[0] ? glob_mi.log_file_name :\
"FIRST") "FIRST")
bool slave_running = 0; volatile bool slave_running = 0;
pthread_t slave_real_id; pthread_t slave_real_id;
MASTER_INFO glob_mi; MASTER_INFO glob_mi;
HASH replicate_do_table, replicate_ignore_table; HASH replicate_do_table, replicate_ignore_table;
......
...@@ -98,8 +98,7 @@ int init_master_info(MASTER_INFO* mi); ...@@ -98,8 +98,7 @@ int init_master_info(MASTER_INFO* mi);
void end_master_info(MASTER_INFO* mi); void end_master_info(MASTER_INFO* mi);
extern bool opt_log_slave_updates ; extern bool opt_log_slave_updates ;
pthread_handler_decl(handle_slave,arg); pthread_handler_decl(handle_slave,arg);
extern bool volatile abort_loop, abort_slave; extern bool volatile abort_loop, abort_slave, slave_running;
extern bool slave_running;
extern uint32 slave_skip_counter; extern uint32 slave_skip_counter;
// needed for problems when slave stops and // needed for problems when slave stops and
// we want to restart it skipping one or more events in the master log that // we want to restart it skipping one or more events in the master log that
......
...@@ -34,6 +34,8 @@ HASH open_cache; /* Used by mysql_test */ ...@@ -34,6 +34,8 @@ HASH open_cache; /* Used by mysql_test */
static int open_unireg_entry(THD *thd,TABLE *entry,const char *db, static int open_unireg_entry(THD *thd,TABLE *entry,const char *db,
const char *name, const char *alias, bool locked); 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 free_cache_entry(TABLE *entry);
static void mysql_rm_tmp_tables(void); static void mysql_rm_tmp_tables(void);
static key_map get_key_map_from_key_list(TABLE *table, static key_map get_key_map_from_key_list(TABLE *table,
...@@ -109,71 +111,75 @@ static void check_unused(void) ...@@ -109,71 +111,75 @@ static void check_unused(void)
#define check_unused() #define check_unused()
#endif #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; int result = 0;
uint col_access=thd->col_access; uint col_access=thd->col_access;
OPEN_TABLE_LIST **start_list, *open_list;
TABLE_LIST table_list; TABLE_LIST table_list;
char name[NAME_LEN*2];
DBUG_ENTER("list_open_tables"); DBUG_ENTER("list_open_tables");
VOID(pthread_mutex_lock(&LOCK_open)); VOID(pthread_mutex_lock(&LOCK_open));
bzero((char*) &table_list,sizeof(table_list)); 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); TABLE *entry=(TABLE*) hash_element(&open_cache,idx);
if ((!entry->real_name) || strcmp(entry->table_cache_key,db))
if ((!entry->real_name)) continue;
continue; // Shouldn't happen if (wild && wild[0] && wild_compare(entry->real_name,wild))
if (wild) continue;
if (db && !(col_access & TABLE_ACLS))
{ {
strxmov(name,entry->table_cache_key,".",entry->real_name,NullS); table_list.db= (char*) db;
if (wild_compare(name,wild)) 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; continue;
} }
/* need to check if he have't already listed it */
/* Check if user has SELECT privilege for any column in the table */ List_iterator<char> it(*tables);
table_list.db= (char*) entry->table_cache_key; char *table_name;
table_list.real_name= entry->real_name; int check = 0;
table_list.grant.privilege=0; while (check == 0 && (table_name=it++))
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) && if (!strcmp(table_name,entry->real_name))
!strcmp(table->db,entry->table_cache_key)) check++;
{
if (entry->in_use)
table->in_use++;
if (entry->locked_by_name)
table->locked++;
break;
}
} }
if (table) if (check)
continue; 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; 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)); 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);
} }
...@@ -253,7 +259,7 @@ send_fields(THD *thd,List<Item> &list,uint flag) ...@@ -253,7 +259,7 @@ send_fields(THD *thd,List<Item> &list,uint flag)
if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length())) if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length()))
break; /* purecov: inspected */ break; /* purecov: inspected */
} }
send_eof(&thd->net); send_eof(&thd->net,(test_flags & TEST_MIT_THREAD) ? 0: 1);
return 0; return 0;
err: err:
send_error(&thd->net,ER_OUT_OF_RESOURCES); /* purecov: inspected */ send_error(&thd->net,ER_OUT_OF_RESOURCES); /* purecov: inspected */
...@@ -424,34 +430,9 @@ void close_thread_tables(THD *thd, bool locked) ...@@ -424,34 +430,9 @@ void close_thread_tables(THD *thd, bool locked)
DBUG_PRINT("info", ("thd->open_tables=%p", thd->open_tables)); DBUG_PRINT("info", ("thd->open_tables=%p", thd->open_tables));
while (thd->open_tables) for (table=thd->open_tables ; table ; table=next)
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 */ next=table->next;
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)
{
DBUG_ENTER("close_thread_table");
bool found_old_table=0;
TABLE *table=*table_ptr;
*table_ptr=table->next;
if (table->version != refresh_version || if (table->version != refresh_version ||
thd->version != refresh_version || !table->db_stat) thd->version != refresh_version || !table->db_stat)
{ {
...@@ -481,7 +462,21 @@ bool close_thread_table(THD *thd, TABLE **table_ptr) ...@@ -481,7 +462,21 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
else else
unused_tables=table->next=table->prev=table; 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 */ /* Close and delete temporary tables */
...@@ -1837,7 +1832,7 @@ static key_map get_key_map_from_key_list(TABLE *table, ...@@ -1837,7 +1832,7 @@ static key_map get_key_map_from_key_list(TABLE *table,
** Returns pointer to last inserted field if ok ** Returns pointer to last inserted field if ok
****************************************************************************/ ****************************************************************************/
bool static bool
insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
const char *table_name, List_iterator<Item> *it) const char *table_name, List_iterator<Item> *it)
{ {
......
...@@ -95,34 +95,38 @@ mysqld_show_dbs(THD *thd,const char *wild) ...@@ -95,34 +95,38 @@ mysqld_show_dbs(THD *thd,const char *wild)
** List all open tables in a database ** 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; List<Item> field_list;
OPEN_TABLE_LIST *open_list; char *end,*table_name;
CONVERT *convert=thd->convert_set; List<char> tables;
DBUG_ENTER("mysqld_show_open_tables"); DBUG_ENTER("mysqld_show_open_tables");
field_list.push_back(new Item_empty_string("Database",NAME_LEN)); field->name=(char*) thd->alloc(20+(uint) strlen(db)+(wild ? (uint) strlen(wild)+4:0));
field_list.push_back(new Item_empty_string("Table",NAME_LEN)); end=strxmov(field->name,"Open_tables_in_",db,NullS);
field_list.push_back(new Item_int("In_use",0, 4)); if (wild && wild[0])
field_list.push_back(new Item_int("Name_locked",0, 4)); 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)) if (send_fields(thd,field_list,1))
DBUG_RETURN(1); DBUG_RETURN(1);
if (!(open_list=list_open_tables(thd,wild))) if (list_open_tables(thd,&tables,db,wild))
DBUG_RETURN(-1); DBUG_RETURN(-1);
for ( ; open_list ; open_list=open_list->next) List_iterator<char> it(tables);
while ((table_name=it++))
{ {
thd->packet.length(0); thd->packet.length(0);
net_store_data(&thd->packet,convert, open_list->db); net_store_data(&thd->packet,table_name);
net_store_data(&thd->packet,convert, open_list->table); net_store_data(&thd->packet,query_table_status(thd,db,table_name));
net_store_data(&thd->packet,open_list->in_use);
net_store_data(&thd->packet,open_list->locked);
if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length())) if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length()))
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
send_eof(&thd->net); send_eof(&thd->net);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment