118
119
return (*str != '\0');
123
bool drizzled_show_create(Session *session, TableList *table_list, bool is_if_not_exists)
126
String buffer(buff, sizeof(buff), system_charset_info);
128
/* Only one table for now, but VIEW can involve several tables */
129
if (session->openTables(table_list))
131
if (session->is_error())
135
Clear all messages with 'error' level status and
136
issue a warning with 'warning' level status in
137
case of invalid view and last error is ER_VIEW_INVALID
139
drizzle_reset_errors(session, true);
140
session->clear_error();
145
if (store_create_info(table_list, &buffer, is_if_not_exists))
148
List<Item> field_list;
150
field_list.push_back(new Item_empty_string("Table",NAME_CHAR_LEN));
151
// 1024 is for not to confuse old clients
152
field_list.push_back(new Item_empty_string("Create Table",
153
max(buffer.length(),(uint32_t)1024)));
156
if (session->client->sendFields(&field_list))
159
session->client->store(table_list->table->alias);
162
session->client->store(buffer.ptr(), buffer.length());
164
if (session->client->flush())
172
Get a CREATE statement for a given database.
174
The database is identified by its name, passed as @c dbname parameter.
175
The name should be encoded using the system character set (UTF8 currently).
177
Resulting statement is stored in the string pointed by @c buffer. The string
178
is emptied first and its character set is set to the system character set.
180
If is_if_not_exists is set, then
181
the resulting CREATE statement contains "IF NOT EXISTS" clause. Other flags
182
in @c create_options are ignored.
184
@param session The current thread instance.
185
@param dbname The name of the database.
186
@param buffer A String instance where the statement is stored.
187
@param create_info If not NULL, the options member influences the resulting
190
@returns true if errors are detected, false otherwise.
193
static bool store_db_create_info(SchemaIdentifier &schema_identifier, string &buffer, bool if_not_exists)
195
message::Schema schema;
197
bool found= plugin::StorageEngine::getSchemaDefinition(schema_identifier, schema);
201
buffer.append("CREATE DATABASE ");
204
buffer.append("IF NOT EXISTS ");
207
buffer.append(schema.name());
210
if (schema.has_collation())
212
buffer.append(" COLLATE = ");
213
buffer.append(schema.collation());
219
bool mysqld_show_create_db(Session &session, SchemaIdentifier &schema_identifier, bool if_not_exists)
221
message::Schema schema_message;
224
if (not plugin::StorageEngine::getSchemaDefinition(schema_identifier, schema_message))
227
This assumes that the only reason for which store_db_create_info()
228
can fail is incorrect database name (which is the case now).
230
my_error(ER_BAD_DB_ERROR, MYF(0), schema_identifier.getSQLPath().c_str());
234
if (not store_db_create_info(schema_identifier, buffer, if_not_exists))
237
This assumes that the only reason for which store_db_create_info()
238
can fail is incorrect database name (which is the case now).
240
my_error(ER_BAD_DB_ERROR, MYF(0), schema_identifier.getSQLPath().c_str());
244
List<Item> field_list;
245
field_list.push_back(new Item_empty_string("Database",NAME_CHAR_LEN));
246
field_list.push_back(new Item_empty_string("Create Database",1024));
248
if (session.client->sendFields(&field_list))
251
session.client->store(schema_message.name());
252
session.client->store(buffer);
254
if (session.client->flush())
122
263
Get the quote character for displaying an identifier.
288
#define LIST_PROCESS_HOST_LEN 64
290
static bool get_field_default_value(Field *timestamp_field,
291
Field *field, String *def_value,
295
bool has_now_default;
298
We are using CURRENT_TIMESTAMP instead of NOW because it is
301
has_now_default= (timestamp_field == field &&
302
field->unireg_check != Field::TIMESTAMP_UN_FIELD);
304
has_default= (field->type() != DRIZZLE_TYPE_BLOB &&
305
!(field->flags & NO_DEFAULT_VALUE_FLAG) &&
306
field->unireg_check != Field::NEXT_NUMBER);
308
def_value->length(0);
312
def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
313
else if (!field->is_null())
314
{ // Not null by default
315
char tmp[MAX_FIELD_WIDTH];
316
String type(tmp, sizeof(tmp), field->charset());
317
field->val_str(&type);
321
uint32_t dummy_errors;
322
/* convert to system_charset_info == utf8 */
323
def_val.copy(type.ptr(), type.length(), field->charset(),
324
system_charset_info, &dummy_errors);
326
append_unescaped(def_value, def_val.ptr(), def_val.length());
328
def_value->append(def_val.ptr(), def_val.length());
331
def_value->append(STRING_WITH_LEN("''"));
333
else if (field->maybe_null() && quoted)
334
def_value->append(STRING_WITH_LEN("NULL")); // Null as default
342
Build a CREATE TABLE statement for a table.
346
table_list A list containing one table to write statement
348
packet Pointer to a string where statement will be
352
Currently always return 0, but might return error code in the
359
int store_create_info(TableList *table_list, String *packet, bool is_if_not_exists)
361
List<Item> field_list;
362
char tmp[MAX_FIELD_WIDTH], *for_str, def_value_buf[MAX_FIELD_WIDTH];
365
String type(tmp, sizeof(tmp), system_charset_info);
366
String def_value(def_value_buf, sizeof(def_value_buf), system_charset_info);
368
uint32_t primary_key;
370
Table *table= table_list->table;
371
Cursor *cursor= table->cursor;
372
HA_CREATE_INFO create_info;
373
my_bitmap_map *old_map;
375
table->restoreRecordAsDefault(); // Get empty record
377
if (table->getShare()->tmp_table)
378
packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
380
packet->append(STRING_WITH_LEN("CREATE TABLE "));
381
if (is_if_not_exists)
382
packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
383
alias= table->getShare()->getTableName();
385
packet->append_identifier(alias, strlen(alias));
386
packet->append(STRING_WITH_LEN(" (\n"));
388
We need this to get default values from the table
389
We have to restore the read_set if we are called from insert in case
390
of row based replication.
392
old_map= table->use_all_columns(table->read_set);
394
for (ptr=table->field ; (field= *ptr); ptr++)
396
uint32_t flags = field->flags;
398
if (ptr != table->field)
399
packet->append(STRING_WITH_LEN(",\n"));
401
packet->append(STRING_WITH_LEN(" "));
402
packet->append_identifier(field->field_name, strlen(field->field_name));
404
// check for surprises from the previous call to Field::sql_type()
405
if (type.ptr() != tmp)
406
type.set(tmp, sizeof(tmp), system_charset_info);
408
type.set_charset(system_charset_info);
410
field->sql_type(type);
411
packet->append(type.ptr(), type.length(), system_charset_info);
413
if (field->has_charset())
416
For string types dump collation name only if
417
collation is not primary for the given charset
419
if (!(field->charset()->state & MY_CS_PRIMARY))
421
packet->append(STRING_WITH_LEN(" COLLATE "));
422
packet->append(field->charset()->name);
426
if (flags & NOT_NULL_FLAG)
427
packet->append(STRING_WITH_LEN(" NOT NULL"));
428
else if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
431
TIMESTAMP field require explicit NULL flag, because unlike
432
all other fields they are treated as NOT NULL by default.
434
packet->append(STRING_WITH_LEN(" NULL"));
438
Add field flags about FIELD FORMAT (FIXED or DYNAMIC)
439
and about STORAGE (DISK or MEMORY).
441
enum column_format_type column_format= (enum column_format_type)
442
((flags >> COLUMN_FORMAT_FLAGS) & COLUMN_FORMAT_MASK);
445
packet->append(STRING_WITH_LEN(" /*!"));
446
packet->append(STRING_WITH_LEN(" COLUMN_FORMAT"));
447
if (column_format == COLUMN_FORMAT_TYPE_FIXED)
448
packet->append(STRING_WITH_LEN(" FIXED */"));
450
packet->append(STRING_WITH_LEN(" DYNAMIC */"));
453
if (get_field_default_value(table->timestamp_field, field, &def_value, 1))
455
packet->append(STRING_WITH_LEN(" DEFAULT "));
456
packet->append(def_value.ptr(), def_value.length(), system_charset_info);
459
if (table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_DN_FIELD)
460
packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP"));
462
if (field->unireg_check == Field::NEXT_NUMBER)
463
packet->append(STRING_WITH_LEN(" AUTO_INCREMENT"));
465
if (field->comment.length)
467
packet->append(STRING_WITH_LEN(" COMMENT "));
468
append_unescaped(packet, field->comment.str, field->comment.length);
472
key_info= table->key_info;
473
memset(&create_info, 0, sizeof(create_info));
474
/* Allow update_create_info to update row type */
475
create_info.row_type= table->getShare()->row_type;
476
cursor->update_create_info(&create_info);
477
primary_key= table->getShare()->primary_key;
479
for (uint32_t i=0 ; i < table->getShare()->keys ; i++,key_info++)
481
KeyPartInfo *key_part= key_info->key_part;
482
bool found_primary=0;
483
packet->append(STRING_WITH_LEN(",\n "));
485
if (i == primary_key && is_primary_key(key_info))
489
No space at end, because a space will be added after where the
490
identifier would go, but that is not added for primary key.
492
packet->append(STRING_WITH_LEN("PRIMARY KEY"));
494
else if (key_info->flags & HA_NOSAME)
495
packet->append(STRING_WITH_LEN("UNIQUE KEY "));
497
packet->append(STRING_WITH_LEN("KEY "));
500
packet->append_identifier(key_info->name, strlen(key_info->name));
502
packet->append(STRING_WITH_LEN(" ("));
504
for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
510
packet->append_identifier(key_part->field->field_name,
511
strlen(key_part->field->field_name));
512
if (key_part->field &&
514
table->field[key_part->fieldnr-1]->key_length()))
517
buff.append(to_string((int32_t) key_part->length /
518
key_part->field->charset()->mbmaxlen));
520
packet->append(buff.c_str(), buff.length());
524
store_key_options(packet, table, key_info);
528
Get possible foreign key definitions stored in InnoDB and append them
529
to the CREATE TABLE statement
532
if ((for_str= cursor->get_foreign_key_create_info()))
534
packet->append(for_str, strlen(for_str));
535
cursor->free_foreign_key_create_info(for_str);
538
packet->append(STRING_WITH_LEN("\n)"));
541
Get possible table space definitions and append them
542
to the CREATE TABLE statement
546
We should always store engine since we will now be
547
making sure engines accept options (aka... no
548
dangling arguments for engines.
550
packet->append(STRING_WITH_LEN(" ENGINE="));
551
packet->append(cursor->getEngine()->getName().c_str());
553
size_t num_engine_options= table->getShare()->getTableProto()->engine().options_size();
554
for (size_t x= 0; x < num_engine_options; ++x)
556
const message::Engine::Option &option= table->getShare()->getTableProto()->engine().options(x);
558
packet->append(option.name().c_str());
560
append_unescaped(packet, option.state().c_str(), option.state().length());
564
if (create_info.row_type != ROW_TYPE_DEFAULT)
566
packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
567
packet->append(ha_row_type[(uint32_t) create_info.row_type]);
570
if (table->getShare()->block_size)
572
packet->append(STRING_WITH_LEN(" BLOCK_SIZE="));
573
buff= to_string(table->getShare()->block_size);
574
packet->append(buff.c_str(), buff.length());
576
table->cursor->append_create_info(packet);
577
if (table->getMutableShare()->hasComment() && table->getMutableShare()->getCommentLength())
579
packet->append(STRING_WITH_LEN(" COMMENT="));
580
append_unescaped(packet, table->getMutableShare()->getComment(),
581
table->getMutableShare()->getCommentLength());
584
table->restore_column_map(old_map);
588
static void store_key_options(String *packet, Table *, KeyInfo *key_info)
590
if (key_info->algorithm == HA_KEY_ALG_BTREE)
591
packet->append(STRING_WITH_LEN(" USING BTREE"));
593
if (key_info->algorithm == HA_KEY_ALG_HASH)
594
packet->append(STRING_WITH_LEN(" USING HASH"));
596
assert(test(key_info->flags & HA_USES_COMMENT) ==
597
(key_info->comment.length > 0));
598
if (key_info->flags & HA_USES_COMMENT)
600
packet->append(STRING_WITH_LEN(" COMMENT "));
601
append_unescaped(packet, key_info->comment.str,
602
key_info->comment.length);
607
/****************************************************************************
608
Return info about all processes
609
returns for each thread: thread id, user, host, db, command, info
610
****************************************************************************/
625
thread_info(uint64_t thread_id_arg,
626
time_t start_time_arg,
627
uint32_t command_arg,
628
const string &user_arg,
629
const string &host_arg,
630
const string &db_arg,
631
const string &proc_info_arg,
632
const string &state_info_arg,
633
const string &query_arg)
634
: thread_id(thread_id_arg), start_time(start_time_arg), command(command_arg),
635
user(user_arg), host(host_arg), db(db_arg), proc_info(proc_info_arg),
636
state_info(state_info_arg), query(query_arg)
640
/*****************************************************************************
642
*****************************************************************************/
644
static vector<drizzle_show_var *> all_status_vars;
645
static bool status_vars_inited= 0;
646
static int show_var_cmp(const void *var1, const void *var2)
648
return strcmp(((drizzle_show_var*)var1)->name, ((drizzle_show_var*)var2)->name);
651
class show_var_cmp_functor
654
show_var_cmp_functor() { }
655
inline bool operator()(const drizzle_show_var *var1, const drizzle_show_var *var2) const
657
int val= strcmp(var1->name, var2->name);
662
class show_var_remove_if
665
show_var_remove_if() { }
666
inline bool operator()(const drizzle_show_var *curr) const
668
return (curr->type == SHOW_UNDEF);
672
drizzle_show_var *getFrontOfStatusVars()
674
return all_status_vars.front();
678
Adds an array of drizzle_show_var entries to the output of SHOW STATUS
681
add_status_vars(drizzle_show_var *list)
682
list - an array of drizzle_show_var entries to add to all_status_vars
683
the last entry must be {0,0,SHOW_UNDEF}
686
The handling of all_status_vars[] is completely internal, it's allocated
687
automatically when something is added to it, and deleted completely when
688
the last entry is removed.
690
As a special optimization, if add_status_vars() is called before
691
init_status_vars(), it assumes "startup mode" - neither concurrent access
692
to the array nor SHOW STATUS are possible (thus it skips locks and qsort)
694
int add_status_vars(drizzle_show_var *list)
697
if (status_vars_inited)
698
pthread_mutex_lock(&LOCK_status);
700
all_status_vars.insert(all_status_vars.begin(), list++);
701
if (status_vars_inited)
702
sort(all_status_vars.begin(), all_status_vars.end(),
703
show_var_cmp_functor());
704
if (status_vars_inited)
705
pthread_mutex_unlock(&LOCK_status);
710
Make all_status_vars[] usable for SHOW STATUS
713
See add_status_vars(). Before init_status_vars() call, add_status_vars()
714
works in a special fast "startup" mode. Thus init_status_vars()
715
should be called as late as possible but before enabling multi-threading.
717
void init_status_vars()
719
status_vars_inited= 1;
720
sort(all_status_vars.begin(), all_status_vars.end(),
721
show_var_cmp_functor());
724
void reset_status_vars()
726
vector<drizzle_show_var *>::iterator p;
728
p= all_status_vars.begin();
729
while (p != all_status_vars.end())
731
/* Note that SHOW_LONG_NOFLUSH variables are not reset */
732
if ((*p)->type == SHOW_LONG)
739
catch-all cleanup function, cleans up everything no matter what
742
This function is not strictly required if all add_to_status/
743
remove_status_vars are properly paired, but it's a safety measure that
744
deletes everything from the all_status_vars vector even if some
745
remove_status_vars were forgotten
747
void free_status_vars()
749
all_status_vars.clear();
753
Removes an array of drizzle_show_var entries from the output of SHOW STATUS
756
remove_status_vars(drizzle_show_var *list)
757
list - an array of drizzle_show_var entries to remove to all_status_vars
758
the last entry must be {0,0,SHOW_UNDEF}
761
there's lots of room for optimizing this, especially in non-sorted mode,
762
but nobody cares - it may be called only in case of failed plugin
763
initialization in the mysqld startup.
766
void remove_status_vars(drizzle_show_var *list)
768
if (status_vars_inited)
770
pthread_mutex_lock(&LOCK_status);
771
drizzle_show_var *all= all_status_vars.front();
772
int a= 0, b= all_status_vars.size(), c= (a+b)/2;
774
for (; list->name; list++)
777
for (a= 0, b= all_status_vars.size(); b-a > 1; c= (a+b)/2)
779
res= show_var_cmp(list, all+c);
788
all[c].type= SHOW_UNDEF;
790
/* removes all the SHOW_UNDEF elements from the vector */
791
all_status_vars.erase(std::remove_if(all_status_vars.begin(),
792
all_status_vars.end(),show_var_remove_if()),
793
all_status_vars.end());
794
pthread_mutex_unlock(&LOCK_status);
798
drizzle_show_var *all= all_status_vars.front();
800
for (; list->name; list++)
802
for (i= 0; i < all_status_vars.size(); i++)
804
if (show_var_cmp(list, all+i))
806
all[i].type= SHOW_UNDEF;
810
/* removes all the SHOW_UNDEF elements from the vector */
811
all_status_vars.erase(std::remove_if(all_status_vars.begin(),
812
all_status_vars.end(),show_var_remove_if()),
813
all_status_vars.end());
817
/* collect status for all running threads */
819
void calc_sum_of_all_status(system_status_var *to)
821
/* Ensure that thread id not killed during loop */
822
pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
824
/* Get global values as base */
825
*to= global_status_var;
827
/* Add to this status from existing threads */
828
for(SessionList::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it )
830
add_to_status(to, &((*it)->status_var));
833
pthread_mutex_unlock(&LOCK_thread_count);
146
837
} /* namespace drizzled */