Drizzled Public API Documentation

table_function.cc
1 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3  *
4  * Copyright (C) 2010 Monty Taylor
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #include <config.h>
21 
22 #include <drizzled/current_session.h>
23 #include <drizzled/gettext.h>
24 #include <drizzled/charset.h>
25 #include <drizzled/plugin/table_function.h>
26 #include <drizzled/session.h>
27 #include <drizzled/show.h>
28 #include <drizzled/table_function_container.h>
29 #include <drizzled/sql_lex.h>
30 #include <drizzled/internal/my_sys.h>
31 
32 #include <vector>
33 
34 namespace drizzled {
35 
36 static int wild_case_compare(const charset_info_st * const cs, const char *str, const char *wildstr)
37 {
38  int flag;
39 
40  while (*wildstr)
41  {
42  while (*wildstr && *wildstr != internal::wild_many && *wildstr != internal::wild_one)
43  {
44  if (*wildstr == internal::wild_prefix && wildstr[1])
45  {
46  wildstr++;
47  }
48 
49  if (cs->toupper(*wildstr++) != cs->toupper(*str++))
50  {
51  return (1);
52  }
53  }
54 
55  if (! *wildstr )
56  return (*str != 0);
57 
58  if (*wildstr++ == internal::wild_one)
59  {
60  if (! *str++)
61  {
62  return (1); /* One char; skip */
63  }
64  }
65  else
66  { /* Found '*' */
67  if (! *wildstr)
68  {
69  return (0); /* '*' as last char: OK */
70  }
71 
72  flag=(*wildstr != internal::wild_many && *wildstr != internal::wild_one);
73  do
74  {
75  if (flag)
76  {
77  char cmp;
78  if ((cmp= *wildstr) == internal::wild_prefix && wildstr[1])
79  {
80  cmp= wildstr[1];
81  }
82 
83  cmp= cs->toupper(cmp);
84 
85  while (*str && cs->toupper(*str) != cmp)
86  {
87  str++;
88  }
89 
90  if (! *str)
91  {
92  return (1);
93  }
94  }
95 
96  if (wild_case_compare(cs, str, wildstr) == 0)
97  {
98  return (0);
99  }
100 
101  } while (*str++);
102 
103  return (1);
104  }
105  }
106 
107  return (*str != '\0');
108 }
109 
110 static TableFunctionContainer table_functions;
111 
112 void plugin::TableFunction::init()
113 {
114  drizzled::message::table::init(proto, getTableLabel(), identifier.getSchemaName(), "FunctionEngine");
115  proto.set_type(drizzled::message::Table::FUNCTION);
116  proto.set_creation_timestamp(0);
117  proto.set_update_timestamp(0);
118  message::set_is_replicated(proto, false);
119  message::set_definer(proto, SYSTEM_USER);
120 }
121 
122 bool plugin::TableFunction::addPlugin(plugin::TableFunction *tool)
123 {
124  assert(tool != NULL);
125  table_functions.addFunction(tool);
126  return false;
127 }
128 
129 plugin::TableFunction *plugin::TableFunction::getFunction(const std::string &arg)
130 {
131  return table_functions.getFunction(arg);
132 }
133 
134 void plugin::TableFunction::getNames(const std::string &arg,
135  std::set<std::string> &set_of_names)
136 {
137  table_functions.getNames(arg, set_of_names);
138 }
139 
140 LEX& plugin::TableFunction::Generator::lex()
141 {
142  return getSession().lex();
143 }
144 
145 statement::Statement& plugin::TableFunction::Generator::statement()
146 {
147  return *lex().statement;
148 }
149 
150 plugin::TableFunction::Generator *plugin::TableFunction::generator(Field **arg)
151 {
152  return new Generator(arg);
153 }
154 
155 void plugin::TableFunction::add_field(const char *label,
156  uint32_t field_length)
157 {
158  add_field(label, TableFunction::STRING, field_length);
159 }
160 
161 void plugin::TableFunction::add_field(const char *label,
162  TableFunction::ColumnType type,
163  bool is_default_null)
164 {
165  add_field(label, type, 5, is_default_null);
166 }
167 
168 void plugin::TableFunction::add_field(const char *label,
169  TableFunction::ColumnType type,
170  uint32_t field_length,
171  bool is_default_null)
172 {
176 
177  field= proto.add_field();
178  field->set_name(label);
179 
180  field_options= field->mutable_options();
181  field_constraints= field->mutable_constraints();
182  field_options->set_default_null(is_default_null);
183  field_constraints->set_is_notnull(not is_default_null);
184 
185  switch (type)
186  {
187  case TableFunction::STRING:
188  {
190  if (field_length >= TABLE_FUNCTION_BLOB_SIZE)
191  {
192  field->set_type(drizzled::message::Table::Field::BLOB);
193  string_field_options= field->mutable_string_options();
194  string_field_options->set_collation_id(default_charset_info->number);
195  string_field_options->set_collation(default_charset_info->name);
196  }
197  else
198  {
199  field->set_type(drizzled::message::Table::Field::VARCHAR);
200  string_field_options= field->mutable_string_options();
201  string_field_options->set_length(field_length);
202  }
203  }
204  break;
205  case TableFunction::VARBINARY:
206  {
208  field->set_type(drizzled::message::Table::Field::VARCHAR);
209 
210  string_field_options= field->mutable_string_options();
211  string_field_options->set_length(field_length);
212  string_field_options->set_collation(my_charset_bin.csname);
213  string_field_options->set_collation_id(my_charset_bin.number);
214  }
215  break;
216  case TableFunction::NUMBER:
217  field->set_type(drizzled::message::Table::Field::BIGINT);
218  break;
219  case TableFunction::SIZE:
220  field->set_type(drizzled::message::Table::Field::BIGINT);
221  field_constraints->set_is_unsigned(true);
222  break;
223  case TableFunction::BOOLEAN: // Currently BOOLEAN always has a value
224  field->set_type(drizzled::message::Table::Field::BOOLEAN);
225  field_constraints->set_is_unsigned(true);
226  break;
227  }
228 }
229 
230 plugin::TableFunction::Generator::Generator(Field **arg) :
231  columns(arg),
232  session(current_session)
233 {
234  scs= system_charset_info;
235 }
236 
237 bool plugin::TableFunction::Generator::sub_populate(uint32_t field_size)
238 {
239  columns_iterator= columns;
240  bool ret= populate();
241  if (ret)
242  assert(columns_iterator == columns + field_size);
243  return ret;
244 }
245 
246 void plugin::TableFunction::Generator::push(uint64_t arg)
247 {
248  (*columns_iterator)->store(static_cast<int64_t>(arg), true);
249  (*columns_iterator)->set_notnull();
250  columns_iterator++;
251 }
252 
253 void plugin::TableFunction::Generator::push(int64_t arg)
254 {
255  (*columns_iterator)->store(arg, false);
256  (*columns_iterator)->set_notnull();
257  columns_iterator++;
258 }
259 
260 void plugin::TableFunction::Generator::push(const char *arg, uint32_t length)
261 {
262  assert(columns_iterator);
263  assert(*columns_iterator);
264  if (arg and length == 0)
265  {
266  length= strlen(arg);
267  }
268 
269  if ((*columns_iterator)->char_length() < length)
270  {
271  length= (*columns_iterator)->char_length();
272  }
273 
274  (*columns_iterator)->store(arg, length, scs);
275  (*columns_iterator)->set_notnull();
276  columns_iterator++;
277 }
278 
279 void plugin::TableFunction::Generator::push()
280 {
281  /* Only accept NULLs */
282  assert((*columns_iterator)->maybe_null());
283  (*columns_iterator)->set_null();
284  columns_iterator++;
285 }
286 
287 void plugin::TableFunction::Generator::push(str_ref arg)
288 {
289  push(arg.data(), arg.size());
290 }
291 
292 void plugin::TableFunction::Generator::push(bool arg)
293 {
294  if (arg)
295  {
296  (*columns_iterator)->store("YES", 3, scs);
297  }
298  else
299  {
300  (*columns_iterator)->store("NO", 2, scs);
301  }
302  columns_iterator++;
303 }
304 
305 bool plugin::TableFunction::Generator::isWild(const std::string &predicate)
306 {
307  return lex().wild ? wild_case_compare(system_charset_info, predicate.c_str(), lex().wild->ptr()) : false;
308 }
309 
310 } /* namespace drizzled */