40
40
#include <drizzled/item/return_date_time.h>
41
41
#include <drizzled/item/empty_string.h>
42
42
#include "drizzled/plugin/registry.h"
43
#include "drizzled/session_list.h"
44
43
#include <drizzled/plugin/info_schema_table.h>
45
44
#include <drizzled/message/schema.pb.h>
46
45
#include <drizzled/plugin/client.h>
47
#include <drizzled/cached_directory.h>
48
#include "drizzled/sql_table.h"
49
#include "drizzled/global_charset_info.h"
50
#include "drizzled/pthread_globals.h"
51
#include "drizzled/internal/m_string.h"
52
#include "drizzled/internal/my_sys.h"
46
#include <mysys/cached_directory.h>
54
47
#include <sys/stat.h>
306
bool mysqld_show_create_db(Session *session, const NormalisedDatabaseName &database_name, bool if_not_exists)
302
bool mysqld_show_create_db(Session *session, char *dbname, bool if_not_exists)
309
305
String buffer(buff, sizeof(buff), system_charset_info);
311
if (store_db_create_info(database_name.to_string().c_str(), &buffer, if_not_exists))
307
if (store_db_create_info(dbname, &buffer, if_not_exists))
314
310
This assumes that the only reason for which store_db_create_info()
315
311
can fail is incorrect database name (which is the case now).
317
my_error(ER_BAD_DB_ERROR, MYF(0), database_name.to_string().c_str());
313
my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
626
630
to the CREATE TABLE statement
630
We should always store engine since we will now be
631
making sure engines accept options (aka... no
632
dangling arguments for engines.
635
THEN add ENGINE only if it was used when creating the table
634
packet->append(STRING_WITH_LEN(" ENGINE="));
635
packet->append(cursor->engine->getName().c_str());
637
if (!create_info_arg ||
638
(create_info_arg->used_fields & HA_CREATE_USED_ENGINE))
640
packet->append(STRING_WITH_LEN(" ENGINE="));
641
packet->append(cursor->engine->getName().c_str());
637
644
if (share->db_create_options & HA_OPTION_PACK_KEYS)
638
645
packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
701
708
returns for each thread: thread id, user, host, db, command, info
702
709
****************************************************************************/
711
class thread_info :public ilink {
713
static void *operator new(size_t size)
715
return (void*) sql_alloc((uint32_t) size);
717
static void operator delete(void *, size_t)
718
{ TRASH(ptr, size); }
720
my_thread_id thread_id;
709
721
time_t start_time;
710
722
uint32_t command;
711
string user, host, db, proc_info, state_info, query;
712
thread_info(uint64_t thread_id_arg,
713
time_t start_time_arg,
714
uint32_t command_arg,
715
const string &user_arg,
716
const string &host_arg,
717
const string &db_arg,
718
const string &proc_info_arg,
719
const string &state_info_arg,
720
const string &query_arg)
721
: thread_id(thread_id_arg), start_time(start_time_arg), command(command_arg),
722
user(user_arg), host(host_arg), db(db_arg), proc_info(proc_info_arg),
723
state_info(state_info_arg), query(query_arg)
723
const char *user,*host,*db,*proc_info,*state_info;
727
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
728
template class I_List<thread_info>;
727
731
void mysqld_list_processes(Session *session,const char *user, bool)
730
734
List<Item> field_list;
731
vector<thread_info> thread_infos;
735
I_List<thread_info> thread_infos;
733
737
field_list.push_back(new Item_int("Id", 0, MY_INT32_NUM_DECIMAL_DIGITS));
734
738
field_list.push_back(new Item_empty_string("User",16));
748
752
if (!session->killed)
751
for(vector<Session*>::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it)
755
for( vector<Session*>::iterator it= session_list.begin(); it != session_list.end(); ++it )
754
758
Security_context *tmp_sctx= &tmp->security_ctx;
755
759
struct st_my_thread_var *mysys_var;
756
760
if (tmp->client->isConnected() && (!user || (tmp_sctx->user.c_str() && !strcmp(tmp_sctx->user.c_str(), user))))
762
thread_info *session_info= new thread_info;
764
session_info->thread_id=tmp->thread_id;
765
session_info->user= session->strdup(tmp_sctx->user.c_str() ? tmp_sctx->user.c_str() : "unauthenticated user");
766
session_info->host= session->strdup(tmp_sctx->ip.c_str());
767
if ((session_info->db= tmp->db.c_str())) // Safe test
768
session_info->db=session->strdup(session_info->db);
769
session_info->command=(int) tmp->command;
759
770
if ((mysys_var= tmp->mysys_var))
760
771
pthread_mutex_lock(&mysys_var->mutex);
762
const string tmp_proc_info((tmp->killed == Session::KILL_CONNECTION) ? "Killed" : command_name[tmp->command].str);
773
if (tmp->killed == Session::KILL_CONNECTION)
774
session_info->proc_info= (char*) "Killed";
776
session_info->proc_info= command_name[session_info->command].str;
764
const string tmp_state_info(tmp->client->isWriting()
766
: tmp->client->isReading()
767
? (tmp->command == COM_SLEEP
769
: "Reading from net")
770
: tmp->get_proc_info()
771
? tmp->get_proc_info()
772
: (tmp->mysys_var && tmp->mysys_var->current_cond)
778
session_info->state_info= (char*) (tmp->client->isWriting() ?
780
tmp->client->isReading() ?
781
(session_info->command == COM_SLEEP ?
782
NULL : "Reading from net") :
783
tmp->get_proc_info() ? tmp->get_proc_info() :
785
tmp->mysys_var->current_cond ?
786
"Waiting on cond" : NULL);
776
788
pthread_mutex_unlock(&mysys_var->mutex);
778
const string tmp_query((tmp->process_list_info[0]) ? tmp->process_list_info : "");
779
thread_infos.push_back(thread_info(tmp->thread_id,
782
tmp_sctx->user.empty()
783
? string("unauthenticated user")
790
session_info->start_time= tmp->start_time;
791
session_info->query= NULL;
792
if (tmp->process_list_info[0])
793
session_info->query= session->strdup(tmp->process_list_info);
794
thread_infos.append(session_info);
793
798
pthread_mutex_unlock(&LOCK_thread_count);
800
thread_info *session_info;
794
801
time_t now= time(NULL);
795
for(vector<thread_info>::iterator iter= thread_infos.begin();
796
iter != thread_infos.end();
802
while ((session_info=thread_infos.get()))
799
session->client->store((uint64_t) (*iter).thread_id);
800
session->client->store((*iter).user);
801
session->client->store((*iter).host);
802
session->client->store((*iter).db);
803
session->client->store((*iter).proc_info);
804
session->client->store((uint64_t) session_info->thread_id);
805
session->client->store(session_info->user);
806
session->client->store(session_info->host);
807
session->client->store(session_info->db);
808
session->client->store(session_info->proc_info);
805
if ((*iter).start_time)
806
session->client->store((uint32_t) (now - (*iter).start_time));
810
if (session_info->start_time)
811
session->client->store((uint32_t) (now - session_info->start_time));
808
813
session->client->store();
810
session->client->store((*iter).state_info);
811
session->client->store((*iter).query);
815
session->client->store(session_info->state_info);
816
session->client->store(session_info->query);
813
818
if (session->client->flush())
816
821
session->my_eof();
1021
Store record to I_S table, convert HEAP table
1022
to MyISAM if necessary
1025
schema_table_store_record()
1026
session thread Cursor
1027
table Information schema table to be updated
1034
bool schema_table_store_record(Session *session, Table *table)
1037
if ((error= table->cursor->ha_write_row(table->record[0])))
1039
Tmp_Table_Param *param= table->pos_in_table_list->schema_table_param;
1041
if (create_myisam_from_heap(session, table, param->start_recinfo,
1042
¶m->recinfo, error, 0))
1017
1049
static int make_table_list(Session *session, Select_Lex *sel,
1018
1050
LEX_STRING *db_name, LEX_STRING *table_name)
1158
1189
else if (cond->type() == Item::FUNC_ITEM &&
1159
get_lookup_value(session, (Item_func*) cond, table, lookup_field_vals, schema_table))
1190
get_lookup_value(session, (Item_func*) cond, table, lookup_field_vals))
1165
static bool uses_only_table_name_fields(Item *item, Table *table, plugin::InfoSchemaTable *schema_table)
1196
static bool uses_only_table_name_fields(Item *item, TableList *table)
1167
1198
if (item->type() == Item::FUNC_ITEM)
1169
1200
Item_func *item_func= (Item_func*)item;
1170
1201
for (uint32_t i=0; i<item_func->argument_count(); i++)
1172
if (! uses_only_table_name_fields(item_func->arguments()[i], table, schema_table))
1203
if (!uses_only_table_name_fields(item_func->arguments()[i], table))
1178
1209
Item_field *item_field= (Item_field*)item;
1179
1210
const CHARSET_INFO * const cs= system_charset_info;
1211
plugin::InfoSchemaTable *schema_table= table->schema_table;
1180
1212
const char *field_name1= schema_table->getFirstColumnIndex() >= 0 ?
1181
1213
schema_table->getColumnName(schema_table->getFirstColumnIndex()).c_str() : "";
1182
1214
const char *field_name2= schema_table->getSecondColumnIndex() >= 0 ?
1183
1215
schema_table->getColumnName(schema_table->getSecondColumnIndex()).c_str() : "";
1184
if (table != item_field->field->table ||
1216
if (table->table != item_field->field->table ||
1185
1217
(cs->coll->strnncollsp(cs, (unsigned char *) field_name1, strlen(field_name1),
1186
1218
(unsigned char *) item_field->field_name,
1187
1219
strlen(item_field->field_name), 0) &&
1211
1243
/* Create new top level AND item */
1212
1244
Item_cond_and *new_cond=new Item_cond_and;
1215
1247
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1217
1249
while ((item=li++))
1219
Item *fix= make_cond_for_info_schema(item, table, schema_table);
1221
new_cond->argument_list()->push_back(fix);
1251
Item *fix= make_cond_for_info_schema(item, table);
1253
new_cond->argument_list()->push_back(fix);
1223
1255
switch (new_cond->argument_list()->elements) {
1227
return new_cond->argument_list()->head();
1229
new_cond->quick_fix_field();
1259
return new_cond->argument_list()->head();
1261
new_cond->quick_fix_field();
1235
1267
Item_cond_or *new_cond=new Item_cond_or;
1238
1270
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1240
1272
while ((item=li++))
1242
Item *fix=make_cond_for_info_schema(item, table, schema_table);
1245
new_cond->argument_list()->push_back(fix);
1274
Item *fix=make_cond_for_info_schema(item, table);
1277
new_cond->argument_list()->push_back(fix);
1247
1279
new_cond->quick_fix_field();
1248
1280
new_cond->top_level_item();
1602
schema_table->addRow(table->record[0], table->s->reclength);
1632
if (schema_table_store_record(session, table))
1606
int plugin::InfoSchemaMethods::fillTable(Session *session,
1608
plugin::InfoSchemaTable *schema_table)
1639
@brief Get open table method
1641
@details The function calculates the method which will be used
1643
SKIP_OPEN_TABLE - do not open table
1644
OPEN_FRM_ONLY - open FRM cursor only
1645
OPEN_FULL_TABLE - open FRM, data, index files
1646
@param[in] tables I_S table table_list
1647
@param[in] schema_table I_S table struct
1649
@return return a set of flags
1650
@retval SKIP_OPEN_TABLE | OPEN_FRM_ONLY | OPEN_FULL_TABLE
1653
static uint32_t get_table_open_method(TableList *tables,
1654
plugin::InfoSchemaTable *schema_table)
1657
determine which method will be used for table opening
1659
if (schema_table->getRequestedObject() & OPTIMIZE_I_S_TABLE)
1661
Field **ptr, *field;
1662
int table_open_method= 0, field_indx= 0;
1663
for (ptr= tables->table->field; (field= *ptr) ; ptr++)
1665
if (field->isReadSet())
1666
table_open_method|= schema_table->getColumnOpenMethod(field_indx);
1669
return table_open_method;
1671
/* I_S tables which use get_all_tables but can not be optimized */
1672
return (uint32_t) OPEN_FULL_TABLE;
1677
@brief Fill I_S table with data from FRM cursor only
1679
@param[in] session thread Cursor
1680
@param[in] table Table struct for I_S table
1681
@param[in] schema_table I_S table struct
1682
@param[in] db_name database name
1683
@param[in] table_name table name
1685
@return Operation status
1686
@retval 0 Table is processed and we can continue
1688
@retval 1 It's view and we have to use
1689
open_tables function for this table
1692
static int fill_schema_table_from_frm(Session *session,TableList *tables,
1693
plugin::InfoSchemaTable *schema_table,
1694
LEX_STRING *db_name,
1695
LEX_STRING *table_name)
1697
Table *table= tables->table;
1700
TableList table_list;
1703
char key[MAX_DBKEY_LENGTH];
1704
uint32_t key_length;
1706
memset(&tbl, 0, sizeof(Table));
1708
table_list.table_name= table_name->str;
1709
table_list.db= db_name->str;
1711
key_length= table_list.create_table_def_key(key);
1712
pthread_mutex_lock(&LOCK_open); /* Locking to get table share when filling schema table from FRM */
1713
share= TableShare::getShare(session, &table_list, key, key_length, 0, &error);
1722
table_list.table= &tbl;
1723
res= schema_table->processTable(session, &table_list, table,
1724
res, db_name, table_name);
1726
/* For the moment we just set everything to read */
1727
table->setReadSet();
1729
TableShare::release(share);
1732
pthread_mutex_unlock(&LOCK_open);
1733
session->clear_error();
1740
@brief Fill I_S tables whose data are retrieved
1741
from frm files and storage engine
1743
@details The information schema tables are internally represented as
1744
temporary tables that are filled at query execution time.
1745
Those I_S tables whose data are retrieved
1746
from frm files and storage engine are filled by the function
1747
plugin::InfoSchemaMethods::fillTable().
1749
@param[in] session thread Cursor
1750
@param[in] tables I_S table
1752
@return Operation status
1756
int plugin::InfoSchemaMethods::fillTable(Session *session, TableList *tables)
1610
1758
LEX *lex= session->lex;
1759
Table *table= tables->table;
1611
1760
Select_Lex *old_all_select_lex= lex->all_selects_list;
1612
1761
enum_sql_command save_sql_command= lex->sql_command;
1613
Select_Lex *lsel= table->pos_in_table_list->schema_select_lex;
1762
Select_Lex *lsel= tables->schema_select_lex;
1763
plugin::InfoSchemaTable *schema_table= tables->schema_table;
1614
1764
Select_Lex sel;
1615
1765
LOOKUP_FIELD_VALUES lookup_field_vals;
1616
1766
bool with_i_schema;
1639
1792
if (lsel && lsel->table_list.first)
1641
error= fill_schema_show_cols_or_idxs(session, table->pos_in_table_list, schema_table,
1794
error= fill_schema_show_cols_or_idxs(session, tables, schema_table,
1642
1795
&open_tables_state_backup);
1646
if (get_lookup_field_values(session,
1648
table->pos_in_table_list,
1799
if (get_lookup_field_values(session, cond, tables, &lookup_field_vals))
1670
1819
if (lookup_field_vals.db_value.length &&
1671
1820
!lookup_field_vals.wild_db_value)
1672
table->pos_in_table_list->has_db_lookup_value= true;
1821
tables->has_db_lookup_value= true;
1674
1823
if (lookup_field_vals.table_value.length &&
1675
1824
!lookup_field_vals.wild_table_value)
1676
table->pos_in_table_list->has_table_lookup_value= true;
1825
tables->has_table_lookup_value= true;
1678
if (table->pos_in_table_list->has_db_lookup_value &&
1679
table->pos_in_table_list->has_table_lookup_value)
1827
if (tables->has_db_lookup_value && tables->has_table_lookup_value)
1680
1828
partial_cond= 0;
1682
partial_cond= make_cond_for_info_schema(cond, table, schema_table);
1830
partial_cond= make_cond_for_info_schema(cond, tables);
1684
1832
if (lex->describe)
1718
1866
if (!partial_cond || partial_cond->val_int())
1869
If table is I_S.tables and open_table_method is 0 (eg SKIP_OPEN)
1870
we can skip table opening and we don't have lookup value for
1871
table name or lookup value is wild string(table name list is
1872
already created by make_table_name_list() function).
1874
if (! table_open_method &&
1875
schema_table->getTableName().compare("TABLES") == 0 &&
1876
(! lookup_field_vals.table_value.length ||
1877
lookup_field_vals.wild_table_value))
1879
if (schema_table_store_record(session, table))
1880
goto err; /* Out of space in temporary table */
1720
1884
/* SHOW Table NAMES command */
1721
1885
if (schema_table->getTableName().compare("TABLE_NAMES") == 0)
1723
if (fill_schema_table_names(session,
1887
if (fill_schema_table_names(session, tables->table, *db_name,
1888
*table_name, with_i_schema))
1893
if (!(table_open_method & ~OPEN_FRM_ONLY) &&
1896
if (!fill_schema_table_from_frm(session, tables, schema_table, *db_name,
1733
1901
LEX_STRING tmp_lex_string, orig_db_name;
1735
1903
Set the parent lex of 'sel' because it is needed by
2026
2195
table->field[20]->store((const char*) pos,
2027
2196
strlen((const char*) pos), cs);
2029
store_table->addRow(table->record[0], table->s->reclength);
2198
if (schema_table_store_record(session, table))
2205
Table *plugin::InfoSchemaMethods::createSchemaTable(Session *session, TableList *table_list)
2211
List<Item> field_list;
2212
const CHARSET_INFO * const cs= system_charset_info;
2213
const plugin::InfoSchemaTable::Columns &columns= table_list->schema_table->getColumns();
2214
plugin::InfoSchemaTable::Columns::const_iterator iter= columns.begin();
2216
while (iter != columns.end())
2218
const plugin::ColumnInfo *column= *iter;
2219
switch (column->getType()) {
2220
case DRIZZLE_TYPE_LONG:
2221
case DRIZZLE_TYPE_LONGLONG:
2222
if (!(item= new Item_return_int(column->getName().c_str(),
2223
column->getLength(),
2225
column->getValue())))
2229
item->unsigned_flag= (column->getFlags() & MY_I_S_UNSIGNED);
2231
case DRIZZLE_TYPE_DATE:
2232
case DRIZZLE_TYPE_TIMESTAMP:
2233
case DRIZZLE_TYPE_DATETIME:
2234
if (!(item=new Item_return_date_time(column->getName().c_str(),
2235
column->getType())))
2240
case DRIZZLE_TYPE_DOUBLE:
2241
if ((item= new Item_float(column->getName().c_str(), 0.0, NOT_FIXED_DEC,
2242
column->getLength())) == NULL)
2245
case DRIZZLE_TYPE_DECIMAL:
2246
if (!(item= new Item_decimal((int64_t) column->getValue(), false)))
2250
item->unsigned_flag= (column->getFlags() & MY_I_S_UNSIGNED);
2251
item->decimals= column->getLength() % 10;
2252
item->max_length= (column->getLength()/100)%100;
2253
if (item->unsigned_flag == 0)
2254
item->max_length+= 1;
2255
if (item->decimals > 0)
2256
item->max_length+= 1;
2257
item->set_name(column->getName().c_str(),
2258
column->getName().length(), cs);
2260
case DRIZZLE_TYPE_BLOB:
2261
if (!(item= new Item_blob(column->getName().c_str(),
2262
column->getLength())))
2268
if (!(item= new Item_empty_string("", column->getLength(), cs)))
2272
item->set_name(column->getName().c_str(),
2273
column->getName().length(), cs);
2276
field_list.push_back(item);
2277
item->maybe_null= (column->getFlags() & MY_I_S_MAYBE_NULL);
2281
Tmp_Table_Param *tmp_table_param =
2282
(Tmp_Table_Param*) (session->alloc(sizeof(Tmp_Table_Param)));
2283
tmp_table_param->init();
2284
tmp_table_param->table_charset= cs;
2285
tmp_table_param->field_count= field_count;
2286
tmp_table_param->schema_table= 1;
2287
Select_Lex *select_lex= session->lex->current_select;
2288
if (!(table= create_tmp_table(session, tmp_table_param,
2289
field_list, (order_st*) 0, 0, 0,
2290
(select_lex->options | session->options |
2291
TMP_TABLE_ALL_COLUMNS),
2292
HA_POS_ERROR, table_list->alias)))
2294
my_bitmap_map* bitmaps=
2295
(my_bitmap_map*) session->alloc(bitmap_buffer_size(field_count));
2296
table->def_read_set.init((my_bitmap_map*) bitmaps, field_count);
2297
table->read_set= &table->def_read_set;
2298
table->read_set->clearAll();
2299
table_list->schema_table_param= tmp_table_param;
2036
2305
For old SHOW compatibility. It is used when
2037
2306
old SHOW doesn't have generated column names
2350
Create information_schema table
2353
mysql_schema_table()
2354
session thread Cursor
2356
table_list pointer to table_list
2362
bool mysql_schema_table(Session *session, LEX *, TableList *table_list)
2365
if (!(table= table_list->schema_table->createSchemaTable(session, table_list)))
2367
table->s->tmp_table= SYSTEM_TMP_TABLE;
2369
This test is necessary to make
2370
case insensitive cursor systems +
2371
upper case table names(information schema tables) +
2375
if (table_list->schema_table_name)
2376
table->alias_name_used= my_strcasecmp(table_alias_charset,
2377
table_list->schema_table_name,
2379
table_list->table_name= table->s->table_name.str;
2380
table_list->table_name_length= table->s->table_name.length;
2381
table_list->table= table;
2382
table->next= session->derived_tables;
2383
session->derived_tables= table;
2384
table_list->select_lex->options |= OPTION_SCHEMA_TABLE;
2081
2391
Generate select from information_schema table
2426
Fill temporary schema tables before SELECT
2429
get_schema_tables_result()
2430
join join which use schema tables
2431
executed_place place where I_S table processed
2438
bool get_schema_tables_result(JOIN *join,
2439
enum enum_schema_table_state executed_place)
2441
JoinTable *tmp_join_tab= join->join_tab+join->tables;
2442
Session *session= join->session;
2443
LEX *lex= session->lex;
2446
session->no_warnings_for_error= 1;
2447
for (JoinTable *tab= join->join_tab; tab < tmp_join_tab; tab++)
2449
if (!tab->table || !tab->table->pos_in_table_list)
2452
TableList *table_list= tab->table->pos_in_table_list;
2453
if (table_list->schema_table)
2455
bool is_subselect= (&lex->unit != lex->current_select->master_unit() &&
2456
lex->current_select->master_unit()->item);
2459
/* skip I_S optimizations specific to get_all_tables */
2460
if (session->lex->describe &&
2461
(table_list->schema_table->isOptimizationPossible() != true))
2467
If schema table is already processed and
2468
the statement is not a subselect then
2469
we don't need to fill this table again.
2470
If schema table is already processed and
2471
schema_table_state != executed_place then
2472
table is already processed and
2473
we should skip second data processing.
2475
if (table_list->schema_table_state &&
2476
(!is_subselect || table_list->schema_table_state != executed_place))
2480
if table is used in a subselect and
2481
table has been processed earlier with the same
2482
'executed_place' value then we should refresh the table.
2484
if (table_list->schema_table_state && is_subselect)
2486
table_list->table->cursor->extra(HA_EXTRA_NO_CACHE);
2487
table_list->table->cursor->extra(HA_EXTRA_RESET_STATE);
2488
table_list->table->cursor->ha_delete_all_rows();
2489
table_list->table->free_io_cache();
2490
table_list->table->filesort_free_buffers(true);
2491
table_list->table->null_row= 0;
2494
table_list->table->cursor->stats.records= 0;
2496
if (table_list->schema_table->fillTable(session, table_list))
2500
tab->read_record.cursor= table_list->table->cursor;
2501
table_list->schema_table_state= executed_place;
2504
tab->read_record.cursor= table_list->table->cursor;
2505
table_list->schema_table_state= executed_place;
2508
session->no_warnings_for_error= 0;