120
118
return (*str != '\0');
124
bool drizzled_show_create(Session *session, TableList *table_list, bool is_if_not_exists)
127
String buffer(buff, sizeof(buff), system_charset_info);
129
/* Only one table for now, but VIEW can involve several tables */
130
if (session->openTables(table_list))
132
if (session->is_error())
136
Clear all messages with 'error' level status and
137
issue a warning with 'warning' level status in
138
case of invalid view and last error is ER_VIEW_INVALID
140
drizzle_reset_errors(session, true);
141
session->clear_error();
146
if (store_create_info(table_list, &buffer, is_if_not_exists))
149
List<Item> field_list;
151
field_list.push_back(new Item_empty_string("Table",NAME_CHAR_LEN));
152
// 1024 is for not to confuse old clients
153
field_list.push_back(new Item_empty_string("Create Table",
154
max(buffer.length(),(uint32_t)1024)));
157
if (session->client->sendFields(&field_list))
160
session->client->store(table_list->table->alias);
163
session->client->store(buffer.ptr(), buffer.length());
165
if (session->client->flush())
173
Get a CREATE statement for a given database.
175
The database is identified by its name, passed as @c dbname parameter.
176
The name should be encoded using the system character set (UTF8 currently).
178
Resulting statement is stored in the string pointed by @c buffer. The string
179
is emptied first and its character set is set to the system character set.
181
If is_if_not_exists is set, then
182
the resulting CREATE statement contains "IF NOT EXISTS" clause. Other flags
183
in @c create_options are ignored.
185
@param session The current thread instance.
186
@param dbname The name of the database.
187
@param buffer A String instance where the statement is stored.
188
@param create_info If not NULL, the options member influences the resulting
191
@returns true if errors are detected, false otherwise.
194
static bool store_db_create_info(SchemaIdentifier &schema_identifier, string &buffer, bool if_not_exists)
196
message::Schema schema;
198
bool found= plugin::StorageEngine::getSchemaDefinition(schema_identifier, schema);
202
buffer.append("CREATE DATABASE ");
205
buffer.append("IF NOT EXISTS ");
208
buffer.append(schema.name());
211
if (schema.has_collation())
213
buffer.append(" COLLATE = ");
214
buffer.append(schema.collation());
220
bool mysqld_show_create_db(Session &session, SchemaIdentifier &schema_identifier, bool if_not_exists)
222
message::Schema schema_message;
225
if (not plugin::StorageEngine::getSchemaDefinition(schema_identifier, schema_message))
228
This assumes that the only reason for which store_db_create_info()
229
can fail is incorrect database name (which is the case now).
231
my_error(ER_BAD_DB_ERROR, MYF(0), schema_identifier.getSQLPath().c_str());
235
if (not store_db_create_info(schema_identifier, buffer, if_not_exists))
238
This assumes that the only reason for which store_db_create_info()
239
can fail is incorrect database name (which is the case now).
241
my_error(ER_BAD_DB_ERROR, MYF(0), schema_identifier.getSQLPath().c_str());
245
List<Item> field_list;
246
field_list.push_back(new Item_empty_string("Database",NAME_CHAR_LEN));
247
field_list.push_back(new Item_empty_string("Create Database",1024));
249
if (session.client->sendFields(&field_list))
252
session.client->store(schema_message.name());
253
session.client->store(buffer);
255
if (session.client->flush())
264
122
Get the quote character for displaying an identifier.
289
#define LIST_PROCESS_HOST_LEN 64
291
static bool get_field_default_value(Field *timestamp_field,
292
Field *field, String *def_value,
296
bool has_now_default;
299
We are using CURRENT_TIMESTAMP instead of NOW because it is
302
has_now_default= (timestamp_field == field &&
303
field->unireg_check != Field::TIMESTAMP_UN_FIELD);
305
has_default= (field->type() != DRIZZLE_TYPE_BLOB &&
306
!(field->flags & NO_DEFAULT_VALUE_FLAG) &&
307
field->unireg_check != Field::NEXT_NUMBER);
309
def_value->length(0);
313
def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
314
else if (!field->is_null())
315
{ // Not null by default
316
char tmp[MAX_FIELD_WIDTH];
317
String type(tmp, sizeof(tmp), field->charset());
318
field->val_str(&type);
322
uint32_t dummy_errors;
323
/* convert to system_charset_info == utf8 */
324
def_val.copy(type.ptr(), type.length(), field->charset(),
325
system_charset_info, &dummy_errors);
327
append_unescaped(def_value, def_val.ptr(), def_val.length());
329
def_value->append(def_val.ptr(), def_val.length());
332
def_value->append(STRING_WITH_LEN("''"));
334
else if (field->maybe_null() && quoted)
335
def_value->append(STRING_WITH_LEN("NULL")); // Null as default
343
Build a CREATE TABLE statement for a table.
347
table_list A list containing one table to write statement
349
packet Pointer to a string where statement will be
353
Currently always return 0, but might return error code in the
360
int store_create_info(TableList *table_list, String *packet, bool is_if_not_exists)
362
List<Item> field_list;
363
char tmp[MAX_FIELD_WIDTH], *for_str, def_value_buf[MAX_FIELD_WIDTH];
366
String type(tmp, sizeof(tmp), system_charset_info);
367
String def_value(def_value_buf, sizeof(def_value_buf), system_charset_info);
369
uint32_t primary_key;
371
Table *table= table_list->table;
372
Cursor *cursor= table->cursor;
373
TableShare *share= table->s;
374
HA_CREATE_INFO create_info;
375
bool show_table_options= false;
376
my_bitmap_map *old_map;
378
table->restoreRecordAsDefault(); // Get empty record
380
if (share->tmp_table)
381
packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
383
packet->append(STRING_WITH_LEN("CREATE TABLE "));
384
if (is_if_not_exists)
385
packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
386
alias= share->table_name.str;
388
packet->append_identifier(alias, strlen(alias));
389
packet->append(STRING_WITH_LEN(" (\n"));
391
We need this to get default values from the table
392
We have to restore the read_set if we are called from insert in case
393
of row based replication.
395
old_map= table->use_all_columns(table->read_set);
397
for (ptr=table->field ; (field= *ptr); ptr++)
399
uint32_t flags = field->flags;
401
if (ptr != table->field)
402
packet->append(STRING_WITH_LEN(",\n"));
404
packet->append(STRING_WITH_LEN(" "));
405
packet->append_identifier(field->field_name, strlen(field->field_name));
407
// check for surprises from the previous call to Field::sql_type()
408
if (type.ptr() != tmp)
409
type.set(tmp, sizeof(tmp), system_charset_info);
411
type.set_charset(system_charset_info);
413
field->sql_type(type);
414
packet->append(type.ptr(), type.length(), system_charset_info);
416
if (field->has_charset())
419
For string types dump collation name only if
420
collation is not primary for the given charset
422
if (!(field->charset()->state & MY_CS_PRIMARY))
424
packet->append(STRING_WITH_LEN(" COLLATE "));
425
packet->append(field->charset()->name);
429
if (flags & NOT_NULL_FLAG)
430
packet->append(STRING_WITH_LEN(" NOT NULL"));
431
else if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
434
TIMESTAMP field require explicit NULL flag, because unlike
435
all other fields they are treated as NOT NULL by default.
437
packet->append(STRING_WITH_LEN(" NULL"));
441
Add field flags about FIELD FORMAT (FIXED or DYNAMIC)
442
and about STORAGE (DISK or MEMORY).
444
enum column_format_type column_format= (enum column_format_type)
445
((flags >> COLUMN_FORMAT_FLAGS) & COLUMN_FORMAT_MASK);
448
packet->append(STRING_WITH_LEN(" /*!"));
449
packet->append(STRING_WITH_LEN(" COLUMN_FORMAT"));
450
if (column_format == COLUMN_FORMAT_TYPE_FIXED)
451
packet->append(STRING_WITH_LEN(" FIXED */"));
453
packet->append(STRING_WITH_LEN(" DYNAMIC */"));
456
if (get_field_default_value(table->timestamp_field, field, &def_value, 1))
458
packet->append(STRING_WITH_LEN(" DEFAULT "));
459
packet->append(def_value.ptr(), def_value.length(), system_charset_info);
462
if (table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_DN_FIELD)
463
packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP"));
465
if (field->unireg_check == Field::NEXT_NUMBER)
466
packet->append(STRING_WITH_LEN(" AUTO_INCREMENT"));
468
if (field->comment.length)
470
packet->append(STRING_WITH_LEN(" COMMENT "));
471
append_unescaped(packet, field->comment.str, field->comment.length);
475
key_info= table->key_info;
476
memset(&create_info, 0, sizeof(create_info));
477
/* Allow update_create_info to update row type */
478
create_info.row_type= share->row_type;
479
cursor->update_create_info(&create_info);
480
primary_key= share->primary_key;
482
for (uint32_t i=0 ; i < share->keys ; i++,key_info++)
484
KEY_PART_INFO *key_part= key_info->key_part;
485
bool found_primary=0;
486
packet->append(STRING_WITH_LEN(",\n "));
488
if (i == primary_key && is_primary_key(key_info))
492
No space at end, because a space will be added after where the
493
identifier would go, but that is not added for primary key.
495
packet->append(STRING_WITH_LEN("PRIMARY KEY"));
497
else if (key_info->flags & HA_NOSAME)
498
packet->append(STRING_WITH_LEN("UNIQUE KEY "));
500
packet->append(STRING_WITH_LEN("KEY "));
503
packet->append_identifier(key_info->name, strlen(key_info->name));
505
packet->append(STRING_WITH_LEN(" ("));
507
for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
513
packet->append_identifier(key_part->field->field_name,
514
strlen(key_part->field->field_name));
515
if (key_part->field &&
517
table->field[key_part->fieldnr-1]->key_length()))
520
buff.append(to_string((int32_t) key_part->length /
521
key_part->field->charset()->mbmaxlen));
523
packet->append(buff.c_str(), buff.length());
527
store_key_options(packet, table, key_info);
531
Get possible foreign key definitions stored in InnoDB and append them
532
to the CREATE TABLE statement
535
if ((for_str= cursor->get_foreign_key_create_info()))
537
packet->append(for_str, strlen(for_str));
538
cursor->free_foreign_key_create_info(for_str);
541
packet->append(STRING_WITH_LEN("\n)"));
543
show_table_options= true;
545
Get possible table space definitions and append them
546
to the CREATE TABLE statement
550
We should always store engine since we will now be
551
making sure engines accept options (aka... no
552
dangling arguments for engines.
554
packet->append(STRING_WITH_LEN(" ENGINE="));
555
packet->append(cursor->engine->getName().c_str());
557
if (share->db_create_options & HA_OPTION_PACK_KEYS)
558
packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
559
if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
560
packet->append(STRING_WITH_LEN(" PACK_KEYS=0"));
561
if (create_info.row_type != ROW_TYPE_DEFAULT)
563
packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
564
packet->append(ha_row_type[(uint32_t) create_info.row_type]);
566
if (table->s->hasKeyBlockSize())
568
packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
569
buff= to_string(table->s->getKeyBlockSize());
570
packet->append(buff.c_str(), buff.length());
572
if (share->block_size)
574
packet->append(STRING_WITH_LEN(" BLOCK_SIZE="));
575
buff= to_string(share->block_size);
576
packet->append(buff.c_str(), buff.length());
578
table->cursor->append_create_info(packet);
579
if (share->hasComment() && share->getCommentLength())
581
packet->append(STRING_WITH_LEN(" COMMENT="));
582
append_unescaped(packet, share->getComment(),
583
share->getCommentLength());
586
table->restore_column_map(old_map);
590
static void store_key_options(String *packet, Table *table, KEY *key_info)
594
if (key_info->algorithm == HA_KEY_ALG_BTREE)
595
packet->append(STRING_WITH_LEN(" USING BTREE"));
597
if (key_info->algorithm == HA_KEY_ALG_HASH)
598
packet->append(STRING_WITH_LEN(" USING HASH"));
600
if ((key_info->flags & HA_USES_BLOCK_SIZE) &&
601
table->s->getKeyBlockSize() != key_info->block_size)
603
packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
604
end= internal::int64_t10_to_str(key_info->block_size, buff, 10);
605
packet->append(buff, (uint32_t) (end - buff));
608
assert(test(key_info->flags & HA_USES_COMMENT) ==
609
(key_info->comment.length > 0));
610
if (key_info->flags & HA_USES_COMMENT)
612
packet->append(STRING_WITH_LEN(" COMMENT "));
613
append_unescaped(packet, key_info->comment.str,
614
key_info->comment.length);
619
/****************************************************************************
620
Return info about all processes
621
returns for each thread: thread id, user, host, db, command, info
622
****************************************************************************/
637
thread_info(uint64_t thread_id_arg,
638
time_t start_time_arg,
639
uint32_t command_arg,
640
const string &user_arg,
641
const string &host_arg,
642
const string &db_arg,
643
const string &proc_info_arg,
644
const string &state_info_arg,
645
const string &query_arg)
646
: thread_id(thread_id_arg), start_time(start_time_arg), command(command_arg),
647
user(user_arg), host(host_arg), db(db_arg), proc_info(proc_info_arg),
648
state_info(state_info_arg), query(query_arg)
652
/*****************************************************************************
654
*****************************************************************************/
656
static vector<drizzle_show_var *> all_status_vars;
657
static vector<drizzle_show_var *> com_status_vars;
658
static bool status_vars_inited= 0;
659
static int show_var_cmp(const void *var1, const void *var2)
661
return strcmp(((drizzle_show_var*)var1)->name, ((drizzle_show_var*)var2)->name);
664
class show_var_cmp_functor
667
show_var_cmp_functor() { }
668
inline bool operator()(const drizzle_show_var *var1, const drizzle_show_var *var2) const
670
int val= strcmp(var1->name, var2->name);
675
class show_var_remove_if
678
show_var_remove_if() { }
679
inline bool operator()(const drizzle_show_var *curr) const
681
return (curr->type == SHOW_UNDEF);
685
drizzle_show_var *getFrontOfStatusVars()
687
return all_status_vars.front();
690
drizzle_show_var *getCommandStatusVars()
692
return com_status_vars.front();
696
Adds an array of drizzle_show_var entries to the output of SHOW STATUS
699
add_status_vars(drizzle_show_var *list)
700
list - an array of drizzle_show_var entries to add to all_status_vars
701
the last entry must be {0,0,SHOW_UNDEF}
704
The handling of all_status_vars[] is completely internal, it's allocated
705
automatically when something is added to it, and deleted completely when
706
the last entry is removed.
708
As a special optimization, if add_status_vars() is called before
709
init_status_vars(), it assumes "startup mode" - neither concurrent access
710
to the array nor SHOW STATUS are possible (thus it skips locks and qsort)
712
int add_status_vars(drizzle_show_var *list)
715
if (status_vars_inited)
716
pthread_mutex_lock(&LOCK_status);
718
all_status_vars.insert(all_status_vars.begin(), list++);
719
if (status_vars_inited)
720
sort(all_status_vars.begin(), all_status_vars.end(),
721
show_var_cmp_functor());
722
if (status_vars_inited)
723
pthread_mutex_unlock(&LOCK_status);
727
int add_com_status_vars(drizzle_show_var *list)
732
com_status_vars.insert(com_status_vars.begin(), list++);
733
if (status_vars_inited)
734
sort(com_status_vars.begin(), com_status_vars.end(),
735
show_var_cmp_functor());
741
Make all_status_vars[] usable for SHOW STATUS
744
See add_status_vars(). Before init_status_vars() call, add_status_vars()
745
works in a special fast "startup" mode. Thus init_status_vars()
746
should be called as late as possible but before enabling multi-threading.
748
void init_status_vars()
750
status_vars_inited= 1;
751
sort(all_status_vars.begin(), all_status_vars.end(),
752
show_var_cmp_functor());
753
sort(com_status_vars.begin(), com_status_vars.end(),
754
show_var_cmp_functor());
757
void reset_status_vars()
759
vector<drizzle_show_var *>::iterator p;
761
p= all_status_vars.begin();
762
while (p != all_status_vars.end())
764
/* Note that SHOW_LONG_NOFLUSH variables are not reset */
765
if ((*p)->type == SHOW_LONG)
770
p= com_status_vars.begin();
771
while (p != com_status_vars.end())
773
/* Note that SHOW_LONG_NOFLUSH variables are not reset */
774
if ((*p)->type == SHOW_LONG)
781
catch-all cleanup function, cleans up everything no matter what
784
This function is not strictly required if all add_to_status/
785
remove_status_vars are properly paired, but it's a safety measure that
786
deletes everything from the all_status_vars vector even if some
787
remove_status_vars were forgotten
789
void free_status_vars()
791
all_status_vars.clear();
792
com_status_vars.clear();
796
Removes an array of drizzle_show_var entries from the output of SHOW STATUS
799
remove_status_vars(drizzle_show_var *list)
800
list - an array of drizzle_show_var entries to remove to all_status_vars
801
the last entry must be {0,0,SHOW_UNDEF}
804
there's lots of room for optimizing this, especially in non-sorted mode,
805
but nobody cares - it may be called only in case of failed plugin
806
initialization in the mysqld startup.
809
void remove_status_vars(drizzle_show_var *list)
811
if (status_vars_inited)
813
pthread_mutex_lock(&LOCK_status);
814
drizzle_show_var *all= all_status_vars.front();
815
int a= 0, b= all_status_vars.size(), c= (a+b)/2;
817
for (; list->name; list++)
820
for (a= 0, b= all_status_vars.size(); b-a > 1; c= (a+b)/2)
822
res= show_var_cmp(list, all+c);
831
all[c].type= SHOW_UNDEF;
833
/* removes all the SHOW_UNDEF elements from the vector */
834
all_status_vars.erase(std::remove_if(all_status_vars.begin(),
835
all_status_vars.end(),show_var_remove_if()),
836
all_status_vars.end());
837
pthread_mutex_unlock(&LOCK_status);
841
drizzle_show_var *all= all_status_vars.front();
843
for (; list->name; list++)
845
for (i= 0; i < all_status_vars.size(); i++)
847
if (show_var_cmp(list, all+i))
849
all[i].type= SHOW_UNDEF;
853
/* removes all the SHOW_UNDEF elements from the vector */
854
all_status_vars.erase(std::remove_if(all_status_vars.begin(),
855
all_status_vars.end(),show_var_remove_if()),
856
all_status_vars.end());
860
/* collect status for all running threads */
862
void calc_sum_of_all_status(system_status_var *to)
864
/* Ensure that thread id not killed during loop */
865
pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
867
/* Get global values as base */
868
*to= global_status_var;
870
/* Add to this status from existing threads */
871
for(SessionList::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it )
873
add_to_status(to, &((*it)->status_var));
876
pthread_mutex_unlock(&LOCK_thread_count);
880
146
} /* namespace drizzled */