2004-10-07 09:50:13 +02:00
|
|
|
/* Copyright (C) 2000-2004 MySQL AB
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
|
|
|
|
|
|
|
|
/* Function with list databases, tables or fields */
|
|
|
|
|
|
|
|
#include "mysql_priv.h"
|
2000-09-01 13:24:36 +02:00
|
|
|
#include "sql_select.h" // For select_describe
|
2005-12-22 06:39:02 +01:00
|
|
|
#include "sql_show.h"
|
2001-10-10 23:36:35 +02:00
|
|
|
#include "repl_failsafe.h"
|
2005-08-08 15:46:06 +02:00
|
|
|
#include "sp.h"
|
2004-11-13 11:56:39 +01:00
|
|
|
#include "sp_head.h"
|
2005-07-19 18:06:49 +02:00
|
|
|
#include "sql_trigger.h"
|
2005-11-10 18:43:17 +01:00
|
|
|
#include "authors.h"
|
2006-01-30 13:15:23 +01:00
|
|
|
#include "event.h"
|
2000-07-31 21:29:14 +02:00
|
|
|
#include <my_dir.h>
|
2000-11-29 04:09:28 +01:00
|
|
|
|
2006-01-10 16:44:04 +01:00
|
|
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
|
|
|
#include "ha_partition.h"
|
|
|
|
#endif
|
2000-12-15 12:18:52 +01:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
static const char *grant_names[]={
|
|
|
|
"select","insert","update","delete","create","drop","reload","shutdown",
|
|
|
|
"process","file","grant","references","index","alter"};
|
|
|
|
|
2004-04-05 12:56:05 +02:00
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
2000-07-31 21:29:14 +02:00
|
|
|
static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
|
2000-09-01 13:24:36 +02:00
|
|
|
"grant_types",
|
2004-10-25 14:51:26 +02:00
|
|
|
grant_names, NULL};
|
2004-04-05 12:56:05 +02:00
|
|
|
#endif
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2002-06-12 23:13:12 +02:00
|
|
|
/***************************************************************************
|
|
|
|
** List all table types supported
|
|
|
|
***************************************************************************/
|
|
|
|
|
2005-12-21 19:18:40 +01:00
|
|
|
static my_bool show_handlerton(THD *thd, st_plugin_int *plugin,
|
|
|
|
void *arg)
|
|
|
|
{
|
|
|
|
handlerton *default_type= (handlerton *) arg;
|
|
|
|
Protocol *protocol= thd->protocol;
|
|
|
|
handlerton *hton= (handlerton *) plugin->plugin->info;
|
|
|
|
|
|
|
|
if (!(hton->flags & HTON_HIDDEN))
|
|
|
|
{
|
|
|
|
protocol->prepare_for_resend();
|
|
|
|
protocol->store(hton->name, system_charset_info);
|
|
|
|
const char *option_name= show_comp_option_name[(int) hton->state];
|
|
|
|
|
|
|
|
if (hton->state == SHOW_OPTION_YES && default_type == hton)
|
|
|
|
option_name= "DEFAULT";
|
|
|
|
protocol->store(option_name, system_charset_info);
|
|
|
|
protocol->store(hton->comment, system_charset_info);
|
|
|
|
protocol->store(hton->commit ? "YES" : "NO", system_charset_info);
|
|
|
|
protocol->store(hton->prepare ? "YES" : "NO", system_charset_info);
|
|
|
|
protocol->store(hton->savepoint_set ? "YES" : "NO", system_charset_info);
|
|
|
|
|
|
|
|
return protocol->write() ? 1 : 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-10-20 03:04:37 +02:00
|
|
|
bool mysqld_show_storage_engines(THD *thd)
|
2002-06-12 23:13:12 +02:00
|
|
|
{
|
|
|
|
List<Item> field_list;
|
2002-12-11 08:17:51 +01:00
|
|
|
Protocol *protocol= thd->protocol;
|
2003-12-17 23:52:03 +01:00
|
|
|
DBUG_ENTER("mysqld_show_storage_engines");
|
2002-06-12 23:13:12 +02:00
|
|
|
|
2004-04-27 14:33:40 +02:00
|
|
|
field_list.push_back(new Item_empty_string("Engine",10));
|
2002-06-12 23:13:12 +02:00
|
|
|
field_list.push_back(new Item_empty_string("Support",10));
|
2002-10-02 12:33:08 +02:00
|
|
|
field_list.push_back(new Item_empty_string("Comment",80));
|
2005-11-11 00:40:00 +01:00
|
|
|
field_list.push_back(new Item_empty_string("Transactions",3));
|
|
|
|
field_list.push_back(new Item_empty_string("XA",3));
|
|
|
|
field_list.push_back(new Item_empty_string("Savepoints",3));
|
2002-06-12 23:13:12 +02:00
|
|
|
|
2004-08-03 12:32:21 +02:00
|
|
|
if (protocol->send_fields(&field_list,
|
|
|
|
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2002-06-12 23:13:12 +02:00
|
|
|
|
2005-12-21 19:18:40 +01:00
|
|
|
if (plugin_foreach(thd, show_handlerton,
|
|
|
|
MYSQL_STORAGE_ENGINE_PLUGIN, thd->variables.table_type))
|
|
|
|
DBUG_RETURN(TRUE);
|
2002-06-12 23:13:12 +02:00
|
|
|
|
2002-10-02 12:33:08 +02:00
|
|
|
send_eof(thd);
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(FALSE);
|
2002-06-12 23:13:12 +02:00
|
|
|
}
|
|
|
|
|
2005-12-21 19:18:40 +01:00
|
|
|
static int make_version_string(char *buf, int buf_length, uint version)
|
|
|
|
{
|
2005-12-21 21:50:50 +01:00
|
|
|
return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff);
|
2005-12-21 19:18:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static my_bool show_plugins(THD *thd, st_plugin_int *plugin,
|
|
|
|
void *arg)
|
|
|
|
{
|
|
|
|
TABLE *table= (TABLE*) arg;
|
|
|
|
struct st_mysql_plugin *plug= plugin->plugin;
|
|
|
|
Protocol *protocol= thd->protocol;
|
|
|
|
CHARSET_INFO *cs= system_charset_info;
|
|
|
|
char version_buf[20];
|
|
|
|
|
|
|
|
restore_record(table, s->default_values);
|
|
|
|
|
|
|
|
table->field[0]->store(plugin->name.str, plugin->name.length, cs);
|
2005-12-21 21:50:50 +01:00
|
|
|
|
|
|
|
table->field[1]->store(version_buf,
|
|
|
|
make_version_string(version_buf, sizeof(version_buf), plug->version),
|
|
|
|
cs);
|
|
|
|
|
2005-12-21 19:18:40 +01:00
|
|
|
|
|
|
|
switch (plugin->state)
|
|
|
|
{
|
|
|
|
/* case PLUGIN_IS_FREED: does not happen */
|
|
|
|
case PLUGIN_IS_DELETED:
|
2005-12-21 21:50:50 +01:00
|
|
|
table->field[2]->store(STRING_WITH_LEN("DELETED"), cs);
|
2005-12-21 19:18:40 +01:00
|
|
|
break;
|
|
|
|
case PLUGIN_IS_UNINITIALIZED:
|
2005-12-21 21:50:50 +01:00
|
|
|
table->field[2]->store(STRING_WITH_LEN("INACTIVE"), cs);
|
2005-12-21 19:18:40 +01:00
|
|
|
break;
|
|
|
|
case PLUGIN_IS_READY:
|
2005-12-21 21:50:50 +01:00
|
|
|
table->field[2]->store(STRING_WITH_LEN("ACTIVE"), cs);
|
2005-12-21 19:18:40 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
}
|
|
|
|
|
2005-12-29 21:29:02 +01:00
|
|
|
table->field[3]->store(plugin_type_names[plug->type].str,
|
|
|
|
plugin_type_names[plug->type].length,
|
|
|
|
cs);
|
2005-12-21 21:50:50 +01:00
|
|
|
table->field[4]->store(version_buf,
|
2005-12-29 21:29:02 +01:00
|
|
|
make_version_string(version_buf, sizeof(version_buf),
|
2005-12-21 21:50:50 +01:00
|
|
|
*(uint *)plug->info), cs);
|
2005-12-21 19:18:40 +01:00
|
|
|
|
|
|
|
if (plugin->plugin_dl)
|
|
|
|
{
|
2005-12-29 21:29:02 +01:00
|
|
|
table->field[5]->store(plugin->plugin_dl->dl.str,
|
2005-12-21 19:18:40 +01:00
|
|
|
plugin->plugin_dl->dl.length, cs);
|
|
|
|
table->field[5]->set_notnull();
|
2005-12-21 21:50:50 +01:00
|
|
|
table->field[6]->store(version_buf,
|
2005-12-29 21:29:02 +01:00
|
|
|
make_version_string(version_buf, sizeof(version_buf),
|
2005-12-21 21:50:50 +01:00
|
|
|
plugin->plugin_dl->version),
|
|
|
|
cs);
|
|
|
|
table->field[6]->set_notnull();
|
2005-12-21 19:18:40 +01:00
|
|
|
}
|
|
|
|
else
|
2005-12-21 21:50:50 +01:00
|
|
|
{
|
2005-12-21 19:18:40 +01:00
|
|
|
table->field[5]->set_null();
|
2005-12-21 21:50:50 +01:00
|
|
|
table->field[6]->set_null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-21 19:18:40 +01:00
|
|
|
if (plug->author)
|
|
|
|
{
|
2005-12-21 21:50:50 +01:00
|
|
|
table->field[7]->store(plug->author, strlen(plug->author), cs);
|
|
|
|
table->field[7]->set_notnull();
|
2005-12-21 19:18:40 +01:00
|
|
|
}
|
|
|
|
else
|
2005-12-21 21:50:50 +01:00
|
|
|
table->field[7]->set_null();
|
2005-12-21 19:18:40 +01:00
|
|
|
|
|
|
|
if (plug->descr)
|
|
|
|
{
|
2005-12-21 21:50:50 +01:00
|
|
|
table->field[8]->store(plug->descr, strlen(plug->descr), cs);
|
|
|
|
table->field[8]->set_notnull();
|
2005-12-21 19:18:40 +01:00
|
|
|
}
|
|
|
|
else
|
2005-12-21 21:50:50 +01:00
|
|
|
table->field[8]->set_null();
|
2005-12-21 19:18:40 +01:00
|
|
|
|
|
|
|
return schema_table_store_record(thd, table);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int fill_plugins(THD *thd, TABLE_LIST *tables, COND *cond)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("fill_plugins");
|
|
|
|
TABLE *table= tables->table;
|
|
|
|
|
|
|
|
if (plugin_foreach(thd, show_plugins, MYSQL_ANY_PLUGIN, table))
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-10 18:43:17 +01:00
|
|
|
/***************************************************************************
|
|
|
|
** List all Authors.
|
|
|
|
** If you can update it, you get to be in it :)
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
bool mysqld_show_authors(THD *thd)
|
|
|
|
{
|
|
|
|
List<Item> field_list;
|
|
|
|
Protocol *protocol= thd->protocol;
|
|
|
|
DBUG_ENTER("mysqld_show_authors");
|
|
|
|
|
|
|
|
field_list.push_back(new Item_empty_string("Name",40));
|
|
|
|
field_list.push_back(new Item_empty_string("Location",40));
|
|
|
|
field_list.push_back(new Item_empty_string("Comment",80));
|
|
|
|
|
|
|
|
if (protocol->send_fields(&field_list,
|
|
|
|
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
|
|
|
DBUG_RETURN(TRUE);
|
|
|
|
|
|
|
|
show_table_authors_st *authors;
|
|
|
|
for (authors= show_table_authors; authors->name; authors++)
|
|
|
|
{
|
|
|
|
protocol->prepare_for_resend();
|
|
|
|
protocol->store(authors->name, system_charset_info);
|
|
|
|
protocol->store(authors->location, system_charset_info);
|
|
|
|
protocol->store(authors->comment, system_charset_info);
|
|
|
|
if (protocol->write())
|
|
|
|
DBUG_RETURN(TRUE);
|
|
|
|
}
|
|
|
|
send_eof(thd);
|
|
|
|
DBUG_RETURN(FALSE);
|
|
|
|
}
|
2002-10-02 12:33:08 +02:00
|
|
|
|
2002-06-12 23:13:12 +02:00
|
|
|
/***************************************************************************
|
2002-10-02 12:33:08 +02:00
|
|
|
List all privileges supported
|
2002-06-12 23:13:12 +02:00
|
|
|
***************************************************************************/
|
|
|
|
|
2002-10-02 12:33:08 +02:00
|
|
|
struct show_privileges_st {
|
|
|
|
const char *privilege;
|
|
|
|
const char *context;
|
|
|
|
const char *comment;
|
2002-06-12 23:13:12 +02:00
|
|
|
};
|
|
|
|
|
2002-10-02 12:33:08 +02:00
|
|
|
static struct show_privileges_st sys_privileges[]=
|
|
|
|
{
|
2004-03-24 14:44:31 +01:00
|
|
|
{"Alter", "Tables", "To alter the table"},
|
2004-12-23 11:46:24 +01:00
|
|
|
{"Alter routine", "Functions,Procedures", "To alter or drop stored functions/procedures"},
|
2002-10-02 12:33:08 +02:00
|
|
|
{"Create", "Databases,Tables,Indexes", "To create new databases and tables"},
|
2004-12-23 11:46:24 +01:00
|
|
|
{"Create routine","Functions,Procedures","To use CREATE FUNCTION/PROCEDURE"},
|
2004-07-20 22:03:22 +02:00
|
|
|
{"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"},
|
|
|
|
{"Create view", "Tables", "To create new views"},
|
2005-03-22 15:54:18 +01:00
|
|
|
{"Create user", "Server Admin", "To create new users"},
|
2004-03-24 14:44:31 +01:00
|
|
|
{"Delete", "Tables", "To delete existing rows"},
|
2004-07-20 22:03:22 +02:00
|
|
|
{"Drop", "Databases,Tables", "To drop databases, tables, and views"},
|
2006-02-24 11:52:03 +01:00
|
|
|
{"Event","Server Admin","To create, alter, drop and execute events"},
|
2004-12-23 11:46:24 +01:00
|
|
|
{"Execute", "Functions,Procedures", "To execute stored routines"},
|
2004-03-24 14:44:31 +01:00
|
|
|
{"File", "File access on server", "To read and write files on the server"},
|
2004-12-23 11:46:24 +01:00
|
|
|
{"Grant option", "Databases,Tables,Functions,Procedures", "To give to other users those privileges you possess"},
|
2004-03-24 14:44:31 +01:00
|
|
|
{"Index", "Tables", "To create or drop indexes"},
|
|
|
|
{"Insert", "Tables", "To insert data into tables"},
|
|
|
|
{"Lock tables","Databases","To use LOCK TABLES (together with SELECT privilege)"},
|
|
|
|
{"Process", "Server Admin", "To view the plain text of currently executing queries"},
|
2002-10-02 12:33:08 +02:00
|
|
|
{"References", "Databases,Tables", "To have references on tables"},
|
2004-03-24 14:44:31 +01:00
|
|
|
{"Reload", "Server Admin", "To reload or refresh tables, logs and privileges"},
|
|
|
|
{"Replication client","Server Admin","To ask where the slave or master servers are"},
|
|
|
|
{"Replication slave","Server Admin","To read binary log events from the master"},
|
|
|
|
{"Select", "Tables", "To retrieve rows from table"},
|
|
|
|
{"Show databases","Server Admin","To see all databases with SHOW DATABASES"},
|
2004-07-20 22:03:22 +02:00
|
|
|
{"Show view","Tables","To see views with SHOW CREATE VIEW"},
|
|
|
|
{"Shutdown","Server Admin", "To shut down the server"},
|
2004-03-24 14:44:31 +01:00
|
|
|
{"Super","Server Admin","To use KILL thread, SET GLOBAL, CHANGE MASTER, etc."},
|
2006-02-01 11:28:45 +01:00
|
|
|
{"Trigger","Tables", "To use triggers"},
|
2004-03-24 14:44:31 +01:00
|
|
|
{"Update", "Tables", "To update existing rows"},
|
|
|
|
{"Usage","Server Admin","No privileges - allow connect only"},
|
2002-10-02 12:33:08 +02:00
|
|
|
{NullS, NullS, NullS}
|
|
|
|
};
|
|
|
|
|
2004-10-20 03:04:37 +02:00
|
|
|
bool mysqld_show_privileges(THD *thd)
|
2002-06-12 23:13:12 +02:00
|
|
|
{
|
|
|
|
List<Item> field_list;
|
2002-12-11 08:17:51 +01:00
|
|
|
Protocol *protocol= thd->protocol;
|
2002-06-12 23:13:12 +02:00
|
|
|
DBUG_ENTER("mysqld_show_privileges");
|
|
|
|
|
|
|
|
field_list.push_back(new Item_empty_string("Privilege",10));
|
|
|
|
field_list.push_back(new Item_empty_string("Context",15));
|
|
|
|
field_list.push_back(new Item_empty_string("Comment",NAME_LEN));
|
|
|
|
|
2004-08-03 12:32:21 +02:00
|
|
|
if (protocol->send_fields(&field_list,
|
|
|
|
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2002-06-12 23:13:12 +02:00
|
|
|
|
2002-10-02 12:33:08 +02:00
|
|
|
show_privileges_st *privilege= sys_privileges;
|
|
|
|
for (privilege= sys_privileges; privilege->privilege ; privilege++)
|
2002-06-12 23:13:12 +02:00
|
|
|
{
|
2002-12-11 08:17:51 +01:00
|
|
|
protocol->prepare_for_resend();
|
2003-03-17 10:14:04 +01:00
|
|
|
protocol->store(privilege->privilege, system_charset_info);
|
|
|
|
protocol->store(privilege->context, system_charset_info);
|
|
|
|
protocol->store(privilege->comment, system_charset_info);
|
2002-12-11 08:17:51 +01:00
|
|
|
if (protocol->write())
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2002-06-12 23:13:12 +02:00
|
|
|
}
|
2002-10-02 12:33:08 +02:00
|
|
|
send_eof(thd);
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(FALSE);
|
2002-06-12 23:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
2002-10-02 12:33:08 +02:00
|
|
|
List all column types
|
2002-06-12 23:13:12 +02:00
|
|
|
***************************************************************************/
|
|
|
|
|
2002-10-02 12:33:08 +02:00
|
|
|
struct show_column_type_st
|
|
|
|
{
|
2002-06-12 23:13:12 +02:00
|
|
|
const char *type;
|
|
|
|
uint size;
|
2002-10-02 12:33:08 +02:00
|
|
|
const char *min_value;
|
|
|
|
const char *max_value;
|
|
|
|
uint precision;
|
|
|
|
uint scale;
|
|
|
|
const char *nullable;
|
|
|
|
const char *auto_increment;
|
|
|
|
const char *unsigned_attr;
|
|
|
|
const char *zerofill;
|
|
|
|
const char *searchable;
|
|
|
|
const char *case_sensitivity;
|
|
|
|
const char *default_value;
|
|
|
|
const char *comment;
|
2002-06-12 23:13:12 +02:00
|
|
|
};
|
2002-10-02 12:33:08 +02:00
|
|
|
|
|
|
|
/* TODO: Add remaning types */
|
|
|
|
|
|
|
|
static struct show_column_type_st sys_column_types[]=
|
|
|
|
{
|
2002-06-12 23:13:12 +02:00
|
|
|
{"tinyint",
|
|
|
|
1, "-128", "127", 0, 0, "YES", "YES",
|
2004-03-24 14:44:31 +01:00
|
|
|
"NO", "YES", "YES", "NO", "NULL,0",
|
|
|
|
"A very small integer"},
|
2002-06-12 23:13:12 +02:00
|
|
|
{"tinyint unsigned",
|
2004-03-24 14:44:31 +01:00
|
|
|
1, "0" , "255", 0, 0, "YES", "YES",
|
|
|
|
"YES", "YES", "YES", "NO", "NULL,0",
|
2002-06-12 23:13:12 +02:00
|
|
|
"A very small integer"},
|
|
|
|
};
|
|
|
|
|
2004-10-20 03:04:37 +02:00
|
|
|
bool mysqld_show_column_types(THD *thd)
|
2002-06-12 23:13:12 +02:00
|
|
|
{
|
|
|
|
List<Item> field_list;
|
2002-12-11 08:17:51 +01:00
|
|
|
Protocol *protocol= thd->protocol;
|
2002-06-12 23:13:12 +02:00
|
|
|
DBUG_ENTER("mysqld_show_column_types");
|
|
|
|
|
|
|
|
field_list.push_back(new Item_empty_string("Type",30));
|
|
|
|
field_list.push_back(new Item_int("Size",(longlong) 1,21));
|
|
|
|
field_list.push_back(new Item_empty_string("Min_Value",20));
|
|
|
|
field_list.push_back(new Item_empty_string("Max_Value",20));
|
2002-12-11 08:17:51 +01:00
|
|
|
field_list.push_back(new Item_return_int("Prec", 4, MYSQL_TYPE_SHORT));
|
|
|
|
field_list.push_back(new Item_return_int("Scale", 4, MYSQL_TYPE_SHORT));
|
2002-06-12 23:13:12 +02:00
|
|
|
field_list.push_back(new Item_empty_string("Nullable",4));
|
|
|
|
field_list.push_back(new Item_empty_string("Auto_Increment",4));
|
|
|
|
field_list.push_back(new Item_empty_string("Unsigned",4));
|
|
|
|
field_list.push_back(new Item_empty_string("Zerofill",4));
|
|
|
|
field_list.push_back(new Item_empty_string("Searchable",4));
|
|
|
|
field_list.push_back(new Item_empty_string("Case_Sensitive",4));
|
|
|
|
field_list.push_back(new Item_empty_string("Default",NAME_LEN));
|
|
|
|
field_list.push_back(new Item_empty_string("Comment",NAME_LEN));
|
|
|
|
|
2004-08-03 12:32:21 +02:00
|
|
|
if (protocol->send_fields(&field_list,
|
|
|
|
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2002-06-12 23:13:12 +02:00
|
|
|
|
2002-10-02 12:33:08 +02:00
|
|
|
/* TODO: Change the loop to not use 'i' */
|
2002-06-12 23:13:12 +02:00
|
|
|
for (uint i=0; i < sizeof(sys_column_types)/sizeof(sys_column_types[0]); i++)
|
|
|
|
{
|
2002-12-11 08:17:51 +01:00
|
|
|
protocol->prepare_for_resend();
|
2003-03-17 10:14:04 +01:00
|
|
|
protocol->store(sys_column_types[i].type, system_charset_info);
|
2002-12-11 08:17:51 +01:00
|
|
|
protocol->store((ulonglong) sys_column_types[i].size);
|
2003-03-17 10:14:04 +01:00
|
|
|
protocol->store(sys_column_types[i].min_value, system_charset_info);
|
|
|
|
protocol->store(sys_column_types[i].max_value, system_charset_info);
|
2002-12-11 08:17:51 +01:00
|
|
|
protocol->store_short((longlong) sys_column_types[i].precision);
|
|
|
|
protocol->store_short((longlong) sys_column_types[i].scale);
|
2003-03-17 10:14:04 +01:00
|
|
|
protocol->store(sys_column_types[i].nullable, system_charset_info);
|
|
|
|
protocol->store(sys_column_types[i].auto_increment, system_charset_info);
|
|
|
|
protocol->store(sys_column_types[i].unsigned_attr, system_charset_info);
|
|
|
|
protocol->store(sys_column_types[i].zerofill, system_charset_info);
|
|
|
|
protocol->store(sys_column_types[i].searchable, system_charset_info);
|
|
|
|
protocol->store(sys_column_types[i].case_sensitivity, system_charset_info);
|
|
|
|
protocol->store(sys_column_types[i].default_value, system_charset_info);
|
|
|
|
protocol->store(sys_column_types[i].comment, system_charset_info);
|
2002-12-11 08:17:51 +01:00
|
|
|
if (protocol->write())
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2002-06-12 23:13:12 +02:00
|
|
|
}
|
2002-10-02 12:33:08 +02:00
|
|
|
send_eof(thd);
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(FALSE);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-07-10 11:13:05 +02:00
|
|
|
int
|
2000-07-31 21:29:14 +02:00
|
|
|
mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
|
2000-09-01 13:24:36 +02:00
|
|
|
const char *wild, bool dir)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
uint i;
|
|
|
|
char *ext;
|
|
|
|
MY_DIR *dirp;
|
|
|
|
FILEINFO *file;
|
2004-04-05 12:56:05 +02:00
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
2000-07-31 21:29:14 +02:00
|
|
|
uint col_access=thd->col_access;
|
2004-04-05 12:56:05 +02:00
|
|
|
#endif
|
2000-07-31 21:29:14 +02:00
|
|
|
TABLE_LIST table_list;
|
|
|
|
DBUG_ENTER("mysql_find_files");
|
|
|
|
|
2001-08-28 05:43:55 +02:00
|
|
|
if (wild && !wild[0])
|
|
|
|
wild=0;
|
2004-09-21 12:13:58 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
bzero((char*) &table_list,sizeof(table_list));
|
|
|
|
|
2005-08-17 17:51:10 +02:00
|
|
|
if (!(dirp = my_dir(path,MYF(dir ? MY_WANT_STAT : 0))))
|
|
|
|
{
|
|
|
|
if (my_errno == ENOENT)
|
|
|
|
my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), db);
|
|
|
|
else
|
|
|
|
my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), path, my_errno);
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_RETURN(-1);
|
2005-08-17 17:51:10 +02:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2000-09-01 13:24:36 +02:00
|
|
|
for (i=0 ; i < (uint) dirp->number_off_files ; i++)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-12-31 06:01:26 +01:00
|
|
|
char uname[NAME_LEN*3+1]; /* Unencoded name */
|
2000-07-31 21:29:14 +02:00
|
|
|
file=dirp->dir_entry+i;
|
|
|
|
if (dir)
|
2000-09-01 13:24:36 +02:00
|
|
|
{ /* Return databases */
|
2005-12-31 06:01:26 +01:00
|
|
|
if ((file->name[0] == '.' &&
|
|
|
|
((file->name[1] == '.' && file->name[2] == '\0') ||
|
|
|
|
file->name[1] == '\0')))
|
|
|
|
continue; /* . or .. */
|
2000-07-31 21:29:14 +02:00
|
|
|
#ifdef USE_SYMDIR
|
|
|
|
char *ext;
|
2004-09-25 18:43:07 +02:00
|
|
|
char buff[FN_REFLEN];
|
2000-07-31 21:29:14 +02:00
|
|
|
if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym"))
|
2003-12-11 05:24:08 +01:00
|
|
|
{
|
|
|
|
/* Only show the sym file if it points to a directory */
|
2004-09-25 18:43:07 +02:00
|
|
|
char *end;
|
2000-09-01 13:24:36 +02:00
|
|
|
*ext=0; /* Remove extension */
|
2003-12-11 05:24:08 +01:00
|
|
|
unpack_dirname(buff, file->name);
|
|
|
|
end= strend(buff);
|
|
|
|
if (end != buff && end[-1] == FN_LIBCHAR)
|
|
|
|
end[-1]= 0; // Remove end FN_LIBCHAR
|
2004-09-25 18:43:07 +02:00
|
|
|
if (!my_stat(buff, file->mystat, MYF(0)))
|
|
|
|
continue;
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
#endif
|
2005-12-31 09:34:39 +01:00
|
|
|
if (!MY_S_ISDIR(file->mystat->st_mode))
|
|
|
|
continue;
|
2005-12-31 06:01:26 +01:00
|
|
|
VOID(filename_to_tablename(file->name, uname, sizeof(uname)));
|
2005-12-31 09:34:39 +01:00
|
|
|
if (wild && wild_compare(uname, wild, 0))
|
2005-12-31 06:01:26 +01:00
|
|
|
continue;
|
|
|
|
file->name= uname;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-12-18 22:22:20 +01:00
|
|
|
// Return only .frm files which aren't temp files.
|
2005-12-31 06:01:26 +01:00
|
|
|
if (my_strcasecmp(system_charset_info, ext=fn_rext(file->name),reg_ext) ||
|
2000-12-18 22:22:20 +01:00
|
|
|
is_prefix(file->name,tmp_file_prefix))
|
2000-09-01 13:24:36 +02:00
|
|
|
continue;
|
2000-07-31 21:29:14 +02:00
|
|
|
*ext=0;
|
2005-12-31 06:01:26 +01:00
|
|
|
VOID(filename_to_tablename(file->name, uname, sizeof(uname)));
|
|
|
|
file->name= uname;
|
2001-08-28 05:43:55 +02:00
|
|
|
if (wild)
|
|
|
|
{
|
|
|
|
if (lower_case_table_names)
|
|
|
|
{
|
2004-05-22 21:41:58 +02:00
|
|
|
if (wild_case_compare(files_charset_info, file->name, wild))
|
2001-08-28 05:43:55 +02:00
|
|
|
continue;
|
|
|
|
}
|
2003-07-22 22:21:23 +02:00
|
|
|
else if (wild_compare(file->name,wild,0))
|
2001-08-28 05:43:55 +02:00
|
|
|
continue;
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2003-09-26 12:33:13 +02:00
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
2000-07-31 21:29:14 +02:00
|
|
|
/* Don't show tables where we don't have any privileges */
|
|
|
|
if (db && !(col_access & TABLE_ACLS))
|
|
|
|
{
|
|
|
|
table_list.db= (char*) db;
|
2005-02-08 20:52:50 +01:00
|
|
|
table_list.db_length= strlen(db);
|
2005-01-06 12:00:13 +01:00
|
|
|
table_list.table_name= file->name;
|
2005-02-08 20:52:50 +01:00
|
|
|
table_list.table_name_length= strlen(file->name);
|
2000-07-31 21:29:14 +02:00
|
|
|
table_list.grant.privilege=col_access;
|
2004-04-10 00:14:32 +02:00
|
|
|
if (check_grant(thd, TABLE_ACLS, &table_list, 1, UINT_MAX, 1))
|
2000-09-01 13:24:36 +02:00
|
|
|
continue;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2003-09-26 12:33:13 +02:00
|
|
|
#endif
|
2000-08-21 02:00:52 +02:00
|
|
|
if (files->push_back(thd->strdup(file->name)))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
my_dirend(dirp);
|
|
|
|
DBUG_RETURN(-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DBUG_PRINT("info",("found: %d files", files->elements));
|
|
|
|
my_dirend(dirp);
|
2004-09-26 16:11:24 +02:00
|
|
|
|
|
|
|
VOID(ha_find_files(thd,db,path,wild,dir,files));
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
2002-10-02 12:33:08 +02:00
|
|
|
|
2004-10-20 03:04:37 +02:00
|
|
|
bool
|
2000-07-31 21:29:14 +02:00
|
|
|
mysqld_show_create(THD *thd, TABLE_LIST *table_list)
|
|
|
|
{
|
2002-12-11 08:17:51 +01:00
|
|
|
Protocol *protocol= thd->protocol;
|
|
|
|
char buff[2048];
|
|
|
|
String buffer(buff, sizeof(buff), system_charset_info);
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_ENTER("mysqld_show_create");
|
|
|
|
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
|
2005-01-06 12:00:13 +01:00
|
|
|
table_list->table_name));
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2005-06-16 01:27:41 +02:00
|
|
|
/* We want to preserve the tree for views. */
|
|
|
|
thd->lex->view_prepare_mode= TRUE;
|
|
|
|
|
2004-07-16 00:15:55 +02:00
|
|
|
/* Only one table for now, but VIEW can involve several tables */
|
2005-08-08 15:46:06 +02:00
|
|
|
if (open_normal_and_derived_tables(thd, table_list, 0))
|
2005-11-11 10:39:46 +01:00
|
|
|
{
|
|
|
|
if (!table_list->view || thd->net.last_errno != ER_VIEW_INVALID)
|
|
|
|
DBUG_RETURN(TRUE);
|
2006-02-13 17:53:34 +01:00
|
|
|
|
2005-11-11 10:39:46 +01:00
|
|
|
/*
|
|
|
|
Clear all messages with 'error' level status and
|
|
|
|
issue a warning with 'warning' level status in
|
|
|
|
case of invalid view and last error is ER_VIEW_INVALID
|
|
|
|
*/
|
|
|
|
mysql_reset_errors(thd, true);
|
2006-02-27 14:52:14 +01:00
|
|
|
thd->clear_error();
|
|
|
|
|
2005-11-11 10:39:46 +01:00
|
|
|
push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
|
|
ER_VIEW_INVALID,
|
|
|
|
ER(ER_VIEW_INVALID),
|
|
|
|
table_list->view_db.str,
|
|
|
|
table_list->view_name.str);
|
|
|
|
}
|
2005-09-01 11:36:42 +02:00
|
|
|
|
2004-07-16 00:15:55 +02:00
|
|
|
/* TODO: add environment variables show when it become possible */
|
|
|
|
if (thd->lex->only_view && !table_list->view)
|
|
|
|
{
|
2004-11-13 18:35:51 +01:00
|
|
|
my_error(ER_WRONG_OBJECT, MYF(0),
|
2005-01-06 12:00:13 +01:00
|
|
|
table_list->db, table_list->table_name, "VIEW");
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2004-07-16 00:15:55 +02:00
|
|
|
}
|
2004-09-24 11:50:10 +02:00
|
|
|
|
2005-09-01 11:36:42 +02:00
|
|
|
buffer.length(0);
|
2004-07-16 00:15:55 +02:00
|
|
|
if ((table_list->view ?
|
|
|
|
view_store_create_info(thd, table_list, &buffer) :
|
2005-12-22 06:39:02 +01:00
|
|
|
store_create_info(thd, table_list, &buffer, NULL)))
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2003-08-21 20:21:07 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
List<Item> field_list;
|
2004-09-24 11:50:10 +02:00
|
|
|
if (table_list->view)
|
|
|
|
{
|
|
|
|
field_list.push_back(new Item_empty_string("View",NAME_LEN));
|
|
|
|
field_list.push_back(new Item_empty_string("Create View",
|
|
|
|
max(buffer.length(),1024)));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
field_list.push_back(new Item_empty_string("Table",NAME_LEN));
|
|
|
|
// 1024 is for not to confuse old clients
|
|
|
|
field_list.push_back(new Item_empty_string("Create Table",
|
|
|
|
max(buffer.length(),1024)));
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2004-08-03 12:32:21 +02:00
|
|
|
if (protocol->send_fields(&field_list,
|
|
|
|
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2002-12-11 08:17:51 +01:00
|
|
|
protocol->prepare_for_resend();
|
2004-07-16 00:15:55 +02:00
|
|
|
if (table_list->view)
|
|
|
|
protocol->store(table_list->view_name.str, system_charset_info);
|
|
|
|
else
|
|
|
|
{
|
2004-11-18 10:16:06 +01:00
|
|
|
if (table_list->schema_table)
|
2005-05-31 10:15:23 +02:00
|
|
|
protocol->store(table_list->schema_table->table_name,
|
|
|
|
system_charset_info);
|
2004-11-18 10:16:06 +01:00
|
|
|
else
|
2005-09-01 11:36:42 +02:00
|
|
|
protocol->store(table_list->table->alias, system_charset_info);
|
2004-07-16 00:15:55 +02:00
|
|
|
}
|
2003-03-17 10:14:04 +01:00
|
|
|
protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
|
2004-07-16 00:15:55 +02:00
|
|
|
|
2002-12-11 08:17:51 +01:00
|
|
|
if (protocol->write())
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2002-10-02 12:33:08 +02:00
|
|
|
send_eof(thd);
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(FALSE);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2004-10-20 03:04:37 +02:00
|
|
|
bool mysqld_show_create_db(THD *thd, char *dbname,
|
|
|
|
HA_CREATE_INFO *create_info)
|
2004-01-30 07:32:35 +01:00
|
|
|
{
|
2005-09-20 20:20:38 +02:00
|
|
|
Security_context *sctx= thd->security_ctx;
|
2004-01-30 07:32:35 +01:00
|
|
|
int length;
|
2005-09-15 21:29:07 +02:00
|
|
|
char path[FN_REFLEN];
|
2004-01-30 07:32:35 +01:00
|
|
|
char buff[2048];
|
|
|
|
String buffer(buff, sizeof(buff), system_charset_info);
|
2004-04-05 12:56:05 +02:00
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
2004-01-30 07:32:35 +01:00
|
|
|
uint db_access;
|
2004-04-05 12:56:05 +02:00
|
|
|
#endif
|
2004-01-30 07:32:35 +01:00
|
|
|
bool found_libchar;
|
|
|
|
HA_CREATE_INFO create;
|
|
|
|
uint create_options = create_info ? create_info->options : 0;
|
|
|
|
Protocol *protocol=thd->protocol;
|
|
|
|
DBUG_ENTER("mysql_show_create_db");
|
|
|
|
|
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
2005-09-20 20:20:38 +02:00
|
|
|
if (test_all_bits(sctx->master_access, DB_ACLS))
|
2004-01-30 07:32:35 +01:00
|
|
|
db_access=DB_ACLS;
|
|
|
|
else
|
2005-09-15 21:29:07 +02:00
|
|
|
db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, dbname, 0) |
|
|
|
|
sctx->master_access);
|
2004-01-30 07:32:35 +01:00
|
|
|
if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
|
|
|
|
{
|
2004-11-13 18:35:51 +01:00
|
|
|
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
|
2005-09-15 21:29:07 +02:00
|
|
|
sctx->priv_user, sctx->host_or_ip, dbname);
|
2006-01-19 03:56:06 +01:00
|
|
|
general_log_print(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
|
|
|
|
sctx->priv_user, sctx->host_or_ip, dbname);
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2004-01-30 07:32:35 +01:00
|
|
|
}
|
|
|
|
#endif
|
2005-06-16 10:27:22 +02:00
|
|
|
if (!my_strcasecmp(system_charset_info, dbname,
|
|
|
|
information_schema_name.str))
|
2004-01-30 07:32:35 +01:00
|
|
|
{
|
2005-06-16 10:27:22 +02:00
|
|
|
dbname= information_schema_name.str;
|
|
|
|
create.default_table_charset= system_charset_info;
|
2004-01-30 07:32:35 +01:00
|
|
|
}
|
2005-06-16 10:27:22 +02:00
|
|
|
else
|
2004-01-30 07:32:35 +01:00
|
|
|
{
|
2005-12-31 06:01:26 +01:00
|
|
|
length= build_table_filename(path, sizeof(path), dbname, "", "");
|
2005-06-16 10:27:22 +02:00
|
|
|
found_libchar= 0;
|
|
|
|
if (length && path[length-1] == FN_LIBCHAR)
|
|
|
|
{
|
|
|
|
found_libchar= 1;
|
|
|
|
path[length-1]=0; // remove ending '\'
|
|
|
|
}
|
|
|
|
if (access(path,F_OK))
|
|
|
|
{
|
|
|
|
my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
|
|
|
|
DBUG_RETURN(TRUE);
|
|
|
|
}
|
|
|
|
if (found_libchar)
|
|
|
|
path[length-1]= FN_LIBCHAR;
|
|
|
|
strmov(path+length, MY_DB_OPT_FILE);
|
|
|
|
load_db_opt(thd, path, &create);
|
2004-01-30 07:32:35 +01:00
|
|
|
}
|
|
|
|
List<Item> field_list;
|
|
|
|
field_list.push_back(new Item_empty_string("Database",NAME_LEN));
|
|
|
|
field_list.push_back(new Item_empty_string("Create Database",1024));
|
|
|
|
|
2004-08-03 12:32:21 +02:00
|
|
|
if (protocol->send_fields(&field_list,
|
|
|
|
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2004-01-30 07:32:35 +01:00
|
|
|
|
|
|
|
protocol->prepare_for_resend();
|
|
|
|
protocol->store(dbname, strlen(dbname), system_charset_info);
|
|
|
|
buffer.length(0);
|
2005-11-20 19:47:07 +01:00
|
|
|
buffer.append(STRING_WITH_LEN("CREATE DATABASE "));
|
2004-01-30 07:32:35 +01:00
|
|
|
if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS)
|
2005-11-20 19:47:07 +01:00
|
|
|
buffer.append(STRING_WITH_LEN("/*!32312 IF NOT EXISTS*/ "));
|
2004-01-30 07:32:35 +01:00
|
|
|
append_identifier(thd, &buffer, dbname, strlen(dbname));
|
|
|
|
|
|
|
|
if (create.default_table_charset)
|
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
buffer.append(STRING_WITH_LEN(" /*!40100"));
|
|
|
|
buffer.append(STRING_WITH_LEN(" DEFAULT CHARACTER SET "));
|
2004-01-30 07:32:35 +01:00
|
|
|
buffer.append(create.default_table_charset->csname);
|
|
|
|
if (!(create.default_table_charset->state & MY_CS_PRIMARY))
|
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
buffer.append(STRING_WITH_LEN(" COLLATE "));
|
2004-01-30 07:32:35 +01:00
|
|
|
buffer.append(create.default_table_charset->name);
|
|
|
|
}
|
2005-11-20 19:47:07 +01:00
|
|
|
buffer.append(STRING_WITH_LEN(" */"));
|
2004-01-30 07:32:35 +01:00
|
|
|
}
|
|
|
|
protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
|
|
|
|
|
|
|
|
if (protocol->write())
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2004-01-30 07:32:35 +01:00
|
|
|
send_eof(thd);
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(FALSE);
|
2004-01-30 07:32:35 +01:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2000-12-15 12:18:52 +01:00
|
|
|
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
/****************************************************************************
|
2002-10-02 12:33:08 +02:00
|
|
|
Return only fields for API mysql_list_fields
|
|
|
|
Use "show table wildcard" in mysql instead of this
|
2000-07-31 21:29:14 +02:00
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
void
|
|
|
|
mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
|
|
|
|
{
|
|
|
|
TABLE *table;
|
|
|
|
DBUG_ENTER("mysqld_list_fields");
|
2005-01-06 12:00:13 +01:00
|
|
|
DBUG_PRINT("enter",("table: %s",table_list->table_name));
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2005-08-08 15:46:06 +02:00
|
|
|
if (open_normal_and_derived_tables(thd, table_list, 0))
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_VOID_RETURN;
|
2004-09-07 14:50:56 +02:00
|
|
|
table= table_list->table;
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
List<Item> field_list;
|
|
|
|
|
|
|
|
Field **ptr,*field;
|
|
|
|
for (ptr=table->field ; (field= *ptr); ptr++)
|
|
|
|
{
|
2002-03-12 18:37:58 +01:00
|
|
|
if (!wild || !wild[0] ||
|
|
|
|
!wild_case_compare(system_charset_info, field->field_name,wild))
|
2000-07-31 21:29:14 +02:00
|
|
|
field_list.push_back(new Item_field(field));
|
|
|
|
}
|
2005-01-06 12:00:13 +01:00
|
|
|
restore_record(table, s->default_values); // Get empty record
|
2004-08-03 12:32:21 +02:00
|
|
|
if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS |
|
|
|
|
Protocol::SEND_EOF))
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_VOID_RETURN;
|
2004-11-02 19:13:27 +01:00
|
|
|
thd->protocol->flush();
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
2002-10-02 12:33:08 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
int
|
2004-11-18 10:16:06 +01:00
|
|
|
mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2002-12-11 08:17:51 +01:00
|
|
|
Protocol *protocol= thd->protocol;
|
|
|
|
String *packet= protocol->storage_packet();
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_ENTER("mysqld_dump_create_info");
|
2005-11-23 21:45:02 +01:00
|
|
|
DBUG_PRINT("enter",("table: %s",table_list->table->s->table_name.str));
|
2001-04-11 13:04:03 +02:00
|
|
|
|
2002-12-11 08:17:51 +01:00
|
|
|
protocol->prepare_for_resend();
|
2005-12-22 06:39:02 +01:00
|
|
|
if (store_create_info(thd, table_list, packet, NULL))
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_RETURN(-1);
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2001-04-11 13:04:03 +02:00
|
|
|
if (fd < 0)
|
2000-09-01 13:24:36 +02:00
|
|
|
{
|
2002-12-11 08:17:51 +01:00
|
|
|
if (protocol->write())
|
2000-09-01 13:24:36 +02:00
|
|
|
DBUG_RETURN(-1);
|
2004-11-02 19:13:27 +01:00
|
|
|
protocol->flush();
|
2000-09-01 13:24:36 +02:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
else
|
2000-09-01 13:24:36 +02:00
|
|
|
{
|
2001-10-08 22:20:19 +02:00
|
|
|
if (my_write(fd, (const byte*) packet->ptr(), packet->length(),
|
|
|
|
MYF(MY_WME)))
|
2000-09-01 13:24:36 +02:00
|
|
|
DBUG_RETURN(-1);
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2004-02-06 21:57:22 +01:00
|
|
|
/*
|
2004-02-17 00:35:17 +01:00
|
|
|
Go through all character combinations and ensure that sql_lex.cc can
|
2004-10-07 00:45:06 +02:00
|
|
|
parse it as an identifier.
|
2004-02-06 21:57:22 +01:00
|
|
|
|
|
|
|
SYNOPSIS
|
2004-02-17 00:35:17 +01:00
|
|
|
require_quotes()
|
|
|
|
name attribute name
|
|
|
|
name_length length of name
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
# Pointer to conflicting character
|
|
|
|
0 No conflicting character
|
2004-02-06 21:57:22 +01:00
|
|
|
*/
|
|
|
|
|
2004-02-17 00:35:17 +01:00
|
|
|
static const char *require_quotes(const char *name, uint name_length)
|
2004-02-06 21:57:22 +01:00
|
|
|
{
|
2004-02-17 00:35:17 +01:00
|
|
|
uint length;
|
|
|
|
const char *end= name + name_length;
|
|
|
|
|
2005-08-20 10:00:00 +02:00
|
|
|
for (; name < end ; name++)
|
2004-02-06 21:57:22 +01:00
|
|
|
{
|
2004-02-17 00:35:17 +01:00
|
|
|
uchar chr= (uchar) *name;
|
|
|
|
length= my_mbcharlen(system_charset_info, chr);
|
|
|
|
if (length == 1 && !system_charset_info->ident_map[chr])
|
|
|
|
return name;
|
2004-01-14 11:52:25 +01:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2002-10-02 12:33:08 +02:00
|
|
|
|
2004-02-17 00:35:17 +01:00
|
|
|
|
2003-06-27 15:29:10 +02:00
|
|
|
void
|
|
|
|
append_identifier(THD *thd, String *packet, const char *name, uint length)
|
2000-10-10 21:31:00 +02:00
|
|
|
{
|
2004-02-17 00:35:17 +01:00
|
|
|
const char *name_end;
|
|
|
|
char quote_char;
|
2004-10-01 10:51:59 +02:00
|
|
|
int q= get_quote_char_for_identifier(thd, name, length);
|
2004-02-17 00:35:17 +01:00
|
|
|
|
2004-10-20 00:28:42 +02:00
|
|
|
if (q == EOF)
|
2000-10-10 21:31:00 +02:00
|
|
|
{
|
2004-10-01 10:51:59 +02:00
|
|
|
packet->append(name, length, system_charset_info);
|
2004-02-17 00:35:17 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-10-20 00:28:42 +02:00
|
|
|
/*
|
|
|
|
The identifier must be quoted as it includes a quote character or
|
|
|
|
it's a keyword
|
|
|
|
*/
|
2004-02-17 00:35:17 +01:00
|
|
|
|
2006-01-03 17:54:54 +01:00
|
|
|
VOID(packet->reserve(length*2 + 2));
|
2004-10-20 00:28:42 +02:00
|
|
|
quote_char= (char) q;
|
2004-02-17 00:35:17 +01:00
|
|
|
packet->append("e_char, 1, system_charset_info);
|
|
|
|
|
|
|
|
for (name_end= name+length ; name < name_end ; name+= length)
|
|
|
|
{
|
2004-10-20 00:28:42 +02:00
|
|
|
uchar chr= (uchar) *name;
|
2004-02-17 00:35:17 +01:00
|
|
|
length= my_mbcharlen(system_charset_info, chr);
|
2004-12-02 08:39:50 +01:00
|
|
|
/*
|
|
|
|
my_mbcharlen can retur 0 on a wrong multibyte
|
|
|
|
sequence. It is possible when upgrading from 4.0,
|
|
|
|
and identifier contains some accented characters.
|
|
|
|
The manual says it does not work. So we'll just
|
|
|
|
change length to 1 not to hang in the endless loop.
|
|
|
|
*/
|
|
|
|
if (!length)
|
|
|
|
length= 1;
|
2004-10-20 00:28:42 +02:00
|
|
|
if (length == 1 && chr == (uchar) quote_char)
|
2004-02-17 00:35:17 +01:00
|
|
|
packet->append("e_char, 1, system_charset_info);
|
|
|
|
packet->append(name, length, packet->charset());
|
2000-10-10 21:31:00 +02:00
|
|
|
}
|
2004-02-17 00:35:17 +01:00
|
|
|
packet->append("e_char, 1, system_charset_info);
|
2000-10-10 21:31:00 +02:00
|
|
|
}
|
|
|
|
|
2003-08-23 11:25:39 +02:00
|
|
|
|
2004-10-20 00:28:42 +02:00
|
|
|
/*
|
|
|
|
Get the quote character for displaying an identifier.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
get_quote_char_for_identifier()
|
|
|
|
thd Thread handler
|
|
|
|
name name to quote
|
|
|
|
length length of name
|
|
|
|
|
|
|
|
IMPLEMENTATION
|
|
|
|
If name is a keyword or includes a special character, then force
|
|
|
|
quoting.
|
|
|
|
Otherwise identifier is quoted only if the option OPTION_QUOTE_SHOW_CREATE
|
|
|
|
is set.
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
EOF No quote character is needed
|
|
|
|
# Quote character
|
|
|
|
*/
|
2004-10-01 10:51:59 +02:00
|
|
|
|
|
|
|
int get_quote_char_for_identifier(THD *thd, const char *name, uint length)
|
|
|
|
{
|
|
|
|
if (!is_keyword(name,length) &&
|
|
|
|
!require_quotes(name, length) &&
|
|
|
|
!(thd->options & OPTION_QUOTE_SHOW_CREATE))
|
|
|
|
return EOF;
|
2004-10-20 00:28:42 +02:00
|
|
|
if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
|
2004-10-01 10:51:59 +02:00
|
|
|
return '"';
|
2004-10-20 00:28:42 +02:00
|
|
|
return '`';
|
2004-10-01 10:51:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-08-23 11:25:39 +02:00
|
|
|
/* Append directory name (if exists) to CREATE INFO */
|
|
|
|
|
|
|
|
static void append_directory(THD *thd, String *packet, const char *dir_type,
|
|
|
|
const char *filename)
|
|
|
|
{
|
2003-09-11 18:06:23 +02:00
|
|
|
if (filename && !(thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE))
|
2003-08-23 11:25:39 +02:00
|
|
|
{
|
2004-10-20 00:28:42 +02:00
|
|
|
uint length= dirname_length(filename);
|
2003-08-23 11:25:39 +02:00
|
|
|
packet->append(' ');
|
|
|
|
packet->append(dir_type);
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" DIRECTORY='"));
|
2005-03-15 18:33:06 +01:00
|
|
|
#ifdef __WIN__
|
2005-03-16 15:11:01 +01:00
|
|
|
/* Convert \ to / to be able to create table on unix */
|
|
|
|
char *winfilename= (char*) thd->memdup(filename, length);
|
|
|
|
char *pos, *end;
|
|
|
|
for (pos= winfilename, end= pos+length ; pos < end ; pos++)
|
|
|
|
{
|
|
|
|
if (*pos == '\\')
|
|
|
|
*pos = '/';
|
|
|
|
}
|
|
|
|
filename= winfilename;
|
2005-03-15 18:33:06 +01:00
|
|
|
#endif
|
2005-03-16 15:11:01 +01:00
|
|
|
packet->append(filename, length);
|
2003-08-23 11:25:39 +02:00
|
|
|
packet->append('\'');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-03-16 18:17:54 +01:00
|
|
|
#define LIST_PROCESS_HOST_LEN 64
|
2002-10-02 12:33:08 +02:00
|
|
|
|
2005-12-22 06:39:02 +01:00
|
|
|
/*
|
|
|
|
Build a CREATE TABLE statement for a table.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
store_create_info()
|
|
|
|
thd The thread
|
|
|
|
table_list A list containing one table to write statement
|
|
|
|
for.
|
|
|
|
packet Pointer to a string where statement will be
|
|
|
|
written.
|
|
|
|
create_info_arg Pointer to create information that can be used
|
|
|
|
to tailor the format of the statement. Can be
|
|
|
|
NULL, in which case only SQL_MODE is considered
|
|
|
|
when building the statement.
|
|
|
|
|
|
|
|
NOTE
|
|
|
|
Currently always return 0, but might return error code in the
|
|
|
|
future.
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
0 OK
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
|
|
|
|
HA_CREATE_INFO *create_info_arg)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2003-08-23 11:25:39 +02:00
|
|
|
List<Item> field_list;
|
2005-12-31 06:01:26 +01:00
|
|
|
char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end, uname[NAME_LEN*3+1];
|
2005-01-06 12:00:13 +01:00
|
|
|
const char *alias;
|
2004-05-25 12:54:03 +02:00
|
|
|
String type(tmp, sizeof(tmp), system_charset_info);
|
2003-08-23 11:25:39 +02:00
|
|
|
Field **ptr,*field;
|
|
|
|
uint primary_key;
|
|
|
|
KEY *key_info;
|
2004-11-18 10:16:06 +01:00
|
|
|
TABLE *table= table_list->table;
|
2003-08-23 11:25:39 +02:00
|
|
|
handler *file= table->file;
|
2005-01-06 12:00:13 +01:00
|
|
|
TABLE_SHARE *share= table->s;
|
2003-08-23 11:25:39 +02:00
|
|
|
HA_CREATE_INFO create_info;
|
2003-06-04 17:28:51 +02:00
|
|
|
my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
|
|
|
|
MODE_ORACLE |
|
|
|
|
MODE_MSSQL |
|
|
|
|
MODE_DB2 |
|
2003-10-15 11:50:36 +02:00
|
|
|
MODE_MAXDB |
|
2003-06-04 17:28:51 +02:00
|
|
|
MODE_ANSI)) != 0;
|
|
|
|
my_bool limited_mysql_mode= (thd->variables.sql_mode &
|
|
|
|
(MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
|
|
|
|
MODE_MYSQL40)) != 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_ENTER("store_create_info");
|
2005-11-23 21:45:02 +01:00
|
|
|
DBUG_PRINT("enter",("table: %s", table->s->table_name.str));
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2005-01-06 12:00:13 +01:00
|
|
|
restore_record(table, s->default_values); // Get empty record
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->tmp_table)
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
|
2001-04-25 21:44:27 +02:00
|
|
|
else
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN("CREATE TABLE "));
|
2004-11-18 10:16:06 +01:00
|
|
|
if (table_list->schema_table)
|
2005-05-31 10:15:23 +02:00
|
|
|
alias= table_list->schema_table->table_name;
|
2004-11-18 10:16:06 +01:00
|
|
|
else
|
2005-12-31 06:01:26 +01:00
|
|
|
{
|
|
|
|
if (lower_case_table_names == 2)
|
|
|
|
alias= table->alias;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
alias= share->table_name.str;
|
|
|
|
}
|
|
|
|
}
|
2004-02-11 00:06:46 +01:00
|
|
|
append_identifier(thd, packet, alias, strlen(alias));
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" (\n"));
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
for (ptr=table->field ; (field= *ptr); ptr++)
|
|
|
|
{
|
2003-08-23 11:25:39 +02:00
|
|
|
bool has_default;
|
2004-04-02 08:12:53 +02:00
|
|
|
bool has_now_default;
|
2003-08-23 11:25:39 +02:00
|
|
|
uint flags = field->flags;
|
|
|
|
|
2001-02-17 13:19:19 +01:00
|
|
|
if (ptr != table->field)
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(",\n"));
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" "));
|
2003-06-27 15:29:10 +02:00
|
|
|
append_identifier(thd,packet,field->field_name, strlen(field->field_name));
|
2000-07-31 21:29:14 +02:00
|
|
|
packet->append(' ');
|
|
|
|
// check for surprises from the previous call to Field::sql_type()
|
2001-02-17 13:19:19 +01:00
|
|
|
if (type.ptr() != tmp)
|
2004-06-08 11:26:16 +02:00
|
|
|
type.set(tmp, sizeof(tmp), system_charset_info);
|
2004-09-24 10:14:44 +02:00
|
|
|
else
|
|
|
|
type.set_charset(system_charset_info);
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
field->sql_type(type);
|
2004-05-25 12:54:03 +02:00
|
|
|
packet->append(type.ptr(), type.length(), system_charset_info);
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2005-09-29 13:17:45 +02:00
|
|
|
if (field->has_charset() &&
|
|
|
|
!(thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)))
|
2003-01-09 12:37:59 +01:00
|
|
|
{
|
2005-01-06 12:00:13 +01:00
|
|
|
if (field->charset() != share->table_charset)
|
2003-05-23 10:10:25 +02:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" character set "));
|
2004-03-26 13:11:46 +01:00
|
|
|
packet->append(field->charset()->csname);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
For string types dump collation name only if
|
|
|
|
collation is not primary for the given charset
|
|
|
|
*/
|
|
|
|
if (!(field->charset()->state & MY_CS_PRIMARY))
|
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" collate "));
|
2004-03-26 13:11:46 +01:00
|
|
|
packet->append(field->charset()->name);
|
2003-05-23 10:10:25 +02:00
|
|
|
}
|
2003-01-09 12:37:59 +01:00
|
|
|
}
|
2003-05-23 10:10:25 +02:00
|
|
|
|
2000-10-24 01:39:54 +02:00
|
|
|
if (flags & NOT_NULL_FLAG)
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" NOT NULL"));
|
2004-10-01 16:54:06 +02:00
|
|
|
else if (field->type() == FIELD_TYPE_TIMESTAMP)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
TIMESTAMP field require explicit NULL flag, because unlike
|
|
|
|
all other fields they are treated as NOT NULL by default.
|
|
|
|
*/
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" NULL"));
|
2004-10-01 16:54:06 +02:00
|
|
|
}
|
2004-04-02 08:12:53 +02:00
|
|
|
|
|
|
|
/*
|
2004-04-06 11:13:43 +02:00
|
|
|
Again we are using CURRENT_TIMESTAMP instead of NOW because it is
|
2004-04-02 08:12:53 +02:00
|
|
|
more standard
|
|
|
|
*/
|
|
|
|
has_now_default= table->timestamp_field == field &&
|
|
|
|
field->unireg_check != Field::TIMESTAMP_UN_FIELD;
|
|
|
|
|
2003-08-23 11:25:39 +02:00
|
|
|
has_default= (field->type() != FIELD_TYPE_BLOB &&
|
2004-10-02 21:20:08 +02:00
|
|
|
!(field->flags & NO_DEFAULT_VALUE_FLAG) &&
|
2004-04-02 08:12:53 +02:00
|
|
|
field->unireg_check != Field::NEXT_NUMBER &&
|
2005-09-29 13:17:45 +02:00
|
|
|
!((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) &&
|
2004-04-02 08:12:53 +02:00
|
|
|
has_now_default));
|
2003-05-23 10:10:25 +02:00
|
|
|
|
2000-10-24 01:39:54 +02:00
|
|
|
if (has_default)
|
2000-09-01 13:24:36 +02:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" default "));
|
2004-04-02 08:12:53 +02:00
|
|
|
if (has_now_default)
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
|
2004-04-02 08:12:53 +02:00
|
|
|
else if (!field->is_null())
|
2000-09-01 13:24:36 +02:00
|
|
|
{ // Not null by default
|
2003-12-15 18:01:38 +01:00
|
|
|
type.set(tmp, sizeof(tmp), field->charset());
|
2004-04-06 21:35:26 +02:00
|
|
|
field->val_str(&type);
|
2001-02-17 13:19:19 +01:00
|
|
|
if (type.length())
|
2003-12-16 14:39:33 +01:00
|
|
|
{
|
2004-04-06 21:35:26 +02:00
|
|
|
String def_val;
|
2004-10-29 14:00:39 +02:00
|
|
|
uint dummy_errors;
|
2003-12-16 14:39:33 +01:00
|
|
|
/* convert to system_charset_info == utf8 */
|
|
|
|
def_val.copy(type.ptr(), type.length(), field->charset(),
|
2004-10-29 14:00:39 +02:00
|
|
|
system_charset_info, &dummy_errors);
|
2003-12-16 14:39:33 +01:00
|
|
|
append_unescaped(packet, def_val.ptr(), def_val.length());
|
|
|
|
}
|
2002-06-02 20:22:20 +02:00
|
|
|
else
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN("''"));
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2000-10-24 01:39:54 +02:00
|
|
|
else if (field->maybe_null())
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN("NULL")); // Null as default
|
2000-09-01 13:24:36 +02:00
|
|
|
else
|
2004-05-25 12:54:03 +02:00
|
|
|
packet->append(tmp);
|
2000-09-01 13:24:36 +02:00
|
|
|
}
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2005-09-29 13:17:45 +02:00
|
|
|
if (!(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS) &&
|
2004-04-02 08:12:53 +02:00
|
|
|
table->timestamp_field == field &&
|
|
|
|
field->unireg_check != Field::TIMESTAMP_DN_FIELD)
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" on update CURRENT_TIMESTAMP"));
|
2004-04-02 08:12:53 +02:00
|
|
|
|
2005-09-29 13:17:45 +02:00
|
|
|
if (field->unireg_check == Field::NEXT_NUMBER &&
|
|
|
|
!(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS))
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" auto_increment"));
|
2002-06-02 20:22:20 +02:00
|
|
|
|
|
|
|
if (field->comment.length)
|
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" COMMENT "));
|
2002-06-02 20:22:20 +02:00
|
|
|
append_unescaped(packet, field->comment.str, field->comment.length);
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2003-08-23 11:25:39 +02:00
|
|
|
key_info= table->key_info;
|
2003-08-25 16:19:44 +02:00
|
|
|
bzero((char*) &create_info, sizeof(create_info));
|
2003-08-23 11:25:39 +02:00
|
|
|
file->update_create_info(&create_info);
|
2005-01-06 12:00:13 +01:00
|
|
|
primary_key= share->primary_key;
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2005-01-06 12:00:13 +01:00
|
|
|
for (uint i=0 ; i < share->keys ; i++,key_info++)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2001-06-21 09:50:14 +02:00
|
|
|
KEY_PART_INFO *key_part= key_info->key_part;
|
|
|
|
bool found_primary=0;
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(",\n "));
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2004-01-14 13:01:55 +01:00
|
|
|
if (i == primary_key && !strcmp(key_info->name, primary_key_name))
|
2001-06-21 09:50:14 +02:00
|
|
|
{
|
|
|
|
found_primary=1;
|
2006-02-02 20:39:28 +01:00
|
|
|
/*
|
|
|
|
No space at end, because a space will be added after where the
|
|
|
|
identifier would go, but that is not added for primary key.
|
|
|
|
*/
|
|
|
|
packet->append(STRING_WITH_LEN("PRIMARY KEY"));
|
2001-06-21 09:50:14 +02:00
|
|
|
}
|
2001-02-17 13:19:19 +01:00
|
|
|
else if (key_info->flags & HA_NOSAME)
|
2006-02-02 20:39:28 +01:00
|
|
|
packet->append(STRING_WITH_LEN("UNIQUE KEY "));
|
2001-02-17 13:19:19 +01:00
|
|
|
else if (key_info->flags & HA_FULLTEXT)
|
2006-02-02 20:39:28 +01:00
|
|
|
packet->append(STRING_WITH_LEN("FULLTEXT KEY "));
|
2002-02-22 12:24:42 +01:00
|
|
|
else if (key_info->flags & HA_SPATIAL)
|
2006-02-02 20:39:28 +01:00
|
|
|
packet->append(STRING_WITH_LEN("SPATIAL KEY "));
|
|
|
|
else
|
|
|
|
packet->append(STRING_WITH_LEN("KEY "));
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2001-06-21 09:50:14 +02:00
|
|
|
if (!found_primary)
|
2003-06-27 15:29:10 +02:00
|
|
|
append_identifier(thd, packet, key_info->name, strlen(key_info->name));
|
2002-02-22 12:24:42 +01:00
|
|
|
|
2003-01-16 01:04:50 +01:00
|
|
|
if (!(thd->variables.sql_mode & MODE_NO_KEY_OPTIONS) &&
|
|
|
|
!limited_mysql_mode && !foreign_db_mode)
|
|
|
|
{
|
2005-01-08 06:15:41 +01:00
|
|
|
if (key_info->algorithm == HA_KEY_ALG_BTREE)
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" USING BTREE"));
|
2005-01-13 18:31:54 +01:00
|
|
|
|
2005-01-08 06:15:41 +01:00
|
|
|
if (key_info->algorithm == HA_KEY_ALG_HASH)
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" USING HASH"));
|
2005-01-13 18:31:54 +01:00
|
|
|
|
2003-01-16 01:04:50 +01:00
|
|
|
// +BAR: send USING only in non-default case: non-spatial rtree
|
|
|
|
if ((key_info->algorithm == HA_KEY_ALG_RTREE) &&
|
|
|
|
!(key_info->flags & HA_SPATIAL))
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" USING RTREE"));
|
2005-01-08 06:15:41 +01:00
|
|
|
|
2005-01-13 18:31:54 +01:00
|
|
|
// No need to send USING FULLTEXT, it is sent as FULLTEXT KEY
|
2003-01-16 01:04:50 +01:00
|
|
|
}
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" ("));
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
|
|
|
|
{
|
2000-09-28 23:58:16 +02:00
|
|
|
if (j)
|
2000-09-01 13:24:36 +02:00
|
|
|
packet->append(',');
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2000-09-28 23:58:16 +02:00
|
|
|
if (key_part->field)
|
2003-06-27 15:29:10 +02:00
|
|
|
append_identifier(thd,packet,key_part->field->field_name,
|
|
|
|
strlen(key_part->field->field_name));
|
2006-01-03 17:54:54 +01:00
|
|
|
if (key_part->field &&
|
2000-09-01 13:24:36 +02:00
|
|
|
(key_part->length !=
|
|
|
|
table->field[key_part->fieldnr-1]->key_length() &&
|
|
|
|
!(key_info->flags & HA_FULLTEXT)))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2000-09-01 13:24:36 +02:00
|
|
|
buff[0] = '(';
|
2006-01-03 17:54:54 +01:00
|
|
|
char* end=int10_to_str((long) key_part->length /
|
2003-09-15 11:45:42 +02:00
|
|
|
key_part->field->charset()->mbmaxlen,
|
|
|
|
buff + 1,10);
|
2000-09-01 13:24:36 +02:00
|
|
|
*end++ = ')';
|
|
|
|
packet->append(buff,(uint) (end-buff));
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
packet->append(')');
|
2005-11-06 13:13:06 +01:00
|
|
|
if (key_info->parser)
|
|
|
|
{
|
|
|
|
packet->append(" WITH PARSER ", 13);
|
|
|
|
append_identifier(thd, packet, key_info->parser->name.str,
|
|
|
|
key_info->parser->name.length);
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2003-06-27 15:29:10 +02:00
|
|
|
/*
|
|
|
|
Get possible foreign key definitions stored in InnoDB and append them
|
|
|
|
to the CREATE TABLE statement
|
|
|
|
*/
|
2002-03-21 17:05:46 +01:00
|
|
|
|
2003-08-23 11:25:39 +02:00
|
|
|
if ((for_str= file->get_foreign_key_create_info()))
|
2003-06-27 15:29:10 +02:00
|
|
|
{
|
|
|
|
packet->append(for_str, strlen(for_str));
|
|
|
|
file->free_foreign_key_create_info(for_str);
|
2002-03-21 17:05:46 +01:00
|
|
|
}
|
|
|
|
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN("\n)"));
|
2003-01-16 01:04:50 +01:00
|
|
|
if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode)
|
2002-06-19 18:21:30 +02:00
|
|
|
{
|
2006-01-31 18:46:44 +01:00
|
|
|
/*
|
|
|
|
Get possible table space definitions and append them
|
|
|
|
to the CREATE TABLE statement
|
|
|
|
*/
|
|
|
|
|
2006-02-13 21:55:49 +01:00
|
|
|
if ((for_str= file->get_tablespace_name(thd)))
|
2006-01-31 18:46:44 +01:00
|
|
|
{
|
2006-02-01 11:56:20 +01:00
|
|
|
packet->append(" TABLESPACE ");
|
2006-01-31 18:46:44 +01:00
|
|
|
packet->append(for_str, strlen(for_str));
|
2006-02-01 11:56:20 +01:00
|
|
|
packet->append(" STORAGE DISK");
|
2006-01-31 18:46:44 +01:00
|
|
|
my_free(for_str, MYF(0));
|
|
|
|
}
|
|
|
|
|
2005-12-22 06:39:02 +01:00
|
|
|
/*
|
|
|
|
IF check_create_info
|
|
|
|
THEN add ENGINE only if it was used when creating the table
|
|
|
|
*/
|
|
|
|
if (!create_info_arg ||
|
|
|
|
(create_info_arg->used_fields & HA_CREATE_USED_ENGINE))
|
|
|
|
{
|
|
|
|
if (thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
|
|
|
|
packet->append(STRING_WITH_LEN(" TYPE="));
|
|
|
|
else
|
|
|
|
packet->append(STRING_WITH_LEN(" ENGINE="));
|
2005-11-07 16:25:06 +01:00
|
|
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
2005-11-23 21:45:02 +01:00
|
|
|
if (table->part_info)
|
2005-12-21 19:18:40 +01:00
|
|
|
packet->append(ha_resolve_storage_engine_name(
|
|
|
|
table->part_info->default_engine_type));
|
2005-09-20 16:29:59 +02:00
|
|
|
else
|
2005-07-18 13:31:02 +02:00
|
|
|
packet->append(file->table_type());
|
2005-09-20 16:29:59 +02:00
|
|
|
#else
|
2005-12-22 06:39:02 +01:00
|
|
|
packet->append(file->table_type());
|
2005-09-20 16:29:59 +02:00
|
|
|
#endif
|
2005-12-22 06:39:02 +01:00
|
|
|
}
|
2003-01-16 01:04:50 +01:00
|
|
|
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->table_charset &&
|
2003-01-16 04:35:59 +01:00
|
|
|
!(thd->variables.sql_mode & MODE_MYSQL323) &&
|
|
|
|
!(thd->variables.sql_mode & MODE_MYSQL40))
|
2003-01-09 12:37:59 +01:00
|
|
|
{
|
2005-12-22 06:39:02 +01:00
|
|
|
/*
|
|
|
|
IF check_create_info
|
|
|
|
THEN add DEFAULT CHARSET only if it was used when creating the table
|
|
|
|
*/
|
|
|
|
if (!create_info_arg ||
|
|
|
|
(create_info_arg->used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
|
2003-01-16 01:04:50 +01:00
|
|
|
{
|
2005-12-22 06:39:02 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" DEFAULT CHARSET="));
|
|
|
|
packet->append(share->table_charset->csname);
|
|
|
|
if (!(share->table_charset->state & MY_CS_PRIMARY))
|
|
|
|
{
|
|
|
|
packet->append(STRING_WITH_LEN(" COLLATE="));
|
|
|
|
packet->append(table->s->table_charset->name);
|
|
|
|
}
|
2003-01-16 01:04:50 +01:00
|
|
|
}
|
2003-01-09 12:37:59 +01:00
|
|
|
}
|
2002-06-19 18:21:30 +02:00
|
|
|
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->min_rows)
|
2003-01-16 01:04:50 +01:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" MIN_ROWS="));
|
2005-01-06 12:00:13 +01:00
|
|
|
end= longlong10_to_str(share->min_rows, buff, 10);
|
2003-08-29 12:44:35 +02:00
|
|
|
packet->append(buff, (uint) (end- buff));
|
2003-01-16 01:04:50 +01:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2005-03-25 10:19:11 +01:00
|
|
|
if (share->max_rows && !table_list->schema_table)
|
2003-01-16 01:04:50 +01:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" MAX_ROWS="));
|
2005-01-06 12:00:13 +01:00
|
|
|
end= longlong10_to_str(share->max_rows, buff, 10);
|
2003-08-29 12:44:35 +02:00
|
|
|
packet->append(buff, (uint) (end - buff));
|
2003-01-16 01:04:50 +01:00
|
|
|
}
|
2003-08-29 12:44:35 +02:00
|
|
|
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->avg_row_length)
|
2003-01-16 01:04:50 +01:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" AVG_ROW_LENGTH="));
|
2005-01-06 12:00:13 +01:00
|
|
|
end= longlong10_to_str(share->avg_row_length, buff,10);
|
2003-08-29 12:44:35 +02:00
|
|
|
packet->append(buff, (uint) (end - buff));
|
2003-01-16 01:04:50 +01:00
|
|
|
}
|
2000-08-29 17:44:22 +02:00
|
|
|
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->db_create_options & HA_OPTION_PACK_KEYS)
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" PACK_KEYS=0"));
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->db_create_options & HA_OPTION_CHECKSUM)
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" CHECKSUM=1"));
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" DELAY_KEY_WRITE=1"));
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->row_type != ROW_TYPE_DEFAULT)
|
2003-01-16 01:04:50 +01:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
|
2005-01-06 12:00:13 +01:00
|
|
|
packet->append(ha_row_type[(uint) share->row_type]);
|
2003-01-16 01:04:50 +01:00
|
|
|
}
|
|
|
|
table->file->append_create_info(packet);
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->comment && share->comment[0])
|
2003-01-16 01:04:50 +01:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" COMMENT="));
|
2005-01-06 12:00:13 +01:00
|
|
|
append_unescaped(packet, share->comment, strlen(share->comment));
|
2003-01-16 01:04:50 +01:00
|
|
|
}
|
2005-10-11 02:41:36 +02:00
|
|
|
if (share->connect_string.length)
|
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
packet->append(STRING_WITH_LEN(" CONNECTION="));
|
2005-10-11 02:41:36 +02:00
|
|
|
append_unescaped(packet, share->connect_string.str, share->connect_string.length);
|
|
|
|
}
|
2003-08-29 12:44:35 +02:00
|
|
|
append_directory(thd, packet, "DATA", create_info.data_file_name);
|
|
|
|
append_directory(thd, packet, "INDEX", create_info.index_file_name);
|
2000-12-22 12:25:49 +01:00
|
|
|
}
|
2005-11-07 16:25:06 +01:00
|
|
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
2005-07-18 13:31:02 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
Partition syntax for CREATE TABLE is at the end of the syntax.
|
|
|
|
*/
|
|
|
|
uint part_syntax_len;
|
|
|
|
char *part_syntax;
|
2005-11-23 21:45:02 +01:00
|
|
|
if (table->part_info &&
|
|
|
|
((part_syntax= generate_partition_syntax(table->part_info,
|
2006-01-17 08:40:00 +01:00
|
|
|
&part_syntax_len,
|
|
|
|
FALSE,FALSE))))
|
2005-07-18 13:31:02 +02:00
|
|
|
{
|
|
|
|
packet->append(part_syntax, part_syntax_len);
|
|
|
|
my_free(part_syntax, MYF(0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
2005-09-14 09:53:09 +02:00
|
|
|
void
|
|
|
|
view_store_options(THD *thd, TABLE_LIST *table, String *buff)
|
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
buff->append(STRING_WITH_LEN("ALGORITHM="));
|
2005-09-14 09:53:09 +02:00
|
|
|
switch ((int8)table->algorithm) {
|
|
|
|
case VIEW_ALGORITHM_UNDEFINED:
|
2005-11-20 19:47:07 +01:00
|
|
|
buff->append(STRING_WITH_LEN("UNDEFINED "));
|
2005-09-14 09:53:09 +02:00
|
|
|
break;
|
|
|
|
case VIEW_ALGORITHM_TMPTABLE:
|
2005-11-20 19:47:07 +01:00
|
|
|
buff->append(STRING_WITH_LEN("TEMPTABLE "));
|
2005-09-14 09:53:09 +02:00
|
|
|
break;
|
|
|
|
case VIEW_ALGORITHM_MERGE:
|
2005-11-20 19:47:07 +01:00
|
|
|
buff->append(STRING_WITH_LEN("MERGE "));
|
2005-09-14 09:53:09 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0); // never should happen
|
|
|
|
}
|
2005-11-10 20:25:03 +01:00
|
|
|
append_definer(thd, buff, &table->definer.user, &table->definer.host);
|
2005-09-14 09:53:09 +02:00
|
|
|
if (table->view_suid)
|
2005-11-20 19:47:07 +01:00
|
|
|
buff->append(STRING_WITH_LEN("SQL SECURITY DEFINER "));
|
2005-09-14 09:53:09 +02:00
|
|
|
else
|
2005-11-20 19:47:07 +01:00
|
|
|
buff->append(STRING_WITH_LEN("SQL SECURITY INVOKER "));
|
2005-09-14 09:53:09 +02:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2005-11-10 20:25:03 +01:00
|
|
|
/*
|
|
|
|
Append DEFINER clause to the given buffer.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
append_definer()
|
|
|
|
thd [in] thread handle
|
|
|
|
buffer [inout] buffer to hold DEFINER clause
|
|
|
|
definer_user [in] user name part of definer
|
|
|
|
definer_host [in] host name part of definer
|
|
|
|
*/
|
|
|
|
|
|
|
|
void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user,
|
|
|
|
const LEX_STRING *definer_host)
|
|
|
|
{
|
|
|
|
buffer->append(STRING_WITH_LEN("DEFINER="));
|
|
|
|
append_identifier(thd, buffer, definer_user->str, definer_user->length);
|
|
|
|
buffer->append('@');
|
|
|
|
append_identifier(thd, buffer, definer_host->str, definer_host->length);
|
|
|
|
buffer->append(' ');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-22 06:39:02 +01:00
|
|
|
int
|
2004-07-16 00:15:55 +02:00
|
|
|
view_store_create_info(THD *thd, TABLE_LIST *table, String *buff)
|
|
|
|
{
|
|
|
|
my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
|
|
|
|
MODE_ORACLE |
|
|
|
|
MODE_MSSQL |
|
|
|
|
MODE_DB2 |
|
|
|
|
MODE_MAXDB |
|
|
|
|
MODE_ANSI)) != 0;
|
2005-09-01 11:36:42 +02:00
|
|
|
/*
|
|
|
|
Compact output format for view can be used
|
|
|
|
- if user has db of this view as current db
|
|
|
|
- if this view only references table inside it's own db
|
|
|
|
*/
|
2005-09-13 12:43:43 +02:00
|
|
|
if (!thd->db || strcmp(thd->db, table->view_db.str))
|
2005-09-01 11:36:42 +02:00
|
|
|
table->compact_view_format= FALSE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TABLE_LIST *tbl;
|
2005-09-13 12:43:43 +02:00
|
|
|
table->compact_view_format= TRUE;
|
2005-09-01 11:36:42 +02:00
|
|
|
for (tbl= thd->lex->query_tables;
|
|
|
|
tbl;
|
|
|
|
tbl= tbl->next_global)
|
|
|
|
{
|
|
|
|
if (strcmp(table->view_db.str, tbl->view ? tbl->view_db.str :tbl->db)!= 0)
|
|
|
|
{
|
|
|
|
table->compact_view_format= FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-20 19:47:07 +01:00
|
|
|
buff->append(STRING_WITH_LEN("CREATE "));
|
2004-10-07 14:43:04 +02:00
|
|
|
if (!foreign_db_mode)
|
2004-07-16 00:15:55 +02:00
|
|
|
{
|
2005-09-14 09:53:09 +02:00
|
|
|
view_store_options(thd, table, buff);
|
2004-07-16 00:15:55 +02:00
|
|
|
}
|
2005-11-20 19:47:07 +01:00
|
|
|
buff->append(STRING_WITH_LEN("VIEW "));
|
2005-09-01 11:36:42 +02:00
|
|
|
if (!table->compact_view_format)
|
|
|
|
{
|
|
|
|
append_identifier(thd, buff, table->view_db.str, table->view_db.length);
|
|
|
|
buff->append('.');
|
|
|
|
}
|
2004-08-24 22:07:34 +02:00
|
|
|
append_identifier(thd, buff, table->view_name.str, table->view_name.length);
|
2005-11-20 19:47:07 +01:00
|
|
|
buff->append(STRING_WITH_LEN(" AS "));
|
2005-06-16 01:27:41 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
We can't just use table->query, because our SQL_MODE may trigger
|
|
|
|
a different syntax, like when ANSI_QUOTES is defined.
|
|
|
|
*/
|
|
|
|
table->view->unit.print(buff);
|
|
|
|
|
2004-10-07 14:43:04 +02:00
|
|
|
if (table->with_check != VIEW_CHECK_NONE)
|
|
|
|
{
|
|
|
|
if (table->with_check == VIEW_CHECK_LOCAL)
|
2005-11-20 19:47:07 +01:00
|
|
|
buff->append(STRING_WITH_LEN(" WITH LOCAL CHECK OPTION"));
|
2004-10-07 14:43:04 +02:00
|
|
|
else
|
2005-11-20 19:47:07 +01:00
|
|
|
buff->append(STRING_WITH_LEN(" WITH CASCADED CHECK OPTION"));
|
2004-10-07 14:43:04 +02:00
|
|
|
}
|
2004-07-16 00:15:55 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
/****************************************************************************
|
2002-10-02 12:33:08 +02:00
|
|
|
Return info about all processes
|
|
|
|
returns for each thread: thread id, user, host, db, command, info
|
2000-07-31 21:29:14 +02:00
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
class thread_info :public ilink {
|
|
|
|
public:
|
2004-11-28 15:53:17 +01:00
|
|
|
static void *operator new(size_t size)
|
|
|
|
{
|
|
|
|
return (void*) sql_alloc((uint) size);
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
static void operator delete(void *ptr __attribute__((unused)),
|
2004-11-28 15:53:17 +01:00
|
|
|
size_t size __attribute__((unused)))
|
|
|
|
{ TRASH(ptr, size); }
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2000-08-23 14:02:27 +02:00
|
|
|
ulong thread_id;
|
|
|
|
time_t start_time;
|
2000-09-01 13:24:36 +02:00
|
|
|
uint command;
|
2000-07-31 21:29:14 +02:00
|
|
|
const char *user,*host,*db,*proc_info,*state_info;
|
|
|
|
char *query;
|
|
|
|
};
|
|
|
|
|
2005-06-22 11:08:28 +02:00
|
|
|
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
|
2000-07-31 21:29:14 +02:00
|
|
|
template class I_List<thread_info>;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void mysqld_list_processes(THD *thd,const char *user, bool verbose)
|
|
|
|
{
|
|
|
|
Item *field;
|
|
|
|
List<Item> field_list;
|
|
|
|
I_List<thread_info> thread_infos;
|
2002-07-23 17:31:22 +02:00
|
|
|
ulong max_query_length= (verbose ? thd->variables.max_allowed_packet :
|
|
|
|
PROCESS_LIST_WIDTH);
|
2002-12-11 08:17:51 +01:00
|
|
|
Protocol *protocol= thd->protocol;
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_ENTER("mysqld_list_processes");
|
|
|
|
|
2002-12-11 08:17:51 +01:00
|
|
|
field_list.push_back(new Item_int("Id",0,11));
|
2000-07-31 21:29:14 +02:00
|
|
|
field_list.push_back(new Item_empty_string("User",16));
|
2003-02-17 21:07:26 +01:00
|
|
|
field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN));
|
2000-07-31 21:29:14 +02:00
|
|
|
field_list.push_back(field=new Item_empty_string("db",NAME_LEN));
|
|
|
|
field->maybe_null=1;
|
|
|
|
field_list.push_back(new Item_empty_string("Command",16));
|
2002-12-11 08:17:51 +01:00
|
|
|
field_list.push_back(new Item_return_int("Time",7, FIELD_TYPE_LONG));
|
2000-07-31 21:29:14 +02:00
|
|
|
field_list.push_back(field=new Item_empty_string("State",30));
|
|
|
|
field->maybe_null=1;
|
|
|
|
field_list.push_back(field=new Item_empty_string("Info",max_query_length));
|
|
|
|
field->maybe_null=1;
|
2004-08-03 12:32:21 +02:00
|
|
|
if (protocol->send_fields(&field_list,
|
|
|
|
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
|
|
|
|
VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
|
|
|
|
if (!thd->killed)
|
|
|
|
{
|
|
|
|
I_List_iterator<THD> it(threads);
|
|
|
|
THD *tmp;
|
|
|
|
while ((tmp=it++))
|
|
|
|
{
|
2005-09-20 20:20:38 +02:00
|
|
|
Security_context *tmp_sctx= tmp->security_ctx;
|
2002-12-11 11:44:17 +01:00
|
|
|
struct st_my_thread_var *mysys_var;
|
2004-05-28 12:59:29 +02:00
|
|
|
if ((tmp->vio_ok() || tmp->system_thread) &&
|
2005-09-15 21:29:07 +02:00
|
|
|
(!user || (tmp_sctx->user && !strcmp(tmp_sctx->user, user))))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-09-15 21:29:07 +02:00
|
|
|
thread_info *thd_info= new thread_info;
|
2000-09-01 13:24:36 +02:00
|
|
|
|
|
|
|
thd_info->thread_id=tmp->thread_id;
|
2005-09-15 21:29:07 +02:00
|
|
|
thd_info->user= thd->strdup(tmp_sctx->user ? tmp_sctx->user :
|
|
|
|
(tmp->system_thread ?
|
|
|
|
"system user" : "unauthenticated user"));
|
|
|
|
if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) &&
|
|
|
|
thd->security_ctx->host_or_ip[0])
|
2003-02-17 21:07:26 +01:00
|
|
|
{
|
|
|
|
if ((thd_info->host= thd->alloc(LIST_PROCESS_HOST_LEN+1)))
|
2003-02-28 20:17:44 +01:00
|
|
|
my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN,
|
2005-09-15 21:29:07 +02:00
|
|
|
"%s:%u", tmp_sctx->host_or_ip, tmp->peer_port);
|
2003-02-17 21:07:26 +01:00
|
|
|
}
|
|
|
|
else
|
2005-09-22 21:03:53 +02:00
|
|
|
thd_info->host= thd->strdup(tmp_sctx->host_or_ip);
|
2000-09-01 13:24:36 +02:00
|
|
|
if ((thd_info->db=tmp->db)) // Safe test
|
|
|
|
thd_info->db=thd->strdup(thd_info->db);
|
|
|
|
thd_info->command=(int) tmp->command;
|
2002-12-11 11:44:17 +01:00
|
|
|
if ((mysys_var= tmp->mysys_var))
|
|
|
|
pthread_mutex_lock(&mysys_var->mutex);
|
2003-03-31 10:39:46 +02:00
|
|
|
thd_info->proc_info= (char*) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0);
|
2003-01-15 09:11:44 +01:00
|
|
|
#ifndef EMBEDDED_LIBRARY
|
2000-09-01 13:24:36 +02:00
|
|
|
thd_info->state_info= (char*) (tmp->locked ? "Locked" :
|
|
|
|
tmp->net.reading_or_writing ?
|
|
|
|
(tmp->net.reading_or_writing == 2 ?
|
|
|
|
"Writing to net" :
|
|
|
|
thd_info->command == COM_SLEEP ? "" :
|
|
|
|
"Reading from net") :
|
|
|
|
tmp->proc_info ? tmp->proc_info :
|
|
|
|
tmp->mysys_var &&
|
|
|
|
tmp->mysys_var->current_cond ?
|
|
|
|
"Waiting on cond" : NullS);
|
2003-01-15 09:11:44 +01:00
|
|
|
#else
|
|
|
|
thd_info->state_info= (char*)"Writing to net";
|
|
|
|
#endif
|
2002-12-11 11:44:17 +01:00
|
|
|
if (mysys_var)
|
|
|
|
pthread_mutex_unlock(&mysys_var->mutex);
|
2000-07-31 21:29:14 +02:00
|
|
|
|
|
|
|
#if !defined(DONT_USE_THR_ALARM) && ! defined(SCO)
|
2000-09-01 13:24:36 +02:00
|
|
|
if (pthread_kill(tmp->real_id,0))
|
|
|
|
tmp->proc_info="*** DEAD ***"; // This shouldn't happen
|
2000-07-31 21:29:14 +02:00
|
|
|
#endif
|
2001-04-01 12:45:48 +02:00
|
|
|
#ifdef EXTRA_DEBUG
|
|
|
|
thd_info->start_time= tmp->time_after_lock;
|
|
|
|
#else
|
2000-09-01 13:24:36 +02:00
|
|
|
thd_info->start_time= tmp->start_time;
|
2001-04-01 12:45:48 +02:00
|
|
|
#endif
|
2000-09-01 13:24:36 +02:00
|
|
|
thd_info->query=0;
|
|
|
|
if (tmp->query)
|
|
|
|
{
|
2004-05-14 15:48:56 +02:00
|
|
|
/*
|
|
|
|
query_length is always set to 0 when we set query = NULL; see
|
|
|
|
the comment in sql_class.h why this prevents crashes in possible
|
|
|
|
races with query_length
|
|
|
|
*/
|
2001-12-05 12:03:00 +01:00
|
|
|
uint length= min(max_query_length, tmp->query_length);
|
2004-05-15 08:08:03 +02:00
|
|
|
thd_info->query=(char*) thd->strmake(tmp->query,length);
|
2000-09-01 13:24:36 +02:00
|
|
|
}
|
|
|
|
thread_infos.append(thd_info);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
|
|
|
|
|
|
thread_info *thd_info;
|
2002-12-11 08:17:51 +01:00
|
|
|
time_t now= time(0);
|
2000-07-31 21:29:14 +02:00
|
|
|
while ((thd_info=thread_infos.get()))
|
|
|
|
{
|
2002-12-11 08:17:51 +01:00
|
|
|
protocol->prepare_for_resend();
|
|
|
|
protocol->store((ulonglong) thd_info->thread_id);
|
2003-03-17 10:14:04 +01:00
|
|
|
protocol->store(thd_info->user, system_charset_info);
|
|
|
|
protocol->store(thd_info->host, system_charset_info);
|
|
|
|
protocol->store(thd_info->db, system_charset_info);
|
2000-07-31 21:29:14 +02:00
|
|
|
if (thd_info->proc_info)
|
2003-03-17 10:14:04 +01:00
|
|
|
protocol->store(thd_info->proc_info, system_charset_info);
|
2000-07-31 21:29:14 +02:00
|
|
|
else
|
2006-01-19 03:56:06 +01:00
|
|
|
protocol->store(command_name[thd_info->command].str, system_charset_info);
|
2000-07-31 21:29:14 +02:00
|
|
|
if (thd_info->start_time)
|
2002-12-11 08:17:51 +01:00
|
|
|
protocol->store((uint32) (now - thd_info->start_time));
|
2000-07-31 21:29:14 +02:00
|
|
|
else
|
2002-12-11 08:17:51 +01:00
|
|
|
protocol->store_null();
|
2003-03-17 10:14:04 +01:00
|
|
|
protocol->store(thd_info->state_info, system_charset_info);
|
|
|
|
protocol->store(thd_info->query, system_charset_info);
|
2002-12-11 08:17:51 +01:00
|
|
|
if (protocol->write())
|
2000-07-31 21:29:14 +02:00
|
|
|
break; /* purecov: inspected */
|
|
|
|
}
|
2002-10-02 12:33:08 +02:00
|
|
|
send_eof(thd);
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
2006-02-16 14:45:05 +01:00
|
|
|
int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
|
|
|
|
{
|
|
|
|
TABLE *table= tables->table;
|
|
|
|
CHARSET_INFO *cs= system_charset_info;
|
|
|
|
char *user;
|
|
|
|
bool verbose;
|
|
|
|
ulong max_query_length;
|
|
|
|
time_t now= time(0);
|
|
|
|
DBUG_ENTER("fill_process_list");
|
|
|
|
|
|
|
|
user= thd->security_ctx->master_access & PROCESS_ACL ?
|
|
|
|
NullS : thd->security_ctx->priv_user;
|
|
|
|
verbose= thd->lex->verbose;
|
|
|
|
max_query_length= PROCESS_LIST_WIDTH;
|
|
|
|
|
|
|
|
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
|
|
|
|
|
|
|
if (!thd->killed)
|
|
|
|
{
|
|
|
|
I_List_iterator<THD> it(threads);
|
|
|
|
THD* tmp;
|
|
|
|
|
|
|
|
while ((tmp= it++))
|
|
|
|
{
|
|
|
|
Security_context *tmp_sctx= tmp->security_ctx;
|
|
|
|
struct st_my_thread_var *mysys_var;
|
|
|
|
const char *val;
|
|
|
|
|
|
|
|
if ((!tmp->vio_ok() && !tmp->system_thread) ||
|
|
|
|
(user && (!tmp_sctx->user || strcmp(tmp_sctx->user, user))))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
restore_record(table, s->default_values);
|
|
|
|
/* ID */
|
|
|
|
table->field[0]->store((longlong) tmp->thread_id, TRUE);
|
|
|
|
/* USER */
|
|
|
|
val= tmp_sctx->user ? tmp_sctx->user :
|
|
|
|
(tmp->system_thread ? "system user" : "unauthenticated user");
|
|
|
|
table->field[1]->store(val, strlen(val), cs);
|
|
|
|
/* HOST */
|
|
|
|
if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) &&
|
|
|
|
thd->security_ctx->host_or_ip[0])
|
|
|
|
{
|
|
|
|
char host[LIST_PROCESS_HOST_LEN + 1];
|
|
|
|
my_snprintf(host, LIST_PROCESS_HOST_LEN, "%s:%u",
|
|
|
|
tmp_sctx->host_or_ip, tmp->peer_port);
|
|
|
|
table->field[2]->store(host, strlen(host), cs);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
table->field[2]->store(tmp_sctx->host_or_ip,
|
|
|
|
strlen(tmp_sctx->host_or_ip), cs);
|
|
|
|
/* DB */
|
|
|
|
if (tmp->db)
|
|
|
|
{
|
|
|
|
table->field[3]->store(tmp->db, strlen(tmp->db), cs);
|
|
|
|
table->field[3]->set_notnull();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((mysys_var= tmp->mysys_var))
|
|
|
|
pthread_mutex_lock(&mysys_var->mutex);
|
|
|
|
/* COMMAND */
|
|
|
|
if ((val= (char *) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0)))
|
|
|
|
table->field[4]->store(val, strlen(val), cs);
|
|
|
|
else
|
|
|
|
table->field[4]->store(command_name[tmp->command].str,
|
|
|
|
command_name[tmp->command].length, cs);
|
|
|
|
/* TIME */
|
|
|
|
table->field[5]->store((uint32)(tmp->start_time ?
|
|
|
|
now - tmp->start_time : 0), TRUE);
|
|
|
|
/* STATE */
|
|
|
|
#ifndef EMBEDDED_LIBRARY
|
|
|
|
val= (char*) (tmp->locked ? "Locked" :
|
|
|
|
tmp->net.reading_or_writing ?
|
|
|
|
(tmp->net.reading_or_writing == 2 ?
|
|
|
|
"Writing to net" :
|
|
|
|
tmp->command == COM_SLEEP ? "" :
|
|
|
|
"Reading from net") :
|
|
|
|
tmp->proc_info ? tmp->proc_info :
|
|
|
|
tmp->mysys_var &&
|
|
|
|
tmp->mysys_var->current_cond ?
|
|
|
|
"Waiting on cond" : NullS);
|
|
|
|
#else
|
|
|
|
val= (char *) "Writing to net";
|
|
|
|
#endif
|
|
|
|
if (val)
|
|
|
|
{
|
|
|
|
table->field[6]->store(val, strlen(val), cs);
|
|
|
|
table->field[6]->set_notnull();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mysys_var)
|
|
|
|
pthread_mutex_unlock(&mysys_var->mutex);
|
|
|
|
|
|
|
|
/* INFO */
|
|
|
|
if (tmp->query)
|
|
|
|
{
|
|
|
|
table->field[7]->store(tmp->query,
|
|
|
|
min(max_query_length, tmp->query_length), cs);
|
|
|
|
table->field[7]->set_notnull();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (schema_table_store_record(thd, table))
|
|
|
|
{
|
|
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
/*****************************************************************************
|
2002-08-30 11:40:40 +02:00
|
|
|
Status functions
|
2000-07-31 21:29:14 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
2006-01-07 14:41:57 +01:00
|
|
|
static DYNAMIC_ARRAY all_status_vars;
|
|
|
|
static bool status_vars_inited= 0;
|
|
|
|
static int show_var_cmp(const void *var1, const void *var2)
|
|
|
|
{
|
|
|
|
return strcmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
deletes all the SHOW_UNDEF elements from the array and calls
|
|
|
|
delete_dynamic() if it's completely empty.
|
|
|
|
*/
|
|
|
|
static void shrink_var_array(DYNAMIC_ARRAY *array)
|
|
|
|
{
|
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement),
and new binlog format called "mixed" (which is statement-based except if only row-based is correct,
in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release):
SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default;
the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha.
It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE
TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because
NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below).
The added tests test the possibility or impossibility to SET, their effects, and the mixed mode,
including in prepared statements and in stored procedures and functions.
Caveats:
a) The mixed mode will not work for stored functions: in mixed mode, a stored function will
always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()).
b) for the same reason, changing the thread's binlog format inside a stored function is
refused with an error message.
c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask
Dmitri).
Additionally, as the binlog format is now changeable by each user for his session, I remove the implication
which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1
(not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically
set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled
phantom protection).
Plus fixes for compiler warnings.
2006-02-25 22:21:03 +01:00
|
|
|
uint a,b;
|
2006-01-07 14:41:57 +01:00
|
|
|
SHOW_VAR *all= dynamic_element(array, 0, SHOW_VAR *);
|
|
|
|
|
|
|
|
for (a= b= 0; b < array->elements; b++)
|
|
|
|
if (all[b].type != SHOW_UNDEF)
|
|
|
|
all[a++]= all[b];
|
|
|
|
if (a)
|
|
|
|
{
|
|
|
|
bzero(all+a, sizeof(SHOW_VAR)); // writing NULL-element to the end
|
|
|
|
array->elements= a;
|
|
|
|
}
|
|
|
|
else // array is completely empty - delete it
|
|
|
|
delete_dynamic(array);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Adds an array of SHOW_VAR entries to the output of SHOW STATUS
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
add_status_vars(SHOW_VAR *list)
|
|
|
|
list - an array of SHOW_VAR entries to add to all_status_vars
|
|
|
|
the last entry must be {0,0,SHOW_UNDEF}
|
|
|
|
|
|
|
|
NOTE
|
|
|
|
The handling of all_status_vars[] is completely internal, it's allocated
|
|
|
|
automatically when something is added to it, and deleted completely when
|
|
|
|
the last entry is removed.
|
|
|
|
|
|
|
|
As a special optimization, if add_status_vars() is called before
|
|
|
|
init_status_vars(), it assumes "startup mode" - neither concurrent access
|
|
|
|
to the array nor SHOW STATUS are possible (thus it skips locks and qsort)
|
|
|
|
|
|
|
|
The last entry of the all_status_vars[] should always be {0,0,SHOW_UNDEF}
|
|
|
|
*/
|
|
|
|
int add_status_vars(SHOW_VAR *list)
|
|
|
|
{
|
|
|
|
int res= 0;
|
|
|
|
if (status_vars_inited)
|
|
|
|
pthread_mutex_lock(&LOCK_status);
|
|
|
|
if (!all_status_vars.buffer && // array is not allocated yet - do it now
|
|
|
|
my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 200, 20))
|
|
|
|
{
|
|
|
|
res= 1;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
while (list->name)
|
|
|
|
res|= insert_dynamic(&all_status_vars, (gptr)list++);
|
|
|
|
res|= insert_dynamic(&all_status_vars, (gptr)list); // appending NULL-element
|
|
|
|
all_status_vars.elements--; // but next insert_dynamic should overwite it
|
|
|
|
if (status_vars_inited)
|
|
|
|
sort_dynamic(&all_status_vars, show_var_cmp);
|
|
|
|
err:
|
|
|
|
if (status_vars_inited)
|
|
|
|
pthread_mutex_unlock(&LOCK_status);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Make all_status_vars[] usable for SHOW STATUS
|
|
|
|
|
|
|
|
NOTE
|
|
|
|
See add_status_vars(). Before init_status_vars() call, add_status_vars()
|
|
|
|
works in a special fast "startup" mode. Thus init_status_vars()
|
|
|
|
should be called as late as possible but before enabling multi-threading.
|
|
|
|
*/
|
|
|
|
void init_status_vars()
|
|
|
|
{
|
|
|
|
status_vars_inited=1;
|
|
|
|
sort_dynamic(&all_status_vars, show_var_cmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
catch-all cleanup function, cleans up everything no matter what
|
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
This function is not strictly required if all add_to_status/
|
|
|
|
remove_status_vars are properly paired, but it's a safety measure that
|
|
|
|
deletes everything from the all_status_vars[] even if some
|
|
|
|
remove_status_vars were forgotten
|
|
|
|
*/
|
|
|
|
void free_status_vars()
|
|
|
|
{
|
|
|
|
delete_dynamic(&all_status_vars);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Removes an array of SHOW_VAR entries from the output of SHOW STATUS
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
remove_status_vars(SHOW_VAR *list)
|
|
|
|
list - an array of SHOW_VAR entries to remove to all_status_vars
|
|
|
|
the last entry must be {0,0,SHOW_UNDEF}
|
|
|
|
|
|
|
|
NOTE
|
|
|
|
there's lots of room for optimizing this, especially in non-sorted mode,
|
|
|
|
but nobody cares - it may be called only in case of failed plugin
|
|
|
|
initialization in the mysqld startup.
|
|
|
|
|
|
|
|
*/
|
|
|
|
void remove_status_vars(SHOW_VAR *list)
|
|
|
|
{
|
|
|
|
if (status_vars_inited)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&LOCK_status);
|
|
|
|
SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
|
|
|
|
int a= 0, b= all_status_vars.elements, c= (a+b)/2, res;
|
|
|
|
|
|
|
|
for (; list->name; list++)
|
|
|
|
{
|
|
|
|
for (a= 0, b= all_status_vars.elements; b-a > 1; c= (a+b)/2)
|
|
|
|
{
|
|
|
|
res= show_var_cmp(list, all+c);
|
|
|
|
if (res < 0)
|
|
|
|
b= c;
|
|
|
|
else if (res > 0)
|
|
|
|
a= c;
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
if (res == 0)
|
|
|
|
all[c].type= SHOW_UNDEF;
|
|
|
|
}
|
|
|
|
shrink_var_array(&all_status_vars);
|
|
|
|
pthread_mutex_unlock(&LOCK_status);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
|
|
|
|
int i;
|
|
|
|
for (; list->name; list++)
|
|
|
|
{
|
|
|
|
for (i= 0; i < all_status_vars.elements; i++)
|
|
|
|
{
|
|
|
|
if (show_var_cmp(list, all+i))
|
|
|
|
continue;
|
|
|
|
all[i].type= SHOW_UNDEF;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
shrink_var_array(&all_status_vars);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-11-18 11:00:42 +01:00
|
|
|
static bool show_status_array(THD *thd, const char *wild,
|
2006-01-07 14:41:57 +01:00
|
|
|
SHOW_VAR *variables,
|
2004-12-30 13:20:40 +01:00
|
|
|
enum enum_var_type value_type,
|
|
|
|
struct system_status_var *status_var,
|
|
|
|
const char *prefix, TABLE *table)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2006-01-02 15:41:13 +01:00
|
|
|
char buff[SHOW_VAR_FUNC_BUFF_SIZE], *prefix_end;
|
2004-11-18 11:00:42 +01:00
|
|
|
/* the variable name should not be longer then 80 characters */
|
|
|
|
char name_buffer[80];
|
|
|
|
int len;
|
2003-07-06 18:09:57 +02:00
|
|
|
LEX_STRING null_lex_str;
|
2006-01-07 14:41:57 +01:00
|
|
|
SHOW_VAR tmp, *var;
|
2004-11-18 11:00:42 +01:00
|
|
|
DBUG_ENTER("show_status_array");
|
2002-08-30 11:40:40 +02:00
|
|
|
|
2003-07-06 18:09:57 +02:00
|
|
|
null_lex_str.str= 0; // For sys_var->value_ptr()
|
2003-11-18 12:47:27 +01:00
|
|
|
null_lex_str.length= 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2004-11-18 11:00:42 +01:00
|
|
|
prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1);
|
2006-01-07 14:41:57 +01:00
|
|
|
if (*prefix)
|
|
|
|
*prefix_end++= '_';
|
2004-11-18 11:00:42 +01:00
|
|
|
len=name_buffer + sizeof(name_buffer) - prefix_end;
|
|
|
|
|
2002-07-23 17:31:22 +02:00
|
|
|
for (; variables->name; variables++)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-11-18 11:00:42 +01:00
|
|
|
strnmov(prefix_end, variables->name, len);
|
|
|
|
name_buffer[sizeof(name_buffer)-1]=0; /* Safety */
|
2006-01-02 15:41:13 +01:00
|
|
|
|
2006-01-07 14:41:57 +01:00
|
|
|
/*
|
|
|
|
if var->type is SHOW_FUNC, call the function.
|
|
|
|
Repeat as necessary, if new var is again SHOW_FUNC
|
|
|
|
*/
|
2006-01-02 15:41:13 +01:00
|
|
|
for (var=variables; var->type == SHOW_FUNC; var= &tmp)
|
2006-01-07 14:41:57 +01:00
|
|
|
((mysql_show_var_func)(var->value))(thd, &tmp, buff);
|
2006-01-02 15:41:13 +01:00
|
|
|
|
|
|
|
SHOW_TYPE show_type=var->type;
|
|
|
|
if (show_type == SHOW_ARRAY)
|
2004-11-18 11:00:42 +01:00
|
|
|
{
|
2006-01-07 14:41:57 +01:00
|
|
|
show_status_array(thd, wild, (SHOW_VAR *) var->value,
|
2006-01-02 15:41:13 +01:00
|
|
|
value_type, status_var, name_buffer, table);
|
2004-11-18 11:00:42 +01:00
|
|
|
}
|
|
|
|
else
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-11-18 11:00:42 +01:00
|
|
|
if (!(wild && wild[0] && wild_case_compare(system_charset_info,
|
|
|
|
name_buffer, wild)))
|
2002-07-23 17:31:22 +02:00
|
|
|
{
|
2006-01-02 15:41:13 +01:00
|
|
|
char *value=var->value;
|
2005-06-01 15:35:09 +02:00
|
|
|
const char *pos, *end; // We assign a lot of const's
|
2004-11-18 11:00:42 +01:00
|
|
|
long nr;
|
|
|
|
if (show_type == SHOW_SYS)
|
|
|
|
{
|
|
|
|
show_type= ((sys_var*) value)->type();
|
|
|
|
value= (char*) ((sys_var*) value)->value_ptr(thd, value_type,
|
|
|
|
&null_lex_str);
|
|
|
|
}
|
|
|
|
|
|
|
|
pos= end= buff;
|
2006-01-02 15:41:13 +01:00
|
|
|
/*
|
|
|
|
note that value may be == buff. All SHOW_xxx code below
|
|
|
|
should still work in this case
|
|
|
|
*/
|
2004-11-18 11:00:42 +01:00
|
|
|
switch (show_type) {
|
2006-01-02 15:41:13 +01:00
|
|
|
case SHOW_DOUBLE_STATUS:
|
|
|
|
{
|
|
|
|
value= ((char *) status_var + (ulong) value);
|
|
|
|
end= buff + sprintf(buff, "%f", *(double*) value);
|
|
|
|
break;
|
|
|
|
}
|
2004-11-18 11:00:42 +01:00
|
|
|
case SHOW_LONG_STATUS:
|
|
|
|
value= ((char *) status_var + (ulong) value);
|
|
|
|
/* fall through */
|
|
|
|
case SHOW_LONG:
|
2006-01-07 14:41:57 +01:00
|
|
|
case SHOW_LONG_NOFLUSH: // the difference lies in refresh_status()
|
2004-11-18 11:00:42 +01:00
|
|
|
end= int10_to_str(*(long*) value, buff, 10);
|
|
|
|
break;
|
|
|
|
case SHOW_LONGLONG:
|
|
|
|
end= longlong10_to_str(*(longlong*) value, buff, 10);
|
|
|
|
break;
|
|
|
|
case SHOW_HA_ROWS:
|
|
|
|
end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
|
|
|
|
break;
|
|
|
|
case SHOW_BOOL:
|
|
|
|
end= strmov(buff, *(bool*) value ? "ON" : "OFF");
|
|
|
|
break;
|
|
|
|
case SHOW_MY_BOOL:
|
|
|
|
end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
|
|
|
|
break;
|
|
|
|
case SHOW_INT:
|
|
|
|
end= int10_to_str((long) *(uint32*) value, buff, 10);
|
|
|
|
break;
|
|
|
|
case SHOW_HAVE:
|
2004-11-18 17:06:02 +01:00
|
|
|
{
|
|
|
|
SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
|
|
|
|
pos= show_comp_option_name[(int) tmp];
|
|
|
|
end= strend(pos);
|
|
|
|
break;
|
|
|
|
}
|
2004-11-18 11:00:42 +01:00
|
|
|
case SHOW_CHAR:
|
2004-11-18 17:06:02 +01:00
|
|
|
{
|
|
|
|
if (!(pos= value))
|
|
|
|
pos= "";
|
|
|
|
end= strend(pos);
|
|
|
|
break;
|
|
|
|
}
|
2004-11-18 11:00:42 +01:00
|
|
|
case SHOW_CHAR_PTR:
|
2004-11-18 17:06:02 +01:00
|
|
|
{
|
|
|
|
if (!(pos= *(char**) value))
|
|
|
|
pos= "";
|
|
|
|
end= strend(pos);
|
|
|
|
break;
|
|
|
|
}
|
2004-11-18 11:00:42 +01:00
|
|
|
case SHOW_KEY_CACHE_LONG:
|
2006-01-02 15:41:13 +01:00
|
|
|
value= (char*) dflt_key_cache + (ulong)value;
|
2004-11-18 11:00:42 +01:00
|
|
|
end= int10_to_str(*(long*) value, buff, 10);
|
|
|
|
break;
|
2005-09-14 13:37:16 +02:00
|
|
|
case SHOW_KEY_CACHE_LONGLONG:
|
2006-01-02 15:41:13 +01:00
|
|
|
value= (char*) dflt_key_cache + (ulong)value;
|
2005-09-14 13:37:16 +02:00
|
|
|
end= longlong10_to_str(*(longlong*) value, buff, 10);
|
|
|
|
break;
|
2006-01-02 15:41:13 +01:00
|
|
|
case SHOW_UNDEF:
|
2006-01-07 14:41:57 +01:00
|
|
|
break; // Return empty string
|
|
|
|
case SHOW_SYS: // Cannot happen
|
2004-11-18 11:00:42 +01:00
|
|
|
default:
|
2006-01-07 14:41:57 +01:00
|
|
|
DBUG_ASSERT(0);
|
2004-11-18 11:00:42 +01:00
|
|
|
break;
|
|
|
|
}
|
2005-01-06 12:00:13 +01:00
|
|
|
restore_record(table, s->default_values);
|
2004-12-30 13:20:40 +01:00
|
|
|
table->field[0]->store(name_buffer, strlen(name_buffer),
|
|
|
|
system_charset_info);
|
|
|
|
table->field[1]->store(pos, (uint32) (end - pos), system_charset_info);
|
2005-03-24 14:32:11 +01:00
|
|
|
if (schema_table_store_record(thd, table))
|
|
|
|
DBUG_RETURN(TRUE);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-11-18 11:00:42 +01:00
|
|
|
|
|
|
|
DBUG_RETURN(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-09-13 15:48:01 +02:00
|
|
|
/* collect status for all running threads */
|
|
|
|
|
|
|
|
void calc_sum_of_all_status(STATUS_VAR *to)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("calc_sum_of_all_status");
|
|
|
|
|
|
|
|
/* Ensure that thread id not killed during loop */
|
|
|
|
VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
|
|
|
|
|
|
|
|
I_List_iterator<THD> it(threads);
|
|
|
|
THD *tmp;
|
|
|
|
|
|
|
|
/* Get global values as base */
|
|
|
|
*to= global_status_var;
|
|
|
|
|
|
|
|
/* Add to this status from existing threads */
|
|
|
|
while ((tmp= it++))
|
|
|
|
add_to_status(to, &tmp->status_var);
|
|
|
|
|
|
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
LEX_STRING *make_lex_string(THD *thd, LEX_STRING *lex_str,
|
|
|
|
const char* str, uint length,
|
|
|
|
bool allocate_lex_string)
|
|
|
|
{
|
|
|
|
MEM_ROOT *mem= thd->mem_root;
|
|
|
|
if (allocate_lex_string)
|
2006-01-03 17:54:54 +01:00
|
|
|
if (!(lex_str= (LEX_STRING *)thd->alloc(sizeof(LEX_STRING))))
|
|
|
|
return 0;
|
2004-11-13 11:56:39 +01:00
|
|
|
lex_str->str= strmake_root(mem, str, length);
|
|
|
|
lex_str->length= length;
|
|
|
|
return lex_str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* INFORMATION_SCHEMA name */
|
|
|
|
LEX_STRING information_schema_name= {(char*)"information_schema", 18};
|
2005-05-06 10:39:30 +02:00
|
|
|
|
|
|
|
/* This is only used internally, but we need it here as a forward reference */
|
2004-11-13 11:56:39 +01:00
|
|
|
extern ST_SCHEMA_TABLE schema_tables[];
|
|
|
|
|
|
|
|
typedef struct st_index_field_values
|
|
|
|
{
|
|
|
|
const char *db_value, *table_value;
|
|
|
|
} INDEX_FIELD_VALUES;
|
|
|
|
|
|
|
|
|
2005-03-24 14:32:11 +01:00
|
|
|
/*
|
|
|
|
Store record to I_S table, convert HEAP table
|
|
|
|
to MyISAM if necessary
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
schema_table_store_record()
|
|
|
|
thd thread handler
|
2005-03-30 15:00:31 +02:00
|
|
|
table Information schema table to be updated
|
|
|
|
|
2005-03-24 14:32:11 +01:00
|
|
|
RETURN
|
|
|
|
0 success
|
2005-03-30 15:00:31 +02:00
|
|
|
1 error
|
2005-03-24 14:32:11 +01:00
|
|
|
*/
|
|
|
|
|
2006-01-28 04:16:23 +01:00
|
|
|
bool schema_table_store_record(THD *thd, TABLE *table)
|
2005-03-24 14:32:11 +01:00
|
|
|
{
|
|
|
|
int error;
|
2005-12-22 06:39:02 +01:00
|
|
|
if ((error= table->file->ha_write_row(table->record[0])))
|
2005-03-24 14:32:11 +01:00
|
|
|
{
|
|
|
|
if (create_myisam_from_heap(thd, table,
|
|
|
|
table->pos_in_table_list->schema_table_param,
|
|
|
|
error, 0))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
void get_index_field_values(LEX *lex, INDEX_FIELD_VALUES *index_field_values)
|
|
|
|
{
|
|
|
|
const char *wild= lex->wild ? lex->wild->ptr() : NullS;
|
|
|
|
switch (lex->orig_sql_command) {
|
|
|
|
case SQLCOM_SHOW_DATABASES:
|
|
|
|
index_field_values->db_value= wild;
|
|
|
|
break;
|
|
|
|
case SQLCOM_SHOW_TABLES:
|
|
|
|
case SQLCOM_SHOW_TABLE_STATUS:
|
2005-07-19 18:06:49 +02:00
|
|
|
case SQLCOM_SHOW_TRIGGERS:
|
2006-01-30 13:15:23 +01:00
|
|
|
case SQLCOM_SHOW_EVENTS:
|
2005-08-23 02:32:02 +02:00
|
|
|
index_field_values->db_value= lex->select_lex.db;
|
2004-11-13 11:56:39 +01:00
|
|
|
index_field_values->table_value= wild;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
index_field_values->db_value= NullS;
|
|
|
|
index_field_values->table_value= NullS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int make_table_list(THD *thd, SELECT_LEX *sel,
|
|
|
|
char *db, char *table)
|
|
|
|
{
|
|
|
|
Table_ident *table_ident;
|
|
|
|
LEX_STRING ident_db, ident_table;
|
|
|
|
ident_db.str= db;
|
|
|
|
ident_db.length= strlen(db);
|
|
|
|
ident_table.str= table;
|
|
|
|
ident_table.length= strlen(table);
|
|
|
|
table_ident= new Table_ident(thd, ident_db, ident_table, 1);
|
|
|
|
sel->init_query();
|
2005-07-18 14:33:18 +02:00
|
|
|
if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ,
|
2004-11-13 11:56:39 +01:00
|
|
|
(List<String> *) 0, (List<String> *) 0))
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool uses_only_table_name_fields(Item *item, TABLE_LIST *table)
|
|
|
|
{
|
|
|
|
if (item->type() == Item::FUNC_ITEM)
|
|
|
|
{
|
|
|
|
Item_func *item_func= (Item_func*)item;
|
|
|
|
Item **child;
|
|
|
|
Item **item_end= (item_func->arguments()) + item_func->argument_count();
|
|
|
|
for (child= item_func->arguments(); child != item_end; child++)
|
2004-12-07 14:47:00 +01:00
|
|
|
{
|
2004-11-13 11:56:39 +01:00
|
|
|
if (!uses_only_table_name_fields(*child, table))
|
|
|
|
return 0;
|
2004-12-07 14:47:00 +01:00
|
|
|
}
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
else if (item->type() == Item::FIELD_ITEM)
|
|
|
|
{
|
|
|
|
Item_field *item_field= (Item_field*)item;
|
|
|
|
CHARSET_INFO *cs= system_charset_info;
|
|
|
|
ST_SCHEMA_TABLE *schema_table= table->schema_table;
|
|
|
|
ST_FIELD_INFO *field_info= schema_table->fields_info;
|
2005-05-06 10:39:30 +02:00
|
|
|
const char *field_name1= schema_table->idx_field1 >= 0 ? field_info[schema_table->idx_field1].field_name : "";
|
|
|
|
const char *field_name2= schema_table->idx_field2 >= 0 ? field_info[schema_table->idx_field2].field_name : "";
|
2004-12-07 14:47:00 +01:00
|
|
|
if (table->table != item_field->field->table ||
|
|
|
|
(cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1),
|
|
|
|
(uchar *) item_field->field_name,
|
|
|
|
strlen(item_field->field_name), 0) &&
|
|
|
|
cs->coll->strnncollsp(cs, (uchar *) field_name2, strlen(field_name2),
|
|
|
|
(uchar *) item_field->field_name,
|
|
|
|
strlen(item_field->field_name), 0)))
|
2004-11-13 11:56:39 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2005-04-14 08:06:37 +02:00
|
|
|
else if (item->type() == Item::REF_ITEM)
|
|
|
|
return uses_only_table_name_fields(item->real_item(), table);
|
2005-03-03 17:20:16 +01:00
|
|
|
if (item->type() == Item::SUBSELECT_ITEM &&
|
|
|
|
!item->const_item())
|
|
|
|
return 0;
|
|
|
|
|
2004-12-07 14:47:00 +01:00
|
|
|
return 1;
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static COND * make_cond_for_info_schema(COND *cond, TABLE_LIST *table)
|
|
|
|
{
|
|
|
|
if (!cond)
|
|
|
|
return (COND*) 0;
|
|
|
|
if (cond->type() == Item::COND_ITEM)
|
|
|
|
{
|
|
|
|
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
|
|
|
|
{
|
|
|
|
/* Create new top level AND item */
|
|
|
|
Item_cond_and *new_cond=new Item_cond_and;
|
|
|
|
if (!new_cond)
|
|
|
|
return (COND*) 0;
|
|
|
|
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
|
|
|
|
Item *item;
|
|
|
|
while ((item=li++))
|
|
|
|
{
|
|
|
|
Item *fix= make_cond_for_info_schema(item, table);
|
|
|
|
if (fix)
|
|
|
|
new_cond->argument_list()->push_back(fix);
|
|
|
|
}
|
|
|
|
switch (new_cond->argument_list()->elements) {
|
|
|
|
case 0:
|
|
|
|
return (COND*) 0;
|
|
|
|
case 1:
|
|
|
|
return new_cond->argument_list()->head();
|
|
|
|
default:
|
|
|
|
new_cond->quick_fix_field();
|
|
|
|
return new_cond;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // Or list
|
|
|
|
Item_cond_or *new_cond=new Item_cond_or;
|
|
|
|
if (!new_cond)
|
|
|
|
return (COND*) 0;
|
|
|
|
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
|
|
|
|
Item *item;
|
|
|
|
while ((item=li++))
|
|
|
|
{
|
|
|
|
Item *fix=make_cond_for_info_schema(item, table);
|
|
|
|
if (!fix)
|
|
|
|
return (COND*) 0;
|
|
|
|
new_cond->argument_list()->push_back(fix);
|
|
|
|
}
|
|
|
|
new_cond->quick_fix_field();
|
|
|
|
new_cond->top_level_item();
|
|
|
|
return new_cond;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!uses_only_table_name_fields(cond, table))
|
|
|
|
return (COND*) 0;
|
|
|
|
return cond;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-12-30 13:20:40 +01:00
|
|
|
enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table)
|
|
|
|
{
|
|
|
|
return (enum enum_schema_tables) (schema_table - &schema_tables[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-12-10 16:25:12 +01:00
|
|
|
/*
|
2005-05-06 21:06:10 +02:00
|
|
|
Create db names list. Information schema name always is first in list
|
2004-12-10 16:25:12 +01:00
|
|
|
|
|
|
|
SYNOPSIS
|
2005-05-06 21:06:10 +02:00
|
|
|
make_db_list()
|
2004-12-10 16:25:12 +01:00
|
|
|
thd thread handler
|
|
|
|
files list of db names
|
|
|
|
wild wild string
|
2005-05-06 21:06:10 +02:00
|
|
|
idx_field_vals idx_field_vals->db_name contains db name or
|
|
|
|
wild string
|
2004-12-10 16:25:12 +01:00
|
|
|
with_i_schema returns 1 if we added 'IS' name to list
|
|
|
|
otherwise returns 0
|
2005-05-06 21:06:10 +02:00
|
|
|
is_wild_value if value is 1 then idx_field_vals->db_name is
|
|
|
|
wild string otherwise it's db name;
|
2004-12-10 16:25:12 +01:00
|
|
|
|
|
|
|
RETURN
|
|
|
|
1 error
|
|
|
|
0 success
|
|
|
|
*/
|
|
|
|
|
2005-05-06 21:06:10 +02:00
|
|
|
int make_db_list(THD *thd, List<char> *files,
|
|
|
|
INDEX_FIELD_VALUES *idx_field_vals,
|
|
|
|
bool *with_i_schema, bool is_wild_value)
|
2004-12-10 10:07:11 +01:00
|
|
|
{
|
2005-05-06 21:06:10 +02:00
|
|
|
LEX *lex= thd->lex;
|
2004-12-10 16:25:12 +01:00
|
|
|
*with_i_schema= 0;
|
2005-05-06 21:06:10 +02:00
|
|
|
get_index_field_values(lex, idx_field_vals);
|
|
|
|
if (is_wild_value)
|
2004-12-10 16:25:12 +01:00
|
|
|
{
|
2005-05-10 20:34:04 +02:00
|
|
|
/*
|
|
|
|
This part of code is only for SHOW DATABASES command.
|
|
|
|
idx_field_vals->db_value can be 0 when we don't use
|
|
|
|
LIKE clause (see also get_index_field_values() function)
|
|
|
|
*/
|
2005-05-06 21:06:10 +02:00
|
|
|
if (!idx_field_vals->db_value ||
|
|
|
|
!wild_case_compare(system_charset_info,
|
|
|
|
information_schema_name.str,
|
|
|
|
idx_field_vals->db_value))
|
|
|
|
{
|
|
|
|
*with_i_schema= 1;
|
|
|
|
if (files->push_back(thd->strdup(information_schema_name.str)))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return mysql_find_files(thd, files, NullS, mysql_data_home,
|
|
|
|
idx_field_vals->db_value, 1);
|
2004-12-10 16:25:12 +01:00
|
|
|
}
|
2005-05-06 21:06:10 +02:00
|
|
|
|
2005-05-10 20:34:04 +02:00
|
|
|
/*
|
|
|
|
This part of code is for SHOW TABLES, SHOW TABLE STATUS commands.
|
|
|
|
idx_field_vals->db_value can't be 0 (see get_index_field_values()
|
|
|
|
function). lex->orig_sql_command can be not equal to SQLCOM_END
|
|
|
|
only in case of executing of SHOW commands.
|
|
|
|
*/
|
2005-05-06 21:06:10 +02:00
|
|
|
if (lex->orig_sql_command != SQLCOM_END)
|
|
|
|
{
|
2005-05-10 20:34:04 +02:00
|
|
|
if (!my_strcasecmp(system_charset_info, information_schema_name.str,
|
2005-05-06 21:06:10 +02:00
|
|
|
idx_field_vals->db_value))
|
|
|
|
{
|
|
|
|
*with_i_schema= 1;
|
|
|
|
return files->push_back(thd->strdup(information_schema_name.str));
|
|
|
|
}
|
|
|
|
return files->push_back(thd->strdup(idx_field_vals->db_value));
|
|
|
|
}
|
|
|
|
|
2005-05-10 20:34:04 +02:00
|
|
|
/*
|
|
|
|
Create list of existing databases. It is used in case
|
|
|
|
of select from information schema table
|
|
|
|
*/
|
2005-05-06 21:06:10 +02:00
|
|
|
if (files->push_back(thd->strdup(information_schema_name.str)))
|
|
|
|
return 1;
|
|
|
|
*with_i_schema= 1;
|
|
|
|
return mysql_find_files(thd, files, NullS, mysql_data_home, NullS, 1);
|
2004-12-10 10:07:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int schema_tables_add(THD *thd, List<char> *files, const char *wild)
|
|
|
|
{
|
|
|
|
ST_SCHEMA_TABLE *tmp_schema_table= schema_tables;
|
2005-08-20 10:00:00 +02:00
|
|
|
for (; tmp_schema_table->table_name; tmp_schema_table++)
|
2004-12-10 10:07:11 +01:00
|
|
|
{
|
2004-12-18 11:49:13 +01:00
|
|
|
if (tmp_schema_table->hidden)
|
|
|
|
continue;
|
2004-12-10 10:07:11 +01:00
|
|
|
if (wild)
|
|
|
|
{
|
|
|
|
if (lower_case_table_names)
|
|
|
|
{
|
|
|
|
if (wild_case_compare(files_charset_info,
|
|
|
|
tmp_schema_table->table_name,
|
|
|
|
wild))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (wild_compare(tmp_schema_table->table_name, wild, 0))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (files->push_back(thd->strdup(tmp_schema_table->table_name)))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
|
|
|
|
{
|
|
|
|
LEX *lex= thd->lex;
|
|
|
|
TABLE *table= tables->table;
|
|
|
|
SELECT_LEX *select_lex= &lex->select_lex;
|
2005-02-22 12:42:44 +01:00
|
|
|
SELECT_LEX *old_all_select_lex= lex->all_selects_list;
|
2005-08-08 15:46:06 +02:00
|
|
|
TABLE_LIST **save_query_tables_last= lex->query_tables_last;
|
|
|
|
enum_sql_command save_sql_command= lex->sql_command;
|
2004-11-15 17:20:45 +01:00
|
|
|
SELECT_LEX *lsel= tables->schema_select_lex;
|
2004-11-13 11:56:39 +01:00
|
|
|
ST_SCHEMA_TABLE *schema_table= tables->schema_table;
|
2005-01-12 02:38:53 +01:00
|
|
|
SELECT_LEX sel;
|
|
|
|
INDEX_FIELD_VALUES idx_field_vals;
|
|
|
|
char path[FN_REFLEN], *end, *base_name, *file_name;
|
|
|
|
uint len;
|
|
|
|
bool with_i_schema;
|
|
|
|
enum enum_schema_tables schema_table_idx;
|
|
|
|
List<char> bases;
|
2005-02-03 17:00:50 +01:00
|
|
|
List_iterator_fast<char> it(bases);
|
2005-09-15 21:29:07 +02:00
|
|
|
COND *partial_cond;
|
2005-09-20 20:20:38 +02:00
|
|
|
Security_context *sctx= thd->security_ctx;
|
2005-02-22 12:42:44 +01:00
|
|
|
uint derived_tables= lex->derived_tables;
|
2005-02-03 17:00:50 +01:00
|
|
|
int error= 1;
|
2005-12-21 19:18:40 +01:00
|
|
|
enum legacy_db_type not_used;
|
2005-08-08 15:46:06 +02:00
|
|
|
Open_tables_state open_tables_state_backup;
|
2006-01-03 11:25:19 +01:00
|
|
|
bool save_view_prepare_mode= lex->view_prepare_mode;
|
|
|
|
lex->view_prepare_mode= TRUE;
|
2005-01-12 02:38:53 +01:00
|
|
|
DBUG_ENTER("get_all_tables");
|
|
|
|
|
|
|
|
LINT_INIT(end);
|
|
|
|
LINT_INIT(len);
|
2004-11-13 11:56:39 +01:00
|
|
|
|
2005-08-08 15:46:06 +02:00
|
|
|
/*
|
|
|
|
Let us set fake sql_command so views won't try to merge
|
|
|
|
themselves into main statement.
|
|
|
|
*/
|
|
|
|
lex->sql_command= SQLCOM_SHOW_FIELDS;
|
|
|
|
|
|
|
|
/*
|
|
|
|
We should not introduce deadlocks even if we already have some
|
|
|
|
tables open and locked, since we won't lock tables which we will
|
|
|
|
open and will ignore possible name-locks for these tables.
|
|
|
|
*/
|
|
|
|
thd->reset_n_backup_open_tables_state(&open_tables_state_backup);
|
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
if (lsel)
|
|
|
|
{
|
|
|
|
TABLE_LIST *show_table_list= (TABLE_LIST*) lsel->table_list.first;
|
2005-01-12 02:38:53 +01:00
|
|
|
bool res;
|
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
lex->all_selects_list= lsel;
|
2005-12-19 11:46:54 +01:00
|
|
|
/*
|
|
|
|
Restore thd->temporary_tables to be able to process
|
|
|
|
temporary tables(only for 'show index' & 'show columns').
|
|
|
|
This should be changed when processing of temporary tables for
|
|
|
|
I_S tables will be done.
|
|
|
|
*/
|
|
|
|
thd->temporary_tables= open_tables_state_backup.temporary_tables;
|
2005-08-08 15:46:06 +02:00
|
|
|
res= open_normal_and_derived_tables(thd, show_table_list,
|
|
|
|
MYSQL_LOCK_IGNORE_FLUSH);
|
2005-08-25 09:24:21 +02:00
|
|
|
/*
|
|
|
|
get_all_tables() returns 1 on failure and 0 on success thus
|
|
|
|
return only these and not the result code of ::process_table()
|
2005-09-07 13:11:53 +02:00
|
|
|
|
|
|
|
We should use show_table_list->alias instead of
|
|
|
|
show_table_list->table_name because table_name
|
|
|
|
could be changed during opening of I_S tables. It's safe
|
|
|
|
to use alias because alias contains original table name
|
|
|
|
in this case(this part of code is used only for
|
|
|
|
'show columns' & 'show statistics' commands).
|
2005-08-25 09:24:21 +02:00
|
|
|
*/
|
|
|
|
error= test(schema_table->process_table(thd, show_table_list,
|
2005-09-07 13:11:53 +02:00
|
|
|
table, res,
|
|
|
|
(show_table_list->view ?
|
|
|
|
show_table_list->view_db.str :
|
|
|
|
show_table_list->db),
|
|
|
|
show_table_list->alias));
|
2005-12-19 11:46:54 +01:00
|
|
|
thd->temporary_tables= 0;
|
2005-08-08 15:46:06 +02:00
|
|
|
close_thread_tables(thd);
|
2004-11-13 11:56:39 +01:00
|
|
|
show_table_list->table= 0;
|
2005-02-03 17:00:50 +01:00
|
|
|
goto err;
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
|
2005-01-12 02:38:53 +01:00
|
|
|
schema_table_idx= get_schema_table_idx(schema_table);
|
2004-12-10 10:07:11 +01:00
|
|
|
|
2005-05-06 21:06:10 +02:00
|
|
|
if (make_db_list(thd, &bases, &idx_field_vals,
|
|
|
|
&with_i_schema, 0))
|
2005-02-03 17:00:50 +01:00
|
|
|
goto err;
|
2005-01-12 02:38:53 +01:00
|
|
|
|
|
|
|
partial_cond= make_cond_for_info_schema(cond, tables);
|
2005-02-03 17:00:50 +01:00
|
|
|
it.rewind(); /* To get access to new elements in basis list */
|
2005-01-12 02:38:53 +01:00
|
|
|
while ((base_name= it++) ||
|
2004-11-13 11:56:39 +01:00
|
|
|
/*
|
|
|
|
generate error for non existing database.
|
|
|
|
(to save old behaviour for SHOW TABLES FROM db)
|
|
|
|
*/
|
|
|
|
((lex->orig_sql_command == SQLCOM_SHOW_TABLES ||
|
|
|
|
lex->orig_sql_command == SQLCOM_SHOW_TABLE_STATUS) &&
|
|
|
|
(base_name= select_lex->db) && !bases.elements))
|
|
|
|
{
|
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
2005-09-13 13:07:38 +02:00
|
|
|
if (!check_access(thd,SELECT_ACL, base_name,
|
|
|
|
&thd->col_access, 0, 1, with_i_schema) ||
|
2005-09-15 21:29:07 +02:00
|
|
|
sctx->master_access & (DB_ACLS | SHOW_DB_ACL) ||
|
|
|
|
acl_get(sctx->host, sctx->ip, sctx->priv_user, base_name,0) ||
|
2004-11-13 11:56:39 +01:00
|
|
|
(grant_option && !check_grant_db(thd, base_name)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
List<char> files;
|
2004-12-10 10:07:11 +01:00
|
|
|
if (with_i_schema) // information schema table names
|
|
|
|
{
|
|
|
|
if (schema_tables_add(thd, &files, idx_field_vals.table_value))
|
2005-02-03 17:00:50 +01:00
|
|
|
goto err;
|
2004-12-10 10:07:11 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-12-31 06:01:26 +01:00
|
|
|
len= build_table_filename(path, sizeof(path), base_name, "", "");
|
|
|
|
end= path + len;
|
2004-12-10 10:07:11 +01:00
|
|
|
len= FN_LEN - len;
|
|
|
|
if (mysql_find_files(thd, &files, base_name,
|
|
|
|
path, idx_field_vals.table_value, 0))
|
2005-02-03 17:00:50 +01:00
|
|
|
goto err;
|
2004-12-10 10:07:11 +01:00
|
|
|
}
|
2004-11-13 11:56:39 +01:00
|
|
|
|
2005-01-12 02:38:53 +01:00
|
|
|
List_iterator_fast<char> it_files(files);
|
|
|
|
while ((file_name= it_files++))
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
2005-01-06 12:00:13 +01:00
|
|
|
restore_record(table, s->default_values);
|
2004-11-13 11:56:39 +01:00
|
|
|
table->field[schema_table->idx_field1]->
|
|
|
|
store(base_name, strlen(base_name), system_charset_info);
|
|
|
|
table->field[schema_table->idx_field2]->
|
|
|
|
store(file_name, strlen(file_name),system_charset_info);
|
|
|
|
if (!partial_cond || partial_cond->val_int())
|
|
|
|
{
|
|
|
|
if (schema_table_idx == SCH_TABLE_NAMES)
|
|
|
|
{
|
|
|
|
if (lex->verbose || lex->orig_sql_command == SQLCOM_END)
|
|
|
|
{
|
2004-12-10 10:07:11 +01:00
|
|
|
if (with_i_schema)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"),
|
|
|
|
system_charset_info);
|
2004-12-10 10:07:11 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
my_snprintf(end, len, "/%s%s", file_name, reg_ext);
|
2005-11-03 15:10:11 +01:00
|
|
|
switch (mysql_frm_type(thd, path, ¬_used)) {
|
2004-12-10 10:07:11 +01:00
|
|
|
case FRMTYPE_ERROR:
|
2005-11-20 19:47:07 +01:00
|
|
|
table->field[3]->store(STRING_WITH_LEN("ERROR"),
|
|
|
|
system_charset_info);
|
2004-12-10 10:07:11 +01:00
|
|
|
break;
|
|
|
|
case FRMTYPE_TABLE:
|
2005-11-20 19:47:07 +01:00
|
|
|
table->field[3]->store(STRING_WITH_LEN("BASE TABLE"),
|
|
|
|
system_charset_info);
|
2004-12-10 10:07:11 +01:00
|
|
|
break;
|
|
|
|
case FRMTYPE_VIEW:
|
2005-11-20 19:47:07 +01:00
|
|
|
table->field[3]->store(STRING_WITH_LEN("VIEW"),
|
|
|
|
system_charset_info);
|
2004-12-10 10:07:11 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
}
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
}
|
2005-03-24 14:32:11 +01:00
|
|
|
if (schema_table_store_record(thd, table))
|
2005-03-30 15:00:31 +02:00
|
|
|
goto err;
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int res;
|
2005-08-12 16:57:19 +02:00
|
|
|
/*
|
|
|
|
Set the parent lex of 'sel' because it is needed by sel.init_query()
|
|
|
|
which is called inside make_table_list.
|
|
|
|
*/
|
|
|
|
sel.parent_lex= lex;
|
2004-11-13 11:56:39 +01:00
|
|
|
if (make_table_list(thd, &sel, base_name, file_name))
|
2005-02-03 17:00:50 +01:00
|
|
|
goto err;
|
2004-11-13 11:56:39 +01:00
|
|
|
TABLE_LIST *show_table_list= (TABLE_LIST*) sel.table_list.first;
|
2005-02-22 12:42:44 +01:00
|
|
|
lex->all_selects_list= &sel;
|
|
|
|
lex->derived_tables= 0;
|
2005-08-08 15:46:06 +02:00
|
|
|
res= open_normal_and_derived_tables(thd, show_table_list,
|
|
|
|
MYSQL_LOCK_IGNORE_FLUSH);
|
2005-09-07 13:11:53 +02:00
|
|
|
/*
|
|
|
|
We should use show_table_list->alias instead of
|
|
|
|
show_table_list->table_name because table_name
|
|
|
|
could be changed during opening of I_S tables. It's safe
|
|
|
|
to use alias because alias contains original table name
|
|
|
|
in this case.
|
|
|
|
*/
|
2005-08-25 09:24:21 +02:00
|
|
|
res= schema_table->process_table(thd, show_table_list, table,
|
2005-01-27 11:16:51 +01:00
|
|
|
res, base_name,
|
2005-08-25 09:24:21 +02:00
|
|
|
show_table_list->alias);
|
2005-08-08 15:46:06 +02:00
|
|
|
close_thread_tables(thd);
|
2005-08-25 09:24:21 +02:00
|
|
|
if (res)
|
2005-02-03 17:00:50 +01:00
|
|
|
goto err;
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-12-12 18:54:26 +01:00
|
|
|
/*
|
|
|
|
If we have information schema its always the first table and only
|
|
|
|
the first table. Reset for other tables.
|
|
|
|
*/
|
2004-12-10 10:07:11 +01:00
|
|
|
with_i_schema= 0;
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
}
|
2005-02-03 17:00:50 +01:00
|
|
|
|
|
|
|
error= 0;
|
|
|
|
err:
|
2005-08-08 15:46:06 +02:00
|
|
|
thd->restore_backup_open_tables_state(&open_tables_state_backup);
|
2005-02-22 12:42:44 +01:00
|
|
|
lex->derived_tables= derived_tables;
|
|
|
|
lex->all_selects_list= old_all_select_lex;
|
2005-08-08 15:46:06 +02:00
|
|
|
lex->query_tables_last= save_query_tables_last;
|
2006-01-03 11:25:19 +01:00
|
|
|
lex->view_prepare_mode= save_view_prepare_mode;
|
2005-08-08 15:46:06 +02:00
|
|
|
*save_query_tables_last= 0;
|
|
|
|
lex->sql_command= save_sql_command;
|
2005-02-03 17:00:50 +01:00
|
|
|
DBUG_RETURN(error);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-03-24 14:32:11 +01:00
|
|
|
bool store_schema_shemata(THD* thd, TABLE *table, const char *db_name,
|
2005-05-06 22:14:22 +02:00
|
|
|
CHARSET_INFO *cs)
|
2004-12-10 10:07:11 +01:00
|
|
|
{
|
2005-01-06 12:00:13 +01:00
|
|
|
restore_record(table, s->default_values);
|
2004-12-10 10:07:11 +01:00
|
|
|
table->field[1]->store(db_name, strlen(db_name), system_charset_info);
|
2005-05-06 22:14:22 +02:00
|
|
|
table->field[2]->store(cs->csname, strlen(cs->csname), system_charset_info);
|
|
|
|
table->field[3]->store(cs->name, strlen(cs->name), system_charset_info);
|
2005-03-25 11:31:29 +01:00
|
|
|
return schema_table_store_record(thd, table);
|
2004-12-10 10:07:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
int fill_schema_shemata(THD *thd, TABLE_LIST *tables, COND *cond)
|
|
|
|
{
|
2005-02-25 15:53:22 +01:00
|
|
|
char path[FN_REFLEN];
|
2004-11-13 11:56:39 +01:00
|
|
|
bool found_libchar;
|
|
|
|
INDEX_FIELD_VALUES idx_field_vals;
|
|
|
|
List<char> files;
|
|
|
|
char *file_name;
|
|
|
|
uint length;
|
2004-12-10 16:25:12 +01:00
|
|
|
bool with_i_schema;
|
2004-11-13 11:56:39 +01:00
|
|
|
HA_CREATE_INFO create;
|
|
|
|
TABLE *table= tables->table;
|
2005-09-20 20:20:38 +02:00
|
|
|
Security_context *sctx= thd->security_ctx;
|
2005-02-24 22:33:42 +01:00
|
|
|
DBUG_ENTER("fill_schema_shemata");
|
2004-11-13 11:56:39 +01:00
|
|
|
|
2005-05-06 21:06:10 +02:00
|
|
|
if (make_db_list(thd, &files, &idx_field_vals,
|
|
|
|
&with_i_schema, 1))
|
2005-02-24 22:33:42 +01:00
|
|
|
DBUG_RETURN(1);
|
2005-05-06 21:06:10 +02:00
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
List_iterator_fast<char> it(files);
|
|
|
|
while ((file_name=it++))
|
|
|
|
{
|
2004-12-10 10:07:11 +01:00
|
|
|
if (with_i_schema) // information schema name is always first in list
|
|
|
|
{
|
2005-03-24 14:32:11 +01:00
|
|
|
if (store_schema_shemata(thd, table, file_name,
|
2005-05-06 22:14:22 +02:00
|
|
|
system_charset_info))
|
2005-03-24 14:32:11 +01:00
|
|
|
DBUG_RETURN(1);
|
2004-12-10 10:07:11 +01:00
|
|
|
with_i_schema= 0;
|
|
|
|
continue;
|
|
|
|
}
|
2004-11-13 11:56:39 +01:00
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
2005-09-15 21:29:07 +02:00
|
|
|
if (sctx->master_access & (DB_ACLS | SHOW_DB_ACL) ||
|
|
|
|
acl_get(sctx->host, sctx->ip, sctx->priv_user, file_name,0) ||
|
2004-11-13 11:56:39 +01:00
|
|
|
(grant_option && !check_grant_db(thd, file_name)))
|
|
|
|
#endif
|
|
|
|
{
|
2005-12-31 06:01:26 +01:00
|
|
|
length= build_table_filename(path, sizeof(path), file_name, "", "");
|
2004-11-13 11:56:39 +01:00
|
|
|
found_libchar= 0;
|
|
|
|
if (length && path[length-1] == FN_LIBCHAR)
|
|
|
|
{
|
|
|
|
found_libchar= 1;
|
|
|
|
path[length-1]=0; // remove ending '\'
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found_libchar)
|
|
|
|
path[length-1]= FN_LIBCHAR;
|
|
|
|
strmov(path+length, MY_DB_OPT_FILE);
|
|
|
|
load_db_opt(thd, path, &create);
|
2005-03-24 14:32:11 +01:00
|
|
|
if (store_schema_shemata(thd, table, file_name,
|
2005-05-06 22:14:22 +02:00
|
|
|
create.default_table_charset))
|
2005-03-24 14:32:11 +01:00
|
|
|
DBUG_RETURN(1);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
}
|
2005-02-24 22:33:42 +01:00
|
|
|
DBUG_RETURN(0);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-13 22:26:15 +01:00
|
|
|
static int get_schema_tables_record(THD *thd, struct st_table_list *tables,
|
|
|
|
TABLE *table, bool res,
|
|
|
|
const char *base_name,
|
|
|
|
const char *file_name)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
const char *tmp_buff;
|
|
|
|
TIME time;
|
|
|
|
CHARSET_INFO *cs= system_charset_info;
|
|
|
|
DBUG_ENTER("get_schema_tables_record");
|
2005-01-06 12:00:13 +01:00
|
|
|
|
|
|
|
restore_record(table, s->default_values);
|
2004-11-13 11:56:39 +01:00
|
|
|
table->field[1]->store(base_name, strlen(base_name), cs);
|
|
|
|
table->field[2]->store(file_name, strlen(file_name), cs);
|
2004-11-13 22:26:15 +01:00
|
|
|
if (res)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
there was errors during opening tables
|
|
|
|
*/
|
|
|
|
const char *error= thd->net.last_error;
|
2005-12-01 08:00:33 +01:00
|
|
|
if (tables->view)
|
|
|
|
table->field[3]->store(STRING_WITH_LEN("VIEW"), cs);
|
|
|
|
else if (tables->schema_table)
|
|
|
|
table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs);
|
|
|
|
else
|
|
|
|
table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs);
|
2004-11-13 22:26:15 +01:00
|
|
|
table->field[20]->store(error, strlen(error), cs);
|
|
|
|
thd->clear_error();
|
|
|
|
}
|
|
|
|
else if (tables->view)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
table->field[3]->store(STRING_WITH_LEN("VIEW"), cs);
|
|
|
|
table->field[20]->store(STRING_WITH_LEN("VIEW"), cs);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TABLE *show_table= tables->table;
|
2005-01-06 12:00:13 +01:00
|
|
|
TABLE_SHARE *share= show_table->s;
|
2004-11-13 11:56:39 +01:00
|
|
|
handler *file= show_table->file;
|
2005-01-06 12:00:13 +01:00
|
|
|
|
2005-08-08 15:46:06 +02:00
|
|
|
file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_AUTO |
|
|
|
|
HA_STATUS_NO_LOCK);
|
2005-08-08 21:59:04 +02:00
|
|
|
if (share->tmp_table == SYSTEM_TMP_TABLE)
|
2005-11-20 19:47:07 +01:00
|
|
|
table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs);
|
2005-08-08 21:59:04 +02:00
|
|
|
else if (share->tmp_table)
|
2005-11-20 19:47:07 +01:00
|
|
|
table->field[3]->store(STRING_WITH_LEN("LOCAL TEMPORARY"), cs);
|
2004-12-10 10:07:11 +01:00
|
|
|
else
|
2005-11-20 19:47:07 +01:00
|
|
|
table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs);
|
2004-12-10 10:07:11 +01:00
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
for (int i= 4; i < 20; i++)
|
|
|
|
{
|
2004-12-24 10:16:47 +01:00
|
|
|
if (i == 7 || (i > 12 && i < 17) || i == 18)
|
2004-11-13 11:56:39 +01:00
|
|
|
continue;
|
|
|
|
table->field[i]->set_notnull();
|
|
|
|
}
|
|
|
|
tmp_buff= file->table_type();
|
|
|
|
table->field[4]->store(tmp_buff, strlen(tmp_buff), cs);
|
2005-09-14 00:41:44 +02:00
|
|
|
table->field[5]->store((longlong) share->frm_version, TRUE);
|
2005-02-08 12:35:10 +01:00
|
|
|
enum row_type row_type = file->get_row_type();
|
|
|
|
switch (row_type) {
|
|
|
|
case ROW_TYPE_NOT_USED:
|
|
|
|
case ROW_TYPE_DEFAULT:
|
|
|
|
tmp_buff= ((share->db_options_in_use &
|
|
|
|
HA_OPTION_COMPRESS_RECORD) ? "Compressed" :
|
|
|
|
(share->db_options_in_use & HA_OPTION_PACK_RECORD) ?
|
|
|
|
"Dynamic" : "Fixed");
|
|
|
|
break;
|
|
|
|
case ROW_TYPE_FIXED:
|
|
|
|
tmp_buff= "Fixed";
|
|
|
|
break;
|
|
|
|
case ROW_TYPE_DYNAMIC:
|
|
|
|
tmp_buff= "Dynamic";
|
|
|
|
break;
|
|
|
|
case ROW_TYPE_COMPRESSED:
|
|
|
|
tmp_buff= "Compressed";
|
|
|
|
break;
|
|
|
|
case ROW_TYPE_REDUNDANT:
|
|
|
|
tmp_buff= "Redundant";
|
|
|
|
break;
|
|
|
|
case ROW_TYPE_COMPACT:
|
|
|
|
tmp_buff= "Compact";
|
|
|
|
break;
|
|
|
|
}
|
2004-11-13 11:56:39 +01:00
|
|
|
table->field[6]->store(tmp_buff, strlen(tmp_buff), cs);
|
2004-12-24 10:16:47 +01:00
|
|
|
if (!tables->schema_table)
|
|
|
|
{
|
2005-09-14 00:41:44 +02:00
|
|
|
table->field[7]->store((longlong) file->records, TRUE);
|
2004-12-24 10:16:47 +01:00
|
|
|
table->field[7]->set_notnull();
|
|
|
|
}
|
2005-10-14 16:12:54 +02:00
|
|
|
table->field[8]->store((longlong) file->mean_rec_length, TRUE);
|
|
|
|
table->field[9]->store((longlong) file->data_file_length, TRUE);
|
2004-11-13 11:56:39 +01:00
|
|
|
if (file->max_data_file_length)
|
|
|
|
{
|
2005-10-14 16:12:54 +02:00
|
|
|
table->field[10]->store((longlong) file->max_data_file_length, TRUE);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
2005-10-14 16:12:54 +02:00
|
|
|
table->field[11]->store((longlong) file->index_file_length, TRUE);
|
|
|
|
table->field[12]->store((longlong) file->delete_length, TRUE);
|
2004-11-17 16:48:12 +01:00
|
|
|
if (show_table->found_next_number_field)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
2005-09-14 00:41:44 +02:00
|
|
|
table->field[13]->store((longlong) file->auto_increment_value, TRUE);
|
2004-11-13 11:56:39 +01:00
|
|
|
table->field[13]->set_notnull();
|
|
|
|
}
|
|
|
|
if (file->create_time)
|
|
|
|
{
|
|
|
|
thd->variables.time_zone->gmt_sec_to_TIME(&time,
|
|
|
|
file->create_time);
|
|
|
|
table->field[14]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
|
|
|
|
table->field[14]->set_notnull();
|
|
|
|
}
|
|
|
|
if (file->update_time)
|
|
|
|
{
|
|
|
|
thd->variables.time_zone->gmt_sec_to_TIME(&time,
|
|
|
|
file->update_time);
|
|
|
|
table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
|
|
|
|
table->field[15]->set_notnull();
|
|
|
|
}
|
|
|
|
if (file->check_time)
|
|
|
|
{
|
|
|
|
thd->variables.time_zone->gmt_sec_to_TIME(&time, file->check_time);
|
|
|
|
table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
|
|
|
|
table->field[16]->set_notnull();
|
|
|
|
}
|
2005-01-06 12:00:13 +01:00
|
|
|
tmp_buff= (share->table_charset ?
|
|
|
|
share->table_charset->name : "default");
|
2004-11-13 11:56:39 +01:00
|
|
|
table->field[17]->store(tmp_buff, strlen(tmp_buff), cs);
|
2004-11-23 15:41:39 +01:00
|
|
|
if (file->table_flags() & (ulong) HA_HAS_CHECKSUM)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
2005-09-14 00:41:44 +02:00
|
|
|
table->field[18]->store((longlong) file->checksum(), TRUE);
|
2004-11-13 11:56:39 +01:00
|
|
|
table->field[18]->set_notnull();
|
|
|
|
}
|
|
|
|
|
|
|
|
char option_buff[350],*ptr;
|
|
|
|
ptr=option_buff;
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->min_rows)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
ptr=strmov(ptr," min_rows=");
|
2005-01-06 12:00:13 +01:00
|
|
|
ptr=longlong10_to_str(share->min_rows,ptr,10);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->max_rows)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
ptr=strmov(ptr," max_rows=");
|
2005-01-06 12:00:13 +01:00
|
|
|
ptr=longlong10_to_str(share->max_rows,ptr,10);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->avg_row_length)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
ptr=strmov(ptr," avg_row_length=");
|
2005-01-06 12:00:13 +01:00
|
|
|
ptr=longlong10_to_str(share->avg_row_length,ptr,10);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->db_create_options & HA_OPTION_PACK_KEYS)
|
2004-11-13 11:56:39 +01:00
|
|
|
ptr=strmov(ptr," pack_keys=1");
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
|
2004-11-13 11:56:39 +01:00
|
|
|
ptr=strmov(ptr," pack_keys=0");
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->db_create_options & HA_OPTION_CHECKSUM)
|
2004-11-13 11:56:39 +01:00
|
|
|
ptr=strmov(ptr," checksum=1");
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
|
2004-11-13 11:56:39 +01:00
|
|
|
ptr=strmov(ptr," delay_key_write=1");
|
2005-01-06 12:00:13 +01:00
|
|
|
if (share->row_type != ROW_TYPE_DEFAULT)
|
2004-11-13 11:56:39 +01:00
|
|
|
ptr=strxmov(ptr, " row_format=",
|
2005-01-06 12:00:13 +01:00
|
|
|
ha_row_type[(uint) share->row_type],
|
2004-11-13 11:56:39 +01:00
|
|
|
NullS);
|
|
|
|
table->field[19]->store(option_buff+1,
|
|
|
|
(ptr == option_buff ? 0 :
|
|
|
|
(uint) (ptr-option_buff)-1), cs);
|
2004-11-17 16:48:12 +01:00
|
|
|
{
|
2005-01-06 12:00:13 +01:00
|
|
|
char *comment;
|
|
|
|
comment= show_table->file->update_table_comment(share->comment);
|
2004-11-17 16:48:12 +01:00
|
|
|
if (comment)
|
|
|
|
{
|
|
|
|
table->field[20]->store(comment, strlen(comment), cs);
|
2005-01-06 12:00:13 +01:00
|
|
|
if (comment != share->comment)
|
|
|
|
my_free(comment, MYF(0));
|
2004-11-17 16:48:12 +01:00
|
|
|
}
|
|
|
|
}
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
2005-03-25 11:31:29 +01:00
|
|
|
DBUG_RETURN(schema_table_store_record(thd, table));
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-13 22:26:15 +01:00
|
|
|
static int get_schema_column_record(THD *thd, struct st_table_list *tables,
|
|
|
|
TABLE *table, bool res,
|
|
|
|
const char *base_name,
|
|
|
|
const char *file_name)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
2004-12-16 14:31:36 +01:00
|
|
|
LEX *lex= thd->lex;
|
|
|
|
const char *wild= lex->wild ? lex->wild->ptr() : NullS;
|
2004-11-13 11:56:39 +01:00
|
|
|
CHARSET_INFO *cs= system_charset_info;
|
2005-08-20 10:00:00 +02:00
|
|
|
TABLE *show_table;
|
|
|
|
handler *file;
|
|
|
|
Field **ptr,*field;
|
|
|
|
int count;
|
|
|
|
uint base_name_length, file_name_length;
|
2004-11-13 11:56:39 +01:00
|
|
|
DBUG_ENTER("get_schema_column_record");
|
2005-08-20 10:00:00 +02:00
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
if (res)
|
|
|
|
{
|
2004-12-16 14:31:36 +01:00
|
|
|
if (lex->orig_sql_command != SQLCOM_SHOW_FIELDS)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS
|
|
|
|
rather than in SHOW COLUMNS
|
|
|
|
*/
|
|
|
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
|
|
thd->net.last_errno, thd->net.last_error);
|
|
|
|
thd->clear_error();
|
|
|
|
res= 0;
|
|
|
|
}
|
|
|
|
DBUG_RETURN(res);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
|
2005-08-20 10:00:00 +02:00
|
|
|
show_table= tables->table;
|
|
|
|
file= show_table->file;
|
|
|
|
count= 0;
|
2004-11-13 11:56:39 +01:00
|
|
|
file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
2005-01-06 12:00:13 +01:00
|
|
|
restore_record(show_table, s->default_values);
|
2005-08-20 10:00:00 +02:00
|
|
|
base_name_length= strlen(base_name);
|
|
|
|
file_name_length= strlen(file_name);
|
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
for (ptr=show_table->field; (field= *ptr) ; ptr++)
|
|
|
|
{
|
2005-08-20 10:00:00 +02:00
|
|
|
const char *tmp_buff;
|
|
|
|
byte *pos;
|
|
|
|
bool is_blob;
|
|
|
|
uint flags=field->flags;
|
|
|
|
char tmp[MAX_FIELD_WIDTH];
|
|
|
|
char tmp1[MAX_FIELD_WIDTH];
|
|
|
|
String type(tmp,sizeof(tmp), system_charset_info);
|
|
|
|
char *end;
|
|
|
|
int decimals, field_length;
|
|
|
|
|
|
|
|
if (wild && wild[0] &&
|
|
|
|
wild_case_compare(system_charset_info, field->field_name,wild))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
flags= field->flags;
|
|
|
|
count++;
|
|
|
|
/* Get default row, with all NULL fields set to NULL */
|
|
|
|
restore_record(table, s->default_values);
|
2005-04-05 12:12:15 +02:00
|
|
|
|
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
2005-08-20 10:00:00 +02:00
|
|
|
uint col_access;
|
|
|
|
check_access(thd,SELECT_ACL | EXTRA_ACL, base_name,
|
2005-09-13 13:07:38 +02:00
|
|
|
&tables->grant.privilege, 0, 0, test(tables->schema_table));
|
2005-08-20 10:00:00 +02:00
|
|
|
col_access= get_column_grant(thd, &tables->grant,
|
|
|
|
base_name, file_name,
|
|
|
|
field->field_name) & COL_ACLS;
|
|
|
|
if (lex->orig_sql_command != SQLCOM_SHOW_FIELDS &&
|
|
|
|
!tables->schema_table && !col_access)
|
|
|
|
continue;
|
|
|
|
end= tmp;
|
|
|
|
for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
|
|
|
|
{
|
|
|
|
if (col_access & 1)
|
2005-04-05 12:12:15 +02:00
|
|
|
{
|
2005-08-20 10:00:00 +02:00
|
|
|
*end++=',';
|
|
|
|
end=strmov(end,grant_types.type_names[bitnr]);
|
2005-04-05 12:12:15 +02:00
|
|
|
}
|
2005-08-20 10:00:00 +02:00
|
|
|
}
|
2005-09-13 13:07:38 +02:00
|
|
|
table->field[17]->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), cs);
|
2005-04-05 12:12:15 +02:00
|
|
|
|
2005-05-07 17:25:59 +02:00
|
|
|
#endif
|
2005-08-20 10:00:00 +02:00
|
|
|
table->field[1]->store(base_name, base_name_length, cs);
|
|
|
|
table->field[2]->store(file_name, file_name_length, cs);
|
|
|
|
table->field[3]->store(field->field_name, strlen(field->field_name),
|
|
|
|
cs);
|
2005-09-14 00:41:44 +02:00
|
|
|
table->field[4]->store((longlong) count, TRUE);
|
2005-08-20 10:00:00 +02:00
|
|
|
field->sql_type(type);
|
|
|
|
table->field[14]->store(type.ptr(), type.length(), cs);
|
|
|
|
tmp_buff= strchr(type.ptr(), '(');
|
|
|
|
table->field[7]->store(type.ptr(),
|
|
|
|
(tmp_buff ? tmp_buff - type.ptr() :
|
|
|
|
type.length()), cs);
|
|
|
|
if (show_table->timestamp_field == field &&
|
|
|
|
field->unireg_check != Field::TIMESTAMP_UN_FIELD)
|
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
table->field[5]->store(STRING_WITH_LEN("CURRENT_TIMESTAMP"), cs);
|
2005-08-20 10:00:00 +02:00
|
|
|
table->field[5]->set_notnull();
|
|
|
|
}
|
|
|
|
else if (field->unireg_check != Field::NEXT_NUMBER &&
|
|
|
|
!field->is_null() &&
|
|
|
|
!(field->flags & NO_DEFAULT_VALUE_FLAG))
|
|
|
|
{
|
|
|
|
String def(tmp1,sizeof(tmp1), cs);
|
|
|
|
type.set(tmp, sizeof(tmp), field->charset());
|
|
|
|
field->val_str(&type);
|
|
|
|
uint dummy_errors;
|
|
|
|
def.copy(type.ptr(), type.length(), type.charset(), cs, &dummy_errors);
|
|
|
|
table->field[5]->store(def.ptr(), def.length(), def.charset());
|
|
|
|
table->field[5]->set_notnull();
|
|
|
|
}
|
|
|
|
else if (field->unireg_check == Field::NEXT_NUMBER ||
|
|
|
|
lex->orig_sql_command != SQLCOM_SHOW_FIELDS ||
|
|
|
|
field->maybe_null())
|
|
|
|
table->field[5]->set_null(); // Null as default
|
|
|
|
else
|
|
|
|
{
|
|
|
|
table->field[5]->store("",0, cs);
|
|
|
|
table->field[5]->set_notnull();
|
|
|
|
}
|
|
|
|
pos=(byte*) ((flags & NOT_NULL_FLAG) &&
|
|
|
|
field->type() != FIELD_TYPE_TIMESTAMP ?
|
|
|
|
"NO" : "YES");
|
|
|
|
table->field[6]->store((const char*) pos,
|
|
|
|
strlen((const char*) pos), cs);
|
|
|
|
is_blob= (field->type() == FIELD_TYPE_BLOB);
|
2005-12-19 13:21:02 +01:00
|
|
|
if (field->has_charset() || is_blob ||
|
|
|
|
field->real_type() == MYSQL_TYPE_VARCHAR || // For varbinary type
|
|
|
|
field->real_type() == MYSQL_TYPE_STRING) // For binary type
|
2005-08-20 10:00:00 +02:00
|
|
|
{
|
2006-01-12 13:05:46 +01:00
|
|
|
uint32 octet_max_length= field->max_length();
|
|
|
|
if (octet_max_length != (uint32) 4294967295U)
|
|
|
|
octet_max_length /= field->charset()->mbmaxlen;
|
2005-10-25 14:22:58 +02:00
|
|
|
longlong char_max_len= is_blob ?
|
2006-01-12 13:05:46 +01:00
|
|
|
(longlong) octet_max_length / field->charset()->mbminlen :
|
|
|
|
(longlong) octet_max_length / field->charset()->mbmaxlen;
|
2005-10-24 13:45:27 +02:00
|
|
|
table->field[8]->store(char_max_len, TRUE);
|
2005-08-20 10:00:00 +02:00
|
|
|
table->field[8]->set_notnull();
|
2006-01-12 13:05:46 +01:00
|
|
|
table->field[9]->store((longlong) octet_max_length, TRUE);
|
2005-08-20 10:00:00 +02:00
|
|
|
table->field[9]->set_notnull();
|
|
|
|
}
|
2004-11-19 23:17:18 +01:00
|
|
|
|
2005-08-20 10:00:00 +02:00
|
|
|
/*
|
|
|
|
Calculate field_length and decimals.
|
|
|
|
They are set to -1 if they should not be set (we should return NULL)
|
|
|
|
*/
|
2004-11-15 22:29:49 +01:00
|
|
|
|
2005-08-20 10:00:00 +02:00
|
|
|
decimals= field->decimals();
|
|
|
|
switch (field->type()) {
|
|
|
|
case FIELD_TYPE_NEWDECIMAL:
|
|
|
|
field_length= ((Field_new_decimal*) field)->precision;
|
|
|
|
break;
|
|
|
|
case FIELD_TYPE_DECIMAL:
|
|
|
|
field_length= field->field_length - (decimals ? 2 : 1);
|
|
|
|
break;
|
|
|
|
case FIELD_TYPE_TINY:
|
|
|
|
case FIELD_TYPE_SHORT:
|
|
|
|
case FIELD_TYPE_LONG:
|
|
|
|
case FIELD_TYPE_LONGLONG:
|
|
|
|
case FIELD_TYPE_INT24:
|
|
|
|
field_length= field->max_length() - 1;
|
|
|
|
break;
|
|
|
|
case FIELD_TYPE_BIT:
|
|
|
|
field_length= field->max_length();
|
|
|
|
decimals= -1; // return NULL
|
|
|
|
break;
|
|
|
|
case FIELD_TYPE_FLOAT:
|
|
|
|
case FIELD_TYPE_DOUBLE:
|
|
|
|
field_length= field->field_length;
|
|
|
|
if (decimals == NOT_FIXED_DEC)
|
|
|
|
decimals= -1; // return NULL
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
field_length= decimals= -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (field_length >= 0)
|
|
|
|
{
|
2005-10-18 14:23:18 +02:00
|
|
|
table->field[10]->store((longlong) field_length, TRUE);
|
2005-08-20 10:00:00 +02:00
|
|
|
table->field[10]->set_notnull();
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
2005-08-20 10:00:00 +02:00
|
|
|
if (decimals >= 0)
|
|
|
|
{
|
2005-09-14 00:41:44 +02:00
|
|
|
table->field[11]->store((longlong) decimals, TRUE);
|
2005-08-20 10:00:00 +02:00
|
|
|
table->field[11]->set_notnull();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (field->has_charset())
|
|
|
|
{
|
|
|
|
pos=(byte*) field->charset()->csname;
|
|
|
|
table->field[12]->store((const char*) pos,
|
|
|
|
strlen((const char*) pos), cs);
|
|
|
|
table->field[12]->set_notnull();
|
|
|
|
pos=(byte*) field->charset()->name;
|
|
|
|
table->field[13]->store((const char*) pos,
|
|
|
|
strlen((const char*) pos), cs);
|
|
|
|
table->field[13]->set_notnull();
|
|
|
|
}
|
|
|
|
pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
|
|
|
|
(field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
|
|
|
|
(field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
|
|
|
|
table->field[15]->store((const char*) pos,
|
|
|
|
strlen((const char*) pos), cs);
|
|
|
|
|
|
|
|
end= tmp;
|
|
|
|
if (field->unireg_check == Field::NEXT_NUMBER)
|
|
|
|
end=strmov(tmp,"auto_increment");
|
|
|
|
table->field[16]->store(tmp, (uint) (end-tmp), cs);
|
|
|
|
|
|
|
|
table->field[18]->store(field->comment.str, field->comment.length, cs);
|
|
|
|
if (schema_table_store_record(thd, table))
|
|
|
|
DBUG_RETURN(1);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond)
|
|
|
|
{
|
|
|
|
CHARSET_INFO **cs;
|
|
|
|
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
|
|
|
|
TABLE *table= tables->table;
|
|
|
|
CHARSET_INFO *scs= system_charset_info;
|
2005-08-20 10:00:00 +02:00
|
|
|
|
|
|
|
for (cs= all_charsets ; cs < all_charsets+255 ; cs++)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
CHARSET_INFO *tmp_cs= cs[0];
|
|
|
|
if (tmp_cs && (tmp_cs->state & MY_CS_PRIMARY) &&
|
|
|
|
(tmp_cs->state & MY_CS_AVAILABLE) &&
|
2006-01-18 09:27:02 +01:00
|
|
|
!(tmp_cs->state & MY_CS_HIDDEN) &&
|
2004-11-13 11:56:39 +01:00
|
|
|
!(wild && wild[0] &&
|
|
|
|
wild_case_compare(scs, tmp_cs->csname,wild)))
|
|
|
|
{
|
2005-08-20 10:00:00 +02:00
|
|
|
const char *comment;
|
2005-01-06 12:00:13 +01:00
|
|
|
restore_record(table, s->default_values);
|
2004-11-13 11:56:39 +01:00
|
|
|
table->field[0]->store(tmp_cs->csname, strlen(tmp_cs->csname), scs);
|
2004-12-14 14:18:59 +01:00
|
|
|
table->field[1]->store(tmp_cs->name, strlen(tmp_cs->name), scs);
|
2005-08-20 10:00:00 +02:00
|
|
|
comment= tmp_cs->comment ? tmp_cs->comment : "";
|
|
|
|
table->field[2]->store(comment, strlen(comment), scs);
|
2005-09-14 00:41:44 +02:00
|
|
|
table->field[3]->store((longlong) tmp_cs->mbmaxlen, TRUE);
|
2005-03-24 14:32:11 +01:00
|
|
|
if (schema_table_store_record(thd, table))
|
|
|
|
return 1;
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-22 10:07:47 +01:00
|
|
|
int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond)
|
|
|
|
{
|
|
|
|
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
|
|
|
|
TABLE *table= tables->table;
|
|
|
|
CHARSET_INFO *scs= system_charset_info;
|
|
|
|
handlerton **types;
|
|
|
|
|
|
|
|
DBUG_ENTER("fill_schema_engines");
|
|
|
|
|
|
|
|
for (types= sys_table_types; *types; types++)
|
|
|
|
{
|
|
|
|
if ((*types)->flags & HTON_HIDDEN)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!(wild && wild[0] &&
|
|
|
|
wild_case_compare(scs, (*types)->name,wild)))
|
|
|
|
{
|
|
|
|
const char *tmp;
|
|
|
|
restore_record(table, s->default_values);
|
|
|
|
|
|
|
|
table->field[0]->store((*types)->name, strlen((*types)->name), scs);
|
|
|
|
tmp= (*types)->state ? "DISABLED" : "ENABLED";
|
|
|
|
table->field[1]->store( tmp, strlen(tmp), scs);
|
|
|
|
table->field[2]->store((*types)->comment, strlen((*types)->comment), scs);
|
|
|
|
tmp= (*types)->commit ? "YES" : "NO";
|
|
|
|
table->field[3]->store( tmp, strlen(tmp), scs);
|
|
|
|
tmp= (*types)->prepare ? "YES" : "NO";
|
|
|
|
table->field[4]->store( tmp, strlen(tmp), scs);
|
|
|
|
tmp= (*types)->savepoint_set ? "YES" : "NO";
|
|
|
|
table->field[5]->store( tmp, strlen(tmp), scs);
|
|
|
|
|
|
|
|
if (schema_table_store_record(thd, table))
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond)
|
|
|
|
{
|
|
|
|
CHARSET_INFO **cs;
|
|
|
|
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
|
|
|
|
TABLE *table= tables->table;
|
|
|
|
CHARSET_INFO *scs= system_charset_info;
|
2005-08-20 10:00:00 +02:00
|
|
|
for (cs= all_charsets ; cs < all_charsets+255 ; cs++ )
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
CHARSET_INFO **cl;
|
|
|
|
CHARSET_INFO *tmp_cs= cs[0];
|
|
|
|
if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) ||
|
2006-01-18 09:27:02 +01:00
|
|
|
(tmp_cs->state & MY_CS_HIDDEN) ||
|
2004-11-13 11:56:39 +01:00
|
|
|
!(tmp_cs->state & MY_CS_PRIMARY))
|
|
|
|
continue;
|
2005-08-20 10:00:00 +02:00
|
|
|
for (cl= all_charsets; cl < all_charsets+255 ;cl ++)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
CHARSET_INFO *tmp_cl= cl[0];
|
|
|
|
if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) ||
|
|
|
|
!my_charset_same(tmp_cs, tmp_cl))
|
|
|
|
continue;
|
|
|
|
if (!(wild && wild[0] &&
|
|
|
|
wild_case_compare(scs, tmp_cl->name,wild)))
|
|
|
|
{
|
|
|
|
const char *tmp_buff;
|
2005-01-06 12:00:13 +01:00
|
|
|
restore_record(table, s->default_values);
|
2004-11-13 11:56:39 +01:00
|
|
|
table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
|
|
|
|
table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
|
2005-09-14 00:41:44 +02:00
|
|
|
table->field[2]->store((longlong) tmp_cl->number, TRUE);
|
2004-11-13 11:56:39 +01:00
|
|
|
tmp_buff= (tmp_cl->state & MY_CS_PRIMARY) ? "Yes" : "";
|
|
|
|
table->field[3]->store(tmp_buff, strlen(tmp_buff), scs);
|
|
|
|
tmp_buff= (tmp_cl->state & MY_CS_COMPILED)? "Yes" : "";
|
|
|
|
table->field[4]->store(tmp_buff, strlen(tmp_buff), scs);
|
2005-09-14 00:41:44 +02:00
|
|
|
table->field[5]->store((longlong) tmp_cl->strxfrm_multiply, TRUE);
|
2005-03-24 14:32:11 +01:00
|
|
|
if (schema_table_store_record(thd, table))
|
|
|
|
return 1;
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int fill_schema_coll_charset_app(THD *thd, TABLE_LIST *tables, COND *cond)
|
|
|
|
{
|
|
|
|
CHARSET_INFO **cs;
|
|
|
|
TABLE *table= tables->table;
|
|
|
|
CHARSET_INFO *scs= system_charset_info;
|
2005-08-20 10:00:00 +02:00
|
|
|
for (cs= all_charsets ; cs < all_charsets+255 ; cs++ )
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
CHARSET_INFO **cl;
|
|
|
|
CHARSET_INFO *tmp_cs= cs[0];
|
|
|
|
if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) ||
|
|
|
|
!(tmp_cs->state & MY_CS_PRIMARY))
|
|
|
|
continue;
|
2005-08-20 10:00:00 +02:00
|
|
|
for (cl= all_charsets; cl < all_charsets+255 ;cl ++)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
CHARSET_INFO *tmp_cl= cl[0];
|
|
|
|
if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) ||
|
|
|
|
!my_charset_same(tmp_cs,tmp_cl))
|
|
|
|
continue;
|
2005-01-06 12:00:13 +01:00
|
|
|
restore_record(table, s->default_values);
|
2004-11-13 11:56:39 +01:00
|
|
|
table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
|
|
|
|
table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
|
2005-03-24 14:32:11 +01:00
|
|
|
if (schema_table_store_record(thd, table))
|
|
|
|
return 1;
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-03-24 14:32:11 +01:00
|
|
|
bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
|
2005-03-05 12:35:32 +01:00
|
|
|
const char *wild, bool full_access, const char *sp_user)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
String tmp_string;
|
|
|
|
TIME time;
|
|
|
|
LEX *lex= thd->lex;
|
|
|
|
CHARSET_INFO *cs= system_charset_info;
|
2005-03-05 12:35:32 +01:00
|
|
|
const char *sp_db, *sp_name, *definer;
|
|
|
|
sp_db= get_field(thd->mem_root, proc_table->field[0]);
|
|
|
|
sp_name= get_field(thd->mem_root, proc_table->field[1]);
|
|
|
|
definer= get_field(thd->mem_root, proc_table->field[11]);
|
|
|
|
if (!full_access)
|
|
|
|
full_access= !strcmp(sp_user, definer);
|
2005-05-17 20:54:20 +02:00
|
|
|
if (!full_access && check_some_routine_access(thd, sp_db, sp_name,
|
|
|
|
proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE))
|
2005-03-24 14:32:11 +01:00
|
|
|
return 0;
|
2005-03-05 12:35:32 +01:00
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
if (lex->orig_sql_command == SQLCOM_SHOW_STATUS_PROC &&
|
|
|
|
proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE ||
|
|
|
|
lex->orig_sql_command == SQLCOM_SHOW_STATUS_FUNC &&
|
|
|
|
proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION ||
|
|
|
|
lex->orig_sql_command == SQLCOM_END)
|
|
|
|
{
|
2005-03-05 12:35:32 +01:00
|
|
|
restore_record(table, s->default_values);
|
|
|
|
if (!wild || !wild[0] || !wild_compare(sp_name, wild, 0))
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
2005-06-16 09:12:47 +02:00
|
|
|
int enum_idx= proc_table->field[5]->val_int();
|
2005-03-05 12:35:32 +01:00
|
|
|
table->field[3]->store(sp_name, strlen(sp_name), cs);
|
2004-11-19 23:17:18 +01:00
|
|
|
get_field(thd->mem_root, proc_table->field[3], &tmp_string);
|
|
|
|
table->field[0]->store(tmp_string.ptr(), tmp_string.length(), cs);
|
2005-03-05 12:35:32 +01:00
|
|
|
table->field[2]->store(sp_db, strlen(sp_db), cs);
|
2004-11-13 11:56:39 +01:00
|
|
|
get_field(thd->mem_root, proc_table->field[2], &tmp_string);
|
|
|
|
table->field[4]->store(tmp_string.ptr(), tmp_string.length(), cs);
|
2004-12-14 12:55:28 +01:00
|
|
|
if (proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION)
|
|
|
|
{
|
|
|
|
get_field(thd->mem_root, proc_table->field[9], &tmp_string);
|
|
|
|
table->field[5]->store(tmp_string.ptr(), tmp_string.length(), cs);
|
|
|
|
table->field[5]->set_notnull();
|
|
|
|
}
|
2005-03-05 12:35:32 +01:00
|
|
|
if (full_access)
|
|
|
|
{
|
|
|
|
get_field(thd->mem_root, proc_table->field[10], &tmp_string);
|
|
|
|
table->field[7]->store(tmp_string.ptr(), tmp_string.length(), cs);
|
|
|
|
}
|
2005-11-20 19:47:07 +01:00
|
|
|
table->field[6]->store(STRING_WITH_LEN("SQL"), cs);
|
|
|
|
table->field[10]->store(STRING_WITH_LEN("SQL"), cs);
|
2004-11-13 11:56:39 +01:00
|
|
|
get_field(thd->mem_root, proc_table->field[6], &tmp_string);
|
2004-11-19 23:17:18 +01:00
|
|
|
table->field[11]->store(tmp_string.ptr(), tmp_string.length(), cs);
|
2005-06-16 09:12:47 +02:00
|
|
|
table->field[12]->store(sp_data_access_name[enum_idx].str,
|
|
|
|
sp_data_access_name[enum_idx].length , cs);
|
2004-11-19 23:17:18 +01:00
|
|
|
get_field(thd->mem_root, proc_table->field[7], &tmp_string);
|
|
|
|
table->field[14]->store(tmp_string.ptr(), tmp_string.length(), cs);
|
2004-11-13 11:56:39 +01:00
|
|
|
bzero((char *)&time, sizeof(time));
|
|
|
|
((Field_timestamp *) proc_table->field[12])->get_time(&time);
|
2004-11-19 23:17:18 +01:00
|
|
|
table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
|
2004-11-13 11:56:39 +01:00
|
|
|
bzero((char *)&time, sizeof(time));
|
|
|
|
((Field_timestamp *) proc_table->field[13])->get_time(&time);
|
2004-11-19 23:17:18 +01:00
|
|
|
table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
|
2004-11-13 11:56:39 +01:00
|
|
|
get_field(thd->mem_root, proc_table->field[14], &tmp_string);
|
2004-11-19 23:17:18 +01:00
|
|
|
table->field[17]->store(tmp_string.ptr(), tmp_string.length(), cs);
|
2004-11-13 11:56:39 +01:00
|
|
|
get_field(thd->mem_root, proc_table->field[15], &tmp_string);
|
2004-11-19 23:17:18 +01:00
|
|
|
table->field[18]->store(tmp_string.ptr(), tmp_string.length(), cs);
|
2005-03-05 12:35:32 +01:00
|
|
|
table->field[19]->store(definer, strlen(definer), cs);
|
2005-03-25 11:31:29 +01:00
|
|
|
return schema_table_store_record(thd, table);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
}
|
2005-03-24 14:32:11 +01:00
|
|
|
return 0;
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond)
|
|
|
|
{
|
|
|
|
TABLE *proc_table;
|
|
|
|
TABLE_LIST proc_tables;
|
|
|
|
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
|
|
|
|
int res= 0;
|
2005-08-08 15:46:06 +02:00
|
|
|
TABLE *table= tables->table;
|
2005-03-05 12:35:32 +01:00
|
|
|
bool full_access;
|
2006-01-11 00:07:40 +01:00
|
|
|
char definer[USER_HOST_BUFF_SIZE];
|
2005-08-08 15:46:06 +02:00
|
|
|
Open_tables_state open_tables_state_backup;
|
2004-11-13 11:56:39 +01:00
|
|
|
DBUG_ENTER("fill_schema_proc");
|
|
|
|
|
2005-09-15 21:29:07 +02:00
|
|
|
strxmov(definer, thd->security_ctx->priv_user, "@",
|
|
|
|
thd->security_ctx->priv_host, NullS);
|
2005-08-08 15:46:06 +02:00
|
|
|
/* We use this TABLE_LIST instance only for checking of privileges. */
|
2004-11-13 11:56:39 +01:00
|
|
|
bzero((char*) &proc_tables,sizeof(proc_tables));
|
|
|
|
proc_tables.db= (char*) "mysql";
|
2005-02-08 20:52:50 +01:00
|
|
|
proc_tables.db_length= 5;
|
2005-01-06 12:00:13 +01:00
|
|
|
proc_tables.table_name= proc_tables.alias= (char*) "proc";
|
2005-02-08 20:52:50 +01:00
|
|
|
proc_tables.table_name_length= 4;
|
2004-11-13 11:56:39 +01:00
|
|
|
proc_tables.lock_type= TL_READ;
|
2005-03-05 12:35:32 +01:00
|
|
|
full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, 1);
|
2005-08-08 15:46:06 +02:00
|
|
|
if (!(proc_table= open_proc_table_for_read(thd, &open_tables_state_backup)))
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
2005-07-18 13:31:02 +02:00
|
|
|
proc_table->file->ha_index_init(0, 1);
|
2004-11-13 11:56:39 +01:00
|
|
|
if ((res= proc_table->file->index_first(proc_table->record[0])))
|
|
|
|
{
|
|
|
|
res= (res == HA_ERR_END_OF_FILE) ? 0 : 1;
|
|
|
|
goto err;
|
|
|
|
}
|
2005-03-24 14:32:11 +01:00
|
|
|
if (store_schema_proc(thd, table, proc_table, wild, full_access, definer))
|
|
|
|
{
|
|
|
|
res= 1;
|
|
|
|
goto err;
|
|
|
|
}
|
2004-11-13 11:56:39 +01:00
|
|
|
while (!proc_table->file->index_next(proc_table->record[0]))
|
2005-03-24 14:32:11 +01:00
|
|
|
{
|
|
|
|
if (store_schema_proc(thd, table, proc_table, wild, full_access, definer))
|
|
|
|
{
|
|
|
|
res= 1;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
2004-11-13 11:56:39 +01:00
|
|
|
|
|
|
|
err:
|
|
|
|
proc_table->file->ha_index_end();
|
2005-08-08 15:46:06 +02:00
|
|
|
close_proc_table(thd, &open_tables_state_backup);
|
2004-11-13 11:56:39 +01:00
|
|
|
DBUG_RETURN(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-13 22:26:15 +01:00
|
|
|
static int get_schema_stat_record(THD *thd, struct st_table_list *tables,
|
|
|
|
TABLE *table, bool res,
|
|
|
|
const char *base_name,
|
|
|
|
const char *file_name)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
CHARSET_INFO *cs= system_charset_info;
|
|
|
|
DBUG_ENTER("get_schema_stat_record");
|
2004-12-16 14:31:36 +01:00
|
|
|
if (res)
|
|
|
|
{
|
|
|
|
if (thd->lex->orig_sql_command != SQLCOM_SHOW_KEYS)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS
|
|
|
|
rather than in SHOW KEYS
|
2006-01-03 17:54:54 +01:00
|
|
|
*/
|
2004-12-16 14:31:36 +01:00
|
|
|
if (!tables->view)
|
|
|
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
|
|
thd->net.last_errno, thd->net.last_error);
|
|
|
|
thd->clear_error();
|
|
|
|
res= 0;
|
|
|
|
}
|
|
|
|
DBUG_RETURN(res);
|
|
|
|
}
|
|
|
|
else if (!tables->view)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
TABLE *show_table= tables->table;
|
|
|
|
KEY *key_info=show_table->key_info;
|
2006-01-03 17:54:54 +01:00
|
|
|
show_table->file->info(HA_STATUS_VARIABLE |
|
2004-11-13 11:56:39 +01:00
|
|
|
HA_STATUS_NO_LOCK |
|
|
|
|
HA_STATUS_TIME);
|
2005-01-06 12:00:13 +01:00
|
|
|
for (uint i=0 ; i < show_table->s->keys ; i++,key_info++)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
KEY_PART_INFO *key_part= key_info->key_part;
|
|
|
|
const char *str;
|
|
|
|
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
|
|
|
|
{
|
2005-01-06 12:00:13 +01:00
|
|
|
restore_record(table, s->default_values);
|
2004-11-13 11:56:39 +01:00
|
|
|
table->field[1]->store(base_name, strlen(base_name), cs);
|
|
|
|
table->field[2]->store(file_name, strlen(file_name), cs);
|
2006-01-03 17:54:54 +01:00
|
|
|
table->field[3]->store((longlong) ((key_info->flags &
|
2005-09-14 00:41:44 +02:00
|
|
|
HA_NOSAME) ? 0 : 1), TRUE);
|
2004-11-13 11:56:39 +01:00
|
|
|
table->field[4]->store(base_name, strlen(base_name), cs);
|
|
|
|
table->field[5]->store(key_info->name, strlen(key_info->name), cs);
|
2005-09-14 00:41:44 +02:00
|
|
|
table->field[6]->store((longlong) (j+1), TRUE);
|
2004-11-13 11:56:39 +01:00
|
|
|
str=(key_part->field ? key_part->field->field_name :
|
|
|
|
"?unknown field?");
|
|
|
|
table->field[7]->store(str, strlen(str), cs);
|
|
|
|
if (show_table->file->index_flags(i, j, 0) & HA_READ_ORDER)
|
|
|
|
{
|
|
|
|
table->field[8]->store(((key_part->key_part_flag &
|
|
|
|
HA_REVERSE_SORT) ?
|
|
|
|
"D" : "A"), 1, cs);
|
|
|
|
table->field[8]->set_notnull();
|
|
|
|
}
|
|
|
|
KEY *key=show_table->key_info+i;
|
|
|
|
if (key->rec_per_key[j])
|
|
|
|
{
|
|
|
|
ha_rows records=(show_table->file->records /
|
|
|
|
key->rec_per_key[j]);
|
2005-09-14 00:41:44 +02:00
|
|
|
table->field[9]->store((longlong) records, TRUE);
|
2004-11-13 11:56:39 +01:00
|
|
|
table->field[9]->set_notnull();
|
|
|
|
}
|
2006-01-03 17:54:54 +01:00
|
|
|
if (!(key_info->flags & HA_FULLTEXT) &&
|
|
|
|
(key_part->field &&
|
|
|
|
key_part->length !=
|
2004-11-13 11:56:39 +01:00
|
|
|
show_table->field[key_part->fieldnr-1]->key_length()))
|
|
|
|
{
|
2006-01-03 17:54:54 +01:00
|
|
|
table->field[10]->store((longlong) key_part->length /
|
2005-01-21 14:00:14 +01:00
|
|
|
key_part->field->charset()->mbmaxlen);
|
2004-11-13 11:56:39 +01:00
|
|
|
table->field[10]->set_notnull();
|
|
|
|
}
|
|
|
|
uint flags= key_part->field ? key_part->field->flags : 0;
|
|
|
|
const char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
|
|
|
|
table->field[12]->store(pos, strlen(pos), cs);
|
|
|
|
pos= show_table->file->index_type(i);
|
|
|
|
table->field[13]->store(pos, strlen(pos), cs);
|
2005-01-06 12:00:13 +01:00
|
|
|
if (!show_table->s->keys_in_use.is_set(i))
|
2005-11-20 19:47:07 +01:00
|
|
|
table->field[14]->store(STRING_WITH_LEN("disabled"), cs);
|
2004-11-13 11:56:39 +01:00
|
|
|
else
|
|
|
|
table->field[14]->store("", 0, cs);
|
|
|
|
table->field[14]->set_notnull();
|
2005-03-24 14:32:11 +01:00
|
|
|
if (schema_table_store_record(thd, table))
|
|
|
|
DBUG_RETURN(1);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-11-13 22:26:15 +01:00
|
|
|
DBUG_RETURN(res);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-13 22:26:15 +01:00
|
|
|
static int get_schema_views_record(THD *thd, struct st_table_list *tables,
|
|
|
|
TABLE *table, bool res,
|
|
|
|
const char *base_name,
|
|
|
|
const char *file_name)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
CHARSET_INFO *cs= system_charset_info;
|
|
|
|
DBUG_ENTER("get_schema_views_record");
|
2006-01-11 00:07:40 +01:00
|
|
|
char definer[USER_HOST_BUFF_SIZE];
|
2005-09-16 08:15:45 +02:00
|
|
|
uint definer_len;
|
2004-11-15 17:20:45 +01:00
|
|
|
|
2005-11-11 10:39:46 +01:00
|
|
|
if (tables->view)
|
|
|
|
{
|
|
|
|
restore_record(table, s->default_values);
|
|
|
|
table->field[1]->store(tables->view_db.str, tables->view_db.length, cs);
|
|
|
|
table->field[2]->store(tables->view_name.str, tables->view_name.length,
|
|
|
|
cs);
|
|
|
|
table->field[3]->store(tables->query.str, tables->query.length, cs);
|
2004-11-15 17:20:45 +01:00
|
|
|
|
2005-11-11 10:39:46 +01:00
|
|
|
if (tables->with_check != VIEW_CHECK_NONE)
|
|
|
|
{
|
|
|
|
if (tables->with_check == VIEW_CHECK_LOCAL)
|
|
|
|
table->field[4]->store(STRING_WITH_LEN("LOCAL"), cs);
|
2005-09-15 10:56:06 +02:00
|
|
|
else
|
2005-11-11 10:39:46 +01:00
|
|
|
table->field[4]->store(STRING_WITH_LEN("CASCADED"), cs);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
2005-11-11 10:39:46 +01:00
|
|
|
else
|
|
|
|
table->field[4]->store(STRING_WITH_LEN("NONE"), cs);
|
|
|
|
|
|
|
|
if (tables->updatable_view)
|
|
|
|
table->field[5]->store(STRING_WITH_LEN("YES"), cs);
|
|
|
|
else
|
|
|
|
table->field[5]->store(STRING_WITH_LEN("NO"), cs);
|
|
|
|
definer_len= (strxmov(definer, tables->definer.user.str, "@",
|
|
|
|
tables->definer.host.str, NullS) - definer);
|
|
|
|
table->field[6]->store(definer, definer_len, cs);
|
|
|
|
if (tables->view_suid)
|
|
|
|
table->field[7]->store(STRING_WITH_LEN("DEFINER"), cs);
|
|
|
|
else
|
|
|
|
table->field[7]->store(STRING_WITH_LEN("INVOKER"), cs);
|
|
|
|
if (schema_table_store_record(thd, table))
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
if (res)
|
2004-12-16 15:44:36 +01:00
|
|
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
|
|
thd->net.last_errno, thd->net.last_error);
|
|
|
|
}
|
2005-11-11 10:39:46 +01:00
|
|
|
if (res)
|
|
|
|
thd->clear_error();
|
2004-12-16 15:44:36 +01:00
|
|
|
DBUG_RETURN(0);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-03-24 14:32:11 +01:00
|
|
|
bool store_constraints(THD *thd, TABLE *table, const char *db,
|
|
|
|
const char *tname, const char *key_name,
|
|
|
|
uint key_len, const char *con_type, uint con_len)
|
2004-12-10 10:07:11 +01:00
|
|
|
{
|
|
|
|
CHARSET_INFO *cs= system_charset_info;
|
2005-01-06 12:00:13 +01:00
|
|
|
restore_record(table, s->default_values);
|
2004-12-10 10:07:11 +01:00
|
|
|
table->field[1]->store(db, strlen(db), cs);
|
|
|
|
table->field[2]->store(key_name, key_len, cs);
|
|
|
|
table->field[3]->store(db, strlen(db), cs);
|
|
|
|
table->field[4]->store(tname, strlen(tname), cs);
|
|
|
|
table->field[5]->store(con_type, con_len, cs);
|
2005-03-25 11:31:29 +01:00
|
|
|
return schema_table_store_record(thd, table);
|
2004-12-10 10:07:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-12-14 11:21:38 +01:00
|
|
|
static int get_schema_constraints_record(THD *thd, struct st_table_list *tables,
|
2004-11-13 22:26:15 +01:00
|
|
|
TABLE *table, bool res,
|
|
|
|
const char *base_name,
|
|
|
|
const char *file_name)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
2004-12-14 11:21:38 +01:00
|
|
|
DBUG_ENTER("get_schema_constraints_record");
|
2004-12-16 14:31:36 +01:00
|
|
|
if (res)
|
|
|
|
{
|
|
|
|
if (!tables->view)
|
|
|
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
|
|
thd->net.last_errno, thd->net.last_error);
|
|
|
|
thd->clear_error();
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
else if (!tables->view)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
List<FOREIGN_KEY_INFO> f_key_list;
|
|
|
|
TABLE *show_table= tables->table;
|
|
|
|
KEY *key_info=show_table->key_info;
|
2005-01-06 12:00:13 +01:00
|
|
|
uint primary_key= show_table->s->primary_key;
|
2004-11-13 11:56:39 +01:00
|
|
|
show_table->file->info(HA_STATUS_VARIABLE |
|
|
|
|
HA_STATUS_NO_LOCK |
|
|
|
|
HA_STATUS_TIME);
|
2005-01-06 12:00:13 +01:00
|
|
|
for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
if (i != primary_key && !(key_info->flags & HA_NOSAME))
|
2004-12-10 10:07:11 +01:00
|
|
|
continue;
|
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
if (i == primary_key && !strcmp(key_info->name, primary_key_name))
|
2005-03-24 14:32:11 +01:00
|
|
|
{
|
|
|
|
if (store_constraints(thd, table, base_name, file_name, key_info->name,
|
2005-11-20 19:47:07 +01:00
|
|
|
strlen(key_info->name),
|
|
|
|
STRING_WITH_LEN("PRIMARY KEY")))
|
2005-03-24 14:32:11 +01:00
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
2004-11-13 11:56:39 +01:00
|
|
|
else if (key_info->flags & HA_NOSAME)
|
2005-03-24 14:32:11 +01:00
|
|
|
{
|
|
|
|
if (store_constraints(thd, table, base_name, file_name, key_info->name,
|
2005-11-20 19:47:07 +01:00
|
|
|
strlen(key_info->name),
|
|
|
|
STRING_WITH_LEN("UNIQUE")))
|
2005-03-24 14:32:11 +01:00
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
show_table->file->get_foreign_key_list(thd, &f_key_list);
|
|
|
|
FOREIGN_KEY_INFO *f_key_info;
|
|
|
|
List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
|
|
|
|
while ((f_key_info=it++))
|
|
|
|
{
|
2005-03-24 14:32:11 +01:00
|
|
|
if (store_constraints(thd, table, base_name, file_name,
|
|
|
|
f_key_info->forein_id->str,
|
|
|
|
strlen(f_key_info->forein_id->str),
|
|
|
|
"FOREIGN KEY", 11))
|
|
|
|
DBUG_RETURN(1);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
}
|
2004-11-13 22:26:15 +01:00
|
|
|
DBUG_RETURN(res);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-19 18:06:49 +02:00
|
|
|
static bool store_trigger(THD *thd, TABLE *table, const char *db,
|
|
|
|
const char *tname, LEX_STRING *trigger_name,
|
|
|
|
enum trg_event_type event,
|
|
|
|
enum trg_action_time_type timing,
|
2005-07-28 21:39:11 +02:00
|
|
|
LEX_STRING *trigger_stmt,
|
2005-11-10 20:25:03 +01:00
|
|
|
ulong sql_mode,
|
|
|
|
LEX_STRING *definer_buffer)
|
2005-07-19 18:06:49 +02:00
|
|
|
{
|
|
|
|
CHARSET_INFO *cs= system_charset_info;
|
2005-07-28 21:39:11 +02:00
|
|
|
byte *sql_mode_str;
|
|
|
|
ulong sql_mode_len;
|
|
|
|
|
2005-07-19 18:06:49 +02:00
|
|
|
restore_record(table, s->default_values);
|
|
|
|
table->field[1]->store(db, strlen(db), cs);
|
|
|
|
table->field[2]->store(trigger_name->str, trigger_name->length, cs);
|
|
|
|
table->field[3]->store(trg_event_type_names[event].str,
|
|
|
|
trg_event_type_names[event].length, cs);
|
|
|
|
table->field[5]->store(db, strlen(db), cs);
|
|
|
|
table->field[6]->store(tname, strlen(tname), cs);
|
|
|
|
table->field[9]->store(trigger_stmt->str, trigger_stmt->length, cs);
|
2005-11-20 19:47:07 +01:00
|
|
|
table->field[10]->store(STRING_WITH_LEN("ROW"), cs);
|
2005-07-19 18:06:49 +02:00
|
|
|
table->field[11]->store(trg_action_time_type_names[timing].str,
|
|
|
|
trg_action_time_type_names[timing].length, cs);
|
2005-11-20 19:47:07 +01:00
|
|
|
table->field[14]->store(STRING_WITH_LEN("OLD"), cs);
|
|
|
|
table->field[15]->store(STRING_WITH_LEN("NEW"), cs);
|
2005-07-28 21:39:11 +02:00
|
|
|
|
|
|
|
sql_mode_str=
|
|
|
|
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
|
|
|
|
sql_mode,
|
|
|
|
&sql_mode_len);
|
2005-08-03 00:25:40 +02:00
|
|
|
table->field[17]->store((const char*)sql_mode_str, sql_mode_len, cs);
|
2005-11-10 20:25:03 +01:00
|
|
|
table->field[18]->store((const char *)definer_buffer->str, definer_buffer->length, cs);
|
2005-07-19 18:06:49 +02:00
|
|
|
return schema_table_store_record(thd, table);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int get_schema_triggers_record(THD *thd, struct st_table_list *tables,
|
|
|
|
TABLE *table, bool res,
|
|
|
|
const char *base_name,
|
|
|
|
const char *file_name)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("get_schema_triggers_record");
|
|
|
|
/*
|
|
|
|
res can be non zero value when processed table is a view or
|
|
|
|
error happened during opening of processed table.
|
|
|
|
*/
|
|
|
|
if (res)
|
|
|
|
{
|
|
|
|
if (!tables->view)
|
|
|
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
|
|
thd->net.last_errno, thd->net.last_error);
|
|
|
|
thd->clear_error();
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
if (!tables->view && tables->table->triggers)
|
|
|
|
{
|
|
|
|
Table_triggers_list *triggers= tables->table->triggers;
|
|
|
|
int event, timing;
|
|
|
|
for (event= 0; event < (int)TRG_EVENT_MAX; event++)
|
|
|
|
{
|
|
|
|
for (timing= 0; timing < (int)TRG_ACTION_MAX; timing++)
|
|
|
|
{
|
|
|
|
LEX_STRING trigger_name;
|
|
|
|
LEX_STRING trigger_stmt;
|
2005-07-28 21:39:11 +02:00
|
|
|
ulong sql_mode;
|
2006-01-11 00:07:40 +01:00
|
|
|
char definer_holder[USER_HOST_BUFF_SIZE];
|
2005-11-10 20:25:03 +01:00
|
|
|
LEX_STRING definer_buffer;
|
|
|
|
definer_buffer.str= definer_holder;
|
2005-07-19 18:06:49 +02:00
|
|
|
if (triggers->get_trigger_info(thd, (enum trg_event_type) event,
|
|
|
|
(enum trg_action_time_type)timing,
|
2005-07-28 21:39:11 +02:00
|
|
|
&trigger_name, &trigger_stmt,
|
2005-11-10 20:25:03 +01:00
|
|
|
&sql_mode,
|
|
|
|
&definer_buffer))
|
2005-07-19 18:06:49 +02:00
|
|
|
continue;
|
2005-11-10 20:25:03 +01:00
|
|
|
|
2005-07-19 18:06:49 +02:00
|
|
|
if (store_trigger(thd, table, base_name, file_name, &trigger_name,
|
|
|
|
(enum trg_event_type) event,
|
2005-07-28 21:39:11 +02:00
|
|
|
(enum trg_action_time_type) timing, &trigger_stmt,
|
2005-11-10 20:25:03 +01:00
|
|
|
sql_mode,
|
|
|
|
&definer_buffer))
|
2005-07-19 18:06:49 +02:00
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-12-10 10:07:11 +01:00
|
|
|
void store_key_column_usage(TABLE *table, const char*db, const char *tname,
|
|
|
|
const char *key_name, uint key_len,
|
|
|
|
const char *con_type, uint con_len, longlong idx)
|
|
|
|
{
|
|
|
|
CHARSET_INFO *cs= system_charset_info;
|
|
|
|
table->field[1]->store(db, strlen(db), cs);
|
|
|
|
table->field[2]->store(key_name, key_len, cs);
|
|
|
|
table->field[4]->store(db, strlen(db), cs);
|
|
|
|
table->field[5]->store(tname, strlen(tname), cs);
|
|
|
|
table->field[6]->store(con_type, con_len, cs);
|
2005-09-14 00:41:44 +02:00
|
|
|
table->field[7]->store((longlong) idx, TRUE);
|
2004-12-10 10:07:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-13 22:26:15 +01:00
|
|
|
static int get_schema_key_column_usage_record(THD *thd,
|
|
|
|
struct st_table_list *tables,
|
|
|
|
TABLE *table, bool res,
|
|
|
|
const char *base_name,
|
|
|
|
const char *file_name)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
DBUG_ENTER("get_schema_key_column_usage_record");
|
2004-12-16 14:31:36 +01:00
|
|
|
if (res)
|
|
|
|
{
|
|
|
|
if (!tables->view)
|
|
|
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
|
|
thd->net.last_errno, thd->net.last_error);
|
|
|
|
thd->clear_error();
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
else if (!tables->view)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
List<FOREIGN_KEY_INFO> f_key_list;
|
|
|
|
TABLE *show_table= tables->table;
|
|
|
|
KEY *key_info=show_table->key_info;
|
2005-01-06 12:00:13 +01:00
|
|
|
uint primary_key= show_table->s->primary_key;
|
2004-11-13 11:56:39 +01:00
|
|
|
show_table->file->info(HA_STATUS_VARIABLE |
|
|
|
|
HA_STATUS_NO_LOCK |
|
|
|
|
HA_STATUS_TIME);
|
2005-01-06 12:00:13 +01:00
|
|
|
for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
if (i != primary_key && !(key_info->flags & HA_NOSAME))
|
2004-11-13 22:26:15 +01:00
|
|
|
continue;
|
2004-11-13 11:56:39 +01:00
|
|
|
uint f_idx= 0;
|
|
|
|
KEY_PART_INFO *key_part= key_info->key_part;
|
|
|
|
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
|
|
|
|
{
|
|
|
|
if (key_part->field)
|
|
|
|
{
|
|
|
|
f_idx++;
|
2005-01-06 12:00:13 +01:00
|
|
|
restore_record(table, s->default_values);
|
2004-12-10 10:07:11 +01:00
|
|
|
store_key_column_usage(table, base_name, file_name,
|
|
|
|
key_info->name,
|
|
|
|
strlen(key_info->name),
|
|
|
|
key_part->field->field_name,
|
|
|
|
strlen(key_part->field->field_name),
|
|
|
|
(longlong) f_idx);
|
2005-03-24 14:32:11 +01:00
|
|
|
if (schema_table_store_record(thd, table))
|
|
|
|
DBUG_RETURN(1);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
show_table->file->get_foreign_key_list(thd, &f_key_list);
|
|
|
|
FOREIGN_KEY_INFO *f_key_info;
|
|
|
|
List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
|
|
|
|
while ((f_key_info= it++))
|
|
|
|
{
|
2005-02-25 15:53:22 +01:00
|
|
|
LEX_STRING *f_info;
|
2005-05-20 14:39:28 +02:00
|
|
|
LEX_STRING *r_info;
|
2004-11-13 11:56:39 +01:00
|
|
|
List_iterator_fast<LEX_STRING> it(f_key_info->foreign_fields),
|
|
|
|
it1(f_key_info->referenced_fields);
|
|
|
|
uint f_idx= 0;
|
|
|
|
while ((f_info= it++))
|
|
|
|
{
|
2005-05-20 14:39:28 +02:00
|
|
|
r_info= it1++;
|
2004-11-13 11:56:39 +01:00
|
|
|
f_idx++;
|
2005-01-06 12:00:13 +01:00
|
|
|
restore_record(table, s->default_values);
|
2004-12-10 10:07:11 +01:00
|
|
|
store_key_column_usage(table, base_name, file_name,
|
|
|
|
f_key_info->forein_id->str,
|
|
|
|
f_key_info->forein_id->length,
|
|
|
|
f_info->str, f_info->length,
|
|
|
|
(longlong) f_idx);
|
2005-09-14 00:41:44 +02:00
|
|
|
table->field[8]->store((longlong) f_idx, TRUE);
|
2004-12-10 10:07:11 +01:00
|
|
|
table->field[8]->set_notnull();
|
2005-05-20 14:39:28 +02:00
|
|
|
table->field[9]->store(f_key_info->referenced_db->str,
|
|
|
|
f_key_info->referenced_db->length,
|
|
|
|
system_charset_info);
|
|
|
|
table->field[9]->set_notnull();
|
|
|
|
table->field[10]->store(f_key_info->referenced_table->str,
|
|
|
|
f_key_info->referenced_table->length,
|
|
|
|
system_charset_info);
|
|
|
|
table->field[10]->set_notnull();
|
|
|
|
table->field[11]->store(r_info->str, r_info->length,
|
|
|
|
system_charset_info);
|
|
|
|
table->field[11]->set_notnull();
|
2005-03-24 14:32:11 +01:00
|
|
|
if (schema_table_store_record(thd, table))
|
|
|
|
DBUG_RETURN(1);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-11-13 22:26:15 +01:00
|
|
|
DBUG_RETURN(res);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-01-10 16:44:04 +01:00
|
|
|
static void collect_partition_expr(List<char> &field_list, String *str)
|
|
|
|
{
|
|
|
|
List_iterator<char> part_it(field_list);
|
|
|
|
ulong no_fields= field_list.elements;
|
|
|
|
const char *field_str;
|
|
|
|
str->length(0);
|
|
|
|
while ((field_str= part_it++))
|
|
|
|
{
|
|
|
|
str->append(field_str);
|
|
|
|
if (--no_fields != 0)
|
|
|
|
str->append(",");
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void store_schema_partitions_record(THD *thd, TABLE *table,
|
|
|
|
partition_element *part_elem,
|
|
|
|
handler *file, uint part_id)
|
|
|
|
{
|
|
|
|
CHARSET_INFO *cs= system_charset_info;
|
|
|
|
PARTITION_INFO stat_info;
|
|
|
|
TIME time;
|
|
|
|
file->get_dynamic_partition_info(&stat_info, part_id);
|
|
|
|
table->field[12]->store((longlong) stat_info.records, TRUE);
|
|
|
|
table->field[13]->store((longlong) stat_info.mean_rec_length, TRUE);
|
|
|
|
table->field[14]->store((longlong) stat_info.data_file_length, TRUE);
|
|
|
|
if (stat_info.max_data_file_length)
|
|
|
|
{
|
|
|
|
table->field[15]->store((longlong) stat_info.max_data_file_length, TRUE);
|
|
|
|
table->field[15]->set_notnull();
|
|
|
|
}
|
|
|
|
table->field[16]->store((longlong) stat_info.index_file_length, TRUE);
|
|
|
|
table->field[17]->store((longlong) stat_info.delete_length, TRUE);
|
|
|
|
if (stat_info.create_time)
|
|
|
|
{
|
|
|
|
thd->variables.time_zone->gmt_sec_to_TIME(&time,
|
|
|
|
stat_info.create_time);
|
|
|
|
table->field[18]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
|
|
|
|
table->field[18]->set_notnull();
|
|
|
|
}
|
|
|
|
if (stat_info.update_time)
|
|
|
|
{
|
|
|
|
thd->variables.time_zone->gmt_sec_to_TIME(&time,
|
|
|
|
stat_info.update_time);
|
|
|
|
table->field[19]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
|
|
|
|
table->field[19]->set_notnull();
|
|
|
|
}
|
|
|
|
if (stat_info.check_time)
|
|
|
|
{
|
|
|
|
thd->variables.time_zone->gmt_sec_to_TIME(&time, stat_info.check_time);
|
|
|
|
table->field[20]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
|
|
|
|
table->field[20]->set_notnull();
|
|
|
|
}
|
|
|
|
if (file->table_flags() & (ulong) HA_HAS_CHECKSUM)
|
|
|
|
{
|
|
|
|
table->field[21]->store((longlong) stat_info.check_sum, TRUE);
|
|
|
|
table->field[21]->set_notnull();
|
|
|
|
}
|
|
|
|
if (part_elem)
|
|
|
|
{
|
|
|
|
if (part_elem->part_comment)
|
|
|
|
table->field[22]->store(part_elem->part_comment,
|
|
|
|
strlen(part_elem->part_comment), cs);
|
|
|
|
else
|
|
|
|
table->field[22]->store(STRING_WITH_LEN("default"), cs);
|
|
|
|
if (part_elem->nodegroup_id != UNDEF_NODEGROUP)
|
|
|
|
table->field[23]->store((longlong) part_elem->nodegroup_id, TRUE);
|
|
|
|
else
|
|
|
|
table->field[23]->store(STRING_WITH_LEN("default"), cs);
|
|
|
|
if (part_elem->tablespace_name)
|
|
|
|
table->field[24]->store(part_elem->tablespace_name,
|
|
|
|
strlen(part_elem->tablespace_name), cs);
|
|
|
|
else
|
|
|
|
table->field[24]->store(STRING_WITH_LEN("default"), cs);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int get_schema_partitions_record(THD *thd, struct st_table_list *tables,
|
|
|
|
TABLE *table, bool res,
|
|
|
|
const char *base_name,
|
|
|
|
const char *file_name)
|
|
|
|
{
|
|
|
|
CHARSET_INFO *cs= system_charset_info;
|
|
|
|
char buff[61];
|
|
|
|
String tmp_res(buff, sizeof(buff), cs);
|
|
|
|
String tmp_str;
|
|
|
|
TIME time;
|
|
|
|
TABLE *show_table= tables->table;
|
2006-02-14 09:52:38 +01:00
|
|
|
handler *file;
|
2006-01-11 12:04:18 +01:00
|
|
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
2006-02-14 09:52:38 +01:00
|
|
|
partition_info *part_info;
|
2006-01-11 12:04:18 +01:00
|
|
|
#endif
|
2006-01-10 16:44:04 +01:00
|
|
|
DBUG_ENTER("get_schema_partitions_record");
|
|
|
|
|
|
|
|
if (res)
|
|
|
|
{
|
2006-02-14 09:52:38 +01:00
|
|
|
if (!tables->view)
|
2006-01-10 16:44:04 +01:00
|
|
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
|
|
thd->net.last_errno, thd->net.last_error);
|
|
|
|
thd->clear_error();
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
2006-02-14 09:52:38 +01:00
|
|
|
file= show_table->file;
|
2006-01-11 12:04:18 +01:00
|
|
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
2006-02-14 09:52:38 +01:00
|
|
|
part_info= show_table->part_info;
|
2006-01-10 16:44:04 +01:00
|
|
|
if (part_info)
|
|
|
|
{
|
|
|
|
partition_element *part_elem;
|
|
|
|
List_iterator<partition_element> part_it(part_info->partitions);
|
|
|
|
uint part_pos= 0, part_id= 0;
|
|
|
|
uint no_parts= part_info->no_parts;
|
|
|
|
handler *part_file;
|
|
|
|
|
|
|
|
restore_record(table, s->default_values);
|
|
|
|
table->field[1]->store(base_name, strlen(base_name), cs);
|
|
|
|
table->field[2]->store(file_name, strlen(file_name), cs);
|
|
|
|
|
|
|
|
|
|
|
|
/* Partition method*/
|
|
|
|
switch (part_info->part_type) {
|
|
|
|
case RANGE_PARTITION:
|
|
|
|
table->field[7]->store(partition_keywords[PKW_RANGE].str,
|
|
|
|
partition_keywords[PKW_RANGE].length, cs);
|
|
|
|
break;
|
|
|
|
case LIST_PARTITION:
|
|
|
|
table->field[7]->store(partition_keywords[PKW_LIST].str,
|
|
|
|
partition_keywords[PKW_LIST].length, cs);
|
|
|
|
break;
|
|
|
|
case HASH_PARTITION:
|
|
|
|
tmp_res.length(0);
|
|
|
|
if (part_info->linear_hash_ind)
|
|
|
|
tmp_res.append(partition_keywords[PKW_LINEAR].str,
|
|
|
|
partition_keywords[PKW_LINEAR].length);
|
|
|
|
if (part_info->list_of_part_fields)
|
|
|
|
tmp_res.append(partition_keywords[PKW_KEY].str,
|
|
|
|
partition_keywords[PKW_KEY].length);
|
|
|
|
else
|
|
|
|
tmp_res.append(partition_keywords[PKW_HASH].str,
|
|
|
|
partition_keywords[PKW_HASH].length);
|
|
|
|
table->field[7]->store(tmp_res.ptr(), tmp_res.length(), cs);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
current_thd->fatal_error();
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
table->field[7]->set_notnull();
|
|
|
|
|
|
|
|
/* Partition expression */
|
|
|
|
if (part_info->part_expr)
|
|
|
|
{
|
|
|
|
table->field[9]->store(part_info->part_func_string,
|
|
|
|
part_info->part_func_len, cs);
|
|
|
|
table->field[9]->set_notnull();
|
|
|
|
}
|
|
|
|
else if (part_info->list_of_part_fields)
|
|
|
|
{
|
|
|
|
collect_partition_expr(part_info->part_field_list, &tmp_str);
|
|
|
|
table->field[9]->store(tmp_str.ptr(), tmp_str.length(), cs);
|
|
|
|
table->field[9]->set_notnull();
|
|
|
|
}
|
|
|
|
|
2006-02-16 17:38:33 +01:00
|
|
|
if (part_info->is_sub_partitioned())
|
2006-01-10 16:44:04 +01:00
|
|
|
{
|
|
|
|
/* Subpartition method */
|
|
|
|
if (part_info->list_of_subpart_fields)
|
|
|
|
table->field[8]->store(partition_keywords[PKW_KEY].str,
|
|
|
|
partition_keywords[PKW_KEY].length, cs);
|
|
|
|
else
|
|
|
|
table->field[8]->store(partition_keywords[PKW_HASH].str,
|
|
|
|
partition_keywords[PKW_HASH].length, cs);
|
|
|
|
table->field[8]->set_notnull();
|
|
|
|
|
|
|
|
/* Subpartition expression */
|
|
|
|
if (part_info->subpart_expr)
|
|
|
|
{
|
|
|
|
table->field[10]->store(part_info->subpart_func_string,
|
|
|
|
part_info->subpart_func_len, cs);
|
|
|
|
table->field[10]->set_notnull();
|
|
|
|
}
|
|
|
|
else if (part_info->list_of_subpart_fields)
|
|
|
|
{
|
|
|
|
collect_partition_expr(part_info->subpart_field_list, &tmp_str);
|
|
|
|
table->field[10]->store(tmp_str.ptr(), tmp_str.length(), cs);
|
|
|
|
table->field[10]->set_notnull();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((part_elem= part_it++))
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
table->field[3]->store(part_elem->partition_name,
|
|
|
|
strlen(part_elem->partition_name), cs);
|
|
|
|
table->field[3]->set_notnull();
|
|
|
|
/* PARTITION_ORDINAL_POSITION */
|
|
|
|
table->field[5]->store((longlong) ++part_pos, TRUE);
|
|
|
|
table->field[5]->set_notnull();
|
|
|
|
|
|
|
|
/* Partition description */
|
|
|
|
if (part_info->part_type == RANGE_PARTITION)
|
|
|
|
{
|
|
|
|
if (part_elem->range_value != LONGLONG_MAX)
|
|
|
|
table->field[11]->store((longlong) part_elem->range_value, FALSE);
|
|
|
|
else
|
|
|
|
table->field[11]->store(partition_keywords[PKW_MAXVALUE].str,
|
|
|
|
partition_keywords[PKW_MAXVALUE].length, cs);
|
|
|
|
table->field[11]->set_notnull();
|
|
|
|
}
|
|
|
|
else if (part_info->part_type == LIST_PARTITION)
|
|
|
|
{
|
|
|
|
List_iterator<longlong> list_val_it(part_elem->list_val_list);
|
|
|
|
longlong *list_value;
|
|
|
|
uint no_items= part_elem->list_val_list.elements;
|
|
|
|
tmp_str.length(0);
|
|
|
|
tmp_res.length(0);
|
|
|
|
while ((list_value= list_val_it++))
|
|
|
|
{
|
|
|
|
tmp_res.set(*list_value, cs);
|
|
|
|
tmp_str.append(tmp_res);
|
|
|
|
if (--no_items != 0)
|
|
|
|
tmp_str.append(",");
|
|
|
|
};
|
|
|
|
table->field[11]->store(tmp_str.ptr(), tmp_str.length(), cs);
|
|
|
|
table->field[11]->set_notnull();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (part_elem->subpartitions.elements)
|
|
|
|
{
|
|
|
|
List_iterator<partition_element> sub_it(part_elem->subpartitions);
|
|
|
|
partition_element *subpart_elem;
|
|
|
|
uint subpart_pos= 0;
|
|
|
|
|
|
|
|
while ((subpart_elem= sub_it++))
|
|
|
|
{
|
|
|
|
table->field[4]->store(subpart_elem->partition_name,
|
|
|
|
strlen(subpart_elem->partition_name), cs);
|
|
|
|
table->field[4]->set_notnull();
|
|
|
|
/* SUBPARTITION_ORDINAL_POSITION */
|
|
|
|
table->field[6]->store((longlong) ++subpart_pos, TRUE);
|
|
|
|
table->field[6]->set_notnull();
|
|
|
|
|
|
|
|
store_schema_partitions_record(thd, table, subpart_elem,
|
|
|
|
file, part_id);
|
|
|
|
part_id++;
|
|
|
|
if(schema_table_store_record(thd, table))
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
store_schema_partitions_record(thd, table, part_elem,
|
|
|
|
file, part_id);
|
|
|
|
part_id++;
|
|
|
|
if(schema_table_store_record(thd, table))
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
else
|
2006-01-11 12:04:18 +01:00
|
|
|
#endif
|
2006-01-10 16:44:04 +01:00
|
|
|
{
|
|
|
|
store_schema_partitions_record(thd, table, 0, file, 0);
|
|
|
|
if(schema_table_store_record(thd, table))
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-01-30 13:15:23 +01:00
|
|
|
static interval_type get_real_interval_type(interval_type i_type)
|
|
|
|
{
|
|
|
|
switch (i_type) {
|
|
|
|
case INTERVAL_YEAR:
|
|
|
|
return INTERVAL_YEAR;
|
|
|
|
|
|
|
|
case INTERVAL_QUARTER:
|
|
|
|
case INTERVAL_YEAR_MONTH:
|
|
|
|
case INTERVAL_MONTH:
|
|
|
|
return INTERVAL_MONTH;
|
|
|
|
|
|
|
|
case INTERVAL_WEEK:
|
|
|
|
case INTERVAL_DAY:
|
|
|
|
return INTERVAL_DAY;
|
|
|
|
|
|
|
|
case INTERVAL_DAY_HOUR:
|
|
|
|
case INTERVAL_HOUR:
|
|
|
|
return INTERVAL_HOUR;
|
|
|
|
|
|
|
|
case INTERVAL_DAY_MINUTE:
|
|
|
|
case INTERVAL_HOUR_MINUTE:
|
|
|
|
case INTERVAL_MINUTE:
|
|
|
|
return INTERVAL_MINUTE;
|
|
|
|
|
|
|
|
case INTERVAL_DAY_SECOND:
|
|
|
|
case INTERVAL_HOUR_SECOND:
|
|
|
|
case INTERVAL_MINUTE_SECOND:
|
|
|
|
case INTERVAL_SECOND:
|
|
|
|
return INTERVAL_SECOND;
|
|
|
|
|
|
|
|
case INTERVAL_DAY_MICROSECOND:
|
|
|
|
case INTERVAL_HOUR_MICROSECOND:
|
|
|
|
case INTERVAL_MINUTE_MICROSECOND:
|
|
|
|
case INTERVAL_SECOND_MICROSECOND:
|
|
|
|
case INTERVAL_MICROSECOND:
|
|
|
|
return INTERVAL_MICROSECOND;
|
|
|
|
}
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
return INTERVAL_SECOND;
|
|
|
|
}
|
|
|
|
|
2006-02-16 13:11:16 +01:00
|
|
|
extern LEX_STRING interval_type_to_name[];
|
2006-01-30 13:15:23 +01:00
|
|
|
|
|
|
|
static int
|
|
|
|
fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
|
|
|
|
{
|
|
|
|
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
|
|
|
|
CHARSET_INFO *scs= system_charset_info;
|
|
|
|
TIME time;
|
|
|
|
event_timed et;
|
|
|
|
DBUG_ENTER("fill_events_copy_to_schema_tab");
|
|
|
|
|
|
|
|
restore_record(sch_table, s->default_values);
|
|
|
|
|
|
|
|
if (et.load_from_row(thd->mem_root, event_table))
|
|
|
|
{
|
2006-02-20 16:06:05 +01:00
|
|
|
my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0));
|
2006-01-30 13:15:23 +01:00
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(!wild || !wild[0] || !wild_compare(et.name.str, wild, 0)))
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
|
|
|
|
//->field[0] is EVENT_CATALOG and is by default NULL
|
|
|
|
|
|
|
|
sch_table->field[1]->store(et.dbname.str, et.dbname.length, scs);
|
|
|
|
sch_table->field[2]->store(et.name.str, et.name.length, scs);
|
|
|
|
sch_table->field[3]->store(et.definer.str, et.definer.length, scs);
|
|
|
|
sch_table->field[4]->store(et.body.str, et.body.length, scs);
|
|
|
|
|
2006-02-20 23:52:22 +01:00
|
|
|
// [9] is SQL_MODE
|
|
|
|
{
|
2006-02-21 02:40:23 +01:00
|
|
|
byte *sql_mode_str;
|
2006-02-20 23:52:22 +01:00
|
|
|
ulong sql_mode_len=0;
|
|
|
|
sql_mode_str=
|
|
|
|
sys_var_thd_sql_mode::symbolic_mode_representation(thd, et.sql_mode,
|
|
|
|
&sql_mode_len);
|
|
|
|
sch_table->field[9]->store((const char*)sql_mode_str, sql_mode_len, scs);
|
|
|
|
}
|
|
|
|
|
2006-01-30 13:15:23 +01:00
|
|
|
if (et.expression)
|
|
|
|
{
|
2006-02-14 16:20:48 +01:00
|
|
|
String show_str;
|
2006-01-30 13:15:23 +01:00
|
|
|
//type
|
|
|
|
sch_table->field[5]->store(STRING_WITH_LEN("RECURRING"), scs);
|
|
|
|
//execute_at
|
|
|
|
sch_table->field[6]->set_null();
|
|
|
|
//interval_value
|
|
|
|
//interval_type
|
2006-02-14 16:20:48 +01:00
|
|
|
if (event_reconstruct_interval_expression(&show_str, et.interval,
|
|
|
|
et.expression))
|
|
|
|
DBUG_RETURN(1);
|
2006-02-20 16:06:05 +01:00
|
|
|
|
2006-02-16 13:11:16 +01:00
|
|
|
sch_table->field[7]->set_notnull();
|
|
|
|
sch_table->field[7]->store(show_str.c_ptr(), show_str.length(), scs);
|
|
|
|
|
|
|
|
LEX_STRING *ival= &interval_type_to_name[et.interval];
|
2006-01-30 13:15:23 +01:00
|
|
|
sch_table->field[8]->set_notnull();
|
2006-02-16 13:11:16 +01:00
|
|
|
sch_table->field[8]->store(ival->str, ival->length, scs);
|
2006-01-30 13:15:23 +01:00
|
|
|
//starts & ends
|
|
|
|
sch_table->field[10]->set_notnull();
|
|
|
|
sch_table->field[10]->store_time(&et.starts, MYSQL_TIMESTAMP_DATETIME);
|
|
|
|
sch_table->field[11]->set_notnull();
|
|
|
|
sch_table->field[11]->store_time(&et.ends, MYSQL_TIMESTAMP_DATETIME);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//type
|
|
|
|
sch_table->field[5]->store(STRING_WITH_LEN("ONE TIME"), scs);
|
|
|
|
//execute_at
|
|
|
|
sch_table->field[6]->set_notnull();
|
|
|
|
sch_table->field[6]->store_time(&et.execute_at, MYSQL_TIMESTAMP_DATETIME);
|
|
|
|
//interval
|
|
|
|
sch_table->field[7]->set_null();
|
|
|
|
//interval_type
|
|
|
|
sch_table->field[8]->set_null();
|
|
|
|
//starts & ends
|
|
|
|
sch_table->field[10]->set_null();
|
|
|
|
sch_table->field[11]->set_null();
|
|
|
|
}
|
|
|
|
|
|
|
|
//status
|
|
|
|
if (et.status == MYSQL_EVENT_ENABLED)
|
|
|
|
sch_table->field[12]->store(STRING_WITH_LEN("ENABLED"), scs);
|
|
|
|
else
|
|
|
|
sch_table->field[12]->store(STRING_WITH_LEN("DISABLED"), scs);
|
|
|
|
|
|
|
|
//on_completion
|
|
|
|
if (et.on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
|
|
|
|
sch_table->field[13]->store(STRING_WITH_LEN("NOT PRESERVE"), scs);
|
|
|
|
else
|
|
|
|
sch_table->field[13]->store(STRING_WITH_LEN("PRESERVE"), scs);
|
|
|
|
|
|
|
|
int not_used=0;
|
|
|
|
number_to_datetime(et.created, &time, 0, ¬_used);
|
|
|
|
DBUG_ASSERT(not_used==0);
|
|
|
|
sch_table->field[14]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
|
|
|
|
|
|
|
|
number_to_datetime(et.modified, &time, 0, ¬_used);
|
|
|
|
DBUG_ASSERT(not_used==0);
|
|
|
|
sch_table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
|
|
|
|
|
|
|
|
if (et.last_executed.year)
|
|
|
|
sch_table->field[16]->store_time(&et.last_executed,MYSQL_TIMESTAMP_DATETIME);
|
|
|
|
else
|
|
|
|
sch_table->field[16]->set_null();
|
|
|
|
|
|
|
|
sch_table->field[17]->store(et.comment.str, et.comment.length, scs);
|
|
|
|
|
|
|
|
if (schema_table_store_record(thd, sch_table))
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int fill_schema_events(THD *thd, TABLE_LIST *tables, COND *cond)
|
|
|
|
{
|
|
|
|
TABLE *table= tables->table;
|
|
|
|
CHARSET_INFO *scs= system_charset_info;
|
|
|
|
TABLE *event_table= NULL;
|
|
|
|
Open_tables_state backup;
|
|
|
|
int ret=0;
|
|
|
|
bool verbose= false;
|
|
|
|
char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
|
|
|
|
bool use_prefix_scanning= true;
|
|
|
|
uint key_len= 0;
|
|
|
|
byte *key_buf= NULL;
|
|
|
|
LINT_INIT(key_buf);
|
|
|
|
|
|
|
|
DBUG_ENTER("fill_schema_events");
|
|
|
|
|
|
|
|
strxmov(definer, thd->security_ctx->priv_user,"@",thd->security_ctx->priv_host,
|
|
|
|
NullS);
|
|
|
|
|
|
|
|
DBUG_PRINT("info",("db=%s current_user=%s", thd->lex->select_lex.db, definer));
|
|
|
|
|
|
|
|
thd->reset_n_backup_open_tables_state(&backup);
|
|
|
|
|
|
|
|
if ((ret= evex_open_event_table(thd, TL_READ, &event_table)))
|
|
|
|
{
|
|
|
|
sql_print_error("Table mysql.event is damaged.");
|
|
|
|
ret= 1;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
event_table->file->ha_index_init(0, 1);
|
|
|
|
|
|
|
|
/*
|
|
|
|
see others' events only if you have PROCESS_ACL !!
|
|
|
|
thd->lex->verbose is set either if SHOW FULL EVENTS or
|
|
|
|
in case of SELECT FROM I_S.EVENTS
|
|
|
|
*/
|
|
|
|
verbose= (thd->lex->verbose
|
|
|
|
&& (thd->security_ctx->master_access & PROCESS_ACL));
|
|
|
|
|
|
|
|
if (verbose && thd->security_ctx->user)
|
|
|
|
{
|
|
|
|
ret= event_table->file->index_first(event_table->record[0]);
|
|
|
|
use_prefix_scanning= false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
event_table->field[EVEX_FIELD_DEFINER]->store(definer, strlen(definer), scs);
|
|
|
|
key_len= event_table->key_info->key_part[0].store_length;
|
|
|
|
|
|
|
|
if (thd->lex->select_lex.db)
|
|
|
|
{
|
|
|
|
event_table->field[EVEX_FIELD_DB]->
|
|
|
|
store(thd->lex->select_lex.db, strlen(thd->lex->select_lex.db), scs);
|
|
|
|
key_len+= event_table->key_info->key_part[1].store_length;
|
|
|
|
}
|
2006-02-07 16:30:26 +01:00
|
|
|
if (!(key_buf= (byte *)alloc_root(thd->mem_root, key_len)))
|
2006-01-30 13:15:23 +01:00
|
|
|
{
|
|
|
|
ret= 1;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
key_copy(key_buf, event_table->record[0], event_table->key_info, key_len);
|
|
|
|
ret= event_table->file->index_read(event_table->record[0], key_buf, key_len,
|
|
|
|
HA_READ_PREFIX);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ret= (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND) ? 0 : 1;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!ret)
|
|
|
|
{
|
|
|
|
if ((ret= fill_events_copy_to_schema_table(thd, table, event_table)))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (use_prefix_scanning)
|
|
|
|
ret= event_table->file->
|
|
|
|
index_next_same(event_table->record[0], key_buf, key_len);
|
|
|
|
else
|
|
|
|
ret= event_table->file->index_next(event_table->record[0]);
|
|
|
|
}
|
|
|
|
// ret is guaranteed to be != 0
|
|
|
|
ret= (ret != HA_ERR_END_OF_FILE);
|
|
|
|
err:
|
|
|
|
if (event_table)
|
|
|
|
{
|
|
|
|
event_table->file->ha_index_end();
|
|
|
|
close_thread_tables(thd);
|
|
|
|
}
|
|
|
|
|
|
|
|
thd->restore_backup_open_tables_state(&backup);
|
|
|
|
DBUG_RETURN(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-12-30 13:20:40 +01:00
|
|
|
int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("fill_open_tables");
|
|
|
|
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
|
|
|
|
TABLE *table= tables->table;
|
|
|
|
CHARSET_INFO *cs= system_charset_info;
|
|
|
|
OPEN_TABLE_LIST *open_list;
|
2005-08-16 11:18:35 +02:00
|
|
|
if (!(open_list=list_open_tables(thd,thd->lex->select_lex.db, wild))
|
|
|
|
&& thd->is_fatal_error)
|
2004-12-30 13:20:40 +01:00
|
|
|
DBUG_RETURN(1);
|
|
|
|
|
|
|
|
for (; open_list ; open_list=open_list->next)
|
|
|
|
{
|
2005-01-06 12:00:13 +01:00
|
|
|
restore_record(table, s->default_values);
|
2004-12-30 13:20:40 +01:00
|
|
|
table->field[0]->store(open_list->db, strlen(open_list->db), cs);
|
|
|
|
table->field[1]->store(open_list->table, strlen(open_list->table), cs);
|
2005-09-14 00:41:44 +02:00
|
|
|
table->field[2]->store((longlong) open_list->in_use, TRUE);
|
|
|
|
table->field[3]->store((longlong) open_list->locked, TRUE);
|
2005-03-24 14:32:11 +01:00
|
|
|
if (schema_table_store_record(thd, table))
|
|
|
|
DBUG_RETURN(1);
|
2004-12-30 13:20:40 +01:00
|
|
|
}
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("fill_variables");
|
2005-01-18 15:37:45 +01:00
|
|
|
int res= 0;
|
2004-12-30 13:20:40 +01:00
|
|
|
LEX *lex= thd->lex;
|
|
|
|
const char *wild= lex->wild ? lex->wild->ptr() : NullS;
|
2005-01-18 15:37:45 +01:00
|
|
|
pthread_mutex_lock(&LOCK_global_system_variables);
|
2006-01-07 14:41:57 +01:00
|
|
|
res= show_status_array(thd, wild, init_vars,
|
2005-01-18 15:37:45 +01:00
|
|
|
lex->option_type, 0, "", tables->table);
|
|
|
|
pthread_mutex_unlock(&LOCK_global_system_variables);
|
2004-12-30 13:20:40 +01:00
|
|
|
DBUG_RETURN(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("fill_status");
|
|
|
|
LEX *lex= thd->lex;
|
|
|
|
const char *wild= lex->wild ? lex->wild->ptr() : NullS;
|
|
|
|
int res= 0;
|
|
|
|
STATUS_VAR tmp;
|
2005-01-18 15:37:45 +01:00
|
|
|
pthread_mutex_lock(&LOCK_status);
|
2004-12-30 13:20:40 +01:00
|
|
|
if (lex->option_type == OPT_GLOBAL)
|
|
|
|
calc_sum_of_all_status(&tmp);
|
2006-01-07 14:41:57 +01:00
|
|
|
res= show_status_array(thd, wild,
|
|
|
|
(SHOW_VAR *)all_status_vars.buffer,
|
|
|
|
OPT_GLOBAL,
|
|
|
|
(lex->option_type == OPT_GLOBAL ?
|
2005-01-18 15:37:45 +01:00
|
|
|
&tmp: &thd->status_var), "",tables->table);
|
|
|
|
pthread_mutex_unlock(&LOCK_status);
|
2004-12-30 13:20:40 +01:00
|
|
|
DBUG_RETURN(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
/*
|
|
|
|
Find schema_tables elment by name
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
find_schema_table()
|
|
|
|
thd thread handler
|
|
|
|
table_name table name
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
0 table not found
|
|
|
|
# pointer to 'shema_tables' element
|
|
|
|
*/
|
|
|
|
|
|
|
|
ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name)
|
|
|
|
{
|
|
|
|
ST_SCHEMA_TABLE *schema_table= schema_tables;
|
2005-08-20 10:00:00 +02:00
|
|
|
for (; schema_table->table_name; schema_table++)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
if (!my_strcasecmp(system_charset_info,
|
|
|
|
schema_table->table_name,
|
|
|
|
table_name))
|
|
|
|
return schema_table;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx)
|
|
|
|
{
|
|
|
|
return &schema_tables[schema_table_idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Create information_schema table using schema_table data
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
create_schema_table()
|
|
|
|
thd thread handler
|
|
|
|
schema_table pointer to 'shema_tables' element
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
# Pointer to created table
|
|
|
|
0 Can't create table
|
|
|
|
*/
|
|
|
|
|
2004-11-24 17:32:10 +01:00
|
|
|
TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
int field_count= 0;
|
|
|
|
Item *item;
|
|
|
|
TABLE *table;
|
|
|
|
List<Item> field_list;
|
2004-11-24 17:32:10 +01:00
|
|
|
ST_SCHEMA_TABLE *schema_table= table_list->schema_table;
|
2004-11-13 11:56:39 +01:00
|
|
|
ST_FIELD_INFO *fields_info= schema_table->fields_info;
|
2004-11-18 10:16:06 +01:00
|
|
|
CHARSET_INFO *cs= system_charset_info;
|
2004-11-13 11:56:39 +01:00
|
|
|
DBUG_ENTER("create_schema_table");
|
|
|
|
|
2005-08-20 10:00:00 +02:00
|
|
|
for (; fields_info->field_name; fields_info++)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
switch (fields_info->field_type) {
|
|
|
|
case MYSQL_TYPE_LONG:
|
|
|
|
if (!(item= new Item_int(fields_info->field_name,
|
|
|
|
fields_info->value,
|
|
|
|
fields_info->field_length)))
|
|
|
|
{
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MYSQL_TYPE_TIMESTAMP:
|
|
|
|
if (!(item=new Item_datetime(fields_info->field_name)))
|
|
|
|
{
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2004-12-06 09:55:57 +01:00
|
|
|
/* this should be changed when Item_empty_string is fixed(in 4.1) */
|
|
|
|
if (!(item= new Item_empty_string("", 0, cs)))
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
2004-12-06 09:55:57 +01:00
|
|
|
item->max_length= fields_info->field_length * cs->mbmaxlen;
|
2004-11-18 10:16:06 +01:00
|
|
|
item->set_name(fields_info->field_name,
|
|
|
|
strlen(fields_info->field_name), cs);
|
2004-11-13 11:56:39 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
field_list.push_back(item);
|
|
|
|
item->maybe_null= fields_info->maybe_null;
|
|
|
|
field_count++;
|
|
|
|
}
|
|
|
|
TMP_TABLE_PARAM *tmp_table_param =
|
|
|
|
(TMP_TABLE_PARAM*) (thd->calloc(sizeof(TMP_TABLE_PARAM)));
|
|
|
|
tmp_table_param->init();
|
2004-11-18 10:16:06 +01:00
|
|
|
tmp_table_param->table_charset= cs;
|
2004-11-13 11:56:39 +01:00
|
|
|
tmp_table_param->field_count= field_count;
|
2005-02-23 13:15:36 +01:00
|
|
|
tmp_table_param->schema_table= 1;
|
2004-11-13 11:56:39 +01:00
|
|
|
SELECT_LEX *select_lex= thd->lex->current_select;
|
|
|
|
if (!(table= create_tmp_table(thd, tmp_table_param,
|
|
|
|
field_list, (ORDER*) 0, 0, 0,
|
|
|
|
(select_lex->options | thd->options |
|
|
|
|
TMP_TABLE_ALL_COLUMNS),
|
2004-11-26 16:26:52 +01:00
|
|
|
HA_POS_ERROR, table_list->alias)))
|
2004-11-13 11:56:39 +01:00
|
|
|
DBUG_RETURN(0);
|
2005-03-24 14:32:11 +01:00
|
|
|
table_list->schema_table_param= tmp_table_param;
|
2004-11-13 11:56:39 +01:00
|
|
|
DBUG_RETURN(table);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
For old SHOW compatibility. It is used when
|
|
|
|
old SHOW doesn't have generated column names
|
|
|
|
Make list of fields for SHOW
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
make_old_format()
|
|
|
|
thd thread handler
|
|
|
|
schema_table pointer to 'schema_tables' element
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
-1 errror
|
|
|
|
0 success
|
|
|
|
*/
|
|
|
|
|
|
|
|
int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
|
|
|
{
|
|
|
|
ST_FIELD_INFO *field_info= schema_table->fields_info;
|
2005-07-01 06:05:42 +02:00
|
|
|
Name_resolution_context *context= &thd->lex->select_lex.context;
|
2005-08-20 10:00:00 +02:00
|
|
|
for (; field_info->field_name; field_info++)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
if (field_info->old_name)
|
|
|
|
{
|
2005-07-01 06:05:42 +02:00
|
|
|
Item_field *field= new Item_field(context,
|
|
|
|
NullS, NullS, field_info->field_name);
|
2004-11-13 11:56:39 +01:00
|
|
|
if (field)
|
|
|
|
{
|
|
|
|
field->set_name(field_info->old_name,
|
|
|
|
strlen(field_info->old_name),
|
|
|
|
system_charset_info);
|
|
|
|
if (add_item_to_list(thd, field))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
|
|
|
{
|
|
|
|
char tmp[128];
|
|
|
|
LEX *lex= thd->lex;
|
|
|
|
SELECT_LEX *sel= lex->current_select;
|
2005-07-01 06:05:42 +02:00
|
|
|
Name_resolution_context *context= &sel->context;
|
2004-11-13 11:56:39 +01:00
|
|
|
|
|
|
|
if (!sel->item_list.elements)
|
|
|
|
{
|
|
|
|
ST_FIELD_INFO *field_info= &schema_table->fields_info[1];
|
|
|
|
String buffer(tmp,sizeof(tmp), system_charset_info);
|
2005-07-01 06:05:42 +02:00
|
|
|
Item_field *field= new Item_field(context,
|
|
|
|
NullS, NullS, field_info->field_name);
|
2004-11-13 11:56:39 +01:00
|
|
|
if (!field || add_item_to_list(thd, field))
|
|
|
|
return 1;
|
|
|
|
buffer.length(0);
|
|
|
|
buffer.append(field_info->old_name);
|
|
|
|
if (lex->wild && lex->wild->ptr())
|
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
buffer.append(STRING_WITH_LEN(" ("));
|
2004-11-13 11:56:39 +01:00
|
|
|
buffer.append(lex->wild->ptr());
|
2005-11-20 19:47:07 +01:00
|
|
|
buffer.append(')');
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
|
|
|
{
|
|
|
|
char tmp[128];
|
|
|
|
String buffer(tmp,sizeof(tmp), thd->charset());
|
|
|
|
LEX *lex= thd->lex;
|
2005-07-01 06:05:42 +02:00
|
|
|
Name_resolution_context *context= &lex->select_lex.context;
|
2004-11-13 11:56:39 +01:00
|
|
|
|
|
|
|
ST_FIELD_INFO *field_info= &schema_table->fields_info[2];
|
|
|
|
buffer.length(0);
|
|
|
|
buffer.append(field_info->old_name);
|
|
|
|
buffer.append(lex->select_lex.db);
|
|
|
|
if (lex->wild && lex->wild->ptr())
|
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
buffer.append(STRING_WITH_LEN(" ("));
|
2004-11-13 11:56:39 +01:00
|
|
|
buffer.append(lex->wild->ptr());
|
2005-11-20 19:47:07 +01:00
|
|
|
buffer.append(')');
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
2005-07-01 06:05:42 +02:00
|
|
|
Item_field *field= new Item_field(context,
|
|
|
|
NullS, NullS, field_info->field_name);
|
2004-11-13 11:56:39 +01:00
|
|
|
if (add_item_to_list(thd, field))
|
|
|
|
return 1;
|
|
|
|
field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
|
|
|
|
if (thd->lex->verbose)
|
|
|
|
{
|
|
|
|
field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
|
|
|
|
field_info= &schema_table->fields_info[3];
|
2005-07-01 06:05:42 +02:00
|
|
|
field= new Item_field(context, NullS, NullS, field_info->field_name);
|
2004-11-13 11:56:39 +01:00
|
|
|
if (add_item_to_list(thd, field))
|
|
|
|
return 1;
|
|
|
|
field->set_name(field_info->old_name, strlen(field_info->old_name),
|
|
|
|
system_charset_info);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
|
|
|
{
|
2004-11-19 23:17:18 +01:00
|
|
|
int fields_arr[]= {3, 14, 13, 6, 15, 5, 16, 17, 18, -1};
|
|
|
|
int *field_num= fields_arr;
|
|
|
|
ST_FIELD_INFO *field_info;
|
2005-07-01 06:05:42 +02:00
|
|
|
Name_resolution_context *context= &thd->lex->select_lex.context;
|
|
|
|
|
2004-11-19 23:17:18 +01:00
|
|
|
for (; *field_num >= 0; field_num++)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
2004-11-19 23:17:18 +01:00
|
|
|
field_info= &schema_table->fields_info[*field_num];
|
|
|
|
if (!thd->lex->verbose && (*field_num == 13 ||
|
|
|
|
*field_num == 17 ||
|
|
|
|
*field_num == 18))
|
|
|
|
continue;
|
2005-07-01 06:05:42 +02:00
|
|
|
Item_field *field= new Item_field(context,
|
|
|
|
NullS, NullS, field_info->field_name);
|
2004-11-19 23:17:18 +01:00
|
|
|
if (field)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
2004-11-19 23:17:18 +01:00
|
|
|
field->set_name(field_info->old_name,
|
|
|
|
strlen(field_info->old_name),
|
|
|
|
system_charset_info);
|
|
|
|
if (add_item_to_list(thd, field))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-12-14 14:18:59 +01:00
|
|
|
int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
|
|
|
{
|
|
|
|
int fields_arr[]= {0, 2, 1, 3, -1};
|
|
|
|
int *field_num= fields_arr;
|
|
|
|
ST_FIELD_INFO *field_info;
|
2005-07-01 06:05:42 +02:00
|
|
|
Name_resolution_context *context= &thd->lex->select_lex.context;
|
|
|
|
|
2004-12-14 14:18:59 +01:00
|
|
|
for (; *field_num >= 0; field_num++)
|
|
|
|
{
|
|
|
|
field_info= &schema_table->fields_info[*field_num];
|
2005-07-01 06:05:42 +02:00
|
|
|
Item_field *field= new Item_field(context,
|
|
|
|
NullS, NullS, field_info->field_name);
|
2004-12-14 14:18:59 +01:00
|
|
|
if (field)
|
|
|
|
{
|
|
|
|
field->set_name(field_info->old_name,
|
|
|
|
strlen(field_info->old_name),
|
|
|
|
system_charset_info);
|
|
|
|
if (add_item_to_list(thd, field))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-19 23:17:18 +01:00
|
|
|
int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
|
|
|
{
|
|
|
|
int fields_arr[]= {2, 3, 4, 19, 16, 15, 14, 18, -1};
|
|
|
|
int *field_num= fields_arr;
|
|
|
|
ST_FIELD_INFO *field_info;
|
2005-07-01 06:05:42 +02:00
|
|
|
Name_resolution_context *context= &thd->lex->select_lex.context;
|
|
|
|
|
2004-11-19 23:17:18 +01:00
|
|
|
for (; *field_num >= 0; field_num++)
|
|
|
|
{
|
|
|
|
field_info= &schema_table->fields_info[*field_num];
|
2005-07-01 06:05:42 +02:00
|
|
|
Item_field *field= new Item_field(context,
|
|
|
|
NullS, NullS, field_info->field_name);
|
2004-11-19 23:17:18 +01:00
|
|
|
if (field)
|
|
|
|
{
|
|
|
|
field->set_name(field_info->old_name,
|
|
|
|
strlen(field_info->old_name),
|
|
|
|
system_charset_info);
|
|
|
|
if (add_item_to_list(thd, field))
|
|
|
|
return 1;
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Create information_schema table
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
mysql_schema_table()
|
|
|
|
thd thread handler
|
|
|
|
lex pointer to LEX
|
|
|
|
table_list pointer to table_list
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
0 success
|
|
|
|
1 error
|
|
|
|
*/
|
|
|
|
|
|
|
|
int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
|
|
|
|
{
|
|
|
|
TABLE *table;
|
|
|
|
DBUG_ENTER("mysql_schema_table");
|
2004-11-24 17:32:10 +01:00
|
|
|
if (!(table= table_list->schema_table->create_table(thd, table_list)))
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
2005-08-08 21:59:04 +02:00
|
|
|
table->s->tmp_table= SYSTEM_TMP_TABLE;
|
2004-11-13 11:56:39 +01:00
|
|
|
table->grant.privilege= SELECT_ACL;
|
2005-01-27 11:16:51 +01:00
|
|
|
/*
|
|
|
|
This test is necessary to make
|
|
|
|
case insensitive file systems +
|
|
|
|
upper case table names(information schema tables) +
|
|
|
|
views
|
|
|
|
working correctly
|
|
|
|
*/
|
2005-01-28 17:08:27 +01:00
|
|
|
if (table_list->schema_table_name)
|
|
|
|
table->alias_name_used= my_strcasecmp(table_alias_charset,
|
|
|
|
table_list->schema_table_name,
|
|
|
|
table_list->alias);
|
2005-11-23 21:45:02 +01:00
|
|
|
table_list->table_name= table->s->table_name.str;
|
|
|
|
table_list->table_name_length= table->s->table_name.length;
|
2004-11-13 11:56:39 +01:00
|
|
|
table_list->table= table;
|
|
|
|
table->next= thd->derived_tables;
|
|
|
|
thd->derived_tables= table;
|
|
|
|
table_list->select_lex->options |= OPTION_SCHEMA_TABLE;
|
2004-12-30 13:20:40 +01:00
|
|
|
lex->safe_to_cache_query= 0;
|
2005-01-24 16:44:54 +01:00
|
|
|
|
|
|
|
if (table_list->schema_table_reformed) // show command
|
|
|
|
{
|
|
|
|
SELECT_LEX *sel= lex->current_select;
|
|
|
|
Item *item;
|
2005-07-28 15:10:14 +02:00
|
|
|
Field_translator *transl, *org_transl;
|
2005-01-24 16:44:54 +01:00
|
|
|
|
|
|
|
if (table_list->field_translation)
|
|
|
|
{
|
2005-07-01 06:05:42 +02:00
|
|
|
Field_translator *end= table_list->field_translation_end;
|
2005-01-24 16:44:54 +01:00
|
|
|
for (transl= table_list->field_translation; transl < end; transl++)
|
|
|
|
{
|
|
|
|
if (!transl->item->fixed &&
|
2005-07-01 06:05:42 +02:00
|
|
|
transl->item->fix_fields(thd, &transl->item))
|
2005-01-24 16:44:54 +01:00
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
List_iterator_fast<Item> it(sel->item_list);
|
|
|
|
if (!(transl=
|
2005-09-02 15:21:19 +02:00
|
|
|
(Field_translator*)(thd->stmt_arena->
|
2005-01-24 16:44:54 +01:00
|
|
|
alloc(sel->item_list.elements *
|
|
|
|
sizeof(Field_translator)))))
|
|
|
|
{
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
2005-07-28 15:10:14 +02:00
|
|
|
for (org_transl= transl; (item= it++); transl++)
|
2005-01-24 16:44:54 +01:00
|
|
|
{
|
2005-07-28 15:10:14 +02:00
|
|
|
transl->item= item;
|
|
|
|
transl->name= item->name;
|
|
|
|
if (!item->fixed && item->fix_fields(thd, &transl->item))
|
|
|
|
{
|
2005-01-24 16:44:54 +01:00
|
|
|
DBUG_RETURN(1);
|
2005-07-28 15:10:14 +02:00
|
|
|
}
|
2005-01-24 16:44:54 +01:00
|
|
|
}
|
2005-07-28 15:10:14 +02:00
|
|
|
table_list->field_translation= org_transl;
|
|
|
|
table_list->field_translation_end= transl;
|
2005-01-24 16:44:54 +01:00
|
|
|
}
|
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Generate select from information_schema table
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
make_schema_select()
|
|
|
|
thd thread handler
|
|
|
|
sel pointer to SELECT_LEX
|
|
|
|
schema_table_idx index of 'schema_tables' element
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
0 success
|
|
|
|
1 error
|
|
|
|
*/
|
|
|
|
|
|
|
|
int make_schema_select(THD *thd, SELECT_LEX *sel,
|
|
|
|
enum enum_schema_tables schema_table_idx)
|
|
|
|
{
|
|
|
|
ST_SCHEMA_TABLE *schema_table= get_schema_table(schema_table_idx);
|
|
|
|
LEX_STRING db, table;
|
|
|
|
DBUG_ENTER("mysql_schema_select");
|
2005-12-22 10:07:47 +01:00
|
|
|
DBUG_PRINT("enter", ("mysql_schema_select: %s", schema_table->table_name));
|
2005-07-01 06:05:42 +02:00
|
|
|
/*
|
2004-11-13 11:56:39 +01:00
|
|
|
We have to make non const db_name & table_name
|
|
|
|
because of lower_case_table_names
|
|
|
|
*/
|
|
|
|
make_lex_string(thd, &db, information_schema_name.str,
|
|
|
|
information_schema_name.length, 0);
|
|
|
|
make_lex_string(thd, &table, schema_table->table_name,
|
|
|
|
strlen(schema_table->table_name), 0);
|
2005-07-01 06:05:42 +02:00
|
|
|
if (schema_table->old_format(thd, schema_table) || /* Handle old syntax */
|
2004-11-13 11:56:39 +01:00
|
|
|
!sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0),
|
|
|
|
0, 0, TL_READ, (List<String> *) 0,
|
|
|
|
(List<String> *) 0))
|
|
|
|
{
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2004-12-18 04:19:21 +01:00
|
|
|
Fill temporary schema tables before SELECT
|
2004-11-13 11:56:39 +01:00
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
get_schema_tables_result()
|
|
|
|
join join which use schema tables
|
|
|
|
|
|
|
|
RETURN
|
2004-11-13 22:26:15 +01:00
|
|
|
FALSE success
|
|
|
|
TRUE error
|
2004-11-13 11:56:39 +01:00
|
|
|
*/
|
|
|
|
|
2004-11-13 22:26:15 +01:00
|
|
|
bool get_schema_tables_result(JOIN *join)
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
|
|
|
JOIN_TAB *tmp_join_tab= join->join_tab+join->tables;
|
|
|
|
THD *thd= join->thd;
|
2004-11-18 10:16:06 +01:00
|
|
|
LEX *lex= thd->lex;
|
|
|
|
bool result= 0;
|
2005-02-24 22:33:42 +01:00
|
|
|
DBUG_ENTER("get_schema_tables_result");
|
|
|
|
|
|
|
|
thd->no_warnings_for_error= 1;
|
2004-11-13 11:56:39 +01:00
|
|
|
for (JOIN_TAB *tab= join->join_tab; tab < tmp_join_tab; tab++)
|
|
|
|
{
|
|
|
|
if (!tab->table || !tab->table->pos_in_table_list)
|
|
|
|
break;
|
2004-11-15 17:20:45 +01:00
|
|
|
|
2004-11-18 10:16:06 +01:00
|
|
|
TABLE_LIST *table_list= tab->table->pos_in_table_list;
|
2004-11-13 22:26:15 +01:00
|
|
|
if (table_list->schema_table && thd->fill_derived_tables())
|
2004-11-13 11:56:39 +01:00
|
|
|
{
|
2006-01-24 13:48:19 +01:00
|
|
|
bool is_subselect= (&lex->unit != lex->current_select->master_unit());
|
|
|
|
/*
|
|
|
|
The schema table is already processed and
|
|
|
|
the statement is not a subselect.
|
|
|
|
So we don't need to handle this table again.
|
|
|
|
*/
|
|
|
|
if (table_list->is_schema_table_processed && !is_subselect)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (is_subselect) // is subselect
|
2004-11-18 10:16:06 +01:00
|
|
|
{
|
|
|
|
table_list->table->file->extra(HA_EXTRA_RESET_STATE);
|
|
|
|
table_list->table->file->delete_all_rows();
|
|
|
|
free_io_cache(table_list->table);
|
|
|
|
filesort_free_buffers(table_list->table);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
table_list->table->file->records= 0;
|
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
if (table_list->schema_table->fill_table(thd, table_list,
|
|
|
|
tab->select_cond))
|
2004-11-18 10:16:06 +01:00
|
|
|
result= 1;
|
2006-01-24 13:48:19 +01:00
|
|
|
table_list->is_schema_table_processed= TRUE;
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
}
|
2005-02-24 22:33:42 +01:00
|
|
|
thd->no_warnings_for_error= 0;
|
2004-11-18 10:16:06 +01:00
|
|
|
DBUG_RETURN(result);
|
2004-11-13 11:56:39 +01:00
|
|
|
}
|
|
|
|
|
2006-01-28 04:16:23 +01:00
|
|
|
struct run_hton_fill_schema_files_args
|
|
|
|
{
|
|
|
|
TABLE_LIST *tables;
|
|
|
|
COND *cond;
|
|
|
|
};
|
|
|
|
|
|
|
|
static my_bool run_hton_fill_schema_files(THD *thd, st_plugin_int *plugin,
|
|
|
|
void *arg)
|
|
|
|
{
|
|
|
|
struct run_hton_fill_schema_files_args *args=
|
|
|
|
(run_hton_fill_schema_files_args *) arg;
|
|
|
|
handlerton *hton= (handlerton *) plugin->plugin->info;
|
|
|
|
if(hton->fill_files_table)
|
|
|
|
hton->fill_files_table(thd, args->tables, args->cond);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int fill_schema_files(THD *thd, TABLE_LIST *tables, COND *cond)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
TABLE *table= tables->table;
|
2006-02-01 14:47:08 +01:00
|
|
|
DBUG_ENTER("fill_schema_files");
|
2006-01-28 04:16:23 +01:00
|
|
|
|
|
|
|
struct run_hton_fill_schema_files_args args;
|
|
|
|
args.tables= tables;
|
|
|
|
args.cond= cond;
|
|
|
|
|
|
|
|
plugin_foreach(thd, run_hton_fill_schema_files,
|
|
|
|
MYSQL_STORAGE_ENGINE_PLUGIN, &args);
|
|
|
|
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
2004-11-13 11:56:39 +01:00
|
|
|
|
|
|
|
ST_FIELD_INFO schema_fields_info[]=
|
|
|
|
{
|
2004-11-18 10:16:06 +01:00
|
|
|
{"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"SCHEMA_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Database"},
|
2004-12-23 11:35:34 +01:00
|
|
|
{"DEFAULT_CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0},
|
2005-05-06 22:14:22 +02:00
|
|
|
{"DEFAULT_COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0},
|
2004-11-19 23:17:18 +01:00
|
|
|
{"SQL_PATH", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
2004-11-18 10:16:06 +01:00
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ST_FIELD_INFO tables_fields_info[]=
|
|
|
|
{
|
2004-11-18 10:16:06 +01:00
|
|
|
{"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"},
|
|
|
|
{"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"ENGINE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Engine"},
|
|
|
|
{"VERSION", 21 , MYSQL_TYPE_LONG, 0, 1, "Version"},
|
|
|
|
{"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format"},
|
2004-11-19 23:17:18 +01:00
|
|
|
{"TABLE_ROWS", 21 , MYSQL_TYPE_LONG, 0, 1, "Rows"},
|
2004-11-18 10:16:06 +01:00
|
|
|
{"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Avg_row_length"},
|
|
|
|
{"DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_length"},
|
|
|
|
{"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Max_data_length"},
|
|
|
|
{"INDEX_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Index_length"},
|
|
|
|
{"DATA_FREE", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_free"},
|
|
|
|
{"AUTO_INCREMENT", 21 , MYSQL_TYPE_LONG, 0, 1, "Auto_increment"},
|
|
|
|
{"CREATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Create_time"},
|
|
|
|
{"UPDATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Update_time"},
|
|
|
|
{"CHECK_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Check_time"},
|
2004-12-24 10:16:47 +01:00
|
|
|
{"TABLE_COLLATION", 64, MYSQL_TYPE_STRING, 0, 1, "Collation"},
|
2004-11-18 10:16:06 +01:00
|
|
|
{"CHECKSUM", 21 , MYSQL_TYPE_LONG, 0, 1, "Checksum"},
|
|
|
|
{"CREATE_OPTIONS", 255, MYSQL_TYPE_STRING, 0, 1, "Create_options"},
|
2004-11-19 23:17:18 +01:00
|
|
|
{"TABLE_COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, "Comment"},
|
2004-11-18 10:16:06 +01:00
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ST_FIELD_INFO columns_fields_info[]=
|
|
|
|
{
|
2004-11-18 10:16:06 +01:00
|
|
|
{"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Field"},
|
|
|
|
{"ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 0, 0},
|
2004-11-19 23:17:18 +01:00
|
|
|
{"COLUMN_DEFAULT", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Default"},
|
|
|
|
{"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null"},
|
2004-11-24 17:32:10 +01:00
|
|
|
{"DATA_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
2005-03-31 10:44:42 +02:00
|
|
|
{"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
|
|
|
|
{"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
|
2004-11-19 23:17:18 +01:00
|
|
|
{"NUMERIC_PRECISION", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
|
|
|
|
{"NUMERIC_SCALE", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
|
2004-12-23 11:35:34 +01:00
|
|
|
{"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 1, "Collation"},
|
2004-11-23 15:41:39 +01:00
|
|
|
{"COLUMN_TYPE", 65535, MYSQL_TYPE_STRING, 0, 0, "Type"},
|
2004-11-19 23:17:18 +01:00
|
|
|
{"COLUMN_KEY", 3, MYSQL_TYPE_STRING, 0, 0, "Key"},
|
2004-11-18 10:16:06 +01:00
|
|
|
{"EXTRA", 20, MYSQL_TYPE_STRING, 0, 0, "Extra"},
|
|
|
|
{"PRIVILEGES", 80, MYSQL_TYPE_STRING, 0, 0, "Privileges"},
|
2004-11-19 23:17:18 +01:00
|
|
|
{"COLUMN_COMMENT", 255, MYSQL_TYPE_STRING, 0, 0, "Comment"},
|
2004-11-18 10:16:06 +01:00
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ST_FIELD_INFO charsets_fields_info[]=
|
|
|
|
{
|
2004-12-23 11:35:34 +01:00
|
|
|
{"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Charset"},
|
|
|
|
{"DEFAULT_COLLATE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Default collation"},
|
2004-12-14 14:18:59 +01:00
|
|
|
{"DESCRIPTION", 60, MYSQL_TYPE_STRING, 0, 0, "Description"},
|
2004-11-19 23:17:18 +01:00
|
|
|
{"MAXLEN", 3 ,MYSQL_TYPE_LONG, 0, 0, "Maxlen"},
|
2004-11-18 10:16:06 +01:00
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ST_FIELD_INFO collation_fields_info[]=
|
|
|
|
{
|
2004-12-23 11:35:34 +01:00
|
|
|
{"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Collation"},
|
|
|
|
{"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Charset"},
|
2004-11-19 23:17:18 +01:00
|
|
|
{"ID", 11, MYSQL_TYPE_LONG, 0, 0, "Id"},
|
2004-12-23 11:35:34 +01:00
|
|
|
{"IS_DEFAULT", 3, MYSQL_TYPE_STRING, 0, 0, "Default"},
|
|
|
|
{"IS_COMPILED", 3, MYSQL_TYPE_STRING, 0, 0, "Compiled"},
|
2004-11-19 23:17:18 +01:00
|
|
|
{"SORTLEN", 3 ,MYSQL_TYPE_LONG, 0, 0, "Sortlen"},
|
2004-11-18 10:16:06 +01:00
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2005-12-22 10:07:47 +01:00
|
|
|
ST_FIELD_INFO engines_fields_info[]=
|
|
|
|
{
|
|
|
|
{"ENGINE", 64, MYSQL_TYPE_STRING, 0, 0, "Engine"},
|
|
|
|
{"SUPPORT", 8, MYSQL_TYPE_STRING, 0, 0, "Support"},
|
|
|
|
{"COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, "Comment"},
|
|
|
|
{"TRANSACTIONS", 3, MYSQL_TYPE_STRING, 0, 0, "Transactions"},
|
|
|
|
{"XA", 3, MYSQL_TYPE_STRING, 0, 0, "XA"},
|
|
|
|
{"SAVEPOINTS", 3 ,MYSQL_TYPE_STRING, 0, 0, "Savepoints"},
|
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2006-01-30 13:15:23 +01:00
|
|
|
ST_FIELD_INFO events_fields_info[]=
|
|
|
|
{
|
|
|
|
{"EVENT_CATALOG", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"EVENT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Db"},
|
|
|
|
{"EVENT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"},
|
|
|
|
{"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer"},
|
|
|
|
{"EVENT_BODY", 65535, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"EVENT_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type"},
|
|
|
|
{"EXECUTE_AT", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Execute at"},
|
2006-02-16 13:11:16 +01:00
|
|
|
{"INTERVAL_VALUE", 256, MYSQL_TYPE_STRING, 0, 1, "Interval value"},
|
2006-01-30 13:15:23 +01:00
|
|
|
{"INTERVAL_FIELD", 18, MYSQL_TYPE_STRING, 0, 1, "Interval field"},
|
2006-02-20 23:52:22 +01:00
|
|
|
{"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, 0},
|
2006-01-30 13:15:23 +01:00
|
|
|
{"STARTS", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Starts"},
|
|
|
|
{"ENDS", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Ends"},
|
|
|
|
{"STATUS", 8, MYSQL_TYPE_STRING, 0, 0, "Status"},
|
|
|
|
{"ON_COMPLETION", 12, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0},
|
|
|
|
{"LAST_ALTERED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0},
|
|
|
|
{"LAST_EXECUTED", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, 0},
|
|
|
|
{"EVENT_COMMENT", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
ST_FIELD_INFO coll_charset_app_fields_info[]=
|
|
|
|
{
|
2004-12-23 11:35:34 +01:00
|
|
|
{"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0},
|
2004-11-18 10:16:06 +01:00
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ST_FIELD_INFO proc_fields_info[]=
|
|
|
|
{
|
2004-11-18 10:16:06 +01:00
|
|
|
{"SPECIFIC_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"ROUTINE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"ROUTINE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Db"},
|
|
|
|
{"ROUTINE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"},
|
|
|
|
{"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type"},
|
2004-12-14 12:55:28 +01:00
|
|
|
{"DTD_IDENTIFIER", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"ROUTINE_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0},
|
2004-11-18 10:16:06 +01:00
|
|
|
{"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0},
|
2004-11-19 23:17:18 +01:00
|
|
|
{"EXTERNAL_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"EXTERNAL_LANGUAGE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
2004-12-14 12:55:28 +01:00
|
|
|
{"PARAMETER_STYLE", 8, MYSQL_TYPE_STRING, 0, 0, 0},
|
2004-11-18 10:16:06 +01:00
|
|
|
{"IS_DETERMINISTIC", 3, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"SQL_DATA_ACCESS", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"SQL_PATH", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, "Security_type"},
|
2004-11-19 23:17:18 +01:00
|
|
|
{"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, "Created"},
|
|
|
|
{"LAST_ALTERED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, "Modified"},
|
2004-11-23 15:41:39 +01:00
|
|
|
{"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, 0},
|
2004-11-18 10:16:06 +01:00
|
|
|
{"ROUTINE_COMMENT", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Comment"},
|
2004-11-19 23:17:18 +01:00
|
|
|
{"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer"},
|
2004-11-18 10:16:06 +01:00
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ST_FIELD_INFO stat_fields_info[]=
|
|
|
|
{
|
2004-11-18 10:16:06 +01:00
|
|
|
{"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table"},
|
|
|
|
{"NON_UNIQUE", 1, MYSQL_TYPE_LONG, 0, 0, "Non_unique"},
|
|
|
|
{"INDEX_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"INDEX_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Key_name"},
|
|
|
|
{"SEQ_IN_INDEX", 2, MYSQL_TYPE_LONG, 0, 0, "Seq_in_index"},
|
|
|
|
{"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Column_name"},
|
|
|
|
{"COLLATION", 1, MYSQL_TYPE_STRING, 0, 1, "Collation"},
|
|
|
|
{"CARDINALITY", 21, MYSQL_TYPE_LONG, 0, 1, "Cardinality"},
|
|
|
|
{"SUB_PART", 3, MYSQL_TYPE_LONG, 0, 1, "Sub_part"},
|
|
|
|
{"PACKED", 10, MYSQL_TYPE_STRING, 0, 1, "Packed"},
|
|
|
|
{"NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null"},
|
|
|
|
{"INDEX_TYPE", 16, MYSQL_TYPE_STRING, 0, 0, "Index_type"},
|
|
|
|
{"COMMENT", 16, MYSQL_TYPE_STRING, 0, 1, "Comment"},
|
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ST_FIELD_INFO view_fields_info[]=
|
|
|
|
{
|
2004-11-18 10:16:06 +01:00
|
|
|
{"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"VIEW_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0},
|
2004-12-14 11:41:32 +01:00
|
|
|
{"CHECK_OPTION", 8, MYSQL_TYPE_STRING, 0, 0, 0},
|
2004-11-18 10:16:06 +01:00
|
|
|
{"IS_UPDATABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
|
2005-09-15 10:56:06 +02:00
|
|
|
{"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, 0},
|
2004-11-18 10:16:06 +01:00
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ST_FIELD_INFO user_privileges_fields_info[]=
|
|
|
|
{
|
2004-11-18 10:16:06 +01:00
|
|
|
{"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ST_FIELD_INFO schema_privileges_fields_info[]=
|
|
|
|
{
|
2004-11-18 10:16:06 +01:00
|
|
|
{"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ST_FIELD_INFO table_privileges_fields_info[]=
|
|
|
|
{
|
2004-11-18 10:16:06 +01:00
|
|
|
{"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ST_FIELD_INFO column_privileges_fields_info[]=
|
|
|
|
{
|
2004-11-18 10:16:06 +01:00
|
|
|
{"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ST_FIELD_INFO table_constraints_fields_info[]=
|
|
|
|
{
|
2004-11-18 10:16:06 +01:00
|
|
|
{"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"CONSTRAINT_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ST_FIELD_INFO key_column_usage_fields_info[]=
|
|
|
|
{
|
2004-11-18 10:16:06 +01:00
|
|
|
{"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
2004-11-19 23:17:18 +01:00
|
|
|
{"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
2004-11-18 10:16:06 +01:00
|
|
|
{"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"ORDINAL_POSITION", 10 ,MYSQL_TYPE_LONG, 0, 0, 0},
|
2004-12-10 10:07:11 +01:00
|
|
|
{"POSITION_IN_UNIQUE_CONSTRAINT", 10 ,MYSQL_TYPE_LONG, 0, 1, 0},
|
2005-05-20 14:39:28 +02:00
|
|
|
{"REFERENCED_TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"REFERENCED_TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"REFERENCED_COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
2004-11-18 10:16:06 +01:00
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ST_FIELD_INFO table_names_fields_info[]=
|
|
|
|
{
|
2004-11-18 10:16:06 +01:00
|
|
|
{"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Tables_in_"},
|
|
|
|
{"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_type"},
|
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2004-12-30 13:20:40 +01:00
|
|
|
ST_FIELD_INFO open_tables_fields_info[]=
|
|
|
|
{
|
|
|
|
{"Database", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Database"},
|
|
|
|
{"Table",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table"},
|
|
|
|
{"In_use", 1, MYSQL_TYPE_LONG, 0, 0, "In_use"},
|
|
|
|
{"Name_locked", 4, MYSQL_TYPE_LONG, 0, 0, "Name_locked"},
|
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2005-07-19 18:06:49 +02:00
|
|
|
ST_FIELD_INFO triggers_fields_info[]=
|
|
|
|
{
|
|
|
|
{"TRIGGER_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"TRIGGER_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TRIGGER_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Trigger"},
|
|
|
|
{"EVENT_MANIPULATION", 6, MYSQL_TYPE_STRING, 0, 0, "Event"},
|
|
|
|
{"EVENT_OBJECT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"EVENT_OBJECT_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"EVENT_OBJECT_TABLE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table"},
|
|
|
|
{"ACTION_ORDER", 4, MYSQL_TYPE_LONG, 0, 0, 0},
|
|
|
|
{"ACTION_CONDITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"ACTION_STATEMENT", 65535, MYSQL_TYPE_STRING, 0, 0, "Statement"},
|
|
|
|
{"ACTION_ORIENTATION", 9, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"ACTION_TIMING", 6, MYSQL_TYPE_STRING, 0, 0, "Timing"},
|
|
|
|
{"ACTION_REFERENCE_OLD_TABLE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"ACTION_REFERENCE_NEW_TABLE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"ACTION_REFERENCE_OLD_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"ACTION_REFERENCE_NEW_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Created"},
|
2005-07-28 21:39:11 +02:00
|
|
|
{"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, "sql_mode"},
|
2005-11-10 20:25:03 +01:00
|
|
|
{"DEFINER", 65535, MYSQL_TYPE_STRING, 0, 0, "Definer"},
|
2005-07-19 18:06:49 +02:00
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2006-01-10 16:44:04 +01:00
|
|
|
ST_FIELD_INFO partitions_fields_info[]=
|
|
|
|
{
|
|
|
|
{"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"PARTITION_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"SUBPARTITION_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"PARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
|
|
|
|
{"SUBPARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
|
|
|
|
{"PARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"SUBPARTITION_METHOD", 5, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"PARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"SUBPARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"PARTITION_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"TABLE_ROWS", 21 , MYSQL_TYPE_LONG, 0, 0, 0},
|
|
|
|
{"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 0, 0},
|
|
|
|
{"DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 0, 0},
|
|
|
|
{"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
|
|
|
|
{"INDEX_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 0, 0},
|
|
|
|
{"DATA_FREE", 21 , MYSQL_TYPE_LONG, 0, 0, 0},
|
|
|
|
{"CREATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, 0},
|
|
|
|
{"UPDATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, 0},
|
|
|
|
{"CHECK_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, 0},
|
|
|
|
{"CHECKSUM", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
|
|
|
|
{"PARTITION_COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"NODEGROUP", 21 , MYSQL_TYPE_LONG, 0, 0, 0},
|
|
|
|
{"TABLESPACE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2004-12-30 13:20:40 +01:00
|
|
|
ST_FIELD_INFO variables_fields_info[]=
|
|
|
|
{
|
|
|
|
{"Variable_name", 80, MYSQL_TYPE_STRING, 0, 0, "Variable_name"},
|
|
|
|
{"Value", 255, MYSQL_TYPE_STRING, 0, 0, "Value"},
|
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2006-02-16 14:45:05 +01:00
|
|
|
ST_FIELD_INFO processlist_fields_info[]=
|
|
|
|
{
|
|
|
|
{"ID", 4, MYSQL_TYPE_LONG, 0, 0, "Id"},
|
|
|
|
{"USER", 16, MYSQL_TYPE_STRING, 0, 0, "User"},
|
|
|
|
{"HOST", LIST_PROCESS_HOST_LEN, MYSQL_TYPE_STRING, 0, 0, "Host"},
|
|
|
|
{"DB", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Db"},
|
|
|
|
{"COMMAND", 16, MYSQL_TYPE_STRING, 0, 0, "Command"},
|
|
|
|
{"TIME", 4, MYSQL_TYPE_LONG, 0, 0, "Time"},
|
|
|
|
{"STATE", 30, MYSQL_TYPE_STRING, 0, 1, "State"},
|
|
|
|
{"INFO", PROCESS_LIST_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info"},
|
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2005-12-21 19:18:40 +01:00
|
|
|
ST_FIELD_INFO plugin_fields_info[]=
|
|
|
|
{
|
|
|
|
{"PLUGIN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"},
|
2005-12-21 21:50:50 +01:00
|
|
|
{"PLUGIN_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0},
|
2005-12-21 19:18:40 +01:00
|
|
|
{"PLUGIN_STATUS", 10, MYSQL_TYPE_STRING, 0, 0, "Status"},
|
2006-01-07 14:41:57 +01:00
|
|
|
{"PLUGIN_TYPE", 80, MYSQL_TYPE_STRING, 0, 0, "Type"},
|
2005-12-21 21:50:50 +01:00
|
|
|
{"PLUGIN_TYPE_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0},
|
2005-12-21 19:18:40 +01:00
|
|
|
{"PLUGIN_LIBRARY", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Library"},
|
2005-12-21 21:50:50 +01:00
|
|
|
{"PLUGIN_LIBRARY_VERSION", 20, MYSQL_TYPE_STRING, 0, 1, 0},
|
2005-12-21 19:18:40 +01:00
|
|
|
{"PLUGIN_AUTHOR", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{"PLUGIN_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0},
|
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
|
|
|
};
|
|
|
|
|
2006-01-28 04:16:23 +01:00
|
|
|
ST_FIELD_INFO files_fields_info[]=
|
|
|
|
{
|
|
|
|
{"FILE_ID", 4, MYSQL_TYPE_LONG, 0, 0, 0},
|
|
|
|
{"FILE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"FILE_TYPE", 20, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLESPACE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_CATALOG", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"LOGFILE_GROUP_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"LOGFILE_GROUP_NUMBER", 4, MYSQL_TYPE_LONG, 0, 0, 0},
|
|
|
|
{"ENGINE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"FULLTEXT_KEYS", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"DELETED_ROWS", 4, MYSQL_TYPE_LONG, 0, 0, 0},
|
|
|
|
{"UPDATE_COUNT", 4, MYSQL_TYPE_LONG, 0, 0, 0},
|
|
|
|
{"FREE_EXTENTS", 4, MYSQL_TYPE_LONG, 0, 0, 0},
|
|
|
|
{"TOTAL_EXTENTS", 4, MYSQL_TYPE_LONG, 0, 0, 0},
|
|
|
|
{"EXTENT_SIZE", 4, MYSQL_TYPE_LONG, 0, 0, 0},
|
|
|
|
{"INITIAL_SIZE", 8, MYSQL_TYPE_LONGLONG, 0, 0, 0},
|
|
|
|
{"MAXIMUM_SIZE", 8, MYSQL_TYPE_LONGLONG, 0, 0, 0},
|
|
|
|
{"AUTOEXTEND_SIZE", 8, MYSQL_TYPE_LONGLONG, 0, 0, 0},
|
|
|
|
{"CREATION_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0},
|
|
|
|
{"LAST_UPDATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0},
|
|
|
|
{"LAST_ACCESS_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0},
|
|
|
|
{"RECOVER_TIME", 4, MYSQL_TYPE_LONG, 0, 0, 0},
|
|
|
|
{"TRANSACTION_COUNTER", 4, MYSQL_TYPE_LONG, 0, 0, 0},
|
|
|
|
{"VERSION", 21 , MYSQL_TYPE_LONG, 0, 1, "Version"},
|
|
|
|
{"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format"},
|
|
|
|
{"TABLE_ROWS", 21 , MYSQL_TYPE_LONG, 0, 1, "Rows"},
|
|
|
|
{"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Avg_row_length"},
|
|
|
|
{"DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_length"},
|
|
|
|
{"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Max_data_length"},
|
|
|
|
{"INDEX_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Index_length"},
|
|
|
|
{"DATA_FREE", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_free"},
|
|
|
|
{"CREATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Create_time"},
|
|
|
|
{"UPDATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Update_time"},
|
|
|
|
{"CHECK_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Check_time"},
|
|
|
|
{"CHECKSUM", 21 , MYSQL_TYPE_LONG, 0, 1, "Checksum"},
|
|
|
|
{"STATUS", 20, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{"EXTRA", 255, MYSQL_TYPE_STRING, 0, 0, 0},
|
|
|
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
|
|
|
};
|
2005-12-21 19:18:40 +01:00
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
/*
|
|
|
|
Description of ST_FIELD_INFO in table.h
|
2005-12-22 10:07:47 +01:00
|
|
|
|
|
|
|
Make sure that the order of schema_tables and enum_schema_tables are the same.
|
|
|
|
|
2004-11-13 11:56:39 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
ST_SCHEMA_TABLE schema_tables[]=
|
|
|
|
{
|
|
|
|
{"CHARACTER_SETS", charsets_fields_info, create_schema_table,
|
2004-12-18 11:49:13 +01:00
|
|
|
fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0},
|
2004-11-13 11:56:39 +01:00
|
|
|
{"COLLATIONS", collation_fields_info, create_schema_table,
|
2004-12-18 11:49:13 +01:00
|
|
|
fill_schema_collation, make_old_format, 0, -1, -1, 0},
|
2004-11-13 11:56:39 +01:00
|
|
|
{"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info,
|
2004-12-18 11:49:13 +01:00
|
|
|
create_schema_table, fill_schema_coll_charset_app, 0, 0, -1, -1, 0},
|
2005-08-05 11:01:29 +02:00
|
|
|
{"COLUMNS", columns_fields_info, create_schema_table,
|
|
|
|
get_all_tables, make_columns_old_format, get_schema_column_record, 1, 2, 0},
|
2004-11-13 11:56:39 +01:00
|
|
|
{"COLUMN_PRIVILEGES", column_privileges_fields_info, create_schema_table,
|
2004-12-18 11:49:13 +01:00
|
|
|
fill_schema_column_privileges, 0, 0, -1, -1, 0},
|
2005-12-22 10:07:47 +01:00
|
|
|
{"ENGINES", engines_fields_info, create_schema_table,
|
2006-01-10 16:44:04 +01:00
|
|
|
fill_schema_engines, make_old_format, 0, -1, -1, 0},
|
2006-01-30 13:15:23 +01:00
|
|
|
{"EVENTS", events_fields_info, create_schema_table,
|
|
|
|
fill_schema_events, make_old_format, 0, -1, -1, 0},
|
2006-01-28 04:16:23 +01:00
|
|
|
{"FILES", files_fields_info, create_schema_table,
|
|
|
|
fill_schema_files, 0, 0, -1, -1, 0},
|
2004-11-13 11:56:39 +01:00
|
|
|
{"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
|
2004-12-18 11:49:13 +01:00
|
|
|
get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0},
|
2004-12-30 13:20:40 +01:00
|
|
|
{"OPEN_TABLES", open_tables_fields_info, create_schema_table,
|
|
|
|
fill_open_tables, make_old_format, 0, -1, -1, 1},
|
2006-01-10 16:44:04 +01:00
|
|
|
{"PARTITIONS", partitions_fields_info, create_schema_table,
|
|
|
|
get_all_tables, 0, get_schema_partitions_record, 1, 2, 0},
|
2005-12-21 19:18:40 +01:00
|
|
|
{"PLUGINS", plugin_fields_info, create_schema_table,
|
|
|
|
fill_plugins, make_old_format, 0, -1, -1, 0},
|
2006-02-16 14:45:05 +01:00
|
|
|
{"PROCESSLIST", processlist_fields_info, create_schema_table,
|
|
|
|
fill_schema_processlist, make_old_format, 0, -1, -1, 0},
|
2005-08-05 11:01:29 +02:00
|
|
|
{"ROUTINES", proc_fields_info, create_schema_table,
|
|
|
|
fill_schema_proc, make_proc_old_format, 0, -1, -1, 0},
|
|
|
|
{"SCHEMATA", schema_fields_info, create_schema_table,
|
|
|
|
fill_schema_shemata, make_schemata_old_format, 0, 1, -1, 0},
|
|
|
|
{"SCHEMA_PRIVILEGES", schema_privileges_fields_info, create_schema_table,
|
|
|
|
fill_schema_schema_privileges, 0, 0, -1, -1, 0},
|
|
|
|
{"STATISTICS", stat_fields_info, create_schema_table,
|
|
|
|
get_all_tables, make_old_format, get_schema_stat_record, 1, 2, 0},
|
2004-12-30 13:20:40 +01:00
|
|
|
{"STATUS", variables_fields_info, create_schema_table, fill_status,
|
|
|
|
make_old_format, 0, -1, -1, 1},
|
2005-08-05 11:01:29 +02:00
|
|
|
{"TABLES", tables_fields_info, create_schema_table,
|
|
|
|
get_all_tables, make_old_format, get_schema_tables_record, 1, 2, 0},
|
|
|
|
{"TABLE_CONSTRAINTS", table_constraints_fields_info, create_schema_table,
|
|
|
|
get_all_tables, 0, get_schema_constraints_record, 3, 4, 0},
|
|
|
|
{"TABLE_NAMES", table_names_fields_info, create_schema_table,
|
|
|
|
get_all_tables, make_table_names_old_format, 0, 1, 2, 1},
|
|
|
|
{"TABLE_PRIVILEGES", table_privileges_fields_info, create_schema_table,
|
|
|
|
fill_schema_table_privileges, 0, 0, -1, -1, 0},
|
2005-07-28 21:39:11 +02:00
|
|
|
{"TRIGGERS", triggers_fields_info, create_schema_table,
|
2005-07-19 18:06:49 +02:00
|
|
|
get_all_tables, make_old_format, get_schema_triggers_record, 5, 6, 0},
|
2006-01-29 02:44:51 +01:00
|
|
|
{"USER_PRIVILEGES", user_privileges_fields_info, create_schema_table,
|
|
|
|
fill_schema_user_privileges, 0, 0, -1, -1, 0},
|
2004-12-30 13:20:40 +01:00
|
|
|
{"VARIABLES", variables_fields_info, create_schema_table, fill_variables,
|
|
|
|
make_old_format, 0, -1, -1, 1},
|
2005-08-05 11:01:29 +02:00
|
|
|
{"VIEWS", view_fields_info, create_schema_table,
|
|
|
|
get_all_tables, 0, get_schema_views_record, 1, 2, 0},
|
2004-12-18 11:49:13 +01:00
|
|
|
{0, 0, 0, 0, 0, 0, 0, 0, 0}
|
2004-11-13 11:56:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2005-06-22 11:08:28 +02:00
|
|
|
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
|
2001-08-02 05:29:50 +02:00
|
|
|
template class List_iterator_fast<char>;
|
2000-07-31 21:29:14 +02:00
|
|
|
template class List<char>;
|
|
|
|
#endif
|