| 1 | /* Copyright (c) 2005, 2011, 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 |
| 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
| 15 | |
| 16 | #include <stdlib.h> |
| 17 | #include <ctype.h> |
| 18 | #include <mysql/plugin.h> |
| 19 | |
| 20 | #if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8) |
| 21 | #define __attribute__(A) |
| 22 | #endif |
| 23 | |
| 24 | static long number_of_calls= 0; /* for SHOW STATUS, see below */ |
| 25 | |
| 26 | /* |
| 27 | Simple full-text parser plugin that acts as a replacement for the |
| 28 | built-in full-text parser: |
| 29 | - All non-whitespace characters are significant and are interpreted as |
| 30 | "word characters." |
| 31 | - Whitespace characters are space, tab, CR, LF. |
| 32 | - There is no minimum word length. Non-whitespace sequences of one |
| 33 | character or longer are words. |
| 34 | - Stopwords are used in non-boolean mode, not used in boolean mode. |
| 35 | */ |
| 36 | |
| 37 | /* |
| 38 | simple_parser interface functions: |
| 39 | |
| 40 | Plugin declaration functions: |
| 41 | - simple_parser_plugin_init() |
| 42 | - simple_parser_plugin_deinit() |
| 43 | |
| 44 | Parser descriptor functions: |
| 45 | - simple_parser_parse() |
| 46 | - simple_parser_init() |
| 47 | - simple_parser_deinit() |
| 48 | */ |
| 49 | |
| 50 | |
| 51 | /* |
| 52 | Initialize the parser plugin at server start or plugin installation. |
| 53 | |
| 54 | SYNOPSIS |
| 55 | simple_parser_plugin_init() |
| 56 | |
| 57 | DESCRIPTION |
| 58 | Does nothing. |
| 59 | |
| 60 | RETURN VALUE |
| 61 | 0 success |
| 62 | 1 failure (cannot happen) |
| 63 | */ |
| 64 | |
| 65 | static int simple_parser_plugin_init(void *arg __attribute__((unused))) |
| 66 | { |
| 67 | return(0); |
| 68 | } |
| 69 | |
| 70 | |
| 71 | /* |
| 72 | Terminate the parser plugin at server shutdown or plugin deinstallation. |
| 73 | |
| 74 | SYNOPSIS |
| 75 | simple_parser_plugin_deinit() |
| 76 | Does nothing. |
| 77 | |
| 78 | RETURN VALUE |
| 79 | 0 success |
| 80 | 1 failure (cannot happen) |
| 81 | |
| 82 | */ |
| 83 | |
| 84 | static int simple_parser_plugin_deinit(void *arg __attribute__((unused))) |
| 85 | { |
| 86 | return(0); |
| 87 | } |
| 88 | |
| 89 | |
| 90 | /* |
| 91 | Initialize the parser on the first use in the query |
| 92 | |
| 93 | SYNOPSIS |
| 94 | simple_parser_init() |
| 95 | |
| 96 | DESCRIPTION |
| 97 | Does nothing. |
| 98 | |
| 99 | RETURN VALUE |
| 100 | 0 success |
| 101 | 1 failure (cannot happen) |
| 102 | */ |
| 103 | |
| 104 | static int simple_parser_init(MYSQL_FTPARSER_PARAM *param |
| 105 | __attribute__((unused))) |
| 106 | { |
| 107 | return(0); |
| 108 | } |
| 109 | |
| 110 | |
| 111 | /* |
| 112 | Terminate the parser at the end of the query |
| 113 | |
| 114 | SYNOPSIS |
| 115 | simple_parser_deinit() |
| 116 | |
| 117 | DESCRIPTION |
| 118 | Does nothing. |
| 119 | |
| 120 | RETURN VALUE |
| 121 | 0 success |
| 122 | 1 failure (cannot happen) |
| 123 | */ |
| 124 | |
| 125 | static int simple_parser_deinit(MYSQL_FTPARSER_PARAM *param |
| 126 | __attribute__((unused))) |
| 127 | { |
| 128 | return(0); |
| 129 | } |
| 130 | |
| 131 | |
| 132 | /* |
| 133 | Pass a word back to the server. |
| 134 | |
| 135 | SYNOPSIS |
| 136 | add_word() |
| 137 | param parsing context of the plugin |
| 138 | word a word |
| 139 | len word length |
| 140 | |
| 141 | DESCRIPTION |
| 142 | Fill in boolean metadata for the word (if parsing in boolean mode) |
| 143 | and pass the word to the server. The server adds the word to |
| 144 | a full-text index when parsing for indexing, or adds the word to |
| 145 | the list of search terms when parsing a search string. |
| 146 | */ |
| 147 | |
| 148 | static void add_word(MYSQL_FTPARSER_PARAM *param, const char *word, size_t len) |
| 149 | { |
| 150 | MYSQL_FTPARSER_BOOLEAN_INFO bool_info= |
| 151 | { FT_TOKEN_WORD, 0, 0, 0, 0, ' ', 0 }; |
| 152 | |
| 153 | param->mysql_add_word(param, word, (int)len, &bool_info); |
| 154 | } |
| 155 | |
| 156 | /* |
| 157 | Parse a document or a search query. |
| 158 | |
| 159 | SYNOPSIS |
| 160 | simple_parser_parse() |
| 161 | param parsing context |
| 162 | |
| 163 | DESCRIPTION |
| 164 | This is the main plugin function which is called to parse |
| 165 | a document or a search query. The call mode is set in |
| 166 | param->mode. This function simply splits the text into words |
| 167 | and passes every word to the MySQL full-text indexing engine. |
| 168 | */ |
| 169 | |
| 170 | static int simple_parser_parse(MYSQL_FTPARSER_PARAM *param) |
| 171 | { |
| 172 | const char *end, *start, *docend= param->doc + param->length; |
| 173 | |
| 174 | number_of_calls++; |
| 175 | |
| 176 | for (end= start= param->doc;; end++) |
| 177 | { |
| 178 | if (end == docend) |
| 179 | { |
| 180 | if (end > start) |
| 181 | add_word(param, start, end - start); |
| 182 | break; |
| 183 | } |
| 184 | else if (isspace(*end)) |
| 185 | { |
| 186 | if (end > start) |
| 187 | add_word(param, start, end - start); |
| 188 | start= end + 1; |
| 189 | } |
| 190 | } |
| 191 | return(0); |
| 192 | } |
| 193 | |
| 194 | |
| 195 | /* |
| 196 | Plugin type-specific descriptor |
| 197 | */ |
| 198 | |
| 199 | static struct st_mysql_ftparser simple_parser_descriptor= |
| 200 | { |
| 201 | MYSQL_FTPARSER_INTERFACE_VERSION, /* interface version */ |
| 202 | simple_parser_parse, /* parsing function */ |
| 203 | simple_parser_init, /* parser init function */ |
| 204 | simple_parser_deinit /* parser deinit function */ |
| 205 | }; |
| 206 | |
| 207 | /* |
| 208 | Plugin status variables for SHOW STATUS |
| 209 | */ |
| 210 | |
| 211 | static struct st_mysql_show_var simple_status[]= |
| 212 | { |
| 213 | {"A_static" , (char *)"just a static text" , SHOW_CHAR}, |
| 214 | {"called" , (char *)&number_of_calls, SHOW_LONG}, |
| 215 | {0,0,0} |
| 216 | }; |
| 217 | |
| 218 | /* |
| 219 | Plugin system variables. |
| 220 | */ |
| 221 | |
| 222 | static long sysvar_one_value; |
| 223 | static char *sysvar_two_value; |
| 224 | |
| 225 | static MYSQL_SYSVAR_LONG(simple_sysvar_one, sysvar_one_value, |
| 226 | PLUGIN_VAR_RQCMDARG, |
| 227 | "Simple fulltext parser example system variable number one. Give a number." , |
| 228 | NULL, NULL, 77L, 7L, 777L, 0); |
| 229 | |
| 230 | static MYSQL_SYSVAR_STR(simple_sysvar_two, sysvar_two_value, |
| 231 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, |
| 232 | "Simple fulltext parser example system variable number two. Give a string." , |
| 233 | NULL, NULL, "simple sysvar two default" ); |
| 234 | |
| 235 | static MYSQL_THDVAR_LONG(simple_thdvar_one, |
| 236 | PLUGIN_VAR_RQCMDARG, |
| 237 | "Simple fulltext parser example thread variable number one. Give a number." , |
| 238 | NULL, NULL, 88L, 8L, 888L, 0); |
| 239 | |
| 240 | static MYSQL_THDVAR_STR(simple_thdvar_two, |
| 241 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, |
| 242 | "Simple fulltext parser example thread variable number two. Give a string." , |
| 243 | NULL, NULL, "simple thdvar two default" ); |
| 244 | |
| 245 | static struct st_mysql_sys_var* simple_system_variables[]= { |
| 246 | MYSQL_SYSVAR(simple_sysvar_one), |
| 247 | MYSQL_SYSVAR(simple_sysvar_two), |
| 248 | MYSQL_SYSVAR(simple_thdvar_one), |
| 249 | MYSQL_SYSVAR(simple_thdvar_two), |
| 250 | NULL |
| 251 | }; |
| 252 | |
| 253 | /* |
| 254 | Plugin library descriptor |
| 255 | */ |
| 256 | |
| 257 | maria_declare_plugin(ftexample) |
| 258 | { |
| 259 | MYSQL_FTPARSER_PLUGIN, /* type */ |
| 260 | &simple_parser_descriptor, /* descriptor */ |
| 261 | "simple_parser" , /* name */ |
| 262 | "Sergei Golubchik" , /* author */ |
| 263 | "Simple Full-Text Parser" , /* description */ |
| 264 | PLUGIN_LICENSE_GPL, |
| 265 | simple_parser_plugin_init, /* init function (when loaded) */ |
| 266 | simple_parser_plugin_deinit,/* deinit function (when unloaded) */ |
| 267 | 0x0001, /* version */ |
| 268 | simple_status, /* status variables */ |
| 269 | simple_system_variables, /* system variables */ |
| 270 | "0.01" , /* string version */ |
| 271 | MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */ |
| 272 | } |
| 273 | maria_declare_plugin_end; |
| 274 | |