1
0
Files
irix-657m-src/eoe/cmd/sss/ssdb/ssdbserver/sql/sql_show.cc
2022-09-29 17:59:04 +03:00

529 lines
16 KiB
C++

/* Copyright (C) 1979-1996 TcX AB & Monty Program KB & Detron HB
This software is distributed with NO WARRANTY OF ANY KIND. No author or
distributor accepts any responsibility for the consequences of using it, or
for whether it serves any particular purpose or works at all, unless he or
she says so in writing. Refer to the Free Public License (the "License")
for full details.
Every copy of this file must include a copy of the License, normally in a
plain ASCII text file named PUBLIC. The License grants you the right to
copy, modify and redistribute this file, but only under certain conditions
described in the License. Among other things, the License requires that
the copyright notice and this notice be preserved on all copies. */
/* Function with list databases, tables or fields */
#include "mysql_priv.h"
#include "sql_select.h" // For select_describe
#include "sql_acl.h"
#include <my_dir.h>
static int mysql_find_files(THD *thd,const char *db,const char *path,
const char *wild, bool dir);
/****************************************************************************
** Send list of databases
** A database is a directory in the mysql_data_home directory
****************************************************************************/
int
mysqld_show_dbs(THD *thd,const char *wild)
{
Item_string *field=new Item_string("",0);
List<Item> field_list;
char *end;
DBUG_ENTER("mysqld_show_dbs");
field->name=(char*) sql_alloc(20+ (wild ? strlen(wild)+4: 0));
field->max_length=NAME_LEN;
end=strmov(field->name,"Database");
if (wild && wild[0])
strxmov(end," (",wild,")",NullS);
field_list.push_back(field);
if (send_fields(thd,field_list,1))
DBUG_RETURN(1);
DBUG_RETURN(mysql_find_files(thd,NullS,mysql_data_home,wild,1));
}
/***************************************************************************
** List all tables in a database
** A table is a .frm file in the current databasedir
***************************************************************************/
int mysqld_show_tables(THD *thd,const char *db,const char *wild)
{
Item_string *field=new Item_string("",0);
List<Item> field_list;
char path[FN_LEN],*end;
DBUG_ENTER("mysqld_show_tables");
field->name=(char*) sql_alloc(20+strlen(db)+(wild ? strlen(wild)+4:0));
end=strxmov(field->name,"Tables in ",db,NullS);
if (wild && wild[0])
strxmov(end," (",wild,")",NullS);
field->max_length=NAME_LEN;
(void) sprintf(path,"%s/%s",mysql_data_home,db);
(void) unpack_filename(path,path);
field_list.push_back(field);
if (send_fields(thd,field_list,1))
DBUG_RETURN(1);
DBUG_RETURN(mysql_find_files(thd,db,path,wild,0));
}
static int
mysql_find_files(THD *thd,const char *db,const char *path,
const char *wild,bool dir)
{
uint i;
char *ext;
MY_DIR *dirp;
FILEINFO *file;
uint access=thd->col_access;
TABLE_LIST table_list;
DBUG_ENTER("mysql_find_files");
bzero((char*) &table_list,sizeof(table_list));
if (!(dirp = my_dir(path,MYF(MY_WME | (dir ? MY_WANT_STAT : 0)))))
DBUG_RETURN(-1);
for (i=0 ; i < (uint) dirp->number_off_files ; i++)
{
file=dirp->dir_entry+i;
if (dir)
{ /* Return databases */
if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat.st_mode) ||
(wild && wild[0] && wild_compare(file->name,wild)))
continue;
}
else
{
// Return only .frm files which isn't temp files.
if (strcmp(ext=fn_ext(file->name),reg_ext) ||
strchr(file->name,'-')) // Mysql temp table
continue;
*ext=0;
if (wild && wild[0] && wild_compare(file->name,wild))
continue;
}
/* Don't show tables where we don't have any privileges */
if (db && !(access & TABLE_ACLS))
{
table_list.db= (char*) db;
table_list.real_name=file->name;
table_list.grant.privilege=access;
if (check_grant(thd,TABLE_ACLS,&table_list,1))
continue;
}
thd->packet.length(0);
net_store_data(&thd->packet,file->name);
if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length()))
break;
}
send_eof(&thd->net);
my_dirend(dirp);
DBUG_RETURN(0);
}
int
mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild)
{
TABLE *table;
char tmp[MAX_FIELD_WIDTH];
uint access=thd->col_access;
DBUG_ENTER("mysqld_show_fields");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
{
send_error(&thd->net);
DBUG_RETURN(1);
}
ha_info(table,2); // sync record count
List<Item> field_list;
field_list.push_back(new Item_empty_string("Field",NAME_LEN));
field_list.push_back(new Item_empty_string("Type",40));
field_list.push_back(new Item_empty_string("Null",1));
field_list.push_back(new Item_empty_string("Key",3));
field_list.push_back(new Item_empty_string("Default",NAME_LEN));
field_list.push_back(new Item_empty_string("Extra",20));
// Send first number of fields and records
{
char *pos;
pos=net_store_length(tmp,field_list.elements);
pos=net_store_length(pos,(ulonglong) table->keyfile_info.records);
(void) my_net_write(&thd->net,tmp,(uint) (pos-tmp));
}
if (send_fields(thd,field_list,0))
DBUG_RETURN(1);
restore_record(table,2); // Get empty record
Field **ptr,*field;
for (ptr=table->field; (field= *ptr) ; ptr++)
{
if (!wild || !wild[0] || !wild_case_compare(field->field_name,wild))
{
#ifdef NOT_USED
if (access & TABLE_ACLS ||
! check_grant_column(thd,table,field->field_name,
strlen(field->field_name),1))
#endif
{
byte *pos;
uint flags=field->flags;
String *packet= &thd->packet,type(tmp,sizeof(tmp));
packet->length(0);
net_store_data(packet,field->field_name);
field->sql_type(type);
net_store_data(packet,type.ptr(),type.length());
pos=(byte*) ((flags & NOT_NULL_FLAG) &&
field->type() != FIELD_TYPE_TIMESTAMP ?
"" : "YES");
net_store_data(packet,(const char*) pos);
pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
(field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
(field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
net_store_data(packet,(char*) pos);
if (!(flags & BLOB_FLAG) && field->type() != FIELD_TYPE_TIMESTAMP &&
!field->is_null())
{ // Not null by default
type.set(tmp,sizeof(tmp));
field->val_str(&type,&type);
net_store_data(packet,type.ptr(),type.length());
}
else if (field->maybe_null() ||
field->type() == FIELD_TYPE_TIMESTAMP ||
(flags & BLOB_FLAG))
net_store_null(packet); // Null as default
else
net_store_data(packet,tmp,0);
char *end=tmp;
if (field->unireg_check == Field::NEXT_NUMBER)
end=strmov(tmp,"auto_increment");
net_store_data(packet,tmp,(uint) (end-tmp));
if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
DBUG_RETURN(1);
}
}
}
send_eof(&thd->net);
DBUG_RETURN(0);
}
int
mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
{
TABLE *table;
DBUG_ENTER("mysqld_show_keys");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
{
send_error(&thd->net);
DBUG_RETURN(1);
}
List<Item> field_list;
Item *item;
field_list.push_back(new Item_empty_string("Table",NAME_LEN));
field_list.push_back(new Item_int("Non_unique",0,1));
field_list.push_back(new Item_empty_string("Key_name",NAME_LEN));
field_list.push_back(new Item_int("Seq_in_index",0,2));
field_list.push_back(new Item_empty_string("Column_name",NAME_LEN));
field_list.push_back(item=new Item_empty_string("Collation",1));
item->maybe_null=1;
field_list.push_back(item=new Item_int("Cardinality",0,11));
item->maybe_null=1;
field_list.push_back(item=new Item_int("Sub_part",0,3));
if (send_fields(thd,field_list,1))
DBUG_RETURN(1);
TABLE *form= table;
KEY *key_info=form->key_info;
ha_info(form,2);
for (uint i=0 ; i < form->keys ; i++,key_info++)
{
KEY_PART_INFO *key_part= key_info->key_part;
char buff[10],*end;
String *packet= &thd->packet;
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
{
packet->length(0);
net_store_data(packet,table->table_name);
net_store_data(packet,(key_info->dupp_key ? "1" :"0"), 1);
net_store_data(packet,key_info->name);
end=int2str((long) (j+1),(char*) buff,10);
net_store_data(packet,buff,(uint) (end-buff));
net_store_data(packet,key_part->field ? key_part->field->field_name :
"?unknown field?");
if (ha_option_flag[form->db_type] & HA_READ_ORDER)
net_store_data(packet,(key_part->key_part_flag == 0 ? "A" : "D"), 1);
else
net_store_null(packet); /* purecov: inspected */
if (form->db_type == DB_TYPE_ISAM && form->keyfile_info.rec_per_key[i])
{
ulong records=(form->keyfile_info.records /
form->keyfile_info.rec_per_key[i]);
end=int2str((long) records, buff, 10);
net_store_data(packet,buff,(uint) (end-buff));
}
else
net_store_null(packet);
if (!key_part->field ||
key_part->length !=
table->field[key_part->fieldnr-1]->pack_length())
{
end=int2str((long) key_part->length, buff,10); /* purecov: inspected */
net_store_data(packet,buff,(uint) (end-buff)); /* purecov: inspected */
}
else
net_store_null(packet);
if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
DBUG_RETURN(1); /* purecov: inspected */
}
}
send_eof(&thd->net);
DBUG_RETURN(0);
}
/****************************************************************************
** Return only fields for API mysql_list_fields
** Use "show table wildcard" in mysql instead of this
****************************************************************************/
void
mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
{
TABLE *table;
DBUG_ENTER("mysqld_list_fields");
DBUG_PRINT("enter",("table: %s",table_list->real_name));
if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
{
send_error(&thd->net);
DBUG_VOID_RETURN;
}
List<Item> field_list;
Field **ptr,*field;
for (ptr=table->field ; (field= *ptr); ptr++)
{
if (!wild || !wild[0] || !wild_case_compare(field->field_name,wild))
field_list.push_back(new Item_field(field));
}
restore_record(table,2); // Get empty record
if (send_fields(thd,field_list,2))
DBUG_VOID_RETURN;
VOID(net_flush(&thd->net));
DBUG_VOID_RETURN;
}
/****************************************************************************
** Return info about all processes
** returns for each thread: thread id, user, host, db, command, info
****************************************************************************/
class thread_info :public Sql_alloc, public ilink {
public:
ulong thread_id,start_time;
uint command;
char *user,*host,*db,*query,*proc_info,*state_info;
};
#ifdef __GNUC__
template class I_List<thread_info>;
template class I_List_iterator<THD>;
#endif
void mysqld_list_processes(THD *thd,const char *user)
{
Item *field;
List<Item> field_list;
I_List<thread_info> thread_infos;
DBUG_ENTER("mysql_list_processes");
field_list.push_back(new Item_int("Id",0,7));
field_list.push_back(new Item_empty_string("User",16));
field_list.push_back(new Item_empty_string("Host",64));
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));
field_list.push_back(new Item_empty_string("Time",7));
field_list.push_back(field=new Item_empty_string("State",20));
field->maybe_null=1;
field_list.push_back(field=new Item_empty_string("Info",100));
field->maybe_null=1;
if (send_fields(thd,field_list,1))
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++))
{
if (tmp->net.fd >= 0 && (!user || !strcmp(tmp->user,user)))
{
thread_info *thd_info=new thread_info;
thd_info->thread_id=tmp->thread_id;
thd_info->user=sql_strdup(tmp->user ? tmp->user : "unknown user");
thd_info->host=sql_strdup(tmp->host ? tmp->host : tmp->ip ? tmp->ip : "unknown host");
if ((thd_info->db=tmp->db)) // Safe test
thd_info->db=sql_strdup(thd_info->db);
thd_info->command=(int) tmp->command;
if (tmp->mysys_var)
pthread_mutex_lock(&tmp->mysys_var->mutex);
thd_info->proc_info= (char*) (tmp->killed ? "Killed" : 0);
thd_info->state_info= (char*) (tmp->proc_info ? tmp->proc_info :
tmp->locked ? "Locked" :
tmp->mysys_var &&
tmp->mysys_var->current_cond ?
"Waiting for cond" : NullS);
if (tmp->mysys_var)
pthread_mutex_unlock(&tmp->mysys_var->mutex);
#ifndef DONT_USE_THR_ALARM
if (pthread_kill(tmp->real_id,0))
tmp->proc_info="*** DEAD ***"; // This shouldn't happen
#endif
thd_info->start_time= tmp->start_time;
thd_info->query=0;
if (tmp->query)
{
uint length=strlen(tmp->query);
if (length > 100)
length=100;
thd_info->query=(char*) sql_memdup(tmp->query,length+1);
thd_info->query[length]=0;
}
thread_infos.append(thd_info);
}
}
}
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thread_info *thd_info;
String *packet= &thd->packet;
while ((thd_info=thread_infos.get()))
{
char buff[20],*end;
packet->length(0);
end=int2str((long) thd_info->thread_id, buff,10);
net_store_data(packet,buff,(uint) (end-buff));
net_store_data(packet,thd_info->user);
net_store_data(packet,thd_info->host);
if (thd_info->db)
net_store_data(packet,thd_info->db);
else
net_store_null(packet);
if (thd_info->proc_info)
net_store_data(packet,thd_info->proc_info);
else
net_store_data(packet,command_name[thd_info->command]);
if (thd_info->start_time)
net_store_data(packet,(ulong) (time((time_t*) 0) - thd_info->start_time));
else
net_store_null(packet);
if (thd_info->state_info)
net_store_data(packet,thd_info->state_info);
else
net_store_null(packet);
if (thd_info->query)
net_store_data(packet,thd_info->query);
else
net_store_null(packet);
if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
break; /* purecov: inspected */
}
send_eof(&thd->net);
DBUG_VOID_RETURN;
}
/*****************************************************************************
** Status functions
*****************************************************************************/
int mysqld_show(THD *thd, const char *wild, show_var_st *variables)
{
uint i;
char buff[1024];
String packet2(buff,sizeof(buff));
List<Item> field_list;
DBUG_ENTER("mysqld_show");
field_list.push_back(new Item_empty_string("Variable_name",30));
field_list.push_back(new Item_empty_string("Value",256));
if (send_fields(thd,field_list,1))
DBUG_RETURN(1); /* purecov: inspected */
for (i=0; variables[i].name; i++)
{
if (!(wild && wild[0] && wild_compare(variables[i].name,wild)))
{
packet2.length(0);
net_store_data(&packet2,variables[i].name);
switch (variables[i].type){
case SHOW_LONG:
case SHOW_LONG_CONST:
net_store_data(&packet2,*(ulong*) variables[i].value);
break;
case SHOW_BOOL:
net_store_data(&packet2,(ulong) *(bool*) variables[i].value ?
"ON" : "OFF");
break;
case SHOW_MY_BOOL:
net_store_data(&packet2,(ulong) *(my_bool*) variables[i].value ?
"ON" : "OFF");
break;
case SHOW_INT:
net_store_data(&packet2,(ulong) *(int*) variables[i].value);
break;
case SHOW_CHAR:
net_store_data(&packet2,variables[i].value);
break;
case SHOW_STARTTIME:
net_store_data(&packet2,(long) (thd->query_start() - start_time));
break;
case SHOW_QUESTION:
net_store_data(&packet2,(long) thd->query_id);
break;
case SHOW_OPENTABLES:
net_store_data(&packet2,(long) cached_tables());
break;
case SHOW_CHAR_PTR:
{
char *value= *(char**) variables[i].value;
net_store_data(&packet2,value ? value : "");
break;
}
}
if (my_net_write(&thd->net, (char*) packet2.ptr(),packet2.length()))
DBUG_RETURN(1); /* purecov: inspected */
}
}
send_eof(&thd->net);
DBUG_RETURN(0);
}