1/* Copyright (c) 2010, Oracle and/or its affiliates.
2
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.
6
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.
11
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 Foundation,
14 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
15
16
17#include "mariadb.h"
18#include <ctype.h>
19#include <string.h>
20#include "sql_bootstrap.h"
21
22int read_bootstrap_query(char *query, int *query_length,
23 fgets_input_t input, fgets_fn_t fgets_fn, int *error)
24{
25 char line_buffer[MAX_BOOTSTRAP_LINE_SIZE];
26 const char *line;
27 size_t len;
28 size_t query_len= 0;
29 int fgets_error= 0;
30 *error= 0;
31
32 for ( ; ; )
33 {
34 line= (*fgets_fn)(line_buffer, sizeof(line_buffer), input, &fgets_error);
35
36 if (error)
37 *error= fgets_error;
38
39 if (fgets_error != 0)
40 return READ_BOOTSTRAP_ERROR;
41
42 if (line == NULL)
43 return (query_len == 0) ? READ_BOOTSTRAP_EOF : READ_BOOTSTRAP_ERROR;
44
45 len= strlen(line);
46
47 /*
48 Remove trailing whitespace characters.
49 This assumes:
50 - no multibyte encoded character can be found at the very end of a line,
51 - whitespace characters from the "C" locale only.
52 which is sufficient for the kind of queries found
53 in the bootstrap scripts.
54 */
55 while (len && (isspace(line[len - 1])))
56 len--;
57 /*
58 Cleanly end the string, so we don't have to test len > x
59 all the time before reading line[x], in the code below.
60 */
61 line_buffer[len]= '\0';
62
63 /* Skip blank lines */
64 if (len == 0)
65 continue;
66
67 /* Skip # comments */
68 if (line[0] == '#')
69 continue;
70
71 /* Skip -- comments */
72 if ((line[0] == '-') && (line[1] == '-'))
73 continue;
74
75 /* Skip delimiter, ignored. */
76 if (strncmp(line, "delimiter", 9) == 0)
77 continue;
78
79 /* Append the current line to a multi line query. If the new line will make
80 the query too long, preserve the partial line to provide context for the
81 error message.
82 */
83 if (query_len + len + 1 >= MAX_BOOTSTRAP_QUERY_SIZE)
84 {
85 size_t new_len= MAX_BOOTSTRAP_QUERY_SIZE - query_len - 1;
86 if ((new_len > 0) && (query_len < MAX_BOOTSTRAP_QUERY_SIZE))
87 {
88 memcpy(query + query_len, line, new_len);
89 query_len+= new_len;
90 }
91 query[query_len]= '\0';
92 *query_length= (int)query_len;
93 return READ_BOOTSTRAP_QUERY_SIZE;
94 }
95
96 if (query_len != 0)
97 {
98 /*
99 Append a \n to the current line, if any,
100 to preserve the intended presentation.
101 */
102 query[query_len++]= '\n';
103 }
104 memcpy(query + query_len, line, len);
105 query_len+= len;
106
107 if (line[len - 1] == ';')
108 {
109 /*
110 The last line is terminated by ';'.
111 Return the query found.
112 */
113 query[query_len]= '\0';
114 *query_length= (int)query_len;
115 return READ_BOOTSTRAP_SUCCESS;
116 }
117 }
118}
119
120