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