Drizzled Public API Documentation

cursor.cc
1 /* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3  *
4  * Copyright (C) 2009 Sun Microsystems, Inc.
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; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <config.h>
22 
23 #include <plugin/function_engine/cursor.h>
24 #include <drizzled/session.h>
25 #include <drizzled/internal/my_sys.h>
26 #include <drizzled/field/blob.h>
27 #include <drizzled/table.h>
28 #include <drizzled/statistics_variables.h>
29 
30 #include <unistd.h>
31 #include <fcntl.h>
32 
33 #include <string>
34 
35 using namespace std;
36 using namespace drizzled;
37 
38 /*****************************************************************************
39 ** Data Function tables
40 *****************************************************************************/
41 
42 FunctionCursor::FunctionCursor(plugin::StorageEngine &engine_arg,
43  Table &table_arg) :
44  Cursor(engine_arg, table_arg),
45  estimate_of_rows(100), // Completely fabricated, I used to use the value 2.
46  rows_returned(0)
47 {}
48 
49 int FunctionCursor::open(const char *name, int, uint32_t)
50 {
51  tool= static_cast<Function *>(getEngine())->getFunction(name);
52 // assert(tool);
53 
54  row_cache_position= 0;
55 
56  if (not tool)
57  return HA_ERR_NO_SUCH_TABLE;
58 
59  return 0;
60 }
61 
62 int FunctionCursor::close(void)
63 {
64  tool= NULL;
65  wipeCache();
66 
67  return 0;
68 }
69 
71 {
72  rows_returned= 0;
73  generator= tool->generator(getTable()->getFields());
74 
75  return 0;
76 }
77 
78 
79 int FunctionCursor::rnd_next(unsigned char *)
80 {
81  bool more_rows;
82  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
83 
84  /* Fix bug in the debug logic for field */
85  for (Field **field= getTable()->getFields() ; *field ; field++)
86  {
87  (*field)->setWriteSet();
88  }
89 
90  more_rows= generator->sub_populate(getTable()->getShare()->sizeFields());
91 
92  if (more_rows)
93  {
94  return 0;
95  }
96  else
97  {
98  delete generator;
99  generator= NULL;
100  }
101  rows_returned++;
102 
103  return more_rows ? 0 : HA_ERR_END_OF_FILE;
104 }
105 
106 uint32_t FunctionCursor::max_row_length()
107 {
108  uint32_t length= (uint32_t)(getTable()->getRecordLength() + getTable()->sizeFields()*2);
109 
110  uint32_t *ptr, *end;
111  for (ptr= getTable()->getBlobField(), end=ptr + getTable()->sizeBlobFields();
112  ptr != end ;
113  ptr++)
114  {
115  length += 2 + ((Field_blob*)getTable()->getField(*ptr))->get_length();
116  }
117 
118  return length;
119 }
120 
121 unsigned int FunctionCursor::pack_row(const unsigned char *record)
122 {
123  unsigned char *ptr;
124 
125  record_buffer.resize(max_row_length());
126 
127  /* Copy null bits */
128  memcpy(&record_buffer[0], record, getTable()->getShare()->null_bytes);
129  ptr= &record_buffer[0] + getTable()->getShare()->null_bytes;
130 
131  for (Field **field=getTable()->getFields() ; *field ; field++)
132  {
133  if (!((*field)->is_null()))
134  ptr= (*field)->pack(ptr, record + (*field)->offset(record));
135  }
136 
137  return((unsigned int) (ptr - &record_buffer[0]));
138 }
139 
140 void FunctionCursor::position(const unsigned char *record)
141 {
142  uint32_t max_length= max_row_length();
143 
144  if (row_cache.size() <= row_cache_position + max_length)
145  {
146  row_cache.resize(row_cache.size() + max_length);
147  }
148 
149  unsigned int r_pack_length;
150  r_pack_length= pack_row(record);
151  internal::my_store_ptr(ref, ref_length, row_cache_position);
152 
153  memcpy(&row_cache[row_cache_position], &record_buffer[0], r_pack_length);
154  row_cache_position+= r_pack_length;
155 }
156 
157 
158 void FunctionCursor::wipeCache()
159 {
160  if (rows_returned > estimate_of_rows)
161  estimate_of_rows= rows_returned;
162 
163  row_cache.clear();
164  row_cache_position= 0;
165 }
166 
167 int FunctionCursor::extra(enum ha_extra_function operation)
168 {
169  switch (operation)
170  {
171  case drizzled::HA_EXTRA_CACHE:
172  break;
173  case drizzled::HA_EXTRA_NO_CACHE:
174  break;
175  case drizzled::HA_EXTRA_RESET_STATE:
176  wipeCache();
177  break;
178  default:
179  break;
180  }
181 
182  return 0;
183 }
184 
185 int FunctionCursor::doEndTableScan()
186 {
187  delete generator; // Do this in case of an early exit from rnd_next()
188 
189  return 0;
190 }
191 
192 int FunctionCursor::rnd_pos(unsigned char *buf, unsigned char *pos)
193 {
194  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
195  size_t position_id= (size_t)internal::my_get_ptr(pos, ref_length);
196 
197  const unsigned char *ptr;
198  ptr= &row_cache[position_id];
199 
200  /* Copy null bits */
201  memcpy(buf, ptr, getTable()->getNullBytes());
202  ptr+= getTable()->getNullBytes();
203  // and copy fields
204  for (Field **field= getTable()->getFields() ; *field ; field++)
205  {
206  if (!((*field)->is_null()))
207  {
208  ptr= (*field)->unpack(buf + (*field)->offset(getTable()->getInsertRecord()), ptr);
209  }
210  }
211 
212  return 0;
213 }
214 
215 
216 int FunctionCursor::info(uint32_t flag)
217 {
218  memset(&stats, 0, sizeof(stats));
219 
220  if (flag & HA_STATUS_AUTO)
221  stats.auto_increment_value= 1;
222 
223  stats.records= estimate_of_rows;
224 
225  return 0;
226 }