118
120
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())
122
264
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
my_bitmap_map *old_map;
377
table->restoreRecordAsDefault(); // Get empty record
379
if (share->tmp_table)
380
packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
382
packet->append(STRING_WITH_LEN("CREATE TABLE "));
383
if (is_if_not_exists)
384
packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
385
alias= share->getTableName();
387
packet->append_identifier(alias, strlen(alias));
388
packet->append(STRING_WITH_LEN(" (\n"));
390
We need this to get default values from the table
391
We have to restore the read_set if we are called from insert in case
392
of row based replication.
394
old_map= table->use_all_columns(table->read_set);
396
for (ptr=table->field ; (field= *ptr); ptr++)
398
uint32_t flags = field->flags;
400
if (ptr != table->field)
401
packet->append(STRING_WITH_LEN(",\n"));
403
packet->append(STRING_WITH_LEN(" "));
404
packet->append_identifier(field->field_name, strlen(field->field_name));
406
// check for surprises from the previous call to Field::sql_type()
407
if (type.ptr() != tmp)
408
type.set(tmp, sizeof(tmp), system_charset_info);
410
type.set_charset(system_charset_info);
412
field->sql_type(type);
413
packet->append(type.ptr(), type.length(), system_charset_info);
415
if (field->has_charset())
418
For string types dump collation name only if
419
collation is not primary for the given charset
421
if (!(field->charset()->state & MY_CS_PRIMARY))
423
packet->append(STRING_WITH_LEN(" COLLATE "));
424
packet->append(field->charset()->name);
428
if (flags & NOT_NULL_FLAG)
429
packet->append(STRING_WITH_LEN(" NOT NULL"));
430
else if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
433
TIMESTAMP field require explicit NULL flag, because unlike
434
all other fields they are treated as NOT NULL by default.
436
packet->append(STRING_WITH_LEN(" NULL"));
440
Add field flags about FIELD FORMAT (FIXED or DYNAMIC)
441
and about STORAGE (DISK or MEMORY).
443
enum column_format_type column_format= (enum column_format_type)
444
((flags >> COLUMN_FORMAT_FLAGS) & COLUMN_FORMAT_MASK);
447
packet->append(STRING_WITH_LEN(" /*!"));
448
packet->append(STRING_WITH_LEN(" COLUMN_FORMAT"));
449
if (column_format == COLUMN_FORMAT_TYPE_FIXED)
450
packet->append(STRING_WITH_LEN(" FIXED */"));
452
packet->append(STRING_WITH_LEN(" DYNAMIC */"));
455
if (get_field_default_value(table->timestamp_field, field, &def_value, 1))
457
packet->append(STRING_WITH_LEN(" DEFAULT "));
458
packet->append(def_value.ptr(), def_value.length(), system_charset_info);
461
if (table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_DN_FIELD)
462
packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP"));
464
if (field->unireg_check == Field::NEXT_NUMBER)
465
packet->append(STRING_WITH_LEN(" AUTO_INCREMENT"));
467
if (field->comment.length)
469
packet->append(STRING_WITH_LEN(" COMMENT "));
470
append_unescaped(packet, field->comment.str, field->comment.length);
474
key_info= table->key_info;
475
memset(&create_info, 0, sizeof(create_info));
476
/* Allow update_create_info to update row type */
477
create_info.row_type= share->row_type;
478
cursor->update_create_info(&create_info);
479
primary_key= share->primary_key;
481
for (uint32_t i=0 ; i < share->keys ; i++,key_info++)
483
KeyPartInfo *key_part= key_info->key_part;
484
bool found_primary=0;
485
packet->append(STRING_WITH_LEN(",\n "));
487
if (i == primary_key && is_primary_key(key_info))
491
No space at end, because a space will be added after where the
492
identifier would go, but that is not added for primary key.
494
packet->append(STRING_WITH_LEN("PRIMARY KEY"));
496
else if (key_info->flags & HA_NOSAME)
497
packet->append(STRING_WITH_LEN("UNIQUE KEY "));
499
packet->append(STRING_WITH_LEN("KEY "));
502
packet->append_identifier(key_info->name, strlen(key_info->name));
504
packet->append(STRING_WITH_LEN(" ("));
506
for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
512
packet->append_identifier(key_part->field->field_name,
513
strlen(key_part->field->field_name));
514
if (key_part->field &&
516
table->field[key_part->fieldnr-1]->key_length()))
519
buff.append(to_string((int32_t) key_part->length /
520
key_part->field->charset()->mbmaxlen));
522
packet->append(buff.c_str(), buff.length());
526
store_key_options(packet, table, key_info);
530
Get possible foreign key definitions stored in InnoDB and append them
531
to the CREATE TABLE statement
534
if ((for_str= cursor->get_foreign_key_create_info()))
536
packet->append(for_str, strlen(for_str));
537
cursor->free_foreign_key_create_info(for_str);
540
packet->append(STRING_WITH_LEN("\n)"));
543
Get possible table space definitions and append them
544
to the CREATE TABLE statement
548
We should always store engine since we will now be
549
making sure engines accept options (aka... no
550
dangling arguments for engines.
552
packet->append(STRING_WITH_LEN(" ENGINE="));
553
packet->append(cursor->getEngine()->getName().c_str());
555
size_t num_engine_options= share->getTableProto()->engine().options_size();
556
for (size_t x= 0; x < num_engine_options; ++x)
558
const message::Engine::Option &option= share->getTableProto()->engine().options(x);
560
packet->append(option.name().c_str());
562
append_unescaped(packet, option.state().c_str(), option.state().length());
566
if (create_info.row_type != ROW_TYPE_DEFAULT)
568
packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
569
packet->append(ha_row_type[(uint32_t) create_info.row_type]);
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 *, KeyInfo *key_info)
592
if (key_info->algorithm == HA_KEY_ALG_BTREE)
593
packet->append(STRING_WITH_LEN(" USING BTREE"));
595
if (key_info->algorithm == HA_KEY_ALG_HASH)
596
packet->append(STRING_WITH_LEN(" USING HASH"));
598
assert(test(key_info->flags & HA_USES_COMMENT) ==
599
(key_info->comment.length > 0));
600
if (key_info->flags & HA_USES_COMMENT)
602
packet->append(STRING_WITH_LEN(" COMMENT "));
603
append_unescaped(packet, key_info->comment.str,
604
key_info->comment.length);
609
/****************************************************************************
610
Return info about all processes
611
returns for each thread: thread id, user, host, db, command, info
612
****************************************************************************/
627
thread_info(uint64_t thread_id_arg,
628
time_t start_time_arg,
629
uint32_t command_arg,
630
const string &user_arg,
631
const string &host_arg,
632
const string &db_arg,
633
const string &proc_info_arg,
634
const string &state_info_arg,
635
const string &query_arg)
636
: thread_id(thread_id_arg), start_time(start_time_arg), command(command_arg),
637
user(user_arg), host(host_arg), db(db_arg), proc_info(proc_info_arg),
638
state_info(state_info_arg), query(query_arg)
642
/*****************************************************************************
644
*****************************************************************************/
646
static vector<drizzle_show_var *> all_status_vars;
647
static bool status_vars_inited= 0;
648
static int show_var_cmp(const void *var1, const void *var2)
650
return strcmp(((drizzle_show_var*)var1)->name, ((drizzle_show_var*)var2)->name);
653
class show_var_cmp_functor
656
show_var_cmp_functor() { }
657
inline bool operator()(const drizzle_show_var *var1, const drizzle_show_var *var2) const
659
int val= strcmp(var1->name, var2->name);
664
class show_var_remove_if
667
show_var_remove_if() { }
668
inline bool operator()(const drizzle_show_var *curr) const
670
return (curr->type == SHOW_UNDEF);
674
drizzle_show_var *getFrontOfStatusVars()
676
return all_status_vars.front();
680
Adds an array of drizzle_show_var entries to the output of SHOW STATUS
683
add_status_vars(drizzle_show_var *list)
684
list - an array of drizzle_show_var entries to add to all_status_vars
685
the last entry must be {0,0,SHOW_UNDEF}
688
The handling of all_status_vars[] is completely internal, it's allocated
689
automatically when something is added to it, and deleted completely when
690
the last entry is removed.
692
As a special optimization, if add_status_vars() is called before
693
init_status_vars(), it assumes "startup mode" - neither concurrent access
694
to the array nor SHOW STATUS are possible (thus it skips locks and qsort)
696
int add_status_vars(drizzle_show_var *list)
699
if (status_vars_inited)
700
pthread_mutex_lock(&LOCK_status);
702
all_status_vars.insert(all_status_vars.begin(), list++);
703
if (status_vars_inited)
704
sort(all_status_vars.begin(), all_status_vars.end(),
705
show_var_cmp_functor());
706
if (status_vars_inited)
707
pthread_mutex_unlock(&LOCK_status);
712
Make all_status_vars[] usable for SHOW STATUS
715
See add_status_vars(). Before init_status_vars() call, add_status_vars()
716
works in a special fast "startup" mode. Thus init_status_vars()
717
should be called as late as possible but before enabling multi-threading.
719
void init_status_vars()
721
status_vars_inited= 1;
722
sort(all_status_vars.begin(), all_status_vars.end(),
723
show_var_cmp_functor());
726
void reset_status_vars()
728
vector<drizzle_show_var *>::iterator p;
730
p= all_status_vars.begin();
731
while (p != all_status_vars.end())
733
/* Note that SHOW_LONG_NOFLUSH variables are not reset */
734
if ((*p)->type == SHOW_LONG)
741
catch-all cleanup function, cleans up everything no matter what
744
This function is not strictly required if all add_to_status/
745
remove_status_vars are properly paired, but it's a safety measure that
746
deletes everything from the all_status_vars vector even if some
747
remove_status_vars were forgotten
749
void free_status_vars()
751
all_status_vars.clear();
755
Removes an array of drizzle_show_var entries from the output of SHOW STATUS
758
remove_status_vars(drizzle_show_var *list)
759
list - an array of drizzle_show_var entries to remove to all_status_vars
760
the last entry must be {0,0,SHOW_UNDEF}
763
there's lots of room for optimizing this, especially in non-sorted mode,
764
but nobody cares - it may be called only in case of failed plugin
765
initialization in the mysqld startup.
768
void remove_status_vars(drizzle_show_var *list)
770
if (status_vars_inited)
772
pthread_mutex_lock(&LOCK_status);
773
drizzle_show_var *all= all_status_vars.front();
774
int a= 0, b= all_status_vars.size(), c= (a+b)/2;
776
for (; list->name; list++)
779
for (a= 0, b= all_status_vars.size(); b-a > 1; c= (a+b)/2)
781
res= show_var_cmp(list, all+c);
790
all[c].type= SHOW_UNDEF;
792
/* removes all the SHOW_UNDEF elements from the vector */
793
all_status_vars.erase(std::remove_if(all_status_vars.begin(),
794
all_status_vars.end(),show_var_remove_if()),
795
all_status_vars.end());
796
pthread_mutex_unlock(&LOCK_status);
800
drizzle_show_var *all= all_status_vars.front();
802
for (; list->name; list++)
804
for (i= 0; i < all_status_vars.size(); i++)
806
if (show_var_cmp(list, all+i))
808
all[i].type= SHOW_UNDEF;
812
/* removes all the SHOW_UNDEF elements from the vector */
813
all_status_vars.erase(std::remove_if(all_status_vars.begin(),
814
all_status_vars.end(),show_var_remove_if()),
815
all_status_vars.end());
819
/* collect status for all running threads */
821
void calc_sum_of_all_status(system_status_var *to)
823
/* Ensure that thread id not killed during loop */
824
pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
826
/* Get global values as base */
827
*to= global_status_var;
829
/* Add to this status from existing threads */
830
for(SessionList::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it )
832
add_to_status(to, &((*it)->status_var));
835
pthread_mutex_unlock(&LOCK_thread_count);
146
839
} /* namespace drizzled */