1
/* Copyright (C) 2004 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
24
TOK_ERROR, /* Encodes the "ERROR" word, it doesn't indicate error. */
39
TOK_NOT_FOUND, // must be after all tokens
51
static struct tokens_st tokens[]= {
71
/************************************************************************/
73
Named_value_arr::Named_value_arr() :
79
bool Named_value_arr::init()
81
if (my_init_dynamic_array(&arr, sizeof(Named_value), 0, 32))
90
Named_value_arr::~Named_value_arr()
95
for (int i= 0; i < get_size(); ++i)
96
get_element(i).free();
101
/************************************************************************/
104
Returns token no if word corresponds to some token, otherwise returns
108
inline Token find_token(const char *word, size_t word_len)
113
if (my_strnncoll(default_charset_info, (const uchar *) tokens[i].tok_name,
114
tokens[i].length, (const uchar *) word, word_len) == 0)
117
while (++i < TOK_NOT_FOUND);
122
Token get_token(const char **text, size_t *word_len)
124
get_word(text, word_len);
126
return find_token(*text, *word_len);
131
Token shift_token(const char **text, size_t *word_len)
133
Token save= get_token(text, word_len);
139
int get_text_id(const char **text, LEX_STRING *token)
141
get_word(text, &token->length);
142
if (token->length == 0)
144
token->str= (char *) *text;
149
static bool parse_long(const LEX_STRING *token, long *value)
152
char *end_ptr= token->str + token->length;
154
*value= (long)my_strtoll10(token->str, &end_ptr, &err_code);
156
return err_code != 0;
160
bool parse_option_value(const char *text, size_t *text_len, char **value)
162
char beginning_quote;
163
const char *text_start_ptr;
165
bool escape_mode= FALSE;
167
if (!*text || (*text != '\'' && *text != '"'))
168
return TRUE; /* syntax error: string expected. */
170
beginning_quote= *text;
172
++text; /* skip the beginning quote. */
174
text_start_ptr= text;
176
if (!(v= Named_value::alloc_str(text)))
185
Named_value::free_str(value);
186
return TRUE; /* syntax error: missing terminating ' character. */
189
if (*text == '\n' || *text == '\r')
191
Named_value::free_str(value);
192
return TRUE; /* syntax error: option value should be a single line. */
195
if (!escape_mode && *text == beginning_quote)
202
case 'b': /* \b -- backspace */
207
case 't': /* \t -- tab */
212
case 'n': /* \n -- newline */
217
case 'r': /* \r -- carriage return */
222
case '\\': /* \\ -- back slash */
227
case 's': /* \s -- space */
232
default: /* Unknown escape sequence. Treat as error. */
233
Named_value::free_str(value);
257
/* "2" below stands for beginning and ending quotes. */
258
*text_len= text - text_start_ptr + 2;
264
void skip_spaces(const char **text)
266
while (**text && my_isspace(default_charset_info, **text))
271
Command *parse_command(const char *text)
274
LEX_STRING instance_name;
277
Token tok1= shift_token(&text, &word_len);
280
case TOK_START: // fallthrough
284
if (shift_token(&text, &word_len) != TOK_INSTANCE)
286
get_word(&text, &word_len);
289
instance_name.str= (char *) text;
290
instance_name.length= word_len;
293
if (tok1 == TOK_CREATE)
295
Create_instance *cmd= new Create_instance(&instance_name);
298
return NULL; /* Report ER_OUT_OF_RESOURCES. */
300
if (cmd->init(&text))
310
/* it should be the end of command */
311
get_word(&text, &word_len, NONSPACE);
318
command= new Start_instance(&instance_name);
321
command= new Stop_instance(&instance_name);
324
; /* command already initialized. */
327
command= new Drop_instance(&instance_name);
329
default: /* this is impossible, but nevertheless... */
334
if (shift_token(&text, &word_len) != TOK_INSTANCES)
337
get_word(&text, &word_len, NONSPACE);
341
command= new Flush_instances();
346
Abstract_option_cmd *cmd;
349
cmd= new Set_option();
351
cmd= new Unset_option();
354
return NULL; /* Report ER_OUT_OF_RESOURCES. */
356
if (cmd->init(&text))
367
switch (shift_token(&text, &word_len)) {
369
get_word(&text, &word_len, NONSPACE);
372
command= new Show_instances();
375
switch (Token tok2= shift_token(&text, &word_len)) {
378
if (get_text_id(&text, &instance_name))
380
text+= instance_name.length;
381
/* check that this is the end of the command */
382
get_word(&text, &word_len, NONSPACE);
385
if (tok2 == TOK_STATUS)
386
command= new Show_instance_status(&instance_name);
388
command= new Show_instance_options(&instance_name);
395
instance_name.str= (char *) text - word_len;
396
instance_name.length= word_len;
397
if (instance_name.length)
402
LEX_STRING log_size_str;
405
LEX_STRING log_offset_str= { NULL, 0 };
407
switch (shift_token(&text, &word_len)) {
409
switch (Token tok3= shift_token(&text, &word_len)) {
411
get_word(&text, &word_len, NONSPACE);
412
/* check that this is the end of the command */
415
command= new Show_instance_log_files(&instance_name);
420
/* define a log type */
423
log_type= IM_LOG_ERROR;
426
log_type= IM_LOG_GENERAL;
429
log_type= IM_LOG_SLOW;
434
/* get the size of the log we want to retrieve */
435
if (get_text_id(&text, &log_size_str))
437
text+= log_size_str.length;
439
/* this parameter is required */
440
if (!log_size_str.length)
443
/* the next token should be comma, or nothing */
444
get_word(&text, &word_len);
447
text++; /* swallow the comma */
448
/* read the next word */
449
get_word(&text, &word_len);
452
log_offset_str.str= (char *) text;
453
log_offset_str.length= word_len;
455
get_word(&text, &word_len, NONSPACE);
456
/* check that this is the end of the command */
461
break; /* this is ok */
466
/* Parse size parameter. */
468
if (parse_long(&log_size_str, &log_size))
474
/* Parse offset parameter (if specified). */
476
if (log_offset_str.length)
478
if (parse_long(&log_offset_str, &log_offset))
485
command= new Show_instance_log(&instance_name,
486
log_type, log_size, log_offset);
503
command= new Syntax_error();
506
DBUG_ASSERT(command);