2 Copyright (c) 2004-2007 MySQL AB, 2009 Sun Microsystems, Inc.
3 Use is subject to license terms.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 TOK_ERROR
, /* Encodes the "ERROR" word, it doesn't indicate error. */
42 TOK_NOT_FOUND
, // must be after all tokens
54 static struct tokens_st tokens
[]= {
74 /************************************************************************/
76 Named_value_arr::Named_value_arr() :
82 bool Named_value_arr::init()
84 if (my_init_dynamic_array(&arr
, sizeof(Named_value
), 0, 32))
93 Named_value_arr::~Named_value_arr()
98 for (int i
= 0; i
< get_size(); ++i
)
99 get_element(i
).free();
101 delete_dynamic(&arr
);
104 /************************************************************************/
107 Returns token no if word corresponds to some token, otherwise returns
111 inline Token
find_token(const char *word
, size_t word_len
)
116 if (my_strnncoll(default_charset_info
, (const uchar
*) tokens
[i
].tok_name
,
117 tokens
[i
].length
, (const uchar
*) word
, word_len
) == 0)
120 while (++i
< TOK_NOT_FOUND
);
125 Token
get_token(const char **text
, size_t *word_len
)
127 get_word(text
, word_len
);
129 return find_token(*text
, *word_len
);
134 Token
shift_token(const char **text
, size_t *word_len
)
136 Token save
= get_token(text
, word_len
);
142 int get_text_id(const char **text
, LEX_STRING
*token
)
144 get_word(text
, &token
->length
);
145 if (token
->length
== 0)
147 token
->str
= (char *) *text
;
152 static bool parse_long(const LEX_STRING
*token
, long *value
)
155 char *end_ptr
= token
->str
+ token
->length
;
157 *value
= (long)my_strtoll10(token
->str
, &end_ptr
, &err_code
);
159 return err_code
!= 0;
163 bool parse_option_value(const char *text
, size_t *text_len
, char **value
)
165 char beginning_quote
;
166 const char *text_start_ptr
;
168 bool escape_mode
= FALSE
;
170 if (!*text
|| (*text
!= '\'' && *text
!= '"'))
171 return TRUE
; /* syntax error: string expected. */
173 beginning_quote
= *text
;
175 ++text
; /* skip the beginning quote. */
177 text_start_ptr
= text
;
179 if (!(v
= Named_value::alloc_str(text
)))
188 Named_value::free_str(value
);
189 return TRUE
; /* syntax error: missing terminating ' character. */
192 if (*text
== '\n' || *text
== '\r')
194 Named_value::free_str(value
);
195 return TRUE
; /* syntax error: option value should be a single line. */
198 if (!escape_mode
&& *text
== beginning_quote
)
205 case 'b': /* \b -- backspace */
210 case 't': /* \t -- tab */
215 case 'n': /* \n -- newline */
220 case 'r': /* \r -- carriage return */
225 case '\\': /* \\ -- back slash */
230 case 's': /* \s -- space */
235 default: /* Unknown escape sequence. Treat as error. */
236 Named_value::free_str(value
);
260 /* "2" below stands for beginning and ending quotes. */
261 *text_len
= text
- text_start_ptr
+ 2;
267 void skip_spaces(const char **text
)
269 while (**text
&& my_isspace(default_charset_info
, **text
))
274 Command
*parse_command(const char *text
)
277 LEX_STRING instance_name
;
280 Token tok1
= shift_token(&text
, &word_len
);
283 case TOK_START
: // fallthrough
287 if (shift_token(&text
, &word_len
) != TOK_INSTANCE
)
289 get_word(&text
, &word_len
);
292 instance_name
.str
= (char *) text
;
293 instance_name
.length
= word_len
;
296 if (tok1
== TOK_CREATE
)
298 Create_instance
*cmd
= new Create_instance(&instance_name
);
301 return NULL
; /* Report ER_OUT_OF_RESOURCES. */
303 if (cmd
->init(&text
))
313 /* it should be the end of command */
314 get_word(&text
, &word_len
, NONSPACE
);
321 command
= new Start_instance(&instance_name
);
324 command
= new Stop_instance(&instance_name
);
327 ; /* command already initialized. */
330 command
= new Drop_instance(&instance_name
);
332 default: /* this is impossible, but nevertheless... */
337 if (shift_token(&text
, &word_len
) != TOK_INSTANCES
)
340 get_word(&text
, &word_len
, NONSPACE
);
344 command
= new Flush_instances();
349 Abstract_option_cmd
*cmd
;
352 cmd
= new Set_option();
354 cmd
= new Unset_option();
357 return NULL
; /* Report ER_OUT_OF_RESOURCES. */
359 if (cmd
->init(&text
))
370 switch (shift_token(&text
, &word_len
)) {
372 get_word(&text
, &word_len
, NONSPACE
);
375 command
= new Show_instances();
378 switch (Token tok2
= shift_token(&text
, &word_len
)) {
381 if (get_text_id(&text
, &instance_name
))
383 text
+= instance_name
.length
;
384 /* check that this is the end of the command */
385 get_word(&text
, &word_len
, NONSPACE
);
388 if (tok2
== TOK_STATUS
)
389 command
= new Show_instance_status(&instance_name
);
391 command
= new Show_instance_options(&instance_name
);
398 instance_name
.str
= (char *) text
- word_len
;
399 instance_name
.length
= word_len
;
400 if (instance_name
.length
)
405 LEX_STRING log_size_str
;
408 LEX_STRING log_offset_str
= { NULL
, 0 };
410 switch (shift_token(&text
, &word_len
)) {
412 switch (Token tok3
= shift_token(&text
, &word_len
)) {
414 get_word(&text
, &word_len
, NONSPACE
);
415 /* check that this is the end of the command */
418 command
= new Show_instance_log_files(&instance_name
);
423 /* define a log type */
426 log_type
= IM_LOG_ERROR
;
429 log_type
= IM_LOG_GENERAL
;
432 log_type
= IM_LOG_SLOW
;
437 /* get the size of the log we want to retrieve */
438 if (get_text_id(&text
, &log_size_str
))
440 text
+= log_size_str
.length
;
442 /* this parameter is required */
443 if (!log_size_str
.length
)
446 /* the next token should be comma, or nothing */
447 get_word(&text
, &word_len
);
450 text
++; /* swallow the comma */
451 /* read the next word */
452 get_word(&text
, &word_len
);
455 log_offset_str
.str
= (char *) text
;
456 log_offset_str
.length
= word_len
;
458 get_word(&text
, &word_len
, NONSPACE
);
459 /* check that this is the end of the command */
464 break; /* this is ok */
469 /* Parse size parameter. */
471 if (parse_long(&log_size_str
, &log_size
))
477 /* Parse offset parameter (if specified). */
479 if (log_offset_str
.length
)
481 if (parse_long(&log_offset_str
, &log_offset
))
488 command
= new Show_instance_log(&instance_name
,
489 log_type
, log_size
, log_offset
);
506 command
= new Syntax_error();
509 DBUG_ASSERT(command
);