Drizzled Public API Documentation

cursor.cc
00001 /* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2009 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019  */
00020 
00021 #include <config.h>
00022 
00023 #include <plugin/function_engine/cursor.h>
00024 #include <drizzled/session.h>
00025 #include <drizzled/internal/my_sys.h>
00026 #include <drizzled/field/blob.h>
00027 #include <drizzled/table.h>
00028 
00029 #include <unistd.h>
00030 #include <fcntl.h>
00031 
00032 #include <string>
00033 
00034 using namespace std;
00035 using namespace drizzled;
00036 
00037 /*****************************************************************************
00038 ** Data Function tables
00039 *****************************************************************************/
00040 
00041 FunctionCursor::FunctionCursor(plugin::StorageEngine &engine_arg,
00042                                Table &table_arg) :
00043   Cursor(engine_arg, table_arg),
00044   estimate_of_rows(100), // Completely fabricated, I used to use the value 2.
00045   rows_returned(0)
00046 {}
00047 
00048 int FunctionCursor::open(const char *name, int, uint32_t)
00049 {
00050   tool= static_cast<Function *>(getEngine())->getFunction(name); 
00051 //  assert(tool);
00052 
00053   row_cache_position= 0;
00054 
00055   if (not tool)
00056     return HA_ERR_NO_SUCH_TABLE;
00057 
00058   return 0;
00059 }
00060 
00061 int FunctionCursor::close(void)
00062 {
00063   tool= NULL;
00064   wipeCache();
00065 
00066   return 0;
00067 }
00068 
00069 int FunctionCursor::doStartTableScan(bool)
00070 {
00071   rows_returned= 0;
00072   generator= tool->generator(getTable()->getFields());
00073 
00074   return 0;
00075 }
00076 
00077 
00078 int FunctionCursor::rnd_next(unsigned char *)
00079 {
00080   bool more_rows;
00081   ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
00082 
00083   /* Fix bug in the debug logic for field */
00084   for (Field **field= getTable()->getFields() ; *field ; field++)
00085   {
00086     (*field)->setWriteSet();
00087   }
00088 
00089   more_rows= generator->sub_populate(getTable()->getShare()->sizeFields());
00090 
00091   if (more_rows)
00092   {
00093     return 0;
00094   }
00095   else 
00096   {
00097     delete generator;
00098     generator= NULL;
00099   }
00100   rows_returned++;
00101 
00102   return more_rows ? 0 : HA_ERR_END_OF_FILE;
00103 }
00104 
00105 uint32_t FunctionCursor::max_row_length()
00106 {
00107   uint32_t length= (uint32_t)(getTable()->getRecordLength() + getTable()->sizeFields()*2);
00108 
00109   uint32_t *ptr, *end;
00110   for (ptr= getTable()->getBlobField(), end=ptr + getTable()->sizeBlobFields();
00111        ptr != end ;
00112        ptr++)
00113   {
00114       length += 2 + ((Field_blob*)getTable()->getField(*ptr))->get_length();
00115   }
00116 
00117   return length;
00118 }
00119 
00120 unsigned int FunctionCursor::pack_row(const unsigned char *record)
00121 {
00122   unsigned char *ptr;
00123 
00124   record_buffer.resize(max_row_length());
00125 
00126   /* Copy null bits */
00127   memcpy(&record_buffer[0], record, getTable()->getShare()->null_bytes);
00128   ptr= &record_buffer[0] + getTable()->getShare()->null_bytes;
00129 
00130   for (Field **field=getTable()->getFields() ; *field ; field++)
00131   {
00132     if (!((*field)->is_null()))
00133       ptr= (*field)->pack(ptr, record + (*field)->offset(record));
00134   }
00135 
00136   return((unsigned int) (ptr - &record_buffer[0]));
00137 }
00138 
00139 void FunctionCursor::position(const unsigned char *record)
00140 {
00141   uint32_t max_length= max_row_length();
00142 
00143   if (row_cache.size() <= row_cache_position + max_length)
00144   {
00145     row_cache.resize(row_cache.size() +  max_length);
00146   }
00147 
00148   unsigned int r_pack_length;
00149   r_pack_length= pack_row(record);
00150   internal::my_store_ptr(ref, ref_length, row_cache_position);
00151 
00152   memcpy(&row_cache[row_cache_position], &record_buffer[0], r_pack_length);
00153   row_cache_position+= r_pack_length;
00154 }
00155 
00156 
00157 void FunctionCursor::wipeCache()
00158 {
00159   if (rows_returned > estimate_of_rows)
00160     estimate_of_rows= rows_returned;
00161 
00162   row_cache.clear();
00163   row_cache_position= 0;
00164 }
00165 
00166 int FunctionCursor::extra(enum ha_extra_function operation)
00167 {
00168   switch (operation)
00169   {
00170   case drizzled::HA_EXTRA_CACHE:
00171     break;
00172   case drizzled::HA_EXTRA_NO_CACHE:
00173     break;
00174   case drizzled::HA_EXTRA_RESET_STATE:
00175     wipeCache();
00176     break;
00177   default:
00178     break;
00179   }
00180 
00181   return 0;
00182 }
00183 
00184 int FunctionCursor::doEndTableScan()
00185 { 
00186   delete generator; // Do this in case of an early exit from rnd_next()
00187 
00188   return 0;
00189 }
00190 
00191 int FunctionCursor::rnd_pos(unsigned char *buf, unsigned char *pos)
00192 {
00193   ha_statistic_increment(&system_status_var::ha_read_rnd_count);
00194   size_t position_id= (size_t)internal::my_get_ptr(pos, ref_length);
00195 
00196   const unsigned char *ptr;
00197   ptr= &row_cache[position_id];
00198 
00199   /* Copy null bits */
00200   memcpy(buf, ptr, getTable()->getNullBytes());
00201   ptr+= getTable()->getNullBytes();
00202   // and copy fields
00203   for (Field **field= getTable()->getFields() ; *field ; field++)
00204   {
00205     if (!((*field)->is_null()))
00206     {
00207       ptr= (*field)->unpack(buf + (*field)->offset(getTable()->getInsertRecord()), ptr);
00208     }
00209   }
00210 
00211   return 0;
00212 }
00213 
00214 
00215 int FunctionCursor::info(uint32_t flag)
00216 {
00217   memset(&stats, 0, sizeof(stats));
00218 
00219   if (flag & HA_STATUS_AUTO)
00220     stats.auto_increment_value= 1;
00221 
00222   stats.records= estimate_of_rows;
00223 
00224   return 0;
00225 }